Google Docs API를 사용하면 이름이 지정된 범위를 사용하여 일부 수정 작업을 간소화할 수 있습니다.
이름이 지정된 범위를 만들면 나중에 참조할 수 있는 문서 섹션이 식별됩니다. 콘텐츠가 문서에 추가되거나 문서에서 삭제되면 명명된 범위의 색인이 자동으로 업데이트됩니다. 이렇게 하면 수정할 텍스트를 쉽게 찾을 수 있습니다. 수정사항을 추적하거나 문서를 검색할 필요가 없기 때문입니다. 대신 이름이 지정된 범위를 읽고 색인을 사용하여 수정 위치를 가져올 수 있습니다.
예를 들어 문서에 '제품 설명' 문자열이 표시되어야 하는 명명된 범위를 만든다고 가정해 보겠습니다.
이렇게 하면 설명을 대체할 수 있습니다. 명명된 범위의 시작 및 종료 색인을 가져온 다음 해당 색인 사이의 텍스트를 새 콘텐츠로 업데이트하면 됩니다.
다음 예시 코드는 CreateNamedRangeRequest를 사용하여 이전에 생성된 명명된 범위가 있는 문서의 첫 번째 탭에서 명명된 범위의 콘텐츠를 대체하는 도우미 함수를 구현하는 방법을 보여줍니다.
모든 탭의 명명된 범위를 바꾸려면 이 코드를 보강하여 모든 탭을 반복하면 됩니다. 자세한 내용과 샘플 코드는 탭 사용을 참고하세요.
자바
/** Replaces the text in existing named ranges. */staticvoidreplaceNamedRange(Docsservice,StringdocumentId,StringrangeName,StringnewText)throwsIOException{// Fetch the document to determine the current indexes of the named ranges.Documentdocument=service.documents().get(documentId).setIncludeTabsContent(true).execute();// Find the matching named ranges in the first tab of the document.NamedRangesnamedRangeList=document.getTabs()[0].getDocumentTab().getNamedRanges().get(rangeName);if(namedRangeList==null){thrownewIllegalArgumentException("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=newArrayList<>();Set<Integer>insertIndexes=newHashSet<>();for(NamedRangenamedRange: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=newArrayList<>();for(Rangerange:allRanges){// Delete all the content in the existing range.requests.add(newRequest().setDeleteContentRange(newDeleteContentRangeRequest().setRange(range)));if(insertIndexes.contains(range.getStartIndex())){// Insert the replacement text.requests.add(newRequest().setInsertText(newInsertTextRequest().setLocation(newLocation().setSegmentId(range.getSegmentId()).setIndex(range.getStartIndex()).setTabId(range.getTabId())).setText(newText)));// Re-create the named range on the new text.requests.add(newRequest().setCreateNamedRange(newCreateNamedRangeRequest().setName(rangeName).setRange(newRange().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.BatchUpdateDocumentRequestbatchUpdateRequest=newBatchUpdateDocumentRequest().setRequests(requests).setWriteControl(newWriteControl().setRequiredRevisionId(document.getRevisionId()));service.documents().batchUpdate(documentId,batchUpdateRequest).execute();}
Python
defreplace_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_indexnew_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))ifnotnamed_range_list:raiseException('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={}fornamed_rangeinnamed_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=lambdar:r.get('startIndex'),reverse=True)# Create a sequence of requests for each range.requests=[]forrinall_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')ifinsert_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()
이름이 지정된 범위는 문서 콘텐츠의 범위를 지정하지만 해당 콘텐츠의 일부는 아닙니다. 이름이 지정된 범위를 포함하는 콘텐츠를 추출한 다음 다른 위치에 삽입하면 이름이 지정된 범위는 복제된 섹션이 아닌 원본 콘텐츠만 가리킵니다.
[null,null,["최종 업데이트: 2025-08-29(UTC)"],[],[],null,["# Work with named ranges\n\nThe Google Docs API lets you use *named ranges* to simplify some editing tasks.\n\nWhen you create a named range, you identify a section of the document that you\ncan reference later. The indexes of the named range are automatically updated as\ncontent is added to and removed from the document. This simplifies how you\nlocate text for updating in the future, since you don't need to track the\nediting changes or search through the document. Instead, you can get an edit\nlocation by reading the named range and using its indexes.\n\nFor example, suppose you create a named range where a \"product description\"\nstring must appear in a document:\n\nThis lets you replace the description: you just get the start and end indexes of\nthe named range, and then update the text between those indexes with your new\ncontent.\n\nThe following example code shows how you might implement a helper function to\nreplace contents of a named range in the first tab of the document, where the\nnamed range was previously created using the\n[`CreateNamedRangeRequest`](/workspace/docs/api/reference/rest/v1/documents/request#createnamedrangerequest).\nTo replace the named ranges from all tabs, this code can be augmented to iterate\nacross all tabs. See [Work with Tabs](/workspace/docs/api/how-tos/tabs) for more\ninformation and sample code. \n\n### Java\n\n```java\n/** Replaces the text in existing named ranges. */\nstatic void replaceNamedRange(Docs service, String documentId, String rangeName, String newText)\n throws IOException {\n // Fetch the document to determine the current indexes of the named ranges.\n Document document =\n service.documents().get(documentId).setIncludeTabsContent(true).execute();\n\n // Find the matching named ranges in the first tab of the document.\n NamedRanges namedRangeList =\n document.getTabs()[0].getDocumentTab().getNamedRanges().get(rangeName);\n if (namedRangeList == null) {\n throw new IllegalArgumentException(\"The named range is no longer present in the document.\");\n }\n\n // Determine all the ranges of text to be removed, and at which indexes the replacement text\n // should be inserted.\n List\u003cRange\u003e allRanges = new ArrayList\u003c\u003e();\n Set\u003cInteger\u003e insertIndexes = new HashSet\u003c\u003e();\n for (NamedRange namedRange : namedRangeList.getNamedRanges()) {\n allRanges.addAll(namedRange.getRanges());\n insertIndexes.add(namedRange.getRanges().get(0).getStartIndex());\n }\n\n // Sort the list of ranges by startIndex, in descending order.\n allRanges.sort(Comparator.comparing(Range::getStartIndex).reversed());\n\n // Create a sequence of requests for each range.\n List\u003cRequest\u003e requests = new ArrayList\u003c\u003e();\n for (Range range : allRanges) {\n // Delete all the content in the existing range.\n requests.add(\n new Request().setDeleteContentRange(new DeleteContentRangeRequest().setRange(range)));\n\n if (insertIndexes.contains(range.getStartIndex())) {\n // Insert the replacement text.\n requests.add(\n new Request()\n .setInsertText(\n new InsertTextRequest()\n .setLocation(\n new Location()\n .setSegmentId(range.getSegmentId())\n .setIndex(range.getStartIndex())\n .setTabId(range.getTabId()))\n .setText(newText)));\n\n // Re-create the named range on the new text.\n requests.add(\n new Request()\n .setCreateNamedRange(\n new CreateNamedRangeRequest()\n .setName(rangeName)\n .setRange(\n new Range()\n .setSegmentId(range.getSegmentId())\n .setStartIndex(range.getStartIndex())\n .setEndIndex(range.getStartIndex() + newText.length())\n .setTabId(range.getTabId()))));\n }\n }\n\n // Make a batchUpdate request to apply the changes, ensuring the document hasn't changed since\n // we fetched it.\n BatchUpdateDocumentRequest batchUpdateRequest =\n new BatchUpdateDocumentRequest()\n .setRequests(requests)\n .setWriteControl(new WriteControl().setRequiredRevisionId(document.getRevisionId()));\n service.documents().batchUpdate(documentId, batchUpdateRequest).execute();\n}\n```\n\n### Python\n\n```python\ndef replace_named_range(service, document_id, range_name, new_text):\n \"\"\"Replaces the text in existing named ranges.\"\"\"\n\n # Determine the length of the replacement text, as UTF-16 code units.\n # https://developers.google.com/workspace/docs/api/concepts/structure#start_and_end_index\n new_text_len = len(new_text.encode('utf-16-le')) / 2\n\n # Fetch the document to determine the current indexes of the named ranges.\n document = (\n service.documents()\n .get(documentId=document_id, includeTabsContent=True)\n .execute()\n )\n\n # Find the matching named ranges in the first tab of the document.\n named_range_list = (\n document.get('tabs')[0]\n .get('documentTab')\n .get('namedRanges', {})\n .get(range_name)\n )\n if not named_range_list:\n raise Exception('The named range is no longer present in the document.')\n\n # Determine all the ranges of text to be removed, and at which indices the\n # replacement text should be inserted.\n all_ranges = []\n insert_at = {}\n for named_range in named_range_list.get('namedRanges'):\n ranges = named_range.get('ranges')\n all_ranges.extend(ranges)\n # Most named ranges only contain one range of text, but it's possible\n # for it to be split into multiple ranges by user edits in the document.\n # The replacement text should only be inserted at the start of the first\n # range.\n insert_at[ranges[0].get('startIndex')] = True\n\n # Sort the list of ranges by startIndex, in descending order.\n all_ranges.sort(key=lambda r: r.get('startIndex'), reverse=True)\n\n # Create a sequence of requests for each range.\n requests = []\n for r in all_ranges:\n # Delete all the content in the existing range.\n requests.append({\n 'deleteContentRange': {\n 'range': r\n }\n })\n\n segment_id = r.get('segmentId')\n start = r.get('startIndex')\n tab_id = r.get('tabId')\n if insert_at[start]:\n # Insert the replacement text.\n requests.append({\n 'insertText': {\n 'location': {\n 'segmentId': segment_id,\n 'index': start,\n 'tabId': tab_id\n },\n 'text': new_text\n }\n })\n # Re-create the named range on the new text.\n requests.append({\n 'createNamedRange': {\n 'name': range_name,\n 'range': {\n 'segmentId': segment_id,\n 'startIndex': start,\n 'endIndex': start + new_text_len,\n 'tabId': tab_id\n }\n }\n })\n\n # Make a batchUpdate request to apply the changes, ensuring the document\n # hasn't changed since we fetched it.\n body = {\n 'requests': requests,\n 'writeControl': {\n 'requiredRevisionId': document.get('revisionId')\n }\n }\n service.documents().batchUpdate(documentId=document_id, body=body).execute()\n```\n| Named ranges are not private. Anyone using the Docs API to access the document can see the named range definition.\n\nNote that named ranges specify a range of document content, but are not part of\nthat content. If you extract content that includes a named range, then insert it\nat another location, the named range only points to the original content and not\nthe duplicated section."]]