Exception error relating to method signature - javascript

I'm super new to JavaScript, am an editor by trade, but need to create a Google Calendar view from a Google Sheet for story assignments for my writers. I've gone through a tutorial on how to make this work and have fixed a number of problems with the code. I'm stuck on what I think is the final issue. It relates to the method signature. The error message is:
Exception: The parameters (String,String,String,String,String,String)
don't match the method signature for
CalendarApp.Calendar.createAllDayEvent. (line 20, file "Code")
Here's the code. Can anyone help???
function myFunction() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange ("N8").getValue();
var eventCal = CalendarApp.getCalendarById(calendarId);
var signups = spreadsheet.getRange("G8:L124").getValues();
for (x=6; x<signups.length; x++) {
var shift = signups[x];
var author = shift[0];
var newsletterdate = shift[1];
var livedate = shift[2];
var duetoproductiondate = shift[3];
var duetocopyeditdate = shift[4];
var duetocontenteditdate = shift[5];
eventCal.createAllDayEvent(author, newsletterdate, livedate, duetoproductiondate, duetocopyeditdate, duetocontenteditdate);
}
}

It seems there is no signature for this method that has 6 parameters. The maximum I noted was 5 on this documentation: https://developers.google.com/apps-script/reference/calendar/calendar-app
You must review the arguments you are passing when calling the function and choose the most suitable method signature.

Related

Saving a floating value to a google sheet using a script

I want to use google script to make a request and save some data on google sheet.
The problem is when I try to pass some non integer values as parameters in the request.
I think it's something to do with the fact that sheets uses comma for separating decimal from integer while my program sends the numbers separated by a dot.
This is where I am now:
const doPost = (event) => {
console.log(`doPost`, JSON.stringify(event));
const { parameter } = event;
const { temp, peso } = parameter;
var date = new Date();
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow([date, parseFloat(temp), peso]);
}
When I make a post request with parameters: { temp:1.234, peso:1.234 } the result on google sheet is a big mess.
Does someone have any idea how to fix this?
edit:
function Test(){
var sheet = SpreadsheetApp.getActiveSheet();
var d = 1.23456;
var date = new Date();
sheet.appendRow([date, d]);
}
This works fine... don't know if it can help you debug.
Post Data to Sheet
I don't actually do this all that much so I am by no means an expert at it
function doPost(e) {
Logger.log(e.postData.contents);
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet1");
let data = JSON.parse(e.postData.contents);
sh.appendRow([data.first,data.second])
}
function sendData(obj) {
const url = ScriptApp.getService().getUrl();
const params={"payload":JSON.stringify(obj),"muteHttpExceptions":true,"method":"post","headers": {"Authorization": "Bearer " + ScriptApp.getOAuthToken()}};
UrlFetchApp.fetch(url,params);
}
function saveMyData() {
sendData({first:"1.234",second:"1.432"});
}
This worked for me.
Finally figured it out!
The problem was in the setting of the google sheet file.
I'm from Italy so it enters as defult the Italian format. For some reasons this mess up all the new entries. The solution is very simple: change the format to the english one and the problem should solve itself!

Converting a Google doc to PDF, then moving to another folder

