Google Sheets Script Error When Trying to Copy Folder - javascript

Problem 1:
When I try to execute the below code it comes up with the error 'Exception: Invalid argument: name (line 37, file "Create New Project")'. I originally thought that it could be that the variable 'jobNumber' wasn't a string but now that it is, it still doesn't execute.
Problem 2:
When I don't use the variable 'jobNumber' for the folder name and just us a string value, it executes. However the new folder does not go into the source folders drive but into my personal drive.
function createProject(){
searchProject();
createFolder();
}
//Search for New Project and return values
function searchProject(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
var search = "New Job";
for(var i = 0; i<data.length;i++){
if(data[i][9] == search){
Logger.log((i+1));
var jobNumber = sheet.getRange((i+1), 1).getDisplayValue()
var jobSite = sheet.getRange((i+1), 2).getDisplayValue()
var jobTitle = sheet.getRange((i+1), 3).getDisplayValue()
return i+1;
}
}
}
//Create New Project Folders
function createFolder(jobNumber, jobSite, jobTitle) {
var sourceFolder = "12345_Site Name_Commissioning Engineer Name";
var targetFolder = jobNumber
var source = DriveApp.getFoldersByName(sourceFolder);
var target = DriveApp.createFolder(targetFolder);
if (source.hasNext()) {
copyFolder(source.next(), target);
}
}
function copyFolder(source, target) {
var folders = source.getFolders();
var files = source.getFiles();
while(files.hasNext()) {
var file = files.next();
file.makeCopy(file.getName(), target);
}
while(folders.hasNext()) {
var subFolder = folders.next();
var folderName = subFolder.getName();
var targetFolder = target.createFolder(folderName);
copyFolder(subFolder, targetFolder);
}
}

I have managed to find my own solution.
By adding the 'foler_ID' and 'folder' variable to get the folder to go into the correct folder in google drive.
I also missed calling the creatFolder function in searchProject function, with that now included the variables are carried over.
Thanks for all the contributors that helped :)
/**
* Create New Project
*/
//Search for New Project and return values
function createProject(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
var search = "New Job";
for(var i = 0; i<data.length;i++){
if(data[i][9] == search){
Logger.log((i+1));
var jobNumber = sheet.getRange((i+1), 1).getDisplayValue()
var jobSite = sheet.getRange((i+1), 2).getDisplayValue()
var jobTitle = sheet.getRange((i+1), 3).getDisplayValue()
createFolder (jobNumber, jobSite, jobTitle);
Logger.log(jobNumber);
Logger.log(jobSite);
Logger.log(jobTitle);
return i+1;
}
}
}
//Create New Project Folders
function createFolder(jobNumber, jobSite, jobTitle) {
var sourceFolder = "12345_Site Name_Commissioning Engineer Name";
var targetFolder = (jobNumber + " " + jobSite + " " + jobTitle + "TESTING");
var foler_ID = '14QpCYc803GnDC_pR-7AqViePHBKyNNv_';
var folder = DriveApp.getFolderById(foler_ID);
var source = DriveApp.getFoldersByName(sourceFolder);
var target = folder.createFolder(targetFolder);
Logger.log(target);
if (source.hasNext()) {
copyFolder(source.next(), target);
}
}
function copyFolder(source, target) {
var folders = source.getFolders();
var files = source.getFiles();
while(files.hasNext()) {
var file = files.next();
file.makeCopy(file.getName(), target);
}
while(folders.hasNext()) {
var subFolder = folders.next();
var folderName = subFolder.getName();
var targetFolder = target.createFolder(folderName);
copyFolder(subFolder, targetFolder);
}
}

Related

Add filename to the first column of the import

