ทํางานกับช่วงที่มีชื่อ

Google เอกสาร API ช่วยให้คุณใช้ช่วงที่มีชื่อเพื่อลดความซับซ้อนของงานแก้ไขบางอย่างได้

เมื่อสร้างช่วงที่มีชื่อ คุณจะระบุส่วนของเอกสารที่จะอ้างอิงได้ในภายหลัง ดัชนีของช่วงที่มีชื่อจะอัปเดตโดยอัตโนมัติเมื่อมีการเพิ่มและนำเนื้อหาออกจากเอกสาร วิธีนี้ช่วยให้คุณค้นหาข้อความเพื่ออัปเดตในอนาคตได้ง่ายขึ้น เนื่องจากคุณไม่จําเป็นต้องติดตามการเปลี่ยนแปลงการแก้ไขหรือค้นหาในเอกสาร แต่คุณรับตำแหน่งการแก้ไขได้โดยการอ่านช่วงที่มีชื่อและใช้ดัชนีของช่วง

ตัวอย่างเช่น สมมติว่าคุณสร้างช่วงที่มีชื่อซึ่งสตริง "รายละเอียดผลิตภัณฑ์" ต้องปรากฏในเอกสาร

ซึ่งจะช่วยให้คุณแทนที่คำอธิบายได้ โดยเพียงแค่ดูดัชนีเริ่มต้นและสิ้นสุดของช่วงที่มีชื่อ แล้วอัปเดตข้อความระหว่างดัชนีเหล่านั้นด้วยเนื้อหาใหม่

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีใช้ฟังก์ชันตัวช่วยเพื่อแทนที่เนื้อหาของช่วงที่มีชื่อในแท็บแรกของเอกสาร ซึ่งก่อนหน้านี้มีการสร้างช่วงที่มีชื่อโดยใช้ CreateNamedRangeRequest หากต้องการแทนที่ช่วงที่มีชื่อจากทุกแท็บ ให้เพิ่มโค้ดนี้เพื่อวนซ้ำในทุกแท็บ ดูข้อมูลเพิ่มเติมและโค้ดตัวอย่างได้ที่หัวข้อทํางานกับแท็บ

Java

/** Replaces the text in existing named ranges. */
static void replaceNamedRange(Docs service, String documentId, String rangeName, String newText)
    throws IOException {
  // Fetch the document to determine the current indexes of the named ranges.
  Document document =
      service.documents().get(documentId).setIncludeTabsContent(true).execute();

  // Find the matching named ranges in the first tab of the document.
  NamedRanges namedRangeList =
      document.getTabs()[0].getDocumentTab().getNamedRanges().get(rangeName);
  if (namedRangeList == null) {
    throw new IllegalArgumentException("The named range is no longer present in the document.");
  }

  // Determine all the ranges of text to be removed, and at which indexes the replacement text
  // should be inserted.
  List<Range> allRanges = new ArrayList<>();
  Set<Integer> insertIndexes = new HashSet<>();
  for (NamedRange namedRange : namedRangeList.getNamedRanges()) {
    allRanges.addAll(namedRange.getRanges());
    insertIndexes.add(namedRange.getRanges().get(0).getStartIndex());
  }

  // Sort the list of ranges by startIndex, in descending order.
  allRanges.sort(Comparator.comparing(Range::getStartIndex).reversed());

  // Create a sequence of requests for each range.
  List<Request> requests = new ArrayList<>();
  for (Range range : allRanges) {
    // Delete all the content in the existing range.
    requests.add(
        new Request().setDeleteContentRange(new DeleteContentRangeRequest().setRange(range)));

    if (insertIndexes.contains(range.getStartIndex())) {
      // Insert the replacement text.
      requests.add(
          new Request()
              .setInsertText(
                  new InsertTextRequest()
                      .setLocation(
                          new Location()
                              .setSegmentId(range.getSegmentId())
                              .setIndex(range.getStartIndex())
                              .setTabId(range.getTabId()))
                      .setText(newText)));

      // Re-create the named range on the new text.
      requests.add(
          new Request()
              .setCreateNamedRange(
                  new CreateNamedRangeRequest()
                      .setName(rangeName)
                      .setRange(
                          new Range()
                              .setSegmentId(range.getSegmentId())
                              .setStartIndex(range.getStartIndex())
                              .setEndIndex(range.getStartIndex() + newText.length())
                              .setTabId(range.getTabId()))));
    }
  }

  // Make a batchUpdate request to apply the changes, ensuring the document hasn't changed since
  // we fetched it.
  BatchUpdateDocumentRequest batchUpdateRequest =
      new BatchUpdateDocumentRequest()
          .setRequests(requests)
          .setWriteControl(new WriteControl().setRequiredRevisionId(document.getRevisionId()));
  service.documents().batchUpdate(documentId, batchUpdateRequest).execute();
}