I am working on script that will fill a Google doc template with cell values from a spreadsheet. A copy of the edited doc is created and converted into a PDF. I would then like for both the doc and the pdf to be moved to the specified folder. I am stuck on getting the pdf moved over to the folder. I created a function to move the docs, and it seems to work fine with the Google doc copy, but an error is being returned when the function runs for the pdf. The error seems to be coming from the moveFile function. I have also tried moving moveFile pdf call to fillLetter, but still get the same error. This is my first attempt at coding with Google script, so any advice would be greatly appreciated. Thank you!
function fillLetter() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];//Form Responses tab
var templateId = '1d-CKr_Xi27FrWsH6eWdUCWKyzrLjy3ivTjLkk_WyJ4s';//Test doc
//get candidates row number from user input
var ui = SpreadsheetApp.getUi();
var rowNum = ui.prompt("Please enter candidate row number");
//activates first column in selected row
var col = sheet.getRange("A"+ rowNum.getResponseText());
sheet.setActiveRange(col);
var candName = sheet.getActiveCell().getValue();
col = sheet.getRange("B"+ rowNum.getResponseText());
sheet.setActiveRange(col);
var location = sheet.getActiveCell().getValue();
//creates copy of template doc and renames
var lastName = candName.split(" ");
var filename = candName.substring(0,1) + lastName[lastName.length - 1] + ' - Offer Letter';
var newOffer = DriveApp.getFileById(templateId).makeCopy();
var offerId = newOffer.getId();
DriveApp.getFileById(offerId).setName(filename);
//gets body of template doc and replaces text
var doc = DocumentApp.openById(offerId);
var body = doc.getBody();
var todaysDate = Utilities.formatDate(new Date(), 'PST', 'MMMM dd, yyyy');
body.replaceText('{{Todays date}}', todaysDate);
body.replaceText('{{Candidate name}}', candName);
body.replaceText('{{Location}}', location);
doc.saveAndClose();
//Creates folder and moves newly created files
var folderName = DriveApp.createFolder(candName).getId();
convertPDF(offerId, folderName); // Line 52
moveFile(offerId, folderName);
}
function convertPDF(fileToCopy, folder) {
var docFolder = DriveApp.getFolderById(folder);
var copy = DriveApp.getFileById(fileToCopy);
//Add the PDF extension
var docblob = copy.getAs('application/pdf');
docblob.setName(copy.getName() + ".pdf");
var pdfFile = DriveApp.createFile(docblob);
var fileId = pdfFile.getId();
Logger.log("Offer PDF id - " + fileId);//for debug
moveFile(fileId, docFolder); // Line 66
}
function moveFile(fileId, folderId) {
var file = DriveApp.getFileById(fileId);
DriveApp.getFolderById(folderId).addFile(file); // Line 72: wh/ error is most likely occurring
}
Below is the error message from the Logger:
Error
Exception: Unexpected error while getting the method or property getFolderById on object DriveApp.
moveFile # testCode.gs:72
convertPDF # testCode.gs:66
fillLetter # testCode.gs:52
In the current stage, you can use moveTo method for moving the file on Google Drive. This has added on July 27, 2020. Ref In your script, when moveFile is modified, it becomes as follows.
Modified script:
function moveFile(fileId, folderId) {
var file = DriveApp.getFileById(fileId);
file.moveTo(DriveApp.getFolderById(folderId));
}
Reference:
moveTo(destination)
The methods of addFile, addFolder, removeFile and removeFolder have already been deprecated. Ref

How to write (SetValues) to a Google Sheet using a filtered forEach loop?

