Increment Cell Value by 1 using buttons (g.sheets) - button

I want to create some small buttons in my google sheet that add or substract the cell value incrementally.
Excuse my artistic abilities (I created the buttons in paint)

You would need to create the increment and decrement functions using Google Apps Script like this:
function increment1() {
var activeCell = SpreadsheetApp.getActiveSpreadsheet().getActiveCell();
var cellValue = activeCell.getValue();
activeCell.setValue(++cellValue);
}
function decrement1() {
var activeCell = SpreadsheetApp.getActiveSpreadsheet().getActiveCell();
var cellValue = activeCell.getValue();
activeCell.setValue(--cellValue);
}
function increment01() {
var activeCell = SpreadsheetApp.getActiveSpreadsheet().getActiveCell();
var cellValue = activeCell.getValue() + 0.1;
activeCell.setValue(cellValue);
}
function decrement01() {
var activeCell = SpreadsheetApp.getActiveSpreadsheet().getActiveCell();
var cellValue = activeCell.getValue() - 0.1;
activeCell.setValue(cellValue);
}
After saving the script, you can draw the buttons using Insert menu -> Drawing, then after you've finished the drawing and placed it onto the sheet, you can right click the drawing, then click on the three dots and select Assign Script:
Then type the function name on the dialog box that appears:
This would increment or decrement the value in the active/selected cell by 1 or 0.1, depending on the entered function.

Related

Very simple if else check in Google App Maker

This is likely embarrassingly easy but I'm new and I've been beating my head against the wall on this for a while now. What I am attempting to do is basically a modified version of the "Hello App Maker!" If else test.
The necessary info I have the following widgets attached to the appropriate data sources:
Dropdown widget called source_name (string - list)
Label widget I've called name (string)
Text Box widget called qty_duration (number)
Label widget I've called hours (number)
I have a dropdown widget called source_name with 5 options. On selection I have the value appear in a label widget I've called name. If the option selected from the drop down widget is ever LABOUR I am trying to then have the value of a Text Box widget called qty_duration appear in a label widget I've called hours
On the source_name dropdown event - onValueChange I have the following code:
// Define variables for the input and output widgets
var nameWidget = app.pages.Apex_job_details.descendants.name;
var outputWidget = app.pages.Apex_job_details.descendants.hours;
var techhours = app.pages.Apex_job_details.descendants.qty_duration;
var nothing = 0;
// If a name is LABOUR, add the qty to the output widget Else output 0.
if (nameWidget == 'LABOUR') {
outputWidget.text = techhours;
} else {
outputWidget = nothing;
}
It's not giving me any errors, but it's also not outputting to the hours label. If I edit the code as follows just to muck with it:
// Define variables for the input and output widgets
var nameWidget = app.pages.Apex_job_details.descendants.name;
var outputWidget = app.pages.Apex_job_details.descendants.hours;
var techhours = app.pages.Apex_job_details.descendants.qty_duration;
var nothing = 0;
// If a name is LABOUR, add the qty to the output widget Else output 0.
if (nameWidget == 'LABOUR') {
outputWidget.text = techhours;
} else {
outputWidget.text = nothing;
}
I'm not sure what I'm doing wrong.
Assuming all labels and input widgets are inside a table row you will want to adjust your code as follows:
var tablerow = widget.parent;
var nameWidget = tablerow.descendants.name.text;
var outputWidget = tablerow.descendants.hours;
var techhours = tablerow.descendants.qty_duration.value;
if(nameWidget === 'LABOUR') {
outputWidget.text = techhours;
} else {
outputWidget.text = null;
}
By using widget.parent in the onValueChange event of the dropdown you will automatically reference the table row and then by using descendants you are referencing only the descendants of that table row. This will bridge the error by using an absolute reference when using table rows. If it still doesn't work let me know.

update edited cells within treetable after expand/collapse items

