范围 & 选区 & 单元格

范围 Range

范围指工作表中的一块矩形区域,有起始行号、起始列号、长宽或者结束行号、结束列号来确定。

表格中的大部分操作都可以通过范围 API 来操作,如设置值、获取值、设置样式、获取样式等。

Facade API

范围完整 Facade API 类型定义,请查看 FRange Facade API

创建范围

获得一个范围需要知道起始行号、起始列号、长宽。

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())// 获取单个单元格 A1const 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()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()) // 范围左上角单元格 ICellData 对象console.log(fRange.getRichTextValue()) // 范围左上角单元格富文本值console.log(fRange.getRichTextValue().toPlainText()) // 范围左上角单元格富文本值的纯文本

获取范围的所有值

TypeScript
const fWorkbook = univerAPI.getActiveWorkbook()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.getCellDatas()) // 范围所有单元格 ICellData 对象console.log(fRange.getRichTextValues()) // 范围所有单元格富文本值

获取范围的所有公式

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

设置 A1+B1 的值为公式:

TypeScript
const fWorkbook = univerAPI.getActiveWorkbook()const fWorksheet = fWorkbook.getActiveSheet()const fRange = fWorksheet.getRange('A1:B2')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 方法:

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',  },})

清理范围数据

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)

插入单元格

FRange.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 | 8const 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 中插入空单元格,范围 A1:D5 将变为://   |   | 1 | 2//   |   | 2 | 3// 3 | 4 | 5 | 6// 4 | 5 | 6 | 7// 5 | 6 | 7 | 8const 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 的值,范围 A1:D5 将变为:// 1 | 2 | 3 | 4// 2 | 3 | 4 | 5// 3 | 4 | 5 | 6// 4 | 5 | 6 | 7// 5 | 6 | 7 | 8fRange.setValues(values)// 沿着行维度在范围 A1:B2 中插入空单元格,范围 A1:D5 将变为://   |   | 3 | 4//   |   | 4 | 5// 1 | 2 | 5 | 6// 2 | 3 | 6 | 7// 3 | 4 | 7 | 8const 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 方法可以在范围内删除单元格。工作表中沿指定维度的现有数据将向已删除的范围移动。

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 | 8const 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,范围 A1:D5 将变为:// 3 | 4 |   |// 4 | 5 |   |// 3 | 4 | 5 | 6// 4 | 5 | 6 | 7// 5 | 6 | 7 | 8const 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]]// 再次设置范围 A1:D5 的值,范围 A1:D5 将变为:// 1 | 2 | 3 | 4// 2 | 3 | 4 | 5// 3 | 4 | 5 | 6// 4 | 5 | 6 | 7// 5 | 6 | 7 | 8fRange.setValues(values)// 沿着行维度删除范围 A1:B2,范围 A1:D5 将变为:// 3 | 4 | 3 | 4// 4 | 5 | 4 | 5// 5 | 6 | 5 | 6//   |   | 6 | 7//   |   | 7 | 8const 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:B2const fRange = fWorksheet.getRange('B1:B2')fRange.merge()console.log(fRange.isMerged()) // true// A1:B2 是否合并const fRange2 = fWorksheet.getRange('A1:B2')console.log(fRange2.isMerged()) // falseconsole.log(fRange2.isPartOfMerge()) // true// 取消合并fRange2.breakApart()// 水平合并:fRange2.mergeAcross();// 垂直合并:fRange2.mergeVertically();// 获取表格中所有合并单元格范围:fWorksheet.getMergedRanges();

高亮范围

FRange.highlight 方法可以使用指定样式和主单元格高亮范围。

TypeScript
const fWorkbook = univerAPI.getActiveWorkbook()const fWorksheet = fWorkbook.getActiveSheet()// Highlight the range C3:E5 with default styleconst fRange = fWorksheet.getRange('C3:E5')fRange.highlight()// Highlight the range C7:E9 with custom style and primary cell D8const 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 secondssetTimeout(() => {  disposable.dispose()}, 5000)

