在纯前端导出文件的一种常见方法是通过生成下载链接来实现,可以使用Blob对象和URL.createObjectURL()方法来实现,因为现在工作中主要运用的前端框架是angular,这篇文章将以angular为例进行阐述。
一、示例代码
1. 首先,安装FileSaver库(https://github.***/eligrey/FileSaver.js/)来方便地处理文件下载:
javascript">npm install file-saver --save
npm install xlsx --save
npm install xlsx-js-style --save
2. 在你的Angular组件中,导入必要的模块和依赖项:
import { ***ponent } from '@angular/core';
import { saveAs } from 'file-saver';
import * as XLSX from 'xlsx';
import * as XLSXStyle from 'xlsx-js-style';
3. 创建一个函数来生成和导出文件:
exportFile() {
// 创建需要导出的数据
const data = '这是要导出的纯前端内容。';
// 将数据保存为Blob对象
const blob = new Blob([data], { type: 'text/plain;charset=utf-8' });
// 使用FileSaver库保存Blob对象为文件
saveAs(blob, '导出文件.txt');
}
4. 在组件的模板中添加一个按钮或其他交互元素,并将函数绑定到点击事件上:
<button (click)="exportFile()">导出文件</button>
按照上述方法,当用户点击按钮时,将会触发exportFile()函数,生成并下载一个名为"导出文件.txt"的文件,其中包含指定的纯前端内容。
二、导出数组数据并带有表格样式的文件的完整代码
import { ***ponent } from '@angular/core';
import * as XLSX from 'xlsx';
import * as XLSXStyle from 'xlsx-js-style';
import { saveAs } from 'file-saver';
@***ponent({
selector: 'app-root',
template: `
<button (click)="exportexcel()">导出Excel</button>
`
})
export class App***ponent {
exportExcel() {
// 创建一个工作簿
const workbook = XLSX.utils.book_new();
// 创建一个工作表
const worksheet = XLSX.utils.json_to_sheet(
[{ Column1: 'Value1', Column2: 'Value2', Column3: 'Value3' },]
);
// 设置每列的宽度
const columns = [
{ wch: 15 },
{ wch: 15 },
{ wch: 15 },
];
worksheet['!cols'] = columns;
// 设置边框样式
const range = XLSX.utils.decode_range(worksheet['!ref']);
for (let R = range.s.r; R <= range.e.r; ++R) {
for (let C = range.s.c; C <= range.e.c; ++C) {
const cellAddress = { c: C, r: R };
const cellRef = XLSX.utils.encode_cell(cellAddress);
const cell = worksheet[cellRef];
if (cell) {
cell.s = {
border: {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' },
},
};
}
}
}
// 将工作表添加到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 生成Excel文件
const excelBuffer = XLSXStyle.write(workbook, { bookType: 'xlsx', type: 'array' });
const excelBlob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats- officedocument.spreadsheetml.sheet' });
saveAs(excelBlob, 'filename.xlsx');
}
}
其中exportExcel方法还可以按照以下写来设置到处表格的样式:
特别注意:有数据的才会样式才会生效。比如,设置了表格的边框,但是某栏没有数据,那么边框这个样式就不会生效。解决这个问题的方法是:在处理数据的时候,在数据后面多加一个选择 “ || ' ' ”,这样xlsx默认该栏是有数据的,只是该数据是空字符串!
exportData(data: any[]) {
// 创建一个工作簿对象
const workbook = XLSX.utils.book_new();
// 将数据转换为工作表对象
const worksheet = XLSX.utils.json_to_sheet(data);
// 设置单元格样式
const cellStyle = {
alignment: {
wrapText: true // 设置内容可以换行
},
border: {
top: { style: 'thin' },
bottom: { style: 'thin' },
left: { style: 'thin' },
right: { style: 'thin' }
}
};
// 遍历工作表中的每个单元格,应用样式
Object.keys(worksheet).forEach((cell) => {
if (cell !== '!ref') {
worksheet[cell].s = cellStyle;
}
});
// 将工作表添加到工作簿中
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 生成Excel文件
const excelBuffer = XLSXStyle.write(workbook, { bookType: 'xlsx', type: 'array' });
const excelBlob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats- officedocument.spreadsheetml.sheet' });
saveAs(excelBlob, 'filename.xlsx');
}
注意:导出数组数据处理方法总共有两个,json_to_sheet , ao_sheet。下面说一下两个方法的区别:
json_to_sheet 和 aoa_to_sheet 方法是 xlsx 库中用于创建工作表的两种不同方式。
json_to_sheet 方法接受一个 JSON 数组作为参数,将其转换为适用于工作表的数据格式。每个对象数组的元素都会成为工作表中的一行,对象的键将成为工作表的列标题。这个方法适用于将 JSON 数据直接转换为工作表。
aoa_to_sheet 方法接受一个二维数组(Array of Arrays,简称 AoA)作为参数,将其转换为适用于工作表的数据格式。数组中的每个元素都会成为工作表中的一行,数组的元素将成为工作表的单元格的值。这个方法适用于将已经存在的二维数组转换为工作表。
以下是两种方法的示例使用:
const XLSX = require('xlsx');
const jsonData = [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
{ id: 3, name: '王五' }
];
const aoaData = [
['id', 'name'],//导出文件的表头
[1, '张三'],
[2, '李四'],
[3, '王五']
];
const worksheet1 = XLSX.utils.json_to_sheet(jsonData);
const worksheet2 = XLSX.utils.aoa_to_sheet(aoaData);
在这个示例中,jsonData 是一个包含对象的 JSON 数组,aoaData 是一个二维数组。我们分别使用 json_to_sheet 和 aoa_to_sheet 方法将它们转换为工作表。
需要注意的是,aoa_to_sheet 方法在转换时不会自动为每一行添加列标题,因此需要在传递给方法的二维数组中包含列标题。而 json_to_sheet 方法会根据对象的键自动添加列标题。
三、扩展(导出对象、数组等结构数据并分为多个sheet的方法)
1.导出对象,按照id分为多个sheet
const XlsxStyle = require('xlsx-js-style');
const data = {
1: [
{ id: 1, name: '张三' },
{ id: 1, name: '王五' }
],
2: [
{ id: 2, name: '李四' },
{ id: 2, name: '钱七' }
],
3: [
{ id: 3, name: '赵六' }
]
};
const fileName = 'output.xlsx';
function exportDataToXlsx(data, fileName) {
const workbook = XlsxStyle.utils.book_new();
for (const key in data) {
if (data.hasOwnProperty(key)) {
const dataArray = data[key];
const worksheet = XlsxStyle.utils.json_to_sheet(dataArray);
XlsxStyle.utils.book_append_sheet(workbook, worksheet, key);
}
}
XlsxStyle.writeFile(workbook, fileName);
}
2.导出数组数据,并分为多个多个sheet
import * as XLSX from 'xlsx';
const data = [
[
['姓名', '年龄', '性别'],
['张三', 20, '男'],
['李四', 25, '女']
],
[
['城市', '人口'],
['北京', 21540000],
['上海', 24240000]
]
];
const sheetNames = ['Sheet1', 'Sheet2'];
const fileName = 'output.xlsx';
function exportToXlsx(data: any[][][], sheetNames: string[], fileName: string) {
const workbook = XLSX.utils.book_new();
for (let i = 0; i < data.length; i++) {
const worksheet = XLSX.utils.aoa_to_sheet(data[i]);
XLSX.utils.book_append_sheet(workbook, worksheet, sheetNames[i]);
}
XLSX.writeFile(workbook, fileName);
}
exportToXlsx(data, sheetNames, fileName);
上面的对象、数组是模拟了文件数组,至始至终都没有读取和处理文件数据的情况
3.导出读取到的文件数据,并分为多个sheet
const XLSX = require('xlsx');
function readDataFromXlsx(filePath) {
const workbook = XLSX.readFile(filePath);
const sheetNames = workbook.SheetNames;
const data = {};
sheetNames.forEach(sheetName => {
const worksheet = workbook.Sheets[sheetName];
const dataArray = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
data[sheetName] = dataArray;
});
return data;
}
function exportDataToXlsx(data, fileName) {
const workbook = XLSX.utils.book_new();
for (const key in data) {
if (data.hasOwnProperty(key)) {
const dataArray = data[key];
const worksheet = XLSX.utils.json_to_sheet(dataArray);
XLSX.utils.book_append_sheet(workbook, worksheet, key);
}
}
XLSX.writeFile(workbook, fileName);
}
const filePath = 'data.xlsx';
const data = readDataFromXlsx(filePath);
const fileName = 'output.xlsx';
exportDataToXlsx(data, fileName);
四、一些知识点(插件之间的区别)
1. xlsx.writeFile()
和saveAs()
实际上,xlsx.writeFile()也可以导出文件,但为什么我们前端常用
saveAs()来导出文件呢?
xlsx.writeFile()是XLSX库提供的方法,用于将工作簿对象写入文件。它接受两个参数:工作簿对象和文件路径。这个方法将在服务器端生成文件并将其保存在指定路径上。
saveAs()是FileSaver库提供的方法,用于将Blob对象保存为文件。它接受两个参数:Blob对象和文件名。这个方法将在客户端下载文件,而不需要将文件保存在服务器上。
两个方法的选择取决于你的需求和使用场景:
如果你想在服务器上生成文件并将其保存在特定路径上,那么使用`xlsx.writeFile()`是一个不错的选择。
如果你想在客户端下载文件,而不需要将文件保存在服务器上,那么使用`saveAs()`是一个更好的选择。
2. xlsx-style
和xlsx-js-style
xlsx插件本身是不能导出带有样式的excel文件的,如果要实现将导出的文件设置预期的样式,我们需要安装其他插件,但是一提到xlsx的样式插件我们一般就会想到xlsx-style,但是我比较推荐xlsx-js-style这个插件,下面是两个插件之间的区别:
-
xlsx-style
是一个基于xlsx
库的扩展,它提供了一些额外的方法来设置单元格和范围的样式。它可以用于在Excel文件中设置字体、填充、边框等样式。然而,xlsx-style
插件已经很久没有维护了,可能不支持最新的xlsx
库版本。 -
xlsx-js-style
是另一个基于xlsx
库的扩展,它提供了类似于xlsx-style
的功能,可以用于设置单元格和范围的样式。与xlsx-style
不同的是,xlsx-js-style
是最新的库,仍在积极维护和更新。
所以,总的来说,根据当前的情况,xlsx-js-style
是更好的选择,因为它是最新的库,并且仍在维护和更新。它与最新版本的xlsx
库兼容,并提供了更多的功能和改进。
3.只使用xlsx-js-style用来导出文件的弊端
假如我们并不是真正处理文件数据,只是需要将页面table的对象、数组结构的数据进行导出,我们可以只使用xlsx-js-style插件,但是有几点需要注意:
使用`xlsx-js-style`插件仅导出文件可能存在以下一些弊端:
1. 无法读取和处理Excel文件的数据:`xlsx-js-style`插件专注于提供更丰富的样式设置功能,但并不提供读取和处理Excel文件数据的功能。如果你需要读取和处理Excel文件中的数据,你仍然需要使用`xlsx`库。
2. 缺少其他Excel文件处理功能:`xlsx-js-style`插件只提供了样式设置功能,而没有提供其他Excel文件处理功能,如合并单元格、设置列宽、设置打印区域等。如果你需要这些功能,你仍然需要使用`xlsx`库。
下面是一个具体的例子,演示了使用`xlsx-js-style`插件导出文件的限制:
import * as XLSXStyle from 'xlsx-style';
const workbook = XLSXStyle.utils.book_new();
const worksheet = XLSXStyle.utils.aoa_to_sheet([
['姓名', '年龄', '性别'],
['张三', 20, '男'],
['李四', '', '女'],
['王五', 30, '男']
]);
const cellStyle = {
font: { bold: true },
fill: { fgColor: { rgb: 'FFFF00' } }
};
XLSXStyle.utils.sheet_set_range_style(worksheet, 'A1:C1', cellStyle);
XLSXStyle.utils.sheet_set_range_style(worksheet, 'A2:C4', cellStyle);
XLSXStyle.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
const fileName = 'output.xlsx';
const wbout = XLSXStyle.write(workbook, { bookType: 'xlsx', type: 'binary' });
function s2ab(s: string): ArrayBuffer {
const buf = new ArrayBuffer(s.length);
const view = new Uint8Array(buf);
for (let i = 0; i < s.length; i++) {
view[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
}
const blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' });
saveAs(blob, fileName);
//在上面的示例中,我们使用`xlsx-js-style`插件设置了Excel文件的样式,但没有读取或处理Excel文件中的数据。如果我们想要读取或处理Excel文件中的数据,例如计算每个人的年龄总和,我们需要使用`xlsx`库的其他功能来实现:
import * as XLSX from 'xlsx';
const workbook = XLSX.readFile('input.xlsx');
const worksheet = workbook.Sheets['Sheet1'];
const data = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
let ageSum = 0;
for (let i = 1; i < data.length; i++) {
const age = data[i][1];
if (typeof age === 'number') {
ageSum += age;
}
}
console.log('年龄总和:', ageSum);
在上面的示例中,我们使用`xlsx`库的`readFile()`方法读取Excel文件,并使用`utils.sheet_to_json()`方法将工作表转换为JSON格式的数据。然后,我们遍历数据,计算年龄的总和。这是`xlsx-js-style`插件无法提供的功能。
综上所述,如果你只使用`xlsx-js-style`插件来导出文件,你将无法读取和处理Excel文件的数据,并且缺少其他Excel文件处理功能。因此,根据你的需求,你可能需要同时使用`xlsx`库和`xlsx-js-style`插件来实现更全面的Excel文件处理。
五、附录:(xlsx插件的部分方法和属性)
- 在XLSX库中,单元格对象的属性如下:
这些属性可以用于读取和设置单元格的值、数据类型、公式、样式等信息。通过这些属性,你可以对单元格进行各种操作,如获取单元格的值、设置单元格的样式、读取单元格的公式等。
属性 | 含义 |
---|---|
v |
单元格的值。 |
t |
单元格的数据类型,如:s(字符串)、n(数字)、b(布尔值)、e(错误)、d(日期)、z(格式化数字)。 |
f |
单元格的公式。 |
r |
单元格的标识,如:A1、B2、C3。 |
w |
单元格的显示值。 |
c |
单元格的样式。 |
z |
单元格的数字格式。 |
s |
单元格的样式索引。 |
l |
单元格的超链接。 |
a |
单元格的注释。 |
m |
单元格的备注。 |
- xlsx常用的方法/属性:
方法/属性 | 含义 |
---|---|
XLSX.readFile(filename, options) |
从文件中读取 Excel 数据,并返回一个 Workbook 对象。 |
XLSX.writeFile(workbook, filename, options) |
将一个 Workbook 对象写入到文件中。 |
XLSX.utils.sheet_to_json(worksheet, options) |
将一个 Worksheet 对象转换为 JSON 数组。 |
XLSX.utils.json_to_sheet(data, options) |
将一个 JSON 数组转换为 Worksheet 对象。 |
XLSX.utils.sheet_add_json(worksheet, data, options) |
将一个 JSON 数组添加到现有的 Worksheet 对象中。 |
XLSX.utils.sheet_to_csv(worksheet, options) |
将一个 Worksheet 对象转换为 CSV 格式的字符串。 |
XLSX.utils.sheet_to_formulae(worksheet) |
将一个 Worksheet 对象中的公式转换为字符串数组。 |
XLSX.utils.sheet_to_html(worksheet, options) |
将一个 Worksheet 对象转换为 HTML 格式的字符串。 |
Workbook.SheetNames |
获取 Workbook 对象中所有的 Sheet 名称。 |
Workbook.Sheets[sheetName] |
获取 Workbook 对象中指定名称的 Sheet 对象。 |
Worksheet['!ref'] |
获取 Worksheet 对象中定义的范围。 |
Worksheet['!cols'] |
获取 Worksheet 对象中定义的列宽信息。 |
Worksheet['!merges'] |
获取 Worksheet 对象中定义的合并单元格信息。 |
Cell.v |
获取单元格的值。 |
Cell.t |
获取单元格的数据类型,如:s(字符串)、n(数字)、b(布尔值)、e(错误)、d(日期)、z(格式化数字)。 |
Cell.f |
获取单元格的公式。 |
Cell.r |
获取单元格的标识,如:A1、B2、C3。 |