在 Vue.js 项目中使用 xlsx-js-style
来将 HTML 表格转换为 Excel 并下载,可以通过以下步骤实现:
步骤
-
安装
xlsx-js-style
库:
使用 npm 安装xlsx-js-style
库。npm install xlsx-js-style
-
创建 Vue 组件:
创建一个 Vue 组件,在其中实现表格到 Excel 的转换和下载。
示例代码
<template>
<div>
<table id="myTable">
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data 1</td>
<td>Data 2</td>
<td>Data 3</td>
</tr>
<tr>
<td>Data 4</td>
<td>Data 5</td>
<td>Data 6</td>
</tr>
</tbody>
</table>
<button @click="downloadExcel">Download as Excel</button>
</div>
</template>
<script>
import * as XLSX from 'xlsx-js-style';
export default {
name: 'TableToExcel',
methods: {
downloadExcel() {
// 获取表格元素
const table = document.getElementById('myTable');
// 将表格转换为工作簿
const wb = XLSX.utils.table_to_book(table, { sheet: 'Sheet JS' });
// 获取工作表
const ws = wb.Sheets['Sheet JS'];
const range = XLSX.utils.decode_range(ws['!ref']);
// 遍历单元格并添加样式
for (let R = range.s.r; R <= range.e.r; ++R) {
for (let C = range.s.c; C <= range.e.c; ++C) {
const cell_address = { c: C, r: R };
const cell_ref = XLSX.utils.encode_cell(cell_address);
if (!ws[cell_ref]) continue;
// 样式示例
ws[cell_ref].s = {
fill: { fgColor: { rgb: 'FFFFAA00' } },
font: { name: 'Arial', sz: 14, bold: true, color: { rgb: 'FF000000' } },
alignment: { horizontal: 'center', vertical: 'center' },
};
}
}
// 导出 Excel 文件
XLSX.writeFile(wb, 'table.xlsx');
},
},
};
</script>
<style>
/* 你的样式 */
</style>
详细说明:
-
安装依赖:
- 使用
npm install xlsx-js-style
安装xlsx-js-style
库。
- 使用
-
组件模板:
- 定义一个表格和一个按钮,按钮绑定
downloadExcel
方法。
- 定义一个表格和一个按钮,按钮绑定
-
脚本部分:
- 导入
xlsx-js-style
库。 - 定义
downloadExcel
方法。- 获取表格元素。
- 使用
XLSX.utils.table_to_book
方法将表格转换为工作簿。 - 获取工作表并遍历单元格,应用样式。
- 使用
XLSX.writeFile
方法将工作簿导出为 Excel 文件。
- 导入
-
样式部分:
- 你可以根据需要添加自定义样式。
扩展功能:
- 根据需要,可以扩展
downloadExcel
方法以支持更多样式和功能。 - 可以动态生成表格内容,并使用 Vue 的数据绑定来管理表格数据。
这个示例展示了如何在 Vue 中使用 xlsx-js-style
将 HTML 表格转换为带样式的 Excel 文件并下载。如果你需要进一步的自定义或优化,可以根据需求进行调整。
添加多个工作表sheet
在 Vue.js 中使用 xlsx-js-style
添加多张工作表,并将 HTML 表格转换为 Excel 文件下载,可以按照以下步骤进行。以下是一个示例,演示如何将多个 HTML 表格分别添加到不同的工作表中,并下载包含这些工作表的 Excel 文件。
步骤
-
安装
xlsx-js-style
库:
使用 npm 安装xlsx-js-style
库。npm install xlsx-js-style
-
创建 Vue 组件:
创建一个 Vue 组件,在其中实现将多个表格添加到不同工作表并下载的功能。
示例代码
<template>
<div>
<table id="table1">
<thead>
<tr>
<th>Table 1 Header 1</th>
<th>Table 1 Header 2</th>
<th>Table 1 Header 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data 1</td>
<td>Data 2</td>
<td>Data 3</td>
</tr>
<tr>
<td>Data 4</td>
<td>Data 5</td>
<td>Data 6</td>
</tr>
</tbody>
</table>
<table id="table2">
<thead>
<tr>
<th>Table 2 Header 1</th>
<th>Table 2 Header 2</th>
<th>Table 2 Header 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data A</td>
<td>Data B</td>
<td>Data C</td>
</tr>
<tr>
<td>Data D</td>
<td>Data E</td>
<td>Data F</td>
</tr>
</tbody>
</table>
<button @click="downloadExcel">Download as Excel</button>
</div>
</template>
<script>
import * as XLSX from 'xlsx-js-style';
export default {
name: 'TableToExcel',
methods: {
downloadExcel() {
// 创建一个新的工作簿
const wb = XLSX.utils.book_new();
// 将第一个表格转换为工作表并添加到工作簿
const table1 = document.getElementById('table1');
const ws1 = XLSX.utils.table_to_sheet(table1);
this.applyStyles(ws1);
XLSX.utils.book_append_sheet(wb, ws1, 'Sheet1');
// 将第二个表格转换为工作表并添加到工作簿
const table2 = document.getElementById('table2');
const ws2 = XLSX.utils.table_to_sheet(table2);
this.applyStyles(ws2);
XLSX.utils.book_append_sheet(wb, ws2, 'Sheet2');
// 导出 Excel 文件
XLSX.writeFile(wb, 'tables.xlsx');
},
applyStyles(ws) {
const range = XLSX.utils.decode_range(ws['!ref']);
for (let R = range.s.r; R <= range.e.r; ++R) {
for (let C = range.s.c; C <= range.e.c; ++C) {
const cell_address = { c: C, r: R };
const cell_ref = XLSX.utils.encode_cell(cell_address);
if (!ws[cell_ref]) continue;
// 样式示例
ws[cell_ref].s = {
fill: { fgColor: { rgb: 'FFFFAA00' } },
font: { name: 'Arial', sz: 14, bold: true, color: { rgb: 'FF000000' } },
alignment: { horizontal: 'center', vertical: 'center' },
};
}
}
}
}
};
</script>
<style>
/* 你的样式 */
</style>
详细说明:
-
安装依赖:
- 使用
npm install xlsx-js-style
安装xlsx-js-style
库。
- 使用
-
组件模板:
- 定义两个表格和一个按钮,按钮绑定
downloadExcel
方法。
- 定义两个表格和一个按钮,按钮绑定
-
脚本部分:
- 导入
xlsx-js-style
库。 - 定义
downloadExcel
方法:- 创建一个新的工作簿
wb
。 - 获取第一个表格元素,并将其转换为工作表
ws1
,应用样式后添加到工作簿中。 - 获取第二个表格元素,并将其转换为工作表
ws2
,应用样式后添加到工作簿中。 - 使用
XLSX.writeFile
方法将工作簿导出为 Excel 文件。
- 创建一个新的工作簿
- 定义
applyStyles
方法:- 遍历工作表的单元格,并为每个单元格应用样式。
- 导入
-
样式部分:
- 根据需要添加自定义样式。
扩展功能:
- 根据需要,可以扩展
downloadExcel
方法以支持更多的表格和工作表。 - 可以动态生成表格内容,并使用 Vue 的数据绑定来管理表格数据。
通过这个示例代码,你可以将多个 HTML 表格分别添加到不同的工作表中,并下载包含这些工作表的 Excel 文件。如果需要进一步自定义或优化,可以根据需求进行调整。
使用案例代码
封装常用的表格导出方法
import { isArray } from 'lodash-es';
import XLSX from 'xlsx-js-style';
// columns:表头数据 data:表格数据 excelName:导出的文件名 autoWidth: 自适应列宽 sheetTitle:sheet名称,excel打开以后,的底部切换名称 wrapText:是否自动换行
export interface exportExcelTypes {
columns: any[]
data: any[]
excelName?: string
autoWidth?: boolean
sheetTitle?: string
wrapText?: ''
}
// 导出表头默认样式
const THeaderStyle = {
// font 字体属性
font: {
bold: true,
sz: 12
},
// alignment 对齐方式
alignment: {
vertical: 'center', // 垂直居中
horizontal: 'center', // 水平居中
},
// fill 颜色填充属性
fill: {
fgColor: { rgb: 'e1e2e3' },
},
// border style
border: {
top: { style: 'thin', color: { rgb: '909399' } },
right: { style: 'thin', color: { rgb: '909399' } },
bottom: { style: 'thin', color: { rgb: '909399' } },
left: { style: 'thin', color: { rgb: '909399' } }
}
}
const TBodyStyle = {
alignment: {// 文字居中 //字体水平居中、垂直居中、自动换行
font: {// 字体设置
sz: 12,
bold: false,
},
horizontal: 'left', //居中
vertical: 'center', //垂直居中
wrapText: true
},
// numFmt:'@'
}
/**
* 自适应列宽
* @param {*} data
* @returns {*} {*}
*/
const autoWidthFn = (data: any): any => {
// 设置worksheet每列的最大宽度
const colWidth = data.map((row: any) => row.map((val: { toString: () => { (): any; new(): any; charCodeAt: { (arg0: number): number; new(): any; }; length: number; }; } | null) => {
// 先判断是否为null/undefined
if (val == null) {
return {
'width': 10
}
}
// 再判断是否为中文
else if (val.toString().charCodeAt(0) > 255) {
return {
'width': val.toString().length * 2 + 6
}
} else {
return {
'width': val.toString().length + 2 + 1
}
}
}))
// 以第一行为初始值
const result = colWidth[0]
for (let i = 1; i < colWidth.length; i++) {
for (let j = 0; j < colWidth[i].length; j++) {
if (result[j]['width'] < colWidth[i][j]['width']) {
result[j]['width'] = colWidth[i][j]['width'] > 480 ? 480 : colWidth[i][j]['width']
}
}
}
return result
}
/**
* 是否自动换行
* @param {*} sheet
* @returns {*} {*}
*/
const wrapTextFn = (sheet: any): any => {
for (const key in sheet) {
if (key.indexOf('!') === -1) { // 排除带!的字段,只要单元格字段
if (!sheet[key].s && sheet[key].z != 'm/d/yy') {
sheet[key].t = 's'
sheet[key].s = TBodyStyle
}
}
}
return sheet
}
/**
* json数据导出excel
* @param {exportExcelTypes} params
*/
export const exportExcel = (params: exportExcelTypes) => {
const { columns, data, excelName, autoWidth = true, sheetTitle = 'sheet名称', wrapText = false } = params
if (!isArray(columns) || !isArray(data)) {
return
}
const THeader: any = [], filterVal: any = [];
columns.forEach((item: { label: any; prop: any; }) => {
THeader.push({
v: item.label,
t: 's',
s: THeaderStyle
})
filterVal.push(item.prop)
})
const TData = data.map(v => filterVal.map((j: string | number) => v[j]))
const sheetData = [[...THeader], ...TData]
const sheet = XLSX.utils.aoa_to_sheet(sheetData);// aoa_to_sheet 将二维数组转成 sheet
// 自适应列宽
if (autoWidth) { sheet['!cols'] = autoWidthFn(sheetData) }
// 自动换行
if (wrapText) { wrapTextFn(sheet) }
// 设置表头行高
const rows = [{ hpx: 20 }]
sheet['!rows'] = rows; // 将rows添加到sheet中,设置行高
// 创建虚拟的 workbook
const workbook = XLSX.utils.book_new();
// 向 workbook 中添加 sheet
XLSX.utils.book_append_sheet(workbook, sheet, sheetTitle);
// 导出 workbook
XLSX.writeFile(workbook, ${excelName ? (excelName.includes('.xlsx') ? excelName : excelName + '.xlsx') : 'excel名称.xlsx'});
}
/**
* json数据导出excel 导出多个
* @param {{ params: exportExcelTypes[], excelName: string }} dataParams
* @returns
*/
export const exportMultipleExcel = (dataParams: { params: exportExcelTypes[], excelName: string }) => {
const { params, excelName } = dataParams
if (!isArray(params)) {
return
}
// 创建虚拟的 workbook
const workbook = XLSX.utils.book_new();
params.forEach((item: any) => {
const { columns, data, autoWidth = true, sheetTitle = 'sheet名称', wrapText = false } = item
if (!isArray(columns) || !isArray(data)) {
return
}
const THeader: any = [], filterVal: any = [];
columns.forEach((item: { label: any; prop: any; }) => {
THeader.push({
v: item.label,
t: 's',
s: THeaderStyle
})
filterVal.push(item.prop)
})
const TData = data.map(v => filterVal.map((j: string | number) => v[j]))
const sheetData = [[...THeader], ...TData]
const sheet = XLSX.utils.aoa_to_sheet(sheetData);// aoa_to_sheet 将二维数组转成 sheet
// 自适应列宽
if (autoWidth) { sheet['!cols'] = autoWidthFn(sheetData) }
// 自动换行
if (wrapText) { wrapTextFn(sheet) }
// 设置表头行高
const rows = [{ hpx: 20 }]
sheet['!rows'] = rows; // 将rows添加到sheet中,设置行高
// 向 workbook 中添加 sheet
XLSX.utils.book_append_sheet(workbook, sheet, sheetTitle);
})
// 导出 workbook
XLSX.writeFile(workbook, ${excelName ? (excelName.includes('.xlsx') ? excelName : excelName + '.xlsx') : 'excel名称.xlsx'});
}
/**
* 使用插件内的方法,自动使用dom转换为数据
* 通过将一个table dom直接转成sheet,会自动识别colspan和rowspan并将其转成对应的单元格合并
* @param {{ id: string, excelName: string, autoWidth: boolean, sheetTitle: string, wrapText: boolean}} dataParams
* @returns
*/
export const exportDomExcel = (dataParams: { id: string, excelName: string, autoWidth: boolean, sheetTitle: string, wrapText?: boolean }) => {
const { id, excelName, autoWidth = true, sheetTitle = 'sheet名称', wrapText = false } = dataParams
const table = document.querySelector(id);
// Generate the sheet data and add styles:
const sheet = XLSX.utils.table_to_sheet(table); //将一个table对象转换成一个sheet对象
const headerRange = XLSX.utils.decode_range(sheet['!ref']);
// 把table sheet对象转换成二进制数据
const jsonData = XLSX.utils.sheet_to_json(sheet, { header: 1 });
const arrayData: any = [];
jsonData.forEach((row: any) => {
const rowData: any = [];
Object.values(row).forEach((cell) => {
rowData.push(cell);
});
arrayData.push(rowData);
});
// 设置表头样式
for (let col = headerRange.s.c; col <= headerRange.e.c; col++) {
const cellInfo = XLSX.utils.encode_cell({ r: 0, c: col });
const cell = sheet[cellInfo];
cell.s = THeaderStyle;
}
// 自适应列宽
if (autoWidth) {
sheet['!cols'] = autoWidthFn(arrayData)
}
// 自动换行
if (wrapText) { wrapTextFn(sheet) }
// 设置表头行高
const rows = [{ hpx: 20 }]
sheet['!rows'] = rows; // 将rows添加到sheet中,设置行高
// 创建虚拟的 workbook
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, sheet, sheetTitle);
XLSX.writeFile(workbook, ${excelName ? (excelName.includes('.xlsx') ? excelName : excelName + '.xlsx') : 'excel名称.xlsx'});
return
}
/**
* 手动把table内的值,获取到组装成所需要的数组 如果不需要过滤下载的表格列,用第一个更好,这个主要是为了过滤列,报告里需要过滤掉需要跟操作两列
* 通过将一个table dom直接转成sheet,会自动识别colspan和rowspan并将其转成对应的单元格合并
* @param {{ id: string, excelName: string, autoWidth: boolean, sheetTitle: string, wrapText: boolean,filterTHeaderTextArr:string[]}} dataParams
* @returns
*/
export const exportDomExcelFilter = (dataParams: { id: string, excelName: string, autoWidth: boolean, sheetTitle: string, wrapText?: boolean, filterTHeaderTextArr?: string[] }) => {
const { id, excelName, autoWidth = true, sheetTitle = 'sheet名称', wrapText = false, filterTHeaderTextArr = [] } = dataParams
const table: any = document.querySelector(id);
// Generate the sheet data and add styles:
const rows = Array.from(table.getElementsByTagName('tr'));
const tableData = rows.map((row: any) => Array.from(row.getElementsByTagName('td')).map((cell: any) => cell.textContent.trim())).filter(item => item.length > 0);
const THeader = rows.map((row: any) => Array.from(row.getElementsByTagName('th')).map((cell: any) => cell.textContent.trim())).filter(item => item.length > 0);
if (THeader.length) {
THeader.forEach((item: any) => {
item.forEach((it: any, ind: number) => {
if (filterTHeaderTextArr.includes(it)) {
item.splice(ind, 1)
tableData.forEach(datas => {
datas.splice(ind, 1)
})
}
})
})
}
const sheetData = [...THeader, ...tableData]
const sheet = XLSX.utils.aoa_to_sheet(sheetData);// aoa_to_sheet 将二维数组转成 sheet
const headerRange = XLSX.utils.decode_range(sheet['!ref']);
// 设置表头样式
for (let col = headerRange.s.c; col <= headerRange.e.c; col++) {
const cellInfo = XLSX.utils.encode_cell({ r: 0, c: col });
const cell = sheet[cellInfo];
cell.s = THeaderStyle;
}
// 自适应列宽
if (autoWidth) { sheet['!cols'] = autoWidthFn(sheetData) }
// 自动换行
if (wrapText) { wrapTextFn(sheet) }
// 设置表头行高
const rowstyle = [{ hpx: 20 }]
sheet['!rows'] = rowstyle; // 将rows添加到sheet中,设置行高
// 创建虚拟的 workbook
const workbook = XLSX.utils.book_new();
// 向 workbook 中添加 sheet
XLSX.utils.book_append_sheet(workbook, sheet, sheetTitle);
// 导出 workbook
XLSX.writeFile(workbook, ${excelName ? (excelName.includes('.xlsx') ? excelName : excelName + '.xlsx') : 'excel名称.xlsx'});
}
更多参考文章
前端工程师、程序员
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通