با محدوده های نامگذاری شده کار کنید، با محدوده های نامگذاری شده کار کنید

API گوگل داکس به شما امکان می‌دهد از محدوده‌های نامگذاری‌شده برای ساده‌سازی برخی از کارهای ویرایشی استفاده کنید.

وقتی یک محدوده نامگذاری شده ایجاد می‌کنید، بخشی از سند را مشخص می‌کنید که می‌توانید بعداً به آن مراجعه کنید. شاخص‌های محدوده نامگذاری شده به طور خودکار با اضافه شدن و حذف محتوا از سند به‌روزرسانی می‌شوند. این کار نحوه یافتن متن برای به‌روزرسانی در آینده را ساده می‌کند، زیرا نیازی به پیگیری تغییرات ویرایش یا جستجو در سند ندارید. در عوض، می‌توانید با خواندن محدوده نامگذاری شده و استفاده از شاخص‌های آن، یک مکان ویرایش را دریافت کنید.

برای مثال، فرض کنید یک محدوده نامگذاری شده ایجاد می‌کنید که در آن رشته "توضیحات محصول" باید در یک سند ظاهر شود:

این به شما امکان می‌دهد توضیحات را جایگزین کنید: شما فقط اندیس‌های شروع و پایان محدوده نامگذاری شده را دریافت می‌کنید و سپس متن بین این اندیس‌ها را با محتوای جدید خود به‌روزرسانی می‌کنید.

کد مثال زیر نشان می‌دهد که چگونه می‌توانید یک تابع کمکی برای جایگزینی محتویات یک محدوده نامگذاری شده در اولین تب سند، جایی که محدوده نامگذاری شده قبلاً با استفاده از CreateNamedRangeRequest ایجاد شده است، پیاده‌سازی کنید. برای جایگزینی محدوده‌های نامگذاری شده از همه تب‌ها، این کد را می‌توان به گونه‌ای تکمیل کرد که در همه تب‌ها تکرار شود. برای اطلاعات بیشتر و نمونه کد، به بخش «کار با تب‌ها» مراجعه کنید.

جاوا

/** 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();
}

پایتون

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

توجه داشته باشید که محدوده‌های نامگذاری شده، محدوده‌ای از محتوای سند را مشخص می‌کنند، اما بخشی از آن محتوا نیستند. اگر محتوایی را که شامل یک محدوده نامگذاری شده است استخراج کنید، سپس آن را در مکان دیگری وارد کنید، محدوده نامگذاری شده فقط به محتوای اصلی اشاره می‌کند و نه به بخش کپی شده.