使用下拉式選單方塊

Google 文件 API 可讓您以程式輔助方式,在 Google 文件文件中建立、插入、更新、讀取及管理下拉式選單方塊。

什麼是下拉式選單方塊?

Google 文件的下拉式選單方塊提供互動式自訂選單,可直接插入文件文字中。使用者可以點按下拉式選單方塊,從預先定義的選項清單中選取項目,每個選項都有專屬的顯示文字和顏色樣式。下拉式選單方塊常用於追蹤專案、更新狀態、審查工作流程和核准階段。

透過 Docs API,您可以:

  • 定義可重複使用的下拉式選單範本,並自訂標題、選項名稱和顏色。
  • 在有效字元位置插入下拉式選單晶片。
  • 更新個別下拉式選單方塊例項的所選選項。
  • 直接修改共用下拉式選單定義,同時更新所有參照的晶片。
  • 安全地替換或淘汰選項,同時維持現有晶片之間的參照完整性。
  • 刪除未使用的下拉式選單範本。

架構:定義和執行個體

在 Google 文件 API 中,下拉式選單方塊有定義和執行個體。定義會為下拉式選單執行個體設定選項。下拉式選單執行個體是可供使用者互動的下拉式選單,並會儲存選取項目的相關資訊。

Docs API 會將下拉式選單範本設定與內嵌下拉式選單方塊執行個體分開:

  1. DropdownDefinition:定義下拉式選單標題和可選選項集合 (DropdownOption) 的分頁層級範本。它不會位於文件中的特定字元偏移,而是儲存在分頁的定義對應中:document.tabs[].documentTab.dropdownDefinitions。
  2. 下拉式選單:內嵌在段落元素 (ParagraphElement.dropdown) 中的個別晶片例項。每個下拉式選單例項都會參照 dropdownDefinitionId,並儲存自己的有效 selectedOptionId。

修改 DropdownDefinition (例如新增選項或重新命名標題) 時,系統會更新分頁中的所有參照晶片,不必更新每個個別元素。

每個 Dropdown 執行個體都會追蹤自己的 selectedOptionId。變更個別動態磚的選取值只會影響該特定例項。

ID 格式和驗證規則

使用者提供的 ID 必須符合嚴格的格式、前置字串和長度規格:

ID 必要前置字串 驗證規則運算式 長度限制 範例
下拉式選單定義 ID (dropdownDefinitionId) kix. ^kix\.[a-zA-Z0-9_-]{2,14}$ 6 至 18 個字元 kix.review_status
下拉式選單選項 ID (optionId) dropdownItem. ^dropdownItem\.[a-zA-Z0-9_-]{2,14}$ 15 至 27 個字元 dropdownItem.pending

產生使用者提供的 ID

如要產生符合必要前置字元和規則運算式規定的 ID,請使用下列輔助函式。這些輔助程式會產生小寫的 base-36 英數後置字串,格式與 Google 文件 UI 產生的格式相符:

Python

import random
import string

def generate_dropdown_definition_id(suffix_len: int = 8) -> str:
    """Generates a valid user-provided DropdownDefinition ID (6-18 chars, starting with 'kix.')."""
    chars = string.ascii_lowercase + string.digits
    suffix = "".join(random.choices(chars, k=max(2, min(suffix_len, 14))))
    return f"kix.{suffix}"

def generate_dropdown_option_id(suffix_len: int = 8) -> str:
    """Generates a valid user-provided DropdownOption ID (15-27 chars, starting with 'dropdownItem.')."""
    chars = string.ascii_lowercase + string.digits
    suffix = "".join(random.choices(chars, k=max(2, min(suffix_len, 14))))
    return f"dropdownItem.{suffix}"

Java

import java.security.SecureRandom;

public final class DropdownIdGenerator {
  private static final String BASE36_CHARS =
      "abcdefghijklmnopqrstuvwxyz0123456789";
  private static final SecureRandom RANDOM = new SecureRandom();

  private DropdownIdGenerator() {}

  /** Generates a valid user-provided DropdownDefinition ID (6-18 chars, starting with "kix."). */
  public static String generateDefinitionId(int suffixLength) {
    int length = Math.max(2, Math.min(suffixLength, 14));
    StringBuilder sb = new StringBuilder("kix.");
    for (int i = 0; i < length; i++) {
      sb.append(BASE36_CHARS.charAt(RANDOM.nextInt(BASE36_CHARS.length())));
    }
    return sb.toString();
  }