数据分列

FRange.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 | 6fRange.splitTextToColumns(true)// 调用 splitTextToColumns(false) 后,范围值将变为://  A |   |   |//  1 | 2 | 3 |//  4 |   | 5 | 6fRange.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']])// 调用 splitTextToColumns(false, univerAPI.Enum.SplitDelimiterType.Semicolon|univerAPI.Enum.SplitDelimiterType.Comma) 后,范围值将变为://  A |   |   |//  1 |   | 2 | 3//  1 |   | 2 | 3fRange.splitTextToColumns(false, univerAPI.Enum.SplitDelimiterType.Semicolon | univerAPI.Enum.SplitDelimiterType.Comma)// 调用 splitTextToColumns(true, univerAPI.Enum.SplitDelimiterType.Semicolon|univerAPI.Enum.SplitDelimiterType.Comma) 后,范围值将变为://  A |   |//  1 | 2 | 3//  1 | 2 | 3fRange.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']])// 调用 splitTextToColumns(false, univerAPI.Enum.SplitDelimiterType.Custom, '#') 后,范围值将变为://  A |   |   |//  1 | 2 | 3 |//  4 |   | 5 | 6fRange.splitTextToColumns(false, univerAPI.Enum.SplitDelimiterType.Custom, '#')// 调用 splitTextToColumns(true, univerAPI.Enum.SplitDelimiterType.Custom, '#') 后,范围值将变为://  A |   |//  1 | 2 | 3//  4 | 5 | 6fRange.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())

选区 Selection

Univer 表格支持多选区,所以选区是一个范围数组,可以通过范围 API 来操作选区数据。

我们还提供 API 来获取当前选区、设置选区和监听选区变化。

Facade API

选区完整 Facade API 类型定义,请查看 FSelection Facade API

获取激活选区的范围

TypeScript
const fWorkbook = univerAPI.getActiveWorkbook()const fWorksheet = fWorkbook.getActiveSheet()// 激活新的选区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:B2const fRange = fWorksheet.getRange('A1:B2')fRange.activate()// 通过 FWorksheet 设置选区 C1:D2fWorksheet.setActiveSelection(fWorksheet.getRange('C1:D2'))

获取当前激活的单元格

TypeScript
const fWorkbook = univerAPI.getActiveWorkbook()const fWorksheet = fWorkbook.getActiveSheet()// 激活选区 A10:B11const fRange = fWorksheet.getRange('A10:B11')fRange.activate()// 获取当前激活的单元格let fSelection = fWorksheet.getSelection()const { actualRow, actualColumn } = fSelection.getCurrentCell()console.log(fWorksheet.getRange(actualRow, actualColumn).getA1Notation()) // A10// 更新新的激活单元格 B11fSelection = fSelection.updatePrimaryCell(fWorksheet.getRange('B11'))const { actualRow: newRow, actualColumn: newColumn } = fSelection.getCurrentCell()console.log(fWorksheet.getRange(newRow, newColumn).getA1Notation()) // B11

禁用/启用/隐藏/显示选区

禁用后,选区将不会响应。设置选区不可见,与禁用选区不同,选区仍然有效,只是看不到它们。

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

单元格 Cell

单元格数据以二维 Map 的形式存储在工作表中,一二级索引分别代表行号和列号。

以下是一个典型的单元格对象:

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

详细的字段说明请参考 单元格信息

注意事项

  1. 对单元格的操作可以看作对行高 1 、列宽 1 的范围进行操作,操作范围请阅读 范围-range
  2. 插件还会将拓展的单元格属性存储在 Workbookresources 属性中,详细请阅读 插件自定义模型

事件列表

以下是可用的单元格相关事件列表:

