使用Google App Scripts如何将演示文稿中的单个幻灯片导出为PDF?

huangapple go评论69阅读模式
英文:

How to export an individual slide from a presentation as a PDF using Google App Scripts?

问题

抱歉,你提供的代码中有一些HTML实体字符,我会将其删除,然后为你提供翻译:

function Email3UpPDF() {
  Logger.log("Emailing!");
  var Sapp = SpreadsheetApp;
  var FS = Sapp.getActiveSpreadsheet().getSheetByName("3UP Submissions");
  var ssID = "10Up_PcLxVopXont9Qcu-yk-PrFGWfWPQ3ETsgys4v0Y";
  var shID = "g2580bcdba17_0_22";
  
  var Addy1 = FS.getRange("N" + FS.getLastRow()).getValue();
  
  var requestData = {"method": "GET", "headers":{"Authorization":"Bearer "+ScriptApp.getOAuthToken()}}; 
  var url = "https://docs.google.com/presentation/d/" + ssID + "/export?format=pdf&id=" + shID; //This creates the PDF export url
  var result = UrlFetchApp.fetch(url, requestData);  
  var contents = result.getContent();
  
  MailApp.sendEmail(Addy1,"Local Sign Template","Here is your custom sign Template.", {attachments:[{fileName: "LST3UP.pdf", content:contents, mimeType:"application/pdf"}]});
}

请注意,你提到尝试将演示文稿ID和幻灯片ID替换到ssIDshID变量中,但遇到了404错误。你提到,当你将演示文稿ID同时放在ssIDshID变量中时,程序成功运行,但会发送包含两张幻灯片的2页PDF。你的意图是只有一页幻灯片。如果你需要帮助解决这个问题,可以提供更多关于如何选择特定幻灯片的信息。

英文:

I have a Google Spreadsheet attached to a Form. On Form Submit, a script takes information from the submission and applies it into carefully placed textboxes in a Google Slide. There are two separate forms which are used to submit information into two separate slides on the SAME presentation.

After the information is entered, the script runs a function that is supposed to export the edited slide ONLY as a PDF and email it to an address provided on the Google Form.

I had a similar setup on a different program of mine and had someone from an online forum help me write the export PDF / Email code. The code they helped me write was for exporting and emailing an individual Spreadsheet sheet.

Here is the email code that I copied from my Spreadsheet program.

function Email3UpPDF () {
  Logger.log("Emailing!");
  var Sapp = SpreadsheetApp;
  var FS = Sapp.getActiveSpreadsheet().getSheetByName("3UP Submissions");
  var ssID = "10Up_PcLxVopXont9Qcu-yk-PrFGWfWPQ3ETsgys4v0Y"
  var shID = "g2580bcdba17_0_22"
  
  var Addy1 = FS.getRange("N"+FS.getLastRow()).getValue();
  
  var requestData = {"method": "GET", "headers":{"Authorization":"Bearer "+ScriptApp.getOAuthToken()}}; 
  var url = "https://docs.google.com/presentation/d/"+ ssID + "/export?format=pdf&id="+shID; //This creates the PDF export url
  var result = UrlFetchApp.fetch(url , requestData);  
  var contents = result.getContent();
  
  MailApp.sendEmail(Addy1,"Local Sign Template" ,"Here is your custom sign Template.", {attachments:[{fileName: "LST3UP.pdf", content:contents, mimeType:"application/pdf"}]});

}

My HOPE was that I could simply substitute the Spreadsheet ID with a Presentation ID, and the Sheet ID with a Slide ID. When I tried that I was met with this error:

> Exception: Request failed for https://docs.google.com returned code 404. Truncated server response: <!DOCTYPE html><html lang="en"><head><meta name="description" content="Web word processing, presentations and spreadsheets"><meta name="viewport" c... (use muteHttpExceptions option to examine full response)

The error points to line 13: var contents = result.getContent();

I should note that when I put JUST the Presentation ID in both the ssID and the shID variables, the program runs successfully but ends up sending a 2 page PDF with both slides on it. Which makes sense to me. My intention is to only have one slide though.

答案1

得分: 2

Modified script 1:

