Перейти к содержимому
FastOffice

Набор для встраивания: структура, события, меню

Модель доступа без DOM, структурные проекции книги, события щелчка и выбора, вклад в контекстное меню и команды вместо прямой записи.

Статус Объект Что это означает
Есть сейчас Контракт операций в ядре Чтение структуры, ячеек и объектов, типизированные операции изменения.
Есть сейчас Обработка действий в поверхности Определение попадания, щелчки и вызов меню, выделение и внутренние смысловые события.
Требует оформления Публичный набор для встраивания Устойчивые методы и события, добавление своих пунктов меню, права и версионирование.
  • Чтение — узнать состав книги, выделение, ячейку, объект.
  • События — реагировать на действия пользователя.
  • Команды — безопасно изменять книгу.
  • Расширение интерфейса — добавлять свои команды и пункты меню.

Не DOM документа, а структурные проекции и команды

Заголовок раздела «Не DOM документа, а структурные проекции и команды»

Таблица в F1 не выложена в разметку страницы как дерево элементов. Она рисуется на полотне, а в памяти держится только видимая часть книги — поэтому нужной ячейки или объекта в разметке может не быть вовсе, даже когда пользователь их видит. Обращаться нужно к логической структуре через набор вызовов.

Объект Что даёт Откуда берутся данные
WorkbookSession Идентификаторы книги и сеанса, ревизия, признак несохранённых изменений, активный лист, доступные форматы. Сеанс ядра.
WorkbookInfo Листы с устойчивыми идентификаторами, их имена, видимость и какой лист активен. Проекция из ядра.
Selection Лист, выделенный диапазон, активная ячейка и идентификаторы выбранных объектов. Определение попадания в поверхности плюс идентификаторы из ядра.
CellDetails Хранимое значение, отображаемое значение, формула, тип, формат, проверка ввода, примечание и ссылка. Операция read_cell_details.
RangeSnapshot Ограниченный участок: значения, формулы, стили и сопутствующие данные. Запрос к ядру с явными границами участка.
ObjectInventory Фигуры, диаграммы, изображения, элементы управления, их привязки, порядок наложения и доступные действия. Опись объектов из файла.
ContextTarget Что находится под указателем: ячейка, таблица, диаграмма, фигура, заголовок. Смысловое определение попадания.

Так предлагается назвать публичные вызовы — в текущем контракте таких имён нет.

const session = await F1.open({
mount, documentId, bytes, mode: "edit"
});
const workbook = await session.getWorkbookInfo();
const selection = await session.getSelection();
const cell = await session.getCellDetails(selection.activeCell);

Как получить листы, диапазон, таблицу и графический объект

Заголовок раздела «Как получить листы, диапазон, таблицу и графический объект»
Задача Предлагаемый вызов Что вернётся
Получить листы session.getWorkbookInfo() Список листов с идентификаторами, именами, видимостью и порядком.
Прочитать ячейку session.getCellDetails(...) Хранимое и отображаемое значение, формула, тип, стиль и сопутствующие данные.
Прочитать диапазон session.getRangeSnapshot(...) Значения, формулы и стили запрошенного участка — без всей книги.
Узнать таблицу session.getTableAt(...) Идентификатор таблицы, её диапазон, столбцы, фильтры, итоги и доступные действия.
Получить объекты session.getObjects(...) Опись объектов с идентификаторами, типами, привязками, порядком наложения и признаком изменяемости.
Узнать объект под точкой session.hitTest(...) Что находится под указателем: вид объекта и его устойчивый идентификатор.

Пример: найти диаграмму и переименовать через команду

const objects = await session.getObjects({ sheetId });
const chart = objects.find(x => x.type === "chart");
if (chart?.capabilities.rename) {
await session.execute({
operation: "renameObject",
objectId: chart.stableId,
name: "План перевозок",
expectedRevision: session.revision
});
}

Открытие книги уже возвращает активный лист, список листов, видимую область, предпросмотр ячеек, сведения о таблицах и опись объектов. Для каждого объекта доступны устойчивый идентификатор, лист, тип, имя, привязка, связи с другими частями, порядок наложения, видимость, блокировка и перечень допустимых изменений. Для отдельной ячейки есть операция read_cell_details.

