A API Google Docs permite criar, inserir, atualizar, ler e gerenciar ícones de menu suspenso de forma programática em documentos do Google Docs.
O que são ícones de menu suspenso?
Os ícones de menu suspenso no Google Docs oferecem aos usuários um menu de seleção interativo e personalizável em linha com o texto do documento. Os usuários podem clicar em um ícone de menu suspenso para selecionar em uma lista predefinida de opções, cada uma com seu próprio texto de exibição e estilo de cor. Os ícones de menu suspenso são usados com frequência para rastreamento de projetos, atualizações de status, fluxos de trabalho de revisão e etapas de aprovação.
Com a API Docs, você pode:
- Defina modelos de menu suspenso reutilizáveis com títulos, nomes de opções e cores personalizados.
- Insira ícones de menu suspenso em um local de caractere válido.
- Atualiza a opção selecionada de uma instância de ícone de menu suspenso individual.
- Modifique as definições de menus suspensos compartilhados no lugar, atualizando todos os chips de referência simultaneamente.
- Substitua ou desative opções com segurança, mantendo a integridade referencial em todos os chips atuais.
- Exclua modelos de menu suspenso não usados.
Arquitetura: definições e instâncias
Na API Docs, os ícones de menu suspenso têm definições e instâncias. Uma definição define opções para uma instância de menu suspenso. Uma instância de menu suspenso é um menu com que as pessoas podem interagir e que salva informações sobre as seleções.
A API Docs separa a configuração do modelo de menu suspenso das instâncias de ícone de menu suspenso inline:
- DropdownDefinition: um modelo no nível da guia que define o título do menu suspenso e a coleção de opções selecionáveis (
DropdownOption). Ele não reside em um deslocamento de caractere específico no documento. Em vez disso, é armazenado no mapa de definição da guia:document.tabs[].documentTab.dropdownDefinitions. - Menu suspenso: uma instância de chip individual incorporada inline em um elemento de parágrafo (
ParagraphElement.dropdown). Cada instância de menu suspenso faz referência a umdropdownDefinitionIde armazena seu próprioselectedOptionIdativo.
Ao modificar um DropdownDefinition (por exemplo, adicionar uma opção ou renomear o título), todos os ícones de referência na guia são atualizados sem exigir atualizações em cada elemento individual.
Cada instância de Dropdown rastreia o próprio selectedOptionId. A mutação do valor selecionado de um chip individual afeta apenas essa instância específica.
Formato e regras de validação de ID
Os IDs fornecidos pelo usuário precisam obedecer a especificações rigorosas de formato, prefixo e comprimento:
| Identificador | Prefixo obrigatório | Expressão regular de validação | Limite de tamanho | Exemplo |
|---|---|---|---|---|
ID da definição do menu suspenso (dropdownDefinitionId) |
kix. |
^kix\.[a-zA-Z0-9_-]{2,14}$ |
6 a 18 caracteres | kix.review_status |
ID da opção do menu suspenso (optionId) |
dropdownItem. |
^dropdownItem\.[a-zA-Z0-9_-]{2,14}$ |
15 a 27 caracteres | dropdownItem.pending |
Gerar IDs fornecidos pelo usuário
Para gerar IDs que atendam aos requisitos obrigatórios de prefixo e expressão regular, use as seguintes funções auxiliares. Esses helpers geram sufixos alfanuméricos de base 36 em letras minúsculas, correspondentes ao formato gerado pela interface do Google Docs:
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();
}
}
Criar e inserir ícones de menu suspenso
Criação de lote único (recomendado)
O padrão mais eficiente combina CreateDropdownDefinitionRequest e InsertDropdownRequest em uma chamada documents.batchUpdate.
O exemplo de código a seguir cria uma definição de menu suspenso "Status da revisão" com três opções codificadas por cores usando IDs fornecidos pelo usuário e insere uma instância no final do documento:
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();
Regras e limites de validação de menus suspensos
Ao criar ou modificar definições de menu suspenso, as seguintes restrições se aplicam:
- Contagem de opções: uma definição de menu suspenso precisa ter entre 2 e 50 opções.
- Tamanho do título: a definição
titlenão pode estar vazia e não pode exceder 200 caracteres. - Comprimento do valor de exibição: cada
displayValuede opção não pode estar vazio e não pode exceder 200 caracteres. - Estilo de opção: apenas
foregroundColorebackgroundColorsão compatíveis comDropdownOption.textStyle. Definir outras propriedades de estilo retorna um erro400 Bad Request. - Seleção padrão: em
InsertDropdownRequest, seselectedOptionIdfor omitido, o ícone vai usar a primeira opção definida emDropdownDefinition.
Atualizar a seleção de um ícone de menu suspenso individual
Para mudar a opção selecionada de uma instância de ícone de menu suspenso sem alterar o modelo ou outros ícones, use UpdateDropdownPropertiesRequest:
dropdownId: (obrigatório) o ID da instância específica do ícone de menu suspenso a ser atualizada.tabId: o ID da guia que contém o menu suspenso (o padrão é a primeira guia se omitido).- Defina
fieldscomo"selectedOptionId".
O exemplo de código a seguir atualiza a seleção ativa de um ícone de menu suspenso para "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();
Atualizar definições e opções do menu suspenso
Para modificar o modelo em si (título, lista de opções, rótulos de exibição ou cores), use UpdateDropdownDefinitionPropertiesRequest. Atualizar uma definição atualiza automaticamente todos os ícones de menu suspenso que fazem referência a ela na guia.
Substituição completa da lista de opções
Quando dropdownDefinitionProperties.options é incluído na máscara fields, a solicitação realiza uma substituição completa da lista. Você precisa fornecer a lista completa de opções na ordem escolhida. O servidor diferencia a lista recebida da definição atual:
- Nova opção: incluir uma opção sem um
optionId(ou com um novooptionIdfornecido pelo usuário) adiciona essa opção à definição. - Opção atualizada: fornecer um
optionIdcomdisplayValueoutextStylemodificados atualiza essa opção no lugar. - Opções reordenadas: a lista de opções é salva na sequência exata fornecida na solicitação.
- Opção excluída: omitir um
optionIdexistente exclui essa opção da definição.
Integridade referencial e substituição de opções
Se uma opção excluída estiver selecionada em um ícone de menu suspenso no documento, você precisa fornecer um mapeamento em selectedOptionIdReplacements (map<string, string>). As chaves são os IDs das opções excluídas, e os valores são os IDs das opções de substituição.
O exemplo de código a seguir demonstra como atualizar uma definição de menu suspenso com substituições de opções:
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();
Excluir uma definição de menu suspenso
Para remover um modelo de menu suspenso não usado, use DeleteDropdownDefinitionRequest.
O exemplo de código a seguir demonstra como excluir uma definição de menu suspenso:
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();
Tratamento de erros e solução de problemas
Condições de erro e soluções comuns:
| Código de status | Causa | Resolução |
|---|---|---|
400 INVALID_ARGUMENT |
Prefixo de ID ou formato de expressão regular inválido. | Verifique se dropdownDefinitionId começa com kix. (6 a 18 caracteres) e optionId começa com dropdownItem. (15 a 27 caracteres). |
400 INVALID_ARGUMENT |
A contagem de opções está fora dos limites. | Uma definição de menu suspenso precisa ter entre 2 e 50 opções. |
400 INVALID_ARGUMENT |
O título ou o valor de exibição está vazio ou excede 200 caracteres. | Forneça uma string não vazia com 1 a 200 caracteres. |
400 INVALID_ARGUMENT |
Propriedade de estilo de texto incompatível na opção. | Somente foregroundColor e backgroundColor são compatíveis com opções de menu suspenso. Remova a fonte, o tamanho ou outros atributos. |
400 INVALID_ARGUMENT |
Mapeamento de substituição de opção ausente na exclusão. | Ao excluir uma opção selecionada por um ícone, forneça uma substituição válida em selectedOptionIdReplacements. |
400 INVALID_ARGUMENT |
Tentativa de excluir uma definição em uso. | Exclua ou redefina todas as instâncias de ícone de menu suspenso que fazem referência à definição antes de excluí-la. |
400 INVALID_ARGUMENT |
ID duplicado fornecido pelo usuário. | Verifique se os IDs fornecidos pelo usuário são exclusivos na guia "Documento". |
Temas relacionados
- Como trabalhar com guias
- Formatar texto
- Trabalhar com comentários e sugestões
- Recurso REST: documents.request
- Recurso REST: documentos
- Recurso REST: documents.batchUpdate