Getting "Incorrect range height" in google app script - javascript

Am trying to get the url's printed in a column and am getting this error:
"Incorrect range height,was 1 but should be 132 (line 37, file "Code")"
and when am getting the url in debugger, am getting it in this form:
"http\://myrul.com\:8080/abcde/" and i have more than 130+ urls which am getting from API. now my second concern is i wanna somehow split and get the url in this form:
"http://myrul.com:8080/abcde/"
(remove all the backslash's from all the 130 urls)
hope u guys can help
Thanks
here is the function that i have written:
`
function fetchFromApi() {
var url = '<<my api from where am fetching the data>>';
var urlResponse = UrlFetchApp.fetch(url);
var urlResult = JSON.parse(urlResponse);
var key = Object.keys(urlResult);
var tempArr = [];
for (var x in urlResult) {
var value = urlResult[x];
tempArr.push(value)
}
inputSheet.getRange(2,6,tempArr.length,1).setValues([tempArr]);
Logger.log(tempArr);
}
`

For the second part please use the following regex
value.replace(/\\/g, '');
Please insert it inside your loop.
Please see how it works here

Related

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.

receiving error on MailApp.sendEmail when email list is in array

I am receiving an error on apps script:- "Exception: The parameters (number[],String,String,(class)) don't match the method signature for MailApp.sendEmail."
Its working fine when i use simple text format for example "abc#google.com,xyz#google.com"
but when I use a list of email in array called email_list_S1 it gives me error.
Mentioned below is my code:-
var ss = SpreadsheetApp.openById('19zdQSZFX7gkkjhkhkhhklhklhlxEw8dhtIkzv7mUOI');
var sh = ss.getSheetByName("Sheet2");
var lastR = sh.getLastRow()
var data2 = sh.getRange("A4:QC"+lastR).getValues();
var email_list_S1 = data2.filter(function(item){return item[15]=="ON" && item[9]=="S1" && item[436] =="";}).map(elem => elem[0]);
MailApp.sendEmail(email_list_S1,"Missing Login Detail S1 Shift Reminder!!"+" ["+today+"]", "",
{htmlBody: "Hello All, <br><br>"+"You are receiving this mail because you have missed to log-in."
+ "<br><br>"+'Please click the link attached '
+ 'here'+" and mark your attendance."+'<br><br>Thank You'});
Issues / Explanation:
email_list_S1 is an array with emails, but the first argument of
sendEmail accepts a string of email/s.
You need to convert email_list_S1 to string and you can use Array.prototype.toString() to accomplish that.
Solution:
Replace:
MailApp.sendEmail(email_list_S1,..)
with
MailApp.sendEmail(email_list_S1.toString(),..)

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);
}

Could not Parse text in Utilities.parseCsv using google app script