I have a treeTable with editable cells within the expanded rows. The editable cells get a dirty flag after editing (in the example the background color is set to red).
The problem i'm running into is that i found no certain way to update the dirty flag on expand/collapse (edited cells get the css class 'edited-cell').
At the moment the code looks like that:
// each editable textfield gets a Listener
textField.attachLiveChange(
var source = oEvent.oSource;
...
jQuery('#' + source.getId()).addClass(EDITED_CELL_CLASS, false)
// list with cell ids, e.g. "__field1-col1-row1"
DIRTY_MODELS.push(model.getId()) //*** add also binding context of row
)
// the table rows are updated on toggleOpenState
new sap.ui.table.TreeTable({
toggleOpenState: function(oEvent) {
...
this.updateRows() // see function below
}
})
// update Rows function is also delegated
oTable.addDelegate({ onAfterRendering : jQuery.proxy(this.updateRows, oTable)});
//http://stackoverflow.com/questions/23683627/access-row-for-styling-in-sap-ui5-template-handler-using-jquery
// this method is called on each expand/collapse: here i can make sure that the whole row has it's correct styling...
// but how to make sure that special cells are dirty?
function updateRows(oEvent) {
if (oEvent.type !== 'AfterRendering'){
this.onvscroll(oEvent);
}
var rows = this.getVisibleRowCount();
var rowStart = this.getFirstVisibleRow();
var actualRow;
for (var i = 0; i < rows; i++){
actualRow = this.getContextByIndex(rowStart + i); //content
var row = this.getRows()[i]
var obj = actualRow.getObject()
var rowId = row.getId()
updateStyleOfRows(obj, rowId, actualRow)
updateDirtyCells(rowId) //*** how to get the binding context in this function???
}
};
// update Dirty Cells in function updateRows():
function updateDirtyCells(rowId){
for (var i = 0; i < DIRTY_MODELS.length; i++){
var dirtyCellId = DIRTY_MODELS[i]
//*** make sure that only the correct expanded/collapsed rows will be updated -> depends on the bindingContext of the row
jQuery('#' + rowId).find('#' + dirtyCellId + '.editable-cell').addClass(EDITED_CELL_CLASS, false)
}
}
This doesn't work correctly, because the ids of the cells change on each layout render (e.g. collapse/expand rows). Please see attached image.
Let me know if i should provide more information.

Google Spreadsheets: Button to add B to A and then clear B

Helpful answer, but not exactly what I'm looking for
The above answer gives part of the script I'm looking for. I'd like to add another step (or two) but have no idea how.
Here's what I'm trying to accomplish:
I have a column of numbers, and would like to add numbers from another. The part I can't figure out is how to clear the cells after the numbers have been added to the first column.
Like this:
A <---B
1 <---2
2 <---5
3 <---24
On the click of a button, I'd like the numbers from B to be added to A and then B cleared. Column A would become 3, 7, 27, and the cells in Column B would become blank.
function addRange() {
//replace 'Sheet1' with your actual sheet name
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var tRange = sheet.getRange('A1:A3');
var tValues = tRange.getValues();
var sRange = sheet.getRange('B1:B3');
var sValues = sRange.getValues();
for (var i = 0; i < tValues.length; i++) {
tValues[i][0] += sValues[i][0];
}
tRange.setValues(tValues);
sRange.clearContent();
}
You can also add a button to your spreadsheet menu to execute AdmaL's code example above using this code
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menubutton = [ {name: "Add Range", functionName: "addRange"}]; //"addRange" is the name of the function submitted by AdamL Above //This would also need to be included as a function in your script as the function to call when you click the "Custom" menu button
ss.addMenu("Custom", menubutton);
}

Placing a floating info panel

