Google Docs API позволяет программно создавать, вставлять, изменять, читать и управлять раскрывающимися чипами в документах Google Документов.
Что такое раскрывающиеся чипы?
Раскрывающиеся чипы в Google Документах позволяют пользователям выбирать варианты в интерактивном настраиваемом меню, встроенном в текст документа. Пользователи могут нажать на раскрывающийся чип, чтобы выбрать один из вариантов, каждый из которых имеет свой текст и цвет. Раскрывающиеся чипы часто используются для отслеживания проектов, обновления статусов, рабочих процессов проверки и этапов утверждения.
С помощью Docs API можно:
- Создавайте шаблоны раскрывающихся списков с настраиваемыми заголовками, вариантами и цветами.
- Вставляйте чипы раскрывающихся списков в допустимые места.
- Обновить выбранный вариант отдельного экземпляра раскрывающегося чипа.
- Изменять определения общих раскрывающихся списков, одновременно обновляя все связанные с ними чипы.
- Безопасно заменять или удалять варианты, сохраняя целостность ссылок в существующих чипах.
- Удалите неиспользуемые шаблоны раскрывающихся списков.
Архитектура: определения и примеры
В API Документов раскрывающиеся чипы имеют определения и экземпляры. Определение задает параметры для экземпляра раскрывающегося списка. Раскрывающийся список – это раскрывающийся список, с которым могут взаимодействовать пользователи. В нем сохраняется информация о выбранных вариантах.
В Docs API конфигурация шаблона раскрывающегося списка отделена от экземпляров встроенных чипов раскрывающегося списка:
- DropdownDefinition – шаблон уровня вкладки, который определяет название раскрывающегося списка и набор вариантов выбора (
DropdownOption). Он не находится в определенном месте документа, а хранится в карте определений вкладки:document.tabs[].documentTab.dropdownDefinitions. - Раскрывающийся список – это отдельный экземпляр чипа, встроенный в элемент абзаца (
ParagraphElement.dropdown). Каждый экземпляр раскрывающегося списка ссылается наdropdownDefinitionIdи хранит собственный активныйselectedOptionId.
Если вы измените DropdownDefinition (например, добавите вариант или переименуете заголовок), все связанные с ним чипы на вкладке будут обновлены автоматически.
Каждый экземпляр типа Dropdown отслеживает собственный объект selectedOptionId. Изменение выбранного значения отдельного чипа влияет только на этот чип.
Формат идентификатора и правила проверки
Идентификаторы, предоставленные пользователями, должны соответствовать строгим требованиям к формату, префиксу и длине:
| Идентификатор | Обязательный префикс | Регулярное выражение для проверки | Ограничение длины | Пример |
|---|---|---|---|---|
Идентификатор определения раскрывающегося списка (dropdownDefinitionId) |
kix. |
^kix\.[a-zA-Z0-9_-]{2,14}$ |
6–18 символов | kix.review_status |
Идентификатор варианта раскрывающегося списка (optionId) |
dropdownItem. |
^dropdownItem\.[a-zA-Z0-9_-]{2,14}$ |
15–27 символов | dropdownItem.pending |
Как создавать идентификаторы, предоставленные пользователями
Чтобы создавать идентификаторы, соответствующие обязательным требованиям к префиксу и регулярному выражению, используйте следующие вспомогательные функции. Эти помощники генерируют суффиксы из строчных букв и цифр в системе с основанием 36, которые соответствуют формату, используемому в интерфейсе 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();
}
}
Как создавать и вставлять раскрывающиеся чипы
Создание одного пакета (рекомендуется)
Самый эффективный шаблон сочетает CreateDropdownDefinitionRequest и InsertDropdownRequest в одном вызове documents.batchUpdate.
В следующем примере кода создается раскрывающийся список "Статус проверки" с тремя вариантами выбора, отмеченными цветом, с использованием предоставленных пользователем идентификаторов и вставляется экземпляр в конце документа:
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– обязательный идентификатор экземпляра раскрывающегося чипа, который нужно обновить.tabId– идентификатор вкладки, на которой находится раскрывающийся список (если не указан, по умолчанию используется первая вкладка).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. При изменении определения автоматически обновляются все раскрывающиеся чипы, ссылающиеся на него на вкладке.
Полная замена списка вариантов
Если в маску fields включен параметр dropdownDefinitionProperties.options, запрос выполняет полную замену списка. Вы должны указать полный список вариантов в выбранном порядке. Сервер сравнивает входящий список с текущим определением:
- Новый вариант. Если добавить вариант без
optionId(или с новымoptionId, предоставленным пользователем), он будет включен в определение. - Обновление варианта. Если вы предоставите существующий вариант
optionIdс измененными значениямиdisplayValueилиtextStyle, вариант будет обновлен. - Измененный порядок вариантов. Список вариантов сохраняется в том порядке, в котором он был указан в запросе.
- Удаленный вариант. Если опустить существующий вариант
optionId, он будет удален из определения.
Ссылочная целостность и замена вариантов
Если удаляемый вариант выбран в каком-либо раскрывающемся чипе в документе, вы должны указать сопоставление в selectedOptionIdReplacements (map<string, string>). Ключи – это идентификаторы удаляемых вариантов, а значения – идентификаторы вариантов, которые их заменят.
В приведенном ниже примере кода показано, как обновить определение раскрывающегося списка, заменив варианты.
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 |
Недопустимый префикс идентификатора или формат регулярного выражения. | Убедитесь, что параметр 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 |
Повторяющийся идентификатор, предоставленный пользователем. | Убедитесь, что идентификаторы, предоставленные пользователями, уникальны на вкладке документа. |
Статьи по теме
- Как работать с вкладками
- Форматирование текста
- Как работать с комментариями и правками
- Ресурс REST: documents.request
- Ресурс REST: documents
- Ресурс REST: documents.batchUpdate