  /** Generates a valid user-provided DropdownOption ID (15-27 chars, starting with "dropdownItem."). */
  public static String generateOptionId(int suffixLength) {
    int length = Math.max(2, Math.min(suffixLength, 14));
    StringBuilder sb = new StringBuilder("dropdownItem.");
    for (int i = 0; i < length; i++) {
      sb.append(BASE36_CHARS.charAt(RANDOM.nextInt(BASE36_CHARS.length())));
    }
    return sb.toString();
  }
}

建立及插入下拉式選單方塊

單一批次建立 (建議)

最有效率的模式是將 CreateDropdownDefinitionRequest 和 InsertDropdownRequest 合併為一次 documents.batchUpdate 呼叫。

下列程式碼範例會使用使用者提供的 ID,建立「審查狀態」下拉式選單定義,並提供三種顏色編碼的選項,然後在文件結尾插入執行個體:

Python

requests = [
    {
        "createDropdownDefinition": {
            "dropdownDefinition": {
                "dropdownDefinitionId": "kix.review_status",
                "dropdownDefinitionProperties": {
                    "title": "Review Status",
                    "options": [
                        {
                            "optionId": "dropdownItem.pending",
                            "displayValue": "Pending Review",
                            "textStyle": {
                                "backgroundColor": {
                                    "color": {"rgbColor": {"red": 0.99, "green": 0.90, "blue": 0.65}}
                                },
                                "foregroundColor": {
                                    "color": {"rgbColor": {"red": 0.45, "green": 0.30, "blue": 0.0}}
                                },
                            },
                        },
                        {
                            "optionId": "dropdownItem.approved",
                            "displayValue": "Approved",
                            "textStyle": {
                                "backgroundColor": {
                                    "color": {"rgbColor": {"red": 0.85, "green": 0.95, "blue": 0.85}}
                                },
                                "foregroundColor": {
                                    "color": {"rgbColor": {"red": 0.08, "green": 0.40, "blue": 0.15}}
                                },
                            },
                        },
                        {
                            "optionId": "dropdownItem.rejected",
                            "displayValue": "Needs Changes",
                            "textStyle": {
                                "backgroundColor": {
                                    "color": {"rgbColor": {"red": 0.98, "green": 0.84, "blue": 0.84}}
                                },
                                "foregroundColor": {
                                    "color": {"rgbColor": {"red": 0.65, "green": 0.10, "blue": 0.10}}
                                },
                            },
                        },
                    ],
                },
            }
        }
    },
    {
        "insertDropdown": {
            "endOfSegmentLocation": {},
            "dropdownDefinitionId": "kix.review_status",
            "selectedOptionId": "dropdownItem.pending",
        }
    },
]

result = service.documents().batchUpdate(
    documentId=DOCUMENT_ID,
    body={"requests": requests}
).execute()

Java

List<Request> requests = new ArrayList<>();

List<DropdownOption> options = Arrays.asList(
    new DropdownOption()
        .setOptionId("dropdownItem.pending")
        .setDisplayValue("Pending Review")
        .setTextStyle(new TextStyle()
            .setBackgroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.99f).setGreen(0.90f).setBlue(0.65f))))
            .setForegroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.45f).setGreen(0.30f).setBlue(0.0f))))),
    new DropdownOption()
        .setOptionId("dropdownItem.approved")
        .setDisplayValue("Approved")
        .setTextStyle(new TextStyle()
            .setBackgroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.85f).setGreen(0.95f).setBlue(0.85f))))
            .setForegroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.08f).setGreen(0.40f).setBlue(0.15f))))),
    new DropdownOption()
        .setOptionId("dropdownItem.rejected")
        .setDisplayValue("Needs Changes")
        .setTextStyle(new TextStyle()
            .setBackgroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.98f).setGreen(0.84f).setBlue(0.84f))))
            .setForegroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.65f).setGreen(0.10f).setBlue(0.10f))))));

DropdownDefinition definition = new DropdownDefinition()
    .setDropdownDefinitionId("kix.review_status")
    .setDropdownDefinitionProperties(new DropdownDefinitionProperties()
        .setTitle("Review Status")
        .setOptions(options));

requests.add(new Request().setCreateDropdownDefinition(
    new CreateDropdownDefinitionRequest().setDropdownDefinition(definition)));

requests.add(new Request().setInsertDropdown(
    new InsertDropdownRequest()
        .setEndOfSegmentLocation(new EndOfSegmentLocation())
        .setDropdownDefinitionId("kix.review_status")
        .setSelectedOptionId("dropdownItem.pending")));

BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest().setRequests(requests);
BatchUpdateDocumentResponse response = docsService.documents()
    .batchUpdate(DOCUMENT_ID, body)
    .execute();

下拉式選單驗證規則和限制

建立或修改下拉式選單定義時,須遵守下列限制:

  • 選項數量:下拉式選單定義必須有 2 到 50 個選項。
  • 標題長度:定義 title 不得為空白,且不得超過 200 個字元。
  • 顯示值長度:每個選項的 displayValue 不得為空,且不得超過 200 個字元。
  • 選項樣式:DropdownOption.textStyle 僅支援 foregroundColor 和 backgroundColor。設定其他樣式屬性會傳回 400 Bad Request 錯誤。
  • 預設選取:在 InsertDropdownRequest 中,如果省略 selectedOptionId,方塊預設為 DropdownDefinition 中定義的第一個選項。

更新個別下拉式選單方塊的選取項目

如要變更現有下拉式選單方塊例項的所選選項,但不想變更範本或其他方塊,請使用 UpdateDropdownPropertiesRequest:

  • dropdownId:(必要) 要更新的特定下拉式選單方塊執行個體 ID。
  • tabId:含有下拉式選單的分頁 ID (如省略,則預設為第一個分頁)。
  • fields:設為 "selectedOptionId"。

下列程式碼範例會將下拉式選單方塊的有效選取項目更新為 "dropdownItem.approved":

Python

requests = [
    {
        "updateDropdownProperties": {
            "dropdownId": "kix.chip_abc1",
            "tabId": "t.0",
            "dropdownProperties": {
                "selectedOptionId": "dropdownItem.approved",
            },
            "fields": "selectedOptionId",
        }
    }
]

result = service.documents().batchUpdate(
    documentId=DOCUMENT_ID,
    body={"requests": requests}
).execute()

Java

List<Request> requests = new ArrayList<>();
requests.add(new Request().setUpdateDropdownProperties(
    new UpdateDropdownPropertiesRequest()
        .setDropdownId("kix.chip_abc1")
        .setTabId("t.0")
        .setDropdownProperties(new DropdownProperties()
            .setSelectedOptionId("dropdownItem.approved"))
        .setFields("selectedOptionId")));

BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest().setRequests(requests);
BatchUpdateDocumentResponse response = docsService.documents()
    .batchUpdate(DOCUMENT_ID, body)
    .execute();

更新下拉式選單定義和選項

如要修改範本本身 (標題、選項清單、顯示標籤或顏色),請使用 UpdateDropdownDefinitionPropertiesRequest。更新定義後,分頁中所有參照該定義的下拉式選單方塊都會自動更新。

完整清單取代選項

如果 dropdownDefinitionProperties.options 包含在 fields 遮罩中,要求會執行完整清單替換。您必須按照所選順序提供完整選項清單。伺服器會比對傳入的清單與目前的定義:

  • 新選項:在定義中加入不含 optionId 的選項 (或含使用者提供的新 optionId)。
  • 更新選項:提供現有 optionId,並修改 displayValue 或 textStyle,即可更新該選項。
  • 重新排序的選項:選項清單會按照要求中提供的確切順序儲存。
  • 已刪除的選項:省略現有的 optionId 會從定義中刪除該選項。

參照完整性和選項替換

如果文件中的任何下拉式選單方塊選取了要刪除的選項,您必須在 selectedOptionIdReplacements (map<string, string>) 中提供對應項目。鍵是要刪除的選項 ID,值是替代選項的 ID。

下列程式碼範例說明如何使用選項取代項目更新下拉式選單定義:

Python

requests = [
    {
        "updateDropdownDefinitionProperties": {
            "dropdownDefinitionId": "kix.review_status",
            "tabId": "t.0",
            "dropdownDefinitionProperties": {
                "title": "Editorial Review Status",
                "options": [
                    {
                        "optionId": "dropdownItem.approved",
                        "displayValue": "Approved",
                        "textStyle": {
                            "backgroundColor": {
                                "color": {"rgbColor": {"red": 0.85, "green": 0.95, "blue": 0.85}}
                            },
                            "foregroundColor": {
                                "color": {"rgbColor": {"red": 0.08, "green": 0.40, "blue": 0.15}}
                            },
                        },
                    },
                    {
                        "optionId": "dropdownItem.rejected",
                        "displayValue": "Changes Requested",
                        "textStyle": {
                            "backgroundColor": {
                                "color": {"rgbColor": {"red": 0.98, "green": 0.84, "blue": 0.84}}
                            },
                            "foregroundColor": {
                                "color": {"rgbColor": {"red": 0.65, "green": 0.10, "blue": 0.10}}
                            },
                        },
                    },
                ],
            },
            "selectedOptionIdReplacements": {
                "dropdownItem.pending": "dropdownItem.rejected"
            },
            "fields": "title,options",
        }
    }
]

