Fusionner du texte dans un document

Ce guide explique comment utiliser l'API Google Docs pour fusionner des informations provenant d'une ou de plusieurs sources de données externes dans un document modèle existant.

Un modèle est un type de document contenant du texte fixe et des espaces réservés pour le contenu dynamique. Par exemple, un modèle de contrat peut contenir du texte fixe avec des espaces réservés pour le nom et l'adresse du destinataire. L'application fusionne ensuite les données spécifiques à l'utilisateur dans le modèle pour créer le document final.

Cette approche est utile pour plusieurs raisons :

  • Les concepteurs peuvent affiner la conception d'un document à l'aide de Google Docs. Cette méthode est plus simple que le réglage des paramètres dans votre application pour définir la mise en page rendue.

  • La séparation du contenu et de la présentation est un principe de conception bien connu qui présente de nombreux avantages.

Diagramme montrant comment les données d'une source sont fusionnées dans un modèle pour créer un document.
Figure 1. Fusion de données dans un modèle pour créer un document

Fonctionnement de la fusion de documents

Voici un exemple d'utilisation de l'API Docs pour fusionner des données dans un document :

  1. Créez votre document à l'aide d'un contenu d'espace réservé pour vous aider à concevoir et à mettre en forme. Toute mise en forme de texte que vous souhaitez remplacer est conservée.

  2. Pour chaque élément que vous insérerez, remplacez le contenu de l'espace réservé par une balise. Veillez à utiliser des chaînes qui ne sont pas susceptibles de se produire normalement. Par exemple, {{account-holder-name}} peut être une bonne balise.

  3. Dans votre code, utilisez l'API Google Drive pour créer une copie du document.

  4. Dans votre code, utilisez la méthode batchUpdate de l'API Docs avec le nom du document et incluez un ReplaceAllTextRequest.

Les ID de document font référence à un document et peuvent être dérivés de l'URL :

https://docs.google.com/document/d/DOCUMENT_ID/edit

Gérer les modèles

Pour les documents modèles que l'application définit et possède, créez le modèle à l'aide d'un compte dédié représentant l'application. Les comptes de service sont un bon choix et évitent les complications liées aux règles Google Workspace qui limitent le partage.

Lorsque vous créez des instances de documents à partir de modèles, utilisez toujours les identifiants de l'utilisateur final. Les utilisateurs peuvent ainsi contrôler pleinement le document résultant et éviter les problèmes de scaling liés aux limites par utilisateur dans Google Drive.

Pour créer un modèle à l'aide d'un compte de service, procédez comme suit avec les identifiants de l'application :

  1. Créez un document à l'aide de documents.create dans l'API Docs.
  2. Mettez à jour les autorisations pour permettre aux destinataires du document de le lire à l'aide de permissions.create dans l'API Drive.
  3. Mettez à jour les autorisations pour permettre aux auteurs du modèle d'y écrire à l'aide de permissions.create dans l'API Drive.
  4. Modifiez le modèle selon vos besoins.

Pour créer une instance du document, procédez comme suit avec les identifiants de l'utilisateur :

  1. Créez une copie du modèle à l'aide de files.copy dans l' API Drive.
  2. Remplacez les valeurs à l'aide de documents.batchUpdate dans l'API Docs.

Exemple : Fusionner des données dans un modèle

L'exemple de code suivant montre comment remplacer deux champs dans tous les onglets d'un modèle par des valeurs réelles pour générer un document final :

Image montrant un modèle de document avec des espaces réservés pour les balises et le document fusionné obtenu.
Figure 2. Remplacement des espaces réservés de balise par des valeurs

Pour effectuer cette fusion, utilisez le code suivant :

Java

String customerName = "Alice";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
String date = formatter.format(LocalDate.now());

// Make a copy of the template document using the Drive API.
String copyTitle = "Merged Document";
File copyMetadata = new File().setName(copyTitle);
File documentCopyFile =
        driveService.files().copy(DOCUMENT_ID, copyMetadata).execute();
String documentCopyId = documentCopyFile.getId();

List requests = new ArrayList<>();
// One option for replacing all text is to specify all tab IDs.
requests.add(new Request()
        .setReplaceAllText(new ReplaceAllTextRequest()
                .setContainsText(new SubstringMatchCriteria()
                        .setText("{{customer-name}}")
                        .setMatchCase(true))
                .setReplaceText(customerName)
                .setTabsCriteria(new TabsCriteria()
                        .addTabIds(TAB_ID_1)
                        .addTabIds(TAB_ID_2)
                        .addTabIds(TAB_ID_3))));
// Another option is to omit TabsCriteria if you are replacing across all tabs.
requests.add(new Request()
        .setReplaceAllText(new ReplaceAllTextRequest()
                .setContainsText(new SubstringMatchCriteria()
                        .setText("{{date}}")
                        .setMatchCase(true))
                .setReplaceText(date)));

BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest();
service.documents().batchUpdate(documentCopyId, body.setRequests(requests)).execute();

