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

Проверенный скрипт

Полный проверенный скрипт первого запуска и конфигурация, на которой он подтверждён.

Файл f1-api-first-run.mjs входит в Evaluation Kit, но его можно просто скопировать отсюда: скрипт сам находит процессор по системе, на которой запущен. Если приложение установлено в нестандартный каталог, задайте путь переменной окружения F1_CLI.

#!/usr/bin/env node
import { spawn } from "node:child_process";
import { createInterface } from "node:readline";
import { fileURLToPath, pathToFileURL } from "node:url";
import path from "node:path";
// Путь к процессору: можно задать переменной окружения F1_CLI,
// иначе берётся стандартный каталог установки текущей системы.
const installed = {
darwin: `${process.env.HOME}/Applications/F1.app/Contents/Resources/runtime/native/compute_contract_cli`,
win32: "C:\\Program Files\\F1\\resources\\runtime\\native\\compute_contract_cli.exe",
linux: "/opt/F1/resources/runtime/native/compute_contract_cli",
};
const binary = process.env.F1_CLI ?? installed[process.platform];
if (!binary) throw new Error(`неизвестная система: ${process.platform}`);
const workDir = path.resolve(process.argv[2] ?? path.dirname(fileURLToPath(import.meta.url)));
const source = path.join(workDir, "input.xlsx");
const destination = path.join(workDir, "result.xlsx");
const viewport = { top: 0, left: 0, rows: 20, cols: 12 };
const child = spawn(binary, ["--session"], {
stdio: ["pipe", "pipe", "inherit"],
});
const lines = createInterface({ input: child.stdout });
const queue = [];
let pending;
lines.on("line", (line) => {
const value = JSON.parse(line);
if (pending) {
const resolve = pending;
pending = undefined;
resolve(value);
} else {
queue.push(value);
}
});
function nextLine() {
if (queue.length) return Promise.resolve(queue.shift());
return new Promise((resolve) => {
pending = resolve;
});
}
async function send(request) {
child.stdin.write(`${JSON.stringify(request)}\n`);
const response = await nextLine();
if (!response.ok) {
throw new Error(`${request.operation}: ${JSON.stringify(response)}`);
}
return response.payload;
}
function edit(sheetKey, row, col, inputKind, input) {
return { sheetKey, row, col, inputKind, input };
}
try {
const handshake = await nextLine();
console.log("1. Сессия:", handshake.kind);
const opened = await send({
operation: "open_workbook_subset",
sourceUri: pathToFileURL(source).href,
viewport,
requestedBackend: "native-desktop",
});
const subsetId = opened.subsetId;
const sheetKey = opened.activeSheet.path;
console.log("2. Открыта книга:", opened.activeSheet.name, subsetId);
const applied = await send({
operation: "apply_cell_edits",
subsetId,
edits: [
edit(sheetKey, 0, 0, "text", "F1 API"),
edit(sheetKey, 0, 1, "number", "21"),
edit(sheetKey, 0, 2, "formula", "=B1*2"),
],
expectedRevision: 0,
viewport,
requestedBackend: "native-desktop",
});
console.log("3. Изменения применены, revision:", applied.workbookHistory?.revision);
const cell = await send({
operation: "read_cell_details",
subsetId,
row: 0,
col: 2,
viewport,
requestedBackend: "native-desktop",
});
console.log("4. C1 после формулы:", cell.cell?.displayValue);
await send({
operation: "replay_workbook_history",
subsetId,
direction: "undo",
viewport,
requestedBackend: "native-desktop",
});
await send({
operation: "replay_workbook_history",
subsetId,
direction: "redo",
viewport,
requestedBackend: "native-desktop",
});
console.log("5. Undo/Redo: выполнены");
await send({
operation: "save_workbook_subset",
subsetId,
destinationUri: pathToFileURL(destination).href,
preserveCachedValues: true,
requestedBackend: "native-desktop",
});
console.log("6. Сохранено:", destination);
child.stdin.end();
await new Promise((resolve) => child.once("exit", resolve));
const verify = spawn(binary, ["--session"], { stdio: ["pipe", "pipe", "inherit"] });
const verifyLines = createInterface({ input: verify.stdout });
const iterator = verifyLines[Symbol.asyncIterator]();
await iterator.next();
verify.stdin.write(`${JSON.stringify({
operation: "open_workbook_subset",
sourceUri: pathToFileURL(destination).href,
viewport,
requestedBackend: "native-desktop",
})}\n`);
const reopened = JSON.parse((await iterator.next()).value);
if (!reopened.ok) throw new Error(`cold reopen: ${JSON.stringify(reopened)}`);
const reopenedSubsetId = reopened.payload.subsetId;
verify.stdin.write(`${JSON.stringify({
operation: "read_cell_details",
subsetId: reopenedSubsetId,
row: 0,
col: 2,
viewport,
requestedBackend: "native-desktop",
})}\n`);
const verified = JSON.parse((await iterator.next()).value);
if (!verified.ok) throw new Error(`verify cell: ${JSON.stringify(verified)}`);
console.log("7. Повторное открытие, C1:", verified.payload.cell?.displayValue);
verify.stdin.end();
verify.kill();
} catch (error) {
child.kill();
console.error(error);
process.exitCode = 1;
}
Параметр Значение
Каталог релиза https://dl.plantype.ru/f1/release/latest/
Пакет Архив для macOS на Apple Silicon
Целостность пакета Сверена с суммой из latest*.yml в каталоге релиза
Установка ~/Applications/F1.app
Процессор Contents/Resources/runtime/native/compute_contract_cli внутри пакета
Транспорт Строки JSON через stdin и stdout, режим --session
Проверенный результат C1 = 42 после правки, отмены, повтора, сохранения и открытия заново в новом процессе

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

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