Este guia explica como usar a API Google Docs para mesclar informações de uma ou mais fontes de dados externas em um documento de modelo existente.
Um modelo é um tipo de documento que contém texto fixo e marcadores de posição para conteúdo dinâmico. Por exemplo, um modelo de contrato pode conter texto fixo com marcadores de posição para o nome e o endereço do destinatário. Em seguida, o app mescla dados específicos do usuário no modelo para criar o documento final.
Há vários motivos para essa abordagem ser útil:
Os designers podem ajustar o design de um documento usando o Google Docs. Isso é mais simples do que ajustar parâmetros no app para definir o layout renderizado.
Separar o conteúdo da apresentação é um princípio de design conhecido com muitos benefícios.
Como funciona uma mesclagem de documentos
Confira um exemplo de como usar a API Docs para mesclar dados em um documento:
Crie o documento usando conteúdo de marcador de posição para ajudar no design e no formato. Toda a formatação de texto que você quiser substituir será preservada.
Para cada elemento que você inserir, substitua o conteúdo do marcador de posição por uma tag. Use strings que provavelmente não ocorram normalmente. Por exemplo,
{{account-holder-name}}pode ser uma boa tag.No código, use a API Google Drive para fazer uma cópia do documento.
No código, use o método
batchUpdateda API Docs com o nome do documento e inclua umReplaceAllTextRequest.
Os IDs de documentos fazem referência a um documento e podem ser derivados do URL:
https://docs.google.com/document/d/DOCUMENT_ID/edit
Gerenciar modelos
Para documentos de modelo que o app define e possui, crie o modelo usando uma conta dedicada que representa o app. Contas de serviço são uma boa opção e evitam complicações com as políticas do Google Workspace que restringem o compartilhamento.
Ao criar instâncias de documentos com base em modelos, sempre use credenciais de usuário final. Isso oferece aos usuários controle total sobre o documento resultante e evita problemas de escalonamento relacionados a limites por usuário no Google Drive.
Para criar um modelo usando uma conta de serviço, siga estas etapas com as credenciais do app:
- Crie um documento usando
documents.createna API Docs. - Atualize as permissões para permitir que os destinatários do documento leiam usando
permissions.createna API Drive. - Atualize as permissões para permitir que os autores do modelo gravem nele usando
permissions.createna API Drive. - Edite o modelo conforme necessário.
Para criar uma instância do documento, siga estas etapas com as credenciais do usuário:
- Crie uma cópia do modelo usando
files.copyna API Drive. - Substitua os valores usando
documents.batchUpdatena API Docs.
Exemplo: mesclar dados em um modelo
O exemplo de código a seguir mostra como substituir dois campos em todas as guias de um modelo por valores reais para gerar um documento final:
Para realizar essa mesclagem, use o código a seguir:
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()
Processar listas e tabelas dinâmicas
Uma mesclagem de documentos padrão usa ReplaceAllTextRequest para substituir marcadores de posição individuais
únicos (como {{customer-name}} ou
{{date}}). No entanto, se os dados incluírem
uma lista dinâmica de itens (como linhas em uma fatura, uma lista de produtos
encomendados ou uma tabela dinâmica), não será possível usar a substituição de texto padrão, porque
o número de itens é desconhecido durante o design do modelo.
Para processar o conteúdo da lista dinâmica, use uma das seguintes estratégias.
Opção 1: anexar linhas a uma tabela de modelo
Se o documento de modelo já contiver uma tabela formatada (por exemplo, com uma linha de cabeçalho e uma única linha de marcador de posição), você poderá clonar e preencher linhas dinamicamente para cada item na lista:
- Leia a estrutura do modelo: use o método
documents.getpara localizar a tabela e identificar o índice da linha do modelo. - Insira novas linhas: para cada item na lista dos seus dados (exceto o primeiro
item, que pode reutilizar a linha de modelo existente), chame
InsertTableRowRequestpara inserir uma nova linha abaixo da linha do modelo. - Preencha os dados da célula:preencha as células na linha do modelo substituindo os marcadores de posição. Para as linhas recém-criadas, use
InsertTextRequestpara inserir o texto respectivo no local da coordenada de cada célula.
Para exemplos de como inserir linhas de tabela, consulte Trabalhar com tabelas.
Opção 2: substituir uma tag por uma tabela gerada
Se você quiser criar a tabela do zero de forma programática:
- Coloque uma tag de marcador de posição: use uma única tag (como
{{invoice-table}}) no documento de modelo para marcar onde a lista deve ir. - Localize o marcador de posição: Use uma operação de pesquisa para encontrar o índice inicial da tag.
- Exclua o marcador de posição:use
DeleteContentRangeRequestpara remover o texto{{invoice-table}}. - Insira a tabela: envie um
InsertTableRequestnesse índice inicial, especificando o número de linhas e colunas com base na fonte de dados. - Grave valores:preencha cada célula da tabela sequencialmente.
Para exemplos de inserção de tabelas de forma programática, consulte Trabalhar com tabelas.