Python

def replace_named_range(service, document_id, range_name, new_text):
    """Replaces the text in existing named ranges."""

    # Determine the length of the replacement text, as UTF-16 code units.
    # https://developers.google.com/docs/api/concepts/structure#start_and_end_index
    new_text_len = len(new_text.encode('utf-16-le')) / 2

    # Fetch the document to determine the current indexes of the named ranges.
    document = (
        service.documents()
        .get(documentId=document_id, includeTabsContent=True)
        .execute()
    )

    # Find the matching named ranges in the first tab of the document.
    named_range_list = (
        document.get('tabs')[0]
        .get('documentTab')
        .get('namedRanges', {})
        .get(range_name)
    )
    if not named_range_list:
        raise Exception('The named range is no longer present in the document.')

    # Determine all the ranges of text to be removed, and at which indices the
    # replacement text should be inserted.
    all_ranges = []
    insert_at = {}
    for named_range in named_range_list.get('namedRanges'):
        ranges = named_range.get('ranges')
        all_ranges.extend(ranges)
        # Most named ranges only contain one range of text, but it's possible
        # for it to be split into multiple ranges by user edits in the document.
        # The replacement text should only be inserted at the start of the first
        # range.
        insert_at[ranges[0].get('startIndex')] = True

    # Sort the list of ranges by startIndex, in descending order.
    all_ranges.sort(key=lambda r: r.get('startIndex'), reverse=True)

    # Create a sequence of requests for each range.
    requests = []
    for r in all_ranges:
        # Delete all the content in the existing range.
        requests.append({
            'deleteContentRange': {
                'range': r
            }
        })

        segment_id = r.get('segmentId')
        start = r.get('startIndex')
        tab_id = r.get('tabId')
        if insert_at[start]:
            # Insert the replacement text.
            requests.append({
                'insertText': {
                    'location': {
                        'segmentId': segment_id,
                        'index': start,
                        'tabId': tab_id
                    },
                    'text': new_text
                }
            })
            # Re-create the named range on the new text.
            requests.append({
                'createNamedRange': {
                    'name': range_name,
                    'range': {
                        'segmentId': segment_id,
                        'startIndex': start,
                        'endIndex': start + new_text_len,
                        'tabId': tab_id
                    }
                }
            })

    # Make a batchUpdate request to apply the changes, ensuring the document
    # hasn't changed since we fetched it.
    body = {
        'requests': requests,
        'writeControl': {
            'requiredRevisionId': document.get('revisionId')
        }
    }
    service.documents().batchUpdate(documentId=document_id, body=body).execute()

โปรดทราบว่าช่วงที่มีชื่อจะระบุช่วงของเนื้อหาเอกสาร แต่ไม่ได้เป็นส่วนหนึ่งของเนื้อหานั้น หากคุณดึงข้อมูลที่มีช่วงที่มีชื่อ แล้วแทรกที่ตำแหน่งอื่น ช่วงที่มีชื่อจะชี้ไปยังเนื้อหาต้นฉบับเท่านั้น โดยไม่ชี้ไปยังส่วนที่ซ้ำกัน