I have written some code to automatically add in a user's name to a template Google Slides file. This template is essentially a certificate, and I'm trying to automate the generation of said certificate for each user.
Unfortunately, when I try to convert the Slides file to a PDF, it converts the slide without the user's name - e.g. basically just the template file is exported. It's definitely pulling in the correct file id, but still not working. The only problem I can think of is that the presentation hasn't saved the changes by the time the code gets the blob data from DriveApp
.
function buildCertificate() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1'),
rows = sheet.getDataRange().getValues(),
template = DriveApp.getFileById('some file id'),
destination = DriveApp.getFolderById('some folder id'),
i = 1;
while (i < rows.length) {
if (rows[i][3] != 'Y') {
var file = template.makeCopy(rows[i][0] + ' ' + rows[i][1], destination),
id = file.getId(),
slide = SlidesApp.openById(id).getSlides()[0],
shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 60, 207, 600, 110),
textRange = shape.getText(),
textStyle = textRange.getTextStyle();
textRange.setText([rows[i][0] + ' ' + rows[i][1]]);
textStyle.setFontSize(40);
textStyle.setForegroundColor('#F9B300');
var paragraphStyle = textRange.getParagraphs()[0].getRange().getParagraphStyle();
paragraphStyle.setParagraphAlignment(SlidesApp.ParagraphAlignment.CENTER);
var theBlob = DriveApp.getFileById(id).getBlob().getAs('application/pdf').setName('test'),
newFile = DriveApp.getFolderById("some folder id").createFile(theBlob);
}
sheet.getRange(i + 1, 4).setValue('Y');
i++;
}
}
Per the Apps Script SlidesApp
documentation, you can force any pending writes to the Slides Presentation
by closing it with saveAndClose()
. Closing of open presentations is automatically performed when the script execution ends, but for use cases such as yours, this automatic flush occurs too late to be useful:
saveAndClose()
:
saves the currentPresentation
. Causes pending updates to be flushed and applied.
ThesaveAndClose()
method is automatically invoked at the end of script execution for each openPresentation
, even if the script execution terminated with an error.
A closedPresentation
cannot be edited. Use one of the open methods onSlidesApp
to reopen a given presentation for editing.
The presentation your code uses is bound in your variable slide
, so altering your loop structure to close this prior to your DriveApp
code will ensure the Blob
data reflects the latest changes.
while (i < rows.length) {
if (rows[i][3] != 'Y') {
var file = template.makeCopy(rows[i][0] + ' ' + rows[i][1], destination),
id = file.getId(),
presentation = SlidesApp.openById(id),
slide = presentation.getSlides()[0],
shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 60, 207, 600, 110),
textRange = shape.getText(),
textStyle = textRange.getTextStyle();
textRange.setText([rows[i][0] + ' ' + rows[i][1]]);
textStyle.setFontSize(40);
textStyle.setForegroundColor('#F9B300');
var paragraphStyle = textRange.getParagraphs()[0].getRange().getParagraphStyle();
paragraphStyle.setParagraphAlignment(SlidesApp.ParagraphAlignment.CENTER);
// Flush the changes we've made to the instantiated template presentation.
presentation.saveAndClose();
// Reopen the file with DriveApp -- could perhaps use the existing `file` reference, e.g.:
// var theBlob = file.getAs(MimeType.PDF).setName('test');
var theBlob = DriveApp.getFileById(id).getAs(MimeType.PDF).setName('test');
// Create the PDF in the desired Drive folder.
DriveApp.getFolderById("some folder id").createFile(theBlob);
}
sheet.getRange(i + 1, 4).setValue('Y');
i++;
}