Interfejs Google Docs API umożliwia programowe tworzenie, wstawianie, aktualizowanie, odczytywanie i zarządzanie elementami menu w dokumentach Google.
Czym są elementy menu?
Elementy menu w Dokumentach Google zapewniają użytkownikom interaktywne, konfigurowalne menu wyboru w tekście dokumentu. Użytkownicy mogą kliknąć element menu, aby wybrać jedną z opcji z wstępnie zdefiniowanej listy. Każda z nich ma własny tekst wyświetlany i styl kolorów. Elementy menu są często używane do śledzenia projektów, aktualizowania stanu, przepływów pracy związanych z weryfikacją i etapów zatwierdzania.
Za pomocą interfejsu Docs API możesz:
- Definiuj szablony menu, których można używać wielokrotnie, z dostosowanymi tytułami, nazwami opcji i kolorami.
- Wstaw elementy menu w prawidłowym miejscu.
- Aktualizowanie wybranej opcji pojedynczej instancji elementu menu.
- Modyfikuj definicje udostępnionych menu w miejscu, aktualizując jednocześnie wszystkie powiązane z nimi elementy.
- Bezpiecznie zastępuj lub wycofuj opcje, zachowując integralność referencyjną w przypadku istniejących elementów.
- Usuń nieużywane szablony menu.
Architektura: definicje i instancje
W interfejsie Docs API elementy menu mają definicje i instancje. Definicja określa opcje instancji menu. Instancja menu to menu, z którym użytkownicy mogą wchodzić w interakcję, a które zapisuje informacje o wybranych opcjach.
Interfejs Docs API oddziela konfigurację szablonu menu od instancji wbudowanego elementu menu:
- DropdownDefinition: szablon na poziomie karty, który definiuje tytuł menu i zbiór opcji do wyboru (
DropdownOption). Nie znajduje się w określonym miejscu w dokumencie, ale jest przechowywany na mapie definicji karty:document.tabs[].documentTab.dropdownDefinitions. - Menu: pojedyncza instancja elementu wbudowana w element akapitu (
ParagraphElement.dropdown). Każda instancja menu odwołuje się do elementudropdownDefinitionIdi przechowuje własny aktywny elementselectedOptionId.
Zmiana DropdownDefinition (np. dodanie opcji lub zmiana nazwy) aktualizuje wszystkie powiązane z nią elementy na karcie bez konieczności aktualizowania każdego elementu z osobna.
Każda instancja Dropdown śledzi własną wartość selectedOptionId. Zmiana wybranej wartości pojedynczego elementu wpływa tylko na to konkretne wystąpienie.
Format identyfikatora i reguły sprawdzania poprawności
Identyfikatory przekazywane przez użytkowników muszą być zgodne z określonym formatem, prefiksem i długością:
| Identyfikator | Obowiązkowy prefiks | Wyrażenie regularne do weryfikacji | Limit długości | Przykład |
|---|---|---|---|---|
Identyfikator definicji menu (dropdownDefinitionId) |
kix. |
^kix\.[a-zA-Z0-9_-]{2,14}$ |
6–18 znaków | kix.review_status |
Identyfikator opcji menu (optionId) |
dropdownItem. |
^dropdownItem\.[a-zA-Z0-9_-]{2,14}$ |
15–27 znaków | dropdownItem.pending |
Generowanie identyfikatorów przekazywanych przez użytkowników
Aby wygenerować identyfikatory zgodne z wymaganiami dotyczącymi obowiązkowego prefiksu i wyrażenia regularnego, użyj tych funkcji pomocniczych. Te funkcje pomocnicze generują sufiksy alfanumeryczne w formacie base-36 pisane małymi literami, które są zgodne z formatem generowanym przez interfejs Dokumentów Google:
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();
}
}
Tworzenie i wstawianie elementów menu
Tworzenie pojedynczego wsadu (zalecane)
Najbardziej wydajny wzorzec łączy CreateDropdownDefinitionRequest i InsertDropdownRequest w jednym wywołaniu documents.batchUpdate.
Poniższy przykład kodu tworzy definicję menu „Stan weryfikacji” z 3 opcjami oznaczonymi kolorami przy użyciu identyfikatorów podanych przez użytkownika i wstawia instancję na końcu dokumentu:
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();
Reguły sprawdzania poprawności i limity w przypadku menu
Podczas tworzenia lub modyfikowania definicji menu obowiązują te ograniczenia:
- Liczba opcji: definicja menu musi zawierać od 2 do 50 opcji.
- Długość tytułu: definicja
titlenie może być pusta i nie może przekraczać 200 znaków. - Długość wyświetlanej wartości: pole
displayValuekażdej opcji nie może być puste i nie może przekraczać 200 znaków. - Styl opcji: w
DropdownOption.textStyleobsługiwane są tylko wartościforegroundColoribackgroundColor. Ustawienie innych właściwości stylu zwraca błąd400 Bad Request. - Domyślny wybór: w
InsertDropdownRequest, jeśli pominiętoselectedOptionId, domyślnie wybierana jest pierwsza opcja zdefiniowana wDropdownDefinition.
Aktualizowanie wyboru poszczególnych elementów menu
Aby zmienić wybraną opcję istniejącej instancji elementu menu bez modyfikowania szablonu ani innych elementów, użyj tego symbolu: UpdateDropdownPropertiesRequest.
dropdownId: (Wymagany) identyfikator konkretnej instancji elementu menu do zaktualizowania.tabId: Identyfikator karty zawierającej menu (jeśli zostanie pominięty, domyślnie używana jest pierwsza karta).fields: ustaw na"selectedOptionId".
Poniższy przykładowy kod aktualizuje aktywny wybór elementu menu do wyboru do "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();
Aktualizowanie definicji i opcji menu
Aby zmodyfikować sam szablon (tytuł, listę opcji, etykiety wyświetlania lub kolory), kliknij UpdateDropdownDefinitionPropertiesRequest. Zaktualizowanie definicji spowoduje automatyczne zaktualizowanie wszystkich powiązanych z nią elementów menu na karcie.
Pełna lista opcji zastępowania
Jeśli w masce fields znajduje się znak dropdownDefinitionProperties.options, żądanie powoduje pełną wymianę listy. Musisz podać pełną listę opcji w wybranej kolejności. Serwer porównuje listę przychodzącą z bieżącą definicją:
- Nowa opcja: dodanie opcji bez znaku
optionId(lub z nowym znakiemoptionIdpodanym przez użytkownika) powoduje dodanie jej do definicji. - Zaktualizowana opcja: podanie istniejącego elementu
optionIdze zmodyfikowanymi aktualizacjamidisplayValuelubtextStylepowoduje zaktualizowanie tej opcji. - Zmieniona kolejność opcji: lista opcji jest zapisywana w dokładnej kolejności podanej w żądaniu.
- Usunięta opcja: pominięcie istniejącego elementu
optionIdpowoduje usunięcie tej opcji z definicji.
Integralność referencyjna i zastępowanie opcji
Jeśli usuwana opcja jest wybrana w dowolnym elemencie menu w dokumencie, musisz podać mapowanie w selectedOptionIdReplacements (map<string, string>). Kluczami są identyfikatory usuwanych opcji, a wartościami identyfikatory opcji zastępczych.
Poniższy przykładowy kod pokazuje, jak zaktualizować definicję menu z zastąpieniami opcji:
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();
Usuwanie definicji menu
Aby usunąć nieużywany szablon menu, kliknij DeleteDropdownDefinitionRequest.
Poniższy przykładowy kod pokazuje, jak usunąć definicję menu:
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();
Obsługa błędów i rozwiązywanie problemów
Typowe błędy i sposoby ich rozwiązywania:
| Kod stanu | Przyczyna | Rozdzielczość |
|---|---|---|
400 INVALID_ARGUMENT |
Nieprawidłowy prefiks identyfikatora lub format wyrażenia regularnego. | Sprawdź, czy dropdownDefinitionId zaczyna się od kix. (6–18 znaków), a optionId zaczyna się od dropdownItem. (15–27 znaków). |
400 INVALID_ARGUMENT |
Liczba opcji poza zakresem. | Definicja menu musi zawierać od 2 do 50 opcji. |
400 INVALID_ARGUMENT |
Tytuł lub wyświetlana wartość jest pusta lub przekracza 200 znaków. | Podaj niepusty ciąg znaków o długości od 1 do 200 znaków. |
400 INVALID_ARGUMENT |
Nieobsługiwana właściwość stylu tekstu w opcji. | W przypadku opcji menu obsługiwane są tylko wartości foregroundColor i backgroundColor. Usuń czcionkę, rozmiar lub inne atrybuty. |
400 INVALID_ARGUMENT |
Brak mapowania zastępczego opcji podczas usuwania. | Jeśli usuwasz opcję wybraną przez dowolny element, podaj prawidłową opcję zastępczą w polu selectedOptionIdReplacements. |
400 INVALID_ARGUMENT |
Próbowano usunąć definicję, która jest używana. | Zanim usuniesz definicję, usuń wszystkie instancje elementu menu lub zmień ich docelowy element. |
400 INVALID_ARGUMENT |
Zduplikowany identyfikator przekazywany przez użytkownika. | Upewnij się, że identyfikatory przekazywane przez użytkowników są unikalne na karcie dokumentu. |
Powiązane artykuły
- Praca z kartami
- Formatowanie tekstu
- Praca z komentarzami i sugestiami
- Zasób REST: documents.request
- Zasób REST: documents
- Zasób REST: documents.batchUpdate