@sparta-utils/excel-validate-helper v1.0.13
@sparta-utils/excel-validate-helper
Excel 读取、校验、错误标注和导出工具库,基于 exceljs。
目录
安装
你可以通过 npm 或 yarn 直接安装本库:
npm install @sparta-utils/excel-validate-helper
# 或
yarn add @sparta-utils/excel-validate-helper
使用示例
import {
ExcelReader,
ExcelValidator,
ExcelMarker,
ExcelExporter
} from '@sparta-utils/excel-validate-helper';
async function processExcel(file: File) {
// 1. 读取文件
const = await ExcelReader.read(file, 4);
const { headers, data } = await ExcelReader.read(file, {
dataStartRow: 4,
sheetIndex: 0,
onProgress: (progress) => {
console.log(`读取进度:${progress}%`)
},
mapHeaders: (header) => header.trim(),
filterEmptyRows: true, // 过滤空行
progressStep: 5, // 进度5%通知一次
})
console.log('表头:', headers);
console.log('数据:', data);
// 2. 校验数据
const result = ExcelValidator.validate(data, {
colHeaders: ['姓名', '身份证', '手机号', '年龄', '邮箱'],
fieldNames: ['name', 'idCard', 'phone', 'age', 'email'],
rules: {
0: { required: true },
1: { required: true, pattern: ExcelValidator.getPredefinedPattern('idCard') },
2: { pattern: ExcelValidator.getPredefinedPattern('phone') },
3: { type: 'number', min: 18, max: 65 },
4: { pattern: ExcelValidator.getPredefinedPattern('email') }
},
uniqueGroupCols: [1, 2], // 身份证 + 手机号联合唯一
onProgress: (current, total) => {
console.log(`校验进度: ${current}/${total}`)
}
})
if (result.err.length) {
console.warn('校验失败:', result.err);
// 3. 标注错误
// const errors: CellError[] = [
// { row: 2, col: 3, reason: '缺失必填项', level: 'error' },
// { row: 3, col: 2, reason: '数值超限', level: 'warning' },
// { row: 4, col: 5, reason: '格式建议', level: 'info' },
// { row: 6, col: 1, reason: '跨 Sheet 错误', sheetName: 'Sheet2' }
// ]
const errors: CellError[] = result.err
const options = {
outputType: 'both', //错误输出方式(默认 note)
allowMultiSheet: true, // 是否支持多sheet标记
errorColumnTitle: '数据校验信息', // 错误信息列标题
errorColumnIndex: 10 // 错误信息输入的列,不传则默认最后一列
}
const markedBlob = await ExcelMarker.markErrors(file, errors, options)
// 4. 导出带标注的Excel
ExcelExporter.export(markedBlob, {
fileName: '错误标注.xlsx',
format: 'xlsx',
onSuccess: () => {
console.log('✅ 文件导出成功')
},
onError: (err) => {
console.error('❌ 导出失败', err)
},
onProgress: (progress) => {
console.log(`进度:${progress}%`)
}
})
} else {
console.log('校验通过,数据:', result.succ);
// 继续业务逻辑处理 result.succ
}
}
包中方法介绍
- 本包导出了四个核心类:
1. ExcelReader
ExcelReader
是一个基于 ExcelJS 的前端 Excel 读取工具类,支持读取 .xlsx
文件,灵活配置数据起始行、工作表索引、进度回调、数据映射与空行过滤,方便你快速将 Excel 文件转换为结构化数据,适合用于表格导入、数据展示等场景。
- 快速使用示例
import { ExcelReader } from './ExcelReader'
const fileInput = document.getElementById('fileInput') as HTMLInputElement
fileInput.addEventListener('change', async () => {
const file = fileInput.files?.[0]
if (!file) return
try {
const result = await ExcelReader.read(file, {
dataStartRow: 4,
sheetIndex: 0,
onProgress: (progress) => {
console.log(`读取进度:${progress}%`)
},
mapHeaders: (header) => header.trim(),
mapRow: (row) => row.map(cell => (typeof cell === 'string' ? cell.trim() : cell)),
filterEmptyRows: true,
progressStep: 5,
})
console.log('读取完成:', result)
} catch (error) {
console.error('读取出错:', error)
}
})
参数说明
参数名 | 类型 | 说明 | 默认值 |
---|---|---|---|
dataStartRow | number | 数据开始行,Excel 中第几行开始读取数据,前一行为表头。例如4表示第4行开始读取数据(第3行为表头) | 4 |
sheetIndex | number | 读取第几个工作表,索引从0开始 | 0 |
onProgress | (progress: number) => void | 读取进度回调,参数为百分比,例如50表示完成一半 | 无 |
mapHeaders | (header: string) => string | 表头映射函数,用于对表头字符串进行自定义处理,如去除空格、大小写转换 | 无 |
mapRow | (row: any[]) => any[] | 行数据映射函数,用于对每行数据做转换处理,如去除单元格空格、类型转换等 | 无 |
filterEmptyRows | boolean | 是否过滤全为空的行,避免读取无效数据行 | true |
progressStep | number | 进度回调的最小步长,避免频繁触发回调 | 5 |
- 返回结果 函数返回一个 Promise,resolve 一个对象,结构如下:
interface ExcelReadResult {
headers: string[] // 读取的表头字段数组,顺序对应数据列
data: any[][] // 读取的数据二维数组,每一行为一条数据,首列是 Excel 行号
totalRows: number // 当前工作表总行数
sheetName: string // 当前读取的工作表名称
fileName: string // 上传的 Excel 文件名
}
- mapHeaders 使用示例及功能
mapHeaders 是一个函数,用于对 Excel 表头字符串进行处理。它接受一个字符串参数(当前表头文本),返回一个字符串(处理后的表头)。 常见用法包括: 去除表头两端空白字符 替换或重命名表头字段 转换为驼峰命名或小写 示例:
const mapHeaders = (header: string): string => {
// 去空格并转为小写驼峰
return header.trim().replace(/\s+(\w)/g, (_, c) => c.toUpperCase())
}
示例应用:
const result = await ExcelReader.read(file, {
mapHeaders,
})
console.log(result.headers)
- mapRow 使用示例及功能 mapRow 是一个函数,用于对读取的每行数据进行自定义处理。它接受一个数组参数(该行所有单元格数据,不含行号),返回一个处理后的数组。 常见用法包括: 去除每个单元格字符串的空白字符 类型转换,比如将数字字符串转换为数字 日期格式化 数据校验和修正 示例:
const mapRow = (row: any[]): any[] => {
return row.map(cell => {
if (typeof cell === 'string') {
return cell.trim()
}
if (typeof cell === 'number') {
return cell
}
// 你也可以增加对日期、布尔值等特殊处理
return cell
})
}
示例应用:
const result = await ExcelReader.read(file, {
mapRow,
})
console.log(result.data)
2. ExcelValidator
一个功能强大且灵活的 Excel 数据校验工具,支持常用验证规则、列唯一、组合列唯一、自定义规则等。易用且向下兼容,适合日常 Excel 数据导入校验场景。
功能特点:
- 支持必填项、数字范围、邮箱、手机号、身份证等常用规则校验
- 支持单列唯一校验
- 支持组合列唯一校验(多列拼接判断唯一)
- 支持自定义正则表达式规则
- 支持自定义函数校验
- 数字类型自动
trim
+ 转换成数字 - 验证错误定位准确,支持 Excel 行号(从1开始)、列号(从0开始)
- 进度回调支持大数据场景
API 参数说明
参数名 | 类型 | 说明 |
---|---|---|
colHeaders | string[] | Excel 列标题,用于错误提示 |
fieldNames | string[] | 字段映射,用于生成结果对象 |
rules | Record<number, ColumnRule> | 校验规则集合,key 是列索引 |
uniqueGroupCols | number[] | 组合唯一校验列索引数组,列值拼接做唯一性检查 |
startRowIndex | number | 起始行号(默认2),对应 Excel 实际行号 |
onProgress | (curr: number, total: number) => void | 校验进度回调 |
- 校验规则 ColumnRule 说明
| 属性 | 类型 | 说明 |
| ---------- | ----------------------------------------------------------------- | ---------------------------------------- |
|
required
|boolean
| 是否必填 | |type
|'string' \| 'number' \| 'boolean' \| 'date'
| 数据类型,number 会自动 trim 和转数字 | |pattern
|RegExp
| 自定义正则表达式校验 | |min
|number
| 数字类型最小值 | |max
|number
| 数字类型最大值 | |unique
|boolean
| 该列是否要求唯一(全表) | |custom
|(val: any, row: any[], rowIndex: number) => string \| undefined
| 自定义校验函数,返回错误信息表示校验失败,返回undefined
表示通过 |
- 内置常用正则模板
可以通过 ExcelValidator.getPredefinedPattern(name) 获取,支持:
| 名称 | 说明 |
| -------- | ----- |
|
idCard
| 身份证号码 | |phone
| 手机号码 | |tel
| 固话号码 | |email
| 邮箱地址 |
- 使用示例
const result = ExcelValidator.validate(data, {
colHeaders: ['姓名', '身份证', '手机号', '年龄', '邮箱'],
fieldNames: ['name', 'idCard', 'phone', 'age', 'email'],
rules: {
0: { required: true },
1: { required: true, pattern: ExcelValidator.getPredefinedPattern('idCard') },
2: { pattern: ExcelValidator.getPredefinedPattern('phone') },
3: { type: 'number', min: 18, max: 65 },
4: { pattern: ExcelValidator.getPredefinedPattern('email') }
},
uniqueGroupCols: [1, 2], // 身份证 + 手机号联合唯一
onProgress: (current, total) => {
console.log(`校验进度: ${current}/${total}`)
}
})
1. 基础规则配置示例
const rules = {
0: { required: true }, // 姓名必填
1: { required: true, pattern: ExcelValidator.getPredefinedPattern('idCard') }, // 身份证必填且格式正确
2: { pattern: ExcelValidator.getPredefinedPattern('phone') }, // 手机号格式校验
3: { type: 'number', min: 18, max: 60 }, // 年龄数字范围校验
4: { pattern: ExcelValidator.getPredefinedPattern('email') } // 邮箱格式校验
}
2. 单列唯一校验
const rules = {
1: { unique: true } // 身份证号列唯一
}
3. 组合列唯一校验
const uniqueGroupCols = [1, 2] // 身份证 + 手机号 联合唯一
4. 自定义正则表达式
const rules = {
5: { pattern: /^[A-Z]{3}\d{4}$/ } // 第6列必须是3个大写字母+4个数字
}
5. 自定义函数校验
const rules = {
3: {
custom: (val, row, rowIndex) => {
if (val < 0 || val > 100) return '数值必须在0到100之间'
if (row[0] === '特殊标记' && val < 50) return '特殊标记项最小值为50'
return undefined
}
}
}
返回结果结构
{
err: CellError[], // 错误列表,每条包括 Excel 行号、列号及错误原因
succ: any[] // 解析成功后的对象数组,字段名对应 fieldNames 配置
}
3. ExcelMarker
ExcelMarker 是一个基于 ExcelJS 的轻量级工具类,用于在 Excel 文件中标注错误单元格、批注或添加错误列信息,支持错误等级样式、跨 Sheet 标注、灵活输出方式等。
✨ 功能特性
✅ 支持单元格错误标注:添加批注、修改样式
- ✅ 支持错误等级样式(error/warning/info)
- ✅ 支持在额外列中记录每行错误信息
- ✅ 支持不同 Sheet 多处错误标注
- ✅ 支持自定义“错误列”插入位置
✅ 支持批注(note)、错误列(column)、或二者同时输出(both)
📚 API 使用说明 ExcelMarker.markErrors(file, errors, options?)
参数说明
| 参数 | 类型 | 必填 | 说明 |
| --------- | --------------- | -- | ------------------------ |
| file
| File
| ✅ | 待处理的 Excel 文件对象(.xlsx
) |
| errors
| CellError[]
| ✅ | 错误信息数组,包含具体行列、等级、原因等 |
| options
| MarkerOptions
| ❌ | 标注配置项,详见下方 |
CellError 类型定义
interface CellError {
row: number // 行号(从 1 开始)
col: number // 列号(从 1 开始)
reason?: string // 错误原因(默认显示 defaultNote)
level?: 'error' | 'warning' | 'info' // 错误等级(默认 error)
sheetName?: string // 错误所在 sheet 名(需开启 allowMultiSheet)
}
MarkerOptions 类型定义
interface MarkerOptions {
style?: CellStyle // 自定义样式覆盖默认错误样式
defaultNote?: string // 当错误无 reason 时的默认批注内容
outputType?: 'note' | 'column' | 'both' // 错误输出方式(默认 note)
sheetName?: string // 默认工作表名称(若未指定 error.sheetName)
errorColumnTitle?: string // 错误列标题(默认 "错误信息")
allowMultiSheet?: boolean // 是否允许跨 Sheet 标注(默认 false)
errorColumnIndex?: number // 错误列插入位置(默认追加在最后)
}
CellStyle(可选样式覆盖)
interface CellStyle {
font?: Partial<ExcelJS.Font>
alignment?: Partial<ExcelJS.Alignment>
fill?: Partial<ExcelJS.Fill>
border?: Partial<ExcelJS.Borders>
}
- 🧪 示例代码
import { ExcelMarker, CellError } from './ExcelMarker'
const file = fileInput.files[0] // 来自 <input type="file" />
const errors: CellError[] = [
{ row: 2, col: 3, reason: '缺失必填项', level: 'error' },
{ row: 3, col: 2, reason: '数值超限', level: 'warning' },
{ row: 4, col: 5, reason: '格式建议', level: 'info' },
{ row: 6, col: 1, reason: '跨 Sheet 错误', sheetName: 'Sheet2' }
]
const options = {
outputType: 'both',
allowMultiSheet: true,
errorColumnTitle: '数据校验信息',
errorColumnIndex: 10
}
ExcelMarker.markErrors(file, errors, options).then(blob => {
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = '标注后的数据.xlsx'
link.click()
URL.revokeObjectURL(url)
})
- 🎨 错误等级样式说明
| Level | 背景色 | 字体颜色 | 描述 |
| --------- | ------------- | --------- | ---- |
|
error
|#FFC7CE
(红) |#FF0000
| 严重错误 | |warning
|#FFEB9C
(黄) |#996600
| 警告提示 | |info
|#C6EFCE
(蓝绿) |#0000FF
| 信息提示 |
你可以通过 style 参数进一步自定义颜色、边框、对齐方式等样式细节。
- 🛠 依赖 ExcelJS
4. ExcelExporter
一个功能强大且灵活的 Excel 数据校验工具,支持常用验证规则、列唯一、组合列唯一、自定义规则等。易用且向下兼容,适合日常 Excel 数据导入校验场景。
功能特点
支持必填项、数字范围、邮箱、手机号、身份证等常用规则校验
- 支持单列唯一校验
- 支持组合列唯一校验(多列拼接判断唯一)
- 支持自定义正则表达式规则
- 支持自定义函数校验
- 数字类型自动
trim
+ 转换成数字 - 验证错误定位准确,支持 Excel 行号(从1开始)、列号(从0开始)
进度回调支持大数据场景
API 参数说明 | 参数名 | 类型 | 说明 | | ----------------- | --------------------------------------- | ----------------------- | |
colHeaders
|string[]
| Excel 列标题,用于错误提示 | |fieldNames
|string[]
| 字段映射,用于生成结果对象 | |rules
|Record<number, ColumnRule>
| 校验规则集合,key 是列索引 | |uniqueGroupCols
|number[]
| 组合唯一校验列索引数组,列值拼接做唯一性检查 | |startRowIndex
|number
| 起始行号(默认2),对应 Excel 实际行号 | |onProgress
|(curr: number, total: number) => void
| 校验进度回调 |校验规则 ColumnRule 说明 | 属性 | 类型 | 说明 | | ---------- | ----------------------------------------------------------------- | ---------------------------------------- | |
required
|boolean
| 是否必填 | |type
|'string' \| 'number' \| 'boolean' \| 'date'
| 数据类型,number 会自动 trim 和转数字 | |pattern
|RegExp
| 自定义正则表达式校验 | |min
|number
| 数字类型最小值 | |max
|number
| 数字类型最大值 | |unique
|boolean
| 该列是否要求唯一(全表) | |custom
|(val: any, row: any[], rowIndex: number) => string \| undefined
| 自定义校验函数,返回错误信息表示校验失败,返回undefined
表示通过 |
- 内置常用正则模板
可以通过 ExcelValidator.getPredefinedPattern(name) 获取,支持:
| 名称 | 说明 |
| -------- | ----- |
|
idCard
| 身份证号码 | |phone
| 手机号码 | |tel
| 固话号码 | |email
| 邮箱地址 |
- 使用示例
const result = ExcelValidator.validate(data, {
colHeaders: ['姓名', '身份证', '手机号', '年龄', '邮箱'],
fieldNames: ['name', 'idCard', 'phone', 'age', 'email'],
rules: {
0: { required: true },
1: { required: true, pattern: ExcelValidator.getPredefinedPattern('idCard') },
2: { pattern: ExcelValidator.getPredefinedPattern('phone') },
3: { type: 'number', min: 18, max: 65 },
4: { pattern: ExcelValidator.getPredefinedPattern('email') }
},
uniqueGroupCols: [1, 2], // 身份证 + 手机号联合唯一
onProgress: (current, total) => {
console.log(`校验进度: ${current}/${total}`)
}
})
1. 基础规则配置示例
const rules = {
0: { required: true }, // 姓名必填
1: { required: true, pattern: ExcelValidator.getPredefinedPattern('idCard') }, // 身份证必填且格式正确
2: { pattern: ExcelValidator.getPredefinedPattern('phone') }, // 手机号格式校验
3: { type: 'number', min: 18, max: 60 }, // 年龄数字范围校验
4: { pattern: ExcelValidator.getPredefinedPattern('email') } // 邮箱格式校验
}
2. 单列唯一校验
const rules = {
1: { unique: true } // 身份证号列唯一
}
3. 组合列唯一校验
const uniqueGroupCols = [1, 2] // 身份证 + 手机号 联合唯一
4. 自定义正则表达式
const rules = {
5: { pattern: /^[A-Z]{3}\d{4}$/ } // 第6列必须是3个大写字母+4个数字
}
5. 自定义函数校验
const rules = {
3: {
custom: (val, row, rowIndex) => {
if (val < 0 || val > 100) return '数值必须在0到100之间'
if (row[0] === '特殊标记' && val < 50) return '特殊标记项最小值为50'
return undefined
}
}
}
返回结果结构
{
err: CellError[], // 错误列表,每条包括 Excel 行号、列号及错误原因
succ: any[] // 解析成功后的对象数组,字段名对应 fieldNames 配置
}