事件名称描述参数类型示例
CellPointerMove鼠标移动到单元格上时触发ICellEventParamconst { worksheet, workbook, row, column } = params
CellPointerDown鼠标按下时触发ICellEventParamconst { worksheet, workbook, row, column } = params
CellPointerUp鼠标释放时触发ICellEventParamconst { worksheet, workbook, row, column } = params
CellHover鼠标悬停在单元格上时触发ICellEventParamconst { worksheet, workbook, row, column } = params
DragOver拖动元素经过单元格时触发ICellEventParamconst { worksheet, workbook, row, column } = params
Drop拖动元素放置到单元格时触发ICellEventParamconst { worksheet, workbook, row, column } = params
CellClicked点击单元格时触发ICellEventParamconst { worksheet, workbook, row, column } = params
BeforeSheetEditStart单元格开始编辑前触发IBeforeSheetEditStartEventParamsconst { worksheet, workbook, row, column, eventType, keycode } = params
SheetEditStarted单元格开始编辑时触发ISheetEditStartedEventParamsconst { worksheet, workbook, row, column, eventType, keycode } = params
SheetEditChanging单元格编辑内容变化时触发ISheetEditChangingEventParamsconst { worksheet, workbook, row, column, value } = params
BeforeSheetEditEnd单元格结束编辑前触发IBeforeSheetEditEndEventParamsconst { worksheet, workbook, row, column, value, eventType, keycode, isConfirm } = params
SheetEditEnded单元格结束编辑后触发ISheetEditEndedEventParamsconst { worksheet, workbook, row, column, eventType, keycode, isConfirm } = params

使用示例

所有事件都可以通过 addEvent 方法进行监听。基本格式如下:

