В предыдущей записи я подготовил все необходимые поля к заполнению в шаблоне.
Теперь финал. И первое что необходимо — получить список полей в объект.
Объект с данными
function arrToObj() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName('details');
const dataArr = ws.getDataRange().getDisplayValues()
const objData = Object.fromEntries(dataArr);
return objData;
}
Что здесь происходит?
Помимо обращения к листу с деталями:
Я получаю массив через getDisplayValues() — const dataArr = ws.getDataRange().getDisplayValues()
В чем разница?
Если делать getValues() :
Дата и суммы будут системными. Если же делать getDisplayValues(), то суммы и дата будут ровно такими, как отражено на листе гугл таблицы (что сильно упрощает жизнь):
что конечно же намного удобнее.
Основная магия
Что нужно делать, пошагово:
- Получать файл темплейта
- Копировать его во временную папку
- Заменять в копии темплейта все поля
- Сохранять копию темлейта как pdf в отдельную папку pdf
- Удалять копию темплейта
Как видно из списка выше, мне надо создать дополнительные папки:
Получение и копирование темплейта в папку, делается следующим образом:
function myFunction() {
const tempFileID = "FileID"; // ID файла базового темплейта
const tempFolder = DriveApp.getFolderById("TempFolderId"); // папка в которой будут создаваться копии базового темплейта
const pdfFolder = DriveApp.getFolderById("PDFFolderID"); // папка, в которой будут создаваться заполненные пдф-файлы
//копируeм базовый файл
const docFile = DriveApp.getFileById(tempFileID);
const copiedFile = docFile.makeCopy(tempFolder);
}
Файл скопирован. Теперь надо получить объект с тем, что будет заменено.
const details = arrToObj(); //получили объект с данными
Т.е. вызвали функцию, которая в свою очередь «собирает» все данные в объект.
Открываю скопированный темплейт и заменяю в нем поля
//открываем копию, заменяем, сохраняем и закрываем
const copiedDocFile = DocumentApp.openById(copiedFile.getId());
const body = copiedDocFile.getBody();
body.replaceText("{ourCompany}", details.ourCompany);
body.replaceText("{ourCompanyAddress}", details.ourCompanyAddress);
body.replaceText("{ourCompanyBank}", details.ourCompanyBank);
body.replaceText("{ourCompanyBankBIC}", details.ourCompanyBankBIC);
body.replaceText("{ourCompanyBankAcc}", details.ourCompanyBankAcc);
body.replaceText("{ourCompanyINN}", details.ourCompanyINN);
body.replaceText("{ourCompanyKPP}", details.ourCompanyKPP);
body.replaceText("{ourCompanyAcc}", details.ourCompanyAcc);
body.replaceText("{invoiceNum}", details.invoiceNum);
body.replaceText("{invoiceDate}", details.invoiceDate);
body.replaceText("{buyer}", details.buyer);
body.replaceText("{buyerDoc}", details.buyerDoc);
body.replaceText("{goods}", details.goods);
body.replaceText("{edIzm}", details.edIzm);
body.replaceText("{qty}", details.qty);
body.replaceText("{price}", details.price);
body.replaceText("{totalAmount}", details.totalAmount);
body.replaceText("{vat}", details.vat);
body.replaceText("{totalAmountWords}", details.totalAmountWords);
body.replaceText("{ceo}", details.ceo);
body.replaceText("{chiefAcc}", details.chiefAcc);
copiedDocFile.saveAndClose();
Что здесь может быть непонятного:
- copiedDocFile.getBody() — получаю содержимое копии темплейта, в котором как раз хранится весь текст.
- body.replaceText(«{ourCompany}», details.ourCompany); — что на что меняем 🙂
Сохраняю pdf
// сохраняем скопированный файл как пдф в пдф-папку с установкой нового имени
const copiedDocFileBlob = copiedFile.getAs('application/pdf');
pdfFolder.createFile(copiedDocFileBlob).setName(`pdf to send to ${details.buyer} ${details.buyerDoc}`)
Blob, если совсем просто это некий класс, сущность, которая позволяет из одного гугл «чего-то» сделать другое гугл «что-то». В моем случае из гугл документа получить pdf.
Удаляю копию темплейта
// удаляем темп-файл
tempFolder.removeFile(copiedFile);
тут, как мне кажется, разъяснять особо и нечего 🙂
Код полностью
function createPDF() {
const tempFileID = "заменить на айди вашего файла"; // ID файла базового темплейта
const tempFolder = DriveApp.getFolderById("заменить на айди вашей папки "); // папка в которой будут создаваться копии базового темплейта
const pdfFolder = DriveApp.getFolderById("заменить на айди папки пдф"); // папка, в которой будут создаваться заполненные пдф-файлы
const details = arrToObj(); //получили объект с данными
//копируeм базовый файл
const docFile = DriveApp.getFileById(tempFileID);
const copiedFile = docFile.makeCopy(tempFolder);
//открываем копию, заменяем, сохраняем и закрываем
const copiedDocFile = DocumentApp.openById(copiedFile.getId());
const body = copiedDocFile.getBody();
body.replaceText("{ourCompany}", details.ourCompany);
body.replaceText("{ourCompanyAddress}", details.ourCompanyAddress);
body.replaceText("{ourCompanyBank}", details.ourCompanyBank);
body.replaceText("{ourCompanyBankBIC}", details.ourCompanyBankBIC);
body.replaceText("{ourCompanyBankAcc}", details.ourCompanyBankAcc);
body.replaceText("{ourCompanyINN}", details.ourCompanyINN);
body.replaceText("{ourCompanyKPP}", details.ourCompanyKPP);
body.replaceText("{ourCompanyAcc}", details.ourCompanyAcc);
body.replaceText("{invoiceNum}", details.invoiceNum);
body.replaceText("{invoiceDate}", details.invoiceDate);
body.replaceText("{buyer}", details.buyer);
body.replaceText("{buyerDoc}", details.buyerDoc);
body.replaceText("{goods}", details.goods);
body.replaceText("{edIzm}", details.edIzm);
body.replaceText("{qty}", details.qty);
body.replaceText("{price}", details.price);
body.replaceText("{totalAmount}", details.totalAmount);
body.replaceText("{vat}", details.vat);
body.replaceText("{totalAmountWords}", details.totalAmountWords);
body.replaceText("{ceo}", details.ceo);
body.replaceText("{chiefAcc}", details.chiefAcc);
copiedDocFile.saveAndClose();
// сохраняем скопированный файл как пдф в пдф-папку с установкой нового имени
const copiedDocFileBlob = copiedFile.getAs('application/pdf');
pdfFolder.createFile(copiedDocFileBlob).setName(`pdf to send to ${details.buyer} ${details.buyerDoc}`)
// удаляем темп-файл
tempFolder.removeFile(copiedFile);
}
Итого результат
Выбираю счет, который нужно создать в пдф
Через юзер интерфейс пишу меню, запускающее функцию createPdf и получаю готовый пдф файл: