I am creating an app which will perform some simple mathematical functions. One of these functions is to sum the field on my table. However, it should sum the field based on what is selected on the drop down menu and display the sum value on an edit field component. For instance, using the attached image, when I click control total, I would like to display the sum of the numbers in the fiscal period column and display it on the edit field on the right called sum.
function ControlTotalButtonPushed(app, event)
ct = app.FieldsDropDown.Value;
total = sum(app.UITable.Data.ct);
app.EditFieldTotal.Value = total;
if total == 0
app.BalanceUnbalanceLabel.Text = 'Balance';
else
app.BalanceUnbalanceLabel.Text = 'Unbalance';
end
end
I get an error:
Unrecognized variable name 'ct'
I thought app.UITable.Data.ct would refer to the column name to sum?
Please refer to the attached picture.
Related
I am trying to remove the formula from a column in a existing sheet with python.
I tryed to set my formula to None using the column object (column.formula = None)
It does not work and my column object remains unchanged. Anyone have inputs to solve this issue ? Thank you !
This took me a bit to figure out, but seems like I've found a solution. Turns out that this is a 2-step process:
Update the column object to remove the formula (by setting column.formula to an empty string).
For each row in the sheet, update the cell within that column to remove the formula (set cell.value to an empty string and cell.formula to None).
Completing the STEP 1 will remove the formula from the column object -- but that cell in each row will still contain the formula. That's why STEP 2 is needed -- STEP 2 will remove the formula from the individual cell in each row.
Here's some example code in Python that does what I've described. (Be sure to update the id values to correspond to your sheet.)
STEP 1: Remove formula from the Column
column_spec = smartsheet.models.Column({
'formula': ''
})
# Update column
sheetId = 3932034054809476
columnId = 4793116511233924
result = smartsheet_client.Sheets.update_column(sheetId, columnId, column_spec)
STEP 2: Remove the formula from that cell in each row
Note: This sample code updates only one specific row -- in your case, you'll need to update every row in the sheet. Just build a row object for each row in the sheet (like shown below), then call smartsheet_client.Sheets.update_rows once, passing in the array of row objects that you've built corresponding to all rows in the sheet. By doing things this way, you're only calling the API once, which is the most efficient way of doing things.
# Build new cell value
new_cell = smartsheet.models.Cell()
new_cell.column_id = 4793116511233924
new_cell.value = ''
new_cell.formula = None
# Build the row to update
row_to_update = smartsheet.models.Row()
row_to_update.id = 5225480965908356
row_to_update.cells.append(new_cell)
# Update row
sheetId = 3932034054809476
result = smartsheet_client.Sheets.update_rows(sheetId, [row_to_update])
I have a report like the image below:
Note that the sections separated by a blank space are grouped by the month and are iterated over a group band. I want to put partial in the summary band by the type of the register, like in the example figure get the sum for Register type A in January = 10, February = 5, March = 1 so as the total = 10 + 5 + 1 = 16. So the summary will look like:
How can I achieve that kind of conditional sum in jasper? Thanks in advance.
After trying a little bit with iReport I found a solution: to get the partial sum by type you have to add a variable that has the calculation type as "sum" and the reset type set as "Report". Once you set the values you have to create a variable Expression that has value only when the cell value of type is the desired value, so for the example in the question, in the column Value of the summary band in cell with the value "16" you have the expression :
$F{type}.equals("A") ? $F{value} : 0
and so on for the other types in the summary.
I have a Google Sheet where information from a Google Form is dumped. Two of the columns create a date range (columns C and G) and I would like for the sheet to automatically create a new row of information for every date of the range and copy all the other information from the original row for every row that is created. In the end, every date in the range has it's own row regardless of it being 2 days or 25 and all the the information gathered through the form be present for each day. If there is not a date in column G, it is only a one day trip and there is no need for additional rows. To make things more difficult when someone submits a form, the information is entered into the row directly beneath the last one that it filled, so these new rows filled by the date range will need to be down the sheet, possibly beginning at row 2000 or more as this sheet will have a lot of information in a few months. As you may see in the sample, there is another sheet in the workbook that performs all the sorting. Thanks for any help.
Sample Document
You will need to create a form submit event and attach the following code to it. Also you'll need to create a sheet name 'ResponseReview'.
function formSubmitEvent1(e)
{
var ss=SpreadsheetApp.openById('SpreadsheetID');
var sht=ss.getSheetByName('ResponseReview');
sht.appendRow(e.values);
}
The above code will need the SpreadsheetId in the openById Method. This code will append any new rows to the end of the ResponseReview sheet.
The code below will expand any entrees that have a date in column 3 and 7 and it will also remove the end date in column 7 from that first row. I use the fact that if column 3 is not empty and column 7 is not and column 7 is no equal to column 3 then that's a row that needs to be expanded. So I have to remove the end date so that it won't continue to get expanded when it's run again in the future. We could figure something else out if you need to keep than end date. We could add a don't expand column at the end.
function convertRangetoRows()
{
var ss=SpreadsheetApp.getActive();
var sht=ss.getSheetByName('ResponseReview');
var rng=sht.getDataRange();
var rngA=rng.getValues();
var rngB=[];
var day=86400000;
rngB.push(rngA[0]);
for(var i=1;i<rngA.length;i++)
{
rngB.push(rngA[i]);
if(rngA[i][2] && rngA[i][6] && rngA[i][2]!=rngA[i][6])
{
var row=rngA[i].slice();//returns a new copy of the array by value
rngA[i][6]='';//deletes the end date by reference so it also deletes the one thats already been pushed into rngB
var dt0=new Date(row[2]);
var dt1=new Date(row[6]);
var days=(dt1.valueOf()-dt0.valueOf())/day;
var dt=dt0.valueOf();
for(j=0;j<days;j++)
{
dt+=day;
row[2]=Utilities.formatDate(new Date(dt), Session.getScriptTimeZone(), "MM/dd/yyyy");//original array unchanged
row[6]='';//original array unchanged
rngB.push(row.slice());//push in a copy
}
}
var intermediate='nothing';
}
var outrng=sht.getRange(1,1,rngB.length,rngB[0].length);
outrng.setValues(rngB);
var end='the end is near';
}
This is what my spreadsheet looks like before running the expansion function:
And After:
And now you can leave the sheet linked to the form alone and let it be an archive for submitted data.
Im trying to return the values from a 'repeating item' input. But 'inputs.value' doesn't work. I think I need to creat a loop and index for every item on the list but not sure.
I think I need to create a loop and index for every item on the list..
Yes. You are right on that. The 'Repeating Item' is internally stored as an object array. So you need to iterate that array to process it. The individual items are objects and hence you will not be available on the inputs object directly, but via inputs.lineitems, where lineitems is the property name of the repeating item prototype.
For example:
You are creating a repeating items list of items which you want to order. So, you have two inputs inside the repeating items prototype, say itemName and itemQuantity. You name the repeating items property name as LineItems. You want to display it as an output table and also display total quantity ordered. The output table is named Orders and the total label is named Total.
You could then iterate this to process it further, like this:
var result = [], totalItems = 0;
Where result is an array that you would want to map to your output table, and totalItems is where you would cache the total quantity.
inputs.LineItems.forEach(function(item, idx) {
totalItems += item.itemQuantity;
result.push({
'ItemNumber': idx + 1,
'Item': item.itemName,
'Quantity': item.itemQuantity
});
});
Where, you are iterating the repeating items via inputs.LineItems and increment total accordingly . You also prepare the result array to map to the Orders table later on.
This is what you return:
return {
Total: totalItems,
Orders: result
};
Where, Total is the output label you defined earlier, and Orders is the out put table name you defined earlier.
Here is a demo for you to understand it better:
https://jscalc.io/calc/YicDJYCSlYTGYFMS
To see the source, just click on the ellipsis (three dots shown after the 'Powered by JSCalc.io' text) and click "make a copy".
Hope this helps.
I have a Google Spreadsheet with many hidden rows in it, and I want to skip them when iterating through a list of rows in the spreadsheet.
It's mainly an efficiency issue, as I'm dealing with over half of my rows being hidden and in no need of being checked.
Any help would be appreciated.
New API as of 2018 that's useful for this problem: isRowHiddenByUser. See also isRowFilteredByUser.
There's no direct way of doing this in Apps Script, but there is a feature request open to provide a way get the show/hide status of a row, if you want to star it.
A workaround using SUBTOTAL. Create 2 columns A and B. A must always have a value and B has a set of formulas. These 2 columns look like this:
A | B
---------------------------
1 | =NOT(SUBTOTAL(103, A1))
1 | =NOT(SUBTOTAL(103, A2))
1 | =NOT(SUBTOTAL(103, A3))
SUBTOTAL returns a subtotal using a specified aggregation function. The first argument 103 defines the type of function used for aggregation. The second argument is the range to apply the function to.
3 means COUNTA and counts the number of values in the range
+100 means ignore hidden cells in the range.
The result of SUBTOTAL with a range of 1 cell will be 0 when the cell is hidden and 1 when the cell is shown. NOT inverts it.
Now you can read the column B with your script to know if a row is hidden.
Here's the transposed question and answer: https://stackoverflow.com/a/27846180/1385429
The issue tracker holds that request since Aug 3, 2010 with a Medium priority and just a "Triaged" status. More than 3 years and no signs of solution from the GAS team.
My workaround was to use a special leading character that would indicate the visibility state of the row/column, it is a leading backtick (`) in the cells of top header row/column.
In case if merged cells are used in column headers, then an empty top row should be dedicated just for that functionality until the google engineers will improve the API.
Same applies if there are formulas in the 1st row/column cell(s).
These dedicated rows/columns itself can be hidden.
After starting to use this functionality each show/hide column/row command should be performed from a customized menu, otherwise there'll be errors when iterating through the range programmatically, because of the missing/excessive backtick.
e.g. to hide rows of selected cells the following function is invoked
function hideSelectedRows() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = SpreadsheetApp.getActiveRange();
// hide rows and add a ` backtick to the header cell
for (var row = range.getRow(); row <= range.getLastRow(); row++)
{
// add backtick only if it isn't there (that may happen when manually unhiding the rows)
var cellHeader = sheet.getRange(row, 1)
var cellHeaderValue = cellHeader.getValue()
if ( !cellHeaderValue.match(/^`/) ) {
cellHeader.setValue('`' + cellHeaderValue)
}
// hide rows of selected range
sheet.hideRows( row );
}
}
and the menu
SpreadsheetApp.getActiveSpreadsheet()
.addMenu("Show/Hide", [
{ name : "Hide Selected Rows", functionName : "hideSelectedRows" },
{ name : "Hide Selected Columns", functionName : "hideSelectedColumns" },
null,
{ name : "Hide Rows", functionName : "hideRows" },
{ name : "Hide Columns", functionName : "hideColumns" },
null,
{ name : "Show Rows", functionName : "showRows" },
{ name : "Show Columns", functionName : "showColumns" },
null,
{ name : "Show All Rows", functionName : "unHideAllRows" },
{ name : "Show All Columns", functionName : "unHideAllColumns" }
])
Once google engineers find the time to improve the onChange event, it will be possible to put those backticks automatically. Currently the changeType is limited to EDIT, INSERT_ROW, INSERT_COLUMN, REMOVE_ROW, REMOVE_COLUMN, INSERT_GRID, REMOVE_GRID, OTHER without any details on which Row/Column was inserted/removed. Looks like the team behind GAS is scanty. I wish they could hire more programmers (khm khm)
As for workaround, it is possible by using SUBTOTAL function which can returns a subtotal for a vertical range of cells.
Syntax is:
SUBTOTAL(function_code, range1, [range2, ...])
where hidden values can be skipped for any of these codes by prepending 10 (to the single-digit codes).
For example 102 for COUNT while skipping hidden cells, and 110 for VAR while doing so.
Related: Google Spreadsheets sum only shown rows at Webapps SE