TypeScript
univerAPI.addEvent(univerAPI.Event.事件名称, (params) => {  // 事件处理逻辑})

单元格 PointerMove 事件

CellPointerMove 事件在鼠标移动到单元格上时触发。通过此事件可以获取当前鼠标指向的单元格信息。

TypeScript
univerAPI.addEvent(univerAPI.Event.CellPointerMove, (params) => {  // 获取事件参数  const { worksheet, workbook, row, column } = params  console.log('当前单元格位置:', worksheet.getRange(row, column).getA1Notation())})

单元格 PointerDown 事件

CellPointerDown 事件在鼠标按下时触发。

TypeScript
univerAPI.addEvent(univerAPI.Event.CellPointerDown, (params) => {  const { worksheet, workbook, row, column } = params  console.log('鼠标按下的单元格:', worksheet.getRange(row, column).getA1Notation())})

单元格 PointerUp 事件

CellPointerUp 事件在鼠标释放时触发。

TypeScript
univerAPI.addEvent(univerAPI.Event.CellPointerUp, (params) => {  const { worksheet, workbook, row, column } = params  console.log('鼠标释放的单元格:', worksheet.getRange(row, column).getA1Notation())})

单元格 Hover 事件

CellHover 事件在鼠标悬停在单元格上时触发。

TypeScript
univerAPI.addEvent(univerAPI.Event.CellHover, (params) => {  const { worksheet, workbook, row, column } = params  console.log('悬停的单元格:', worksheet.getRange(row, column).getA1Notation())})

单元格 DragOver 事件

DragOver 事件在拖动元素经过单元格时触发。

TypeScript
univerAPI.addEvent(univerAPI.Event.DragOver, (params) => {  const { worksheet, workbook, row, column } = params  console.log('拖动经过的单元格:', worksheet.getRange(row, column).getA1Notation())})

单元格 Drop 事件

Drop 事件在拖动元素放置到单元格时触发。

TypeScript
univerAPI.addEvent(univerAPI.Event.Drop, (params) => {  const { worksheet, workbook, row, column } = params  console.log('放置的单元格:', worksheet.getRange(row, column).getA1Notation())})

单元格 Click 事件

CellClicked 事件在点击单元格时触发。

TypeScript
univerAPI.addEvent(univerAPI.Event.CellClicked, (params) => {  const { worksheet, workbook, row, column } = params  console.log('点击的单元格:', worksheet.getRange(row, column).getA1Notation())})

单元格渲染事件

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 表示取消编辑// 这是一个异步函数,需要使用 awaitconst 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('单元格编辑前:', 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)  // 取消单元格编辑结束操作  params.cancel = true})// 移除事件监听器,使用 `disposable.dispose()`

SheetEditEnded 事件在单元格结束编辑后触发。

TypeScript
univerAPI.addEvent(univerAPI.Event.SheetEditEnded, (params) => {  const { worksheet, workbook, row, column, eventType, keycode, isConfirm } = params  console.log('单元格编辑后:', params)})

剪贴板事件

BeforeClipboardChange

BeforeClipboardChange 事件在剪贴板内容改变之前触发。你可以使用此事件在内容改变之前监控或修改剪贴板内容。

TypeScript
univerAPI.addEvent(univerAPI.Event.BeforeClipboardChange, (params) => {  const { text, html } = params  console.log('剪贴板内容:', text, html)  // 如果想取消剪贴板内容的改变  // params.cancel = true;})

BeforeClipboardPaste

BeforeClipboardPaste 事件在内容粘贴之前触发。你可以使用此事件在粘贴之前监控或修改内容。

TypeScript
univerAPI.addEvent(univerAPI.Event.BeforeClipboardPaste, (params) => {  const { text, html } = params  console.log('待粘贴内容:', text, html)  // 如果想取消粘贴操作  // params.cancel = true;})

ClipboardChanged

ClipboardChanged 事件在剪贴板内容改变之后触发。

TypeScript
univerAPI.addEvent(univerAPI.Event.ClipboardChanged, (params) => {  const { text, html } = params  console.log('新的剪贴板内容:', text, html)})

ClipboardPasted

ClipboardPasted 事件在内容粘贴完成后触发。

TypeScript
univerAPI.addEvent(univerAPI.Event.ClipboardPasted, (params) => {  const { text, html } = params  console.log('已粘贴的内容:', text, html)})

杂项

如何实时获取单元格编辑器内的数据?

Univer Sheets 的单元格编辑器底层采用了 Univer Docs 的编辑器引擎,因此可以通过 Facade API 获取当前激活的 Univer Docs 编辑器的快照(snapshot)数据,实现对编辑内容的实时获取和处理。

TypeScript
univerAPI.addEvent(univerAPI.Event.CommandExecuted, ({ id }) => {  if (id === 'doc.command.insert-text' || id === 'doc.command.delete-text') {    const doc = univerAPI.getActiveDocument()    if (doc) {      const snapshot = doc.save()      console.log(snapshot.body?.dataStream)    }  }})

参考:https://github.com/dream-num/univer/discussions/2261

单元格编辑器聚焦时,点击外部按钮触发事件,获取的 snapshot 未包含当前单元格数据

单元格数据会在编辑器失焦(即编辑状态结束)时同步到 snapshot。因此,在尝试获取 snapshot 数据前,应确保单元格已经失去焦点。可以通过如下方式主动结束编辑:

TypeScript
import '@univerjs/sheets-ui/facade'$btn.addEventListener('click', () => {  univerAPI.getActiveWorkbook().endEditingAsync(true)})

参考:https://github.com/dream-num/univer/issues/1314

使用 Facade API 创建 Workbook 后,立即调用其它 API 不生效的情况

部分 API 依赖于界面渲染完成后才能正常工作。如果在 Workbook 创建后立即调用相关 API,可能因尚未完成渲染而失效。建议在生命周期的 RenderedSteady 阶段再进行相关操作:

TypeScript
const disposable = univerAPI.addEvent(univerAPI.Event.LifeCycleChanged, ({ stage }) => {  if (stage === univerAPI.Enum.LifecycleStages.Steady) {    // 代码...  }})// 需要移除事件监听时,可调用 disposable.dispose()

参考:生命周期

你觉得这篇文档如何?

© 2026 DreamNum Co., Ltd.