Google Sheets: Updating data in an existing row - google-apps-script

I am just a couple of weeks into my coding adventure. I am trying to build a sheet that will edit values in existing cells based on the value in another cell. I was able to write a script that would write a new row in the database based on the values in the dashboard when the script was run.
function submitClientContact() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("New Client Form"); //Form Sheet
var datasheet = ss.getSheetByName("Info for Sales"); //Data Sheet
//Input Values
var values = [[formSS.getRange("E4").getValue(),
formSS.getRange("E3").getValue(),
formSS.getRange("E5").getValue(),
formSS.getRange("C8").getValue(),
formSS.getRange("C9").getValue(),
formSS.getRange("C10").getValue(),
formSS.getRange("C11").getValue(),
formSS.getRange("C12").getValue(),
formSS.getRange("C13").getValue(),
formSS.getRange("C14").getValue(),
formSS.getRange("C16").getValue(),
formSS.getRange("C17").getValue(),
formSS.getRange("C18").getValue(),
formSS.getRange("C19").getValue(),
formSS.getRange("C20").getValue(),
formSS.getRange("C21").getValue(),
formSS.getRange("C22").getValue(),
formSS.getRange("C24").getValue(),
formSS.getRange("C25").getValue(),
formSS.getRange("C26").getValue(),
formSS.getRange("C27").getValue(),
formSS.getRange("C28").getValue(),
formSS.getRange("C29").getValue(),
formSS.getRange("C30").getValue(),
formSS.getRange("E8").getValue(),
formSS.getRange("E9").getValue(),
formSS.getRange("E10").getValue(),
formSS.getRange("E11").getValue(),
formSS.getRange("E12").getValue(),
formSS.getRange("E13").getValue(),
formSS.getRange("E14").getValue(),
formSS.getRange("E16").getValue(),
formSS.getRange("E17").getValue(),
formSS.getRange("E18").getValue(),
formSS.getRange("E19").getValue(),
formSS.getRange("E20").getValue(),
formSS.getRange("E21").getValue(),
formSS.getRange("E22").getValue(),
formSS.getRange("E24").getValue(),
formSS.getRange("E25").getValue(),
formSS.getRange("E26").getValue(),
formSS.getRange("E27").getValue(),
formSS.getRange("E28").getValue(),
formSS.getRange("E29").getValue(),
formSS.getRange("E30").getValue()]];
datasheet.getRange(datasheet.getLastRow()+1, 1, 1, 45).setValues(values);
var sheet = SpreadsheetApp.getActive().getSheetByName("New Client Form");
sheet.getRange("E3:E5").clearContent();
var sheet = SpreadsheetApp.getActive().getSheetByName("New Client Form");
sheet.getRange("C8:C30").clearContent();
var sheet = SpreadsheetApp.getActive().getSheetByName("New Client Form");
sheet.getRange("E8:E30").clearContent();
}
I now need a script to edit the cells in the database. The sheet will have 3 primary functions. 1 dropdown containing all of the clients in the database (cell A1), 1 row to show the data that is in the database for that client (column A), and one row that would be used to edit that existing data (column B). I can build the lookup equations easily, but I need help with the script to edit the database.
I basically need a script that will use the data in the drop down (A1) to reference the row in the database in which data needs to be edited, followed by editing all 45 columns but leaving blank cells (blank in column B) alone.
I assume it is just a couple of lines that I am missing to make this work, but I have been struggling with this for far too many hours.

Related

How do I automatically copy formules from above row in Google Sheets?

