plus minus button for google sheets that applies on entire column - button

I have managed to put a plus minus button in my google sheets document but it only applies for one cell. Since I want to use it to update my stock in the sheet i want one button plus and one minus button that applies on multiple columns.
the code i use right now is this
function plus() {
ss=SpreadsheetApp.getActiveSpreadsheet()
s=ss.getActiveSheet()
var currVal=s.getRange("A1").getValue()
var plusVal= currVal +1
s.getRange("A1") .setValue(plusVal)
}
function minus() {
ss=SpreadsheetApp.getActiveSpreadsheet()
s=ss.getActiveSheet()
var currVal=s.getRange("A1").getValue()
var minusVal= currVal -1
s.getRange("A1") .setValue(minusVal)
}
Is there a way to apply it to let's say column from B to H?
I'm just starting with using google sheets and script editor so I don't understand most of the language en tricks of using scripteditor

i think what you are looking for is a loop to run through every column.
function plus() {
ss=SpreadsheetApp.getActiveSpreadsheet()
s=ss.getActiveSheet()
//for loop
//r refers to the row (number of rows you have and c refers to column
for (var c=1; c<(total number of columns+1); c++){
for (var r=1; r<(total number of rows); r++){
var currVal = s.getRange(r,c).getValue();
var plusVal= currVal +1;
s.getRange(r,c) .setValue(plusVal);
}
}
}
Basically what happens here is that the referenced range changes each time the loop is completed. go from cell A1 to A2 etc etc, and when the last row is reached, it goes to B1 etc
for your reference, this is the script that i used.
function selftest1() {
var app = SpreadsheetApp;
var activeSheet = app.getActiveSpreadsheet().getActiveSheet();
for (var c=4; c<8; c++){
for (var r=2; r<13; r++){
var someCell = activeSheet.getRange(r,c).getValue();
someCell = someCell+1;
activeSheet.getRange(r,c).setValue(someCell);
}
}
}

Related

Trying to set a trigger

So I'm working on creating my own workout sheet to run on my mobile device b/c I don't like anything the app store offers.
Anyways, I want the sheet to automatically increase the weight being lifted based on a trigger. I've already got the sheet to return the next amount of weight to be lifted using formulas, now I want a trigger to run when the sheet calculates 25 reps to copy that increased value into the weight cell.
I'm trying to use the onEdit function. It runs without giving back an error, but nothing changes on the sheet.
Here's the code I have:
function myFunction() {
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
if ("Data!D15" == "False") {
sheet.getrange("Sheet1!C4").setValue("Data!E15+0");
}
if ("Data!G15" == "0") {
sheet.getrange("Sheet1!C4").setValue("Data!D15+5");
}
}
}
Try this:
function onEdit(e) {
var sh1 = e.range.getSheet();
var sh2 = e.source.getSheetByName('Data');
if(!sh2.getRange('D15').getValue()){sh1.getrange("Sheet1!C4").setValue("Data!E15+0");}
if(sh2.getRange('G15').getValue()=="0"){sh1.getrange("Sheet1!C4").setValue("Data!D15+5");}
}

Performance server scripting

I have table with multiple customerKey values assigned to a numeric value; I wrote a script where foreach row of data I scan whole table to find all values assigned to the current customerKey and return a highest one;
I have a problem with performance - script processes around 10 records per second - any ideas how to improve this or maybe propose an alternative solution plesae?
function getLastest() {
var date = app.models.magicMain.newQuery();
var date_all = date.run();
date_all.forEach(function(e) { // for every row of date_all
var temp = date_all.filter(function(x) {
return x.SubscriberKey === e.SubscriberKey; // find matching records for the current x.SubscriberKey
});
var dates = [];
temp.forEach(function(z) { // get all matching "dates"
dates.push(z.Date);
});
var finalValue = dates.reduce(function(a, b) { // get highest dates value (integer)
return Math.max(a, b);
});
var record = app.models.TempOperatoins.newRecord(); // save results to DB
record.email = e.SubscriberKey.toString() + " " + finalValue.toString();
app.saveRecords([record]);
});
}
The only suggestion I have would be to add:
var recordstosave = [];
At the top of your function.
Then replace app.saveRecords([record]) with recordstosave.push(record).
Finally outside of your foreach function do app.saveRecords(recordstosave).
I saw major processing time improvements doing this rather than saving each record individually inside a loop.

