# 範囲・選択・セル

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

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

- Requested language: `ja-JP`

- Content language: `ja-JP`

- Documentation version: `1.1.0`

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

---

以下から目的のセクションへ進んでください。基本操作、応用例、設定、トラブルシューティングをこのページにまとめ、完全な API 定義は Reference で管理しています。

* [範囲](#range)
* [選択](#selection)
* [範囲の応用操作](#range-operations)
* [シート端でのキーボード移動](#keyboard-navigation)
* [セルのイベントと編集](#events)
* [セル編集のトラブルシューティング](#troubleshooting)

## 範囲

範囲（Range）とは、ワークシート上の矩形領域であり、開始行番号・開始列番号と縦横の長さ、または開始行番号・開始列番号と終了行番号・終了列番号によって特定されます。

スプレッドシートにおける多くの操作（値の設定／取得、スタイルの設定／取得など）は Range API を通じて実行できます。

範囲関連 Facade API の完全な定義は [FRange FacadeAPI](https://docs.univer.ai/ja-JP/reference/facade/range.md) を参照してください。

### 範囲の生成

範囲を取得するには、開始行番号・開始列番号・行数（高さ）・列数（幅）を指定します。

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

// セル A1 の範囲を生成
const fRange = fWorksheet.getRange(0, 0)
console.log(fRange, fRange.getA1Notation())

// セル A1:B2 の範囲を生成
const fRange2 = fWorksheet.getRange(0, 0, 2, 2)
console.log(fRange2, fRange2.getA1Notation())
```

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

// Sheet1 シート上の A1:B2 範囲を取得
const fRange1 = fWorksheet.getRange('Sheet1!A1:B2')
console.log(fRange1, fRange1.getA1Notation())

// 単一セル A1 を取得
const fRange2 = fWorksheet.getRange('A1')
console.log(fRange2, fRange2.getA1Notation())

// A1:B2 範囲を取得
const fRange3 = fWorksheet.getRange('A1:B2')
console.log(fRange3, fRange3.getA1Notation())

// 列 A 全体を取得
const fRange4 = fWorksheet.getRange('A:A')
console.log(fRange4, fRange4.getA1Notation())

// 行 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()) // 範囲左上セルの値
console.log(fRange.getRawValue()) // 範囲左上セルの生値
console.log(fRange.getDisplayValue()) // 範囲左上セルの表示値
console.log(fRange.getCellData()) // 範囲左上セルのセルデータ
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()) // 全セルの値
console.log(fRange.getRawValues()) // 全セルの生値
console.log(fRange.getDisplayValues()) // 全セルの表示値
console.log(fRange.getCellDataGrid()) // 全セルのセルデータ
console.log(fRange.getValues(true))
```

範囲内の数式を取得：

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

console.log(fRange.getFormula()) // 範囲左上セルの数式
console.log(fRange.getFormulas()) // 範囲内全セルの数式
```

### 範囲への値設定

#### 単一値の設定

値またはセルオブジェクトを渡すと、範囲内の全セルがその内容で上書きされます。文字列が `=` で始まる場合は数式として解釈されます。

例: A1:B2 に `Hello, Univer` を設定

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

入力セルとは別の C1 に `=A1+B1` を設定します：

```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')
```

セルオブジェクトを設定：

```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/ja-JP/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' }],
])
```

#### オブジェクトによる複数値設定

オブジェクトを渡す場合、第 1 インデックスが行番号、第 2 インデックスが列番号を表し、範囲サイズと一致している必要はありません（指定された座標のみ反映）。

```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/ja-JP/reference/facade/range.md#clear)： コンテンツと書式をすべてクリア
* [`FRange.clearContent`](https://docs.univer.ai/ja-JP/reference/facade/range.md#clearcontent)： コンテンツのみクリア
* [`FRange.clearFormat`](https://docs.univer.ai/ja-JP/reference/facade/range.md#clearformat)： 書式のみクリア

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

// コンテンツと書式をクリア
fRange.clear()
```

### 範囲スタイルの取得

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
console.log(fRange.getCellStyleData()) // 左上セルのスタイルデータ
console.log(fRange.getCellStyle()) // 左上セルのスタイル
console.log(fRange.getCellStyles()) // 全セルのスタイル
```

### 範囲スタイルの設定

```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 の配列です。各要素は Range API を通じて操作できます。

また、現在の選択の取得・選択状態の設定・選択変更イベントの監視用 API も提供しています。

選択関連 Facade API の完全な定義は [FSelection FacadeAPI](https://docs.univer.ai/ja-JP/reference/facade/selection.md) を参照してください。

### アクティブ選択の取得

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

// A1:B2 を新たにアクティブ選択にする
const fRange = fWorksheet.getRange('A1:B2')
fRange.activate()

// 現在のアクティブ選択を取得
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()

// FRange で A1:B2 を選択
const fRange = fWorksheet.getRange('A1:B2')
fRange.activate()

// FWorksheet で C1:D2 に切替
fWorksheet.setActiveSelection(fWorksheet.getRange('C1:D2'))
```

### 現在セルの取得

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

// A10:B11 をアクティブ選択
const fRange = fWorksheet.getRange('A10:B11')
fRange.activate()

// 現在のアクティブセル
let fSelection = fWorksheet.getSelection()
const { actualRow, actualColumn } = fSelection.getCurrentCell()
console.log(fWorksheet.getRange(actualRow, actualColumn).getA1Notation()) // A10

// アクティブセルを B11 に更新
fSelection = fSelection.updatePrimaryCell(fWorksheet.getRange('B11'))
const { actualRow: newRow, actualColumn: newColumn } = fSelection.getCurrentCell()
console.log(fWorksheet.getRange(newRow, newColumn).getA1Notation()) // B11
```

### 選択の無効化／有効化／非表示／再表示

無効化すると選択操作に反応しません。非表示（transparent）は動作自体は有効なまま可視描画のみ消えます。

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

// 無効化
fWorkbook.disableSelection()

// 有効化
fWorkbook.enableSelection()

// 非表示
fWorkbook.transparentSelection()

// 再表示
fWorkbook.showSelection()
```

### 選択変更の監視

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

## セル

セルデータはワークシート内部で二次元 Map として保持され、第 1・第 2 インデックスがそれぞれ行番号・列番号に対応します。

典型的なセルオブジェクト例:

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

フィールド詳細は [Configure Cell Data](https://docs.univer.ai/ja-JP/guides/sheets/model/cell-data.md) を参照してください。

### 補足

1. セル操作は高さ 1・幅 1 の範囲操作とみなせます。範囲操作については [Range](https://docs.univer.ai/ja-JP/guides/sheets/features/core/range-selection.md#range) を参照。
2. Univer API プラグインは拡張セル属性を `Workbook` の `resources` プロパティにも格納します。詳細は [Plugin Custom Model](/blog/custom-model) を参照。

## 範囲の応用操作

### セル挿入

[`FRange.insertCells`](https://docs.univer.ai/ja-JP/reference/facade/range.md#insertcells) は指定範囲内に空セルを挿入し、指定次元方向に既存データを押し出します。

```typescript
// アクティブシートは空と仮定
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],
]

// A1:D5 を初期化
// 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]]

// A1:B2 に列方向で空セルを挿入
//   |   | 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]]

// 再度 A1:D5 を元に戻す
// 1 | 2 | 3 | 4
// 2 | 3 | 4 | 5
// 3 | 4 | 5 | 6
// 4 | 5 | 6 | 7
// 5 | 6 | 7 | 8
fRange.setValues(values)

// A1:B2 に行方向で空セルを挿入
//   |   | 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/ja-JP/reference/facade/range.md#deletecells) は指定範囲を削除し、指定次元方向へデータを詰めます。

```typescript
// アクティブシートは空と仮定
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],
]

// 初期状態
// 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]]

// A1:B2 を列方向で削除
// 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]]

// 再設定
// 1 | 2 | 3 | 4
// 2 | 3 | 4 | 5
// 3 | 4 | 5 | 6
// 4 | 5 | 6 | 7
// 5 | 6 | 7 | 8
fRange.setValues(values)

// A1:B2 を行方向で削除
// 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()

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

// A1:B2 について
const fRange2 = fWorksheet.getRange('A1:B2')
console.log(fRange2.isMerged()) // false
console.log(fRange2.isPartOfMerge()) // true

// 結合解除
fRange2.breakApart()

// 水平結合：fRange2.mergeAcross();
// 垂直結合：fRange2.mergeVertically();
// シート内の全結合範囲取得：fWorksheet.getMergedRanges();
```

### 範囲のハイライト

[`FRange.highlight`](https://docs.univer.ai/ja-JP/reference/facade/range.md#highlight) は指定スタイルと主セル（primary cell）で範囲を強調表示します。

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

// 既定スタイルで C3:E5 をハイライト
const fRange = fWorksheet.getRange('C3:E5')
fRange.highlight()

// カスタムスタイル＋主セル D8 で C7:E9 をハイライト
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,
  },
)

// 5 秒後に C7:E9 のハイライト解除
setTimeout(() => {
  disposable.dispose()
}, 5000)
```

### テキストを列に分割

[`FRange.splitTextToColumns`](https://docs.univer.ai/ja-JP/reference/facade/range.md#splittexttocolumns) は指定した区切り文字に従いテキストを複数列へ分割します。

デフォルト区切り文字の例:

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

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

// splitTextToColumns(true) 呼び出し後:
//  A |   |
//  1 | 2 | 3
//  4 | 5 | 6
fRange.splitTextToColumns(true)

// splitTextToColumns(false) 呼び出し後:
//  A |   |   |
//  1 | 2 | 3 |
//  4 |   | 5 | 6
fRange.splitTextToColumns(false)
```

特定区切り文字の例:

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

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

// セミコロン + カンマで分割（空要素保持 = false），結果：
//  A |   |   |
//  1 |   | 2 | 3
//  1 |   | 2 | 3
fRange.splitTextToColumns(false, univerAPI.Enum.SplitDelimiterType.Semicolon | univerAPI.Enum.SplitDelimiterType.Comma)

// 空要素圧縮 = true，結果：
//  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：
//     A   |
//  1#2#3  |
//  4##5#6 |
const fRange = fWorksheet.getRange('A1:A3')
fRange.setValues([['A'], ['1#2#3'], ['4##5#6']])

// カスタム '#'、空要素保持 = false
//  A |   |   |
//  1 | 2 | 3 |
//  4 |   | 5 | 6
fRange.splitTextToColumns(false, univerAPI.Enum.SplitDelimiterType.Custom, '#')

// 空要素圧縮 = true
//  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/ja-JP/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) => {
  // イベントパラメータ取得
  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())
})
```

### Cell Render イベント

`registerCellCustomRender` はセル用のカスタムレンダラーを登録します。

例 1: 固定位置レンダリング（行追加などによる位置変動なし）

```typescript
// 固定位置レンダリング
univerAPI.registerCellCustomRender([
  {
    drawWith: (ctx, info, skeleton, spreadsheets) => {
      const { row, col } = info
      // 位置 (1,1) にチェックマークを描画
      if (row === 1 && col === 1) {
        const { primaryWithCoord } = info
        const { startX, startY } = primaryWithCoord
        ctx.fillText('✅', startX, startY + 10)
      }
    },
  },
])

// 再描画反映
univerAPI.getActiveWorkbook().getActiveSheet().refreshCanvas()
```

例 2: マーカー方式（行／列シフトに追随）

```typescript
// マーカー設定
univerAPI
  .getActiveWorkbook()
  .getActiveSheet()
  .getRange('B2')
  .setValue({ custom: { key: 'needCheck' } })

// マーカーに基づき描画
univerAPI.registerCellCustomRender([
  {
    drawWith: (ctx, info, skeleton, spreadsheets) => {
      const { row, col, data } = info
      // マーカーを持つセルにチェックマークを描画
      if (data?.custom?.key === 'needCheck') {
        const { primaryWithCoord } = info
        const { startX, startY } = primaryWithCoord
        ctx.fillText('✅', startX, startY + 10)
      }
    },
  },
])

// 再描画
univerAPI.getActiveWorkbook().getActiveSheet().refreshCanvas()
```

### セル編集イベント

#### 編集開始

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

#### 編集終了

```typescript
// true で確定、false でキャンセル
// 非同期関数のため 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)

  // 編集状態遷移を阻止する場合
  params.cancel = true
})
```

`SheetEditStarted` はセル編集開始時にトリガーされます。

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

// 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
})

// 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)
  // 貼り付けをキャンセルする場合：
  // params.cancel = true;
})
```

#### BeforeClipboardPaste

`BeforeClipboardPaste` イベントは貼り付け実行直前にトリガーされます。貼り付け内容の検査・変換・拒否に利用できます。

```typescript
univerAPI.addEvent(univerAPI.Event.BeforeClipboardPaste, (params) => {
  const { text, html } = params
  console.log('Content to paste:', text, html)
  // 貼り付けをキャンセルする場合：
  // 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)

### Facade API で Workbook を生成直後に一部 API が動作しない

一部 API は UI の完全レンダリング後でないと機能しません。`Rendered` または `Steady` ライフサイクル段階で処理を行うことを推奨します。

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.LifeCycleChanged, ({ stage }) => {
  if (stage === univerAPI.Enum.LifecycleStages.Steady) {
    // 実行コード
  }
})

// disposable.dispose() で解除
```

参考：[Lifecycle](https://docs.univer.ai/ja-JP/guides/sheets/getting-started/lifecycle.md)