Событие Когда приходит Основные поля
selectionChanged Выделение изменилось и это подтверждено. новое и прежнее выделение, источник изменения, ревизия.
cellActivated Одиночный щелчок или касание сделали ячейку активной. ссылка на ячейку, диапазон, нажатые клавиши-модификаторы, источник.
cellDoubleClicked Двойной щелчок по ячейке — после того, как определено, во что именно попали. ссылка на ячейку, намерение правки, клавиши-модификаторы.
objectSelected Выбрана фигура, диаграмма, картинка или элемент управления. устойчивый идентификатор, тип объекта, привязка, доступные действия.
objectDoubleClicked Двойной щелчок по графическому объекту. сам объект, действие по умолчанию, клавиши-модификаторы.
contextMenuOpening Щелчок правой кнопкой или долгое нажатие на телефоне. объект под указателем, выделение, встроенные пункты меню, доступные действия.
workbookChanged Ядро применило изменение. новая ревизия, какая операция, что изменилось, признак несохранённых изменений.
operationRefused Ядро отказало — до того, как что-либо изменилось. код и текст отказа, объект, текущая ревизия.

Подписка на смысловые события

const unsubscribe = session.on("cellDoubleClicked", async event => {
const details = await session.getCellDetails(event.cellRef);
hostPanel.open({ documentId, cell: details });
});
session.on("objectSelected", event => {
propertiesPanel.show(event.target);
});
// При закрытии интеграции:
unsubscribe();

указатель или касание → определение попадания → подтверждение выделения → смысловое событие → действие по умолчанию

Как менять меню в зависимости от выбранного элемента

Заголовок раздела «Как менять меню в зависимости от выбранного элемента»

Искать внутренний элемент меню в разметке и вставлять туда кнопку не нужно. Вместо этого вы регистрируете поставщика пунктов меню: перед показом F1 определяет, что находится под указателем, и запрашивает у вас дополнительные пункты.

ContextTarget.kind Примеры данных контекста
cell / range sheetId, address, valueType, formula, validation, comment, hyperlink, protected.
table tableId, name, range, columnId, totals/filter state, mutation capabilities.
chart objectId, chartType, source range, anchor, editable capabilities.
shape / image objectId, anchor, zOrder, groupId, metadata, supported mutations.
rowHeader / columnHeader track index, hidden state, size, protection.
sheetTab sheetId, name, visibility, active/grouped state.
canvas sheetId, pointer coordinates, no semantic object.

Пример menu contribution для строки таблицы

session.contextMenu.registerProvider(async context => {
if (context.target.kind !== "table") return [];
return [{
id: "partner.open-shipment-card",
label: "Открыть карточку перевозки",
icon: "external-link",
enabled: Boolean(context.target.rowKey),
group: "partner",
order: 20,
run: () => host.openCard(context.target.rowKey)
}];
});
  • У пункта есть собственное имя с вашей приставкой, переводимая подпись, необязательный значок, группа, порядок в ней и правило, по которому он включён или виден.

  • Поставщик пунктов получает безопасный снимок обстановки, а не внутреннюю разметку и не всю книгу.

  • Встроенные команды остаются за F1; вы добавляете свои пункты и в оговорённых местах заменяете разрешённые.

  • Если ваш поставщик пунктов думает слишком долго, ожидание обрывается: меню не должно зависнуть из-за вашей серверной части.

Любая операция, меняющая документ, проходит через контракт операций в ядре. Так поведение остаётся одинаковым в браузере, в настольном приложении и на сервере, а история изменений — целостной.

Шаг Что происходит
1. Собрать намерение Имя операции, устойчивая ссылка на объект или диапазон, параметры и ожидаемая ревизия.
2. Проверить доступ Режим только для чтения, защита листа, объявленные возможности, формат исходного файла и правила сеанса.
3. Передать ядру Тот же контракт — через сборку для браузера, настольный процессор или серверную службу.
4. Применить целиком При успехе меняются ревизия и история; при отказе книга остаётся нетронутой — половины правки не бывает.
5. Отдать результат Новая проекция и событие об изменении книги — либо событие об отказе.

Пример правки с проверкой ревизии

const result = await session.execute({
operation: "setCellValue",
target: { sheetId, row: 12, col: 4 },
value: { kind: "string", value: "Доставлено" },
expectedRevision: session.revision
});
if (!result.ok && result.code.endsWith("-stale-revision")) {
await session.refreshProjection();
}
// НЕЛЬЗЯ: это обходит Rust, историю и сохранение.
document.querySelector("[data-cell='E13']").textContent = "Доставлено";
session.workbook.sheets[0].cells[12][4].value = "Доставлено";

Ассистент документации

Ответ собран из документации и может быть неточным — сверяйтесь с источниками.