如何用AppScript将HTML转PDF自动下载到本地,不存至Google Drive
批量生成发票PDF本地下载的问题修复方案
问题根源
原代码存在三个核心问题:
- 重复调用
DriveApp.createFile(blob)导致PDF被存储到Google Drive - HTML模板占位符替换逻辑错误,生成的PDF内容损坏
- 函数参数传递不匹配,导致PDF名称和内容异常
修复后的完整代码
1. 主函数createPDF修复
function createPDF() { var ws = SpreadsheetApp.getActiveSpreadsheet(); var xs = ws.getSheetByName('Nota'); var lr = xs.getLastRow(); var list = xs.getRange('B2:C' + lr).getValues(); var filtered = list.filter(row => row[0] !== '' && row[1] === ''); var notaList = filtered.map(row => row[0]); notaList.forEach(function(invoiceNumber) { downloadPdfToDesktop(invoiceNumber); }); }
- 修正循环参数传递错误:将
noInvoice改为与循环变量一致的invoiceNumber - 简化变量命名,提升代码可读性
2. 下载函数downloadPdfToDesktop修复
function downloadPdfToDesktop(noInvoice) { var pdfFileName = noInvoice + '.pdf'; // 读取HTML模板并替换占位符 var template = HtmlService.createHtmlOutputFromFile('report').getContent(); // 替换客户名称占位符(若需填充$custData,需补充对应数据逻辑) var htmlBody = template.replace('$custName', noInvoice); // 直接生成PDF Blob,不存储到Drive var pdfBlob = HtmlService.createHtmlOutput(htmlBody).getAs('application/pdf').setName(pdfFileName); // 生成Base64编码的Data URI,直接触发本地下载 var base64Pdf = Utilities.base64Encode(pdfBlob.getBytes()); var downloadUrl = 'data:application/pdf;base64,' + base64Pdf; SpreadsheetApp.getUi().showModelessDialog( HtmlService.createHtmlOutput( '<a target="_blank" download="' + pdfFileName + '" href="' + downloadUrl + '">点击这里</a> 手动下载(若未自动开始)' + '<script>' + 'var a = document.querySelector("a");' + 'a.addEventListener("click", () => setTimeout(google.script.host.close, 10));' + 'a.click();' + '</script>' ).setHeight(50), '正在下载PDF...' ); }
- 移除所有
DriveApp.createFile调用,彻底避免PDF存储到Google Drive - 修正占位符替换逻辑:用字符串
'$custName'作为替换目标,避免变量未定义错误 - 改用
HtmlService.createHtmlOutput(htmlBody).getAs('application/pdf')生成PDF,保证HTML样式和结构正确转换 - 直接从PDF Blob生成Base64编码,跳过Drive的URL获取流程,避免权限和内容损坏问题
额外说明
若需要填充模板中的$custData表格内容,需在createPDF函数中获取对应客户的产品数据,并在htmlBody替换时补充逻辑,示例如下:
// 假设从表格中获取对应noInvoice的产品数据,生成表格行HTML var productRows = '<tr><td>Product A</td><td>M</td><td>$100</td><td>10%</td><td>2</td><td>$180</td></tr>'; var htmlBody = template.replace('$custName', noInvoice).replace('$custData', productRows);
内容的提问来源于stack exchange,提问作者erem
相关产品推荐
相关产品推荐

