دمج نص في مستند

يوضّح هذا الدليل كيفية استخدام Google Docs API لدمج المعلومات من مصدر أو أكثر من مصادر البيانات الخارجية في مستند نموذج حالي.

القالب هو نوع من المستندات يحتوي على نص ثابت وعناصر نائبة للمحتوى الديناميكي. على سبيل المثال، قد يحتوي نموذج عقد على نص ثابت مع عناصر نائبية لاسم المستلم وعنوانه. بعد ذلك، يدمج التطبيق البيانات الخاصة بالمستخدم في النموذج لإنشاء المستند النهائي.

هناك عدة أسباب تجعل هذا النهج مفيدًا:

  • يمكن للمصمّمين تحسين تصميم المستند باستخدام "مستندات Google". وهذه الطريقة أبسط من ضبط المَعلمات في تطبيقك لتحديد التنسيق المعروض.

  • إنّ فصل المحتوى عن طريقة عرضه هو أحد مبادئ التصميم المعروفة التي تتضمّن العديد من المزايا.

مخطّط يوضّح كيفية دمج البيانات من مصدر في نموذج لإنشاء مستند
الشكل 1. دمج البيانات في نموذج لإنشاء مستند

طريقة عمل دمج المستندات

في ما يلي مثال على كيفية استخدام Docs API لدمج البيانات في مستند:

  1. أنشئ مستندك باستخدام محتوى عناصر نائبة لمساعدتك في التصميم والتنسيق. يتم الاحتفاظ بأي تنسيق نص تريد استبداله.

  2. لكل عنصر ستدرجه، استبدِل المحتوى النائب بعلامة احرص على استخدام سلاسل من غير المحتمل أن تحدث بشكل طبيعي. على سبيل المثال، قد تكون {{account-holder-name}} علامة جيدة.

  3. في الرمز البرمجي، استخدِم Google Drive API لإنشاء نسخة من المستند.

  4. في الرمز البرمجي، استخدِم طريقة batchUpdate في Docs API مع اسم المستند، وأدرِج ReplaceAllTextRequest.

تشير معرّفات المستندات إلى مستند ويمكن استخراجها من عنوان URL:

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

إدارة النماذج

بالنسبة إلى مستندات النماذج التي يحدّدها التطبيق ويمتلكها، أنشئ النموذج باستخدام حساب مخصّص يمثّل التطبيق. حسابات الخدمة هي خيار جيد وتتجنّب التعقيدات المتعلقة بسياسات Google Workspace التي تقيّد المشاركة.

عند إنشاء نُسخ من المستندات من النماذج، استخدِم دائمًا بيانات اعتماد المستخدم النهائي. ويمنح ذلك المستخدمين تحكّمًا كاملاً في المستند الناتج ويمنع حدوث مشاكل في التوسّع مرتبطة بالحدود القصوى المسموح بها لكل مستخدم في Google Drive.

لإنشاء نموذج باستخدام حساب خدمة، اتّبِع الخطوات التالية باستخدام بيانات اعتماد التطبيق:

  1. أنشئ مستندًا باستخدام documents.create في Docs API.
  2. عدِّل الأذونات للسماح للمستلمين بقراءة المستند باستخدام permissions.create في Drive API.
  3. عدِّل الأذونات للسماح لمؤلفي النماذج بالكتابة إليها باستخدام permissions.create في Drive API.
  4. عدِّل النموذج حسب الحاجة.

لإنشاء نسخة من المستند، اتّبِع الخطوات التالية باستخدام بيانات اعتماد المستخدم:

  1. أنشِئ نسخة من النموذج باستخدام files.copy في Drive API.
  2. استبدِل القيم باستخدام documents.batchUpdate في Docs API.

مثال: دمج البيانات في نموذج

يوضّح نموذج الرمز التالي كيفية استبدال حقلَين في جميع علامات تبويب أحد النماذج بقيم حقيقية لإنشاء مستند مكتمل:

صورة تعرض نموذج مستند يتضمّن عناصر نائبة للعلامات والمستند الناتج بعد الدمج.
الشكل 2. استبدال العناصر النائبة في العلامات بالقيم

لإجراء عملية الدمج هذه، استخدِم الرمز التالي:

جافا

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

التعامل مع القوائم والجداول الديناميكية

تستخدم عملية دمج المستندات العادية ReplaceAllTextRequest لاستبدال العناصر النائبة الفردية التي تُستخدَم لمرة واحدة (مثل {{customer-name}} أو {{date}}). ومع ذلك، إذا كانت بياناتك تتضمّن قائمة ديناميكية بالعناصر (مثل الأسطر في فاتورة أو قائمة بالمنتجات المطلوبة أو جدول ديناميكي)، لا يمكنك استخدام عملية استبدال النص العادية لأنّ عدد العناصر غير معروف أثناء تصميم النموذج.

للتعامل مع محتوى القائمة الديناميكية، استخدِم إحدى الاستراتيجيات التالية.

الخيار 1: إلحاق صفوف بجدول نموذج

إذا كان مستند النموذج يحتوي على جدول منسَّق (على سبيل المثال، مع صف عناوين وصف عنصر نائب واحد)، يمكنك إنشاء نسخ مكرّرة من الصفوف وتعبئتها بشكل ديناميكي لكل عنصر في قائمتك:

  1. قراءة بنية النموذج: استخدِم طريقة documents.get لتحديد موقع الجدول وتحديد الفهرس لصف النموذج.
  2. إدراج صفوف جديدة: لكل عنصر في قائمة بيانات الجمهور (باستثناء العنصر الأول الذي يمكنه إعادة استخدام صف القالب الحالي)، استدعِ الدالة InsertTableRowRequest لإدراج صف جديد أسفل صف القالب.
  3. ملء بيانات الخلايا: املأ الخلايا في صف النموذج عن طريق استبدال العناصر النائبة. بالنسبة إلى الصفوف التي تم إنشاؤها حديثًا، استخدِم InsertTextRequest لإدراج النص المعنيّ في الموقع الجغرافي لكل خلية.

للاطّلاع على أمثلة حول كيفية إدراج صفوف في جدول، يُرجى الاطّلاع على العمل مع الجداول.

الخيار 2: استبدال علامة بجدول تم إنشاؤه

إذا أردت إنشاء الجدول من البداية آليًا، اتّبِع الخطوات التالية:

  1. وضع علامة عنصر نائب: استخدِم علامة واحدة (مثل {{invoice-table}}) في مستند النموذج لتحديد المكان الذي يجب أن تظهر فيه القائمة.
  2. تحديد موقع العنصر النائب: استخدِم عملية بحث للعثور على الفهرس الأوّلي للعلامة.
  3. حذف العنصر النائب: استخدِم DeleteContentRangeRequest لإزالة النص {{invoice-table}}.
  4. إدراج الجدول: أرسِل InsertTableRequest في فهرس البداية هذا، مع تحديد عدد الصفوف والأعمدة استنادًا إلى مصدر البيانات.
  5. كتابة القيم: املأ كل خلية في الجدول بالتسلسل.

للاطّلاع على أمثلة حول إدراج الجداول آليًا، يُرجى الاطّلاع على العمل مع الجداول.