La API de Google Docs te permite crear, insertar, actualizar, leer y administrar chips de menú desplegable de forma programática en documentos de Documentos de Google.
¿Qué son los chips de menú desplegable?
Los chips de menú desplegable en Documentos de Google proporcionan a los usuarios un menú de selección interactivo y personalizable intercalado en el texto del documento. Los usuarios pueden hacer clic en un chip de menú desplegable para seleccionar una opción de una lista predefinida, cada una con su propio texto visible y estilo de color. Los chips de menú desplegable se usan con frecuencia para el seguimiento de proyectos, las actualizaciones de estado, los flujos de trabajo de revisión y las etapas de aprobación.
Con la API de Docs, puedes hacer lo siguiente:
- Define plantillas de menú desplegable reutilizables con títulos, nombres de opciones y colores personalizados.
- Inserta chips de menú desplegable en una ubicación de caracteres válida.
- Actualiza la opción seleccionada de una instancia de chip de menú desplegable individual.
- Modifica las definiciones de los menús desplegables compartidos en el lugar, y actualiza todos los chips de referencia de forma simultánea.
- Reemplazar o retirar opciones de forma segura y, al mismo tiempo, mantener la integridad referencial en los chips existentes
- Borra las plantillas de menú desplegable que no se usen.
Arquitectura: Definiciones e instancias
En la API de Docs, los chips de menú desplegable tienen definiciones e instancias. Una definición establece opciones para una instancia de menú desplegable. Una instancia de menú desplegable es un menú desplegable con el que las personas pueden interactuar y que guarda información sobre las selecciones.
La API de Docs separa la configuración de la plantilla del menú desplegable de las instancias de chips de menú desplegable intercalados:
- DropdownDefinition: Es una plantilla a nivel de la pestaña que define el título del menú desplegable y la colección de opciones seleccionables (
DropdownOption). No se encuentra en un desplazamiento de caracteres específico en el documento, sino que se almacena en el mapa de definición de la pestaña:document.tabs[].documentTab.dropdownDefinitions. - Menú desplegable: Es una instancia de chip individual intercalada en un elemento de párrafo (
ParagraphElement.dropdown). Cada instancia de menú desplegable hace referencia a undropdownDefinitionIdy almacena su propioselectedOptionIdactivo.
Si modificas un DropdownDefinition (p.ej., agregas una opción o cambias el nombre del título), se actualizarán todos los chips de referencia en la pestaña sin necesidad de actualizar cada elemento individual.
Cada instancia de Dropdown hace un seguimiento de su propio selectedOptionId. La modificación del valor seleccionado de un chip individual solo afecta a esa instancia específica.
Formato de ID y reglas de validación
Los IDs proporcionados por el usuario deben cumplir con especificaciones estrictas de formato, prefijo y longitud:
| Identificador | Prefijo obligatorio | Expresión regular de validación | Límite de longitud | Ejemplo |
|---|---|---|---|---|
ID de definición del menú desplegable (dropdownDefinitionId) |
kix. |
^kix\.[a-zA-Z0-9_-]{2,14}$ |
De 6 a 18 caracteres | kix.review_status |
ID de opción de menú desplegable (optionId) |
dropdownItem. |
^dropdownItem\.[a-zA-Z0-9_-]{2,14}$ |
Entre 15 y 27 caracteres | dropdownItem.pending |
Genera IDs proporcionados por el usuario
Para generar IDs que cumplan con los requisitos obligatorios de prefijo y expresión regular, usa las siguientes funciones auxiliares. Estos asistentes generan sufijos alfanuméricos en base 36 en minúsculas, que coinciden con el formato que genera la IU de Documentos de 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();
}
}
Cómo crear e insertar chips de menú desplegable
Creación de un solo lote (recomendado)
El patrón más eficiente combina CreateDropdownDefinitionRequest y InsertDropdownRequest en una sola llamada a documents.batchUpdate.
En la siguiente muestra de código, se crea una definición de menú desplegable "Estado de revisión" con tres opciones codificadas por color que usan IDs proporcionados por el usuario y se inserta una instancia al final del 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();
Reglas y límites de validación de menús desplegables
Cuando crees o modifiques definiciones de menús desplegables, se aplicarán las siguientes restricciones:
- Recuento de opciones: Una definición de menú desplegable debe tener entre 2 y 50 opciones.
- Longitud del título: La definición
titleno puede estar vacía y no debe superar los 200 caracteres. - Longitud del valor para mostrar: El
displayValuede cada opción no puede estar vacío y no debe superar los 200 caracteres. - Diseño de opciones: Solo se admiten
foregroundColorybackgroundColorenDropdownOption.textStyle. Si se configuran otras propiedades de diseño, se devuelve un error400 Bad Request. - Selección predeterminada: En
InsertDropdownRequest, si se omiteselectedOptionId, el chip se establece de forma predeterminada en la primera opción definida enDropdownDefinition.
Actualiza la selección de un chip de menú desplegable individual
Para cambiar la opción seleccionada de una instancia de chip de menú desplegable existente sin alterar su plantilla ni otros chips, usa UpdateDropdownPropertiesRequest:
dropdownId: (Obligatorio) ID de la instancia de chip de menú desplegable específica que se actualizará.tabId: ID de la pestaña que contiene el menú desplegable (si se omite, se usa la primera pestaña de forma predeterminada).fields: Configurado como"selectedOptionId".
En la siguiente muestra de código, se actualiza la selección activa de un chip de menú desplegable a "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();
Actualiza las definiciones y opciones de los menús desplegables
Para modificar la plantilla en sí (título, lista de opciones, etiquetas de visualización o colores), usa UpdateDropdownDefinitionPropertiesRequest. Si actualizas una definición, se actualizarán automáticamente todos los chips de menú desplegable que la referencien en la pestaña.
Reemplazo de la lista completa de opciones
Cuando dropdownDefinitionProperties.options se incluye en la máscara de fields, la solicitud realiza un reemplazo de lista completa. Debes proporcionar la lista completa de opciones en el orden elegido. El servidor compara la lista entrante con la definición actual:
- Nueva opción: Si se incluye una opción sin un
optionId(o con unoptionIdproporcionado por un usuario nuevo), se agrega a la definición. - Opción actualizada: Si proporcionas un
optionIdexistente con actualizaciones dedisplayValueotextStylemodificados, se actualizará esa opción. - Opciones reordenadas: La lista de opciones se guarda en la secuencia exacta que se proporcionó en la solicitud.
- Opción borrada: Si se omite un
optionIdexistente, se borra esa opción de la definición.
Integridad referencial y reemplazo de opciones
Si se selecciona una opción que se borrará en algún chip de menú desplegable del documento, debes proporcionar una asignación en selectedOptionIdReplacements (map<string, string>). Las claves son los IDs de las opciones que se borrarán y los valores son los IDs de las opciones de reemplazo.
En la siguiente muestra de código, se muestra cómo actualizar una definición de menú desplegable con reemplazos de opciones:
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();
Borra una definición de menú desplegable
Para quitar una plantilla de menú desplegable sin usar, usa DeleteDropdownDefinitionRequest.
En la siguiente muestra de código, se indica cómo borrar una definición de menú desplegable:
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();
Manejo de errores y solución de problemas
Condiciones de error y resoluciones comunes:
| Código de estado | Causa | Solución |
|---|---|---|
400 INVALID_ARGUMENT |
El prefijo del ID o el formato de la expresión regular no son válidos. | Asegúrate de que dropdownDefinitionId comience con kix. (de 6 a 18 caracteres) y que optionId comience con dropdownItem. (de 15 a 27 caracteres). |
400 INVALID_ARGUMENT |
El recuento de opciones está fuera de los límites. | Una definición de menú desplegable debe contener entre 2 y 50 opciones. |
400 INVALID_ARGUMENT |
El título o el valor para mostrar están vacíos o superan los 200 caracteres. | Proporciona una cadena no vacía de entre 1 y 200 caracteres. |
400 INVALID_ARGUMENT |
Propiedad de estilo de texto no admitida en la opción. | Solo se admiten foregroundColor y backgroundColor en las opciones del menú desplegable. Quita la fuente, el tamaño o cualquier otro atributo. |
400 INVALID_ARGUMENT |
Falta la asignación de reemplazo de la opción al borrar. | Cuando borres una opción seleccionada por algún chip, proporciona un reemplazo válido en selectedOptionIdReplacements. |
400 INVALID_ARGUMENT |
Se intentó borrar una definición en uso. | Borra o reorienta todas las instancias de chips de menú desplegable que hagan referencia a la definición antes de borrarla. |
400 INVALID_ARGUMENT |
Se duplicó el ID proporcionado por el usuario. | Asegúrate de que los IDs proporcionados por el usuario sean únicos en la pestaña del documento. |
Temas relacionados
- Trabaja con pestañas
- Dar formato al texto
- Trabaja con comentarios y sugerencias
- Recurso de REST: documents.request
- Recurso de REST: documents
- Recurso de REST: documents.batchUpdate