I have files on the folder and i import them to the google sheet.
I need to add filename to first column before import, but my script add it only to first cell before import
So it gives me:
Filename
Pencil
01/01/2022
Pen
01/02/2022
Hat
And i need
Filename
1/01/2022
Pencil
Filename
1/01/2022
Pen
Filename
01/02/2022
Hat
function Import_Kredo() {
var arr = [];
var files = DriveApp.getFolderById("13kymSiqX0-L6a9ev4It1_BEjH-xM8rnc").getFiles();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Table 1");
copySheet.getRange('A2:G').clear();
while (files.hasNext()) {
var file = files.next();
var mimeType = file.getMimeType();
var ss1 = null, id = null;
if (mimeType == MimeType.MICROSOFT_EXCEL) {
id = Drive.Files.copy({ mimeType: MimeType.GOOGLE_SHEETS }, file.getId()).id;
ss1 = SpreadsheetApp.openById(id);
} else if (mimeType == MimeType.GOOGLE_SHEETS) {
ss1 = SpreadsheetApp.open(file);
}
if (!ss1) continue;
var sheet = ss1.getSheetByName("Table 1");
if (!sheet) continue;
var sheetsRange = sheet.getDataRange();
var sheetsValues = sheetsRange.getValues().filter(r => r[1]).filter(e => e);
var v = sheetsValues.slice(1);
console.log([file.getName(), v])
arr = arr.concat([[file.getName(), ...Array(v[0].length - 1).fill(null)], ...v]);
if (id) DriveApp.getFileById(id).setTrashed(true); // or Drive.Files.remove(id);
}
copySheet.getRange(5, 1, arr.length, arr[0].length).setValues(arr);
}
In your situation, how about the following modification?
From:
arr = arr.concat([[file.getName(), ...Array(v[0].length - 1).fill(null)], ...v]);
To:
var filename = file.getName();
arr = arr.concat(v.map(e => [filename, ...e]));
By this modification, the filename is put into the 1st column of each row.

How to create a google doc for each row of a spreadsheet?

Yo!
This is my code that uses the last line of a spreadsheet to generate a google docs, in addition, it places a link to this document in the source spreadsheet. Is it possible to create code that does this for all rows in a worksheet? I'm having trouble using .range() to read the lines individually. The reason for this is simply to maintain and update generated versus updated data.
In advance, thank you!
var app=SpreadsheetApp.openById("Google ID");
var sheet=app.getSheetByName('Respostas ao formulário 1')
function autoFillLastRow() {
var range=sheet.getDataRange().getValues();
var elem = range.pop();
//e.values is an array of form values
var timestamp = elem[0];
//conversor de datas
let data = new Date(timestamp);
let dataFormatada = ((data.getDate() )) + "/" + ((data.getMonth() + 1)) + "/" + data.getFullYear();
var firstName = elem[1];
var lastName = elem[2];
var title = elem[3];
//file is the template file, and you get it by ID
var file = DriveApp.getFileById('Google Drive ID');
//We can make a copy of the template, name it, and optionally tell it what folder to live in
//file.makeCopy will return a Google Drive file object
var folder = DriveApp.getFolderById('Google Drive ID')
var copy = file.makeCopy(dataFormatada + ', ' + firstName, folder);
//Once we've got the new file created, we need to open it as a document by using its ID
var doc = DocumentApp.openById(copy.getId());
//Since everything we need to change is in the body, we need to get that
var body = doc.getBody();
//Then we call all of our replaceText methods
body.replaceText('{{Nome}}', firstName);
body.replaceText('{{Sobrenome}}', lastName);
body.replaceText('{{Título}}', title);
//Lastly we save and close the document to persist our changes
doc.saveAndClose();
//edit cell
var coluna = 5;
var linha = sheet.getLastRow();
var docId = doc.getId();
sheet.getRange(linha, coluna,1,1).setValue("https://docs.google.com/document/d/" + docId);
}
Create document for every row of spreadsheet
function createDocforEveryRowofSpreadsheet() {
var ss = SpreadsheetApp.openById("Google ID");
var sh = ss.getSheetByName('Respostas ao formulário 1')
var file = DriveApp.getFileById('Google Drive ID');
var folder = DriveApp.getFolderById('Google Drive ID')
var [hA,...vs] = sh.getDataRange().getValues();
vs.forEach((r,i) => {
var ts = r[0];
let data = new Date(ts);
let dataFormatada = Utilities.formatDate(new Date(ts), Spreadsheet.getSpreadsheetTimeZone(), "dd/MM/yyyy")
var firstName = r[1];
var lastName = r[2];
var title = r[3];
var copy = file.makeCopy(dataFormatada + ', ' + firstName, folder);
var doc = DocumentApp.openById(copy.getId());
var body = doc.getBody();
body.replaceText('{{Nome}}', firstName);
body.replaceText('{{Sobrenome}}', lastName);
body.replaceText('{{Título}}', title);
doc.saveAndClose();
})
}

List Files in all Subfolders in a Given Folder in Google Drive

