En esta guía, se explica cómo usar la API de Google Docs para combinar información de una o más fuentes de datos externas en un documento de plantilla existente.
Una plantilla es un tipo de documento que contiene texto fijo y marcadores de posición para contenido dinámico. Por ejemplo, una plantilla de contrato puede contener texto fijo con marcadores de posición para el nombre y la dirección del destinatario. Luego, la app combina los datos específicos del usuario en la plantilla para crear el documento terminado.
Existen varios motivos por los que este enfoque es útil:
Los diseñadores pueden ajustar el diseño de un documento con Documentos de Google. Esto es más sencillo que ajustar los parámetros en tu app para establecer el diseño renderizado.
Separar el contenido de la presentación es un principio de diseño conocido con muchos beneficios.
Cómo funciona la combinación de documentos
Este es un ejemplo de cómo puedes usar la API de Docs para combinar datos en un documento:
Crea tu documento con contenido de marcador de posición para ayudarte con el diseño y el formato. Se conserva cualquier formato de texto que desees reemplazar.
Para cada elemento que insertarás, reemplaza el contenido del marcador de posición por una etiqueta. Asegúrate de usar cadenas que no es probable que ocurran normalmente. Por ejemplo,
{{account-holder-name}}podría ser una buena etiqueta.En tu código, usa la API de Google Drive para hacer una copia del documento.
En tu código, usa el método
batchUpdatede la API de Docs con el nombre del documento e incluye unReplaceAllTextRequest.
Los IDs de los documentos hacen referencia a un documento y se pueden derivar de la URL:
https://docs.google.com/document/d/DOCUMENT_ID/edit
Administrar plantillas
Para los documentos de plantilla que la app define y posee, crea la plantilla con una cuenta dedicada que represente la app. Las cuentas de servicio son una buena opción y evitan complicaciones con las políticas de Google Workspace que restringen el uso compartido.
Cuando crees instancias de documentos a partir de plantillas, siempre usa credenciales de usuario final. Esto les brinda a los usuarios control total sobre el documento resultante y evita problemas de escalamiento relacionados con los límites por usuario en Google Drive.
Para crear una plantilla con una cuenta de servicio, sigue estos pasos con las credenciales de la app:
- Crea un documento con
documents.createen la API de Docs. - Actualiza los permisos para permitir que los destinatarios del documento lo lean con
permissions.createen la API de Drive. - Actualiza los permisos para permitir que los autores de la plantilla escriban en ella con
permissions.createen la API de Drive. - Edita la plantilla según sea necesario.
Para crear una instancia del documento, sigue estos pasos con las credenciales del usuario:
- Crea una copia de la plantilla con
files.copyen la API de Drive. - Reemplaza los valores con
documents.batchUpdateen la API de Docs.
Ejemplo: Combina datos en una plantilla
En el siguiente ejemplo de código, se muestra cómo reemplazar dos campos en todas las pestañas de una plantilla con valores reales para generar un documento terminado:
Para realizar esta combinación, usa el siguiente código:
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(); Listrequests = 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()
Cómo controlar listas y tablas dinámicas
Una combinación de documentos estándar usa ReplaceAllTextRequest para reemplazar marcadores de posición individuales únicos (como {{customer-name}} o {{date}}). Sin embargo, si tus datos incluyen una lista dinámica de elementos (como líneas en una factura, una lista de productos pedidos o una tabla dinámica), no puedes usar el reemplazo de texto estándar porque la cantidad de elementos es desconocida durante el diseño de la plantilla.
Para controlar el contenido de la lista dinámica, usa una de las siguientes estrategias.
Opción 1: Agrega filas a una tabla de plantilla
Si tu documento de plantilla ya contiene una tabla con formato (por ejemplo, con una fila de encabezado y una sola fila de marcador de posición), puedes clonar y completar filas de forma dinámica para cada elemento de tu lista:
- Lee la estructura de la plantilla: Usa el método
documents.getpara ubicar la tabla y, luego, identificar el índice de la fila de la plantilla. - Inserta filas nuevas: Para cada elemento de tu lista de datos (excepto el primer
elemento, que puede reutilizar la fila de plantilla existente), llama a
InsertTableRowRequestpara insertar una fila nueva debajo de la fila de la plantilla. - Completa los datos de la celda: Completa las celdas de la fila de la plantilla reemplazando sus marcadores de posición. Para las filas recién creadas, usa
InsertTextRequestpara insertar el texto respectivo en la ubicación de coordenadas de cada celda.
Para ver ejemplos de cómo insertar filas de tabla, consulta Trabaja con tablas.
Opción 2: Reemplaza una etiqueta por una tabla generada
Si deseas compilar la tabla desde cero de forma programática, haz lo siguiente:
- Coloca una etiqueta de marcador de posición: Usa una sola etiqueta (como
{{invoice-table}}) en el documento de plantilla para marcar dónde debe ir la lista. - Ubica el marcador de posición: Usa una operación de búsqueda para encontrar el índice de inicio de la etiqueta.
- Borra el marcador de posición: Usa
DeleteContentRangeRequestpara quitar el texto{{invoice-table}}. - Inserta la tabla: Envía un
InsertTableRequesten ese índice de inicio y especifica la cantidad de filas y columnas según tu fuente de datos. - Escribe valores: Completa cada celda de la tabla de forma secuencial.
Para ver ejemplos de cómo insertar tablas de forma programática, consulta Trabaja con tablas.