Google Sheets: delete rows containing specified data

I'm new to Java scripting and Google Apps Scripts so i am sorry if this has already been answered. I was not able to find what i was looking for over the last few months of working on this project.
I am working on a variant of the scripts here:
Delete row in Google Sheets if certain "word" is found in cell
AND
Google Sheet Script - Find Value in Col and Delete Row
I want to create a button, or menu, that will allow someone to enter specific data, and have each row in the spreadsheet containing that data deleted.
I have a test sheet here that illustrates the data i'm working with, formulas i'm using, and has the beginning of the script attached to it:
https://docs.google.com/spreadsheets/d/1e2ILQYf8MJD3mrmUeFQyET6lOLYEb-4coDTd52QBWtU/edit?usp=sharing
The first 4 sheets are pulling data from the "Form Responses 1" sheet via a formula in cell A:3 in each sheet so the data would only need to be deleted from the "Form Responses 1" sheet to clear it from the rest of the sheets.
I tried working this in but i do not think i am on the right track.
https://developers.google.com/apps-script/guides/dialogs
I also posted this on Google Docs Help Forum 60 days ago, but have not received any responses.
Any help would be greatly appreciated.
There's a few steps. For usability of UI this takes a little longer code. In concise form:
The user activates a dialog and enters a string.
Rows w/ the string are deleted (with error handling and confirmation)
(Hopefully this gets you started and you can tailor it to your needs)
Function that initiates the menu:
function onOpen(){
SpreadsheetApp.getUi()
.createMenu('My Menu')
.addItem('Delete Data', 'deleteFunction')
.addToUi();
}
The main workhorse:
function deleteFunction(){
//declarations
var sheetName = "Form Responses 1";
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
var dataRange = sheet.getDataRange();
var numRows = dataRange.getNumRows();
var values = dataRange.getValues();
var delete_string = getUIstring();//open initial UI, save value
if (delete_string.length < 3) return shortStringError()//UI to protect your document from an accidental entry of a very short string.
//removing the rows (start with i=2, so don't delete header row.)
var rowsDeleted = 0;
for (var i = 2; i <= numRows; i++){
var rowValues = values[i-1].toString();//your sheet has various data types, script can be improved here to allow deleting dates, ect.
if (rowValues.indexOf(delete_string) > -1){
sheet.deleteRow(i - rowsDeleted);//keeps loop and sheet in sync
rowsDeleted++;
}
}
postUIconfirm(rowsDeleted);//Open confirmation UI
}
Isolated UI functions to help make above function more concise:
function getUIstring(){
var ui = SpreadsheetApp.getUi();
var response = ui.prompt("Enter the target data element for deletion")
return response.getResponseText()
}
function postUIconfirm(rowsDeleted){
var ui = SpreadsheetApp.getUi();
ui.alert("Operation complete. There were "+rowsDeleted+" rows deleted.")
}
function shortStringError(){
var ui = SpreadsheetApp.getUi();
ui.alert("The string is too short. Enter a longer string to prevent unexpected deletion")
}
I'll just show a way to delete the cell value if it matches your search criteria. It's up to you to connect it to buttons ,etc.
You'll loop through a Sheet Range. When you find the word match, delete it using clearContent()
function deleteSpecificData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange("Sheet1!A1:C4");
var values = range.getValues();
var numArray = [1,2,3,4,5,6,7,8,9];
var deleteItem = "Garen";
Logger.log(range);
for(var i=0; i< values.length; i++){
for(var j=0; j<values[i].length; j++){
if(values[i][j] == deleteItem){
var row = numArray[i];
var col = numArray[j];
var range = sheet.getRange(row,col).clearContent();
}
}
}
}
Before:
After:

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);
}

Resources