# 数据验证

- Human documentation: [https://docs.univer.ai/zh-CN/guides/sheets/features/data-validation](https://docs.univer.ai/zh-CN/guides/sheets/features/data-validation)

- Agent Markdown: [https://docs.univer.ai/zh-CN/guides/sheets/features/data-validation.md](https://docs.univer.ai/zh-CN/guides/sheets/features/data-validation.md)

- Requested language: `zh-CN`

- Content language: `zh-CN`

- Documentation version: `1.0.0-rc.0`

- Source: [sheets/features/data-validation.zh-CN.mdx](https://github.com/dream-num/documentation/blob/dev/content/guides/sheets/features/data-validation.zh-CN.mdx)

---

#### Package metadata

```json
{
  "preset": [
    {
      "client": "@univerjs/preset-sheets-data-validation",
      "locale": "@univerjs/preset-sheets-data-validation/locales/zh-CN",
      "style": "@univerjs/preset-sheets-data-validation/lib/index.css"
    }
  ],
  "plugins": [
    {
      "client": "@univerjs/data-validation",
      "locale": "@univerjs/data-validation/locale/zh-CN"
    },
    {
      "client": "@univerjs/sheets-data-validation",
      "facade": "@univerjs/sheets-data-validation/facade",
      "locale": "@univerjs/sheets-data-validation/locale/zh-CN"
    },
    {
      "client": "@univerjs/sheets-data-validation-ui",
      "locale": "@univerjs/sheets-data-validation-ui/locale/zh-CN",
      "style": "@univerjs/sheets-data-validation-ui/lib/index.css"
    }
  ],
  "mobile": true,
  "server": false
}
```

数据验证是一种在单元格中设置规则的功能，以确保输入的数据符合特定要求。它可以帮助用户避免输入错误，提高数据的准确性和一致性。

目前支持以下数据验证类型：

* 数字
* 整数
* 文本长度
* 日期
* 复选框
* 下拉列表(单选/多选)
* 自定义公式

## 预设模式

### 安装

#### npm

```bash
npm install @univerjs/preset-sheets-data-validation
```

#### pnpm

```bash
pnpm add @univerjs/preset-sheets-data-validation
```

#### yarn

```bash
yarn add @univerjs/preset-sheets-data-validation
```

#### bun

```bash
bun add @univerjs/preset-sheets-data-validation
```

### 使用

```typescript
import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core'
import UniverPresetSheetsCoreZhCN from '@univerjs/preset-sheets-core/locales/zh-CN'
import { UniverSheetsDataValidationPreset } from '@univerjs/preset-sheets-data-validation' // [!code ++]
import UniverPresetSheetsDataValidationZhCN from '@univerjs/preset-sheets-data-validation/locales/zh-CN' // [!code ++]
import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets'

import '@univerjs/preset-sheets-core/lib/index.css'
import '@univerjs/preset-sheets-data-validation/lib/index.css' // [!code ++]

const { univerAPI } = createUniver({
  locale: LocaleType.ZH_CN,
  locales: {
    [LocaleType.ZH_CN]: mergeLocales(
      UniverPresetSheetsCoreZhCN,
      UniverPresetSheetsDataValidationZhCN, // [!code ++]
    ),
  },
  presets: [
    UniverSheetsCorePreset(),
    UniverSheetsDataValidationPreset(), // [!code ++]
  ],
})
```

### 预设与配置

```typescript
UniverSheetsDataValidationPreset({
  /**
   * 是否在下拉菜单中显示编辑按钮
   * @default true
   */
  showEditOnDropdown: true,
  /**
   * 是否在下拉菜单中显示搜索框
   * @default true
   */
  showSearchOnDropdown: true,
})
```

完整的配置项参考 [`IUniverSheetsDataValidationPresetConfig`](https://github.com/dream-num/univer/tree/dev/presets/packages/preset-sheets-data-validation)。

## 插件模式

### 安装

#### npm

```bash
npm install @univerjs/data-validation @univerjs/sheets-data-validation @univerjs/sheets-data-validation-ui
```

#### pnpm

```bash
pnpm add @univerjs/data-validation @univerjs/sheets-data-validation @univerjs/sheets-data-validation-ui
```

#### yarn

```bash
yarn add @univerjs/data-validation @univerjs/sheets-data-validation @univerjs/sheets-data-validation-ui
```

#### bun

```bash
bun add @univerjs/data-validation @univerjs/sheets-data-validation @univerjs/sheets-data-validation-ui
```

### 使用

```typescript
import { LocaleType, mergeLocales, Univer } from '@univerjs/core'
import { UniverDataValidationPlugin } from '@univerjs/data-validation' // [!code ++]
import { UniverSheetsDataValidationPlugin } from '@univerjs/sheets-data-validation' // [!code ++]
import { UniverSheetsDataValidationUIPlugin } from '@univerjs/sheets-data-validation-ui' // [!code ++]
import SheetsDataValidationZhCN from '@univerjs/sheets-data-validation-ui/locale/zh-CN' // [!code ++]

import '@univerjs/sheets-data-validation-ui/lib/index.css' // [!code ++]

import '@univerjs/sheets-data-validation/facade' // [!code ++]

const univer = new Univer({
  locale: LocaleType.ZH_CN,
  locales: {
    [LocaleType.ZH_CN]: mergeLocales(
      SheetsDataValidationZhCN, // [!code ++]
    ),
  },
})

univer.registerPlugin(UniverDataValidationPlugin) // [!code ++]
univer.registerPlugin(UniverSheetsDataValidationPlugin) // [!code ++]
univer.registerPlugin(UniverSheetsDataValidationUIPlugin) // [!code ++]
```

### 插件与配置

```typescript
univer.registerPlugin(UniverSheetsDataValidationUIPlugin, {
  /**
   * 是否在下拉菜单中显示编辑按钮
   * @default true
   */
  showEditOnDropdown: true,
  /**
   * 是否在下拉菜单中显示搜索框
   * @default true
   */
  showSearchOnDropdown: true,
})
```

完整的配置项参考 [`IUniverSheetsDataValidationUIConfig`](https://github.com/dream-num/univer/blob/dev/packages/sheets-data-validation-ui/src/config/config.ts)。

## Facade API

完整 Facade API 类型定义，请查看 [FacadeAPI](https://reference.univer.ai/zh-CN)

### 引入

> [!INFO: 插件模式提示]
> 仅插件模式需要手动引入 Facade 包。预设模式已内置对应的 Facade 包，无需额外导入。

```typescript
import '@univerjs/sheets-data-validation/facade'
```

### 添加一个数据验证规则

[`univerAPI.newDataValidation()`](https://docs.univer.ai/zh-CN/reference/facade/univer.md#newdatavalidation) 可以创建一个新的数据验证构建器，返回一个 `FDataValidationBuilder` 实例，可以通过链式调用生成数据验证规则。

以下是 [`FDataValidationBuilder`](https://docs.univer.ai/zh-CN/reference/facade/data-validation.md) 上的一些成员方法：

| 方法                                | 描述                                           |
| --------------------------------- | -------------------------------------------- |
| build                             | 构建数据验证规则                                     |
| requireCheckbox                   | 设置数据验证规则，要求输入为布尔值；该值将呈现为复选框                  |
| requireDateAfter                  | 将数据验证类型设置为 DATE，并配置验证规则为在特定日期之后              |
| requireDateBefore                 | 将数据验证类型设置为 DATE，并配置验证规则为在特定日期之前              |
| requireDateBetween                | 将数据验证类型设置为 DATE，并配置验证规则为在特定日期范围内             |
| requireDateEqualTo                | 将数据验证类型设置为 DATE，并配置验证规则为等于特定日期               |
| requireDateNotBetween             | 将数据验证类型设置为 DATE，并配置验证规则为不在特定日期范围内            |
| requireDateOnOrAfter              | 将数据验证类型设置为 DATE，并将验证规则配置为特定日期或之后             |
| requireDateOnOrBefore             | 将数据验证类型设置为 DATE，并将验证规则配置为特定日期或之前             |
| requireFormulaSatisfied           | 设置数据验证规则要求给定公式求值为 `true`                     |
| requireNumberBetween              | 设置数据验证规则要求数字在两个指定数字之间，或者是其中之一                |
| requireNumberEqualTo              | 设置数据验证规则要求数字等于给定值                            |
| requireNumberGreaterThan          | 设置数据验证规则要求数字大于给定值                            |
| requireNumberGreaterThanOrEqualTo | 设置数据验证规则要求数字大于或等于给定值                         |
| requireNumberLessThan             | 设置数据验证规则要求数字小于给定值                            |
| requireNumberLessThanOrEqualTo    | 设置数据验证规则要求数字小于或等于给定值                         |
| requireNumberNotBetween           | 设置数据验证规则要求数字不在两个指定数字之间，也不是其中之一               |
| requireNumberNotEqualTo           | 设置数据验证规则要求数字不等于给定值                           |
| requireValueInList                | 设置数据验证规则，要求用户从特定值列表中输入一个值。支持单选/多选，支持显示/隐藏下拉框 |
| requireValueInRange               | 设置数据验证规则，要求用户输入特定范围内的值。支持单选/多选，支持显示/隐藏下拉框    |
| setOptions                        | 设置数据验证规则的选项                                  |

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

// 创建一个新的数据验证规则，要求 A1:B10 范围内的数字在 1 到 10 之间
const fRange = fWorksheet.getRange('A1:B10')
const rule = univerAPI.newDataValidation()
  .requireNumberBetween(1, 10)
  .setOptions({
    allowBlank: true,
    showErrorMessage: true,
    error: 'Please enter a number between 1 and 10',
  })
  .build()
fRange.setDataValidation(rule)
```

### 清除 Range 的数据验证规则

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

// 清除 A1:B10 范围内的数据验证规则
const fRange = fWorksheet.getRange('A1:B10')
fRange.setDataValidation(null)
```

### 获取 Range/Worksheet 的数据验证规则

返回的数据验证规则对象是一个 `FDataValidation` 实例，可以通过该实例获取验证规则的条件、选项等。

以下是 [`FDataValidation`](https://docs.univer.ai/zh-CN/reference/facade/data-validation.md) 上的一些成员方法：

| 方法                | 描述                                       |
| ----------------- | ---------------------------------------- |
| copy              | 使用当前规则对象创建一个新的 FDataValidationBuilder 实例 |
| getCriteriaType   | 获取数据验证规则的类型                              |
| getCriteriaValues | 获取数据验证规则的条件值                             |
| getHelpText       | 获取帮助文本信息，用于为用户提供指导和支持                    |
| getRanges         | 获取数据验证规则的应用范围                            |
| setCriteria       | 设置数据验证规则的条件值                             |
| setOptions        | 设置数据验证规则的选项                              |
| setRanges         | 设置数据验证规则的应用范围                            |
| delete            | 从工作表中删除数据验证规则                            |

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

// 获取当前工作表的所有数据验证规则
const rulesOfSheet = fWorksheet.getDataValidations()

// 通过规则 ID 获取数据验证规则
const ruleById = fWorksheet.getDataValidation(rulesOfSheet[0]?.rule?.uid)

const fRange = fWorksheet.getRange('A1:B10')

// 获取当前范围的第一个数据验证规则
const ruleOfRange = fRange.getDataValidation()
ruleOfRange?.getCriteriaValues()

// 获取当前范围的所有数据验证规则
const rulesOfRange = fRange.getDataValidations()
```

### 更新/删除数据验证

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

// 创建一个新的数据验证规则，要求 A1:B10 范围内的数字等于 20
const fRange = fWorksheet.getRange('A1:B10')
const rule = univerAPI.newDataValidation()
  .requireNumberEqualTo(20)
  .build()
fRange.setDataValidation(rule)

const newRuleRange = fWorksheet.getRange('C1:D10')

// 3 秒后更新规则
setTimeout(() => {
  fRange.getDataValidation()
    // 更改新的范围 C1:D10
    .setRanges([newRuleRange])
    // 更改新的条件，要求数字在 1 到 10 之间
    .setCriteria(
      univerAPI.Enum.DataValidationType.DECIMAL,
      [univerAPI.Enum.DataValidationOperator.BETWEEN, '1', '10'],
    )
    // 更改验证选项，当输入不符合条件时停止输入并显示错误消息
    .setOptions({
      allowBlank: true,
      showErrorMessage: true,
      error: 'Please enter a valid value',
      errorStyle: univerAPI.Enum.DataValidationErrorStyle.STOP,
    })
}, 3000)

// 6 秒后删除该规则
setTimeout(() => {
  newRuleRange.getDataValidation().delete()
}, 6000)
```

### 获取验证错误

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

// 获取当前工作簿的所有数据验证错误
const workbookErrors = await fWorkbook.getAllDataValidationErrorAsync()
console.log('workbookErrors:', workbookErrors)

// 获取当前工作表的所有数据验证错误
const worksheetErrors = await fWorksheet.getAllDataValidationErrorAsync()
console.log('worksheetErrors:', worksheetErrors)

// 获取当前范围的数据验证错误
const fRange = fWorksheet.getRange('A1:B10')
const rangeErrors = await fRange.getDataValidationErrorAsync()
console.log('rangeErrors:', rangeErrors)
```

每个错误对象包含以下字段：

* `sheetName`：发生错误的工作表名称
* `row`：触发错误的单元格行索引
* `column`：触发错误的单元格列索引
* `ruleId`：触发错误的规则 ID
* `inputValue`：触发错误的输入值
* `rule`：规则内容快照

### 查询校验状态

校验状态是 `DataValidationStatus` 的枚举值，包括：

* `valid`：单元格值通过验证
* `invalid`：单元格值未通过验证
* `validating`：单元格正在验证中

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

// 获取当前工作簿的数据验证校验状态
fWorkbook.getValidatorStatus().then((status) => {
})

// 获取当前工作表的数据验证校验状态
fWorksheet.getValidatorStatusAsync().then((status) => {
})

// 获取当前范围的数据验证校验状态
const fRange = fWorksheet.getRange('A1:B10')
fRange.getValidatorStatus().then((status) => {
})
```

### 事件监听

完整事件类型定义，请查看 [Events](https://docs.univer.ai/zh-CN/reference/facade/events.md)。

数据验证模块提供了一系列事件用于监听验证规则的添加、更新、删除和验证状态变更。所有事件都可以通过 `univerAPI.addEvent()` 进行监听。

#### 验证规则变更事件

`univerAPI.Event.SheetDataValidationChanged`: 验证规则变更后触发

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.SheetDataValidationChanged, (params) => {
  const { origin, worksheet, workbook, changeType, oldRule, rule } = params
})

// 移除事件监听器，使用 `disposable.dispose()`
```

`univerAPI.Event.BeforeSheetDataValidationAdd`: 添加验证规则前触发

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeSheetDataValidationAdd, (params) => {
  const { worksheet, workbook, rule } = params

  // 取消添加验证规则操作
  params.cancel = true
})

// 移除事件监听器，使用 `disposable.dispose()`
```

`univerAPI.Event.BeforeSheetDataValidationDelete`: 删除验证规则前触发

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeSheetDataValidationDelete, (params) => {
  const { worksheet, workbook, ruleId, rule } = params

  // 取消删除验证规则操作
  params.cancel = true
})

// 移除事件监听器，使用 `disposable.dispose()`
```

`univerAPI.Event.BeforeSheetDataValidationDeleteAll`: 删除所有验证规则前触发

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeSheetDataValidationDeleteAll, (params) => {
  const { worksheet, workbook, rules } = params

  // 取消删除所有验证规则操作
  params.cancel = true
})

// 移除事件监听器，使用 `disposable.dispose()`
```

#### 验证规则更新事件

`univerAPI.Event.BeforeSheetDataValidationCriteriaUpdate`: 更新验证规则条件前触发

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeSheetDataValidationCriteriaUpdate, (params) => {
  const { worksheet, workbook, ruleId, rule, newCriteria } = params

  // 取消更新验证规则条件操作
  params.cancel = true
})

// 移除事件监听器，使用 `disposable.dispose()`
```

`univerAPI.Event.BeforeSheetDataValidationRangeUpdate`: 更新验证规则范围前触发

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeSheetDataValidationRangeUpdate, (params) => {
  const { worksheet, workbook, ruleId, rule, newRanges } = params

  // 取消更新验证规则范围操作
  params.cancel = true
})

// 移除事件监听器，使用 `disposable.dispose()`
```

`univerAPI.Event.BeforeSheetDataValidationOptionsUpdate`: 更新验证规则选项前触发

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeSheetDataValidationOptionsUpdate, (params) => {
  const { worksheet, workbook, ruleId, rule, newOptions } = params

  // 取消更新验证规则选项操作
  params.cancel = true
})

// 移除事件监听器，使用 `disposable.dispose()`
```

#### 验证状态事件

`univerAPI.Event.SheetDataValidatorStatusChanged`: 单元格验证状态变更时触发

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.SheetDataValidatorStatusChanged, (params) => {
  const { worksheet, workbook, row, column, status, rule } = params
})

// 移除事件监听器，使用 `disposable.dispose()`
```

每个事件都包含以下通用参数：

* `workbook`: 当前工作簿实例
* `worksheet`: 当前工作表实例

特殊参数：

* `rule`: 相关的验证规则对象
* `ruleId`: 验证规则的唯一标识符
* `status`: 验证状态（仅在 `SheetDataValidatorStatusChanged` 事件中）
* `newCriteria`: 新的验证条件（仅在 `BeforeSheetDataValidationCriteriaUpdate` 事件中）
* `newRanges`: 新的验证范围（仅在 `BeforeSheetDataValidationRangeUpdate` 事件中）
* `newOptions`: 新的验证选项（仅在 `BeforeSheetDataValidationOptionsUpdate` 事件中）

所有 `Before` 前缀的事件回调函数都可以使用 `params.cancel = true` 来阻止对应的操作。

### 错误样式

`errorStyle` 选项控制输入无效数据时的行为。它是 `DataValidationErrorStyle` 的枚举值，包括：

* `STOP`：阻止用户输入无效数据
* `WARNING`：允许用户输入无效数据，但显示警告
* `INFO`：允许用户输入无效数据，但显示信息提示

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

const rule = univerAPI.newDataValidation()
  .requireNumberBetween(1, 10)
  .setOptions({
    allowBlank: true,
    showErrorMessage: true,
    error: '请输入 1 到 10 之间的数字',
    errorStyle: univerAPI.Enum.DataValidationErrorStyle.STOP,
  })
  .build()
fRange.setDataValidation(rule)
```

### 变更列表型验证的渲染模式

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

fRange.getDataValidation()?.setOptions({
  // support TEXT, ARROW, CUSTOM
  // default is `CUSTOM`
  renderMode: univerAPI.Enum.DataValidationRenderMode.TEXT,
})
```