I've been trying for hours to make the following Google Apps Script work. What it needs to do, is send emails (from an html-template) to anyone that:
has a complete Event Schedule (which is completed if they have been
assigned to at least 4 events, which is counted in column Q);
has NOT been sent an email earlier (which is kept track of in column
R);
The script keeps track of errors in column S, i.e. if there's no email address provided.
It appears it only works:
if I comment out
data = data.filter(function(r){ return r[17] == true & r[16] > 3});
or if I comment out
ws.getRange("S3:S" + ws.getLastRow()).setValues(errors);
ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces);
How can I get this script to work properly?
A copy of the Google Sheet I'm referring to is this one:
https://docs.google.com/spreadsheets/d/1sbOlvLVVfiQMWxNZmtCLuizci2cQB9Kfd8tYz64gjP0/edit?usp=sharing
This is my code so far:
function SendEmail(){
var voornaam = 3;
var achternaam = 4;
var email = 5;
var event1 = 9;
var event2 = 10;
var event3 = 11;
var event4 = 12;
var event5 = 13;
var event6 = 14;
var event7 = 15;
var emailTemp = HtmlService.createTemplateFromFile("email");
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Events Day 1");
var datum = ws.getRange(1,3).getValue();
var spreker = ws.getRange(1,6).getValue();
var data = ws.getRange("A3:R" + ws.getLastRow()).getValues();
data = data.filter(function(r){ return r[17] == false && r[16] > 3}); //Either this needs to be commented out...
let errors = [];
let mailSucces = [];
data.forEach(function(row){
try{
emailTemp.voornaam = row[voornaam];
emailTemp.email = row[email];
emailTemp.datum = datum;
emailTemp.spreker = spreker;
emailTemp.event1 = row[event1];
emailTemp.event2 = row[event2];
emailTemp.event3 = row[event3];
emailTemp.event4 = row[event4];
emailTemp.event5 = row[event5];
emailTemp.event6 = row[event6];
emailTemp.event7 = row[event7];
var htmlMessage = emailTemp.evaluate().getContent();
GmailApp.sendEmail(
row[email],
"Here you go! Your personal schedule for the event of " + datum,
"Your emailprogramm doesn't support html.",
{
name: "Event Organisation Team", htmlBody: htmlMessage, replyTo: "info#fakeemail.com"
});
errors.push([""]);
mailSucces.push(["TRUE"]);
}
catch(err){
errors.push(["Error: no message sent."]);
mailSucces.push(["False"]);
}
}); //close forEach
ws.getRange("S3:S" + ws.getLastRow()).setValues(errors); //or this and the next line need to be commented out.
ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces);
}
Edit I have been trying and thinking en trying... but still haven't found out how to make it work. But I also got understanding of why it's not working; I just don't know how to get it fixed.
Let me elaborate on the problem a bit more:
The problem is, that within the forEach loop the range is a filtered variant of the data, pulled from the spreadsheet with getValues. Therefore, writing data back with ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces); results in mismatched checkmarks in te spreadsheet.
So, somehow I need to put the range of the previous used filter data = data.filter(function(r){ return r[17] == false & r[16] > 3}); in a variable...? I guess?
Furthermore, I don't think it's wise to use setValue within the loop, because (from what I understand from my searching on the topic) this results in a slow script, because every loop the script makes an API call to write in the spreadsheet. Hence the errors.push and mailSucces.push, and my attempt to do a setValue at the end, after the loop is finished.
Can someone help me to finish this problem?
The problem is different size of the range you write to and data you are writing in.
Try replacing:
ws.getRange("S3:S" + ws.getLastRow()).setValues(errors);
ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces);
With:
ws.getRange(3, 19, errors.length, 1).setValues(errors);
ws.getRange(3, 18, mailSucces.length, 1).setValues(mailSucces);
You should use this variation of getRange
https://developers.google.com/apps-script/reference/spreadsheet/sheet#getrangerow,-column,-numrows,-numcolumns
Your data has non-fixed number of rows and fixed number of columns (1). In general case your data will be matrix of X rows and Y columns. For that purpose you can make it completely dynamic:
sheet.getRange(startRow, startColumn, data.length, data[0].length)
Just make sure data.length is > 0 before you do this, otherwise data[0].length will break.
Edit:
I started writing a comment but it got too long. There are couple of things that may go wrong with sending emails. First thing I noticed is that you use & in filter, but in AppsScript/JavaScript/C-like-languages, you should use && for logical AND. Now the email: you only detect the code break with the catch block. At this point you don't know why the code breaks it could be anything. With GmailApp I recommend you to use createDraft while developing, then when all ok replace it with sendEmail for the final version, both functions have the exact same parameters, thank you Google devs ;-).
To find out the exact problem you should get the error message on break and display it. err.stack should tell you pretty much everything:
catch(err){
Logger.log(err.stack); // Added
errors.push(["Error: no message sent."]);
mailSucces.push(["False"]);
}
Run the sendEmail function from the code editor and you should see the Log for each catch(err) pass.

How to get formatted array on Google AppScript?