I'm trying to adapt a script found at https://github.com/bluexm/snipets/blob/master/list%20Gdrive%20files%20and%20folders.
While the creator of the script could assume unique folder names, I can't. So, I've made a couple of changes that should have resulted in limiting my search to the one folder. The problem is, this goes one level of subfolders, but not two. So, currently, the script searches 'Client Documents'/'2021-01-25'/'Subfolder1' and then stops, even though I need it to keep going to 'Client Documents'/'2021-01-25'/'Subfolder1'/'Sub-Subfolder2'.
Any thoughts on what has stopped this from going to Sub-Subfolder1?
function ListFilesandFolders(){
var sheet = ss.getActiveSheet();
var fileno = sheet.getSheetName();
var filenoFolders = DriveApp.searchFolders("title contains '"+fileno.replace("'","\'")+"' and trashed = false and hidden = false");
var filenoFolder = filenoFolders.next().getFoldersByName("Internal Documents").next();
var clientdocsFolders = filenoFolder.getFoldersByName("Disclosure").next().getFoldersByName("Our Client").next().getFolders();
var clientdocsFolder = filenoFolder.getFoldersByName("Disclosure").next().getFoldersByName("Our Client").next();
var aorFolder = clientdocsFolder.getFoldersByName("Affidavit of Records").next();
var tz = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
var date = Utilities.formatDate(new Date(), tz, "yyyy-MM-dd");
// Find or Create doclist
var aorFolderlist = aorFolder.getFiles();
var doclist = "new"
while (aorFolderlist.hasNext()) {
var aorFile = aorFolderlist.next();
if (aorFile.getName().includes("Document List")) {
var doclist = SpreadsheetApp.open(aorFile);
// doclist.duplicateActiveSheet().activate();
// doclist.renameActiveSheet(date);
// doclist.moveActiveSheet(0)
}
}
if (doclist == "new") {
var doclist = SpreadsheetApp.create(date + " Document List");
doclist.renameActiveSheet(date);
doclist.appendRow(["Document No.", "Document Date", "Document Title", "File Name", "URL", "Folder", "Date Created", "File ID", "File Name (No Date)", "Producible"]);
DriveApp.getFileById(doclist.getId()).moveTo(aorFolder);
}
ListFilesandFolders1F(clientdocsFolders,'',doclist)
}
function ListFilesandFolders1F(fn,rfn,sheet) {
// declare an array to push data into the spreadsheet
var data = [];
var count = 1;
var foldersnext = fn.next();
Logger.log("THE FOLDER IS "+foldersnext);// DEBUG
// list files in this folder
// myfiles is a File Iterator
var myfiles = foldersnext.getFiles();
Logger.log("FILES IN THIS FOLDER"); //DEBUG
// loop through files in this folder
while (myfiles.hasNext()) {
var myfile = myfiles.next();
count = Number(count) + 1;
var shno = "#";
var shdate = '=LEFT(D' + count + ',FIND(" ",D' + count + ')-1)';
var shtitle = '=LEFT(I' + count + ',FIND(".",I' + count + ')-1)';
var shfilename = '=RIGHT(D' + count + ',LEN(D' + count + ')-FIND(" ",D' + count + '))';
var fname = myfile.getName();
var fdate = myfile.getDateCreated();
var fid = myfile.getId();
var furl = myfile.getUrl();
// Populate the array for this file
data = [
shno,
shdate,
shtitle,
fname,
furl,
foldersnext,
fdate,
fid,
shfilename
];
//Logger.log("data = "+data); //DEBUG
sheet.appendRow(data);
} // Completes listing of the files in the named folder
// Now get the subfolder
// subfolders is a Folder Iterator
var subfolders = foldersnext.getFolders();
Logger.log("THE SUBFOLDER(S) ARE"); //DEBUG HEADING
// now start a loop on the SubFolder list
while (subfolders.hasNext()) {
var subfolderdata = [];
var mysubfolders = subfolders.next().getFolders();
var mysubfolder = mysubfolders.next();
ListFilesandFolders1F(mysubfolders,rfn +'/'+ mysubfolder,sheet)
}
}
And here's the answer:
/* Adapted from Code written by #hubgit https://gist.github.com/hubgit/3755293
Updated since DocsList is deprecated https://ctrlq.org/code/19854-list-files-in-google-drive-folder
Bluexm: added recursion on subfolders */
// List all files and sub-folders in a folder and subfolders Google Drive
// entry function
function ListFilesandFolders(){
var sheet = ss.getActiveSheet();
var fileno = sheet.getSheetName();
var filenoFolders = DriveApp.searchFolders("title contains '"+fileno.replace("'","\'")+"' and trashed = false and hidden = false");
var filenoFolder = filenoFolders.next().getFoldersByName("Internal Documents").next();
var clientdocsFolder = filenoFolder.getFoldersByName("Disclosure").next().getFoldersByName("Our Client").next();
var aorFolder = clientdocsFolder.getFoldersByName("Affidavit of Records").next();
var tz = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
var date = Utilities.formatDate(new Date(), tz, "yyyy-MM-dd");
// Find or Create doclist
var aorFolderlist = aorFolder.getFiles();
var doclist = "new"
while (aorFolderlist.hasNext()) {
var aorFile = aorFolderlist.next();
if (aorFile.getName().includes("Document List")) {
var doclist = SpreadsheetApp.open(aorFile);
// doclist.duplicateActiveSheet().activate();
// doclist.renameActiveSheet(date);
// doclist.moveActiveSheet(0)
}
}
if (doclist == "new") {
var doclist = SpreadsheetApp.create(date + " Document List");
doclist.renameActiveSheet(date);
doclist.appendRow(["Document No.", "Document Date", "Document Title", "File Name", "URL", "Folder", "Date Created", "File ID", "File Name (No Date)", "Producible"]);
DriveApp.getFileById(doclist.getId()).moveTo(aorFolder);
}
ListFilesandFolders1F(clientdocsFolder,'',doclist)
}
function ListFilesandFolders1F(fn,rfn,sheet) {
// declare an array to push data into the spreadsheet
var data = [];
var count = 1;
var foldersnext = fn;
Logger.log("THE FOLDER IS "+foldersnext);// DEBUG
// list files in this folder
// myfiles is a File Iterator
var myfiles = foldersnext.getFiles();
Logger.log("FILES IN THIS FOLDER"); //DEBUG
// loop through files in this folder
while (myfiles.hasNext()) {
var myfile = myfiles.next();
count = Number(count) + 1;
var shno = "#";
var shdate = '=LEFT(D' + count + ',FIND(" ",D' + count + ')-1)';
var shtitle = '=LEFT(I' + count + ',FIND(".",I' + count + ')-1)';
var shfilename = '=RIGHT(D' + count + ',LEN(D' + count + ')-FIND(" ",D' + count + '))';
var fname = myfile.getName();
var fdate = myfile.getDateCreated();
var fid = myfile.getId();
var furl = myfile.getUrl();
// Populate the array for this file
data = [
shno,
shdate,
shtitle,
fname,
furl,
foldersnext.getName(),
fdate,
fid,
shfilename
];
//Logger.log("data = "+data); //DEBUG
sheet.appendRow(data);
} // Completes listing of the files in the named folder
// Now get the subfolder
// subfolders is a Folder Iterator
var subfolders = foldersnext.getFolders();
Logger.log("THE SUBFOLDER(S) ARE"); //DEBUG HEADING
// now start a loop on the SubFolder list
while (subfolders.hasNext()) {
var subfolderdata = [];
var mysubfolders = subfolders.next();
ListFilesandFolders1F(mysubfolders,rfn +'/'+ fn,sheet)
}
}