function Email3UpPDF() {
  Logger.log("Emailing!");
  var Sapp = SpreadsheetApp;
  var FS = Sapp.getActiveSpreadsheet().getSheetByName("3UP Submissions");
  var Addy1 = FS.getRange("N" + FS.getLastRow()).getValue();

  var presentationId = "10Up_PcLxVopXont9Qcu-yk-PrFGWfWPQ3ETsgys4v0Y"; // Google Slide的文件ID。
  var pageObjectIds = ["g2580bcdba17_0_22"]; // Google Slide的页面对象ID。
  var temp = DriveApp.getFileById(presentationId).makeCopy("temp");
  var s = SlidesApp.openById(temp.getId());
  s.getSlides().forEach(function (s) {
    if (!pageObjectIds.includes(s.getObjectId())) {
      s.remove();
    }
  });
  s.saveAndClose();
  var contents = temp.getBlob().getBytes();
  temp.setTrashed(true);

  MailApp.sendEmail(Addy1, "本地签名模板", "这是您的定制签名模板。", { attachments: [{ fileName: "LST3UP.pdf", content: contents, mimeType: "application/pdf" }] });
}

Modified script 2:

在此修改中,特定页面从Google幻灯片中检索并使用pdf-lib的JavaScript库转换为PDF格式。

// 参考:https://gist.github.com/tanaikech/9d77f7d634d2d31914396d7dc84b79c3
async function exportSpecificPages_(fileId, pageNumbers) {
  const cdnjs = "https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js";
  eval(UrlFetchApp.fetch(cdnjs).getContentText()); // 加载pdf-lib
  const setTimeout = function (f, t) {
    Utilities.sleep(t);
    return f();
  }
  const blob = DriveApp.getFileById(fileId).getBlob();
  const pdfDoc = await PDFLib.PDFDocument.create();
  const pdfData = await PDFLib.PDFDocument.load(new Uint8Array(blob.getBytes()));
  const pages = await pdfDoc.copyPages(pdfData, [...Array(pdfData.getPageCount())].map((_, i) => i));
  pages.forEach((page, i) => {
    if (pageNumbers.includes(i + 1)) {
      pdfDoc.addPage(page);
    }
  });
  const bytes = await pdfDoc.save();
  return [...new Int8Array(bytes)];
}

// 请运行此函数。
async function Email3UpPDF() {
  Logger.log("Emailing!");
  var Sapp = SpreadsheetApp;
  var FS = Sapp.getActiveSpreadsheet().getSheetByName("3UP Submissions");
  var Addy1 = FS.getRange("N" + FS.getLastRow()).getValue();

  var presentationId = "10Up_PcLxVopXont9Qcu-yk-PrFGWfWPQ3ETsgys4v0Y"; // Google Slide的文件ID。
  var pageObjectIds = ["g2580bcdba17_0_22"]; // Google Slide的页面对象ID。

  var pages = SlidesApp.openById(presentationId).getSlides().reduce(function (ar, s, i) {
    if (pageObjectIds.includes(s.getObjectId())) {
      ar.push(i + 1);
    }
    return ar;
  }, []);
  var contents = await exportSpecificPages_(presentationId, pages);

  MailApp.sendEmail(Addy1, "本地签名模板", "这是您的定制签名模板。", { attachments: [{ fileName: "LST3UP.pdf", content: contents, mimeType: "application/pdf" }] });
}

注意:

  • 我认为上述脚本有效。但在这种情况下,当您直接复制并粘贴从https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js检索的JavaScript到您的Google Apps Script项目中时,可以减少加载的处理成本。
英文:

I'm worried that your endpoint might not be able to used for exporting the specific slide from the Google Slide as a PDF format. So, in your situation, how about the following modification?

Modified script 1:

function Email3UpPDF() {
  Logger.log(&quot;Emailing!&quot;);
  var Sapp = SpreadsheetApp;
  var FS = Sapp.getActiveSpreadsheet().getSheetByName(&quot;3UP Submissions&quot;);
  var Addy1 = FS.getRange(&quot;N&quot; + FS.getLastRow()).getValue();

  var presentationId = &quot;10Up_PcLxVopXont9Qcu-yk-PrFGWfWPQ3ETsgys4v0Y&quot;; // File ID of Google Slide.
  var pageObjectIds = [&quot;g2580bcdba17_0_22&quot;]; // Page object ID of Googe Slide.
  var temp = DriveApp.getFileById(presentationId).makeCopy(&quot;temp&quot;);
  var s = SlidesApp.openById(temp.getId());
  s.getSlides().forEach(s =&gt; {
    if (!pageObjectIds.includes(s.getObjectId())) {
      s.remove();
    }
  });
  s.saveAndClose();
  var contents = temp.getBlob().getBytes();
  temp.setTrashed(true);

  MailApp.sendEmail(Addy1, &quot;Local Sign Template&quot;, &quot;Here is your custom sign Template.&quot;, { attachments: [{ fileName: &quot;LST3UP.pdf&quot;, content: contents, mimeType: &quot;application/pdf&quot; }] });
}
  • In this modification, the current Google Slide is copied as a temporal file. And, all slides except for the specific slide are removed. And, the temporal Google Slide is exported as a PDF format. I used this flow because I'm worried that your Google Slide might have a specific theme.

  • In this modification, when you modify var pageObjectIds = [&quot;g2580bcdba17_0_22&quot;]; to var pageObjectIds = [&quot;g2580bcdba17_0_22&quot;, &quot;### other page ID ###&quot;,,,];, you can include several pages in a PDF file.

Modified script 2:

In this modification, the specific pages are retrieved from Google Slide and converted to a PDF format using a Javascript library of pdf-lib.

// Ref: https://gist.github.com/tanaikech/9d77f7d634d2d31914396d7dc84b79c3
async function exportSpecificPages_(fileId, pageNumbers) {
  const cdnjs = &quot;https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js&quot;;
  eval(UrlFetchApp.fetch(cdnjs).getContentText()); // Load pdf-lib
  const setTimeout = function (f, t) {
    Utilities.sleep(t);
    return f();
  }
  const blob = DriveApp.getFileById(fileId).getBlob();
  const pdfDoc = await PDFLib.PDFDocument.create();
  const pdfData = await PDFLib.PDFDocument.load(new Uint8Array(blob.getBytes()));
  const pages = await pdfDoc.copyPages(pdfData, [...Array(pdfData.getPageCount())].map((_, i) =&gt; i));
  pages.forEach((page, i) =&gt; {
    if (pageNumbers.includes(i + 1)) {
      pdfDoc.addPage(page);
    }
  });
  const bytes = await pdfDoc.save();
  return [...new Int8Array(bytes)];
}

// Please run this function.
async function Email3UpPDF() {
  Logger.log(&quot;Emailing!&quot;);
  var Sapp = SpreadsheetApp;
  var FS = Sapp.getActiveSpreadsheet().getSheetByName(&quot;3UP Submissions&quot;);
  var Addy1 = FS.getRange(&quot;N&quot; + FS.getLastRow()).getValue();

  var presentationId = &quot;10Up_PcLxVopXont9Qcu-yk-PrFGWfWPQ3ETsgys4v0Y&quot;; // File ID of Google Slide.
  var pageObjectIds = [&quot;g2580bcdba17_0_22&quot;]; // Page object ID of Googe Slide.

  var pages = SlidesApp.openById(presentationId).getSlides().reduce((ar, s, i) =&gt; {
    if (pageObjectIds.includes(s.getObjectId())) {
      ar.push(i + 1);
    }
    return ar;
  }, []);
  var contents = await exportSpecificPages_(presentationId, pages);

  MailApp.sendEmail(Addy1, &quot;Local Sign Template&quot;, &quot;Here is your custom sign Template.&quot;, { attachments: [{ fileName: &quot;LST3UP.pdf&quot;, content: contents, mimeType: &quot;application/pdf&quot; }] });
}

Note:

答案2

得分: 1

替代方法

我找到了这篇相关的帖子,你可以利用其中提到的特定方法来解决这个问题。我已经对你的脚本进行了微调,并在我的端口进行了快速测试。

示例微调脚本

function extractPdfData() {
  Logger.log("Emailing!");

  //Replace this with your API key, this is my temporary limited 'api key' for testing purposes.
  const apiSecret = 'ZQ2A9pbkh6w3xuBY'; 
  var Sapp = SpreadsheetApp;
  var FS = Sapp.getActiveSpreadsheet().getSheetByName("3UP Submissions");
  var ssID = '10Up_PcLxVopXont9Qcu-yk-PrFGWfWPQ3ETsgys4v0Y';

  //define the number of slide page(s) that you want. E.g. slide number '2'
  var pages = [2].join('%2C');

  var Addy1 = FS.getRange("N"+FS.getLastRow()).getValue();
  var requestData = { "method": "GET", "headers": { "Authorization": "Bearer " + ScriptApp.getOAuthToken() } };
  var pdfUrl = "https://docs.google.com/presentation/d/" + ssID + "/export?format=pdf";
  var slidePDF = UrlFetchApp.fetch(pdfUrl, requestData).getBlob();

  //Retrieve the number of PDF page(s) you only want to attach on your email.
  var pdfPages = processPDF(apiSecret, pages, slidePDF);

  //Send the page(s) in your email
  pdfPages.forEach(page => MailApp.sendEmail(Addy1,"Local Sign Template","Here is your custom sign Template.", {attachments:[{fileName: "LST3UP.pdf", content:UrlFetchApp.fetch(page.Url).getContent(), mimeType:"application/pdf"}]}));
}

//Utilizing the 'convertapi' method
processPDF(apiSecret, pages, slidePDF) {
  var url = `https://v2.convertapi.com/convert/pdf/to/split?Secret=${apiSecret}&amp;ExtractPages=${pages}&amp;StoreFile=true`;
  var options = {
    method: "post",
    payload: { File: slidePDF },
  }
  var res = UrlFetchApp.fetch(url, options);
  var rawData = JSON.parse(res.getContentText());

  return rawData.Files;
}

演示

虚拟幻灯片。
例如:您只希望将幻灯片编号2作为唯一的PDF文件发送给您的收件人。

使用Google App Scripts如何将演示文稿中的单个幻灯片导出为PDF?

运行脚本后。
我的虚拟电子邮件账户收到了这封电子邮件:

使用Google App Scripts如何将演示文稿中的单个幻灯片导出为PDF?

整个PDF附件只包含幻灯片编号2:

使用Google App Scripts如何将演示文稿中的单个幻灯片导出为PDF?

英文:

Alternative Method

I have found this related post that you could utilise to work around this matter using a specific method mentioned in the post. I have tweaked your script below & performed a quick test run on my end.

Sample Tweaked Script

function extractPdfData() {
Logger.log(&quot;Emailing!&quot;);
//Replace this with your API key, this is my temporary limited &#39;api key&#39; for testing purposes.
const apiSecret = &#39;ZQ2A9pbkh6w3xuBY&#39;; 
var Sapp = SpreadsheetApp;
var FS = Sapp.getActiveSpreadsheet().getSheetByName(&quot;3UP Submissions&quot;);
var ssID = &#39;10Up_PcLxVopXont9Qcu-yk-PrFGWfWPQ3ETsgys4v0Y&#39;;
//define the number of slide page(s) that you want. E.g. slide number &#39;2&#39;
var pages = [2].join(&#39;%2C&#39;);
var Addy1 = FS.getRange(&quot;N&quot;+FS.getLastRow()).getValue();
var requestData = { &quot;method&quot;: &quot;GET&quot;, &quot;headers&quot;: { &quot;Authorization&quot;: &quot;Bearer &quot; + ScriptApp.getOAuthToken() } };
var pdfUrl = &quot;https://docs.google.com/presentation/d/&quot; + ssID + &quot;/export?format=pdf&quot;;
var slidePDF = UrlFetchApp.fetch(pdfUrl, requestData).getBlob();
//Retrieve the number of PDF page(s) you only want to attach on your email.
var pdfPages = processPDF(apiSecret, pages, slidePDF);
//Send the page(s) in your email
pdfPages.forEach(page =&gt; MailApp.sendEmail(Addy1,&quot;Local Sign Template&quot; ,&quot;Here is your custom sign Template.&quot;, {attachments:[{fileName: &quot;LST3UP.pdf&quot;, content:UrlFetchApp.fetch(page.Url).getContent(), mimeType:&quot;application/pdf&quot;}]}));
}
//Utilizing the &#39;convertapi&#39; method
processPDF(apiSecret, pages, slidePDF) {
var url = `https://v2.convertapi.com/convert/pdf/to/split?Secret=${apiSecret}&amp;ExtractPages=${pages}&amp;StoreFile=true`;
var options = {
method: &quot;post&quot;,
payload: { File: slidePDF },
}
var res = UrlFetchApp.fetch(url, options);
var rawData = JSON.parse(res.getContentText());
return rawData.Files;
}

Demo

> Dummy Slide. <br> E.g. you want the slide number 2 to be the only PDF file sent to your recipient.

使用Google App Scripts如何将演示文稿中的单个幻灯片导出为PDF?

> After running the script. <br> My dummy email account received this email:

使用Google App Scripts如何将演示文稿中的单个幻灯片导出为PDF?

> The whole PDF attachment is only the slide number 2:

使用Google App Scripts如何将演示文稿中的单个幻灯片导出为PDF?

huangapple
  • 本文由 发表于 2023年7月14日 05:56:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76683483.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定