I have a code that takes each cell from a gsheet and changes the format using appscript but this does not correct it back on the google sheet. I used this because even though the format was correct on the gsheet, when getvalue() is used, the number loses its format.
var Qty1 = ss.getRange(i, 15).getValue();
var Qty1Format = Qty1.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
//Output has a thousands separator and two decimal places.
This takes a lot of time to run and as a result I am looking for alternative ways to correct the format.
I was thinking of getting all the values of the column as an array and I am looking to convert the array in the format needed and paste this back into the sheet.
I've had attempts at coding this but would be grateful for any help on how to change format for the array or alternative ways of achieving the outcome.
Sample code attempt:
function copypastetest() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").activate();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var rng = ss.getRange("C2:"+"c"+lr).getValues();
var frng = rng.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
var copy = ss.getRange("C2:"+"c"+lr).setValues(frng)
}
Further Edit:
#Cooper's answer is spot on. However I'm might not have asked the right question to solve my problem. I am ultimately looking to take values from the google sheet and replace placeholders into a google doc.
See below (although the number is formatted it still appears to be unformatted in the formula bar - and I should have noticed this before but i did not)
So how I can format the array (or get an array that is formatted in the first place to come on my Logger.log on the appscript?
Here is the rest of the script for you to understand what I am looking to achieve,
function generatetest() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").activate();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var rng = ss.getRange("A1:"+"F"+lr).getValues();
for (var i =2;i<=lr;i++){
if(ss.getRange(i, 1).getValue()){
var client = rng[i-1][1];
var email = rng[i-1][2];
var documentId = DriveApp.getFileById('1j36HPQkTPc0R4GCtA0XKcmeHUVPsgBKoyNIl93HFhp0').makeCopy().getId();
DriveApp.getFileById(documentId).setName(client);
var body = DocumentApp.openById(documentId).getBody();
body.replaceText('{Name}', client).replaceText('{Email}', email)
}
else {}
}
}
If I understood your issue correctly, I believe it can be solved by using the getDisplayValues() method of class Range. This method copies the format of the cell and returns the formatted string.
var rng = ss.getRange("C2:"+"c"+lr).getDisplayValues()
References:
Range.getDisplayValues()
I tried this and it seems to work, if I understand your issue.
function runOne() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet22');
const rg=sh.getRange(1,1,sh.getLastRow());
const vA=rg.getValues();
vA.forEach(function(r,i){
sh.getRange(i+1,2).setValue(r[0]).setNumberFormat('#,##0.00');
})
}
Here's my start data:
1000000.33
2000000.34
3000000.35
4000000.36
5000000.37
6000000.38
7000000.39
8000000.4
9000000.41
10000000.42
11000000.43
12000000.44
13000000.45
14000000.46
15000000.47
16000000.48
17000000.49
18000000.5
And here's my ending data:
1000000.33,1000000.33
2000000.34,2000000.34
3000000.35,3000000.35
4000000.36,4000000.36
5000000.37,5000000.37
6000000.38,6000000.38
7000000.39,7000000.39
8000000.4,8000000.4
9000000.41,9000000.41
10000000.42,10000000.42
11000000.43,11000000.43
12000000.44,12000000.44
13000000.45,13000000.45
14000000.46,14000000.46
15000000.47,15000000.47
16000000.48,16000000.48
17000000.49,17000000.49
18000000.5,18000000.5
Here's what the sheet looks like:
I use this script a lot for viewing and editing number formats on a spreadsheet and I find it helpful to solve formatting issues. There's probably an easier way but I haven't found it yet.
function getandSetActiveRangeFormats() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getActiveRange();
var fA=rg.getNumberFormats();
var html='<style>th,td{border:1px solid black;}</style><table><tr><th>Item</th><th>A1 Notation</th><th>Number Format</th><th>Enter Format</th><th>Set Format</th></tr>';
var item=1;
var row=rg.getRow();
var col=rg.getColumn();
fA.forEach(function(r,i){
r.forEach(function(c,j){
var txt=Utilities.formatString('<input type="text" id="RC-%s-%s" />',row+i,col+j);
var btn=Utilities.formatString('<input type="button" value="Set Form" onClick="setFormat(%s,%s);" />',row+i,col+j);
html+=Utilities.formatString('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>',item++,sh.getRange(row + i,col + j).getA1Notation(),fA[i][j],txt,btn);
});
});
html+='</table><input type="button" value="Exit" onClick="google.script.host.close();" />';
html+='<script>function setFormat(row,col){var f=document.getElementById("RC-"+row+"-"+col).value;google.script.run.setFormat(row,col,f);}</script>';
var ui=HtmlService.createHtmlOutput(Utilities.formatString(html));
SpreadsheetApp.getUi().showModelessDialog(ui, "Display and Set Active Range Formats")
}
function setFormat(row,col,format) {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
sh.getRange(row,col).setNumberFormat(format);
}

Timing Tool for work

I have built a tool for timing indirect workers, it consists of a start and stop button which both place a time stamp into the google sheet and then calculates the difference to record a time. It works great however when I share it with some people it does not allow them to use it saying that they do no have access to run the script. If they open script editor they can manually run it however that will no fly because I will be sending this out to approximately 50 people.
Here is the code and start and stop are two different scripts. Please let me know if I am missing something and I appreciate the help. Thanks
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var start = new Date();
function StartScript() {
var last = ss.getLastRow();
ss.getRange(last+1,1).setValue(last+1)
var source = ss.getRange(last+1,1).getValue();
source = Number(source);
if (source <= 16) {
ss.getRange(last+1,2).setValue(start);
}
else {
ss.getRange(last+1,2).setValue("Stop Timing");
}
}
function stop() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var date = new Date();
var last1 = ss.getLastRow();
ss.getRange(last1, 3).setValue(date);
var lastrow = ss.getLastRow()
ss.getRange("D" + (lastrow)).setFormula("=C" + (lastrow) + "-B" + (lastrow));
}

Categories