I have made a simple user interface to get user data. It gets a few entries, puts it into the designated database and clears the form. That works fine. While columns 0 to 6 are user data, columns 7 to 11 are formulas using data from 0 to 6. I'm looking for a solution that the user does not have to put in data and then manually needs to copy the above formulas. I don't want to put in the formulas before hand, because I think I will have a problem since the script looks for the last row.
So in short: it needs to find the last row on the sheet, write the data in to a new row and copy formulas in column 7 to 11 from the row above it to the new row. Total noob here, does this make sense?
function submitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Form");
var datasheet = ss.getSheetByName("Database");
var values = [[formSS.getRange("d3").getValue(),
formSS.getRange("d5").getValue(),
formSS.getRange("d7").getValue(),
formSS.getRange("d9").getValue(),
formSS.getRange("d11").getValue(),
formSS.getRange("d13").getValue()]]
datasheet.getRange(datasheet.getLastRow()+1,1,1,6).setValues(values)
formSS.getRange("d3").clearContent();
formSS.getRange("d5").clearContent();
formSS.getRange("d7").clearContent();
formSS.getRange("d9").clearContent();
formSS.getRange("d11").clearContent();
formSS.getRange("d13").clearContent();
}
There are several options for solving your task:
Option 1: When generating an array of data for the row to be inserted, you can read the formulas from the previous row and add them to the array before inserting
...
var values = [formSS.getRange("d3").getValue(),
formSS.getRange("d5").getValue(),
formSS.getRange("d7").getValue(),
formSS.getRange("d9").getValue(),
formSS.getRange("d11").getValue(),
formSS.getRange("d13").getValue()],
lastRow = datasheet.getLastRow(),
formulas = datasheet.getRange(lastRow,7,1,5).getFormulasR1C1();
datasheet.getRange(lastRow+1,1,1,11).setValues([[...values,...formulas[0]]])
...
Option 2. You can insert formulas directly in the script without reading them from the sheet
...
var values = [[formSS.getRange("d3").getValue(),
formSS.getRange("d5").getValue(),
formSS.getRange("d7").getValue(),
formSS.getRange("d9").getValue(),
formSS.getRange("d11").getValue(),
formSS.getRange("d13").getValue(),
'=FormulaR1C1 for column 7',
`=IMPORTXML(R1C2&R[0]C[-6]&"/","//div[#class='priceValue ']")`,
'=FormulaR1C1 for column 9',
'=FormulaR1C1 for column 10',
'=FormulaR1C1 for column 11',]]
datasheet.getRange(datasheet.getLastRow()+1,1,1,11).setValues(values)
...

Google Sheets - Identify duplicates and overwriting data

