js-xlsx
- 由
SheetJS
出品的js-xlsx
是一款非常方便的只需要纯 JS 即可读取和导出 excel 的工具库,功能强大,支持格式众多,支持 xls、xlsx 等十几种格式
工作类
1. 从数组(数组项为数组)创建工作表
const worksheet = XLSX.utils.aoa_to_sheet(excleData);
XLSX.utils.aoa_to_sheet
:接收js数组并返回数据对应的工作表- 将一个二维数组转成 sheet,会自动处理 number、string、boolean、date 等类型数据
将数组中的数据添加到现有工作表
XLSX.utils.sheet_add_aoa(worksheet, excleData);
XLSX.utils.sheet_add_aoa
:接收js数组并更新现有工作表
2. 从对象数组创建工作表
const worksheet = XLSX.utils.json_to_sheet(newList);
XLSX.utils.json_to_sheet
:接收js对象数组并返回数据对应的工作表
将对象数组中的数据添加到现有工作表
XLSX.utils.sheet_add_json(worksheet, excleData);
XLSX.utils.sheet_add_json
:接收js对象数组并更新现有工作表
3. 创建新工作簿
const workbook = XLSX.utils.book_new();
若不带参数 book_new
函数将创建一个空工作簿
单一工作表
const workbook = XLSX.utils.book_new(worksheet);
const workbook = XLSX.utils.book_new(worksheet, 'Blatte');
- 参数1:工作表对象,它将被添加到新工作簿中
- 参数2:工作表的名称,默认
Sheet1
4. 将工作表附加到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
5. 工作表对象属性
-
worksheet['!cols']
:列对象数组- 每个列对象对属性进行编码,包括级别、宽度和可见性
-
worksheet['!rows']
:行对象数组- 每个行对象对属性进行编码,包括级别、高度和可见性
-
worksheets['!merges']
:与工作表中合并的单元格相对应的范围对象数组-
纯文本格式不支持合并单元格
-
CSV 导出将写入合并范围中的所有单元格(如果存在),因此请确保仅设置范围中的第一个单元格(左上角)
-
快速上手
1. 操作 dom 导出
domExportExcel(id, fileName) {
// 1. 获取表格的 dom 对象 'data-table'
let elt = document.getElementById(id);
// 2. 创建工作簿
let wb = XLSX.utils.table_to_book(elt, {
sheet: 'Sheet1'
});
// 3. 导出
return XLSX.writeFile(wb, fileName)
},
2. 二维数组导出
exportExcel(excleData, excleDataTitle, fileName) {
excleData.unshift(excleDataTitle);
// 1. 生成工作表:aoa_to_sheet 把数组转换为工作表
const worksheet = XLSX.utils.aoa_to_sheet(excleData);
// 2. book_new 新建一个工作簿
const workbook = XLSX.utils.book_new();
// 3. book_append_sheet 将工作表添加到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 4. writeFile 输出工作表
XLSX.writeFile(workbook, fileName);
},
const excleDataTitle = ['周一', '周二', '周三', '周四', '周五'];
const excleDataArr = [
['语文', '数学', '历史', '政治', '英语'],
['数学', '数学', '政治', '英语', '英语'],
['政治', '英语', '历史', '政治', '数学']
];
exportExcel(excleDataArr, excleDataTitle, '课程表.xlsx');
3. 对象数组导出
exportExcel(excleDataObj, excleDataTitle, fileName) {
// 替换 表头 -> { '周一': '语文', ... }
const excleData = [];
excleDataObj.map(item => {
let o = {};
Object.entries(item).map(([key, value]) => {
o[excleDataTitle[key]] = value;
})
excleData.push(o)
})
// 1. 生成工作表:json_to_sheet 把json转换为工作表
const worksheet = XLSX.utils.json_to_sheet(excleData);
// // 设置表格样式,!cols为列宽
// const options = {
// '!cols': [
// { wpx: 100 },
// { wpx: 100 },
// { wpx: 100 },
// { wpx: 100 },
// { wpx: 100 },
// ]
// };
// // 设置每列的列宽,10代表10个字符,注意中文占2个字符
// worksheet['!cols'] = options['!cols'];
// // 合并单元格
// worksheet['!merges'] = [{ e: { c: 2, r: 2 }, s: { c: 1, r: 1 } }];
// 2. book_new 新建一个工作簿
const workbook = XLSX.utils.book_new();
// 3. book_append_sheet 将工作表添加到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 4. writeFile 输出工作表
XLSX.writeFile(workbook, fileName);
},
const excleDataTitle = {
'Monday': '周一',
'Tuesday': '周二',
'Wednesday': '周三',
'Thursday': '周四',
'Friday': '周五'
};
const excleDataObj = [
{ Monday: '语文', Tuesday: '数学', Wednesday: '历史', Thursday: '政治', Friday: '英语' },
{ Monday: '数学', Tuesday: '数学', Wednesday: '政治', Thursday: '英语', Friday: '英语' },
{ Monday: '政治', Tuesday: '英语', Wednesday: '历史', Thursday: '政治', Friday: '数学' }
];
exportExcel(excleDataObj, excleDataTitle, '课程表.xlsx');
应用
由前端生成并下载表格文件
/**
* @typedef {object} ExportConfig
* @prop {array[]|object[]} data 目标数据
* @prop {'matrix'|'dictArray'} dataType 数据的数据格式
* - dictArray:成员是对象的数组
* - matrix:二维数组
* @prop {{[key: string]: string} | string[]} headers 表头
*/
import cloneDeep from "lodash/cloneDeep";
import * as XLSX from "xlsx";
/**
* 由前端生成并下载表格文件
* @param {ExportConfig} setting
*/
function exportLocalSheet(setting) {
const { dataType } = setting;
switch (dataType) {
case "matrix":
exportSheetOfMatrix(setting);
break;
default:
exportSheetOfDictArray(setting);
break;
}
}
/**
* 下载【对象数组】的表格
* @param {ExportConfig} setting
*/
function exportSheetOfDictArray(setting) {
const { data, headers, fileName } = setting;
// 替换 表头
const tableData = data.map((row) => {
const newRow = {};
Object.entries(row).map(([key, value]) => {
newRow[headers[key]] = value;
});
return newRow;
});
// 1. 生成工作表:json_to_sheet 把json转换为工作表
const worksheet = XLSX.utils.json_to_sheet(tableData);
// 2. book_new 新建一个工作簿
const workbook = XLSX.utils.book_new();
// 3. book_append_sheet 将工作表添加到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
// 4. writeFile 输出工作表
XLSX.writeFile(workbook, fileName);
}
/**
* 下载【二维数组】的表格
* @param {ExportConfig} setting
* @param {string[]} setting.headers
*/
function exportSheetOfMatrix(setting) {
const { data, headers, fileName } = setting;
const tableData = cloneDeep(data);
tableData.unshift(headers);
// 1. 生成工作表:aoa_to_sheet 把数组转换为工作表
const worksheet = XLSX.utils.aoa_to_sheet(tableData);
// 2. book_new 新建一个工作簿
const workbook = XLSX.utils.book_new();
// 3. book_append_sheet 将工作表添加到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
// 4. writeFile 输出工作表
XLSX.writeFile(workbook, fileName);
}
export { exportLocalSheet, exportSheetOfDictArray, exportSheetOfMatrix };
组件实现
<template>
<div
v-if="isDownloadOpen"
class="ow-download"
:class="[`ow-download-${type}`, { 'ow-old-school': oldSchool }]">
<!-- 简易模式 -->
<div
v-if="type === 'simple'"
class="icon-btn"
:title="btnTips"
@click="onDownloadClick">
<Icon type="md-download" size="16"></Icon>
</div>
<!-- 完整模式 -->
<div v-else-if="type === 'complete'" class="row align-items-center">
<Button
type="success"
v-bind="btnProps"
:title="btnTips"
@click="onDownloadClick">
<slot>
<Icon type="md-download" size="14"></Icon>
下载明细
</slot>
</Button>
<Dropdown
trigger="click"
v-if="hasExportTypes"
@on-click="onExportTypeChange">
<Button
class="more-btn"
title="选择下载格式"
type="success"
v-bind="btnProps">
<Icon type="md-arrow-dropdown"></Icon>
</Button>
<DropdownMenu slot="list">
<DropdownItem
v-for="item in exportTypeSelection.options"
:key="item.value"
:name="item.label"
:selected="item.label === innerExportType"
>{{ item.label }}</DropdownItem
>
</DropdownMenu>
</Dropdown>
</div>
</div>
</template>
<script>
import { exportLocalSheet } from "./download";
/* 下载文件的格式 */
const EXPORT_FILE_TYPES = {
xls: 1,
csv: 2,
txt: 3,
1: "xlsx",
2: "csv",
3: "txt",
};
export default {
name: "LocalDownloadBtn",
props: {
/** 下载的数据 */
data: Array,
/** 下载的表头 */
headers: Array,
/** 下载的文件名 */
fileName: String,
/** 组件的类型 [simple, complete] */
type: {
type: String,
default: "simple",
},
/** 显示下载格式选项 */
hasExportTypes: {
type: Boolean,
default: true,
},
/** 传入的下载格式值 */
exportType: {
type: String,
default: "csv",
},
/** type=complete 时的按钮属性 */
btnProps: Object,
/* 旧的样式 */
oldSchool: Boolean,
},
data() {
return {
exportTypeSelection: {
visible: false,
options: [
{ label: "xlsx", value: EXPORT_FILE_TYPES.xlsx },
{ label: "csv", value: EXPORT_FILE_TYPES.csv },
// { label: 'txt', value: EXPORT_FILE_TYPES.txt }
],
},
innerExportType: this.exportType,
};
},
watch: {
exportType(val) {
this.innerExportType = val;
},
},
computed: {
isDownloadOpen() {
return this.$store.state.gameConfig.isDownloadOpen;
},
btnTips() {
return `点击下载,当前格式:${this.innerExportType}`;
},
},
methods: {
// 点击下载
onDownloadClick() {
const parmas = {};
const downloadSetting = {
IS_STOP_DOWNLOAD: false, // 中止下载,这里之前的组件放置的地方不一样,应该统一
exportType: this.innerExportType,
};
this.$emit("beforeStart", parmas, downloadSetting);
if (!downloadSetting.IS_STOP_DOWNLOAD) {
exportLocalSheet({
headers: this.headers,
data: this.data,
fileName: `${this.fileName}.${this.innerExportType}`,
...parmas,
});
}
},
onExportTypeChange(val) {
this.innerExportType = val;
// 通知父组件更新 exportType 的值
this.$emit("update:exportType", val);
this.$emit("onExportTypeChange", val);
},
},
};
</script>
标签:XLSX,sheet,17,worksheet,前端,导出,book,const,utils
From: https://www.cnblogs.com/pleaseAnswer/p/18241780