Eingabemasken für Google Docs

Immer wieder die gleiche Vorlage öffnen, sich zu den relevanten Stellen vorarbeiten, Anpassungen vornehmen, abspeichern, abschicken … wenn man das 1000-mal gemacht hat, dann ist es an der Zeit, über eine Dokumentenvorlage nachzudenken, die automatisiert befüllt werden kann.

Das geht natürlich mit einer ganzen Reihe von Programmen. Ich habe mir Google Docs vorgenommen. Google bietet mit Google Apps Script eine Möglichkeit, Dokumente automatisiert zu erstellen und zu editieren.

Tobias Sell hat auf seiner Webseite ein Skript vorgelegt. Die Lösung funktioniert mit allen Dokumenten, in denen man Platzhalter mit Paaren von zwei geschweiften Klammern umschließt. Für jeden Platzhalter, den das Programm noch nicht kennt, wird der Nutzer aufgefordert, einen Wert anzugeben. Das ist sehr flexibel.

Ich wollte jedoch eine Lösung, bei der der Nutzer alle Eingaben auf einmal angeben kann. Dafür bietet Google Docs die Möglichkeit, Formulare via HTML zu definieren.

So sieht meine Lösung aus: Man hat ein Dokument, in dem man Platzhalter mit geschweiften Klammern definiert:

Das Skript erstellt auch ein Menü, wenn man das Dokument aufruft. Drückt man dort „neues Dokument erstellen“ wird eine Eingabemaske aufgerufen:

Nun füllt der Nutzer die benötigten Felder aus. Wenn er das Formular abschickt,

  1. wird eine Kopie der Vorlage in einem speziellen Ordner in Google Drive angelegt
  2. in der Kopie werden alle in der Form definierten Felder, die in doppelt geschweiften Klammern daherkommen, ersetzt
  3. das Dokument wird gespeichert und als PDF dem Nutzer auf eine vordefinierte E-Mail-Adresse geschickt

Der Code gliedert sich in einen JavaScript-Teil und einen HTML-Teil. Zuerst das Skript:

const FOLDER_NAME   = 'TestOrdner'; 
const USER_EMAIL    =  YOUR_EMAIL_ADDRESS;
const USER_GREETING = 'Geben Sie die Daten ein:';
const EMAIL_SUBJECT = 'Neues Dokument'; 
const DOCUMENT_NAME = "doc_search_form_"; 

var ui = DocumentApp.getUi(); 

function onOpen() {

  ui.createMenu('Neues Dokument')
  .addItem('Neues Dokument erstellen', 'openInputDialog')
  .addToUi(); 
} 

function openInputDialog() {
  
  var html = HtmlService.createHtmlOutputFromFile('index')
    .setWidth(350)
    .setHeight(300);

  var dialog = ui.showModalDialog(html, USER_GREETING);
}

function createDocAndMail(form) {

  var newDocument = createDocFromTemplate(form);  

  var body=newDocument.getBody();

 for (var [key, value] of Object.entries(form)){
   body.replaceText("{{"+key+"}}", value) 
  }

  newDocument.saveAndClose();

  GmailApp.sendEmail(USER_EMAIL, EMAIL_SUBJECT, "Schöne Grüße!",{
     attachments: [newDocument.getAs(MimeType.PDF)],
     name: 'Automatic Emailer Script'
  });
}

function createDocFromTemplate (form) {

  const documentName = DOCUMENT_NAME + form.feld1; 
  var matchingFolders = DriveApp.getFoldersByName(FOLDER_NAME);
  if (matchingFolders.hasNext()) {
    var documentFolder =  matchingFolders.next();
  }
  else {
    var documentFolder = DriveApp.createFolder(FOLDER_NAME);
  }
  
  var file = DriveApp
  .getFileById(DocumentApp.getActiveDocument().getId())
  .makeCopy(documentName, documentFolder); 
  
  return DocumentApp.openById(file.getId()); 
}

Am Anfang werden globale Variablen definiert. Hier muss vor allem die eigene E-Mail-Adresse anstelle von YOUR_EMAIL_ADDRESS hinterlegt werden. An diese Adresse soll der Nutzer das erstellte PDF-Dokument gesendet bekommen. Die Funktion onOpen lässt beim Öffnen der Vorlage einen Punkt im Menü erscheinen, von dem man aus die Funktion openInputDialog aufrufen lassen kann. openInputDialog wiederum lässt die unten definierte Eingabemaske erscheinen. Die eigentlichen Ersetzungen passieren in der Funktion createDocAndMail, die ich zu einem großen Teil von Tobias Sell übernommen habe. Im Unterschied zu seiner Lösung wird nicht das Dokument nach Platzhaltern durchsucht, sondern die Felder der Eingabemaske werden nacheinander durchlaufen.

Der HTML-Teil, in index.html, definiert die Eingabemaske. Außerdem wird im HTML-Teil die oben definierte Funktion createDocAndMail mit den Nutzerdaten als Eingabe aufgerufen:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css"> 
  </head>
  <body>
  <form>

    <table>
      <col width="130">
      <col width="100">
      <tr>
        <td> Feld 1: </td> <td><input type="text" name="feld1"> </td> 
      </tr>
      <tr> 
        <td> Feld 2: </td> <td> <input type="text" name="feld2"> </td>
      </tr>
    </table>

    <input type="button" class="action" value="Abschicken"
        onclick="processForm(this.parentNode)" />
    <input type="button" value="Abbrechen" onclick="google.script.host.close()" />

  </form>
  </body>
  <script>
  function processForm(form){
    google.script.run.createDocAndMail(form); 
    google.script.host.close();
  }
  </script>
</html>

Zuerst wird das Layout über das Google-CSS definiert. Ein Tipp, den ich der Lösung von Yaginasatode entnommen habe. Darauf wird eine Form mithilfe einer Tabelle definiert, und am Ende gibt es zwei Buttons, die entweder die Form via google.script.host.close schließen oder via google.script.run die Serverfunktion createDocAndMail aufrufen. Das kleine Stück JavaScript im HTML-Teil wartet nicht darauf, dass createDocAndMail fertig wird, sondern geht gleich zur nächsten Zeile und schließt die Form.

1 Kommentar

  1. Sehr coole Erweiterung. Vielen Dank auch für die Credits!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.