vue项目使用encode_Vue项目中使用xlsx-style导出有格式的表格

本文介绍了如何在Vue项目中利用xlsx-style库导出包含格式(如居中、换行、列宽和单元格合并)的Excel文件。xlsx-style是在SheetJS基础上开发的,支持更多的格式设置。文章详细展示了安装、配置和使用方法,包括列宽设置、单元格合并、冻结表头等,并提供了完整代码示例。
摘要由CSDN通过智能技术生成

SheetJS是前端导出Excel文件的利器,通过很简单的方法就可以实现导出xls、xlsx、odd等格式的文件。

但是SheetJS免费版本支持的格式太少,包括居中、自动换行、冻结等都不行。github上有一个开源的库:xlsx-style。该库是从SheetJS fork出来的,也就是在SheetJS的基础上进行开发的,所以使用xlsx-style就不需要再在项目中引入SheetJS了。

NOTE: That project is a fork of the original (and awesome) SheetJS/xlsx project.

基础

如果你刚开始写SheetJS,强烈推荐你先看SheetJS基础教程。

看完该教程,你已经学会了合并单元格,xlsx文件读取与导出,xlsx与其他格式的转换等。

如果需要增加格式,可以使用另一个开源的库:xlsx-style

成果

我最后导出的Excel的样子:

e927f3afae54

resultExcel.png

使用到的功能:

文字居中

自动换行

列宽设置

单元格合并

冻结表头等

安装

xlsx-style的README文档上的安装方式:

使用 npm:

$ npm install xlsx-style --save

但是我安装后,总是会报错

This relative module was not found:

./cptable in ./node_modules/xlsx-style@0.8.13@xlsx-style/dist/cpexcel.js

如果你安装的时候没问题,最好直接使用npm的方式

直接手动安装

// 下载项目到本地

$ git clone https://github.com/protobi/js-xlsx

然后把 js-xlsx-master/dist/ 路径下的 xlsx.core.min.js、xlsx.js、jszip.js 三个文件拖拽到项目里。你也可以直接使用 xlsx.full.min.js。

然后在index.html中引入就可以用了。

下面是我放的位置,供参考。

e927f3afae54

image-20191213161055737.png

使用

请先阅读基础教程

定义文字字体、大小、居中和换行:

// 设置表格中cell默认的字体,居中,颜色等

defaultCellStyle: {

font: { name: "宋体", sz: 11, color: { auto: 1 } },

border: {

color: { auto: 1 }

},

alignment: {

/// 自动换行

wrapText: 1,

// 居中

horizontal: "center",

vertical: "center",

indent: 0

}

}

在生成CellObject的时候添加这个defaultStyle。

// 从json转化为sheet,xslx中没有aoaToSheet的方法,该方法摘自官方test

sheet_from_array_of_arrays(data) {

const ws = {};

const range = {s: {c:10000000, r:10000000}, e: {c:0, r:0 }};

for(let R = 0; R !== data.length; ++R) {

for(let C = 0; C !== data[R].length; ++C) {

if(range.s.r > R) range.s.r = R;

if(range.s.c > C) range.s.c = C;

if(range.e.r < R) range.e.r = R;

if(range.e.c < C) range.e.c = C;

/// 这里生成cell的时候,使用上面定义的默认样式

const cell = {v: data[R][C], s: this.defaultCellStyle};

if(cell.v == null) continue;

const cell_ref = XLSX.utils.encode_cell({c:C,r:R});

/* TEST: proper cell types and value handling */

if(typeof cell.v === 'number') cell.t = 'n';

else if(typeof cell.v === 'boolean') cell.t = 'b';

else if(cell.v instanceof Date) {

cell.t = 'n'; cell.z = XLSX.SSF._table[14];

cell.v = this.dateNum(cell.v);

}

else cell.t = 's';

ws[cell_ref] = cell;

}

}

/* TEST: proper range */

if(range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);

return ws;

},

冻结列表

// 冻结前6行和第1列,右方下方 可以滑动

// 这里xSplite和ySplite不能设置为0,否则下载下来Excel解析会出现错误

sheet["!freeze"] = {

xSplit: "1",

ySplit: "6",

// 坐上角是哪个cell

topLeftCell: "B7",

activePane: "bottomRight",

state: "frozen",

}

列宽设置

/// wch不是像素宽度!!!这个数值具体换算不太清楚,在Excel里拉动的时候会显示

/// https://docs.sheetjs.com/#column-properties 这里有解释

