Google Apps Script error: Cannot read property 'appendRow' of null [duplicate] - forms

This question already has an answer here:
How to fix 'TypeError: Cannot call method "getRange" of null' in Google Apps Script
(1 answer)
Closed 4 months ago.
Google Apps Script keeps giving me the error:
TypeError: Cannot read property 'appendRow' of null
AddRecord # Code.gs:4
The code:
function AddRecord() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var mainSheet = ss.getSheetByName("MAIN");
mainSheet.appendRow(["purple", new Date()]);
}
How to fix it?

The following function will avoid unwanted active spreadsheet, and potential error :
//replace:
var ss = SpreadsheetApp.getActiveSpreadsheet();
//by:
var ss = SpreadsheetApp.openById('xxxxx');
// you will find the ID in the URL of the sheet, between "spreadsheets/d/" and "/edit"
If still have some issue, the problem must come from the sheet name as #Cooper already told you ;)

According to the document:
getSheetByName(name) returns null if there is no sheet with the given name and Sheet if the sheet name is found in the Spreadsheet.
There are 2 possible reasons for having a null value:
The sheet named MAIN does not exists.
There is a typographical error in the sheet name.
You can fix that by adding a sheet named MAIN or renaming your sheet to MAIN to remove any extra characters.
References:
Sheet
getSheetByName(name)

The sheet is probably not called MAIN in the file you are using.
I had a similar problem. If you have not edited the sheet prior try this:
var mainSheet = ss.getSheetByName("Sheet1");
to replace this:
var mainSheet = ss.getSheetByName("MAIN");
This will reference the specific sheet in the file, and it should execute just fine then.

i had the Problem too!
There is how I fixed that:
function AddRecord() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var mainSheet = ss.getSheetName();
var mainSheet1 = ss.getSheetByName(mainSheet);
mainSheet1.appendRow(["purple", new Date()]);
}

Related

How to convert Date and Time with mailmerge google slides from sheets as it is in cell