How can I copy data from a google spreasheet using the file name, and paste it into another file?

I am trying to use a file name to get data from a Spreadsheet, and copy the data into a different target file. I have the following code, and it is failing at line 7. When I manually put in an ID in line 7 the code works. Could someone help? Thank you very much.
function openFile() {
var fileList = DriveApp.getFilesByName('file name')
while (fileList.hasNext()) {
Logger.log(fileList.next().getId())
}
var fileID = Logger.getLog();
var ss = SpreadsheetApp.openById(fileID);//fails here
var source = ss.getSheetByName('sheet name');
var rangeSource = source.getDataRange();
var data = rangeSource.getValues();
var rowsInData = data.length;
var colsInData = data[0].length;
var sss = SpreadsheetApp.openById('1Hia3_zGk1qyPlVuPTQR5iOjExFaMEe3EQOMXBc2C6eI');
var logSheet = sss.getSheetByName("diamondbackprogress");
var rowsInLogSheet = logSheet.getMaxRows();
var colsInLogSheet = logSheet.getMaxColumns();
if (rowsInLogSheet < rowsInData) {
logSheet.insertRowsAfter(rowsInLogSheet, rowsInData - rowsInLogSheet);
} else if (rowsInLogSheet > rowsInData) {
logSheet.deleteRows(rowsInData, rowsInLogSheet - rowsInData);
}
if (colsInLogSheet < colsInData) {
logSheet.insertColumnsAfter(colsInLogSheet, colsInData - colsInLogSheet);
} else if (colsInLogSheet > colsInData) {
logSheet.deleteColumns(colsInData, colsInLogSheet - colsInData);
}
logSheet.getRange(1, 1, rowsInData, colsInData).setValues(data);
}
Logger.getLog() won't give you the id of the file, it will give a list of messages in the current log. See here for more details.
Replace this part:
function openFile() {
var fileList = DriveApp.getFilesByName('file name')
while (fileList.hasNext()) {
Logger.log(fileList.next().getId())
}
var fileID = Logger.getLog();
with this:
function openFile() {
var fileList = DriveApp.getFilesByName('file name')
while (fileList.hasNext()) {
var fID = fileList.next().getId();
}
var fileID = fID;

How to set a time-driven (clock) trigger for a function that needs parameters sent to it?

I'm trying to have a function run with a time-driven (clock) trigger. My issue is, the function needs variables sent to it as parameters. Normally if I'm not using a trigger I'll just send it directly like this.
<script>
function runFunction(){
google.script.run.myFunction(x,y,z);
}
</script>
And on the server side, I'll call them easily.
function myFunction(x,y,z){
var a = x;
var b = y;
var c = z;
Logger.log(a+b+c);
}
But when I'm using a time-driven (clock) trigger to run the function how can I get x,y,z into the function.
I searched around and saw one method of creating scriptProperties out of the parameters in the trigger function like this.
EDITED This is the actual code.
Client side.
<script>
function sendCall() {
var testNumber = document.getElementById('numberCall').value;
var testGroup = document.getElementById('groupsCall').value;
var testtime = document.getElementById('scheduleCall').value;
var now = document.getElementsByName('sendTimeCall')[0].checked;
var number;
if(testNumber == ''){
number = null;
}else{
number = testNumber;
}
var group;
if(testGroup == ""){
group = null;
}else{
group = testGroup;
}
var time;
if(testtime == ''){
time = null;
}else{
time = testtime;
}
var file = document.getElementsByName('audio')[0].files[0];
var name = file.name;
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
google.script.run.withSuccessHandler(success2).triggerCall(group, number, content, time, now, name);
return false;
}
reader.readAsDataURL(file);
}
</script>
Server side - Trigger Function.
function triggerCall(group, number, content, time, now, name){
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.setProperties({
'GROUP_CALL': group,
'AUDIO': content,
'NUMBER_CALL': number,
'FILE_NAME': name
});
var status;
if(now){
status = 'Call Sent';
}else{
status = 'Call Scheduled';
}
if(now){
return makeCall(status);
}else{
// Set here the date you want to schedule the one-time trigger
var rawdate = time;
var today_D = new Date(new Date().toLocaleString("en-US", {timeZone: "America/New_York"}));
var scheduled_D = new Date(rawdate);
var time_af = Math.abs(scheduled_D - today_D) / 36e5;
ScriptApp.newTrigger("makeCall")
.timeBased()
.after(time_af * 60 *60 * 1000)
.create();
}
return status;
}
Server side - Here is The function that actually does the work.
function makeCall(status) {
var scriptProperties = PropertiesService.getScriptProperties();
var blob = scriptProperties.getProperty('AUDIO');
var number = scriptProperties.getProperty('NUMBER_CALL');
var group = scriptProperties.getProperty('GROUP_CALL');
var name = scriptProperties.getProperty('FILE_NAME');
var fullNumber;
if(group){
var ss = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxx');
var sheet = ss.getSheetByName(group)
var length = sheet.getLastRow();
var values = sheet.getRange(1, 1, length).getValues();
fullNumber = values.flat();
}else{
var num = number;
var prefix = '+1';
var removeDashes = num.replace(/-/g,"");
var format = prefix + removeDashes;
var comma = format.replace(/ /g, ' +1');
fullNumber = comma.split(' ')
}
//upload file to drive
var folder = DriveApp.getFolderById('xxxxxxxxxxxxxxxxxxxxxx');
var blob = blob.split(",");
var blob = Utilities.newBlob(Utilities.base64Decode(blob[1]), 'audio/mpeg', name);
var file = folder.createFile(blob);
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
var id = file.getId();
for (var i = 0; i < fullNumber.length; i++){
//the url with HTTP request to create a call and parameters
var callsUrl = "https://api.twilio.com/2010-04-01/Accounts/ACxxxxxxxxxxxxxxxx/Calls.json";
var payload = {
"To": fullNumber[i],
"From" : "+177777777",
"Twiml" : "<Response><Play>https://docs.google.com/uc?export=play&id=" + id + "</Play></Response>",
};
var options = {
"method" : "post",
"payload" : payload
};
options.headers = {
"Authorization" : "Basic " + Utilities.base64Encode("xxxxxxxxxxx:xxxxxxxx")
};
UrlFetchApp.fetch(callsUrl, options);
}
scriptProperties.deleteProperty('AUDIO');
scriptProperties.deleteProperty('NUMBER_CALL');
scriptProperties.deleteProperty('GROUP_CALL');
scriptProperties.deleteProperty('FILE_NAME');
return status;
}
The problem is when I run the above code without the file input it works, But when I run it as above the function doesn't work. I did some trouble shooting and I think it has to do with transferring the file as a Data URL via the properties method. Is there a limit to how long of a string the VALUE can be?
in a nut shell these are the 2 points of my question.
Any other ideas how to send parameters to a triggered function
How I could do it using PropertiesService.
I would like to propose the following modification.
Modification points:
I think that the reason of your issue might be due to the maximum data size for PropertiesService. In the current stage, it seems that "Properties total storage" is "500kB / property store". I thought that in this case, when you upload a file, the file size might be over than it.
In order to remove your issue, how about creating content as a temporal file and put the file ID to the PropertiesService?
When above points are reflected to your script, it becomes as follows.
Pattern 1:
In this pattern, content is saved as a temporal file and that is used in the function of makeCall().
triggerCall()
function triggerCall(group, number, content, time, now, name){
var scriptProperties = PropertiesService.getScriptProperties();
var tempFile = DriveApp.createFile("tempFile.txt", content, MimeType.PLAIN_TEXT); // Added
scriptProperties.setProperties({'GROUP_CALL': group,'AUDIO': tempFile.getId(),'NUMBER_CALL': number,'FILE_NAME': name}); // Modified
var status;
if(now){
status = 'Call Sent';
}else{
status = 'Call Scheduled';
}
if(now){
return makeCall(status);
}else{
var rawdate = time;
var today_D = new Date(new Date().toLocaleString("en-US", {timeZone: "America/New_York"}));
var scheduled_D = new Date(rawdate);
var time_af = Math.abs(scheduled_D - today_D) / 36e5;
ScriptApp.newTrigger("makeCall").timeBased().after(time_af * 60 *60 * 1000).create();
}
return status;
}
makeCall()
function makeCall(status) {
var scriptProperties = PropertiesService.getScriptProperties();
var tempfileId = scriptProperties.getProperty('AUDIO'); // Modified
var number = scriptProperties.getProperty('NUMBER_CALL');
var group = scriptProperties.getProperty('GROUP_CALL');
var name = scriptProperties.getProperty('FILE_NAME');
var fullNumber;
if(group){
var ss = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxx');
var sheet = ss.getSheetByName(group)
var length = sheet.getLastRow();
var values = sheet.getRange(1, 1, length).getValues();
fullNumber = values.flat();
}else{
var num = number;
var prefix = '+1';
var removeDashes = num.replace(/-/g,"");
var format = prefix + removeDashes;
var comma = format.replace(/ /g, ' +1');
fullNumber = comma.split(' ')
}
var folder = DriveApp.getFolderById('xxxxxxxxxxxxxxxxxxxxxx');
var tempFile = DriveApp.getFileById(tempfileId); // Added
var text = tempFile.getBlob().getDataAsString(); // Added
tempFile.setTrashed(true); // Added
var blob = text.split(","); // Modified
var blob = Utilities.newBlob(Utilities.base64Decode(blob[1]), 'audio/mpeg', name);
var file = folder.createFile(blob);
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
var id = file.getId();
for (var i = 0; i < fullNumber.length; i++){
var callsUrl = "https://api.twilio.com/2010-04-01/Accounts/ACxxxxxxxxxxxxxxxx/Calls.json";
var payload = {"To": fullNumber[i],"From" : "+177777777","Twiml" : "<Response><Play>https://docs.google.com/uc?export=play&id=" + id + "</Play></Response>"};
var options = {"method" : "post","payload" : payload};
options.headers = {"Authorization" : "Basic " + Utilities.base64Encode("xxxxxxxxxxx:xxxxxxxx")};
UrlFetchApp.fetch(callsUrl, options);
}
scriptProperties.deleteProperty('AUDIO');
scriptProperties.deleteProperty('NUMBER_CALL');
scriptProperties.deleteProperty('GROUP_CALL');
scriptProperties.deleteProperty('FILE_NAME');
return status;
}
Pattern 2:
In this pattern, content is saved to a file as the decoded data and that is used in the function of makeCall().
triggerCall()
function triggerCall(group, number, content, time, now, name){
var scriptProperties = PropertiesService.getScriptProperties();
var folder = DriveApp.getFolderById('xxxxxxxxxxxxxxxxxxxxxx'); // Added
var blob = content.split(","); // Added
var blob = Utilities.newBlob(Utilities.base64Decode(blob[1]), 'audio/mpeg', name); // Added
var file = folder.createFile(blob); // Added
scriptProperties.setProperties({'GROUP_CALL': group,'AUDIO': file.getId(),'NUMBER_CALL': number,'FILE_NAME': name}); // Modified
var status;
if(now){
status = 'Call Sent';
}else{
status = 'Call Scheduled';
}
if(now){
return makeCall(status);
}else{
var rawdate = time;
var today_D = new Date(new Date().toLocaleString("en-US", {timeZone: "America/New_York"}));
var scheduled_D = new Date(rawdate);
var time_af = Math.abs(scheduled_D - today_D) / 36e5;
ScriptApp.newTrigger("makeCall").timeBased().after(time_af * 60 *60 * 1000).create();
}
return status;
}
makeCall()
function makeCall(status) {
var scriptProperties = PropertiesService.getScriptProperties();
var fileId = scriptProperties.getProperty('AUDIO'); // Modified
var number = scriptProperties.getProperty('NUMBER_CALL');
var group = scriptProperties.getProperty('GROUP_CALL');
var name = scriptProperties.getProperty('FILE_NAME');
var fullNumber;
if(group){
var ss = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxx');
var sheet = ss.getSheetByName(group)
var length = sheet.getLastRow();
var values = sheet.getRange(1, 1, length).getValues();
fullNumber = values.flat();
}else{
var num = number;
var prefix = '+1';
var removeDashes = num.replace(/-/g,"");
var format = prefix + removeDashes;
var comma = format.replace(/ /g, ' +1');
fullNumber = comma.split(' ')
}
var file = DriveApp.getFileById(fileId); // Modified
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
var id = file.getId();
for (var i = 0; i < fullNumber.length; i++){
var callsUrl = "https://api.twilio.com/2010-04-01/Accounts/ACxxxxxxxxxxxxxxxx/Calls.json";
var payload = {"To": fullNumber[i],"From" : "+177777777","Twiml" : "<Response><Play>https://docs.google.com/uc?export=play&id=" + id + "</Play></Response>"};
var options = {"method" : "post","payload" : payload};
options.headers = {"Authorization" : "Basic " + Utilities.base64Encode("xxxxxxxxxxx:xxxxxxxx")};
UrlFetchApp.fetch(callsUrl, options);
}
scriptProperties.deleteProperty('AUDIO');
scriptProperties.deleteProperty('NUMBER_CALL');
scriptProperties.deleteProperty('GROUP_CALL');
scriptProperties.deleteProperty('FILE_NAME');
return status;
}
Note:
In this modified script, when a file is uploaded, content is saved as a temporal file and the file ID is put to the PropertiesService. When makeCall is run, content is retrieved by the file ID and convert to the blob and saved it as a file. And the temporal file is removed. By this, the limitation of PropertiesService can be cleared.
But, in the current stage, the maximum blob size of Google Apps Script is 50 MB (52,428,800 bytes). So when the uploaded file size is over 50 MB, an error occurs. In this case, the file is converted to the base64 data. So, the maximum size is the size of base64 data. Please be careful this.
Reference:
Current limitations

Categories