Google Scripts - Function Error with Time Trigger - javascript

This function/trigger combo is intended to keep a log of live data on a daily basis. The intent is that N2:P2 get pasted as values at the bottom of Columns C:E.
pullvalue() works fine if I run it manually.
HERE'S THE ISSUE: Setting up a time-driven trigger causes the values to be pasted in at C1:E1 instead of at the bottom of the columns.
My suspicion is that target_range is breaking down when Clast returns a zero value, but I can't figure out why.
What am I missing? Thanks for your help/feedback!
function pullvalue() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = ss.getSheetByName("Production");
var target_sheet = target.getSheetByName("Production");
var source_range = source_sheet.getRange("N2:P2");
var Cvals = ss.getRange("C1:C").getValues();
var Clast = Cvals.filter(String).length;
var target_range = target_sheet.getRange("C"+(Clast+1)+":E"+(Clast+1))
source_range.copyTo(target_range, {contentsOnly:true});}

Please verify this line:
var Cvals = ss.getRange("C1:C").getValues();
variable ss return currently activespreadsheet only, but when it runs from a time-driven trigger there is no active sheet, so you need to indicate the sheet, you can use getSheetByName() or getSheets() the line should look like this:
var sheet = ss.getSheetByName("Sheet1");
var Cvals = sheet.getRange("C1:C").getValues();
Hope this will help you.
Thanks.

Related

Copy data from sheet to the last row of another workbook

I want to copy columns A2:K (or: all data on sheet apart from row 1) to a completely different workbook and paste in the last row every time (this way I can keep running the script and it won't overwrite any previous pasted data).
Here is my code:
function dataLog() {
var ss = SpreadsheetApp.getActive();
var ss = ss.getSheetByName('Data Sheet');
var target = SpreadsheetApp.openById('xxxxxx');
var ss = target.getSheetByName("Copy Of DataInput");
var vs = ss.getRange('A2:K').getValues();
ss.getRange(lastRow + 1,1,vs.length,vs[0].length).setValues(vs);
}
I'm getting an error on line 6:
TypeError: Cannot read properties of null (reading 'getRange') dataLog # Untitled.gs:6
Based on the error, maybe you're trying to access a sheet that doesn't exist and that's why it is returning null. Make sure the sheet names Data Sheet or Copy Of DataInput are spelled correctly and it does exist in your Spreadsheet. Tested the script and made a couple of updates and it works. You can try the following:
function dataLog() {
var ss = SpreadsheetApp.getActive();
var ss = ss.getSheetByName('Data Sheet');
var vs = ss.getRange('A2:K').getValues();
var target = SpreadsheetApp.openById('XXX');
var ss2 = target.getSheetByName('Copy Of DataInput');
ss2.getRange(ss2.getLastRow() + 1,1,vs.length,vs[0].length).setValues(vs);
}

In Google Sheets Apps Script, how to check if a sheet exists, and if it doesn't add one

I am creating a spreadsheet to sort events based on the date inputted. I have successfully gotten the program to add a new sheet with the contents of the event that I want to copy over, but I have not been able to add to the script to allow for two options. My goal is for it to go something like this:
Option 1: The sheet already exists
. A2:D2 cells will be copied from the template sheet to the sheet that is titled the same date as is in cell A2.
. A2:D2 will be cleared from the template sheet as to leave a blank canvas.
Option 2: The sheet does not exist
. Using the template sheet as a template for the new sheet, all the information will be copied over, with the date in A2 as the name of this new sheet.
. A2:D2 will be cleared from the template sheet as to leave a blank canvas.
I have tried to use a try catch statement, trying to find the sheet, and if that doesn't work, the catch creating the sheet with the new name. I get the error "A sheet with the name "____" already exists." though I am confused as to why, since I am receiving this error, it is not going on with the catch.
I have also tried an if else statement with a similar idea, stating that if getSheetByName didn't work, it would create a sheet, or else it would set a new Active Sheet. This one has the same error.
As for my code, I will show it, but I have to warn it's a bit chunky (for whatever reason, it won't acknowledge the variables within the try catch statement unless I restate them).
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
ss.setActiveSheet(ss.getSheets()[0])
var range = sheet.getRange("A2");
var A2 = range.getValue();
var templateSheet = ss.getActiveSheet();
var value = sheet.getRange("A2").getValue();
var val = Utilities.formatDate(new Date(A2), "GMT+1", "MM/dd/yyyy");
range.setValue(new Date(A2)).setNumberFormat("MM/dd/yyyy");
A2 = SpreadsheetApp.getActiveSheet().getRange('A2').getValue();
try {
ss.setActiveSheet(ss.getSheetByName(A2));
var sheet1 = ss.getSheetByName("GUI");
var sheet2 = ss.getSheetByName(A2);
sheet1.getRange("A2:D2").copyTo(sheet2.getRange(sheet2.getLastRow()+1,1,1,4), {contentsOnly:true});
ss.setActiveSheet(ss.getSheets()[0]);
sheet.getRange("A2:D2").clearContent();
} catch (e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var A2 = range.getValue();
var templateSheet = ss.getActiveSheet();
var val = Utilities.formatDate(new Date(A2), "GMT+1", "MM/dd/yyyy");
ss.insertSheet(val, ss.getSheets().length, {template: templateSheet});
ss.setActiveSheet(ss.getSheets()[0]);
sheet.getRange("A2:D2").clearContent();
}
}
If anyone has any ideas why this isn't working, I'd love to know. Thanks!
The function getSheetByName returns null when it doesn't exist a sheet with that name. If you implement the code that way I think It will be easier.
Code would be something like this:
var sheet2 = ss.getSheetByName(A2);
if( ss.getSheetByName(A2) == null)
{
//if returned null means the sheet doesn't exist, so create it
var val = Utilities.formatDate(new Date(A2), "GMT+1", "MM/dd/yyyy");
ss.insertSheet(val, ss.getSheets().length, {template: templateSheet});
sheet2 = ss.insertSheet(A2);
}
//Rest of the behavior...