const sheetCols = [

{ wch: 8} , // 序号

{ wch: 10 }, // 市别

{ wch: 20 }, // 示范工程项目名称

{ wch: 9 }, // 联运线路(条)

];

下面是我最后的代码

导出用的是FileSaver

// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载

sheet2blob(sheet, sheetName) {

sheetName = sheetName || 'sheet1';

const workbook = {

SheetNames: [sheetName],

Sheets: {}

};

workbook.Sheets[sheetName] = sheet

window.console.log(workbook)

// 生成excel的配置项

const wopts = {

bookType: 'xlsx', // 要生成的文件类型

bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性

type: 'binary'

};

const wbout = XLSX.write(workbook, wopts, { defaultCellStyle: this.defaultCellStyle });

const blob = new Blob([s2ab(wbout)], {type: "application/octet-stream"});

// 字符串转ArrayBuffer

function s2ab(s) {

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;

}

return blob;

},

transformF() {

// 表头信息 要合并的字段用null代替

let aoa = [

['江苏省多式联运示范工程项目2019年第二季度动态监测信息表'],

['序号', '市别', '示范工程项目名称', '示范工程项目运行情况'],

[null, null, null, '联运组织',null, null, null, null, null, null, '企业总货物运输量(万吨/万标箱)', null, '枢纽场站建设投资额(万元)', '装备配备建设投资额(万元)', '信息化建设投资额(万元)', '其他'],

[null, null, null, '联运线路(条)','联运线路运营情况', null, null, null, null, null],

[null, null, null, null, '线路', '联运路线', '联运模式', '联运量', null, '联运周转量(万吨公里)', null, null, null, null, null, null],

[null, null, null, null, null, null, null, '万吨', '万标箱', null, '万吨', '万标箱', null, null, null],

]

// json => sheet

const sheet = this.sheet_from_array_of_arrays(aoa);

// 表头合并: r: row 行;c:column 列

const mergeTitle = [

// 江苏省多式联运示范工程项目2019年第二季度动态监测信息表

{

s: {r: 0, c: 0},

e: {r: 0, c: 15}

},

// 序号

{

s: {r: 1, c: 0},

e: {r: 5, c: 0}

},

// 市别

{

s: {r: 1, c: 1},

e: {r: 5, c: 1}

},

// 示范工程名称

{

s: {r: 1, c: 2},

e: {r: 5, c: 2}

},

// 示范工程项目运行情况

{

s: {r: 1, c: 3},

e: {r: 1, c: 15}

},

// 联运组织

{

s: {r: 2, c: 3},

e: {r: 2, c: 9}

},

// 联运线路(条)

{

s: {r: 3, c: 3},

e: {r: 5, c: 3}

},

// 联运线路运营情况

{

s: {r: 3, c: 4},

e: {r: 3, c: 9}

},

// 线路

{

s: {r: 4, c: 4},

e: {r: 5, c: 4}

},

// 联运路线

{

s: {r: 4, c: 5},

e: {r: 5, c: 5}

},

// 联运模式

{

s: {r: 4, c: 6},

e: {r: 5, c: 6}

},

// 联运量

{

s: {r: 4, c: 7},

e: {r: 4, c: 8}

},

// 联运周转量(万吨公里)

{

s: {r: 4, c: 9},

e: {r: 5, c: 9}

},

// 企业总货物运输量(万吨/万标箱)

{

s: {r: 2, c: 10},

e: {r: 4, c: 11}

},

// 枢纽场站建设投资额(万元)

{

s: {r: 2, c: 12},

e: {r: 5, c: 12}

},

//装备配备建设投资额(万元)

{

s: {r: 2, c: 13},

e: {r: 5, c: 13}

},

// 信息化建设投资额(万元)

{

s: {r: 2, c: 14},

e: {r: 5, c: 14}

},

// 其他

{

s: {r: 2, c: 15},

e: {r: 5, c: 15}

},]

sheet['!merges'] = mergeTitle.concat(mergeContent);

// 冻结前6行和第一列,右下可以滑动

sheet["!freeze"] = {

xSplit: "1",

ySplit: "6",

topLeftCell: "B7",

activePane: "bottomRight",

state: "frozen",

}

sheet["!margins"] = { left: 1.0, right: 1.0, top: 1.0, bottom: 1.0, header: 0.5, footer: 0.5 }

// 列宽 使用的不是像素值

const sheetCols = [

{ wch: 8} , // 序号

{ wch: 10 }, // 市别

{ wch: 20 }, // 示范工程项目名称

{ wch: 9 }, // 联运线路(条)

{ wch: 8 }, // 线路

{ wch: 18 }, // 联运路线

{ wch: 15 }, // 联运模式

{ wch: 9 }, // 联运量-万吨

{ wch: 9 }, // 联运量-万标箱

{ wch: 12 }, // 联运周转量

{ wch: 9 }, // 企业万吨

{ wch: 9 }, // 企业 万标箱

{ wch: 10 }, // 枢纽站

{ wch: 10 }, // 装备

{ wch: 10 }, // 信息化

{ wch: 27 }, // 备注

];

sheet['!cols'] = sheetCols;

// 设置行高,但是没起作用

/*

* type RowInfo = {

hidden?: boolean; // if true, the row is hidden

/// row height is specified in one of the following ways:

hpx?: number; // height in screen pixels

hpt?: number; // height in points

level?: number; // 0-indexed outline / group level

};*/

// sheet['!rows'] = [

// { hidden: true },

// { hpx: 44 },

// { hpt: 12 },

// { level: 1 },

// { level: 2 },

// { level: 3 },

// { level: 4 },

// null,null,null,null,null,

// null,null,null,null,null,

// null,null,null,null,null,

// null,null,null,null,null,

// ];

// sheet => bolb

const wbBlob = this.sheet2blob(sheet, '1')

// 保存下载

FileSaver.saveAs(wbBlob, 'd.xlsx')

},