I'm using Jame Ferreira's Google Script: Enterprise Application Essentials to create a product page (Chapter 5). I've created the app that displays thumbnails of the products all on a page, and then the info panel with more detail that pops up when the user mouses over. It's using CSS to achieve this styling.
Problem comes in when placing the info panel. It pops up in only one location, as opposed to being tied to the thumbnail with which it is associated.
Here's the code related to the info panel. I believe the problem exists in the placement of the last few lines, but have tried everything I can think of:
function onInfo(e){
var app = UiApp.getActiveApplication();
var id = e.parameter.source;
for (var i in productDetails){
if(productDetails[i].id == id){
var r = 50;
var c = 0;
var infoPanel = app.createVerticalPanel().setSize('300px', '300px');
var horzPanel = app.createHorizontalPanel();
var image = app.createImage(productDetails[i].imageUrl).setHeight('100px');
var title = app.createLabel(productDetails[i].title);
horzPanel.add(image);
horzPanel.add(title);
var description = app.createLabel(productDetails[i].description);
infoPanel.add(horzPanel);
infoPanel.add(description);
applyCSS(infoPanel, _infoPanel);
applyCSS(image, _infoImage);
applyCSS(horzPanel, _infoBoxSeparator);
applyCSS(title, _infoTitle);
applyCSS(description, _infoDescription);
app.getElementById('infoGrid').setVisible(true)
.setWidget(0,0, infoPanel);
break;
}
c++
if (c == 3){
c = 0;
r = r+250;
}
switch (c)
{
case 0:
c=250;
break;
case 1:
c=500;
break;
case 2:
c=250;
break;
}
}
var _infoLocation =
{
"top":r+"px",
"left":c+"px",}
applyCSS(infoPanel, _infoLocation);
return app;
}
You may get the position of the mouse using e.parameter.x and e.parameter.y based on which you can position the infoPanel
infoPanel.setStyleAttribute('top',e.parameter.y)
.setStyleAttribute('left',e.parameter.x).setStyleAttribute('zIndex','1')
.setStyleAttribute('position','fixed');
You may add some offset to x and y positions of mouse to display it according to your needs.
Position related parameter which you get in handler function are
e.parameter.x
e.parameter.y
e.parameter.clientX
e.parameter.clientY
e.parameter.screenX
e.parameter.screenY

When to render Legend in Flex

My Flex chart has code that creates a legend from each data series. Currently, I have the drawLegend function execute when a button is clicked.
I am trying to get the legend to draw automatically but I am having trouble determining when to call the drawLegend function. Users click on an 'Update' button which retrieves data. I want the legend to get created after this, without the users having to click on another button.
I have put my drawLegend function in several places (ResultHandler, afterEffectEnd(for chart animation, etc.) and nothing works.
Sometime after the series has been added to the chart and after the series animation ends, the legend can be added.
How can I trap this point in time and call my function?
Any ideas?
Below is the code I used to create the legend. Note that even though the code processes each series, I noticed that the Fill color is null if it is called too early.
private function drawLegend(event:Event):void {
clearLegend();
// Use a counter for the series.
var z:int = 0;
var numRows:int;
if (chart.series.length % rowSize == 0) {
// The number of series is exactly divisible by the rowSize.
numRows = Math.floor(chart.series.length / rowSize);
} else {
// One extra row is needed if there is a remainder.
numRows = Math.floor(chart.series.length / rowSize) + 1;
}
for (var j:int = 0; j < numRows; j++) {
var gr:GridRow = new GridRow();
myGrid.addChild(gr);
for (var k:int = 0; k < rowSize; k++) {
// As long as the series counter is less than the number of series...
//skip columnset group
if (chart.series[z] is LineSeries || chart.series[z] is ColumnSeries){
if (z < chart.series.length) {
var gi:GridItem = new GridItem();
gr.addChild(gi);
var li:LegendItem = new LegendItem();
// Apply the current series' displayName to the LegendItem's label.
li.label = chart.series[z].displayName;
// Get the current series' fill.
var sc:SolidColor = new SolidColor();
sc.color = chart.series[z].items[0].fill.color;
// Apply the current series' fill to the corresponding LegendItem.
li.setStyle("fill", sc.color);//was just sc
// Apply other styles to make the LegendItems look uniform.
li.setStyle("textIndent", 5);
li.setStyle("labelPlacement", "left");
li.setStyle("fontSize", 9);
gi.setStyle("backgroundAlpha", "1");
gi.setStyle("backgroundColor", sc.color);
//gi.width = 80;
// Add the LegendItem to the GridItem.
gi.addChild(li);
}
}
// Increment any time a LegendItem is added.
z++;
}
}
}
Well, I couldn't quite figure out what event to trap so I used the following in the chart's parent container:
chart.addEventListener(ChartItemEvent.ITEM_ROLL_OVER,drawLegend);
Seems to work ok.

Resources