# Диапазоны, выделения и ячейки

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

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

- Requested language: `ru-RU`

- Content language: `ru-RU`

- Documentation version: `1.2.0`

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

---

Перейдите к разделу по своей задаче. Базовые операции, расширенные примеры, настройки и устранение проблем остаются на этой странице; полные контракты API поддерживаются в Reference.

* [Диапазон](#range)
* [Выделение](#selection)
* [Расширенные операции с диапазонами](#range-operations)
* [Навигация на границах листа](#keyboard-navigation)
* [События и редактирование ячеек](#events)
* [Устранение проблем редактирования](#troubleshooting)

## Диапазон

Диапазон — это прямоугольная область на листе, заданная начальной строкой, начальным столбцом, высотой и шириной либо конечной строкой и конечным столбцом.

Большинство операций с электронной таблицей можно выполнять через Range API: задавать и получать значения, задавать и получать стили и т. д.

Полное описание Facade API для диапазонов см. в разделе [FRange FacadeAPI](https://docs.univer.ai/ru-RU/reference/facade/range.md).

### Создание диапазона

Чтобы получить диапазон, необходимо знать начальную строку, начальный столбец, высоту и ширину.

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// Create a range of A1 cell:
const fRange = fWorksheet.getRange(0, 0)
console.log(fRange, fRange.getA1Notation())

// Creates a range of A1:B2:
const fRange2 = fWorksheet.getRange(0, 0, 2, 2)
console.log(fRange2, fRange2.getA1Notation())
```

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// Get the A1:B2 range on named Sheet1
const fRange1 = fWorksheet.getRange('Sheet1!A1:B2')
console.log(fRange1, fRange1.getA1Notation())

// Get a single cell A1
const fRange2 = fWorksheet.getRange('A1')
console.log(fRange2, fRange2.getA1Notation())

// Get the A1:B2 range
const fRange3 = fWorksheet.getRange('A1:B2')
console.log(fRange3, fRange3.getA1Notation())

// Get the range of column A
const fRange4 = fWorksheet.getRange('A:A')
console.log(fRange4, fRange4.getA1Notation())

// Get the range of row 1
const fRange5 = fWorksheet.getRange('1:1')
console.log(fRange5, fRange5.getA1Notation())
```

### Получение данных диапазона

Получение значения первой ячейки диапазона

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
if (!fWorkbook) throw new Error('No active workbook')
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')

console.log(fRange.getValue()) // The value of the top-left cell in the range
console.log(fRange.getRawValue()) // The raw value of the top-left cell in the range
console.log(fRange.getDisplayValue()) // The displayed value of the top-left cell in the range
console.log(fRange.getCellData()) // The cell data of the top-left cell in the range
const value = fRange.getValue(true)
console.log(value)
if (value !== null && typeof value === 'object') {
  console.log(value.toPlainText())
}
```

Используйте `getValue(true)`, чтобы сохранить объект форматированного текста. Пустая ячейка возвращает `null` / `undefined`, обычная — строку, число или логическое значение. Вызывайте `toPlainText()` только для объекта форматированного текста.

Получение значений всех ячеек диапазона

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
if (!fWorkbook) throw new Error('No active workbook')
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')

console.log(fRange.getValues()) // The values of all cells in the range
console.log(fRange.getRawValues()) // The raw values of all cells in the range
console.log(fRange.getDisplayValues()) // The displayed values of all cells in the range
console.log(fRange.getCellDataGrid()) // The cell data of all cells in the range
console.log(fRange.getValues(true))
```

Получение всех формул диапазона

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')

console.log(fRange.getFormula()) // The formula of the top-left cell in the range
console.log(fRange.getFormulas()) // The formulas of all cells in the range
```

### Задание значения диапазона

#### Задание одного значения

Если передать значение или объект ячейки, оно будет записано во все ячейки диапазона. Если значение начинается с `=`, оно будет интерпретировано как формула.

Например, чтобы задать для диапазона A1:B2 значение `Hello, Univer`:

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
fRange.setValue('Hello, Univer')
```

Запишите `=A1+B1` в C1, чтобы результат находился вне исходных ячеек:

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
if (!fWorkbook) throw new Error('No active workbook')
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('C1')
fRange.setValue('=A1+B1')
```

Чтобы задать объект ячейки в качестве значения диапазона A1:B2:

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
fRange.setValue({
  v: 'Hello, Univer',
  custom: {
    key: 'value',
  },
})
```

Если требуется задать значение только для верхней левой ячейки диапазона, используйте метод [`FRange.setValueForCell`](https://docs.univer.ai/ru-RU/reference/facade/range.md#setvalueforcell):

```typescript
fRange.setValueForCell('Hello, Univer')
```

#### Задание нескольких значений с помощью массива

Высота и ширина массива должны совпадать с высотой и шириной диапазона.

Можно передавать значения ячеек или объекты ячеек.

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
fRange.setValues([
  ['A1', 'B1'],
  ['A2', 'B2'],
])

fRange.setValues([
  [{ v: 'A1' }, { v: 'B1' }],
  [{ v: 'A2' }, { v: 'B2' }],
])
```

#### Задание нескольких значений с помощью объекта

Если передать объект, его индекс первого уровня обозначает номер строки, а индекс второго уровня — номер столбца. При этом высота и ширина диапазона могут не совпадать с размерами объекта.

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
fRange.setValues({
  0: {
    0: 'A1',
    1: 'B1',
  },
  1: {
    0: 'A2',
    1: 'B2',
  },
})
```

### Очистка данных диапазона

* Метод [`FRange.clear`](https://docs.univer.ai/ru-RU/reference/facade/range.md#clear) очищает содержимое и сведения о форматировании диапазона.
* Метод [`FRange.clearContent`](https://docs.univer.ai/ru-RU/reference/facade/range.md#clearcontent) очищает содержимое диапазона.
* Метод [`FRange.clearFormat`](https://docs.univer.ai/ru-RU/reference/facade/range.md#clearformat) очищает сведения о форматировании диапазона.

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorkSheet = fWorkbook.getActiveSheet()
const fRange = fWorkSheet.getRange('A1:D10')

// Clears content and formatting information of the range.
fRange.clear()
```

### Получение стиля диапазона

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
console.log(fRange.getCellStyleData()) // The style data of the top-left cell in the range
console.log(fRange.getCellStyle()) // The style of the top-left cell in the range
console.log(fRange.getCellStyles()) // The styles of all cells in the range
```

### Задание стиля диапазона

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
fRange
  .setValues([
    [1, 2],
    [3, 4],
  ])
  .setFontWeight('bold')
  .setFontLine('underline')
  .setFontFamily('Arial')
  .setFontSize(24)
  .setFontColor('red')
```

### Очистка стиля диапазона

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
fRange.setFontWeight(null).setFontLine(null).setFontFamily(null).setFontSize(null).setFontColor(null)
```

## Выделение

Univer Sheets поддерживает несколько областей выделения: выделение представляет собой массив диапазонов, данными которого можно управлять через Range API.

Также доступны API для получения и задания текущего выделения и отслеживания его изменений.

Полное описание Facade API для выделений см. в разделе [FSelection FacadeAPI](https://docs.univer.ai/ru-RU/reference/facade/selection.md).

### Получение активного выделения

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// Activate the new selection of A1:B2
const fRange = fWorksheet.getRange('A1:B2')
fRange.activate()

// Get the current active selection
const fSelection = fWorksheet.getSelection()
console.log(fSelection)
const activeRange = fSelection.getActiveRange()
console.log(activeRange.getA1Notation()) // A1:B2
```

### Задание выделения

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// Set the selection to A1:B2 by FRange
const fRange = fWorksheet.getRange('A1:B2')
fRange.activate()

// Set the selection to C1:D2 by FWorksheet
fWorksheet.setActiveSelection(fWorksheet.getRange('C1:D2'))
```

### Получение текущей ячейки

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// Activate the new selection of A10:B11
const fRange = fWorksheet.getRange('A10:B11')
fRange.activate()

// Get the current active cell
let fSelection = fWorksheet.getSelection()
const { actualRow, actualColumn } = fSelection.getCurrentCell()
console.log(fWorksheet.getRange(actualRow, actualColumn).getA1Notation()) // A10

// Update the new active cell to B11
fSelection = fSelection.updatePrimaryCell(fWorksheet.getRange('B11'))
const { actualRow: newRow, actualColumn: newColumn } = fSelection.getCurrentCell()
console.log(fWorksheet.getRange(newRow, newColumn).getA1Notation()) // B11
```

### Отключение, включение, скрытие и отображение выделения

После отключения выделение перестаёт реагировать на действия. Метод `transparentSelection` делает выделение невидимым; в отличие от `disableSelection`, оно продолжает работать, но не отображается.

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()

// Disable selection
fWorkbook.disableSelection()

// Enable selection
fWorkbook.enableSelection()

// Hide selection
fWorkbook.transparentSelection()

// Show selection
fWorkbook.showSelection()
```

### Отслеживание изменений выделения

```typescript
univerAPI.addEvent(univerAPI.Event.SelectionChanged, (params) => {
  const { worksheet, workbook, selections } = params
  console.log(params)
})
```

## Ячейка

Данные ячеек хранятся на листе в двумерной структуре Map, где первый индекс обозначает номер строки, а второй — номер столбца.

Типичный объект ячейки выглядит так:

```typescript
const data = {
  v: 'Hello, Univer',
  s: 'styleId',
  t: CellValueType.STRING,
}
```

Подробное описание полей см. в разделе [Настройка данных ячейки](https://docs.univer.ai/ru-RU/guides/sheets/model/cell-data.md).

### Полезно знать

1. Операции с ячейкой можно рассматривать как операции с диапазоном высотой в одну строку и шириной в один столбец. Подробнее см. в разделе [Диапазон](https://docs.univer.ai/ru-RU/guides/sheets/features/core/range-selection.md#range).
2. Плагин Univer API также сохраняет расширенные атрибуты ячеек в свойстве `resources` объекта `Workbook`. Подробнее см. в разделе [Пользовательская модель плагина](/blog/custom-model).

## Расширенные операции с диапазонами

### Вставка ячеек

Метод [`FRange.insertCells`](https://docs.univer.ai/ru-RU/reference/facade/range.md#insertcells) вставляет в диапазон пустые ячейки. Существующие данные на листе сдвигаются по указанному измерению в сторону от вставленного диапазона.

```typescript
// Assume the active sheet empty sheet.
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const values = [
  [1, 2, 3, 4],
  [2, 3, 4, 5],
  [3, 4, 5, 6],
  [4, 5, 6, 7],
  [5, 6, 7, 8],
]

// Set the range A1:D5 with some values, the range A1:D5 will be:
// 1 | 2 | 3 | 4
// 2 | 3 | 4 | 5
// 3 | 4 | 5 | 6
// 4 | 5 | 6 | 7
// 5 | 6 | 7 | 8
const fRange = fWorksheet.getRange('A1:D5')
fRange.setValues(values)
console.log(fWorksheet.getRange('A1:D5').getValues()) // [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8]]

// Insert the empty cells into the range A1:B2 along the columns dimension, the range A1:D5 will be:
//   |   | 1 | 2
//   |   | 2 | 3
// 3 | 4 | 5 | 6
// 4 | 5 | 6 | 7
// 5 | 6 | 7 | 8
const fRange2 = fWorksheet.getRange('A1:B2')
fRange2.insertCells(univerAPI.Enum.Dimension.COLUMNS)
console.log(fWorksheet.getRange('A1:D5').getValues()) // [[null, null, 1, 2], [null, null, 2, 3], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8]]

// Set the range A1:D5 values again, the range A1:D5 will be:
// 1 | 2 | 3 | 4
// 2 | 3 | 4 | 5
// 3 | 4 | 5 | 6
// 4 | 5 | 6 | 7
// 5 | 6 | 7 | 8
fRange.setValues(values)

// Insert the empty cells into the range A1:B2 along the rows dimension, the range A1:D5 will be:
//   |   | 3 | 4
//   |   | 4 | 5
// 1 | 2 | 5 | 6
// 2 | 3 | 6 | 7
// 3 | 4 | 7 | 8
const fRange3 = fWorksheet.getRange('A1:B2')
fRange3.insertCells(univerAPI.Enum.Dimension.ROWS)
console.log(fWorksheet.getRange('A1:D5').getValues()) // [[null, null, 3, 4], [null, null, 4, 5], [1, 2, 5, 6], [2, 3, 6, 7], [3, 4, 7, 8]]
```

### Удаление ячеек

Метод [`FRange.deleteCells`](https://docs.univer.ai/ru-RU/reference/facade/range.md#deletecells) удаляет ячейки диапазона. Существующие данные на листе сдвигаются по указанному измерению в сторону удалённого диапазона.

```typescript
// Assume the active sheet empty sheet.
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const values = [
  [1, 2, 3, 4],
  [2, 3, 4, 5],
  [3, 4, 5, 6],
  [4, 5, 6, 7],
  [5, 6, 7, 8],
]

// Set the range A1:D5 with some values, the range A1:D5 will be:
// 1 | 2 | 3 | 4
// 2 | 3 | 4 | 5
// 3 | 4 | 5 | 6
// 4 | 5 | 6 | 7
// 5 | 6 | 7 | 8
const fRange = fWorksheet.getRange('A1:D5')
fRange.setValues(values)
console.log(fWorksheet.getRange('A1:D5').getValues()) // [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8]]

// Delete the range A1:B2 along the columns dimension, the range A1:D5 will be:
// 3 | 4 |   |
// 4 | 5 |   |
// 3 | 4 | 5 | 6
// 4 | 5 | 6 | 7
// 5 | 6 | 7 | 8
const fRange2 = fWorksheet.getRange('A1:B2')
fRange2.deleteCells(univerAPI.Enum.Dimension.COLUMNS)
console.log(fWorksheet.getRange('A1:D5').getValues()) // [[3, 4, null, null], [4, 5, null, null], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8]]

// Set the range A1:D5 values again, the range A1:D5 will be:
// 1 | 2 | 3 | 4
// 2 | 3 | 4 | 5
// 3 | 4 | 5 | 6
// 4 | 5 | 6 | 7
// 5 | 6 | 7 | 8
fRange.setValues(values)

// Delete the range A1:B2 along the rows dimension, the range A1:D5 will be:
// 3 | 4 | 3 | 4
// 4 | 5 | 4 | 5
// 5 | 6 | 5 | 6
//   |   | 6 | 7
//   |   | 7 | 8
const fRange3 = fWorksheet.getRange('A1:B2')
fRange3.deleteCells(univerAPI.Enum.Dimension.ROWS)
console.log(fWorksheet.getRange('A1:D5').getValues()) // [[3, 4, 3, 4], [4, 5, 4, 5], [5, 6, 5, 6], [null, null, 6, 7], [null, null, 7, 8]]
```

### Объединение ячеек

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// Merge B1:B2
const fRange = fWorksheet.getRange('B1:B2')
fRange.merge()
console.log(fRange.isMerged()) // true

// A1:B2 is merged
const fRange2 = fWorksheet.getRange('A1:B2')
console.log(fRange2.isMerged()) // false
console.log(fRange2.isPartOfMerge()) // true

// Break apart the merged range
fRange2.breakApart()

// merge horizontally: fRange2.mergeAcross();
// merge vertically: fRange2.mergeVertically();
// Get all merged ranges in the worksheet: fWorksheet.getMergedRanges();
```

### Выделение диапазона цветом

Метод [`FRange.highlight`](https://docs.univer.ai/ru-RU/reference/facade/range.md#highlight) выделяет диапазон указанным стилем с заданной основной ячейкой.

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// Highlight the range C3:E5 with default style
const fRange = fWorksheet.getRange('C3:E5')
fRange.highlight()

// Highlight the range C7:E9 with custom style and primary cell D8
const fRange2 = fWorksheet.getRange('C7:E9')
const primaryCell = fWorksheet.getRange('D8').getRange()
const disposable = fRange2.highlight(
  {
    stroke: 'red',
    fill: 'yellow',
  },
  {
    ...primaryCell,
    actualRow: primaryCell.startRow,
    actualColumn: primaryCell.startColumn,
  },
)

// Remove the range C7:E9 highlight after 5 seconds
setTimeout(() => {
  disposable.dispose()
}, 5000)
```

### Разбиение текста по столбцам

Метод [`FRange.splitTextToColumns`](https://docs.univer.ai/ru-RU/reference/facade/range.md#splittexttocolumns) разбивает текст в диапазоне по столбцам согласно указанному разделителю.

Пример с разделителем по умолчанию:

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// A1:A3 has following values:
//  A      |
//  1,2,3  |
//  4,,5,6 |
const fRange = fWorksheet.getRange('A1:A3')
fRange.setValues([['A'], ['1,2,3'], ['4,,5,6']])

// After calling splitTextToColumns(true), the range will be:
//  A |   |
//  1 | 2 | 3
//  4 | 5 | 6
fRange.splitTextToColumns(true)

// After calling splitTextToColumns(false), the range will be:
//  A |   |   |
//  1 | 2 | 3 |
//  4 |   | 5 | 6
fRange.splitTextToColumns(false)
```

Пример с указанным разделителем:

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// A1:A3 has following values:
//     A   |
//  1;;2;3 |
//  1;,2;3 |
const fRange = fWorksheet.getRange('A1:A3')
fRange.setValues([['A'], ['1;;2;3'], ['1;,2;3']])

// After calling splitTextToColumns(false, univerAPI.Enum.SplitDelimiterType.Semicolon|univerAPI.Enum.SplitDelimiterType.Comma), the range will be:
//  A |   |   |
//  1 |   | 2 | 3
//  1 |   | 2 | 3
fRange.splitTextToColumns(false, univerAPI.Enum.SplitDelimiterType.Semicolon | univerAPI.Enum.SplitDelimiterType.Comma)

// After calling splitTextToColumns(true, univerAPI.Enum.SplitDelimiterType.Semicolon|univerAPI.Enum.SplitDelimiterType.Comma), the range will be:
//  A |   |
//  1 | 2 | 3
//  1 | 2 | 3
fRange.splitTextToColumns(true, univerAPI.Enum.SplitDelimiterType.Semicolon | univerAPI.Enum.SplitDelimiterType.Comma)
```

Пример с пользовательским разделителем:

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// A1:A3 has following values:
//     A   |
//  1#2#3  |
//  4##5#6 |
const fRange = fWorksheet.getRange('A1:A3')
fRange.setValues([['A'], ['1#2#3'], ['4##5#6']])

// After calling splitTextToColumns(false, univerAPI.Enum.SplitDelimiterType.Custom, '#'), the range will be:
//  A |   |   |
//  1 | 2 | 3 |
//  4 |   | 5 | 6
fRange.splitTextToColumns(false, univerAPI.Enum.SplitDelimiterType.Custom, '#')

// After calling splitTextToColumns(true, univerAPI.Enum.SplitDelimiterType.Custom, '#'), the range will be:
//  A |   |
//  1 | 2 | 3
//  4 | 5 | 6
fRange.splitTextToColumns(true, univerAPI.Enum.SplitDelimiterType.Custom, '#')
```

### Получение координат диапазона

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
console.log(fRange.getCellRect()) // width、heigh、left、right、top、bottom、x、y
```

### Одновременное получение сведений об объединении и координат диапазона

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
console.log(fRange.getCell())
```

## Навигация на границах листа

Параметр `allowArrowKeyWrapOnSheetBoundary` управляет переходом на другую строку или столбец при достижении края листа клавишами со стрелками. По умолчанию он равен `true`; значение `false` останавливает переход на границе. Циклическая навигация Enter/Tab внутри выделения не меняется. В пресете укажите параметр в `sheets`, а в режиме плагинов — непосредственно в `UniverSheetsUIPlugin`.

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

```typescript
univer.registerPlugin(UniverSheetsUIPlugin, {
  allowArrowKeyWrapOnSheetBoundary: false,
})
```

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

```typescript
createUniver({
  presets: [
    UniverSheetsCorePreset({
      sheets: {
        allowArrowKeyWrapOnSheetBoundary: false,
      },
    }),
  ],
})
```

## События и редактирование ячеек

Примеры сгруппированы по указателю, отрисовке, редактированию и буферу обмена. Полный список событий и типов параметров см. в [Events Reference](https://docs.univer.ai/ru-RU/reference/facade/events.md#univerjssheets-ui). В режиме плагинов импортируйте `@univerjs/sheets-ui/facade` до подписки; предустановка Sheets Core уже включает его. Освобождайте подписки при удалении компонента или страницы.

### Пример использования

Для всех событий можно зарегистрировать обработчик с помощью метода `addEvent`. Базовый формат:

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

const subscription = univerAPI.addEvent(univerAPI.Event.CellClicked, ({ row, column }) => {
  console.log(row, column)
})

// Call subscription.dispose() when the owning component or page is removed.
```

### Событие Cell PointerMove

Событие `CellPointerMove` возникает при перемещении указателя мыши над ячейкой и содержит сведения о ячейке под указателем.

```typescript
univerAPI.addEvent(univerAPI.Event.CellPointerMove, (params) => {
  // Get event parameters
  const { worksheet, workbook, row, column } = params
  console.log('Current cell position:', worksheet.getRange(row, column).getA1Notation())
})
```

### Событие Cell PointerDown

Событие `CellPointerDown` возникает при нажатии кнопки мыши на ячейке.

```typescript
univerAPI.addEvent(univerAPI.Event.CellPointerDown, (params) => {
  const { worksheet, workbook, row, column } = params
  console.log('Mouse down cell:', worksheet.getRange(row, column).getA1Notation())
})
```

### Событие Cell PointerUp

Событие `CellPointerUp` возникает при отпускании кнопки мыши на ячейке.

```typescript
univerAPI.addEvent(univerAPI.Event.CellPointerUp, (params) => {
  const { worksheet, workbook, row, column } = params
  console.log('Mouse up cell:', worksheet.getRange(row, column).getA1Notation())
})
```

### Событие Cell Hover

Событие `CellHover` возникает при наведении указателя мыши на ячейку.

```typescript
univerAPI.addEvent(univerAPI.Event.CellHover, (params) => {
  const { worksheet, workbook, row, column } = params
  console.log('Hovered cell:', worksheet.getRange(row, column).getA1Notation())
})
```

### Событие Cell DragOver

Событие `DragOver` возникает при перетаскивании элемента над ячейкой.

```typescript
univerAPI.addEvent(univerAPI.Event.DragOver, (params) => {
  const { worksheet, workbook, row, column } = params
  console.log('Drag over cell:', worksheet.getRange(row, column).getA1Notation())
})
```

### Событие Cell Drop

Событие `Drop` возникает, когда элемент отпускают на ячейке.

```typescript
univerAPI.addEvent(univerAPI.Event.Drop, (params) => {
  const { worksheet, workbook, row, column } = params
  console.log('Drop target cell:', worksheet.getRange(row, column).getA1Notation())
})
```

### Событие Cell Click

Событие `CellClicked` возникает при щелчке по ячейке.

```typescript
univerAPI.addEvent(univerAPI.Event.CellClicked, (params) => {
  const { worksheet, workbook, row, column } = params
  console.log('Clicked cell:', worksheet.getRange(row, column).getA1Notation())
})
```

### Событие отрисовки ячейки

`registerCellCustomRender` регистрирует пользовательские функции отрисовки ячеек.

Пример 1. Отрисовка в фиксированной позиции: добавление строк не влияет на позицию

```typescript
// Fixed position rendering
univerAPI.registerCellCustomRender([
  {
    drawWith: (ctx, info, skeleton, spreadsheets) => {
      const { row, col } = info
      // Render a checkmark at position (1,1)
      if (row === 1 && col === 1) {
        const { primaryWithCoord } = info
        const { startX, startY } = primaryWithCoord
        ctx.fillText('✅', startX, startY + 10)
      }
    },
  },
])

// Refresh canvas to apply rendering
univerAPI.getActiveWorkbook().getActiveSheet().refreshCanvas()
```

Пример 2. Отрисовка по маркеру: позиция меняется при изменении строк или столбцов

```typescript
// Set marker
univerAPI
  .getActiveWorkbook()
  .getActiveSheet()
  .getRange('B2')
  .setValue({ custom: { key: 'needCheck' } })

// Render based on marker
univerAPI.registerCellCustomRender([
  {
    drawWith: (ctx, info, skeleton, spreadsheets) => {
      const { row, col, data } = info
      // Render checkmark at marked position
      if (data?.custom?.key === 'needCheck') {
        const { primaryWithCoord } = info
        const { startX, startY } = primaryWithCoord
        ctx.fillText('✅', startX, startY + 10)
      }
    },
  },
])

// Refresh canvas to apply rendering
univerAPI.getActiveWorkbook().getActiveSheet().refreshCanvas()
```

### События редактирования ячейки

#### Начало редактирования

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
fWorkbook.startEditing()
```

#### Завершение редактирования

```typescript
// Pass true to commit changes, false to cancel editing
// This is an async function, requires await
const fWorkbook = univerAPI.getActiveWorkbook()
await fWorkbook.endEditingAsync(true)
```

#### Событие начала редактирования

Событие `BeforeSheetEditStart` возникает перед началом редактирования ячейки.

```typescript
univerAPI.addEvent(univerAPI.Event.BeforeSheetEditStart, (params) => {
  const { worksheet, workbook, row, column, eventType, keycode } = params
  console.log('Before cell edit:', params)

  // If you want to prevent entering the editing state
  params.cancel = true
})
```

Событие `SheetEditStarted` возникает при начале редактирования ячейки.

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.SheetEditStarted, (params) => {
  const { worksheet, workbook, row, column, eventType, keycode } = params
  console.log(params)
})

// Remove the event listener, use `disposable.dispose()`
```

#### Событие завершения редактирования

Событие `BeforeSheetEditEnd` возникает перед завершением редактирования ячейки.

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeSheetEditEnd, (params) => {
  const { worksheet, workbook, row, column, value, eventType, keycode, isConfirm } = params
  console.log(params)

  // Cancel the cell edit end operation
  params.cancel = true
})

// Remove the event listener, use `disposable.dispose()`
```

Событие `SheetEditEnded` возникает после завершения редактирования ячейки.

```typescript
univerAPI.addEvent(univerAPI.Event.SheetEditEnded, (params) => {
  const { worksheet, workbook, row, column, eventType, keycode, isConfirm } = params
  console.log('After cell edit:', params)
})
```

### События буфера обмена

#### BeforeClipboardChange

Событие `BeforeClipboardChange` возникает перед изменением содержимого буфера обмена. Оно позволяет проверить или изменить содержимое до изменения.

```typescript
univerAPI.addEvent(univerAPI.Event.BeforeClipboardChange, (params) => {
  const { text, html } = params
  console.log('Clipboard content:', text, html)
  // If you want to cancel the clipboard change
  // params.cancel = true;
})
```

#### BeforeClipboardPaste

Событие `BeforeClipboardPaste` возникает перед вставкой содержимого. Оно позволяет проверить или изменить содержимое до вставки.

```typescript
univerAPI.addEvent(univerAPI.Event.BeforeClipboardPaste, (params) => {
  const { text, html } = params
  console.log('Content to paste:', text, html)
  // If you want to cancel the paste operation
  // params.cancel = true;
})
```

#### ClipboardChanged

Событие `ClipboardChanged` возникает после изменения содержимого буфера обмена.

```typescript
univerAPI.addEvent(univerAPI.Event.ClipboardChanged, (params) => {
  const { text, html } = params
  console.log('New clipboard content:', text, html)
})
```

#### ClipboardPasted

Событие `ClipboardPasted` возникает после вставки содержимого.

```typescript
univerAPI.addEvent(univerAPI.Event.ClipboardPasted, (params) => {
  const { text, html } = params
  console.log('Pasted content:', text, html)
})
```

## Устранение проблем редактирования

### Как получать данные из редактора ячейки в реальном времени?

Подпишитесь на `SheetEditChanging`, чтобы читать форматированный текст во время редактирования ячейки. Значение ещё находится в редакторе и сохраняется в листе при завершении редактирования.

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

const subscription = univerAPI.addEvent(univerAPI.Event.SheetEditChanging, ({ value }) => {
  console.log(value.toPlainText())
})

// Call subscription.dispose() when the owning component or page is removed.
```

### Почему при щелчке по внешней кнопке снимок не содержит данные ячейки, в которой установлен фокус?

Данные ячейки синхронизируются со снимком, когда редактор ячейки теряет фокус, то есть после завершения редактирования. Поэтому перед получением снимка убедитесь, что ячейка потеряла фокус. Редактирование можно завершить следующим образом:

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

async function saveWorkbook() {
  const fWorkbook = univerAPI.getActiveWorkbook()
  if (!fWorkbook) return

  await fWorkbook.endEditingAsync(true)
  const snapshot = fWorkbook.save()
  console.log(snapshot)
}

$btn.addEventListener('click', () => {
  saveWorkbook().catch(console.error)
})
```

Источник: [https://github.com/dream-num/univer/issues/1314](https://github.com/dream-num/univer/issues/1314)

### При создании Workbook через Facade API некоторые API могут не работать сразу, поскольку им требуется полностью отрисованный интерфейс. Рекомендуется выполнять соответствующие операции на этапе жизненного цикла `Rendered` или `Steady`.

Многие API работают только после полной отрисовки интерфейса. Если вызвать их сразу после создания Workbook, интерфейс может быть ещё не готов. Рекомендуется выполнять такие операции на этапе жизненного цикла `Rendered` или `Steady`:

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.LifeCycleChanged, ({ stage }) => {
  if (stage === univerAPI.Enum.LifecycleStages.Steady) {
    // code...
  }
})

// To remove the event listener, you can call `disposable.dispose()`
```

Источник: [Жизненный цикл](https://docs.univer.ai/ru-RU/guides/sheets/getting-started/lifecycle.md)
