Related
I have read all the previous posts and I have a similiar subjetc that I can't solve. I have to copy/paste a Google Sheets (two sheets, 'GENERAL', 'VALEUR') document.
I have won to write a code to copy/paste : 1 document (source) ==to==> 1 document (destination)
function expCalc(){
copypaste_GENERAL();
copypaste_VALEUR();
}
function copypaste_GENERAL() {
var source_G = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1xTBgfI-yy30GHm-LpsUWWoLRACNk5rdc81DPKGyS9fw/edit#gid=0');
var sourceSheet_G = source_G.getSheetByName('GENERAL');
var sourceRange_G = sourceSheet_G.getDataRange();
var sourceValues_G = sourceRange_G.getValues();
var tempSheet_G = source_G.getSheetByName('TEMP_GENERAL');
var tempRange_G = tempSheet_G.getRange('A1:DU11');
var destination_G = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1kFKaNOc8JbRM63tb24QB3_fJms5vnQbZj2lOYsoh0CA/edit#gid=1580219321');
var destSheet_G = destination_G.getSheetByName('GENERAL');
sourceRange_G.copyTo(tempRange_G); // paste all formats?, broken references
tempRange_G.offset(0, 0, sourceValues_G.length, sourceValues_G[0].length)
.setValues(sourceValues_G); // paste all values (over broken refs)
copydSheet = tempSheet_G.copyTo(destination_G); // now copy temp sheet to another ss
copydSheet.getDataRange().copyTo(destSheet_G.getDataRange());
destination_G.deleteSheet(copydSheet); //delete copydSheet
}
function copypaste_VALEUR() {
var source_V = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1xTBgfI-yy30GHm-LpsUWWoLRACNk5rdc81DPKGyS9fw/edit#gid=0');
var sourceSheet_V = source_V.getSheetByName('VALEUR');
var sourceRange_V = sourceSheet_V.getDataRange();
var sourceValues_V = sourceRange_V.getValues();
var tempSheet_V = source_V.getSheetByName('TEMP_VALEUR');
var tempRange_V = tempSheet_V.getRange('A1:I255');
var destination_V = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1kFKaNOc8JbRM63tb24QB3_fJms5vnQbZj2lOYsoh0CA/edit#gid=1580219321');
var destSheet_V = destination_V.getSheetByName('VALEUR');
sourceRange_V.copyTo(tempRange_V); // paste all formats?, broken references
tempRange_V.offset(0, 0, sourceValues_V.length, sourceValues_V[0].length)
.setValues(sourceValues_V); // paste all values (over broken refs)
copydSheet = tempSheet_V.copyTo(destination_V); // now copy temp sheet to another ss
copydSheet.getDataRange().copyTo(destSheet_V.getDataRange());
destination_V.deleteSheet(copydSheet); //delete copydSheet
}
but I can't write a code to copy/paste : 1 document (source) ==to==> MANY (more than 1) documents (destination) according to a list of URLs (here, example only on 2 URLs)
Here is my test code (using only t'GENERAL' sheet for this present test)
function copypaste_GENERAL() {
var source = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1xTBgfI-yy30GHm-LpsUWWoLRACNk5rdc81DPKGyS9fw/edit#gid=0');
var sourceSheet = source.getSheetByName('GENERAL');
var sourceRange = sourceSheet.getDataRange();
var sourceValues = sourceRange.getValues();
var tempSheet = source.getSheetByName('TEMP_GENERAL');
var tempRange = tempSheet.getRange('A1:DU11');
var destSpreadUrl = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1kFKaNOc8JbRM63tb24QB3_fJms5vnQbZj2lOYsoh0CA/edit#gid=1580219321');
var destSheetUrl = destSpreadUrl.getSheetByName('URLTST');
var destSheet_G = destSpreadUrl.getSheetByName('GENERAL');
var urlessai = destSheetUrl.getRange("D2:D3").getValues();
for (var row = 1; row = 3; row++) {
if (urlessai[row] != '') {
sourceRange.copyTo(tempRange); // paste all formats?, broken references
tempRange.offset(0, 0, sourceValues.length, sourceValues[0].length)
.setValues(sourceValues); // paste all values (over broken refs)
copydSheet = tempSheet.copyTo(destSpreadUrl); // now copy temp sheet to another ss
copydSheet.getDataRange().copyTo(destSheet_G.getDataRange());
destSpreadUrl.deleteSheet(copydSheet); //delete copydSheet
};
};
};
Please, can you help me to find a solution to write this copy/paste loop on a list of URLs (for x users) ?
Thanks in advance !
Philippe
This is probably not exactly what you want but I think it's close and I'm willing to tweak it.
function copySrcDes() {
const ss = SpreadsheetApp.getActive();
const locs = [{srcid:"1xTBgfI-yy30GHm-LpsUWWoLRACNk5rdc81DPKGyS9fw",desid:"1kFKaNOc8JbRM63tb24QB3_fJms5vnQbZj2lOYsoh0CA",shts:["GENERAL"]},{srcid:"1xTBgfI-yy30GHm-LpsUWWoLRACNk5rdc81DPKGyS9fw",desid:"1kFKaNOc8JbRM63tb24QB3_fJms5vnQbZj2lOYsoh0CA",shts:["VALEUR"]}];
locs.forEach(obj => {
let sss = SpreadsheetApp.openById(obj.srcid);
let dss = SpreadsheetApp.openById(obj.desid);
obj.shts.forEach(n => {
let ssh = sss.getSheetByName(n);
let dsh = dss.getSheetByName(n);
let vs = ssh.getDataRange().getValues();
dsh.getRange(1,1,vs.length,vs[0].length).setValues(vs);
});
});
}
I'm relatively new to coding, so thanks in advance for any assistance here.
I have a script that runs two functions on the same sheet.
Button2 contains a function (email_button2) that runs a SQL query and pulls info into columns A to D
Button1 also contains a function (email_button1) that runs a separate query and I want to pull this info in columns G to AA (21 columns)
Right now, when I click Button1, I get the following error: Incorrect range width, was 1 but should be 21
Any idea what I should change or add to my script?
function data_button() {
// Logger.log(e)
var thisDoc = SpreadsheetApp.getActiveSpreadsheet();
var helpers = thisDoc.getSheetByName("helper");
query =
helpers.getRange(3,2).getValue().split(String.fromCharCode(13)).join(" ").split(String.fromCharCode(10)).join(" ")
// lastrow = helpers.getRange("lastrow").getValue()
do_query(query,"data")
}
function email_button1() {
// Logger.log(e)
var thisDoc = SpreadsheetApp.getActiveSpreadsheet();
var helpers = thisDoc.getSheetByName("helper");
query =
helpers.getRange(4,2).getValue().split(String.fromCharCode(13)).join("
").split(String.fromCharCode(10)).join(" ")
// lastrow = helpers.getRange("lastrow").getValue()
do_query(query,"emails",11,7)
}
function email_button2() {
// Logger.log(e)
var thisDoc = SpreadsheetApp.getActiveSpreadsheet();
var helpers = thisDoc.getSheetByName("helper");
query =
helpers.getRange(5,2).getValue().split(String.fromCharCode(13)).join("
").split(String.fromCharCode(10)).join(" ")
// lastrow = helpers.getRange("lastrow").getValue()
do_query(query,"emails",11,1)
}
function do_query(query,sheetname,startRow,startCol){
//List of lists?
var url= "xxxxxxxxxxxxxx"
var q = {"query":query}
var options = {
'method' : 'post',
'payload' : q,
'muteHttpExceptions': true
};
var response = UrlFetchApp.fetch(url, options); // get feed
var response2 = response.getContentText()
var rows = response2.split(";;;")
var columnCount = rows[0].length
var data = [];
for(var i = 0; i < rows.length; i++){
var row = rows[i].split('|||');
data.push(row);
}
Logger.log(data)
var a = data[1]
var thisDoc = SpreadsheetApp.getActiveSpreadsheet();
var sheet2 = thisDoc.getSheetByName(sheetname);
sheet2.getRange(startRow,startCol,200,4).clear()
sheet2.getRange(startRow,startCol, data.length,
data[0].length).setValues(data);
//this line above designates column headers
//sheet2.getRange(12, 1, data[1].length, data[1] .
[0].length).setValues(data[1]);
//Logger.log(data[0].length)
//Logger.log(data[0][0].length)
//Logger.log(data[0])
// thisDoc.getSheetByName("helper").getRange("lastrow").setValue(data.length)
}
I'm new to GAS. I'm trying to accomplish four tasks in a single spreadsheet with three separate sheets to relate to.
I want to copy data from the 'rawData sheet', set it in an array, rearrange the array, and set the values in the 'destination sheet'. And keep it active for new submissions (i.e. getLastRow/appendRow).
In 'destination sheet' I want to color code based on status.
Create a button in 'destination sheet' to mark row(case) complete and move from 'destination' to the 'complete sheet'.
And add onEdit triggers for each.
Your input is greatly appreciated.
Thanks.
function colorCode() {
var range = outerArray;
Logger.log(range);
var row = dBoard.getRange(dBoard.getLastRow(),1,1,dBoard.getLastColumn());
var submitter = range[3];
var status = range[11];
Logger.log(submitter);
Logger.log(status);
//var column = range.getColumn();
//var row = range.getRow();
if (status === "Approved"){
var rowToColor = row.offset(0,0,1,13);
rowToColor.setBackground("#6bb2ff");
}
else if (status === "Requester"){
var rowToColor = row.offset(0,0,1,13);
rowToColor.setBackground("#ffe16b");
}
else if (range === 12 && range > 1 && status === "Denied"){
var rowToColor = row.offset(0,0,1,13);
rowToColor.setBackground("#f9441b");
}
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source1 = ss.getSheetByName("Copy of rawData");
var dBoard = ss.getSheetByName("dBoard2");
//function copyData() {
//var rawD = source1.getRange(1,1,source1.getLastRow(),source1.getLastColumn()).getValues();
//Logger.log(rawD);
function setData() {
var rawD = source1.getRange(source1.getLastRow(),1,1,source1.getLastColumn()).getValues();
//Logger.log(limits);
var columnA = rawD[0][0];
var columnB = rawD[0][18];
var columnC = rawD[0][13];
var columnD = rawD[0][2];
var columnE = rawD[0][3]
var columnF = rawD[0][4];
var columnG = rawD[0][5];
var columnH = rawD[0][6];
var columnI = rawD[0][7];
var columnJ = rawD[0][8];
var columnK = rawD[0][9];
var columnL = rawD[0][11];
var columnM = rawD[0][12];
var outerArray = [columnA,
columnB,
columnC,
columnD,
columnE,
columnF,
columnG,
columnH,
columnI,
columnJ,
columnK,
columnL,
columnM];
Logger.log(columnA);
Logger.log(columnB);
Logger.log(outerArray);
dBoard.getRange(2,1,outerArray.length,outerArray.length);
dBoard.appendRow(outerArray);
}
I've been searching for the answer to this question but have so far been unable to piece together the answer. Please explain any answer you have in really simple terms as I'm fairly new to GAS and RegEx. I've got most of the syntax down but the execution of it in GAS is giving me a hard time.
Basically, I want to write a script that, when the spreadsheet is edited, checks which rows have yet to be merged. Then, on those rows, creates a copy of a template Google Doc and names the document based on the spreadsheet data. From there (this is the hard part), I need it to replace merge tags in the template with the data from the spreadsheet.
The tags in the templates I'll be using look like this: <<mergeTag>>
My idea was to match the whole tag, and replace it with data from the spreadsheet that exists in the column with the same name as what's inside the "<<>>". Ex: <<FooBar>> would be replaced with the data from the column named FooBar. It would obviously be from the current row that needs the merging.
After that, all that's left is to send an email (a few more row-specific personalization) with that document attached (sometimes as a PDF) with the body of the message coming from an HTML file elsewhere in the project.
This is the whole thing I have so far (notice the placeholders here and there that I can personalize for each spreadsheet I use this for):
function onEdit() {
//SPREADSHEET GLOBAL VARIABLES
var ss = SpreadsheetApp.getActiveSpreadsheet();
//get only the merge sheet
var sheet = ss.getSheetByName("Merge Data");
//get all values for later reference
var range = sheet.getActiveRange();
var values = range.getValues();
var lastRow = range.getLastRow();
var lastColumn = range.getLastColumn();
//get merge checker ranges
var urlColumn = range.getLastColumn();
var checkColumn = (urlColumn - 1);
var checkRow = range.getLastRow();
var checkRange = sheet.getRange(2, checkColumn, checkRow);
var check = checkRange.getBackgrounds();
//get template determination range (unique to each project)
var tempConditionRange = sheet.getRange(row, column);
var tempConditionCheck = tempConditionRange.getValues();
//set color variables for status cell
var red = "#FF0000";
var yellow = "#FFCC00";
var green = "#33CC33";
//////////////////////////////////////////////////////////
//DOC GLOBAL VARIABLES
var docTemplate1 = DriveApp.getFileById(id);
var docTemplate2 = DriveApp.getFileById(id);
var docTemplate3 = DriveApp.getFileById(id);
var folderDestination = DriveApp.getFolderById(id);
//////////////////////////////////////////////////////////
//EMAIL GLOBAL VARIABLES
var emailTag = ss.getRangeByName("Merge Data!EmailTag");
var personalizers = "";
var subject = "" + personalizers;
var emailBody = HtmlService.createHtmlOutputFromFile("Email Template");
//////////////////////////////////////////////////////////
// MERGE CODE
for (i = 0; i < check.length; i++) {
//for rows with data, check if they have already been merged
if (check[i] == green) {
continue;
} else {
var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
var dataRow = sheet.getRange((i+2), 1, lastRow, (lastColumn - 2))
statusCell.setBackground(red);
//for rows with data, but not yet merged, perform the merge code
//////////////////////////////////////////////////////////
//DOC CREATION
//Determine which template to use
if (tempConditionCheck[i] == "") {
var docToUse = docTemplate1;
}
if (tempConditionCheck[i] == "") {
var docToUse = docTemplate2;
}
if (tempConditionCheck[i] == "") {
var docToUse = docTemplate3;
}
//Create a copy of the template
//Rename the document using data from specific columns, at specific rows
//Move the doc to the correct folder
var docName = "";
var docCopy = docToUse.makeCopy(docName, folderDestination);
var docId = docCopy.getId();
var docURL = docCopy.getUrl();
var docToSend = DriveApp.getFileById(docId);
var docBody = DocumentApp.openById(docId).getBody();
Here's where I need the help
//Locate the Merge Tags
//Match Merge Tags to the column headers of the same name
//Replace the Merge Tags with the data from the matched column, from the correct row
function tagReplace() {
var tagMatch = "/(<{2}(\w+)>{2})/g";
}
statusCell.setBackground(yellow);
urlCell.setValue(docURL);
The rest is just finishing up the process
//////////////////////////////////////////////////////////
//EMAIL CREATION
//Create an email using an HTML template
//Use Merge Tags to personalize email
//Attach the doc we created to the email
//Send email to recipients based on data in the sheet
MailApp.sendEmail(emailTag, subject, emailBody, {
name: "Person McPerson",
attachments: [docToSend], //[docToSend.getAs(MIME.PDF)],
html: emailBody,
});
//////////////////////////////////////////////////////////
//CHECK ROW UPDATE
statusCell.setBackground(green);
}
}
}
My sheets all have a frozen first row that acts as the header row. All my columns will be consistently named the exact same thing as the tags (minus the <<>>).
How do I match the tags to the data?
EDIT
```````````````````
The solution did not work as described when I inserted it into my code as follows:
function formMerge() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Merge Data");
var urlColumn = sheet.getMaxColumns();
var checkColumn = urlColumn - 1;
var lastRow = ss.getSheetByName("Form Responses").getLastRow();
var values = sheet.getDataRange().getValues();
var headers = values[0];
var urlRange = sheet.getRange(2, urlColumn, lastRow);
var checkRange = sheet.getRange(2, checkColumn, lastRow);
var check = checkRange.getBackgrounds();
var red = "#ff0404";
var yellow = "#ffec0a";
var green = "#3bec3b";
var docTemplate = DriveApp.getFileById(id);
var folderDestination = DriveApp.getFolderById(id);
// MERGE CODE
for (i = 0; i < check.length; i++) {
if (check[i] == green) {
continue;
} else {
var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
var dataRow = sheet.getRange((i+2), 1, 1, (urlColumn - 2)).getValues();
var clientNameRange = sheet.getRange((i+2), 3);
var clientName = clientNameRange.getValue();
var dateRange = sheet.getRange((i+2), 2);
var datePreFormat = dateRange.getValue();
var timeZone = CalendarApp.getTimeZone();
var date = Utilities.formatDate(new Date(datePreFormat), timeZone, "MM/dd/yyyy");
statusCell.setBackground(red);
//EMAIL VARIABLES
var personalizers = clientName;
var subject = "Post Intake Report for " + personalizers;
var emailBody = "Please see the attached Google Doc for the Post Intake Report for " + clientName + ". The intake was performed on " + date + ".";
var emailTagRange = sheet.getRange((i+2), 24);
var emailTagValue = emailTagRange.getValue();
var emailTag = emailTagValue.split(", ");
//DOC CREATION
var docToUse = docTemplate;
var docName = "Post Intake Report - " + clientName + " [" + date + "]";
var docCopy = docToUse.makeCopy(docName, folderDestination);
var docId = docCopy.getId();
var docURL = docCopy.getUrl();
var docBody = DocumentApp.openById(docId).getBody().editAsText();
for (var j=0; j<headers.length; j++) {
var re = new RegExp("(<<"+headers[j]+">>)","g");
docBody.replaceText(re, dataRow[j]);
}
statusCell.setBackground(yellow);
urlCell.setValue(docURL);
//EMAIL CREATION
MailApp.sendEmail(emailTag, subject, emailBody, {
name: "Christopher Anderson",
attachments: [docCopy],
html: emailBody
});
statusCell.setBackground(green);
}
}
}
Build the RegExp for each tag on the fly, using the header values from your spreadsheet.
Use Body.replaceText() to perform the replacements.
var values = sheet.getDataRange().getValues();
var headers = values[0];
...
// Loop over all columns. Use header names to search for tags.
for (var col=0; col<headers.length; col++) {
// Build RegExp using column header
var re = new RegExp("(<{2}"+headers[col]+">{2})","g");
// Replace tags with data from this column in dataRow
body.replaceText(re, dataRow[col]);
}
This snippet will operate on a single row; the first couple of declarations should appear outside of your row loop. The column looping is then done after you've created and opened the new document, and obtained the body object.
It loops over all the columns in the spreadsheet, using the header names to find the tags you've defined, and replaces them with the corresponding cell contents for the current row.
here is the code
function makeaCVdoc(){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var startRow = 2;
var numRows = sheet.getLastRow() -1;
var EMAIL_SENT = "EMAIL_SENT";
var subject = "Here is your CV";
//var dataRange = sheet.getRange(2,2,numRows,50);
var data = dataRange.getValues();
for(var i = 0; i < data.length; ++i)
{
var row = data[i];
var firstname = row[1];
var secondname = row[2];
var thiredname = row[3];
var address = row[4]
var email_address = row[5];
var homenumber = row[6];
var mobilenumber= row[7];
var objective = row[8];
var language = row[9];
var educationwithdegree = row[10];
var computerskill = row[11];
var TrainingCourse = row[12];
var Hobbies = row[13];
var DOB = row[14];
var nationality = row[15];
var MaritalStatus = row[16]
var emailSent = row[17];
var CVdoc = DocumentApp.create(firstname+' '+secondname+' '+thiredname);
var par1 = CVdoc.getBody().appendParagraph(firstname+' '+secondname+' '+thiredname);
par1.setHeading(DocumentApp.ParagraphHeading.TITLE);
var par2 = CVdoc.getBody().appendParagraph("Address: ");
par2.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(address);
var par3 = CVdoc.getBody().appendParagraph("Email Address: ");
par3.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(email_address);
var par4 = CVdoc.getBody().appendParagraph("Home Number: ");
par4.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(homenumber);
var par5 = CVdoc.getBody().appendParagraph("Mobile Number: ");
par5.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(mobilenumber);
var par6 = CVdoc.getBody().appendParagraph("Objective: ");
par6.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(objective);
var par7 = CVdoc.getBody().appendParagraph("Spoken Languages: ");
par7.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(language);
var par8 = CVdoc.getBody().appendParagraph("Education and Degree: ");
par8.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(educationwithdegree);
var par9 = CVdoc.getBody().appendParagraph("Computer Skills: ");
par9.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(computerskill);
var par10 = CVdoc.getBody().appendParagraph("Training Courses: ");
par10.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(TrainingCourse);
var par11 = CVdoc.getBody().appendParagraph("Hobbies: ");
par11.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(Hobbies);
var par12 = CVdoc.getBody().appendParagraph("Nationality: ");
par12.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(nationality);
var par13 = CVdoc.getBody().appendParagraph("Date Of Birth: ");
par13.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(DOB);
var par14 = CVdoc.getBody().appendParagraph("Marital Status: ");
par14.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(MaritalStatus);
var url = CVdoc.getUrl();
var body = 'Link to your doc: ' + url +'Thank you for using our Tech';
if(emailSent != EMAIL_SENT)
{
//GmailApp.sendEmail(email_address, subject, body);
//sheet.getRange(2,17).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
}
it's basically a form that i want to use to get all the information that it's needed in order to make a CV and after the user enter all the information and submit the form it's stored at a spreadsheet than i have this code inside this spreadsheet but something wrong with the comment lines and i still don't know why
i get something wrong with the getRange() command
which lead to another code error at the GmailApp command
right now i made them as comments
but no matter what i do i don't know what's wrong
so please could anyone help me
some said that they needed more information about the error
like i said the error is at the commented lines
var dataRange = sheet.getRange(2,2,numRows,50);
GmailApp.sendEmail(email_address, subject, body);
sheet.getRange(2,17).setValue(EMAIL_SENT);
it basically tell me error at line whatever the line is
and write the line to me as a function
what i mean is getRange(number,number,number,number);
and that's all what i get nothing more nothing less
this is the code after i changed it
function makeaCVdoc()
{
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var startRow = 2;
var numRows = sheet.getLastRow() -1;
var EMAIL_SENT = "EMAIL_SENT";
var subject = "Here is your CV";
var dataRange = sheet.getRange("B2:R2");
var data = dataRange.getValues();
for(var i = 0; i < data.length; ++i)
{
var row = data[i];
var firstname = row[0];
var secondname = row[1];
var thiredname = row[2];
var address = row[3]
var email_address = row[4];
var homenumber = row[5];
var mobilenumber= row[6];
var objective = row[7];
var language = row[8];
var educationwithdegree = row[9];
var computerskill = row[10];
var TrainingCourse = row[11];
var Hobbies = row[12];
var DOB = row[13];
var nationality = row[14];
var MaritalStatus = row[15]
var emailSent = row[16];
var CVdoc = DocumentApp.create(firstname+' '+secondname+' '+thiredname);
var par1 = CVdoc.getBody().appendParagraph(firstname+' '+secondname+' '+thiredname);
par1.setHeading(DocumentApp.ParagraphHeading.TITLE);
var par2 = CVdoc.getBody().appendParagraph("Address: ");
par2.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(address);
var par3 = CVdoc.getBody().appendParagraph("Email Address: ");
par3.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(email_address);
var par4 = CVdoc.getBody().appendParagraph("Home Number: ");
par4.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(homenumber);
var par5 = CVdoc.getBody().appendParagraph("Mobile Number: ");
par5.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(mobilenumber);
var par6 = CVdoc.getBody().appendParagraph("Objective: ");
par6.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(objective);
var par7 = CVdoc.getBody().appendParagraph("Spoken Languages: ");
par7.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(language);
var par8 = CVdoc.getBody().appendParagraph("Education and Degree: ");
par8.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(educationwithdegree);
var par9 = CVdoc.getBody().appendParagraph("Computer Skills: ");
par9.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(computerskill);
var par10 = CVdoc.getBody().appendParagraph("Training Courses: ");
par10.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(TrainingCourse);
var par11 = CVdoc.getBody().appendParagraph("Hobbies: ");
par11.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(Hobbies);
var par12 = CVdoc.getBody().appendParagraph("Nationality: ");
par12.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(nationality);
var par13 = CVdoc.getBody().appendParagraph("Date Of Birth: ");
par13.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(DOB);
var par14 = CVdoc.getBody().appendParagraph("Marital Status: ");
par14.setHeading(DocumentApp.ParagraphHeading.HEADING2);
CVdoc.getBody().appendParagraph(MaritalStatus);
CVdoc.saveAndClose();
var CVdocID = CVdoc.getId();
var url = CVdoc.getUrl();
var pdf = DocsList.getFileById(CVdocID).getAs("application/pdf");
var body = 'Here is your CV ' + pdf +'Thank you for using our Tech';
if(emailSent != EMAIL_SENT)
{
GmailApp.sendEmail(email_address, subject, body);
sheet.getRange("r2").setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
sheet.deleteRow(2);
}
I'm not sure how to fix what you have going on, I suspect it is structure and the fact that you're pulling 50 columns in your getRange, but really only need 17 of them (possible column width error?) Here is a script I use to procedurally generate a document from a form submission. In my case, I delete the document when I'm finished, but you'd leave it there and collect the URL and enclose it in the email you spit out. You can also use chained functions to repeat some of the repetitive tasks like copyBody.replaceText("text", variable), but if I gave you my version of that, it is more confusing since I use a lot of for() iterators, and the data in that example comes from UiApp not a form and spreadsheet combo.
function onFormSubmit(e) { // add an onsubmit trigger
var sheet = SpreadsheetApp.getActiveSheet();
var row = SpreadsheetApp.getActiveSheet().getLastRow();
//Set Unique ID for each entry
sheet.getRange(row,2).setValue(row);
// Full name and email address values come from the spreadsheet form
var email_address = "myemail#somewhere.com";//used as a reporting email for errors
var userName = e.values[1];
var date = e.values[2];
var vendor = e.values[3];
var coordinator = e.values[4];
var buyer = e.values[5];
var category = e.values[7];
var submittedBy = e.values[79];
//Values from form
var line1 = e.values[9];
var item1 = e.values[10];
var quantity1 = e.values[11];
var sku1 = e.values[12];
var price1 = e.values[13];
var total1 = e.values[14];
var line2 = e.values[16];
var item2 = e.values[17];
var quantity2 = e.values[18];
var sku2 = e.values[19];
var price2 = e.values[20];
var total2 = e.values[21];
var line3 = e.values[23];
var item3 = e.values[24];
var quantity3 = e.values[25];
var sku3 = e.values[26];
var price3 = e.values[27];
var total3 = e.values[28];
var line4 = e.values[30];
var item4 = e.values[31];
var quantity4 = e.values[32];
var sku4 = e.values[33];
var price4 = e.values[34];
var total4 = e.values[35];
var line5 = e.values[37];
var item5 = e.values[38];
var quantity5 = e.values[39];
var sku5 = e.values[40];
var price5 = e.values[41];
var total5 = e.values[42];
var line6 = e.values[44];
var item6 = e.values[45];
var quantity6 = e.values[46];
var sku6 = e.values[47];
var price6 = e.values[48];
var total6 = e.values[49];
var line7 = e.values[51];
var item7 = e.values[52];
var quantity7 = e.values[53];
var sku7 = e.values[54];
var price7 = e.values[55];
var total7 = e.values[56];
var line8 = e.values[58];
var item8 = e.values[59];
var quantity8 = e.values[60];
var sku8 = e.values[61];
var price8 = e.values[62];
var total8 = e.values[63];
var line9 = e.values[65];
var item9 = e.values[66];
var quantity9 = e.values[67];
var sku9 = e.values[68];
var price9 = e.values[69];
var total9 = e.values[70];
var line10 = e.values[72];
var item10 = e.values[73];
var quantity10 = e.values[74];
var sku10 = e.values[75];
var price10 = e.values[76];
var total10 = e.values[77];
var sumRange = sheet.getRange(1,86,sheet.getLastRow(),1);
sumRange.setNumberFormat("0,000,000.00");
sheet.getRange(row,86,1,1).setNumberFormat("0,000,000.00");
var sum = Math.round(100*(sheet.getRange(row,86,1,1).getValue())/100);
Logger.log(sum);
sheet.getRange(row,86,1,1).setNumberFormat("0,000,000.00");
Logger.log(sum);
//Document variables
var docTemplate = "Doc Id for your template document to replace text"; // *** replace with your template ID ***
var todaysDate = Utilities.formatDate(new Date(), "GMT", "MM/dd/yyyy");
var docName = "CV Document name " +userName +" on " +todaysDate;
// Get document template, copy it as a new temp doc, and save the Doc’s id
var copyId = DocsList.getFileById(docTemplate)
.makeCopy(docName)
.getId();
// Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
// Get the document’s body section
var copyBody = copyDoc.getActiveSection();
// Replace place holder keys this can be iterated with a number of for() loops
// Template Header
copyBody.replaceText('keyDate', date);
copyBody.replaceText('keyVendor', vendor);
copyBody.replaceText('keyCoordinator', coordinator);
copyBody.replaceText('keyBuyer', buyer);
copyBody.replaceText('keyCategory', category);
//Template Table
copyBody.replaceText('keyLine1', line1);
copyBody.replaceText('keyItem1', item1);
copyBody.replaceText('keyQuantity1', quantity1);
copyBody.replaceText('keySKU1', sku1);
copyBody.replaceText('keyPrice1', price1);
copyBody.replaceText('keyTotal1', total1);
copyBody.replaceText('keyLine1', line1);
copyBody.replaceText('keyItem1', item1);
copyBody.replaceText('keyQuantity1', quantity1);
copyBody.replaceText('keySKU1', sku1);
copyBody.replaceText('keyPrice1', price1);
copyBody.replaceText('keyTotal1', total1);
copyBody.replaceText('keyLine2', line2);
copyBody.replaceText('keyItem2', item2);
copyBody.replaceText('keyQuantity2', quantity2);
copyBody.replaceText('keySKU2', sku2);
copyBody.replaceText('keyPrice2', price2);
copyBody.replaceText('keyTotal2', total2);
copyBody.replaceText('keyLine3', line3);
copyBody.replaceText('keyItem3', item3);
copyBody.replaceText('keyQuantity3', quantity3);
copyBody.replaceText('keySKU3', sku3);
copyBody.replaceText('keyPrice3', price3);
copyBody.replaceText('keyTotal3', total3);
copyBody.replaceText('keyLine4', line4);
copyBody.replaceText('keyItem4', item4);
copyBody.replaceText('keyQuantity4', quantity4);
copyBody.replaceText('keySKU4', sku4);
copyBody.replaceText('keyPrice4', price4);
copyBody.replaceText('keyTotal4', total4);
copyBody.replaceText('keyLine5', line5);
copyBody.replaceText('keyItem5', item5);
copyBody.replaceText('keyQuantity5', quantity5);
copyBody.replaceText('keySKU5', sku5);
copyBody.replaceText('keyPrice5', price5);
copyBody.replaceText('keyTotal5', total5);
copyBody.replaceText('keyLine6', line6);
copyBody.replaceText('keyItem6', item6);
copyBody.replaceText('keyQuantity6', quantity6);
copyBody.replaceText('keySKU6', sku6);
copyBody.replaceText('keyPrice6', price6);
copyBody.replaceText('keyTotal6', total6);
copyBody.replaceText('keyLine7', line7);
copyBody.replaceText('keyItem7', item7);
copyBody.replaceText('keyQuantity7', quantity7);
copyBody.replaceText('keySKU7', sku7);
copyBody.replaceText('keyPrice7', price7);
copyBody.replaceText('keyTotal7', total7);
copyBody.replaceText('keyLine8', line8);
copyBody.replaceText('keyItem8', item8);
copyBody.replaceText('keyQuantity8', quantity8);
copyBody.replaceText('keySKU8', sku8);
copyBody.replaceText('keyPrice8', price8);
copyBody.replaceText('keyTotal8', total8);
copyBody.replaceText('keyLine9', line9);
copyBody.replaceText('keyItem9', item9);
copyBody.replaceText('keyQuantity9', quantity9);
copyBody.replaceText('keySKU9', sku9);
copyBody.replaceText('keyPrice9', price9);
copyBody.replaceText('keyTotal9', total9);
copyBody.replaceText('keyLineA', line10);
copyBody.replaceText('keyItemA', item10);
copyBody.replaceText('keyQuantityA', quantity10);
copyBody.replaceText('keySKUA', sku10);
copyBody.replaceText('keyPriceA', price10);
copyBody.replaceText('keyTotalA', total10);
copyBody.replaceText('keySum', +sum);
// Save and close the temporary document
copyDoc.saveAndClose();
// Convert temporary document to PDF by using the getAs blob conversion
var pdf = DocsList.getFileById(copyId).getAs("application/pdf");
// Attach PDF and send the email
var subject = "CV submitted by "+submittedBy;
var body = userName +" has submitted a new CV, which is attached to this email.\nPlease ensure there are no errors before printing.\nIf there are errors, please notify: "+email_address +"\n\n";
MailApp.sendEmail(email_address, subject, body, {htmlBody: body, attachments: pdf});
// Delete temp file
DocsList.getFileById(copyId).setTrashed(true);//remove this if you added URL above for posterity
}
If you're interested I can post the iterator version of this code that makes loops for repetitive actions. Just let me know. It's a lot more complex than this example because there are a lot of function calls, but if you're comfortable with that, I'll put it up.
I know for a fact that this code will make an invoice type/shipping label document because my template is built that way. I did not change the code to your variables and needs. You will also need to build a template document with keys to replace with each user's entry values, but that isn't terribly hard. All of the formatting can be done there, and you can add headings and such in the script that read from submitted data columns so if the section (such as nationality) is left blank there's no heading or content for it.
You're looking for technique #3 in this tutorial http://googleappsdeveloper.blogspot.com/2011/10/4-ways-to-do-mail-merge-using-google.html for a guide on how to do the script I provided.
Also, be careful with body.replaceText() using keys that are numbers. When you get to 10, it will replace the text with keyText1 and add a 0 string to the end. I'd recommend using alphabet letters or words instead for your keyValues.
Here is the iterated function version of the same basic process. Ignore the UiApp lines and remove the app methods, and it will work like a form. I'm including it as an alternative to show how you can use for loops to construct a document from a template without having to hand-code it all. It's also more modular, so if I need to change something, I can just add or modify that function and not mess with the rest of it.
function doPost(e){
var app = UiApp.getActiveApplication();
var vertPanel = app.createVerticalPanel();
var grantName = e.parameter.grantName;
var userEmail = Session.getActiveUser().getEmail();
var mrNumber = e.parameter.MR;
var ss = SpreadsheetApp.openById("Id for the form response spreadsheet");
var infoSheet = ss.getSheetByName('name of the form response sheet');
var keyRow = selectKeysByGrant(grantName);
var keyHeaders = infoSheet.getRange(1,1,1,infoSheet.getLastColumn()).getValues();
var infoData = infoSheet.getRange(keyRow,1,1,infoSheet.getLastColumn()).getValues();
var keyIds = new Array (makeKeys(keyHeaders));
var dataVars = new Array (makeDataVars(keyIds));
var copyId = assignKeys(dataVars,keyIds,infoData,userEmail,mrNumber);
var pdf = mailCheatSheet(copyId,userEmail,mrNumber);
var completeLabel = app.createLabel('You should receive your worksheet results in your email soon.');
app.add(completeLabel);
return app;
}
//Select Data Row from funding type
function selectKeysByGrant(grantName){
var grant = null;
switch (grantName){
case "1":
grant = 2
break;
case "2":
grant = 3
break;
case "3":
grant = 4
break;
case "4":
grant = 5
break;
}
return grant;
}
function makeKeys(keyHeaders){
var keys = [];
for (var i = 0; i< keyHeaders[0].length; i++){
keys.push("key"+keyHeaders[0][i]);
}
return keys;
}
function makeDataVars(keyIds){
var dataVarLabels = [];
for (var k = 0; k < keyIds[0].length; k++){
dataVarLabels.push(keyIds[0][k] +"text");
}
return dataVarLabels;
}
function assignKeys(dataVars,keyIds,infoData,userEmail,mrNumber){
var variables = dataVars;
var keys = keyIds;
var rowData = infoData;
var userEmail = userEmail;
var date = Utilities.formatDate(new Date, "CST","MM/dd/yyyy");
var mrNum = mrNumber;
Logger.log(variables);
Logger.log(keys);
Logger.log(rowData);
var docTemplate = "ID of your document template";
var todaysDate = Utilities.formatDate(new Date(), "GMT", "MM/dd/yyyy");
var docName = "New name of document created submitted by " +userEmail +" on " +todaysDate;
// Get document template, copy it as a new temp doc, and save the Doc’s id
var copyId = DocsList.getFileById(docTemplate).makeCopy(docName).getId();
// Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
// Get the document’s body section
var copyBody = copyDoc.getActiveSection();
for (n = 1; n < variables[0].length; n++){
copyBody.replaceText(keys[0][n].toString(),rowData[0][n].toString())
}
//replacing some text from the UIapp but isn't on the spreadsheet
copyBody.replaceText('keyUserEmail',userEmail);
copyBody.replaceText('keyDate',date);
copyBody.replaceText('keyMR',mrNum);
// Save and close the temporary document
copyDoc.saveAndClose();
return copyId;
}
function mailCheatSheet(copyId,userEmail,mrNumber){
var copyId = copyId;
var userEmail = userEmail;
var mrNum = mrNumber;
// Convert temporary document to PDF by using the getAs blob conversion
var pdf = DocsList.getFileById(copyId).getAs("application/pdf");
// Attach PDF and send the email
var subject = "SA Funding request by: "+userEmail;
var body = userEmail +" has submitted a document for " +mrNumber +", which is attached to this email.\nPlease ensure there are no errors before printing.\nIf there are errors, please notify: myself#xyz.com.\n\n";
MailApp.sendEmail(userEmail, subject, body, {name: 'CV Helperbot', htmlBody: body, attachments: pdf});
// Delete temp file
DocsList.getFileById(copyId).setTrashed(true);
return pdf;
}