I have created a table with which I can record our check in times of our employees with the help of a generated Qr code in each line.The data in the table is generated as slides and converted into pdf. For this I use a script that I got to work with your help and it works. Here I would like to thank you especially #tanaike.
My problem is that the date and time are not copied to the slides to be generated as indicated in the cell but completely with Central European time and I added in the script to look in column if its empty to generate the slide. If it's not empty don't do anything. As I said everything is working except this two things.
I must confess I did not try to correct it somehow because I had already shot the script and I made some here despair. It would be really great if you write me the solutions and I can take them over. I will share the spreadsheet with you and the screenshot with ae and time. Thanks for your time and effort to help people like us; we are really trying.
As another approach, when I saw your question, I thought that if your Spreadsheet has the correct date values you expect, and in your script, you are retrieving the values using getValues, getValues is replaced with getDisplayValues(), it might be your expected result.
When I saw your provided sample Spreadsheet, I found your current script, when your script is modified, how about the following modification?
From:
var sheetContents = dataRange.getValues();
To:
sheetContents = dataRange.getDisplayValues();
Note:
When I saw your sample Spreadsheet, it seems that the column of the date has mixed values of both the string value and the date object. So, if you want to use the values as the date object using getValues, please be careful about this.
Reference:
getDisplayValues()
Added:
About your 2nd question of I mean that when a slide has been generated, the script saves the link from the slide in column D if the word YES is in column L. How do I make the script create the slide if there is JA in the column L and there is no link in column D. is a link in column D, the script should not generate a slide again. Thus, the script should only generate a slide if column D is empty and at the same time the word JA is in column L., when I proposed to modify from if (row[2] === "" && row[11] === "JA") { to if (row[3] == "" && ["JA", "YES"].includes(row[11])) {, you say as follows.
If ichanged as you descripted if (row[3] == "" && ["JA", "YES"].includes(row[11])) { i got this error. Syntax error: Unexpected token 'else' Line: 21 File: Code.gs
In this case, I'm worried that you might correctly reflect my proposed script. Because when I tested it, no error occurs. So, just in case, I add the modified script from your provided Spreadsheet as follows. Please test this.
Modified script:
function mailMergeSlidesFromSheets() {
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getDataRange();
sheetContents = dataRange.getDisplayValues(); // Modified
sheetContents.shift();
var updatedContents = [];
var check = 0;
sheetContents.forEach(function (row) {
if (row[3] == "" && ["JA", "YES"].includes(row[11])) { // Modified
check++;
var slides = createSlidesFromRow(row);
var slidesId = slides.getId();
var slidesUrl = `https://docs.google.com/presentation/d/${slidesId}/edit`;
updatedContents.push([slidesUrl]);
slides.saveAndClose();
var pdf = UrlFetchApp.fetch(`https://docs.google.com/feeds/download/presentations/Export?exportFormat=pdf&id=${slidesId}`, { headers: { authorization: "Bearer " + ScriptApp.getOAuthToken() } }).getBlob().setName(slides.getName() + ".pdf");
DriveApp.getFolderById("1tRC505IWtTj8nnPB7XyydvTtCJmOb6Ek").createFile(pdf);
// Or DriveApp.getFolderById("###folderId###").createFile(pdf);
} else {
updatedContents.push([row[3]]);
}
});
if (check == 0) return;
sheet.getRange(2, 4, updatedContents.length).setValues(updatedContents);
}
function todaysDateAndTime() {
const dt = Utilities.formatDate(new Date(),Session.getScriptTimeZone(),"MM:dd:yyyy");
const tm = Utilities.formatDate(new Date(),Session.getScriptTimeZone(),"HH:mm:ss");
Logger.log(dt);
Logger.log(tm);
}

Unable to set a javascript date object to a cell hidden by filter

I have a script which checks certain conditions to send reminders emails or sms to my clients. the only issues I'm finding is that if I try to write a cell that is hidden by a filter, the script executes but the data is not changed in any way.
I'll write a short version of the whole script:
function test(){
var nowTime = new Date();
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var lastrow =sheet.getLastRow();
var lastcol =sheet.getLastColumn();
var fullData =cell.offset(0, 0,lastrow-
cell.getRow()+1,lastcol).getValues();
var cell = sheet.getRange("A2");
var i=0;
while (i<fullData.length){
var reminderType =0;
var row = fullData[i];
if (row[0] == 1) {sendreminder();cell.offset(i, 2).setValue(new Date());}
}
}
if for example the first column has hidden all the rows with 1 the script executes and sends all the reminders but ignore the setvalue(), if the rows are visible it works perfectly.
One solution can de to remove the filter but would be very annoying since we use the filter a lot and the script is triggered by time every 10 minutes so I would be working on the sheet and suddenly the filter get removed to run the script.
I have tried with cell.offset, getrange etc.. without any success ... Ideas?
EDIT: The problem seems to be only if I try to write a date if (row[0] == 1) {cell.offset(i, 1).setValue(new Date());}
For instance I'm writing another information (a number) in a different column and that cell gets updated.
The rest remain the same
here is a test sheet I created:
https://docs.google.com/spreadsheets/d/1-FNDGmvCc8nRFTG65Sj9L2RhGn8R3DtwR3llwBG5-FA/edit#gid=0
For now I added this code to save the state of the filter and reestablish it at the end. It's not really elegant and still add a lot of chances of something being messed up or the script failing but it's the less invasive solution I came out with. Does someone has a better one?
// at the beginning
if (sheet1.getFilter()){
var filterRange= sheet1.getFilter().getRange();
var filterSetting = [];
var i=0;
while (i<filterRange.getNumColumns()-1) {filterSetting[i]= sheet1.getFilter().getColumnFilterCriteria(i+1);sheet1.getFilter().removeColumnFilterCriteria(i+1);i++; }
}
// At the end
if (sheet1.getFilter()){
var i=0;
while (i<filterRange.getNumColumns()-1) {if (filterSetting[i]) sheet1.getFilter().setColumnFilterCriteria(i+1, filterSetting[i]);i++; }
}
Given the fact the problem is not writing in the hidden row as it was pointed out, the solution is to use the formatdate to format the value before writing it in the cell.
Not ideal either since regional formattings might prevent the script from working on different accounts but sure better solution than disabling the filters.
here is the code i needed to add:
var nowTime = new Date();
var timeZone = Session.getScriptTimeZone();
var nowTimeFormatted = Utilities.formatDate(nowTime, timeZone, 'MM/dd/yyyy HH:mm:ss');
any idea on how to improve this script or to solve the original problem without workarounds is appreciated :)

Name email attachment in Google Apps Script

I have the following G.A.S script to email a google sheet as a pdf attachment.
var spreadsheet = SpreadsheetApp.getActive();
var subject = spreadsheet.getRange("U1:U1").getValues();
var emailTo = spreadsheet.getRange("V1:V1").getValues();
var message = spreadsheet.getRange("W1:W1").getValues();
var pdf = DriveApp.getFileById(spreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:subject,content:pdf, mimeType:'application/pdf'};
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
The above code works well except that the file attached to the email message has a bizarre name like "[Ljava.lang.Object_#4e63998c" with no ".pdf" extension!
I am looking for a way to set a name for the pdf file before being attached to the email. The file name should equal the "subject" variable.
Thanks in advance.
Omid
Values retrieved by getValues() is 2 dimensional array. I think that the filename becomes such string because the array is used as the filename. Please retrieve the element from the array and try again. So could you please modify as follows?
From :
var attach = {fileName:subject,content:pdf, mimeType:'application/pdf'};
To :
var attach = {fileName:subject[0][0],content:pdf, mimeType:'application/pdf'};
You can also use the following modification. In this case, getValue() can retrieve the value as a string from the cell "U1".
From :
var subject = spreadsheet.getRange("U1:U1").getValues();
To :
var subject = spreadsheet.getRange("U1:U1").getValue();
Reference :
getValue()
getValues()
If this was not what you want, please tell me. I would like to think of other solutions.
I'm a bit late, but another way to solve this problem might be:
var spreadsheet = SpreadsheetApp.getActive();
var subject = spreadsheet.getRange("U1:U1").getValues();
var emailTo = spreadsheet.getRange("V1:V1").getValues();
var message = spreadsheet.getRange("W1:W1").getValues();
var pdf = DriveApp.getFileById(spreadsheet.getId())
.getAs('application/pdf')
.getBlob()
.setName(subject);
MailApp.sendEmail(emailTo, subject, message, {attachments:[pdf]});
The Blob class has a setName method https://developers.google.com/apps-script/reference/base/blob#setName(String), that can be chained into a Blob object (which is the result of getBlob())
After that you just need to add the Blob object inside attachments array of function MailApp.sendEmail

google script column change email notification

This is my first attempt at writing any kind of script, and also posting a question.
I have created a google sheet, and I would like to send an e-mail notification every time a row is added in this spreadsheet (or to keep things simple, every time a new cell is populated in column A).
I've been searching these forums for a couple of hours, and put together the following script, and tried installing both "onedit" & "onchange" triggers in google scripts but nothing working.
The following links have been helpful, but still not able to get the result I want. No notification is being triggered at all automatically upon the relevant edits.
how to attach onChange cell value event/script to google sheet
email notification if cell is changed
//Open function
function sendNotification() {
//Get spreadsheet & sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Define notification details
var recipients = "myname#email.com";
var subject = "New lead";
var body = 'A new lead has been added to Simba. For message: ' + message + '';
//Specify several sheet variables
var cell = ss.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
var message = '';
//Specify if statement
if(cell.indexOf('A')!=-1){
message = sheet.getRange('B'+ sheet.getActiveCell().getRowIndex()).getValue()
}
//Send the Email
MailApp.sendEmail(recipients, subject, body);
//Close function
};
var body = 'A new lead has been added to Simba. For message: ' + message + '';
At this line, "message" is undefined. It occurs an error. By this error, mail cannot be sent. Because the definition of "message" is below from this line. So please change this line to below
message = sheet.getRange('B'+ sheet.getActiveCell().getRowIndex()).getValue()
And please install a trigger for this function. The method of installing trigger is shown at your reference URL.

How to copy paste a google spreadsheet table into gmail using google script?

I have a google spreadsheet with a pivot table, which i want to be emailed automatically based on certain criteria using my gmail. I am quite happy with the email script and the cinditions however I cannot find anywhere a script that can effectively replicate a "copy - paste" of the table into the email.
I would appreciate any help you could offer with this.
Thanks
Agi
I managed to get it to work using advice from this community. Thank you!
I am trying to get it to display values horizontally i.e. each line a new customer record. However, i get something different. I am attaching a file with what I get and the code. I would appreciate any advice. I am so sure that the solution is just there but after many hours I cannot get it :( I am showing the code below and I am attaching a photo with the current and desired outcome.
Many thanks
Agi
function testMail(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var responses = ss.getSheetByName("Monitoreo de Pedidos");
// var lastRow = responses.getLastRow();
// var values = responses.getRange("A2"+(lastRow)+":R2"+(lastRow)).getValues();
var values = responses.getRange("A3:R12").getValues();
var headers = responses.getRange("A2:R2").getValues(); //The headers. A1 TO R1 does not contain relevant data
var message = composeMessage (headers,values);
var messageHTML = composeHtmlMsg(headers,values);
Logger.log(messageHTML);
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),'test html', message,{'htmlBody':messageHTML});
}
function composeMessage(headers,values){
var message = 'Here are the data you submitted :\n'
for (var j=0;j<5;++j){ //NUMBER OF ROWS
for(var c=0;c<values[0].length;++c){ //NUMBER OF COLUMNS, in the future this will be dynamic
message+='\n'+headers[0][c]+' : '+values[j][c]
}
}
return message;
}
function composeHtmlMsg(headers,values){
var message = 'Here are the data you submitted :<br><br><table style="background- color:yellow;border-collapse:collapse;" border = 1 cellpadding = 5><th>Title</th> <th>Customer Info</th><tr>'
for (var j=0;j<5;++j){
for(var c=0;c<values[0].length;++c){
message+='<tr><td>'+headers[0][c]+'</td><td>'+values[j][c]+'</td></tr>'
}
}
return message+'</table>';
![Desired outcome][1]}
You need to write the email body as html and insert the in there. More work if you want to mimic formatting. Try if and write back if you get stuck.