Use Google Apps Script functions in project - javascript

I am very new to Google Apps Scripts and am curious how I can use functions created in my own project. For example, I have a script bound to a spreadsheet with just one function:
function addOrder(title, content) {
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow([ Date(), title, content]);
}
It simply takes 2 arguments and adds a row to the spreadsheet with that data. I have deployed it as a web app, but I'm not sure how to use this function in an environment like JSFiddle. Any help is appreciated.
Thanks

Spreadsheet bound scripts run server side and the SpreadsheetApp.getActiveSheet() method you are using will only work in the context of a spreadsheet bound script since it's the only case where the script actually "sees" an active spreadsheet. When you deploy this as a webapp you will have to tell the script which spreadsheet it must look at using for example the SpreadsheetApp.openById('spreadsheet ID') method.
But even doing so will not allow for using such a code outside of Google environment (as in JS fiddle for example) since SpreadsheetApp is specific to Google Apps service.
You have to remember that Google Apps Script is based on JavaScript but is not "plain" JavaScript , it uses a lot of specific services that work only in relation with Google Apps.
edit to answer your comment below :
the code used in the spreadsheet to work as a data server goes like this : (this is deployed as a webapp without user interface. It runs as a service
function doGet(e) {
if(e.parameter.mode==null){return ContentService.createTextOutput("error, wrong request").setMimeType(ContentService.MimeType.TEXT)};
var mode = e.parameter.mode;
var value = e.parameter.value;
var ss = SpreadsheetApp.openById('1yad5sZZt-X6bIftpR--OSyf3VZWf3Jxx8UJBhh7Arwg');
var sh = ss.getSheets()[0];
if(mode=='read'){
var sheetValues = sh.getDataRange().getValues();// get data from sheet
var valToReturn = ContentService.createTextOutput(JSON.stringify(sheetValues)).setMimeType(ContentService.MimeType.JSON);
return valToReturn;// send it as JSon string
}
if(mode=='write'){
var val = Utilities.base64Decode(value,Utilities.Charset.UTF_8);// decode base64 and get an array of numbers
Logger.log(val);// see it !
var stringVal = ''; // create an empty string
for(var n in val){
stringVal += String.fromCharCode(val[n]);// add each character in turn
}
var sheetValues = JSON.parse(stringVal);// convert the string into an object (2D array)
Logger.log(sheetValues);// check result
sh.getRange(1,1,sheetValues.length,sheetValues[0].length).setValues(sheetValues);// update the sheet
return ContentService.createTextOutput(JSON.stringify(sheetValues)).setMimeType(ContentService.MimeType.JSON);// send back the result as a string
}
return ContentService.createTextOutput('error').setMimeType(ContentService.MimeType.TEXT);// in case mode is not 'read' nor 'write'... should not happen !
}
you can call this service by its url + parameters and it will get / set values in the spreadsheet. This is a basic example but it works nicely.
below it the webapp code of the Ui that uses this service in this spreadsheet
var stylePanel = {'padding':'50px', 'background':'#FFA'};
var styleButton = {'padding':'5px', 'border-radius':'5px', 'borderWidth':'1px', 'borderColor':'#DDD','fontSize':'12pt'};
var styleTextItalic = {'fontSize':'12pt','fontStyle':'italic','fontFamily':'arial,sans-serif','color':'#F00'};
var styleTextNormal = {'fontSize':'12pt','fontStyle':'normal','fontFamily':'arial,sans-serif','color':'#00F'};
var styleLabel = {'fontSize':'12pt','color':'#F00'};
var url = 'https://script.google.com/macros/s/AKfycbwPioVjYMSrmhKnJOaF2GG83dnstLWI7isU9SF1vxPV8td-g9E7/exec';
var numRow = 21;// the number of rows in the grid = number of rows in the SS + 1
;
function doGet() {
var app = UiApp.createApplication().setTitle('url_fetch_demo');
var panel = app.createVerticalPanel().setStyleAttributes(stylePanel);
var headers = ['Field Name','Your answer'];// grid title
var grid = app.createGrid(numRow+2,2);// create the grid with right size
var wait = app.createImage('https://dl.dropboxusercontent.com/u/211279/loading3T.gif').setId('wait').setVisible(false);// get a spinner image in animated gif
var handlerWrite = app.createServerHandler('writeSheet').addCallbackElement(grid);// 2 handlers for the buttons
var handlerRead = app.createServerHandler('readSheet').addCallbackElement(grid);
var Chandler = app.createClientHandler().forTargets(wait).setVisible(true);// a client handler for the spinner
var buttonWrite = app.createButton('Write to Sheet',handlerWrite).addClickHandler(Chandler).setStyleAttributes(styleButton);
var buttonRead = app.createButton('Read from Sheet',handlerRead).addClickHandler(Chandler).setStyleAttributes(styleButton);
for(var n=1 ; n < numRow ; n++){
for(var m=0 ; m < 2 ; m++){ // create all the textBoxes with names & IDs
var textBox = app.createTextBox().setText('no value').setName('text'+n+'-'+m).setId('text'+n+'-'+m).setStyleAttributes(styleTextNormal);
//if(m==0){textBox.setEnabled(false)};// prevent writing to left column (optional)
grid.setWidget(n,m,textBox);// place widgets
}
}
grid.setWidget(numRow,0,buttonRead).setWidget(numRow,1,buttonWrite).setWidget(numRow+1,1,wait) // place buttons
.setWidget(0,0,app.createLabel(headers[0]).setStyleAttributes(styleLabel)) // and headers
.setWidget(0,1,app.createLabel(headers[1]).setStyleAttributes(styleLabel));
app.add(panel.add(grid));
return app; // show Ui
}
function writeSheet(e){
var app = UiApp.getActiveApplication();
app.getElementById('wait').setVisible(false);// spinner will be hidden when fct returns
var dataArrayImage = [];// an array to get typed values
for(var n=1 ; n < numRow ; n++){
var row=[];
for(var m=0 ; m < 2 ; m++){
row.push(e.parameter['text'+n+'-'+m]); // get every value in every "cell"
var textBox = app.getElementById('text'+n+'-'+m).setStyleAttributes(styleTextItalic);// update "cells" style
//textBox.setText('written value = '+e.parameter['text'+n+'-'+m]);// rewrite to the cells - not usefull but serves to check while debugging
}
dataArrayImage.push(row);// store one row(=2cells)
}
var UiValues = JSON.stringify(dataArrayImage);// stringfy the array
var newValues = url+'?mode=write&value='+Utilities.base64Encode(UiValues,Utilities.Charset.UTF_8);// add to url & parameters+ encode in pure ASCII characters
Logger.log(newValues);// check in logger
var check = UrlFetchApp.fetch(newValues).getContent();// get back the result
Logger.log(check);// check result = newValues sent back in bytes format
return app;//update Ui
}
function readSheet(e){
var app = UiApp.getActiveApplication();
app.getElementById('wait').setVisible(false);
var returnedValue = UrlFetchApp.fetch(url+'?mode=read').getContentText();// get data from server
Logger.log(returnedValue);// check values
var sheetValues = JSON.parse(returnedValue);
for(var n=1 ; n < numRow ; n++){
for(var m=0 ; m < 2 ; m++){
var textBox = app.getElementById('text'+n+'-'+m).setStyleAttributes(styleTextNormal);
textBox.setText(sheetValues[n-1][m]);// iterate and update cells values
}
}
return app;// update Ui
}

Related

google-apps-script cannot read array value ("typeError: "cannot read property "1" ) [duplicate]

This question already has an answer here:
Freezing rows in Sheets with Google Apps throws type error
(1 answer)
Closed 2 years ago.
I'm trying to make my code sending an email by referring to my google sheet data. Im using Apps Script and here is the code. However, as I run my function "sendEmail()", I got "typeError: "cannot read property "1" of undefined(line 17)".
Code line 17
var currentEmail = rows[i][1];
Here is the full code.
var ss = "1kuTkOuCd-wKTS2564oHdxALFbFo-IeyjzToYYhB6NrQ";
var SheetName = "FormResp";
function getRows(){
var rangeName = 'FormResp!A2:E';
var rows = Sheets.Spreadsheets.Values.get(ss, rangeName).values;
return rows;
}
function sendEmails() {
var ss_1 = SpreadsheetApp.openById(ss);
var sheet = ss_1.getSheetByName(SheetName);
var lr = sheet.getLastRow();
for (var i = 0;i<=lr;i++){
rows=getRows();
var currentEmail = rows[i][1];
var startingdate = rows[i][3];
var endingdate = rows[i][4];
MailApp.sendEmail(currentEmail,"Thank You for Applying Leave via Leave form: your request leave starting" + startingdate + "until" + endingdate,"Hello");
}
}
function testgetrow(){
var nama = getRows();
var x = "";
}
I do make a test function "testgetrow()" to check my data, and I do manage to run the function without any error and I do confirm that there is values in my getRows() function.
my getRows() function working, and there is a value in the array as shown in the picture below.
I suppose you can do it any way you wish but this seems a lot simpler to me.
function sendEmails() {
const ss = SpreadsheetApp.openById("1kuTkOuCd-wKTS2564oHdxALFbFo-IeyjzToYYhB6NrQ");
const sh = ss.getSheetByName('FormResp');
const rg = sh.getRange(2,1,sh.getLastRow()-1,5);
const vs=rg.getValues();
vs.forEach(r=>{
var currentEmail = r[1];
var startingdate = r[3];
var endingdate = r[4];
MailApp.sendEmail(currentEmail,"Thank You for Applying Leave via Leave form: your request leave starting" + startingdate + "until" + endingdate,"Hello");
});
}
Answer
The main problem is that you have not declared properly the variable rows in your line 16 rows=getRows(); because you forgot to use the keyword var. Change that line with var rows = getRows() and try it again.
Take a look
You are mixing SpreadsheetApp with Sheets API. I recommend you to pick one and stay there to have a clear and less confusing code.
Try use less functions if they are not really necessary, as #Cooper suggested, you can define the variable rows with getRange that can handle A1 notation ranges and getValues.
Define properly your range in A1 notation: if you write A2:E, your range goes from column A, row 2 until column E, row 1000. You have to add the number of the last row in your range, for example A2:E10.
With the last change, you do not have to calculate the last row, you can simply use rows.length.
It is not necessary to have the id of the spreadsheet if your script is a Container-bound Scripts and not a Standalone Script with getActiveSpreadsheet
I attach you a snippet of the code:
var sheetName = "FormResp";
var spreadsheet_id = "1kuTkOuCd-wKTS2564oHdxALFbFo-IeyjzToYYhB6NrQ";
var ss = SpreadsheetApp.openById(spreadsheet_id).getSheetByName(sheetName)
function sendEmails() {
var rangeName = 'A1:B9';
var rows = ss.getRange(rangeName).getValues()
for (var i = 0; i <= rows.length; i++){
var currentEmail = rows[i][1];
var startingdate = rows[i][3];
var endingdate = rows[i][4];
MailApp.sendEmail(currentEmail,"Thank You for Applying Leave via Leave form: your request leave starting" + startingdate + "until" + endingdate,"Hello");
}
}
I hope that it helps you!
References
SpreadsheetApp
Sheets API
getRange
getValues
getActiveSpreadsheet
Container-bound Scripts
Standalone Script

Exception: Document is missing (perhaps it was deleted, or you don't have read access?)

I'm working on a project that take "profiles" stored in a Google Sheet, makes a unique Google Doc for each profile, and then updates the unique Google Doc with any new information when you push a button on the Google Sheet.
I have some other automations built into my original code, but I simplified most of it to what's pertinent to the error I'm getting, which is this:
Exception: Document is missing (perhaps it was deleted, or you don't have read access?
It happens on Line 52 of my script in the fileUpdate funtion. Here's the appropriate line for reference:
var file = DocumentApp.openById(fileName);
And this is the rest of my code:
function manageFiles() {
//Basic setup. Defining the range and retrieving the spreadsheet to store as an array.
var date = new Date();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var array = sheet.getDataRange().getValues();
var arrayL = sheet.getLastRow();
var arrayW = sheet.getLastColumn();
for (var i = 1; i < arrayL; i++) {
if (array[i][arrayW-2] == "") {
//Collect the data from the current sheet.
//Create the document and retrieve some information from it.
var docTitle = array[i , 0]
var doc = DocumentApp.create(docTitle);
var docBody = doc.getBody();
var docLink = doc.getUrl();
//Use a for function to collect the unique data from each cell in the row.
docBody.insertParagraph(0 , "Last Updated: "+date);
for (var j = 2; j <= arrayW; j++) {
var colName = array[0][arrayW-j];
var data = array[i][arrayW-j];
if (colName !== "Filed?") {
docBody.insertParagraph(0 , colName+": "+data);
}
}
//Insert a hyperlink to the file in the cell containing the SID
sheet.getRange(i+1 , 1).setFormula('=HYPERLINK("'+docLink+'", "'+SID+'")');
//Insert a checkbox and check it.
sheet.getRange(i+1 , arrayW-1).insertCheckboxes();
sheet.getRange(i+1 , arrayW-1).setFormula('=TRUE');
}
else if (array[i][arrayW-2] !== "") {
updateFiles(i);
}
}
sheet.getRange(1 , arrayW).setValue('Last Update: '+date);
}
//Note: I hate how cluttered updateFiles is. I'm going to clean it up later.
function fileUpdate(rowNum) {
//now you do the whole thing over again from createFiles()
//Basic setup. Defining the range and retrieving the spreadsheet to store as an array.
var date = new Date();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var array = sheet.getDataRange().getValues();
var arrayL = sheet.getLastRow();
var arrayW = sheet.getLastColumn();
//Collect the data from the current sheet.
var fileName = array[rowNum][0];
var file = DocumentApp.openById(fileName);
//retrieve the body of the document and clear the text, making it blank.
file.getBody().setText("");
//Use a for function to collect the the unique date from every non-blank cell in the row.
file.getBody().insertParagraph(0 , "Last Updated: "+date);
for (var j = 2; j <= arrayW; j++) {
var colName = array[0][arrayW-j];
var data = array[rowNum][arrayW-j];
file.getBody().insertParagraph(0 , colName+": "+data);
}
}
If you'd like to take a look at my sample spreadsheet, you can see it here. I suggest you make a copy though, because you won't have permissions to the Google Docs my script created.
I've looked at some other forums with this same error and tried several of the prescribed solutions (signing out of other Google Accounts, clearing my cookies, completing the URL with a backslash, widening permissions to everyone with the link), but to no avail.
**Note to anyone offended by my janky code or formatting: I'm self-taught, so I do apologize if my work is difficult to read.
The problem (in the updated code attached to your sheet) comes from your URL
Side Note:
In your initial question, you define DocumentApp.openById(fileName);
I assume your realized that this is not correct, since you updated
your code to DocumentApp.openByUrl(docURL);, so I will discuss the
problem of the latter in the following.
The URLs in your sheet are of the form
https://docs.google.com/open?id=1pT5kr7V11TMH0pJea281VhZg_1bOt8YDRrh9thrUV0w
while DocumentApp.openByUrl expects a URL of form
https://docs.google.com/document/d/1pT5kr7V11TMH0pJea281VhZg_1bOt8YDRrh9thrUV0w/
Just adding a / is not enough!
Either create the expected URL manually, or - much easier / use the method DocumentApp.openById(id) instead.
For this, you can extract the id from your URL as following:
var id = docURL.split("https://docs.google.com/open?id=")[1];
var file = DocumentApp.openById(id)

Google App Scripts find text in spreadsheet and return location index

I am a novice here to google app scripts and my JavaScript is also not very strong, but neither of these seem to be the problem here as my code works the first time I run it but then when I try to call it again it fails.
Simply I am trying to have a function that will dynamically find a given text in a given range. While it looks like there might be a built in package that does this I cannot figure out how to implement it. And the documentation is not helpful for someone new.
Option 1: was to implement the following: https://developers.google.com/apps-script/reference/spreadsheet/text-finder#findAll()
Since that has not been sucessful in finding out how to do it I moved to creating the following simple two functions, Option 2:
function findIndexRow(range,fText){
for(var i = 0; i<range.length;i++){
for(var j = 0; j<range.length;j++){
if(range[i][j] == fText){
var fTextRow = i+1;
var fTextCol = j+1;
}
}
}
return fTextRow
}
function findIndexCol(range,fText){
for(var i = 0; i<range.length;i++){
for(var j = 0; j<range.length;j++){
if(range[i][j] == fText){
var fTextRow = i+1;
var fTextCol = j+1;
}
}
}
return fTextCol
}
It takes in a range that I defined like:
var sheet = SpreadsheetApp.openById('the-gsheet-id');
var CurrSheet = sheet.getSheetByName('Sheet1');
var SHTvalues = CurrSheet.getDataRange().getValues();
So the above works when I call it once in my main code but the second time it returns null, help here as to why re calling the same function does not work.
var text1Row = findIndexRow(SHTvalues,"text1");
var text1Col = findIndexCol(SHTvalues,"text1");
Logger.log(text1Row)
Logger.log(text1Col)
var text2Row = findIndexRow(SHTvalues,"text2");
var text2Col = findIndexCol(SHTvalues,"text2");
Logger.log(text2Col)
Logger.log(text2Row)
I can't understand why my logs return the correct values for text1Row and text1Col but when it is called a second time the text2Row and text2Col both return null
I believe your goal as follows.
You want to search a text value from a sheet in the Google Spreadsheet, and want to retrieve the row and column numbers of the found values.
You want to achieve this using TextFinder.
For this, how about this answer?
Sample script:
var findText = "text1";
var sheet = SpreadsheetApp.openById('the-gsheet-id');
var CurrSheet = sheet.getSheetByName('Sheet1');
var SHTvalues = CurrSheet.createTextFinder(findText).findAll();
var result = SHTvalues.map(r => ({row: r.getRow(), col: r.getColumn()}));
console.log(result)
Note:
About my logs return the correct values for text1Row and text1Col but when it is called a second time the text2Row and text2Col both return null in your script, if there are the values of text1 and text2 in Sheet1, text1Row, text1Col, text2Col and text2Row has the values. If only the value of text1 is put in Sheet1, text1Col and text2Col has the values. But text2Col and text2Row has no values (null). Please be careful this.
But in this case, when 2 values of `text1 are put to the cells "A1" and "A2", only "A2" is returned. Also please be careful this.
In this sample script, please enable V8.
References:
createTextFinder() in Class Sheet
Class TextFinder
Here's a script that I used for searching through my spreadsheets when I'm having trouble finding the sheet I want. It does read another sheet to get a list of spreadsheets to search through.
function regexSearch(sObj) {
var ass=SpreadsheetApp.getActive();
var startRow=2;
var msrsh=ass.getSheetByName('MultiSearchResults');
msrsh.clearContents();
msrsh.appendRow(['Path','FileName','FileId','SheetName','CellA1Notation','Value','Pattern']);
msrsh.activate();
var sh=ass.getSheetByName('SelectedSpreadsheets');
var hA=sh.getRange(1,1,1,sh.getLastColumn()).getValues()[0];
var getArrayIndex={};
hA.forEach(function(e,i){getArrayIndex[e]=i;});
var rg=sh.getRange(startRow,1,sh.getLastRow()-startRow+1,sh.getLastColumn());
var ssA=rg.getValues();
var matches='';
var n=0
for(var k=0;k<ssA.length;k++) {
var fileid=ssA[k][getArrayIndex['FileId']];
var filename=ssA[k][getArrayIndex['FileName']];
var filepath=getFilePathFromId(ssA[k][getArrayIndex['FileId']]);
//Logger.log(fileid);
var ss=SpreadsheetApp.openById(fileid);
Logger.log(sObj.pattern);
var tf=ss.createTextFinder(sObj.pattern).useRegularExpression(true);
var all=tf.findAll();
for(var i=0;i<all.length;i++) {
if(i==0)n++;
matches+=Utilities.formatString('<br /><b>Path:</b> %s <b>Sheet:</b> %s <b>Cell:</b> %s <b>Value:</b> %s<hr width="100%"/>',filepath,all[i].getSheet().getName(),all[i].getA1Notation(),all[i].getValue());
msrsh.appendRow([filepath,filename,fileid,all[i].getSheet().getName(),all[i].getA1Notation(),all[i].getValue(),sObj.pattern]);
}
}
if(matches) {
sObj.matches=matches;
sObj.message=Utilities.formatString('<p>Pattern %s was found in %s spreadsheet out of a total of %s</p>',sObj.pattern,n,ssA.length);
}else{
sObj.message=Utilities.formatString('No Matches found for %s',sObj.pattern);
}
return sObj;
}

Looking for one Google Script App for 4 sheet tabs to produce one json

Ok...not sure how to do this. Right now I 4 sheets and 4 scripts for each sheet producing 4 json feeds. What I am trying to experiment with is having one script that will produce 1 json that I can use in a web page and just call the type of class. They are all formatted the same with columns etc.
Here is the Google Script App code I have.
function doGet(e){
// Change Spread Sheet url
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/SpreadsheetID/edit#gid=0");
// Sheet Name, Change Sheet to whatever name you used to name your sheet
var sheet = ss.getSheetByName("Class Sheet 1");
return getClasses(sheet);
}
function getClasses(sheet){
var dataObj = {};
var dataArray = [];
// collecting data starting from 2nd Row , 1st column to last row and last column
var rows = sheet.getRange(2,1,sheet.getLastRow()-1, sheet.getLastColumn()).sort([{column: 1, ascending: true}, 1]).getValues();
for(var i = 0, l= rows.length; i<l ; i++){
var dataRow = rows[i];
var record = {};
record['Name'] = dataRow[0];
record['Note'] = dataRow[1];
record['Address'] = dataRow[2];
record['StreetAddress'] = dataRow[3];
record['City'] = dataRow[4];
record['State'] = dataRow[5];
record['ZipCode'] = dataRow[6];
record['ContactName'] = dataRow[7];
record['EMailAddress'] = dataRow[8];
record['CustomerServicePhone'] = dataRow[9];
dataArray.push(record);
}
dataObj = dataArray;
var result = JSON.stringify(dataObj);
return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);
}
Scratching my head on this a little bit....I'm sure its something simple and I am probably over thinking things, but any help would be appreciated.
Possible Solution:
The e object in your doGet(e) provides a way to send parameters to your script. You can access different sheets with different url parameters. You can then easily get the requested SheetName through e.parameter. Use
https://script.google.com/.../exec?sheet=ClassSheet1 //for ClassSheet1
https://script.google.com/.../exec?sheet=ClassSheet2 //for ClassSheet2
Code.gs:
function doGet(e){
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/SpreadsheetID/edit#gid=0");
var sheetName = e.parameter.sheet;
var sheet = ss.getSheetByName(sheetName);
return getClasses(sheet);
}
You can also provide UI in your web-app to select a sheet.

Update data from a Spreadsheet - Apps Script

I'm doing a data transfer of several spreadsheets to a single one, what I do is transfer the last data of certain columns to the master spreadsheet and also insert them in the last available row of certain columns, for now, I insert all the data but I would like to to know how I can have it examine the master spreadsheet so that if those data already exist, it does not delete them but update them. The script that I have is the following ...
function Gas10(){
var ss1 = SpreadsheetApp.openById("ID");
var ssh1 = ss1.getSheetByName("Sheet 1");
var lastRow1 = ssh1.getLastRow();
var gtRange1 = ssh1.getRange("C"+(lastRow1)+":K"+(lastRow1)).getValues();
var gtRange2= ssh1.getRange("A" + (lastRow1)).getValue();
var ss2 = SpreadsheetApp.getActiveSpreadsheet();
var ssh2 = ss.getSheetByName("Sheet 2");
var lastRow2 = ssh2.getLastRow() + 1;
var setRange1 = ssh2.getRange(lastRow2, 4, gtRange1.length, gtRange1[0].length).setValues(gtRange1);
var setRange2 = ssh2.getRange(lastRow2, 3).setValue(gtRange2);
}
I need to know how I can do it when I insert a piece of information (I already do that), but update it if it already exists. This is the example that I created so that it can be better understood, in this example I have two sheets of which from sheet 1 I pass data to sheet 2 and what I'm looking for is that sheet 2 updates all the data that are equal to (Name, Num, Proyect). I hope that now I understand better what I'm looking for.
Basically what you have to do is
get the new Line you want to add to the destination spreadsheet
get all the required datas of the destination spreadsheet
Check if the new Line datas have the same datas than in the destination data array
If so change ID value
paste changed datas in the destination spreadsheet
based on this spreadsheet The code should look something like this
function Gas10(){
var ss1 = SpreadsheetApp.getActiveSpreadsheet();
var ssh1 = ss1.getSheetByName("Sheet 1");
var ssh2 = ss1.getSheetByName("Sheet 2");
var lastRow1 = ssh1.getLastRow();
var lastCol1 = ssh1.getLastColumn();
var newLine = ssh1.getRange(lastRow1, 2, 1, lastCol1 - 1 ).getValues();
var destDatas = ssh2.getDataRange().getValues();
for (var i = 1; i < destDatas.length; i++)
{
if (newLine[0][0] == destDatas[i][0]
&& newLine[0][1] == destDatas[i][1]
&& newLine[0][2] == destDatas[i][2])
{
destDatas[i][3] = newLine[0][3];
}
}
// add newLine to destDatas
destDatas.splice(destDatas.length, 0, newLine[0]);
var lastColumn = ssh2.getLastColumn();
var lastRow2 = ssh2.getLastRow() + 1;
ssh2.getRange(1, 1, destDatas.length, lastColumn).setValues(destDatas);
ssh1.deleteRow(lastRow1);
}
Here's an example I played around with:
It looks at the slave sheet for any data. When it finds data it puts the row and col and value into an obj which is then added to an array. When it finishes it calls the updMaster which then looks for data in those same cells (assuming that the cells are in the same place if those cells are blank then it adds data and I also changed the background to lightblue to show me where it updated the cells.
You could run the getSlaveData() for different sheets if you wish.
function getSlaveData(){
var ss=SpreadsheetApp.getActive();
var ssh=ss.getSheetByName('Sheet2');
var sA=[];
var srg=ssh.getDataRange();
var svA=srg.getValues();
for(var i=0;i<svA.length;i++){
for(var j=0;j<svA[i].length;j++){
//if(svA[i][j]){
if(!ssh.getRange(i+1,j+1).isBlank()){//optional way to look for values
var sObj={};
sObj['row']=i + 1;
sObj['col']=j + 1;
sObj['value']=svA[i][j];
sA.push(sObj);
}
}
}
updMaster(sA);
}
function updMaster(sA){
var ss=SpreadsheetApp.getActive();
var msh=ss.getSheetByName('Sheet1');
for(var i=0;i<sA.length;i++){
if(msh.getRange(sA[i].row,sA[i].col).isBlank()){
msh.getRange(sA[i].row,sA[i].col).setValue(sA[i].value);
msh.getRange(sA[i].row,sA[i].col).setBackground('lightblue');
}
}
}

Categories

Resources