Double the variables in move script (Google) - google-apps-script

For my work I am trying to automatically move a marked line to a 'Historie' sheet. I have currently managed to follow an example and use 1 variable (see copy).
Now I want 2 variables. Instead of just column K -> Completed, I also want to add that column J needs to be True!
function onEdit(event){
var url = "https://docs.google.com/spreadsheets/d/1per7L2wPkMKrzVgv5npQ-2RQ8fkWzslo09Ntlzy4qAs/edit?ts=6034e66e#gid=0";
var source_sheet_name = "Werklijst";
var target_sheet_name = "Historie";
var columnLetter = "J";
var ss= SpreadsheetApp.openByUrl(url);
var source_sheet = ss.getSheetByName(source_sheet_name);
var target_sheet = ss.getSheetByName(target_sheet_name);
var source_range = source_sheet.getRange(columnLetter+":"+columnLetter).getValues();
for(var i = source_range.length-1; i >= 0;i--){
if(source_range[i]=="COMPLETE"){
var targetRange = target_sheet.getRange(target_sheet.getLastRow() + 1, 1);
source_sheet.getRange((i+1), 1, 1, source_sheet.getLastColumn()).moveTo(targetRange);
source_sheet.deleteRow((i+1));
}
}
}
Here is the link to a copy of said sheet (it is in Dutch).

The obvious solution would be to do something like that:
var columnLetter1 = "K";
var columnLetter2 = "J";
var source_range1 = source_sheet.getRange(columnLetter1+":"+columnLetter1).getValues();
var source_range2 = source_sheet.getRange(columnLetter2+":"+columnLetter2).getValues();
and then change the if statement to:
if(source_range1[i]=="COMPLETE" && source_range2[i]==true)
Full snippet of the user's code with the modification points:
function onEdit(event){
var url = "https://docs.google.com/spreadsheets/d/1per7L2wPkMKrzVgv5npQ-2RQ8fkWzslo09Ntlzy4qAs/edit?ts=6034e66e#gid=0";
var source_sheet_name = "Werklijst";
var target_sheet_name = "Historie";
var columnLetter1 = "K";
var columnLetter2 = "J";
var ss= SpreadsheetApp.openByUrl(url);
var source_sheet = ss.getSheetByName(source_sheet_name);
var target_sheet = ss.getSheetByName(target_sheet_name);
var source_range1 = source_sheet.getRange(columnLetter1+":"+columnLetter1).getValues();
var source_range2 = source_sheet.getRange(columnLetter2+":"+columnLetter2).getValues();
for(var i = source_range.length-1; i >= 0;i--){
if(source_range1[i]=="COMPLETE" && source_range2[i]==true){
var targetRange = target_sheet.getRange(target_sheet.getLastRow() + 1, 1);
source_sheet.getRange((i+1), 1, 1, source_sheet.getLastColumn()).moveTo(targetRange);
source_sheet.deleteRow((i+1));
}
}
}
Keep in mind that the current code is not very optimal since you don't use the event object anywhere in your code. The latter will help you get info regarding the edits.
For example, right now your whole code will be executed upon every edit in any cell in the entire spreadsheet file. If you use the event object you can execute some code upon edits on a particular sheet (e.g. Werklijst) and on particular cells (e.g. cells in column K or J). In this way your code will be way faster and more efficient.

Related

Missing Headers row and Leaving space

