如何解决提交后从 Google 表单生成 PDF 时出现问题
我正在创建一个 Google 脚本,它根据 Google 表单的字段填充 Google 文档模板,并通过电子邮件将生成的 PDF 发送给用户。
此处详细解释了我遵循的所有步骤:Hacking it: Generate PDFs from Google Forms
脚本(从文章中获得)是:
function onSubmit(e) {
const rg = e.range;
const sh = rg.getSheet();
//Get all the form submitted data
//Note: This data is dependent on the headers. If headers,are changed update these as well.
const cName = e.namedValues['Client Name'][0];
const cEmail = e.namedValues['Client Email'][0];
const cAddress = e.namedValues['Client Address'][0];
const cMobile = e.namedValues['Client Mobile'][0];
const sendcopy = e.namedValues['Send client a copy?'][0];
const paymentType = e.namedValues['What is your agreed upon payment schedule?'][0];
const fixedcost = e.namedValues['What was your agreed upon cost for the project?'][0];
const hourlyRate = e.namedValues['Hourly Rate'][0];
const manHours = e.namedValues['Total man hours'][0];
const services = e.namedValues['Select the services'][0];
//Consequential Data
const tax = 18.5
var subtotal = 0;
var taxAmt = 0;
var payableAmt = 0;
//if the user has selected hourly payment model
//Note: Be careful that the responses match the elements on the actual form
switch (paymentType ){
case 'Hourly Rate':
subtotal = hourlyRate*manHours;
taxAmt = subtotal * (tax/100);
payableAmt = +subtotal + +taxAmt;
break;
case 'Fixed Cost':
subtotal = fixedcost;
taxAmt = fixedcost * (tax/100)
payableAmt = +fixedcost + +taxAmt;
break;
}
const invoiceID = 'IN' + Math.random().toString().substr(2,9);
var formattedDate = Utilities.formatDate(new Date(),"IST","dd-MMM-yyyy");
//Set the consequential data in the columns of the spreadsheet for record keeping
//Note: These variable are dependent on the sheet's columns so if that changes,please update.
const row = rg.getRow();
const payableAmtCol = 2; //B
const invoiceIDCol = 3; //C
sh.getRange(row,payableAmtCol).setValue(payableAmt);
sh.getRange(row,invoiceIDCol).setValue(invoiceID);
//Build a new invoice from the file
//Folder and file IDs
const invoiceFolderID = '<invoice-folder-id>';
const invoiceFolder = DriveApp.getFolderById(invoiceFolderID);
const templateFileID = '<template-id>';
const newFilename = 'Invoice_' + invoiceID;
//Make a copy of the template file
const newInvoiceFileID = DriveApp.getFileById(templateFileID).makecopy(newFilename,invoiceFolder).getId();;
//Get the invoice body into a variable
var document = DocumentApp.openById(newInvoiceFileID);
var body = document.getBody();
//Replace all the {{ }} text in the invoice body
body.replaceText('{{Invoice num}}',invoiceID);
body.replaceText('{{Date}}',formattedDate);
body.replaceText('{{Client Name}}',cName);
body.replaceText('{{Client Address}}',cAddress);
body.replaceText('{{Client Mobile}}',cMobile);
body.replaceText('{{Client Email}}',cEmail);
body.replaceText('{{Services}}',services.split(',').join('\n'));
body.replaceText('{{Subtotal}}',subtotal);
body.replaceText('{{Tax Value}}',taxAmt);
body.replaceText('{{Total}}',payableAmt);
//In the case of hourly rate payment type,let's add an additional message giving the rate and the man hours.
if(paymentType.includes('Hourly Rate')){
//It should look something like this on the invoice
//Hourly Rate
//Rate of Rs.1200/hour
//Completed 50 man hours
const message = paymentType + '\nRate of Rs.' + hourlyRate + '/hour\nCompleted ' + manHours + ' man hours';
body.replaceText('{{Payment Type}}',message);
} else {
body.replaceText('{{Payment Type}}',paymentType);
}
document.saveAndClose();
//send email with the file
var attachment = DriveApp.getFileById(newInvoiceFileID);
GmailApp.sendEmail(cEmail,'<subject>,'<body>',{attachments: [attachment.getAs(MimeType.PDF)]});
}
代码运行良好。现在我需要用户在 Google 表单上按“发送表单”后可以编辑其回复。所以我决定选中“回复者可以在提交后进行编辑”。然后我需要通过 GmailApp
再次发送带有编辑过的字段的文档。所以我创建了一个新触发器:Edit
(来自电子表格)。另一个触发器是 Form submit
。
但是我有一个问题。 当用户编辑一个字段并再次按下“发送表单”时,触发器“编辑”被激活并出现以下错误:Failed to send email: no recipient
。
如果我转到电子表格回复,我可以看到已编辑的行(因为单元格有一条评论“回复的人已更新此值”),并且列邮件未编辑但仍会引发异常。
如果从未编辑过 cEmail
,我们如何解决这个问题?
搜索
我可以找到一些有趣的答案:
- Failed to send email: no recipient
- Google scripts “Failed to send email: no recipient” but email arrives
- Failed to send email: no recipient,what is wrong with my code?
他们似乎描述了激活触发器“编辑”时可以生成一个空白行。但是,我不明白为什么会发生这种情况,以及如何解决它,因为在新用户提交答案后会自动编辑电子表格响应。
解决方法
编辑表单回复时,表单提交事件对象属性 values
和 namedValues
仅包含已编辑问题的值。
要修复错误 Failed to send email: no recipient
,请替换
GmailApp.sendEmail(cEmail,'<subject>,'<body>',{attachments: [attachment.getAs(MimeType.PDF)]});
由
const recipientIdx = 1; // This is the 0 based index of the column having the recipient email address
const recipient = cEmail ? cEmail : e.range.getValues().flat()[recipientIdx]
GmailApp.sendEmail(recipient,'<subject>',{attachments: [attachment.getAs(MimeType.PDF)]});
附言您可以使用一些代码来根据列标题获取它,而不是对分配给 recipientIdx
的值进行硬编码。
注意:以上只会防止问题中提到的错误。为了使脚本工作,您必须对所有字段应用相同的想法:使用 e.range.getValues().flat()
从电子表格中读取缺失值。
相关
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。