Transpose script for google sheets

I have a spreadsheet A which is the source of data and spreadsheet B where this data should be put to. The data needs to be transposed, but there's also a number of conditions like Month, Name and Attribute. So there's 3 matching parameters to meet(Name, Month, Attribute). And this is what I can't get my head around.
This is the code I've come up with, but it's no good since the transpose function doesn't work at all. And how to apply matching to this code is hard for me.
function transpose()
var sourcess = SpreadsheetApp.openById();
var sourcesheet = sourcess.getSheetByName();
var sourcerange = sourcesheet.getRange((row2col()));
var sourcevalues = sourcerange.getValues();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var destsheet = ss.getSheetByName();
var destrange = destsheet.getRange();
destrange.setValues(sourcevalues);
function row2col(row) {
return row[0].map(function(elem) {return [elem];});
Any help is very much appreciated.
Here is a test file of what this should look like

How do I copy a range from one Google Sheet to another when edits are made?

I have a sheet that will update based on new articles in an RSS feed using importfeed() and the URLs are analyzed with importxml(). Problem is the data is always changing and I would like to archive old data from the importfeed() function. I'd just like to move the most updated data from one sheet to another without overwriting anything.
Here is the sample code from: https://stackoverflow.com/users/650206/jeremy:
function myFunction() {
// Get Spreadsheets
var source = SpreadsheetApp.openById("spreadsheetKeySource");
var target = SpreadsheetApp.openById("spreadsheetKeyTarget");
// Set Sheets
var source_sheet = source.getSheetByName("Sheet1");
var target_sheet = target.getSheetByName("Sheet1");
// Get target last row
var last_row = target_sheet.getLastRow();
// Set Ranges
var source_range = source_sheet.getRange("A1:B1");
var target_range = target_sheet.getRange("A"+(last_row+1)+":B"+(last_row+1));
// Fetch values
var values = source_range.getValues();
// Save to spreadsheet
target_range.setValues(values);
}
Problem with the above code is it only selects one row when I need it to select an entire range (e.g. A1:G55) and paste that data below the old data in another sheet.
Any help would be much appreciated!
EDIT
The error I'm getting when I change:
var source_range = source_sheet.getRange("A1:B1");
var target_range = target_sheet.getRange("A"+(last_row+1)+":B"+(last_row+1));
to:
var source_range = source_sheet.getRange("A1:G25");
var target_range = target_sheet.getRange("A"+(last_row+1)+":G"+(last_row+1));
is "Incorrect range height, was 5 but should be 1 (line 21, file "Code")"
which is this piece of code:
target_range.setValues(values);
var source_range = source_sheet.getRange("A1:G25");
var target_range = target_sheet.getRange("A"+(last_row+1)+":G"+(last_row+1));
The lines above attempt to copy 25 rows of data and paste that into one row. I'm surprised that the error message says "was 5 but should be 1". I'd have expected it to say "was 25 but should be 1".
Try this instead:
var source_range = source_sheet.getRange("A1:G25");
var target_range = target_sheet.getRange("A"+(last_row+1)+":G"+(last_row+25));

How to script the addition of a row in one sheet when the source sheet has a row added?

I have a google form which populates a google spreadsheet (source sheet). I located and customized a script to pull certain columns -in their entirety- from the source sheet into a new tab/sheet. Apparently there has to be the same number of rows in both sheets for the script to run properly. If not, it turns back an error. Every time a new form is submitted, a row is added to the source sheet, putting the two sheets out of sync and breaking the script.
I'd like help figuring out what function I need to add to the existing script (or what changes I can make to it) so when a new row appears in the source sheet (because a form has been submitted), a blank row appears in the target sheet.
Do I need to tweak my script or add a new function?
function importFunction(a) {
var ss = SpreadsheetApp.openById("0ApTaY3v27-UqdElwZTBvanNpaC1UckpxaTJRZS1XNWc");
var sourceSheet = ss.getSheets()[0];
var ss2 = SpreadsheetApp.openById("0ApTaY3v27-UqdElwZTBvanNpaC1UckpxaTJRZS1XNWc");
var targetSheet = ss2.getSheets()[1];
var values1 = sourceSheet.setActiveSelection("C:C").getValues();
var values2 = sourceSheet.setActiveSelection("AD:AD").getValues();
var values3 = sourceSheet.setActiveSelection("D:E").getValues();
var values4 = sourceSheet.setActiveSelection("AE:AE").getValues();
var values5 = sourceSheet.setActiveSelection("F:H").getValues();
var values6 = sourceSheet.setActiveSelection("N:U").getValues();
targetSheet.setActiveSelection("A:A").setValues(values1);
targetSheet.setActiveSelection("B:B").setValues(values2);
targetSheet.setActiveSelection("C:D").setValues(values3);
targetSheet.setActiveSelection("E:E").setValues(values4);
targetSheet.setActiveSelection("F:H").setValues(values5);
targetSheet.setActiveSelection("I:P").setValues(values6);
}
Per the suggestion below, I tried to change script to the following, but I get an error - Cannot find method appendRow(). How do I fix that?
function importFunction(a) {
var ss = SpreadsheetApp.openById("0ApTaY3v27-UqdElwZTBvanNpaC1UckpxaTJRZS1XNWc");
var sourceSheet = ss.getSheets()[0];
var ss2 = SpreadsheetApp.openById("0ApTaY3v27-UqdElwZTBvanNpaC1UckpxaTJRZS1XNWc");
var targetSheet = ss2.getSheets()[1];
var targetMax = targetSheet.getMaxRows();
var values1 = sourceSheet.setActiveSelection("C:C").getValues();
var values2 = sourceSheet.setActiveSelection("AD:AD").getValues();
var values3 = sourceSheet.setActiveSelection("D:E").getValues();
var values4 = sourceSheet.setActiveSelection("AE:AE").getValues();
var values5 = sourceSheet.setActiveSelection("F:H").getValues();
var values6 = sourceSheet.setActiveSelection("N:U").getValues();
if(targetMax == values1.length) {
targetSheet.setActiveSelection("A:A").setValues(values1);
targetSheet.setActiveSelection("B:B").setValues(values2);
targetSheet.setActiveSelection("C:D").setValues(values3);
targetSheet.setActiveSelection("E:E").setValues(values4);
targetSheet.setActiveSelection("F:H").setValues(values5);
targetSheet.setActiveSelection("I:P").setValues(values6);
}
else
targetSheet.appendRow();
}
You could simply check the number of available rows in sheet SS2 before writing the values using getMaxRows() and compare it to the length of your data arrays value1.length, then, depending on this comparison add the rows you need using appendRow() eventually in a for next loop.
EDIT : following your EDIT, I tested a bit further and it appears that appendRow() doesn't work as I thought, it appends Rows at the begining of an empty sheet... so I tried this :
if(targetMax < values1.length) {
var RowsToAdd = values1.length-targetMax
for(nn=0;nn<RowsToAdd;++nn){targetSheet.insertRowAfter(targetMax)}
}
Just place it right after var value6=...
sorry for this little error ;-)

Categories

Resources