几乎所有相关代码都已经贴出来了,希望有帮到你。

如果有其他格式我没有用到而你迫切需要,首先你可以看免费的SheetJS是否能满足你的需求。不够的话,可以去js-xlsx的查看文档或者下载官方的demo,查看是否有相应的test文件,文章里的很多属性也都是通过许多测试文件找到的。

最后,用餐愉快。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用 `xlsx` 库和 `file-saver` 库来导出 xlsx 表格。具体步骤如下: 1. 安装 `xlsx` 和 `file-saver` 库 ``` npm install xlsx file-saver --save ``` 2. 在组件引入 `xlsx` 和 `file-saver` 库 ```typescript import * as XLSX from 'xlsx'; import { saveAs } from 'file-saver'; ``` 3. 定义表格数据和表头 ```typescript const data = [ { name: 'John', age: 25, gender: 'male' }, { name: 'Mary', age: 30, gender: 'female' }, { name: 'Tom', age: 35, gender: 'male' }, ]; const header = ['Name', 'Age', 'Gender']; ``` 4. 定义导出函数 ```typescript export const exportExcel = () => { // 创建工作簿 const workbook = XLSX.utils.book_new(); // 创建工作表 const worksheet = XLSX.utils.json_to_sheet(data); // 设置表头 const headerRange = XLSX.utils.decode_range(worksheet['!ref']); headerRange.s.r = 1; XLSX.utils.sheet_set_range_style(worksheet, XLSX.utils.encode_range(headerRange), { font: { bold: true }, fill: { fgColor: { rgb: 'cccccc' } }, }); XLSX.utils.sheet_add_aoa(worksheet, [header], { origin: 'A1' }); // 设置表格宽度 const colWidth = header.map((item) => ({ wch: item.length + 5, })); worksheet['!cols'] = colWidth; // 添加工作表到工作簿 XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1'); // 导出表格 const buffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }); const blob = new Blob([buffer], { type: 'application/octet-stream' }); saveAs(blob, 'example.xlsx'); }; ``` 5. 在组件调用导出函数 ```html <template> <button @click="exportExcel">导出表格</button> </template> <script lang="ts"> import * as XLSX from 'xlsx'; import { saveAs } from 'file-saver'; const data = [ { name: 'John', age: 25, gender: 'male' }, { name: 'Mary', age: 30, gender: 'female' }, { name: 'Tom', age: 35, gender: 'male' }, ]; const header = ['Name', 'Age', 'Gender']; export default { methods: { exportExcel() { const workbook = XLSX.utils.book_new(); const worksheet = XLSX.utils.json_to_sheet(data); const headerRange = XLSX.utils.decode_range(worksheet['!ref']); headerRange.s.r = 1; XLSX.utils.sheet_set_range_style(worksheet, XLSX.utils.encode_range(headerRange), { font: { bold: true }, fill: { fgColor: { rgb: 'cccccc' } }, }); XLSX.utils.sheet_add_aoa(worksheet, [header], { origin: 'A1' }); const colWidth = header.map((item) => ({ wch: item.length + 5, })); worksheet['!cols'] = colWidth; XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1'); const buffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }); const blob = new Blob([buffer], { type: 'application/octet-stream' }); saveAs(blob, 'example.xlsx'); }, }, }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值