# Формулы

- Human documentation: [https://docs.univer.ai/ru-RU/guides/sheets/features/core/formula](https://docs.univer.ai/ru-RU/guides/sheets/features/core/formula)

- Agent Markdown: [https://docs.univer.ai/ru-RU/guides/sheets/features/core/formula.md](https://docs.univer.ai/ru-RU/guides/sheets/features/core/formula.md)

- Requested language: `ru-RU`

- Content language: `ru-RU`

- Documentation version: `1.2.0`

- Source: [sheets/features/core/formula.ru-RU.mdx](https://github.com/dream-num/documentation/blob/dev/content/guides/sheets/features/core/formula.ru-RU.mdx)

---

Формулы — одна из ключевых возможностей Univer. Они позволяют выполнять вычисления в ячейках. Поддерживаемые функции совместимы с Excel и включают математические, логические, текстовые функции, функции для работы с датами и многие другие.

Если книга содержит много формул, их вычисление может занять основной поток и снизить отзывчивость страницы. Рекомендуется выполнять вычисления формул в процессе Worker, чтобы уменьшить влияние на отрисовку и взаимодействие с пользователем. Подробнее о настройке см. в разделе [Web Workers](https://docs.univer.ai/ru-RU/guides/sheets/getting-started/worker.md).

## Настройка

Ниже приведены ссылки на параметры конфигурации плагинов формул:

| Плагин                     | Параметр конфигурации                                                                 |
| -------------------------- | ------------------------------------------------------------------------------------- |
| `@univerjs/engine-formula` | [IUniverEngineFormulaConfig](https://docs.univer.ai/ru-RU/reference/packages/plugins/univerjs/engine-formula.md)     |
| `@univerjs/sheets-formula` | [IUniverSheetsFormulaBaseConfig](https://docs.univer.ai/ru-RU/reference/packages/plugins/univerjs/sheets-formula.md) |

`initialFormulaComputing` управляет вычислениями при загрузке книги. Если сохранённые результаты устарели, используйте `CalculationMode.FORCED` для пересчёта. В режиме предустановок этот параметр находится внутри `formula`.

Выберите свой режим и добавьте эти параметры в существующую инициализацию. Сохраните остальные плагины, язык, тему и контейнер; не регистрируйте один плагин дважды.

#### Режим плагинов

```typescript
import { CalculationMode, UniverSheetsFormulaPlugin } from '@univerjs/sheets-formula'

univer.registerPlugin(UniverSheetsFormulaPlugin, {
  initialFormulaComputing: CalculationMode.FORCED,
})
```

#### Режим предустановок

```typescript
import { CalculationMode, UniverSheetsCorePreset } from '@univerjs/preset-sheets-core'
import { createUniver } from '@univerjs/presets'

const { univerAPI } = createUniver({
  presets: [
    UniverSheetsCorePreset({
      formula: {
        initialFormulaComputing: CalculationMode.FORCED,
      },
    }),
  ],
})
```

* `CalculationMode.FORCED`: Пересчитывает все формулы.
* `CalculationMode.WHEN_EMPTY`: По умолчанию: вычисляет только ячейки с формулами без сохранённого значения `v`.
* `CalculationMode.NO_CALCULATION`: Пропускает вычисления при инициализации.

## Ссылки между книгами

Формула может суммировать в `Report` продажи из `Sales.xlsx`. В отличие от ссылки на другой лист той же книги, здесь указывается и книга-источник.

### Синтаксис ссылок

| Сценарий                 | Пример                                | Источник                                       |
| ------------------------ | ------------------------------------- | ---------------------------------------------- |
| Другой лист той же книги | `=SUM(Data!A1:A10)`                   | Лист Data текущей книги                        |
| Диапазон другой книги    | `=SUM('[Sales.xlsx]Data'!A1:A10)`     | Лист Data книги Sales.xlsx                     |
| Таблица другой книги     | `=SUM(Sales.xlsx!SalesTable[Amount])` | Столбец Amount существующей таблицы SalesTable |

`Sales.xlsx` — имя книги, а не путь или URL. Запись формулы не читает файл, не скачивает Excel и не подключается к редактору на другой странице. Для структурированной ссылки сначала создайте соответствующую [таблицу](https://docs.univer.ai/ru-RU/guides/sheets/features/table.md).

### Ссылки на книги в одном экземпляре

При использовании базового движка загрузите обе книги в один экземпляр Univer и одну среду вычислений. Выполните пример после инициализации Sheets. В режиме плагинов также импортируйте расширения Facade, указанные на этой странице.

```typescript
const source = univerAPI.createWorkbook({
  id: 'sales-workbook',
  name: 'Sales.xlsx',
  sheetOrder: ['sales-data'],
  sheets: {
    'sales-data': {
      id: 'sales-data',
      name: 'Data',
      rowCount: 100,
      columnCount: 20,
      cellData: {
        0: { 0: { v: 100 } },
        1: { 0: { v: 200 } },
      },
    },
  },
}, { makeCurrent: false })

const report = univerAPI.createWorkbook({ id: 'report-workbook', name: 'Report' })
const resultCell = report.getActiveSheet().getRange('A1')
resultCell.setFormula("=SUM('[Sales.xlsx]Data'!A1:A2)")

const formula = univerAPI.getFormula()
formula.executeCalculation()
await formula.onCalculationResultApplied()
console.log(resultCell.getValue()) // 300
```

`makeCurrent: false` загружает источник, не меняя активную книгу. Сохраняйте `source` и `report`, чтобы не записать формулу в другую книгу после переключения.

Имена сравниваются без учёта регистра. Полное совпадение имеет приоритет; если его нет, игнорируются расширения Excel, например `.xlsx` и `.xlsm`. Отсутствующее или неоднозначное имя даёт `#REF!`. Используйте уникальные имена.

### Привязка к постоянному ID источника

Чтобы связать имя в формуле с постоянным ID документа, используйте Pro-расширение `@univerjs-pro/engine-formula`. Настройте [клиентскую лицензию](https://docs.univer.ai/ru-RU/server/license.md), замените `UniverFormulaEnginePlugin` на `UniverProFormulaEnginePlugin` при инициализации и импортируйте Pro Facade. Не регистрируйте оба движка. Один импорт Facade не регистрирует плагин.

Пример использует книги выше в среде с настроенным Pro-движком:

```typescript
import '@univerjs-pro/engine-formula/facade'

const reference = univerAPI.getFormula().buildReference({
  hostUnitId: report.getId(),
  unit: {
    unitId: source.getId(),
    formulaQualifier: 'Sales Source',
  },
  target: {
    kind: univerAPI.Enum.FormulaReferenceType.SHEET_RANGE,
    sheetName: 'Data',
    range: { startRow: 0, endRow: 1, startColumn: 0, endColumn: 0 },
  },
})

resultCell.setFormula(`=SUM(${reference})`)
```

`hostUnitId` — ID книги с формулой, `unit.unitId` — постоянный ID источника, `formulaQualifier` — его публичное имя в формуле. Координаты начинаются с нуля и включают конечную границу.

`buildReference()` возвращает фрагмент без `=` и сохраняет привязку. Он не загружает источник и не запускает вычисления. Данные должны поступать из книги, загруженной в среду вычислений, или настроенного поставщика данных. Для написанной вручную или сгенерированной формулы сначала создайте привязку:

```typescript
const formula = univerAPI.getFormula()
const bound = formula.upsertExternalReference({
  unitId: report.getId(),
  qualifier: 'Sales Source',
  sourceUnitId: source.getId(),
  sourceUnitType: univerAPI.Enum.UniverInstanceType.UNIVER_SHEET,
})
if (!bound) throw new Error('Could not bind Sales Source')

resultCell.setFormula("=SUM('[Sales Source]Data'!A1:A2)")
```

Повторная запись той же привязки идемпотентна. В `qualifier` не нужны скобки или кавычки. Положительные целые числа вроде `1` и `2` зарезервированы для слотов внешних ссылок Excel, а не ID документов. При импорте сохраняйте ресурсы внешних ссылок: одного текста формулы недостаточно.

### Обновление, сохранение и выгрузка

После изменения источника через Facade запустите вычисления и дождитесь применения результатов перед чтением. Возврат из `setFormula()` или `setValue()` не означает завершения асинхронного расчёта.

```typescript
const sourceSheet = source.getSheetBySheetId('sales-data')
if (!sourceSheet) throw new Error('Source sheet not found')
sourceSheet.getRange('A1').setValue(150)
formula.executeCalculation()
await formula.onCalculationResultApplied()
console.log(resultCell.getValue()) // 350
```

Используйте `report.save()` для сохранения полного снимка с ресурсами привязок. Сохранение только формул теряет соответствие имён и ID. Данные источника сохраняются и загружаются отдельно.

После выгрузки источника обычная ссылка на загруженную книгу больше не может его читать. Продолжение расчётов Pro-ссылок зависит от поставщиков данных и доступного кеша. Привязка не содержит данных и не гарантирует автономный расчёт. Старое значение на экране не доказывает актуальность результата.

Ненужную Pro-привязку можно удалить:

```typescript
univerAPI.getFormula().removeExternalReference({
  unitId: report.getId(),
  qualifier: 'Sales Source',
})
```

Удаление не стирает и не переписывает формулы. При следующем расчёте имя разрешается заново: может найтись загруженная книга с таким именем, иначе вернётся `#REF!`. Чтобы прекратить ссылку, измените или очистите и саму формулу. Полные параметры приведены в [API ссылок FFormula](https://docs.univer.ai/ru-RU/reference/facade/formula.md).

## Трёхмерные ссылки

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

```text
=SUM(Jan:Mar!B2:C3)
=SUM('Jan':'Mar'!B2)
```

Диапазон включает Jan, Mar и все листы между ними в порядке книги, а не по алфавиту. После перестановки листов проверьте диапазон суммирования.

## Поддерживаемые функции



## Facade API

Подробные сведения см. в документации [Facade API для FFormula](https://docs.univer.ai/ru-RU/reference/facade/formula.md).

### Импорт

> [!INFO: Примечание о режиме плагинов]
> Импортировать пакет Facade вручную требуется только в режиме плагинов. В режиме предустановок соответствующий пакет
> Facade уже включён, поэтому дополнительно импортировать его не нужно.

```typescript
import '@univerjs/engine-formula/facade'
import '@univerjs/sheets-formula/facade'
import '@univerjs/sheets-formula-ui/facade'
```

### Открытие диалогового окна выбора диапазона

Пакет `@univerjs/sheets-formula-ui/facade` добавляет метод `univerAPI.showRangeSelectorDialog`. Используйте его, если в вашем интерфейсе пользователю нужно выбрать один или несколько диапазонов с помощью того же инструмента, который применяется в панелях для работы с формулами.

```typescript
const workbook = univerAPI.getActiveWorkbook()
const worksheet = workbook?.getActiveSheet()

if (workbook && worksheet) {
  await univerAPI.showRangeSelectorDialog({
    unitId: workbook.getId(),
    subUnitId: worksheet.getSheetId(),
    initialValue: [
      {
        unitId: workbook.getId(),
        sheetName: worksheet.getSheetName(),
        range: worksheet.getRange('A1:B2').getRange(),
      },
    ],
    maxRangeCount: 2,
    supportAcrossSheet: true,
    callback: (ranges, isCancel) => {
      console.log(ranges, isCancel)
    },
  })
}
```

### Запуск вычисления формул

```typescript
const formulaEngine = univerAPI.getFormula()
formulaEngine.executeCalculation()
```

### Остановка вычисления формул

```typescript
const formulaEngine = univerAPI.getFormula()
formulaEngine.stopCalculation()
```

### Начало вычисления формул

```typescript
// Listening to formula calculation start event
const formulaEngine = univerAPI.getFormula()
formulaEngine.calculationStart((forceCalculate) => {
  console.log(forceCalculate)
})
```

### Процесс вычисления формул

```typescript
// Listening to formula calculation processing event
const formulaEngine = univerAPI.getFormula()
formulaEngine.calculationProcessing((stageInfo) => {
  console.log(stageInfo)
})
```

### Завершение вычисления формул

```typescript
// Listening to formula calculation end event
const formulaEngine = univerAPI.getFormula()
formulaEngine.calculationEnd((functionsExecutedState) => {
  console.log(functionsExecutedState)
})
```

### Применение результатов вычисления формул

```typescript
// Listening to formula calculation result applied event
const formulaEngine = univerAPI.getFormula()
formulaEngine.calculationResultApplied((result) => {
  console.log(result)
})

// Wait for formula calculation result to be applied
await formulaEngine.onCalculationResultApplied()
```

### Установка режима вычисления формул при инициализации данных

```typescript
const formulaEngine = univerAPI.getFormula()
formulaEngine.setInitialFormulaComputing(CalculationMode.FORCED)
```

Если вызвать этот API после этапа жизненного цикла `Starting`, настройка вступит в силу при следующем создании Univer Sheet.

Чтобы применить её во время текущей инициализации Univer Sheet, вызовите API до этапа жизненного цикла `Ready`, например:

```typescript
univerAPI.addEvent(univerAPI.Event.LifeCycleChanged, ({ stage }) => {
  if (stage === LifecycleStages.Starting) {
    const formulaEngine = univerAPI.getFormula()
    formulaEngine.setInitialFormulaComputing(CalculationMode.FORCED)
  }
})
```

### Итерационные вычисления

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

| Параметр               | По умолчанию | Поведение                                                                                                                                                     |
| ---------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iterativeCalculation` | `false`      | Включает итерационные вычисления циклических ссылок.                                                                                                          |
| `maxIterations`        | `100`        | Целое число от 1 до 32767.                                                                                                                                    |
| `maxChange`            | `0.001`      | Конечный положительный порог сходимости. Вычисления останавливаются, когда изменение каждого числового результата циклической группы не превышает этот порог. |

Обновляйте все три параметра вместе через Facade книги. Команда поддерживает отмену, повтор и совместное редактирование; возвращает `false`, если книга отсутствует или недоступна для редактирования. Некорректные значения заменяются стандартными.

```ts
const workbook = univerAPI.getActiveWorkbook()
if (!workbook) throw new Error('No active workbook')

const applied = workbook.setCalculationSettings({
  iterativeCalculation: true,
  maxIterations: 100,
  maxChange: 0.001,
})
if (!applied) throw new Error('Could not update calculation settings')

console.log(workbook.getCalculationSettings())
```

Поле `calculationSettings` также можно передать в `createWorkbook()`. Книги хранят настройки независимо. Те же параметры доступны в настройках вычислений на вкладке формул.

`getCircularReferences()` читает диагностику после применения результатов и не запускает вычисления. Результат содержит ID листов, координаты с нуля, ID циклических групп, число итераций и сведения о сходимости, если они доступны.

```ts
const formula = univerAPI.getFormula()
formula.executeCalculation()
await formula.onCalculationResultApplied()
console.table(workbook.getCircularReferences())
```

### Получение результатов выполнения строковых формул

Метод асинхронно выполняет пакет формул и возвращает результаты вычислений:

```typescript
const formulaEngine = univerAPI.getFormula()
const formulas = {
  Book1: {
    Sheet1: {
      2: {
        3: [
          // Full formula:
          '=SUM(A1:A10) + SQRT(D7)',

          // Decomposed sub-formulas (each one can be evaluated independently):
          'SUM(A1:A10)', // sub-formula 1
          'SQRT(D7)', // sub-formula 2
          'A1:A10', // range reference
          'D7', // single-cell reference
        ],
      },
      4: {
        5: ['=A2 + B2 + SQRT(C5)', 'A2', 'B2', 'SQRT(C5)'],
      },
    },
  },
}
const result = await formulaEngine.executeFormulas(formulas)
console.log(result)
```

## Пользовательские формулы

Univer поддерживает пользовательские формулы. Инструкции по их реализации приведены в разделе [Пользовательские формулы](/blog/custom-formula).

## Часто задаваемые вопросы

### Не удаётся открыть гиперссылку из ячейки с формулой `HYPERLINK`

Необходимо импортировать плагин гиперссылок для Univer Sheets. Подробнее см. в разделе [Гиперссылка](https://docs.univer.ai/ru-RU/guides/sheets/features/hyper-link.md).

## Семантика значений формул

`ISBLANK(A1)` проверяет содержимое ячейки, а не только отображаемый результат. Очищенная ячейка пуста даже при сохранении формата; формула с результатом `""` — нет. Литерал `ISBLANK("")` также даёт `FALSE`. `UNIQUE` сравнивает текст без учёта регистра, сохраняя первое написание. `PROPER` распознаёт буквы Unicode, включая латиницу с диакритикой, греческие и кириллические буквы. `AVERAGE` обрабатывает весь массив, возвращаемый, например, `FILTER`.

```text
=ISBLANK("")                         → FALSE
=UNIQUE({"Univer";"univer";"Sheets"})  → {"Univer";"Sheets"}
=PROPER("élise müller")               → Élise Müller
=AVERAGE({3;7})                      → 5
```