I've heavily edited the original question I posted, as i have solved some of the issue myself. I'm now stuck on just one thing.
function payINVOICE() {
var ss = SpreadsheetApp.getActive();
var ds = SpreadsheetApp.openById("14imcEob2qIZbH6AjGYtf16MJxbnfkhQn1ae4jR-Nzq4");
var srcSheet = ss.getSheetByName("INVOICE_ENTRY");
var dstSheet = ds.getSheetByName("INVOICE_ENTRY");
var data_range = srcSheet.getRange('B4:J100');
var data_data = data_range.getValues();
var data_clean = data_data.filter(function (r) {return r[1]});
var clear_range = srcSheet.getRange('B4:I100');
var lr = dstSheet.getLastRow();
dstSheet.getRange(lr+1, 2,data_clean.length,9).setValues(data_clean);
clear_range.clear();
}
This code checks the range B4:J100 for a value in Column B.
If there is a value and the script is run, it copies those rows onto dstSheet.
My role is marking invoices as paid or not.
The dstSheet will already contain the data, which is pulled back into the srcSheet with a query. Column K is not part of the original query.
If I mark a row as "PAID" in column K on the srcSheet, I want the code to take the data_data variable and overwrite what is already in the dstSheet, so that the query then pulls the data back into srcSheet with column J then showing "PAID".
It means I can then change column K to "NOT PAID", run the script again and it will over-write the "PAID".
This makes better sense than my last post and I am so close to achieving what I need, just stuck on this last bit.
If you simply want to monitor the changes between the two mentioned sheets, it would be much easier to use an onEdit(e) trigger which will tell you which cell has been edited.
Snippet
function payINVOICE(e) {
var srcSheet = SpreadsheetApp.getActiveSheet(); //gets the active sheet which is supposed to be source sheet
var dstSheet = SpreadsheetApp.openById('DEST_SHEET_ID').getSheetByName('INVOICE_ENTRY'); //gets the destination sheet
if (e.range.getSheet().getName() == 'INVOICE_ENTRY' && e.range.getColumn() == 11) { //e specifies where the edit has been made - therefore this if condition checks if the edit is in the INVOICE ENTRY sheet and if the column is the K column
var row =e.range.getRow(); //this gathers the row at which the edit has been made
var data = srcSheet.getRange(row, 2, 1, 10).getValues(); //this gathers the data corresponding to the row at which the edit has been made
dstSheet.getRange(row, 2, 1, 10).setValues(data); //this sets the data into the corresponding row in the destination sheet
}
Explanation
The above code uses the onEdit(e) installable trigger and the e event object. In this way, when an edit is being made on the srcSheet on the 11th column (aka K column) and the sheet name is "INVOICE_ENTRY", then the row at which the change has been made is kept in the row variable. Afterwards, the corresponding row of data is kept in the data variable; the getRange(row, 2, 1, 10) references the range for the row at which the change on the K column has been made. In order to update the dstSheet, the data value is set to the according range using setValues(data).
Installing the trigger
To make the payINVOICE(e) function trigger on an edit action, you need to install an onEdit trigger.
This is being done by accessing the project's triggers by clicking this icon:
After that, you just need to create a new trigger by clicking the Add trigger button and create a trigger with the following settings:
Trying the function
In order to try the behavior for this, you just need to make an edit on the srcSheet on the K column and this change will be reflected in the destSheet.
Note
The ranges that have been used in this script are chosen considering the fact that:
K column consists of the PAID/NOT PAID text;
The srcSheet and the dstSheet have the data wanted in the same ranges.
You might need to customize these according to your sheet and add the needed formulas/filters you have mentioned.
Reference
Apps Script Installable Triggers;
Apps Script Event Objects.

Google Sheets, fill data from form sheet into specific cells on other sheets

I'm new to coding in general (other than experience with MATLAB which I don't think counts) but I'm starting with trying to code in the Google Sheets API for some advanced functionality.
The code I'm trying to write is for a spreadsheet that I track all my car expenses on. I have it doing a bunch of number crunching for MPG currently, but don't want to have to find the row and column each time to enter the date. Instead I'd like one sheet that is clean and simple that I enter the variables on (Miles driven, gallons pumped, price per gallon, estimated MPG from the car computer) and it fills the other sheets in the document with that information automatically when I hit save, then clears the form so I can do it again next time.
Here is what I have so far.
function submitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName('Fill-Up'); //Form Sheet
var datasheet1 = ss.getSheetByName('Mileage Stats'); //Data Sheet 1
var datasheet2 = ss.getSheetByName('Costs and Savings'); //Data Sheet 2
//Input Values 1
var values1 = [[formSS.getRange('B3').getValue(),
formSS.getRange('B6').getValue()]];
datasheet1.getRange(datasheet1.getLastRow()+1, 2, 1, 2).setValues(values1);
//Input Values 2
var values2 = [[formSS.getRange('B4').getValue(),
formSS.getRange('B5').getValue()]];
datasheet2.getRange(datasheet2.getLastRow()+1, 2, 1, 2).setValues(values2);
}
It works with the exception of two issues that I haven't been able to solve yet.
1) It writes the information to a new row at the bottom of the page, not the next empty row.
2) It isn't writing the information in B6 to the correct cell. I want B3 written to column B in "Mileage Stats" sheet, and it is, B4 is written to column B in "Costs and Savings" as I want, and B5 is written to column C in "Costs and Savings" as I want, but B6 is written to column C in "Mileage Stats" but I want it in column G, and can't figure out how to change that with my current code, or any other code I can find.
Any help anyone can give would be awesome!
Are you using any ArrayFormulas on the sheets that you are trying to use getLastRow()? If so, ArrayFormula will add data into the cells for the whole range.
You may want to look at using the Sheet.appendRow() method like below and remove all the empty rows on your data sheets. appendRow() will add a new row at the bottom of the sheet with that data passed to the method.
datasheet1.appendRow(values1);
datasheet2.appendRow(values2);
Cells with functions are counted as data cells, that's why you're inserting the rows at the bottom of the sheet. To solve this, you can use getNextDataCell() method to a column range without functions (e.g. a cell in column B), which returns the last cell with data for a given direction. I tested the below code and worked for inserting the data in the last row with data in column B:
function submitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName('Fill-Up'); //Form Sheet
var datasheet1 = ss.getSheetByName('Mileage Stats'); //Data Sheet 1
var datasheet2 = ss.getSheetByName('Costs and Savings'); //Data Sheet 2
//Input Values 1
var values1 = [[formSS.getRange('B3').getValue(),
formSS.getRange('B6').getValue()]];
var lastRowInB = datasheet1.getRange("B6").getNextDataCell(SpreadsheetApp.Direction.DOWN).getLastRow();
datasheet1.getRange(lastRowInB+1, 2, 1, 2).setValues(values1);
//Input Values 2
var values2 = [[formSS.getRange('B4').getValue(),
formSS.getRange('B5').getValue()]];
lastRowInB = datasheet1.getRange("B7").getNextDataCell(SpreadsheetApp.Direction.DOWN).getLastRow();
datasheet2.getRange(lastRowInB+1, 2, 1, 2).setValues(values2);
}

