前言
kk-utils 是一款我自己基于这几年开发封装出来的前端工具库
excel-js
excel-js
是kk-utils
里的工具之一(1.2.0版本开始支持)
,其作用是有多个针对导出导出的方法函数,是我在写项目时积累下来的,几乎可以覆盖日常所需
这个工具是基于GitHub
上开源的exceljs的代码,基于此工具库的基础上进行二次封装适合我业务的功能
使用方法
安装
js
npm install kk-utils-library -S
pnpm add kk-utils-library -S
可用方法
importExcel
导入Excel
js
importExcel(File, [options])
- File:要导入的Excel文件
- options:配置项,可选,对象类型
- allWorksheets:
boolean
,是否导入所有工作表,无论true
还是false
,返回的结果都是二维数组,默认为false
- getValue:
(cell) => string
,获取单元格的文本值,默认为(cell) => cell.text
- headerStartLine:
number
,表头开始行数,默认1
开始 - headerTotalLine:
number
,表头总行数,默认1
- toJsonArray:
boolean
,是否转换成JSON格式,默认true
- false:则返回的数据是
[[key, key, key], [value, value, value], [value,value,value]]
这种格式 - true:则返回的数据是
[{key, value}, {key, value}, {key, value}]
这种格式
- false:则返回的数据是
- allWorksheets:
html
<input type="file" id="file" accept=".xlsx" />
<button id="import">导入所选文件</button>
这是我要导入的Excel文件,第一行就是表头,总共一行表头,所以使用默认的headerStartLine和headerTotalLine就可以了,如果是多行表头或者开始不是第一行则自行调整或者传入对应参数

