谷歌应用脚本 getAs('application/pdf') 布局

7
我正在使用一个我在这里找到的应用脚本从电子表格生成PDF文件。该脚本使用了经典的getAs('application/pdf')方法,效果很好。
问题是,以这种方式生成的PDF文档具有不必要的不对称边距(右侧较大,左侧较窄)。我只想让页面居中。奇怪的是,当我从Google菜单文件->打印(或Ctrl + P)中打印时,文档会正确地居中显示。
我的代码如下:
function CreaPDF() {
  //The function prints an invoice to PDF. First it copies spreadsheet to a new document.
  //Deletes all sheet except the one to print. Saves it to PDF. 
  //It overwrites any existing doc with same name.

  var sourceSpreadsheet = SpreadsheetApp.getActive();          
  var sheetName = "Factura";
  var folderID = getParentFolder(); // Folder id to save in a folder.
  var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
  var folder = DriveApp.getFolderById(folderID); 
  var numf = sourceSpreadsheet.getRangeByName("NumeroFactura").getValue();
  var anof = numf.split("/",2);   // Seeks number and year -> filename 

  var pdfName = anof[1] +"_Factura_" + anof[0]+ "_Dra_Salazar"; // Nombre del documento;

  //Copy whole spreadsheet 2 temporary sheet
  var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder))

  //delete redundant sheets
  var sheets = destSpreadsheet.getSheets();
  for (i = 0; i < sheets.length; i++) {
    if (sheets[i].getSheetName() != sheetName){
    destSpreadsheet.deleteSheet(sheets[i]);
    }
  }

  //Deletes pdf if already exists
  var files = DriveApp.getFilesByName(pdfName);
  while (files.hasNext()) {
   files.next().setTrashed(true);
   }
  var destSheet = destSpreadsheet.getSheets()[0];
  //repace cell values with text (to avoid broken references)
  var sourceRange = sourceSheet.getRange(1, 1,sourceSheet.getMaxRows(),sourceSheet.getMaxColumns());

  var sourcevalues = sourceRange.getDisplayValues();
  var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
  destRange.setValues(sourcevalues);

  SpreadsheetApp.getActiveSpreadsheet().toast('Creando PDF');

  //save to pdf
  var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
  var newFile = folder.createFile(theBlob);

  //Delete the temporary sheet
  DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
  return true;
}

我打印时的设置如下:

  • 纸张大小: "A4"
  • 缩放比例: "正常" (我也试过:"适合宽度"和"适合页面")
  • 方向: "竖向"
  • 边距: "正常"

Google帮助论坛中可以看出,谷歌打印的旧问题似乎仍然存在。总的来说,似乎无法保存打印设置,也没有办法传递任何参数给getAs('application/pdf')方法。因此,我认为该方法(以及菜单打印选项)使用的是默认参数,不能进行修改。有什么解决办法吗?"打印或更改页面设置"帮助页面并没有提供太多帮助。

非常感谢。


这个答案有一些更多的参数,例如如何设置边距:https://dev59.com/clYO5IYBdhLWcg3wRfd-#46312255 - tomb
2个回答

8

尝试使用基于 https://ctrlq.org/code/19869-email-google-spreadsheets-pdf 的解决方案。

使用导出URL参数,您可以设置所需的结果PDF选项。此外,您还可以设置要导出的特定工作表的ID,因此您不再需要复制整个电子表格。

function CreaPDF() {
  //The function prints an invoice to PDF. First it copies spreadsheet to a new document.
  //Deletes all sheet except the one to print. Saves it to PDF. 
  //It overwrites any existing doc with same name.

  var sourceSpreadsheet = SpreadsheetApp.getActive();          
  var sheetName = "Factura";
  var folderID = getParentFolder(); // Folder id to save in a folder.
  var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
  var folder = DriveApp.getFolderById(folderID); 
  var numf = sourceSpreadsheet.getRangeByName("NumeroFactura").getValue();
  var anof = numf.split("/",2);   // Seeks number and year -> filename 

  var pdfName = anof[1] +"_Factura_" + anof[0]+ "_Dra_Salazar"; // Nombre del documento;

  SpreadsheetApp.getActiveSpreadsheet().toast('Creando PDF');

  // export url
  var url = 'https://docs.google.com/spreadsheets/d/'+sourceSpreadsheet.getId()+'/export?exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
  + '&size=A4'                           // paper size legal / letter / A4
  + '&portrait=true'                     // orientation, false for landscape
  + '&fitw=false'                        // fit to page width, false for actual size
  + '&sheetnames=false&printtitle=false' // hide optional headers and footers
  + '&pagenumbers=false&gridlines=false' // hide page numbers and gridlines
  + '&fzr=false'                         // do not repeat row headers (frozen rows) on each page
  + '&gid='+sourceSheet.getSheetId();    // the sheet's Id

  var token = ScriptApp.getOAuthToken();

  // request export url
  var response = UrlFetchApp.fetch(url, {
    headers: {
      'Authorization': 'Bearer ' +  token
    }
  });

  var theBlob = response.getBlob().setName(pdfName+'.pdf');

  // delete pdf if already exists
  var files = folder.getFilesByName(pdfName);
  while (files.hasNext())
  {
    files.next().setTrashed(true);
  }

  // create pdf
  var newFile = folder.createFile(theBlob);

  return true;
}