Insert specific number of rows in a google sheet

I am trying to insert a specific number of cells into a Google sheet based on a number that is saved as a range. For example, the number in the range is 52, so on sheet 'Master' I want to insert 52 rows after row A3. This range is found on the sheet 'Staff' and changes according to how many staff were present each day, therefore, making it dynamic.
I am looking for some gscript to do this. I have been able to do this using a macro in Excel VBA but would like to move this from Excel to Google Sheets. The VBA code looks like this:
Sheets("Master").Select
Range("A3").EntireRow.Resize(Range("staff_count").Value).Insert CopyOrigin:=xlFormatFromRightOrBelow
Would be very grateful if anyone could help.
Thanks
You want to insert a given number of rows after row 3 on "Master". The number of rows is the value of a range on another sheet "Staff". This value will change from day to day.
In the following example, the range on Staff is cell "B1" and its value is 52.
There are several methods of doing this. In this example, I've used insertRowsAfter(afterPosition, howMany)doc. However, you could also use insertRows(rowIndex, numRows) doc.
function so5910073802() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var mastersheetname = "Master";
var master = ss.getSheetByName(mastersheetname);
var staffsheetname = "Staff";
var staff = ss.getSheetByName(staffsheetname);
// Staff range and value
var staffAttendRange = staff.getRange("B1");
var staffAttendValue = staffAttendRange.getValue(); // value = 52
// Logger.log("DEBUG: Staff attendance = "+staffAttendValue);
// Master variables
var headerRows = 3;
// insert the rows on Master based on value from Staff
master.insertRowsAfter(headerRows, staffAttendValue);
}
Before vs After
The value on row 4 and row 56 is =row()
BEFORE
AFTER

Delete Row in Google Sheet depending on other Google Sheet cell valuie

Is it possible to write a google script that will delete a row in a Google Sheet, based on cell values for a given range, in another google sheet?
I've done some research on how to do this all in the same google sheet, but my limited experience with writing google sheet scripts has prevented me from understanding if what I described is possible, and how.
This is a script I have so far. This will delete rows in a range of my active spreadsheet if a cell in Column F contains the word "id:123456". What I'd like to be able to do, is to modify this code so that if the word "id:123456" is found, it will look in another column of another Google Sheet, and delete rows that contain "id:123456".
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1'); // change to your own
var values = s.getDataRange().getValues();
for (var row in values)
if (values[row][6] == 'id:123456')
s.deleteRow(parseInt(row)+1);
};
I haven't tested this code, so you might need to do some modifications to run successfully. But the basic idea is simple: have two sheets open at once, and based on the if from the first sheet make changes in the second sheet.
var ss1 = SpreadsheetApp.getActiveSpreadsheet();
var ss2 = SpreadsheetApp.getByID(0); //Change to the other sheet's ID, or somehow open it.
var s1 = ss1.getSheetByName('Sheet1'); // change to your own
var s2 = ss2.getSheetByName('Sheet1'); // change to your own
var values = s1.getDataRange().getValues();
for (var row in values)
if (values[row][6] == 'id:123456')
var other_values = s2.getDataRange().getValues();
for (var other_row in other_values)
if (other_values[row][6] == 'id:123456')
s2.deleteRow(parseInt(other_row)+1);
Main thing to be worried about and test: I copied your delete code, but since we're deleting rows, unless we start from the bottom we might start missing. (Suppose rows 4 and 8 out of 10 contain something to be deleted; you might end up deleting 4, which turns 8 to 7, but then we still delete row 8--meaning that we've missed a row we should have deleted and deleted a row we shouldn't have.)