如何解决格式化 PDF 的 Google Apps 脚本问题
我正在使用 GAS 在源电子表格中生成给定工作表的 PDF。
我的做法是首先将给定的工作表复制到我称之为“中间”的新电子表格文件中,设置样式,然后使用 filetoPDF.getAs("application/pdf");
将其 PDF 格式。
文件被创建,它拥有我想要的一切,除了两个问题:
- 我已经使用
sheet.getRange(borderRange).setBorder(true,true,true);
对某些范围应用了一些边框,并且它们确实在“中间”文件中显示没有问题。但是,它们在 PDF 中消失了。 - 我已经合并了一些范围集,那里没有问题,但有一个很大的例外,即工作表中最后一个合并的范围在 PDF 中没有显示为一个合并的单元格。
我使用的代码如下:
function crearPdf() {
const ssID = SpreadsheetApp.getActiveSpreadsheet().getId();
const destFolder = DriveApp.getFileById(ssID).getParents().next();
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getActiveSheet();
const sourceRange = ws.getRange(1,1,ws.getMaxRows(),ws.getMaxColumns());
const numFac = ws.getRange("D20");
const sourceValues = sourceRange.getdisplayValues();
const dest = SpreadsheetApp.create("temp " + Date());
const destSheet = dest.getSheets()[0];
const destRange = destSheet.getRange(1,destSheet.getMaxRows(),destSheet.getMaxColumns());
destRange.setValues(sourceValues);
styleSheet(destSheet);
const destId = dest.getId();
const filetoPDF = DriveApp.getFileById(destId);
const fileAsPDF = filetoPDF.getAs("application/pdf");
const newFile = DriveApp.createFile(fileAsPDF).setName("Factura " + numFac.getValue() + ' - ' + " '21");
// const fileUrl = newFile.getDownloadUrl();
newFile.moveto(destFolder);
// filetoPDF.setTrashed(true);
}
function styleSheet(sheet) {
// Declaring our constants
const arrToMerge = ["B24:G24","B25:G25","B26:G26","B40:H40","B20:C20","B21:C21","B22:C22"];
const arrToBorder = ["B20:D22","B24:H26","G27:H28"];
const arrToBold = ["B11","B20","B21","B22","B24","B31","B33","B34","B35","B36","G28","H3","H24","H28"];
// Direct tweaks
sheet.setHiddenGridlines(true);
sheet.setColumnWidth(1,15);
sheet.getDatarange().setFontFamily("Open Sans");
sheet.getRange("B40").setWrap(true);
sheet.getRange("B40:B47").setFontSize(9);
sheet.autoResizeRows(40,1);
sheet.setColumnWidth(3,54);
// sheet.setColumnWidth(2,79);
sheet.setRowHeights(37,3,7);
// sheet.setRowHeights(40,7,16);
sheet.getRange("h24").setHorizontalAlignment("right");
sheet.getRange("B24:H24").setBackground("#666666").setFontColor("white");
// Loops for multiple ranges tweaks
for (let range of arrToMerge) {
sheet.getRange(range).merge();
}
for (let cell of arrToBold) {
sheet.getRange(cell).setFontWeight("bold");
}
for (let range of arrToBorder) {
sheet.getRange(range).setBorder(true,true);
}
}
我还从原始文件中删除了一些单元格以使其更易于理解(并没有真正删除代码中的所有引用,因此如果您看到对看起来为空的单元格的引用不要感到惊讶)
而下图对应:
原始电子表格
最终的PDF
最后,link to a public spreadsheet with dummy data
`getAs("application/pdf") 方法是否有一些已知的奇怪行为?有没有办法让它正常工作?
预先感谢您的帮助!
解决方法
而不是使用 getAs()
将工作表导出为 pdf
你可以这样做
- 创建导出链接
"https://docs.google.com/spreadsheets/d/"+destId+"/export?"
- 使用@Shootfast
- 根据响应的 UrlFetchApp.fetch() 创建一个新文件
- 使用 blob 确保在执行导出为 pdf 之前完成电子表格的格式化。
示例:
function crearPdf() {
const ssID = SpreadsheetApp.getActiveSpreadsheet().getId();
const destFolder = DriveApp.getFileById(ssID).getParents().next();
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getActiveSheet();
const sourceRange = ws.getRange(1,1,ws.getMaxRows(),ws.getMaxColumns());
const numFac = ws.getRange("D20");
const sourceValues = sourceRange.getDisplayValues();
const dest = SpreadsheetApp.create("temp " + Date());
const destSheet = dest.getSheets()[0];
const destRange = destSheet.getRange(1,destSheet.getMaxRows(),destSheet.getMaxColumns());
destRange.setValues(sourceValues);
SpreadsheetApp.flush();
styleSheet(destSheet);
SpreadsheetApp.flush();
const destId = dest.getId();
// THIS IS NEW
var token = ScriptApp.getOAuthToken();
var url = "https://docs.google.com/spreadsheets/d/"+destId+"/export?";
var url_ext = 'exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
// adjust the following parametrers as desired
+ '&size=letter' // paper size legal / letter / A4
+ '&portrait=true' // orientation,false for landscape
+'&top_margin=0.50'
+'&bottom_margin=0.50'
+'&left_margin=0.50'
+'&right_margin=0.50'
+ '&gridlines=false'
// other parameters if you need
/*
+ '&fitw=true&source=labnol' // fit to page width,false for actual size
+ '&sheetnames=false&printtitle=false' // hide optional headers and footers
+ '&pagenumbers=false' // hide page numbers
+ '&fzr=false' // do not repeat row headers (frozen rows) on each page
+ '&gid='; // the sheet's Id
*/
var response = UrlFetchApp.fetch(url + url_ext,{
headers: {
'Authorization': 'Bearer ' + token
},muteHttpExceptions:true
});
const newFile = DriveApp.createFile(response.getBlob().setName("Factura " + numFac.getValue() + ' - ' + " '21"));
// const fileUrl = newFile.getDownloadUrl();
newFile.moveTo(destFolder);
// fileToPDF.setTrashed(true);
}
,
嗯,事实证明,您使用 Apps 脚本格式化电子表格的顺序很重要,这就是我丢失一些格式的原因。
我设计格式的方式涉及使用多个单元格数组来应用某些调整,例如合并单元格、设置边框、设置粗体等,并使用 for-of 循环遍历每个单元格范围。碰巧的是,如果您有其他调整要做,这些 for-of 循环似乎必须是您要做的第一件事,否则它们似乎不起作用。
感谢大家的帮助!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。