Node.js

  let customerName = 'Alice';
  let date = yyyymmdd()
  let requests = [
    // One option for replacing all text is to specify all tab IDs.
    {
      replaceAllText: {
        containsText: {
          text: '{{customer-name}}',
          matchCase: true,
        },
        replaceText: customerName,
        tabsCriteria: {
          tabIds: [TAB_ID_1, TAB_ID_2, TAB_ID_3],
        },
      },
    },
    // Another option is to omit TabsCriteria if you are replacing across all tabs.
    {
      replaceAllText: {
        containsText: {
          text: '{{date}}',
          matchCase: true,
        },
        replaceText: date,
      },
    },
  ];

  // Make a copy of the template document using the Drive API.
  let copyTitle = 'Merged Document';
  driveService.files.copy({
    fileId: '1yBx6HSnu_gbV2sk1nChJOFo_g3AizBhr-PpkyKAwcTg',
    resource: {
      name: copyTitle,
    },
  }, (err, driveResponse) => {
    if (err) return console.log('The Drive API returned an error: ' + err);
    let documentCopyId = driveResponse.data.id;

    google.options({auth: auth});
    google
        .discoverAPI(
            'https://docs.googleapis.com/$discovery/rest?version=v1&key={YOUR_API_KEY}')
        .then(function(docs) {
          docs.documents.batchUpdate(
              {
                documentId: documentCopyId,
                resource: {
                  requests,
                },
              },
              (err, {data}) => {
                if (err) return console.log('The API returned an error: ' + err);
                console.log(data);
              });
        });
  });

Python

customer_name = 'Alice'
date = datetime.datetime.now().strftime("%y/%m/%d")

# Make a copy of the template document using the Drive API.
copy_title = 'Merged Document'
body = {
    'name': copy_title
}
drive_response = drive_service.files().copy(
    fileId=DOCUMENT_ID, body=body).execute()
document_copy_id = drive_response.get('id')

requests = [
        # One option for replacing all text is to specify all tab IDs.
        {
        'replaceAllText': {
            'containsText': {
                'text': '{{customer-name}}',
                'matchCase':  'true'
            },
            'replaceText': customer_name,
            'tabsCriteria': {
                'tabIds': [TAB_ID_1, TAB_ID_2, TAB_ID_3],
            },
        }},
        # Another option is to omit TabsCriteria if you are replacing across all tabs.
        {
        'replaceAllText': {
            'containsText': {
                'text': '{{date}}',
                'matchCase':  'true'
            },
            'replaceText': str(date),
        }
    }
]

result = service.documents().batchUpdate(
    documentId=document_copy_id, body={'requests': requests}).execute()

Gérer les listes et les tables dynamiques

Une fusion de documents standard utilise ReplaceAllTextRequest pour remplacer des espaces réservés individuels ponctuels (tels que {{customer-name}} ou {{date}}). Toutefois, si vos données incluent une liste dynamique d'éléments (tels que des lignes dans une facture, une liste de produits commandés ou un tableau dynamique), vous ne pouvez pas utiliser le remplacement de texte standard, car le nombre d'éléments est inconnu lors de la conception du modèle.

Pour gérer le contenu de la liste dynamique, utilisez l'une des stratégies suivantes.

Option 1 : Ajouter des lignes à un tableau de modèle

Si votre document modèle contient déjà un tableau mis en forme (par exemple, avec une ligne d'en-tête et une seule ligne d'espace réservé), vous pouvez cloner et remplir dynamiquement des lignes pour chaque élément de votre liste :

  1. Lire la structure du modèle : utilisez la méthode documents.get pour localiser le tableau et identifier l' index de la ligne du modèle.
  2. Insérer de nouvelles lignes : pour chaque élément de votre liste de données (à l'exception du premier élément, qui peut réutiliser la ligne de modèle existante), appelez InsertTableRowRequest pour insérer une nouvelle ligne sous la ligne de modèle.
  3. Remplir les données des cellules : remplissez les cellules de la ligne de modèle en remplaçant ses espaces réservés. Pour les lignes nouvellement créées, utilisez InsertTextRequest pour insérer le texte correspondant dans l'emplacement des coordonnées de chaque cellule.

Pour obtenir des exemples d'insertion de lignes de tableau, consultez Utiliser des tableaux.

Option 2 : Remplacer une balise par un tableau généré

Si vous souhaitez créer le tableau de toutes pièces par programmation :

  1. Placer une balise d'espace réservé : utilisez une seule balise (telle que {{invoice-table}}) dans le document modèle pour indiquer où la liste doit être placée.
  2. Localiser l'espace réservé : utilisez une opération de recherche pour trouver l'index de début de la balise.
  3. Supprimer l'espace réservé : utilisez DeleteContentRangeRequest pour supprimer le texte {{invoice-table}}.
  4. Insérer le tableau : envoyez une InsertTableRequest à cet index de début, en spécifiant le nombre de lignes et de colonnes en fonction de votre source de données.
  5. Écrire des valeurs : remplissez chaque cellule du tableau de manière séquentielle.

Pour obtenir des exemples d'insertion de tableaux par programmation, consultez Utiliser des tableaux.