I have a the following snippet of code
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var driverArray = sheet.getRange("H2:H33").getValues().flat().filter(r=>r!="");
var ssname = ss.getName();
var length = ssname.length;
var shName = sheet.getName();
var date = ssname.substring(0,length-15);
var scheduleDate = ss.getSheets()[7].getRange("G27").getValue(); //this contains a formula, but it evaluates to a date coinciding with the title of a sheet
const body = "Hello, <br><br>Attached is the pay stub for the week ending "+ date+"."+"<br><br> Thank you, <br> Elizabeth";
var arrayLength = driverArray.length;
var scheduleSheet = SpreadsheetApp.openById("SpreadsheetURL");
var scheduleSS = scheduleSheet.getId();
var nextSchedule = scheduleSheet.getSheetByName(scheduleDate);
var scheduleID = nextSchedule.getSheetId(); // I believe the error is coming here
I am trying to get the ID of a sheet on a different spreadsheet. I believe that I am navigating to that sheet correctly, but I get the error "cannot read property of 'getSheetId' of null". Does this mean that it did not find a sheet with the name?
G27 contains the formula
=(Leftb(Summary!$A$2,2)&"-"&Midb(Summary!$A$2,3,2)&"-"&rightb(Summary!$A$2,2))+7
but it evaluates to a date. And the format of the date matches correctly with the title of the sheet.
Instead of
var scheduleDate = ss.getSheets()[7].getRange("G27").getValue()
use
var scheduleDate = ss.getSheets()[7].getRange("G27").getDisplayValue()
The above because getValue() returns a Date object for cells holding a date value and usually the Date object is parsed as string in a long format rather than the usual date formats.
Related
Main Goals
Retrieve string from google sheets tab.
Edit string to remove "s and ,s.
re-format the string for upload into google sheets.
I have accomplished the first 2 tasks of my goal. Although I will explain in full the situation.
I am querying google sheets to return a row which contains a specified string so it can be added to a new sheet. currently I have been able to retrieve the row fine. the data comes back looking like this.
"12/24/2020, 3:40:33 PM","SanguineDepths+5","The Key Is
Timed","1000","Aegwynn","#name #name #name #[Manager]
name-name","name#0000 name#0000 name#0000
name#0000","Advertiser-Realm","testing-testing","Ticket","33p2bdlfto9g45","Customer-Realm","Horde",""
I have then used the following code to remove all of the "s and ,s.
const result = `"12/24/2020, 3:40:33 PM","SanguineDepths+5","The Key Is Timed","1000","Aegwynn","#name #name #name #[Manager] name-name ","name#0000 name#0000 name#0000 name#0000","Advertiser-Realm","testing-testing","Ticket","33p2bdlfto9g45","Customer-Realm","Horde",""`
var result1 = result.replace (/,/g, " ");
var result2 = result1.replace (/"/g, "");
Now my string is looking like this.
12/24/2020 3:40:33 PM SanguineDepths+5 Timed 1000 Aegwynn #name #name
#name #[Manager] name-name name#0000 name#0000 name#0000
name#0000 Advertiser-Realm testing-testing Ticket 33p2bdlfto9g45
Customer-Realm Horde
When uploading the above string which removes the characters I do not require, google sheets actually inputs all of the data in one cell instead of multiple, is there a way I can fix this? I did try to use arguments although I would like the 4 discord name#0000 in one cell and the 4 discord #name also in their own cell, like this.
Desired format for data to be entered in
So my main goal is to format the result in such a way I can write them to google sheets in their own cells.
Edit #1
I have used the .split(',') function but google API returns the following error:
"The API returned an error: Error: Invalid values[1][0]: list_value"
You could try to target the comma's in between to split the data at that point to an array and then take care of removing charcters.
Try:
result.split(',')
That should give you an Array.
And you could resuse your code to take out the characters you don't need with an array helper: something like:
result.split(',').map((part) => {
return part.replace (/"/g, "")
})
I was hoping for an easier solution, but I ended up using this method with multiple arguments for the string I got back from the sheet.
var result1 = result.replace (/,/g, " ");
var result2 = result1.replace (/"/g, "");
const argsRUN = result2.split(' ');
const command = argsRUN.shift().toLowerCase();
var date1 = (argsRUN[0]);
var time1 = (argsRUN[1]);
var ampm = (argsRUN[2]);
var dungeonkey = (argsRUN[3]);
var timedornot = (argsRUN[4]);
var costofboost = (argsRUN[5]);
var paymentrealm1 = (argsRUN[6]);
var boost1ID = (argsRUN[7]);
var boost2ID = (argsRUN[8]);
var boost3ID = (argsRUN[9]);
var boost4ID = (argsRUN[10]);
var boost1tag = (argsRUN[11]);
var boost2tag = (argsRUN[12]);
var boost3tag = (argsRUN[13]);
var boost4tag = (argsRUN[14]);
var advertiserrealm = (argsRUN[15]);
var commentup = (argsRUN[16]);
var ticketornot = (argsRUN[17]);
var uniquerunid = (argsRUN[18]);
var customerrealm = (argsRUN[19]);
var customerfaction = (argsRUN[20]);
I'm close, but my logic just isn't quite working. I am able to run the code below within Google Sheets Scripts to create a calendar event for each row in the sheet. I am trying to get it to only create an event when a new row is entered and to only read the spreadsheet until it comes to the first column/row being empty/null. enter image description here
Here is the associated code:
function createCalendarEvent() {
var sheet = SpreadsheetApp.getActiveSheet();
var calendar = CalendarApp.getCalendarById('dentaldigitaldesign.bkp#gmail.com');
var startRow = 100; // First row of data to process - 100 exempts my header row and adds to the case number count.
var numRows = sheet.getLastRow(); // Number of rows to process
var numColumns = sheet.getLastColumn();
var dataRange = sheet.getRange(startRow, 1, numRows-1, numColumns);
var data = dataRange.getValues();
var complete = "TRUE";
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var caseID = row[0]; //Case ID Number
var patient = row[4]; //Patient Name
var doctor = row[5]; //Doctor
var contact = row[14]; //Doctor contact info
var tooth = row[15]; //Tooth number
var shade = row[10]; //Tooth Shade
var notes = row[8]; //Notes
var callNotes = row[7]; //Call notes if there are any
var timeStamp = new Date (row[2]); //Retrieve the timestamp field
// year as 4 digits (YYYY)
var year = timeStamp.getFullYear();
// month as 2 digits (MM)
var month = ("0" + (timeStamp.getMonth() + 1)).slice(-2);
// date as 2 digits (DD)
var day = ("0" + timeStamp.getDate()).slice(-2);
var dueDate = new Date(month + day, + year); //Due date
var rDate = new Date(row[2]-1); //Remind date
var caseComplete = row[3]; //Case marked as complete
if (caseComplete !== complete && caseID !== null) {
var currentCell = sheet.getRange(startRow + i, numColumns);
calendar.createEvent(patient, rDate, rDate, {
description: doctor + '\r' + patient + '\r' + contact + '\r' + dueDate + '\r' + tooth + '\r' + shade + '\r' + notes + '\r' + callNotes
});
currentCell.setValue(complete);
}
}
}
When these events are created, they are all created for 8:59am. Ideally, I could do a check on the calendare if an event is set for that time, a new event is added immediately after. (perhaps in 15min or 30min slots). For now it works well for me to get the reminders on cases that are due, but eventually an invite to the doctor for them to know the due date might work well, too.
I can also use help in formatting the description field as it is not pushing the return value and everything is on one line.
And finally, the script continues to run on numerous fields beyond the scope of the desired rows, ultimately ending up with the script failing because too many event attempts are created in too short a time. (all the attempts with fields that are empty do not result in any events being created, but it is a resouce issue....and who knows maybe Google eventually blocks me?)
I appreciate any help that can be offered.
Here is the link to the Google Sheet. No data on it is sensitive as it is only test data: https://docs.google.com/spreadsheets/d/1M9qYzSl1PnRv-GehHEYvpiag15UI_GjnanA0wgA4xmg/edit?usp=sharing
There are several issues with your code, causing this expression to always return true, so that the script tries to create an event for each row:
if (caseComplete !== complete && caseID !== null) {
Empty string !== null:
You want to check whether the cell in column A is empty (that is, whether its value is an empty string), and to do that you are comparing its value to null. null is not the same as an empty string, so the following expression will always be true (a cell value never returns null):
caseID !== null
You should be comparing this to an empty string. For example, like this:
caseID !== ""
So the if statement should be:
if (caseComplete !== complete && caseID !== "") {
Wrong complete column:
Once an event has been created, you want to set the corresponding cell in D to TRUE. You're not doing that, since you specify the last column in the sheet (numColumns) when setting the currentCell:
var currentCell = sheet.getRange(startRow + i, numColumns);
Because of this, the value in D never changes to TRUE, so caseComplete !== complete is always true.
You should specify the correct column index for D instead, which is 4. It should be like this:
var currentCell = sheet.getRange(startRow + i, 4);
Edit: Also, the retrieved value for cell with checked checkboxes is the boolean true, and you're trying to compare it with the string TRUE. Because of this, this condition is not working correctly. Please change:
var complete = "TRUE";
To
var complete = true;
Wrong number of rows in source range:
You want to get the value from row 100 till the last one in the sheet. In this case, the total number of rows in the range should be the last row (numRows) minus the first row in the range (startRow) plus one (numRows - startRow + 1). The dataRange should be defined like this instead:
var dataRange = sheet.getRange(startRow, 1, numRows - startRow + 1, numColumns);
Reference:
Class Range
null
I have a Upper Limit and Lower Limit on my spreadsheet responses that I input towards the right of my responses. The limits are both on F2 and G2. F2 is Lower Limit and G2 is Upper Limit. The code is using the function onFormSubmit and it has an MailApp.sendEmail function that will send an email in case someone enters a figure that is out of the limit.
What I do not understand that, the value that I read when the form is submitted is actually within the range but it still triggers an email.
I have tried this code specifically on a brand new form and spreadsheet and it did not have any problem.
function onFormSubmit(e){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Responses 1");
var speedUL = sheet.getRange("K2").getValue(); //250V
var speedLL = sheet.getRange("L2").getValue(); //207V
//var speedUL= parseInt(activess.getRange("K2").getValue()); //250V
//var speedLL = parseInt(activess.getRange("L2").getValue()); //207V
var speed1 = parseInt(e.values[2]);
if((speed1 >= speedUL) || (speed1 <= speedLL)){
console.log('SpeedUL: '+speedUL);
console.log('SpeedLL: '+speedLL);
console.log('Speed1: '+speed1);
var template1 = HtmlService.createTemplateFromFile("speed1");
template1.speed1 = speed1;
MailApp.sendEmail("someone#gmail.com ",
"Out of Range Notification Speed of VSD",
"",
{htmlBody : template1.evaluate().getContent()});
}else
{
return;
}
}
This is the test script that I am trying to do. With this code, I'm getting this
Error
Aug 26, 2019, 5:24:29 PM
TypeError: Cannot call method "getRange" of null.
at onFormSubmit(Code:7)
Line 7 refers to var speedUL = sheet.getRange("K2").getValue();
Probable Cause:
getRange() is called upon spreadsheet class (ss) and not on the sheet class (sheet). This usually means value of G2 and F2 of the first sheet is taken and not the specied sheet.
e.values is array of strings. Implicit conversion takes place when numbers are compared with strings. This is probably not the cause of your issue, but still needs to be addressed.
Solution:
Call getRange() on the sheet or specify the sheet name, when calling getRange() on spreadsheet.
Use explicit type conversion of e.value to number.
Snippet:
var temperature = Number(e.values[1]);
var temperatureUCL = ss.getRange("H3 Reponses!G2").getValue();
//or
var temperatureUCL = sheet.getRange("G2").getValue();
References:
Spreadsheet#getRange
Sheet#getRange
I should preface by saying I know nothing about scripting. I found this script online that fit my needs, so I was able to re-purpose it for my project. Anyway, this script takes Google form submissions, populates a Google doc template, that template gets copied, converted to PDF, and placed in a specific folder on my Google Drive.
So my question is, I have a simple line that pulls the current date when the script gets run, but I also need some code that can calculate the current date plus 5 weekdays (which should exclude weekends), but I also need it to exclude defined holidays. Any help would be greatly appreciated.
// Work Order
// Get template from Google Docs and name it
var docTemplate = ""; // *** replace with your template ID ***
var docName = "Work Order";
// When Form Gets submitted
function onFormSubmit(e) {
//Get information from form and set as variables
var email_address = "";
var job_name = e.values[1];
var ship_to = e.values[11];
var address = e.values[12];
var order_count = e.values[7];
var program = e.values[2];
var workspace = e.values[3];
var offer = e.values[4];
var sort_1 = e.values[5];
var sort_2 = e.values[6];
var print_services = e.values[10];
var priority = e.values[13];
var notes = e.values[14];
var formattedDate = Utilities.formatDate(new Date(), "EDT", "MM/dd/yyyy");
// Get document template, copy it as a new temp doc, and save the Doc's id
var copyId = DriveApp.getFileById(docTemplate)
.makeCopy(docName + ' for ' + job_name)
.getId();
// Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
// Get the document's body section
var copyBody = copyDoc.getActiveSection();
// Replace place holder keys,in our google doc template
copyBody.replaceText('keyJobName', job_name);
copyBody.replaceText('keyShipTo', ship_to);
copyBody.replaceText('keyAddress', address);
copyBody.replaceText('keyOrderCount', order_count);
copyBody.replaceText('keyProgram', program);
copyBody.replaceText('keyWorkspace', workspace);
copyBody.replaceText('keyOffer', offer);
copyBody.replaceText('keySort1', sort_1);
copyBody.replaceText('keySort2', sort_2);
copyBody.replaceText('keyPrintServices', print_services);
copyBody.replaceText('keyPriority', priority);
copyBody.replaceText('keyNotes', notes);
copyBody.replaceText('keyDate', formattedDate);
copyBody.replaceText('keyDue', expirationDate);
// Save and close the temporary document
copyDoc.saveAndClose();
// Convert temporary document to PDF by using the getAs blob conversion
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
// Attach PDF and send the email
var subject = "New Job Submission";
var body = "Here is the work order for " + job_name + "";
MailApp.sendEmail(email_address, subject, body, {
htmlBody: body,
attachments: pdf
});
// Move file to folder
var file = DriveApp.getFileById(copyId);
DriveApp.getFolderById("").addFile(file);
file.getParents().next().removeFile(file);
}
You can use the below function to get future date which excludes weekends and if any holiday declared in the array.
function addDates() {
var date = new Date(); // yor form date
var hodiday = ["08/09/2017","08/15/2017"]; //Define holiday dates in MM/dd/yyyy
var days = 5; //No of days you want to add
date.setDate(date.getDate());
var counter = 0;
if(days > 0 ){
while (counter < days) {
date.setDate(date.getDate() + 1 );
var check = date.getDay();
var holidayCheck = hodiday.indexOf(Utilities.formatDate(date, "GMT", "MM/dd/yyyy"));
if (check != 0 && check != 6 && holidayCheck == -1) {
counter++;
}
}
}
Logger.log(date) //for this example will give 08/16/2017
return date;
}
I have searched many of the date questions on here, but I am still stumped:
for (nn=3;nn<datacommit.length;++nn){
var duedate1 = datacommit[nn][4]
var duedate = Utilities.formatDate(duedate1,'GMT+0200','yyyy:MM:dd');
var sevendaysfromnow1 = datacommit[nn][9]
var sevendaysfromnow = Utilities.formatDate(sevendaysfromnow1,'GMT+0200','yyyy:MM:dd');
if (+duedate==+sevendaysfromnow) { do my thing}};
Does not find a match when the same date is in those two separate columns. What am I doing wrong?