非常感谢您的帮助。看起来没问题,但是PDF文件应该存储在哪里?我运行了代码,但找不到结果。有没有设置目标文件夹的方法?还是只是父文件夹? - Francisco Javier
文件创建的代码没有改变:var newFile = folder.createFile(theBlob);,只是现在从UrlFetchApp响应中获取文件源(theBlob)。 - Kos
好的,测试过了,它可以工作。我的谷歌账户权限有些问题。非常棒的解决方案! - Francisco Javier
这个方案有效,除了一个参数:&pagenumbers。也就是说,当设置为“true”时,我得不到页码。我还尝试了&pagemun,但对我来说也不起作用。有没有关于如何获得页码的建议?它们与用户界面一起放在页脚中。我也找不到如何使页脚中的其他项目工作:日期/时间戳。我应该单独发布这个问题吗? - Tony M

3

受 Kos 解决方案启发。

我使用 Chrome 开发者工具跟踪了由 Google 电子表格“下载为”GUI 创建的请求。当您在“打印设置”中单击“下一步”时,Chrome 发送 post 请求并获取 PDF 文件。

废话不多说,以下是我的代码。

var sourceSpreadsheet = SpreadsheetApp.getActive();
var url = 'https://docs.google.com/spreadsheets/d/' + sourceSpreadsheet.getId() + '/pdf?id=' + sourceSpreadsheet.getId()
var formData = {
    'a': 'false',
    'pc': '[null,null,null, ... SOME VERY LONG LIST OF NULLS AND NUMBERS ... 166]],[[0,5]]]],0]',
    'gf': '[]'
};
var token = ScriptApp.getOAuthToken(); // doesn't needed when sheet is public
var options = {
        'method': 'post',
        'payload': formData,
        'muteHttpExceptions': true,
        headers: {
            'Authorization': 'Bearer ' + token
        }
    };
var response = UrlFetchApp.fetch(url, options)

var theBlob = response.getBlob().setName('YourPDFName.pdf');


您可以按照以下步骤填写formData['pc']:
1. 在Network选项卡中记录请求。
2. 点击pdf?id=blahblah第二步的图片
3. 向下滚动以找到Form Data第三步的图片
4. 复制表单数据并填写您的代码。

表单数据如下:
[null,null,null,null,null,null,null,null,null,0,[["$Sheet_id"]],10000000,null,null,null,null,null,null,null,null,null,null,null,null,null,null,$day_after_30-12-1899,null,null,[$note,null,1,$note,0,0,0,0,$fixed_row,1,1,1,$headers,$footers,1,1],["A4",1,2,1,[0.75,0.75,0.7,0.7]],null,0,[["$Sheet_id",[[26,52]....],[[0,5]]]],0]
还有许多其他参数,但我无法找到它们。此外,参数可能不正确,因为我是通过检查更改后的值来确定它们的值的。

当您更改$day_after_30-12-1899时,PDF中打印的日期会更改。

您可以自定义页眉/页脚。它们是UTF16编码的,并且具有几个控制字符。

| Name in `Download as` GUI | character | 
|---------------------------|-----------|
| page number A             | \uee12    |
| page number B             | \uee15    |
| page number C             | \uee16    |
| Workbook title            | \uee10    |
| sheet name                | \uee11    |


|   meaning in date & time  | character | 
|---------------------------|-----------|
| date formatstr start      | \uee13    |
| year                      | yyyy      |
| month                     | M         |
| day                       | d         |
| date formatstr end        | \uee14    |
|                           |           |
| time formatstr start      | \uee17    |
| am or pm                  | am/pm     |
| hour in 12hour clock      | h         |
| minute                    | mm        |

你可以像这样使用时间和日期 YourText\uee13yy. M. d\uee14Yourtext

我建议使用 GUI 创建 formData ['pc'] 并修改$day_after_30-12-1899

欢迎纠正。虽然我不是英语母语人士,但有很多笨拙/不正确的表达。


我该如何将其用于我的自定义页脚?抱歉,我是GAS的新手。我正在尝试找到一种方法,在使用GAS导出PDF时使我的gsheet显示页脚。当我将$footer更改为商务地址时,它仍然不会出现在PDF中。 - dell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接