I am beginner to google apps script. I am trying to import CSV file from Zipped attachement from gmail. I am getting error Could not Parse tex at Line of code
var csvData = Utilities.parseCsv(unZipBlob.getDataAsString(), "\t");"
I have tried all combinations Like UTF -8 and other unicode to solve the issue but unable resolve it. even i tried the answer mentioned at Link
Utilities.parseCsv() 'Could not parse text' (Google Apps Script)
Below I have attached my code . can some one please help me to resolve?
Please let me know if you need further details to help
function importCSVFromGmailMC1() {
var threads = GmailApp.search('GOC "CM pacing Report" - 1*');
var message = threads[0].getMessages()[0];
var attachment = message.getAttachments()[0].copyBlob();
attachment.setContentType('application/zip');
var unZipBlob = Utilities.unzip(attachment)[0];
unZipBlob.setContentType('text/csv');
var sheet = SpreadsheetApp.openById('mysheetid').getShee tByName('CM pacing_daily');
if (unZipBlob.getContentType() === "text/csv") {
var csvData = Utilities.parseCsv(unZipBlob.getDataAsString(),"\t");
sheet.clearContents().clearFormats();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
}

JSON.parse() - SyntaxError: Expected end of stream at char 2

In my project, I have written google spreadsheet script to decipher encrypted cell content using sjcl. But I failed.
function encryptCell() {
var masterKey = Browser.inputBox('Enter masterKey');
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var cell = spreadSheet.getActiveSheet().getActiveCell();
var input = cell.getValue();
var encJson = sjcl.encrypt(masterKey, input);
/*
{"iv":"4psT+LTIh/aT7WWv7Ye7qw==","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"PjSOiia9TCM=","ct":"3hwmBbwQ7y/fsjk="}
*/
var encStr = JSON.stringify(encJson);
/*
"{\"iv\":\"4psT+LTIh/aT7WWv7Ye7qw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"PjSOiia9TCM=\",\"ct\":\"3hwmBbwQ7y/fsjk=\"}"
*/
var encB64 = Utilities.base64Encode(encStr);
Browser.msgBox(encB64);
var rencStr = Utilities.base64Decode(encB64);
/*
34,123,92,34,105,118,92,34,58,92,34,52,112,115,84,43,76,84,73,104,47,97,84,55,87,87,118,55,89,101,55,113,119,61,61,92,34,44,92,34,118,92,34,58,49,44,92,34,105,116,101,114,92,34,58,49,48,48,48,44,92,34,107,115,92,34,58,49,50,56,44,92,34,116,115,92,34,58,54,52,44,92,34,109,111,100,101,92,34,58,92,34,99,99,109,92,34,44,92,34,97,100,97,116,97,92,34,58,92,34,92,34,44,92,34,99,105,112,104,101,114,92,34,58,92,34,97,101,115,92,34,44,92,34,115,97,108,116,92,34,58,92,34,80,106,83,79,105,105,97,57,84,67,77,61,92,34,44,92,34,99,116,92,34,58,92,34,51,104,119,109,66,98,119,81,55,121,47,102,115,106,107,61,92,34,125,34
*/
var rencJson = JSON.parse(rencStr);
var rinput = sjcl.decrypt(masterKey, rencJson);
Browser.msgBox(rinput);
}
Encryption is fine, which I can decrypt using this tool. Something is wrong with JSON.parse().
var rencStr = Utilities.base64Decode(encB64);
/*
34,123,92,34,105,118,92,34,58,92,34,52,112,115,84,43,76,84,73,104,47,97,84,55,87,87,118,55,89,101,55,113,119,61,61,92,34,44,92,34,118,92,34,58,49,44,92,34,105,116,101,114,92,34,58,49,48,48,48,44,92,34,107,115,92,34,58,49,50,56,44,92,34,116,115,92,34,58,54,52,44,92,34,109,111,100,101,92,34,58,92,34,99,99,109,92,34,44,92,34,97,100,97,116,97,92,34,58,92,34,92,34,44,92,34,99,105,112,104,101,114,92,34,58,92,34,97,101,115,92,34,44,92,34,115,97,108,116,92,34,58,92,34,80,106,83,79,105,105,97,57,84,67,77,61,92,34,44,92,34,99,116,92,34,58,92,34,51,104,119,109,66,98,119,81,55,121,47,102,115,106,107,61,92,34,125,34
*/
If you take a look, that's not JSON. did you possibly miss the JSON.stringify(); step for that one?
You can't parse it if it's not JSON.
When decoding with Utilities.base64Decode() you have one extra step to follow if you want to get a string back. If you look at the Google Scripts reference it says that base64Decode returns a byte array and not a string. Looking at your code, your decode returns
var rencStr = Utilities.base64Decode(encB64);
/*34,123,92,34,105,118,92,34,58,92,34,52,112,115,84,43,76,84,73,104,47,97,84...*/
which is a numeric representation of your string in Unicode. If you run your return value through Utilities.newBlob(rencStr).getDataAsString() as the reference recommends, you will have your JSON that you can parse back into your encrypted string.

Categories