Я написал свое первое веб-приложение с помощью Google App Maker, который редактирует файл электронной таблицы, чтобы создать отчет, настроенный для пользователя, и позволяет пользователю загрузить копию отчета. Программа действительно простая, просто:
- вводит имя учетной записи пользователя в определенную ячейку документа Sheets,
- очищает электронную таблицу (которая динамически обновляет ее в соответствии с именем учетной записи пользователя),
- создает PDF обновленной электронной таблицы, которая представляет собой отчет о результатах теста,
- и позволяет пользователю загрузить pdf своего отчета.
Все работает нормально, кроме случаев, когда несколько студентов одновременно запускают веб-приложение. Если это произойдет, некоторые ученики получат отчет другого ученика.
Насколько я понимаю, изменения, внесенные в документ Google Sheets серверным скриптом в моем веб-приложении, не будут сохранены в документе, если я не сохраню их намеренно. Поэтому я надеялся, что одновременные пользователи не будут влиять друг на друга.
Я действительно застрял в том, как решить эту проблему. Вот мой код:
Скрипт запуска приложения (запускается сразу после загрузки приложения):
downloadReport();
Клиентский скрипт
function showDownloadLink(downloadURL){
console.log(downloadURL);
var spinnerWidgets = app.pages.appPage.descendants.progressSpinner;
spinnerWidgets.visible = false;
var linkWidgets = app.pages.appPage.descendants.downloadPDFLink;
linkWidgets.href = downloadURL;
linkWidgets.visible = true;
}
function downloadReport() {
var status = app.pages.appPage.descendants.downloadStatus;
var user = app.user.username;
var downloadLink = google.script.run.withSuccessHandler(showDownloadLink)
.createDownload(user);
}
Серверный скрипт:
// Spreadsheet file must have a tab called Report
function createDownload(user) {
///*
// SET SPREADSHEET FILE ID
var ssID = 'xxxxxxxxx_SHEETS_FILE_ID_GOES_HERE_xxxxxxxxxx';
var ss = SpreadsheetApp.openById(ssID);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = ss.getSheetByName("Report");
SpreadsheetApp.setActiveSheet(sheet);
// determines timezone
var timeZone = Session.getScriptTimeZone();
// generates the timestamp and stores in variable formattedDate as year-month-date hour-minute-second
// gets the destination folder using spreadsheet location (folder)
var ssFolder = DriveApp.getFileById(ssID).getParents();
var folder = ssFolder.next();
var folderId = folder.getId();
var destination = DriveApp.getFolderById(folderId);
// Logger.log('destination name: ' + destination.getName());
// generates the timestamp and stores in variable formattedDate as year-month-date hour-minute-second
var formattedDate = Utilities.formatDate(new Date(), timeZone , "yyyy-MM-dd' 'HH:mm:ss");
// gets the name of the original file and appends the ID and the timestamp stored in formattedDate
var PDFfileName = ss.getName()+formattedDate+ "-" + user;
// inputs ID into daughter spreadsheet reference cell to personalize report
ss.getSheetByName("Report").getRange(3, 1).setValue(user); // Puts ID into cell A3
SpreadsheetApp.flush(); // Updates the spreadsheet with changes and refreshes report
// Export URL
var url = "https://docs.google.com/spreadsheets/d/SS_ID/export?".replace("SS_ID", ssID);
var url_ext = 'exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
+ '&size=letter' // paper size legal / letter / A4
+ '&portrait=true' // orientation, false for landscape
+ '&top_margin=0.30' // sets top margin of pdf file
+ '&bottom_margin=0.28' // sets bottom margin of pdf file
+ '&left_margin=0.43' // sets left margin of pdf file
+ '&right_margin=0.43' // sets right margin of pdf file
+ '&fitw=true' // 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='; // the sheet's Id
var token = ScriptApp.getOAuthToken();
// Take snapshot and save to PDF
var response = UrlFetchApp.fetch(url + url_ext + sheet.getSheetId(), {
headers: {
'Authorization': 'Bearer ' + token
}
});
//convert the response to a blob and store in our array
var blob = response.getBlob().getAs('application/pdf').setName(PDFfileName + '.pdf');
var newPDFFile = folder.createFile(blob);
newPDFFile.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
// Link URL
var downloadURL = "https://drive.google.com/uc?export=download&id="+newPDFFile.getId();
return downloadURL;
}