I was working with a combine sheets app script which is working fine at the spot by mereging A bunch of 36 sheetsinto one masterenter code here
the only flaw of the script is that it is not showing a common header row in the top and also leaving a space after data end from first sheets and so on >>>
here the code can anyone help a bit here
function combineSheets() {
var sApp = SpreadsheetApp.getActiveSpreadsheet();
var s1= sApp.getSheetByName("A1");
var s2= sApp.getSheetByName("A2");
var s3= sApp.getSheetByName("A3");
var s4= sApp.getSheetByName("A4");
var s5= sApp.getSheetByName("A5");
var s6= sApp.getSheetByName("A6");
var s7= sApp.getSheetByName("A7");
var s8= sApp.getSheetByName("A8");
var s9= sApp.getSheetByName("A9");
var s10= sApp.getSheetByName("A10");
var s11= sApp.getSheetByName("A11");
var s12= sApp.getSheetByName("A12");
var s13= sApp.getSheetByName("A13");
var s14= sApp.getSheetByName("A14");
var s15= sApp.getSheetByName("A15");
var s16= sApp.getSheetByName("A16");
var s17= sApp.getSheetByName("A17");
var s18= sApp.getSheetByName("A18");
var s19= sApp.getSheetByName("A19");
var s20= sApp.getSheetByName("A20");
var s21= sApp.getSheetByName("A21");
var s22= sApp.getSheetByName("A22");
var s23= sApp.getSheetByName("A23");
var s24= sApp.getSheetByName("A24");
var s25= sApp.getSheetByName("A25");
var s26= sApp.getSheetByName("A26");
var s27= sApp.getSheetByName("A27");
var s28= sApp.getSheetByName("A28");
var s29= sApp.getSheetByName("A29");
var s30= sApp.getSheetByName("A30");
var s31= sApp.getSheetByName("A31");
var s32= sApp.getSheetByName("A32");
var s33= sApp.getSheetByName("A33");
var s34= sApp.getSheetByName("A34");
var s35= sApp.getSheetByName("A35");
var s36= sApp.getSheetByName("A36");
var s37= sApp.getSheetByName("Master");
// If Master doesn't exist you'll need to create it here.
var s1values = s1.getRange(2,1,s1.getLastRow(),27).getValues();
var s2values = s2.getRange(2,1,s2.getLastRow(),27).getValues();
var s3values = s3.getRange(2,1,s3.getLastRow(),27).getValues();
var s4values = s4.getRange(2,1,s4.getLastRow(),27).getValues();
var s5values = s5.getRange(2,1,s5.getLastRow(),27).getValues();
var s6values = s6.getRange(2,1,s6.getLastRow(),27).getValues();
var s7values = s7.getRange(2,1,s7.getLastRow(),27).getValues();
var s8values = s8.getRange(2,1,s8.getLastRow(),27).getValues();
var s9values = s9.getRange(2,1,s9.getLastRow(),27).getValues();
var s10values = s10.getRange(2,1,s10.getLastRow(),27).getValues();
var s11values = s11.getRange(2,1,s11.getLastRow(),27).getValues();
var s12values = s12.getRange(2,1,s12.getLastRow(),27).getValues();
var s13values = s13.getRange(2,1,s13.getLastRow(),27).getValues();
var s14values = s14.getRange(2,1,s14.getLastRow(),27).getValues();
var s15values = s15.getRange(2,1,s15.getLastRow(),27).getValues();
var s16values = s16.getRange(2,1,s16.getLastRow(),27).getValues();
var s17values = s17.getRange(2,1,s17.getLastRow(),27).getValues();
var s18values = s18.getRange(2,1,s18.getLastRow(),27).getValues();
var s19values = s19.getRange(2,1,s19.getLastRow(),27).getValues();
var s20values = s20.getRange(2,1,s20.getLastRow(),27).getValues();
var s21values = s21.getRange(2,1,s21.getLastRow(),27).getValues();
var s22values = s22.getRange(2,1,s22.getLastRow(),27).getValues();
var s23values = s23.getRange(2,1,s23.getLastRow(),27).getValues();
var s24values = s24.getRange(2,1,s24.getLastRow(),27).getValues();
var s25values = s25.getRange(2,1,s25.getLastRow(),27).getValues();
var s26values = s26.getRange(2,1,s26.getLastRow(),27).getValues();
var s27values = s27.getRange(2,1,s27.getLastRow(),27).getValues();
var s28values = s28.getRange(2,1,s28.getLastRow(),27).getValues();
var s29values = s29.getRange(2,1,s29.getLastRow(),27).getValues();
var s30values = s30.getRange(2,1,s30.getLastRow(),27).getValues();
var s31values = s31.getRange(2,1,s31.getLastRow(),27).getValues();
var s32values = s32.getRange(2,1,s32.getLastRow(),27).getValues();
var s33values = s33.getRange(2,1,s33.getLastRow(),27).getValues();
var s34values = s34.getRange(2,1,s34.getLastRow(),27).getValues();
var s35values = s35.getRange(2,1,s35.getLastRow(),27).getValues();
var s36values = s36.getRange(2,1,s36.getLastRow(),27).getValues();
// Now, we can put out all together and stuff it in Master
var s37values = [];
s37values = s1values.concat(s2values,s3values,s4values,s5values,s6values,s7values,s8values,s9values,s10values,s11values,s12values,s13values,s14values,s15values,s16values,s17values,s18values,s19values,s20values,s21values,s22values,s23values,s24values,s25values,s26values,s27values,s28values,s29values,s30values,s31values,s32values,s33values,s34values,s35values,s36values);
s37.getRange(1,1,s37values.length,27).setValues(s37values);
}
Modification points:
About not showing a common header row in the top, in your script, all values are retrieved from the 2nd row. I thought that this might be the reason for your issue. From a common header row, in this modification, the header row is retrieved from the 1st sheet.
About also leaving a space after data end from first sheets and so on, I thought that the reason of your issue is due to getRange(2,1,s1.getLastRow(),27). In this case, the values are retrieved from 2nd row to the last row + 1 rows. In this case, it required to be getRange(2,1,s1.getLastRow() - 1,27).
In your script, I thought that the sheet names from "A1" to "A36" can be created using a script.
When these points are reflected in your script, it becomes as follows.
Modified script:
function combineSheets() {
var sApp = SpreadsheetApp.getActiveSpreadsheet();
var values = [...Array(36)].map((_, i) => `A${i + 1}`).flatMap((s, i) => {
var sheet = sApp.getSheetByName(s);
var lastRow = sheet.getLastRow();
if (i == 0) {
return sheet.getRange(1, 1, lastRow, 27).getValues();
}
return lastRow > 1 ? sheet.getRange(2, 1, lastRow - 1, 27).getValues() : [];
});
sApp.getSheetByName("Master").getRange(1, 1, values.length, 27).setValues(values);
}
The headr row is retrieved from the 1st sheet.
Note:
In this modification, it supposes that the sheet names of "A1" to "A36" and "Master" are existing in your Spreadsheet. Please be careful about this.
From a common header row in the top, this script supposes that your all sheets have the same header row. Please be careful about this.
About Exception: The number of rows in the range must be at least 1. AT HERE................var values = [...Array(36)].map((_, i) => A${i + 1}).flatMap((s, i) => { var sheet = sApp.getSheetByName(s); return sheet.getRange(i == 0 ? 1 : 2, 1, sheet.getLastRow() - (i == 0 ? 0 : 1), 27).getValues(); , from your question, I had thought that your all sheets have the values. But from your reply, it seems that my understanding was not correct. So, I updated my proposed script. Could you please confirm it?
References:
getRange(row, column, numRows, numColumns)
map()

I'm looking to improve the code I use to copy down data

I have some code made by recording a macro in Google Sheets. It does a copy and paste of data into a column. But it's a clumsy way to copy down and I'd like to do it better.
I currently use this code.
function import2() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Road MT'),
true);
spreadsheet.getRange('C2').activate();
spreadsheet.getRange('Imported!A2:A').copyTo(spreadsheet.getActiveRange(),
SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
I have also used code similar to below, but the problem with this code is that it throws an error if the rows don't actually exist. It's doesn't create new rows to fill the data.
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('\'Round Up\'!F:F').activate();
spreadsheet.getActiveRangeList().setNumberFormat('#')
var range = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
range.getRange("\'Road MT\'!AF2").setFormula('=\'Round Up\'!F2');
var lr = range.getLastRow();
var fillDownRange = range.getRange(2, 32, lr-1);
range.getRange("\'Road MT\'!AF2").copyTo(fillDownRange);
I use a script to do something like that. It won't create row your way, but if you know the range of what you are pasting, you can set the range of the data to copy to be rows that don't exist yet and it will make them.
var spreadsheet = SpreadsheetApp.getActive();
//this get what you want to copy and it's length
var sheetToCopy = spreadsheet.getSheetByName(<name>); //or similar
var rangeToCopy = sheetToCopy.getRange(<yourRange>)
var dataToCopy = rangeToCopy.getValues()
var nRowsToCopy = dataToCopy.length // or rangeToCopy.getLastRow()
var nColsToCopy = rangeToCopy.getLastColumn() //because dataToCopy[0].lenght might vary from dataToCopy[5].lenght
//this get get where you wanna copy it and set the proper range so it can be pasted
var fillDownSheet = spreadsheet.getSheetByName(<name>); //or similar
var fillDownRow = fillDownSheet.getLastRow()+1;
var fillDownRange = fillDownSheet.getRange(fillDownRow, <yourColIndex>, nRowsToCopy, nColsToCopy);
//this paste your data
fillDownRange.setValues(dataToCopy);
Alternatively, you could also use the copyToDestination() method like so :
var spreadsheet = SpreadsheetApp.getActive();
var sheetToCopy = spreadsheet.getSheetByName(<name>); //or similar
var rangeToCopy = sheetToCopy.getDataRange()
var nRowsToCopy = rangeToCopy.getLastRow()
var nColsToCopy = rangeToCopy.getLastColumn()
var fillDownSheet = spreadsheet.getSheetByName(<name>); //or similar
var fillDownRow = fillDownSheet.getLastRow();
var fillDownRange = fillDownSheet.getRange(fillDownRow, 1);
var fillDownGridID = fillDownRange.getGridId();
rangeToCopy.copyValuesToRange(fillDownGridID, 1, nRowsToCopy, fillDownRow, (fillDownRow+nColsToCopy))
But you need at least one empty row on your sheet or it's going to overwrite it.

My If statement isn't returning a value based on cell being blank or has data

My If statement says that if the cell it is looking at is null, then return x, if it's got a value in it, then Y... The logger shows data in the cell, but it still returns x!
I've tried changing to isblank, is null, is "". I can see that it is logging data, but it is still returning the answer for a blank cell
function trackingSheetUpdate() {
var now = new Date();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName('Active Campaign');
var Tracking = ss.getSheetByName('Tracking')
var getUpdate = sourceSheet.getRange(2, 5).getValue();
var dateResult = now - sourceSheet.getRange(2, 6).getValue();
var openSS = SpreadsheetApp.openByUrl(getUpdate).getSheetByName('Sheet1')
var weeklyUpdate = openSS.getRange(2, 1).getValue();
if (dateResult > 1 && dateResult <= 7); {
if (weeklyUpdate == null, Tracking.getRange(2, 2).setValue("x"));
else
("Y");
}
}
I want x if the cell is blank and Y if cell is not blank, but it only returns x! Eventually I am going to loop this through a dynamic range, but want to get the basics right first!
I created some test sheet data of my own and the below code seemed to work as you're expecting it to.
function trackingSheetUpdate() {
var now = new Date();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName('Active Campaign');
var trackSheet = ss.getSheetByName('Tracking');
var getUpdate = sourceSheet.getRange(2, 5).getValue();
var dateResult = now - sourceSheet.getRange(2, 6).getValue();
var openSheet = SpreadsheetApp.openByUrl(getUpdate).getSheetByName('Sheet1');
var weeklyUpdate = openSheet.getRange(2, 1).getValue();
if (dateResult > 1 && dateResult <= 7); {
if (weeklyUpdate == '') {
trackSheet.getRange(2, 2).setValue("x");
} else {
trackSheet.getRange(2, 2).setValue("y");
}
}
}
Of course this relies on your sheet data being correct, for example you need var getUpdate to be a URL. I have also renamed some variables for consistency with the rest of the script, along with some grammatical changes like making sure there are semicolons to end lines etc.

Method is heavily used by the script

I am very new on using Google Apps Script and has a shallow knowledge on programming. What I am trying to do is copy the values of specific columns to a different Spreadsheet. Here's my code:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var responses = ss.getSheetByName("Responses ID");//Where ID's of the spreadsheets are listed.
var consolidatedSheet = ss.getSheetByName("Consolidated");//Where the data should be pasted.
var responseColValues = responses.getRange(2,2, responses.getMaxRows() -1).getValues();
var responsesIds = [i for each (i in responseColValues)if (isNaN(i))];
var ssSelected = SpreadsheetApp.openById(responsesIds[0]);
var selectedSheets = ssSelected.getSheets();
for (i=0; i<3; i++){
var maxRows = selectedSheets[i].getLastRow()-1;
var x=2, y=2;
var lastRow = consolidatedSheet.getLastRow()+1;
for (j=0; j<maxRows; j++){
var eventID = selectedSheets[i].getRange(y,2).getValue();
var employeeName = selectedSheets[i].getRange(y,3).getValue();
var productionDate = selectedSheets[i].getRange(y,4).getValue();
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,1).setValue(eventID);
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,2).setValue(employeeName);
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,3).setValue(productionDate);
y++;
lastRow++;
}
}
}
However, I am experiencing this notification on the Execution hints (light bulb icon):
screenshot of the message. I am thinking that my code can be simplified. I am just not sure how to do it. Thank you in advance.
Every line with .getRange().getValue() and getRange.setValue() is a call to the file. Since you have these inside a for(){} loop, they are being called many times. Your goal is to limit these to as few as possible. Since you can read and write a range, you could do something similar to this:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var responses = ss.getSheetByName("Responses ID");//Where ID's of the spreadsheets are listed.
var consolidatedSheet = ss.getSheetByName("Consolidated");//Where the data should be pasted.
var responseColValues = responses.getRange(2,2, responses.getMaxRows() -1).getValues();
var responsesIds = [i for each (i in responseColValues)if (isNaN(i))];
var ssSelected = SpreadsheetApp.openById(responsesIds[0]);
var selectedSheets = ssSelected.getSheets();
for (i=0; i<3; i++){
var maxRows = selectedSheets[i].getLastRow()-1;
var y=2;
var lastRow = consolidatedSheet.getLastRow()+1;
var copyValues = selectedSheets[i].getRange(y,2, maxRows, 4).getValues();
consolidatedSheet.getRange(lastRow,1, maxRows, 4).setValues(copyValues);
}
}