result = service.documents().batchUpdate(
    documentId=DOCUMENT_ID,
    body={"requests": requests}
).execute()

Java

List<DropdownOption> updatedOptions = Arrays.asList(
    new DropdownOption()
        .setOptionId("dropdownItem.approved")
        .setDisplayValue("Approved")
        .setTextStyle(new TextStyle()
            .setBackgroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.85f).setGreen(0.95f).setBlue(0.85f))))
            .setForegroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.08f).setGreen(0.40f).setBlue(0.15f))))),
    new DropdownOption()
        .setOptionId("dropdownItem.rejected")
        .setDisplayValue("Changes Requested")
        .setTextStyle(new TextStyle()
            .setBackgroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.98f).setGreen(0.84f).setBlue(0.84f))))
            .setForegroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.65f).setGreen(0.10f).setBlue(0.10f))))));

Map<String, String> replacements = new HashMap<>();
replacements.put("dropdownItem.pending", "dropdownItem.rejected");

List<Request> requests = new ArrayList<>();
requests.add(new Request().setUpdateDropdownDefinitionProperties(
    new UpdateDropdownDefinitionPropertiesRequest()
        .setDropdownDefinitionId("kix.review_status")
        .setTabId("t.0")
        .setDropdownDefinitionProperties(new DropdownDefinitionProperties()
            .setTitle("Editorial Review Status")
            .setOptions(updatedOptions))
        .setSelectedOptionIdReplacements(replacements)
        .setFields("title,options")));

BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest().setRequests(requests);
BatchUpdateDocumentResponse response = docsService.documents()
    .batchUpdate(DOCUMENT_ID, body)
    .execute();

刪除下拉式選單定義

如要移除未使用的下拉式選單範本,請使用 DeleteDropdownDefinitionRequest。

下列程式碼範例示範如何刪除下拉式選單定義:

Python

requests = [
    {
        "deleteDropdownDefinition": {
            "dropdownDefinitionId": "kix.review_status",
            "tabId": "t.0",
        }
    }
]

result = service.documents().batchUpdate(
    documentId=DOCUMENT_ID,
    body={"requests": requests}
).execute()

Java

List<Request> requests = new ArrayList<>();
requests.add(new Request().setDeleteDropdownDefinition(
    new DeleteDropdownDefinitionRequest()
        .setDropdownDefinitionId("kix.review_status")
        .setTabId("t.0")));

BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest().setRequests(requests);
BatchUpdateDocumentResponse response = docsService.documents()
    .batchUpdate(DOCUMENT_ID, body)
    .execute();

錯誤處理和疑難排解

常見錯誤狀況和解決方法:

狀態碼 原因 解析度
400 INVALID_ARGUMENT ID 前置字串或規則運算式格式無效。 請確認 dropdownDefinitionId 開頭為 kix. (6 至 18 個半形字元),且 optionId 開頭為 dropdownItem. (15 至 27 個半形字元)。
400 INVALID_ARGUMENT 選項數量超出範圍。 下拉式選單定義必須包含 2 到 50 個選項。
400 INVALID_ARGUMENT 標題或顯示值為空白,或超過 200 個字元。 請提供長度介於 1 到 200 個字元的非空白字串。
400 INVALID_ARGUMENT 選項中不支援的文字樣式屬性。 下拉式選單選項僅支援 foregroundColor 和 backgroundColor。移除字型、大小或其他屬性。
400 INVALID_ARGUMENT 刪除時缺少選項替代對應。 如果刪除的選項已由任何方塊選取,請在 selectedOptionIdReplacements 中提供有效的替代選項。
400 INVALID_ARGUMENT 嘗試刪除正在使用的定義。 如要刪除定義,請先刪除或重新指定參照該定義的所有下拉式選單方塊例項。
400 INVALID_ARGUMENT 使用者提供的 ID 重複。 確認使用者提供的 ID 在文件分頁中不重複。