js
import { importExcel } from 'kk-utils-library/excel-js';
const fileInput = document.getElementById('file');
const importButton = document.getElementById('import');
importButton.addEventListener('click', () => {
const file = fileInput.files[0];
if (!file) {
alert('请选择文件');
return;
}
importExcel(file, {
headerStartLine: 1,
headerTotalLine: 1
}).then((data) => {
console.log('data', data);
// [
// [
// {
// 操作类型: '新增',
// 客户名称: '测试1',
// 客户编码: 'TEST001',
// 客户类型: '供应商',
// 省: '辽宁省',
// 市: '沈阳市',
// 区: '辽中县'
// },
// {
// 操作类型: '修改',
// 客户名称: '测试2',
// 客户编码: 'TEST002',
// 客户类型: '客户',
// 省: '山西省',
// 市: '太原市',
// 区: '晋源区'
// },
// {
// 操作类型: '删除',
// 客户名称: '测试3',
// 客户编码: 'TEST003',
// 客户类型: '客户与供应商',
// 省: '吉林省',
// 市: '长春市',
// 区: '宽城区'
// },
// {
// 操作类型: '不变',
// 客户名称: '测试4',
// 客户编码: 'TEST004',
// 客户类型: '供应商',
// 省: '湖南省',
// 市: '长沙市',
// 区: '雨花区'
// }
// ]
// ];
});
});
exportExcel
导出Excel
js
exportExcel([options])
- filename:导出的文件名,默认为
excel
- sheets:
object[]
,要导出的工作表- sheetName:
string
,表名,默认为SheetJS[index + 1]
- withDefaultStyle:
boolean
,携带默认样式,默认true
,全局默认样式可通过setGlobalDefaultStyle()
配置 - adaptiveWidth:
boolean
,自适应列宽,默认true
- adaptiveWidthOptions:
object
,自适应列宽配置项- minWidth:
number
,最小列宽,默认5
- maxWidth:
number
,最大列宽,默认50
- interstice:
number
,列宽额外空隙,默认5
- ignoreLines:
number[]
,计算列宽忽略的行,因为有些行会有合并单元格的操作,这样会导致合并行的列度最大并使用合并行的列宽作为整列的宽,所以可以传入合并行的行数来进行列宽计算忽略
- minWidth:
- processing:
(worksheet) => void
,对工作表对象做操作处理,这个是在自动列宽和默认样式之前
执行的 - extraProcessing:
(worksheet) => void
,对工作表对象做操作额外处理,这个是在自动列宽和默认样式之后
执行的
- sheetName:
- processing:
(workbook) => void
,对Excel对象做操作处理
html
<button id="export">导出测试文件</button>
js
import { exportExcel } from 'kk-utils-library/excel-js';
const exportButton = document.getElementById('export');
exportButton.addEventListener('click', () => {
const data = [
['姓名', '年龄', '性别'],
['张三', 18, '男'],
['李四', 19, '女'],
['王五', 20, '男']
];
exportExcel({
filename: 'test',
sheets: [
{
processing: (worksheet) => {
worksheet.addRows(data);
},
extraProcessing: (worksheet) => {
_merge(worksheet.getRow(1), {
fill: {
type: 'pattern',
pattern: 'solid',
fgColor: {
argb: 'FF99CCFF'
}
}
});
_merge(worksheet.getRow(2).getCell(2), {
fill: {
type: 'pattern',
pattern: 'solid',
fgColor: {
argb: 'FFFF4949'
}
}
});
}
}
]
});
});
然后就可以看到下载了一份名为test.xlsx的文件,打开就是我们要的数据和效果了
coordinatesFromRange
从一个区间范围获取所有的坐标矩阵
js
coordinatesFromRange(range)
- range:
[number, number, number, number]
坐标点,四个参数分别代表开始行
开始列
结束行
结束列
js
import { coordinatesFromRange } from 'kk-utils-library/excel-js';
const coordinatesResult = coordinatesFromRange([2, 3, 3, 4]);
console.log('coordinatesResult', coordinatesResult);
// [
// [2, 3],
// [2, 4],
// [3, 3],
// [3, 4]
// ];
isCoordinateInCoordinates
判断一个坐标点是否在坐标矩阵内
js
isCoordinateInCoordinates(coordinate, coordinates)
- coordinate:
[number, number]
坐标点 - coordinates:坐标矩阵
js
import { isCoordinateInCoordinates } from 'kk-utils-library/excel-js';
const isCoordinateInCoordinatesResult = isCoordinateInCoordinates(
[2, 3],
coordinatesResult
);
const isCoordinateInCoordinatesResult2 = isCoordinateInCoordinates(
[12, 13],
coordinatesResult
);
console.log('isCoordinateInCoordinatesResult', isCoordinateInCoordinatesResult);
// true
console.log('isCoordinateInCoordinatesResult2', isCoordinateInCoordinatesResult2);
// false
isCoordinateInRange
判断一个坐标点是否在坐标范围内
js
isCoordinateInRange(coordinate, range)
- coordinate:
[number, number]
坐标点 - range:
[number, number, number, number]
坐标点,四个参数分别代表开始行
开始列
结束行
结束列
js
import { isCoordinateInRange } from 'kk-utils-library/excel-js';
const isCoordinateInRangeResult = isCoordinateInRange(
[2, 3],
[2, 3, 5, 8]
);
const isCoordinateInRangeResult2 = isCoordinateInRange(
[12, 13],
[2, 3, 5, 8]
);
console.log('isCoordinateInRangeResult', isCoordinateInRangeResult);
// true
console.log('isCoordinateInRangeResult2', isCoordinateInRangeResult2);
// false
getHorizontalMerges
获取横向合并数据,此数据是专门给exceljs
用的
js
getHorizontalMerges(excelData)
- excelData:二维数组
js
import {
getHorizontalMerges,
freeMerge as fm, // 代表自由合并 上下都合并,必须是正方形/长方形 起点为fm左上角单元格
horizontalMerge as hm, // 代表横向合并 起点为hm前一个单元格
verticalMerge as vm // 代表纵向合并 起点为vm上一个单元格
} from 'kk-utils-library/excel-js';
const horizontalMergeAndVerticalMergeTestData = [
[11, 12, hm, hm, 15, 16, 17, 18, 19],
[21, 22, 23, 24, 25, fm, fm, 28, 29],
[31, 32, vm, 34, 35, fm, fm, 38, 39],
[41, 42, vm, 44, vm, 46, hm, hm, hm],
[51, 52, 53, 54, vm, 56, 57, 58, 59],
[61, 62, vm, 64, vm, 66, 67, 68, 69],
[71, 72, vm, 74, 75, 76, 77, 78, 79],
[81, 82, vm, 84, 85, 86, 87, 88, 89],
[91, 92, 93, 94, 95, 96, 97, 98, 99]
];
const horizontalMergesResult = getHorizontalMerges(
horizontalMergeAndVerticalMergeTestData
);
console.log('horizontalMergesResult', horizontalMergesResult);
// [
// [1, 2, 1, 4],
// [4, 6, 4, 9]
// ];
getVerticalMerges
获取纵向合并数据,此数据是专门给exceljs
用的
js
getVerticalMerges(excelData)
- excelData:二维数组
js
import {
getVerticalMerges,
freeMerge as fm, // 代表自由合并 上下都合并,必须是正方形/长方形 起点为fm左上角单元格
horizontalMerge as hm, // 代表横向合并 起点为hm前一个单元格
verticalMerge as vm // 代表纵向合并 起点为vm上一个单元格
} from 'kk-utils-library/excel-js';
const horizontalMergeAndVerticalMergeTestData = [
[11, 12, hm, hm, 15, 16, 17, 18, 19],
[21, 22, 23, 24, 25, fm, fm, 28, 29],
[31, 32, vm, 34, 35, fm, fm, 38, 39],
[41, 42, vm, 44, vm, 46, hm, hm, hm],
[51, 52, 53, 54, vm, 56, 57, 58, 59],
[61, 62, vm, 64, vm, 66, 67, 68, 69],
[71, 72, vm, 74, 75, 76, 77, 78, 79],
[81, 82, vm, 84, 85, 86, 87, 88, 89],
[91, 92, 93, 94, 95, 96, 97, 98, 99]
];
const verticalMergesResult = getVerticalMerges(
horizontalMergeAndVerticalMergeTestData
);
console.log('verticalMergesResult', verticalMergesResult);
// [
// [2, 3, 4, 3],
// [3, 5, 6, 5],
// [5, 3, 8, 3]
// ];
getMatrixMerges
获取纵向和横向的合并数据,此数据是专门给exceljs
用的
js
getMatrixMerges(excelData)
- excelData:二维数组
js
import {
getMatrixMerges,
freeMerge as fm, // 代表自由合并 上下都合并,必须是正方形/长方形 起点为fm左上角单元格
horizontalMerge as hm, // 代表横向合并 起点为hm前一个单元格
verticalMerge as vm // 代表纵向合并 起点为vm上一个单元格
} from 'kk-utils-library/excel-js';
const freeMergeTestData = [
[11, 21, fm, fm, fm, 61, fm, fm, 91],
[21, 22, fm, fm, fm, 26, 27, 28, 29],
[31, 32, fm, fm, fm, 36, fm, fm, 39],
[41, 42, 43, 44, 45, 46, fm, fm, 49],
[51, 52, fm, fm, 55, 56, fm, fm, 59],
[fm, 62, fm, fm, 65, 66, 67, 68, 69],
[fm, 72, fm, fm, 75, 76, 77, 78, 79],
[81, 82, fm, fm, 85, 86, 87, 88, 89],
[91, 92, 93, 94, 95, 96, 97, 98, 99]
];
const matrixMergesResult = getMatrixMerges(freeMergeTestData);
console.log('matrixMergesResult', matrixMergesResult);
// [
// [1, 2, 3, 5],
// [1, 6, 1, 8],
// [2, 6, 5, 8],
// [4, 2, 8, 4],
// [5, 1, 7, 1]
// ];
getMerges
获取合并数据,此数据是专门给exceljs
用的 此方法涵盖了前面三种getMerge
方法,会自动识别数据里的hm
, vm
, fm
js
getMerges(excelData)
- excelData:二维数组
js
import {
getMerges,
freeMerge as fm, // 代表自由合并 上下都合并,必须是正方形/长方形 起点为fm左上角单元格
horizontalMerge as hm, // 代表横向合并 起点为hm前一个单元格
verticalMerge as vm // 代表纵向合并 起点为vm上一个单元格
} from 'kk-utils-library/excel-js';
const horizontalMergeAndVerticalMergeTestData = [
[11, 12, hm, hm, 15, 16, 17, 18, 19],
[21, 22, 23, 24, 25, fm, fm, 28, 29],
[31, 32, vm, 34, 35, fm, fm, 38, 39],
[41, 42, vm, 44, vm, 46, hm, hm, hm],
[51, 52, 53, 54, vm, 56, 57, 58, 59],
[61, 62, vm, 64, vm, 66, 67, 68, 69],
[71, 72, vm, 74, 75, 76, 77, 78, 79],
[81, 82, vm, 84, 85, 86, 87, 88, 89],
[91, 92, 93, 94, 95, 96, 97, 98, 99]
];
const mergesResult = getMerges(horizontalMergeAndVerticalMergeTestData);
console.log('mergesResult', mergesResult);
// [
// [1, 2, 1, 4],
// [4, 6, 4, 9],
// [2, 3, 4, 3],
// [3, 5, 6, 5],
// [5, 3, 8, 3],
// [1, 5, 3, 7]
// ];
getDefaultStyle
获取全局默认样式
js
getDefaultStyle()
js
import { getDefaultStyle } from 'kk-utils-library/excel-js';
const beforeStyle = getDefaultStyle();
console.log('beforeStyle', beforeStyle);
// {
// font: {
// size: 14
// },
// alignment: {
// vertical: 'top',
// wrapText: true
// },
// border: {
// top: {
// style: 'thin'
// },
// left: {
// style: 'thin'
// },
// bottom: {
// style: 'thin'
// },
// right: {
// style: 'thin'
// }
// },
// fill: {
// type: 'pattern',
// pattern: 'solid',
// fgColor: {
// argb: 'FF99CCFF'
// }
// }
// }
getDefaultStyle
获取全局默认样式
js
getDefaultStyle()
js
import { setGlobalDefaultStyle } from 'kk-utils-library/excel-js';
const afterStyle = setGlobalDefaultStyle({
font: {
size: 14
},
fill: {
type: 'pattern',
pattern: 'solid',
fgColor: {
argb: 'FF99CCFF'
}
}
});
const afterStyle = getDefaultStyle();
console.log('afterStyle', afterStyle);
// {
// font: {
// size: 14
// },
// alignment: {
// vertical: 'top',
// wrapText: true
// },
// border: {
// top: {
// style: 'thin'
// },
// left: {
// style: 'thin'
// },
// bottom: {
// style: 'thin'
// },
// right: {
// style: 'thin'
// }
// },
// fill: {
// type: 'pattern',
// pattern: 'solid',
// fgColor: {
// argb: 'FF99CCFF'
// }
// }
// }
setAdaptiveWidth
设置Excel的单元格自适应宽度,如果你自己使用exceljs则需要自己使用setAdaptiveWidth
去处理,kk-utils
里的导出默认是true
了,可以自己传入调整参数,ExcelJs
的参数需自己看文档
js
setAdaptiveWidth(Worksheet, [options])
js
import { setAdaptiveWidth } from 'kk-utils-library/excel-js';
import ExcelJS from 'exceljs';
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('SheetJS');
worksheet.addRows([
['姓名', '简称', '年龄', '性别'],
['小明', '无', 18, '男'],
['古力那扎尔·拜合提亚尔', '古力娜扎', 16, '女'],
[
'巴勃罗·迭戈·荷瑟·山迪亚哥·弗朗西斯科·德·保拉·居安·尼波莫切诺·克瑞斯皮尼亚诺·德·罗斯·瑞米迪欧斯·西波瑞亚诺·德·拉·山迪西玛·特立尼达·玛利亚·帕里西奥·克里托·瑞兹·布拉斯科·毕加索',
'毕加索',
92,
'男'
]
]);
console.log('before worksheet widths', _map(worksheet.columns, 'width'));
// [null, null, null, null];
setAdaptiveWidth(worksheet, {
minWidth: 15,
maxWidth: 50
});
console.log('after worksheet widths', _map(worksheet.columns, 'width'));
// [50, 17, 15, 15];
getDataHeader
获取最后渲染数据用的表头,因为表头我们可能需要合并,所以塞数据的时候原始表头不适用,需要使用列一一对应的表头才能更方便加入表体数据
js
getDataHeader(excelData)
- excelData:二维数组
js
import { getDataHeader } from 'kk-utils-library/excel-js';
const dataHeader = getDataHeader([
['编码', '时间', '已批准', '已核销', '未核销', hm, '已支付', '待支付'],
[vm, vm, vm, vm, '申请中', '未申请', vm, vm]
]);
console.log('dataHeader', dataHeader);
// [
// '编码',
// '时间',
// '已批准',
// '已核销',
// '申请中',
// '未申请',
// '已支付',
// '待支付'
// ];
getColumnLetterByNumber
根据列下标1开始
获取对应的Excel字母列
js
getColumnLetterByNumber(number)
js
import { getColumnLetterByNumber } from 'kk-utils-library/excel-js';
const letter = getColumnLetterByNumber(5);
console.log('letter', letter);
// E
getDepthAndLength
获取树结构的深度和最长子级长度
js
getDepthAndLength(tree, [options])
tree
:树形数组options
:配置项,可选,对象类型,支持基础配置项itemKey
:指定节点key
名,默认值为id
childrenKey
:自定义子节点key
名,默认值为children
js
import { getDepthAndLength } from 'kk-utils-library/excel-js';
const getDepthAndLengthTree = [
{
key: 1,
children: [
{
{
key: 12,
children: [
{
key: 122,
children: [
{
key: 1221
},
{
key: 1222,
children: [
{
key: 12221
},
{
key: 12222
},
{
key: 12223
},
{
key: 12224
},
{
key: 12225
},
{
key: 12226
}
]
}
]
}
]
}
]
}
];
const getDepthAndLengthResult = getDepthAndLength(getDepthAndLengthTree);
console.log('getDepthAndLengthResult', getDepthAndLengthResult);
// { depth: 5, length: 6 }
getFillHorizontalMergeKeyMap
获取表头横向合并列所对应的合并长度
js
getFillHorizontalMergeKeyMap(Tree, [options])
tree
:树形数组options
:配置项,可选,对象类型,支持基础配置项itemKey
:指定节点key
名,默认值为id
childrenKey
:自定义子节点key
名,默认值为children
js
import { getFillHorizontalMergeKeyMap } from 'kk-utils-library/excel-js';
const treeHeader = [
{
prop: 'index',
label: '序号'
},
{
prop: 'budgetCycleItemName',
label: '预算周期项名称'
},
{
prop: 'expectedShipmentAmount',
label: '预发货金额',
children: [
{
prop: 'originalExpectedShipmentAmount',
label: '调整前金额'
},
{
prop: 'adjustedExpectedShipmentAmount',
label: '调整的金额'
},
{
prop: 'finalExpectedShipmentAmount',
label: '调整后金额'
}
]
},
{
prop: 'budgetAmount',
label: '预算金额',
children: [
{
prop: 'originalBudgetAmount',
label: '调整前金额'
},
{
prop: 'adjustedBudgetAmount',
label: '调整的金额'
},
{
prop: 'finalBudgetAmount',
label: '调整后金额'
}
]
}
];
const getFillHorizontalMergeKeyMapResult =
getFillHorizontalMergeKeyMap(treeHeader);
console.log(
'getFillHorizontalMergeKeyMapResult',
getFillHorizontalMergeKeyMapResult
);
// {
// index: 0,
// budgetCycleItemName: 0,
// expectedShipmentAmount: 2,
// originalExpectedShipmentAmount: 0,
// adjustedExpectedShipmentAmount: 0,
// finalExpectedShipmentAmount: 0,
// budgetAmount: 2,
// originalBudgetAmount: 0,
// adjustedBudgetAmount: 0,
// finalBudgetAmount: 0
// }
tableHeaderToMultidimensionalArray
把树结构表头处理成Excel的表头
js
tableHeaderToMultidimensionalArray(Tree, [options])
tree
:树形数组options
:配置项,可选,对象类型,支持基础配置项itemKey
:指定节点key
名,默认值为id
childrenKey
:自定义子节点key
名,默认值为children
labelKey
: 自定义节点文本key
名,默认值为label
js
import { tableHeaderToMultidimensionalArray } from 'kk-utils-library/excel-js';
const treeHeader = [
{
prop: 'index',
label: '序号'
},
{
prop: 'budgetCycleItemName',
label: '预算周期项名称'
},
{
prop: 'expectedShipmentAmount',
label: '预发货金额',
children: [
{
prop: 'originalExpectedShipmentAmount',
label: '调整前金额'
},
{
prop: 'adjustedExpectedShipmentAmount',
label: '调整的金额'
},
{
prop: 'finalExpectedShipmentAmount',
label: '调整后金额'
}
]
},
{
prop: 'budgetAmount',
label: '预算金额',
children: [
{
prop: 'originalBudgetAmount',
label: '调整前金额'
},
{
prop: 'adjustedBudgetAmount',
label: '调整的金额'
},
{
prop: 'finalBudgetAmount',
label: '调整后金额'
}
]
}
];
const multidimensionalArray = tableHeaderToMultidimensionalArray(treeHeader);
console.log('multidimensionalArray', multidimensionalArray);
// [
// [
// '序号',
// '预算周期项名称',
// '预发货金额',
// '-hm',
// '-hm',
// '预算金额',
// '-hm',
// '-hm'
// ],
// [
// '-vm',
// '-vm',
// '调整前金额',
// '调整的金额',
// '调整后金额',
// '调整前金额',
// '调整的金额',
// '调整后金额'
// ]
// ];
conversionToJsonArray
把Excel数据转成数组对象格式
js
conversionToJsonArray(ExcelData, [options])
- excelData:二维数组
- options:配置项,可选,对象类型
- headerStartLine:
number
,表头开始行数,默认1
开始 - headerTotalLine:
number
,表头总行数,默认1
- headerStartLine:
js
import { conversionToJsonArray } from 'kk-utils-library/excel-js';
const arrayData = [
['操作类型', '客户名称', '客户编码', '省', '市', '区'],
[
'不变',
'苏州秦曼商贸有限公司',
'11605028',
'苏北省(作废)',
'苏州市',
'吴中区'
],
[
'不变',
'测试-嘉士柏河南省郑州------麻三定/麻坤丽',
'JSB12001003',
'河南省',
'郑州市',
'中原区'
]
];
const conversionToJsonArrayResult = conversionToJsonArray(arrayData);
console.log('conversionToJsonArrayResult', conversionToJsonArrayResult);
// [
// {
// 操作类型: '不变',
// 客户名称: '苏州秦曼商贸有限公司',
// 客户编码: '11605028',
// 省: '苏北省(作废)',
// 市: '苏州市',
// 区: '吴中区'
// },
// {
// 操作类型: '不变',
// 客户名称: '测试-嘉士柏河南省郑州------麻三定/麻坤丽',
// 客户编码: 'JSB12001003',
// 省: '河南省',
// 市: '郑州市',
// 区: '中原区'
// }
// ];