Hợp nhất văn bản vào tài liệu

Hướng dẫn này giải thích cách sử dụng Google Docs API để hợp nhất thông tin từ một hoặc nhiều nguồn dữ liệu bên ngoài vào một tài liệu mẫu hiện có.

Mẫu là một loại tài liệu chứa văn bản cố định và phần giữ chỗ cho nội dung động. Ví dụ: một mẫu hợp đồng có thể chứa văn bản cố định với các phần giữ chỗ cho tên và địa chỉ của người nhận. Sau đó, ứng dụng sẽ hợp nhất dữ liệu dành riêng cho người dùng vào mẫu để tạo tài liệu hoàn chỉnh.

Có một số lý do khiến phương pháp này hữu ích:

  • Nhà thiết kế có thể tinh chỉnh thiết kế của một tài liệu bằng Google Tài liệu. Cách này đơn giản hơn so với việc điều chỉnh các tham số trong ứng dụng để đặt bố cục được kết xuất.

  • Tách nội dung khỏi bản trình bày là một nguyên tắc thiết kế nổi tiếng với nhiều lợi ích.

Sơ đồ minh hoạ cách dữ liệu từ một nguồn hợp nhất vào một mẫu để tạo tài liệu.
Hình 1. Hợp nhất dữ liệu vào một mẫu để tạo tài liệu.

Cách hoạt động của tính năng hợp nhất tài liệu

Sau đây là ví dụ về cách bạn có thể sử dụng Docs API để hợp nhất dữ liệu vào một tài liệu:

  1. Tạo tài liệu bằng nội dung giữ chỗ để hỗ trợ bạn thiết kế và định dạng. Mọi định dạng văn bản bạn muốn thay thế đều được giữ nguyên.

  2. Đối với mỗi phần tử mà bạn sẽ chèn, hãy thay thế nội dung phần giữ chỗ bằng một thẻ. Hãy nhớ sử dụng những chuỗi không có khả năng xuất hiện một cách bình thường. Ví dụ: {{account-holder-name}} có thể là một thẻ phù hợp.

  3. Trong mã của bạn, hãy sử dụng API Google Drive để tạo bản sao của tài liệu.

  4. Trong mã của bạn, hãy sử dụng phương thức batchUpdate của Docs API với tên tài liệu và thêm ReplaceAllTextRequest.

Mã tài liệu tham chiếu đến một tài liệu và có thể được lấy từ URL:

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

Quản lý mẫu

Đối với tài liệu mẫu mà ứng dụng xác định và sở hữu, hãy tạo mẫu bằng một tài khoản chuyên dụng đại diện cho ứng dụng. Tài khoản dịch vụ là một lựa chọn phù hợp và tránh các vấn đề phức tạp với chính sách của Google Workspace về việc hạn chế chia sẻ.

Khi tạo các thực thể của tài liệu từ mẫu, hãy luôn sử dụng thông tin đăng nhập của người dùng cuối. Điều này giúp người dùng kiểm soát hoàn toàn tài liệu kết quả và ngăn chặn các vấn đề về việc mở rộng quy mô liên quan đến giới hạn cho mỗi người dùng trong Google Drive.

Để tạo một mẫu bằng tài khoản dịch vụ, hãy thực hiện các bước sau bằng thông tin đăng nhập ứng dụng:

  1. Tạo tài liệu bằng documents.create trong Docs API.
  2. Cập nhật các quyền để cho phép người nhận tài liệu đọc tài liệu đó bằng cách sử dụng permissions.create trong API Drive.
  3. Cập nhật quyền để cho phép tác giả mẫu ghi vào đó bằng cách sử dụng permissions.create trong API Drive.
  4. Chỉnh sửa mẫu theo yêu cầu.

Để tạo một phiên bản của tài liệu, hãy thực hiện các bước sau bằng thông tin đăng nhập của người dùng:

  1. Tạo bản sao của mẫu bằng cách sử dụng files.copy trong API Drive.
  2. Thay thế các giá trị bằng documents.batchUpdate trong Docs API.

Ví dụ: Hợp nhất dữ liệu vào một mẫu

Mã mẫu sau đây cho biết cách thay thế 2 trường trên tất cả các thẻ của một mẫu bằng các giá trị thực để tạo ra một tài liệu hoàn chỉnh:

Hình ảnh cho thấy một mẫu tài liệu có phần giữ chỗ thẻ và tài liệu đã hợp nhất thu được.
Hình 2. Thay thế các trình giữ chỗ thẻ bằng các giá trị.

Để thực hiện thao tác hợp nhất này, hãy sử dụng đoạn mã sau:

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()

Xử lý danh sách và bảng động

Tính năng hợp nhất tài liệu tiêu chuẩn sử dụng ReplaceAllTextRequest để thay thế từng phần giữ chỗ dùng một lần (chẳng hạn như {{customer-name}} hoặc {{date}}). Tuy nhiên, nếu dữ liệu của bạn có một danh sách các mục động (chẳng hạn như các dòng trong hoá đơn, danh sách các sản phẩm đã đặt hàng hoặc một bảng động), thì bạn không thể sử dụng tính năng thay thế văn bản tiêu chuẩn vì số lượng mục không xác định trong quá trình thiết kế mẫu.

Để xử lý nội dung danh sách động, hãy sử dụng một trong các chiến lược sau.

Cách 1: Thêm hàng vào bảng mẫu

Nếu tài liệu mẫu của bạn đã chứa một bảng được định dạng (ví dụ: có hàng tiêu đề và một hàng giữ chỗ duy nhất), bạn có thể sao chép và điền sẵn các hàng cho từng mục trong danh sách một cách linh hoạt:

  1. Đọc cấu trúc mẫu: Sử dụng phương thức documents.get để xác định vị trí của bảng và xác định chỉ mục của hàng mẫu.
  2. Chèn hàng mới: Đối với mỗi mục trong danh sách dữ liệu của bạn (ngoại trừ mục đầu tiên, có thể sử dụng lại hàng mẫu hiện có), hãy gọi InsertTableRowRequest để chèn một hàng mới bên dưới hàng mẫu.
  3. Điền dữ liệu vào ô: Điền dữ liệu vào các ô trong hàng mẫu bằng cách thay thế các phần giữ chỗ của hàng đó. Đối với các hàng mới tạo, hãy dùng InsertTextRequest để chèn văn bản tương ứng vào vị trí toạ độ của từng ô.

Để xem ví dụ về cách chèn hàng vào bảng, hãy xem phần Làm việc với bảng.

Cách 2: Thay thế thẻ bằng một bảng được tạo

Nếu bạn muốn tạo bảng từ đầu theo phương thức lập trình:

  1. Đặt thẻ giữ chỗ: Sử dụng một thẻ duy nhất (chẳng hạn như {{invoice-table}}) trong tài liệu mẫu để đánh dấu vị trí cần đặt danh sách.
  2. Xác định vị trí của phần giữ chỗ: Sử dụng một thao tác tìm kiếm để tìm chỉ mục bắt đầu của thẻ.
  3. Xoá phần giữ chỗ: Sử dụng DeleteContentRangeRequest để xoá văn bản {{invoice-table}}.
  4. Chèn bảng: Gửi một InsertTableRequest tại chỉ mục bắt đầu đó, chỉ định số lượng hàng và cột dựa trên nguồn dữ liệu của bạn.
  5. Ghi giá trị: Điền tuần tự vào từng ô trong bảng.

Để xem ví dụ về cách chèn bảng theo phương thức lập trình, hãy xem phần Làm việc với bảng.