Copy value and format from a sheet to a new google Spreadsheet document?

I need to copy a sheet on google SpreadSheet to another SpreadSheet document.
I´ve done my research, and I found two methods that do this, however both have problems that I don´t know how to fix.
The first method copies the sheet with format, but it keeps the referenced cells, so I get a reference error in the new document (#ref). I need a function that copies the format and the values (not references).
function copySheet() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var sheet = source.getSheets()[0];
var destination = SpreadsheetApp.openById("15ucPbZrIYXZAOCYVdpK6OA0oyQT1NcsmuiJmDRfdpHQ");
sheet.copyTo(destination);
}
This second method copies the values without references, however it copies only values, without format.
function copySheetValues()
{
var source = SpreadsheetApp.getActiveSheet();
var sourcename = source.getSheetName();
var sourceDataRange = source.getDataRange();
var sourceSheetValues = sourceDataRange.getValues();
var sourceRows = sourceDataRange.getNumRows();
var sourceColumns = sourceDataRange.getNumColumns();
var destination = SpreadsheetApp.openById('15ucPbZrIYXZAOCYVdpK6OA0oyQT1NcsmuiJmDRfdpHQ');
destination.insertSheet(sourcename, 0);
destination.getDataRange().offset(0, 0, sourceRows, sourceColumns).setValues(sourceSheetValues);
}
How do I write a function that keeps the format and copies the values?
Since you seem to know how to get and set values using the whole data range, just use the other methods to get and set all the other parameters.
The script editor autocomplete is a great help in this case to try not to forget one !
I hope the list is complete, it is a bit of a pain to write though !.
code below, if one of them is not useful to you just delete it (in both directions (set and get).
function copySheetValues(){
var source = SpreadsheetApp.getActiveSheet();
var sourcename = source.getSheetName();
var sValues = source.getDataRange().getValues();
var sBG = source.getDataRange().getBackgrounds();
var sFC = source.getDataRange().getFontColors();
var sFF = source.getDataRange().getFontFamilies();
var sFL = source.getDataRange().getFontLines();
var sFFa = source.getDataRange().getFontFamilies();
var sFSz = source.getDataRange().getFontSizes();
var sFSt = source.getDataRange().getFontStyles();
var sFW = source.getDataRange().getFontWeights();
var sHA = source.getDataRange().getHorizontalAlignments();
var sVA = source.getDataRange().getVerticalAlignments();
var sNF = source.getDataRange().getNumberFormats();
var sWR = source.getDataRange().getWraps();
var destination = SpreadsheetApp.openById('15ucPbZrIYXZAOCYVdpK6OA0oyQT1NcsmuiJmDRfdpHQ');
var destinationSheet = destination.insertSheet(sourcename, 0);
destinationSheet.getRange(1,1,sValues.length,sValues[0].length).setValues(sValues)
.setBackgrounds(sBG)
.setFontColors(sFC)
.setFontFamilies(sFF)
.setFontLines(sFL)
.setFontFamilies(sFFa)
.setFontSizes(sFSz)
.setFontStyles(sFSt)
.setFontWeights(sFW)
.setHorizontalAlignments(sHA)
.setVerticalAlignments(sVA)
.setNumberFormats(sNF)
.setWraps(sWR);
}
Edit :
Bryan's answer and your comment made me think of another solution, much more simple and that handles merged cells as well. Here is the code :
function copySheetValuesV2(){
var source = SpreadsheetApp.getActiveSheet();
var sourceName = source.getSheetName();
var sValues = source.getDataRange().getValues();
var destination = SpreadsheetApp.openById('15ucPbZrIYXZAOCYVdpK6OA0oyQT1NcsmuiJmDRfdpHQ');
source.copyTo(destination)
var destinationSheet = destination.getSheetByName('Copy of '+sourceName)
destinationSheet.getRange(1,1,sValues.length,sValues[0].length).setValues(sValues);// overwrite all formulas that the copyTo preserved
}
In both script be sure that the destination sheet name does not already exist. I didn't handle that case although it is quite easy to do with a try/catch structure.
Another route to try that I think Serge was alluding to here.
function myFunction() {
var source = SpreadsheetApp.openById('SOURCE_ID');
var sourceSheet = source.getSheetByName('Sheet1');
var sourceRange = sourceSheet.getDataRange();
var sourceValues = sourceRange.getValues();
var tempSheet = source.getSheetByName('temp');
var tempRange = tempSheet.getRange('A1');
var destination = SpreadsheetApp.openById('DEST_ID');
sourceRange.copyTo(tempRange); // paste all formats?, broken references
tempRange.offset(0, 0, sourceValues.length, sourceValues[0].length)
.setValues(sourceValues); // paste all values (over broken refs)
tempSheet.copyTo(destination); // now copy temp sheet to another ss
}
This is a variation upon Sergei's answer.
This script will copy all visible sheets and export them in to a new spreadsheet with " Final" appended to the document title.
function copySheetValuesV4(){
var sourceSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheets = sourceSpreadsheet.getSheets();
var destination = SpreadsheetApp.create(sourceSpreadsheet.getName()+' Final');
for (var i = 0; i < sourceSheets.length; i++){
var sourceSheet = sourceSheets[i];
if (!sourceSheet.isSheetHidden()) {
var sourceSheetName = sourceSheet.getSheetName();
var sValues = sourceSheet.getDataRange().getValues();
sourceSheet.copyTo(destination)
var destinationSheet = destination.getSheetByName('Copy of '+sourceSheetName).setName(sourceSheetName);
destinationSheet.getRange(1,1,sValues.length,sValues[0].length).setValues(sValues);// overwrite all formulas that the copyTo preserved */
}
destination.getSheetByName("sheet1").hideSheet() // Remove the default "sheet1" */
}
}