Ile czasu Twój zespół spędza co miesiąc na „eksportuj do PDF → zmień nazwę → wyślij mailem"? W firmach B2B generujących dziesiątki faktur, umów czy raportów tygodniowo, ta ręczna praca pochłania 5–10 godzin miesięcznie. Google Apps Script pozwala zredukować to do zera – jeden klik lub pełna automatyzacja bez ingerencji człowieka.
Koncepcja: szablon + dane = gotowy PDF
Cały mechanizm opiera się na prostym wzorcu:
- Szablon – Google Docs z placeholderami (np.
{{NAZWA_FIRMY}},{{KWOTA}},{{DATA}}). - Dane – wiersz w Google Sheets z konkretnymi wartościami dla każdego klienta/raportu.
- Skrypt – kopiuje szablon, podmienia placeholdery na dane, konwertuje do PDF i zapisuje na Dysku lub wysyła mailem.
To w zasadzie Mail Merge na sterydach – bez żadnych płatnych pluginów. Ten sam mechanizm możesz podpiąć pod formularze Google Forms, żeby PDF generował się automatycznie po każdym wypełnieniu ankiety.
Gotowy skrypt: generowanie PDF z szablonu
Poniższy kod iteruje po wierszach w Arkuszu, dla każdego generuje spersonalizowany dokument PDF i zapisuje go w wybranym folderze na Dysku:
function generatePDFReports() {
const TEMPLATE_ID = 'ID_TWOJEGO_SZABLONU_DOCS';
const OUTPUT_FOLDER_ID = 'ID_FOLDERU_NA_PDF';
const SHEET_NAME = 'Dane';
const sheet = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName(SHEET_NAME);
const rows = sheet.getDataRange().getValues();
const headers = rows[0];
const outputFolder = DriveApp.getFolderById(OUTPUT_FOLDER_ID);
for (let i = 1; i < rows.length; i++) {
const row = rows[i];
if (row[headers.indexOf('Status')] === 'Wygenerowano') continue;
// Kopia szablonu
const templateFile = DriveApp.getFileById(TEMPLATE_ID);
const copy = templateFile.makeCopy(
`Raport_${row[headers.indexOf('Firma')]}_${new Date().toISOString().slice(0,10)}`,
outputFolder
);
const doc = DocumentApp.openById(copy.getId());
const body = doc.getBody();
// Podmiana placeholderów
headers.forEach((header, idx) => {
body.replaceText(`{{${header}}}`, String(row[idx]));
});
doc.saveAndClose();
// Konwersja do PDF
const pdfBlob = DriveApp.getFileById(copy.getId())
.getAs('application/pdf');
const pdfFile = outputFolder.createFile(pdfBlob)
.setName(copy.getName() + '.pdf');
// Opcjonalnie: wyślij mailem
const email = row[headers.indexOf('Email')];
if (email) {
MailApp.sendEmail({
to: email,
subject: `Raport dla ${row[headers.indexOf('Firma')]}`,
body: 'W załączniku przesyłam wygenerowany raport.',
attachments: [pdfFile.getAs(MimeType.PDF)]
});
}
// Usuń kopię Docs (zostaje tylko PDF)
DriveApp.getFileById(copy.getId()).setTrashed(true);
// Oznacz jako wygenerowany
sheet.getRange(i + 1, headers.indexOf('Status') + 1)
.setValue('Wygenerowano');
}
}
Jak przygotować szablon Google Docs?
Klucz tkwi w konwencji nazewnictwa placeholderów. Używam {{NAZWA_KOLUMNY}},
gdzie nazwa kolumny to dokładnie to, co masz w nagłówku Arkusza. Dzięki temu skrypt
jest uniwersalny – dodajesz nową kolumnę do Sheets, wstawiasz odpowiedni placeholder
do Docs i działa bez zmiany kodu.
- Faktura:
{{Nr_faktury}},{{Firma}},{{Kwota_netto}},{{Data_wystawienia}} - Umowa:
{{Imie_Nazwisko}},{{Stanowisko}},{{Wynagrodzenie}} - Raport miesięczny:
{{Okres}},{{Przychod}},{{Koszty}},{{Marza}}
Automatyczny trigger – generowanie bez kliknięcia
Największa wartość skryptu pojawia się, gdy nikt nie musi go uruchamiać ręcznie. Apps Script obsługuje dwa typy triggerów przydatnych przy generowaniu PDF:
Trigger czasowy – uruchamia skrypt codziennie o określonej godzinie (np. pierwsze dni miesiąca = faktury miesięczne):
function setupMonthlyTrigger() {
ScriptApp.newTrigger('generatePDFReports')
.timeBased()
.onMonthDay(1) // 1. dzień miesiąca
.atHour(7) // o 07:00
.create();
}
Trigger onFormSubmit – generuje PDF natychmiast po wypełnieniu formularza Google Forms (np. zlecenie serwisowe → PDF potwierdzenia → e-mail do klienta). Szczegółowy poradnik o formularzach Google Forms i triggerach.
Przypadki użycia według działu
| Dział | Typ dokumentu | Trigger | Oszczędność |
|---|---|---|---|
| Finanse | Faktury, potwierdzenia płatności | 1. dzień miesiąca | ~4h/mies. |
| HR | Umowy o pracę, aneksy | Nowy wiersz w Sheets | ~2h/mies. |
| Sprzedaż B2B | Oferty, potwierdzenia zamówień | onFormSubmit | ~6h/mies. |
| Marketing | Raporty miesięczne dla klientów | Trigger miesięczny | ~8h/mies. |
Ograniczenia i limity Apps Script
Apps Script ma kilka limitów, o których warto wiedzieć przed wdrożeniem:
- 6 minut – maksymalny czas wykonania jednego uruchomienia. Przy 500+ dokumentach trzeba zastosować batching.
- 250 MB/dzień – limit tworzenia plików na Dysku (konto darmowe).
- 100 maili/dzień – Gmail darmowy. Google Workspace B2B: 1 500/dzień.
Dla dużych wolumenów stosuję technikę „batch + continuation token" – skrypt przetwarza 50 plików, zapisuje stan w PropertiesService i kontynuuje przy następnym uruchomieniu triggera. Oznacza to, że 500 dokumentów zostanie wygenerowanych w 10 cyklach bez przekraczania limitu czasu.
Generowanie PDF to często tylko jeden etap w większym pipeline. W moich wdrożeniach łączę go z:
- Automatycznym wysyłaniem przypomnień – jeśli klient nie opłacił faktury, skrypt wysyła przypomnienie z załączonym PDF po X dniach.
- Webhokami i API – zewnętrzny system (np. CRM) triggeruje generowanie dokumentu przez HTTP request do Apps Script jako Web App.
„Generowanie faktury nie powinno wymagać ludzkiego kliknięcia. Jeśli dane są w arkuszu – PDF powinien pojawić się na Dysku sam, bez pytania."