electron中使用adm-zip将多个excel文件压缩进文件夹,使用XLSX以及XLSXStyle生成带样式excel文件
需求:electron环境下想要实现根据多个表生成多个Excel文件,打包存入文件夹内并压缩下载到本地。(实际场景描述:界面中有软件工程一班学生信息、软件工程二班学生信息、软件工程三班学生信息,上方有“一键生成”的按钮,点击时弹出文件存储位置选择框选择压缩包所要保存的位置,选择完成后点击保存后生成压缩包中存放一、二、三班三张对应班级学生信息Excel的文件。)注:生成的Excel文件需要按照对应模板进行显示(合并单元格、修改excel单元格的高度和宽度...)
思路:使用electron中的dialog选择保存文件的位置,判断所选地址是否存在;如果存在使用XLSX、XLSXStyle进行文件的生成;然后使用adm-zip将所有文件存放在zip文件夹中保存到本地。
1.下载xlsx xlsx-style adm-zip
npm i xlsx
npm i xlsx-style
npm i adm-zip
或
yarn add xlsx
yarn add xlsx-style
yarn add adm-zip
注意:使用xlsx-style插件的时候需要简单修改下源码,第一种情况下会出现报错,第二种是为了可以调整excel单元格的行高。
1)修改node_modules文件夹下的xlsx-style下的dist下的cpexcel.js文件
807行:var cpt = cptable;
2)修改xlsx-style文件夹下面的xlsx.js文件 替换write_ws_xml_data以下方法
// xlsx-style版本0.8.13
// xlsx版本0.14.1
//这是xlsx-style文件中的xlsx.js的需要修改的代码,是从xlsx文件夹中的xlsx.js中复制出来的
// write_ws_xml_data找到找个方法名字,全部替换
// 把xlsx中能修改高度的代码复制到xlsx-style中
var DEF_PPI = 96, PPI = DEF_PPI;
function px2pt(px) { return px * 96 / PPI; }
function pt2px(pt) { return pt * PPI / 96; }
function write_ws_xml_data(ws, opts, idx, wb) {
var o = [], r = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows'];
var dense = Array.isArray(ws);
var params = ({r:rr}), row, height = -1;
for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(R = range.s.r; R <= range.e.r; ++R) {
r = [];
rr = encode_row(R);
for(C = range.s.c; C <= range.e.c; ++C) {
ref = cols[C] + rr;
var _cell = dense ? (ws[R]||[])[C]: ws[ref];
if(_cell === undefined) continue;
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
}
if(r.length > 0 || (rows && rows[R])) {
params = ({r:rr});
if(rows && rows[R]) {
row = rows[R];
if(row.hidden) params.hidden = 1;
height = -1;
if (row.hpx) height = px2pt(row.hpx);
else if (row.hpt) height = row.hpt;
if (height > -1) { params.ht = height; params.customHeight = 1; }
if (row.level) { params.outlineLevel = row.level; }
}
o[o.length] = (writextag('row', r.join(""), params));
}
}
if(rows) for(; R < rows.length; ++R) {
if(rows && rows[R]) {
params = ({r:R+1});
row = rows[R];
if(row.hidden) params.hidden = 1;
height = -1;
if (row.hpx) height = px2pt(row.hpx);
else if (row.hpt) height = row.hpt;
if (height > -1) { params.ht = height; params.customHeight = 1; }
if (row.level) { params.outlineLevel = row.level; }
o[o.length] = (writextag('row', "", params));
}
}
return o.join("");
}
2.可以在utils下新建一个js文件用于写入xlsx以及xlsx-style相关方法
// 导出为excel
import XLSX from 'xlsx'
import XLSXStyle from 'xlsx-style'
export function exportExcel(filename, data) {
var sheet_name = 'Sheet1'
var work_book = XLSX.utils.book_new()
var sheet = XLSX.utils.aoa_to_sheet(data)
XLSX.utils.book_append_sheet(work_book, sheet, sheet_name)
XLSXStyle.writeFile(work_book, filename) //导出Excel
}
// 将workbook装化成ArrayBuffer对象
export function workbook2ArrayBuffer(workbook) {
var wopts = {
bookType: 'xlsx',
bookSST: false,
type: 'binary',
}
var wbout = XLSXStyle.write(workbook, wopts)
// 将字符串转ArrayBuffer
function s2ab(s) {
var buf = new ArrayBuffer(s.length)
var view = new Uint8Array(buf)
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
return buf
}
return s2ab(wbout)
}
3.在要进行一键生成的界面进行相关逻辑的编写。
<button @click='ClickGenerate'>一键生成</button>
...
...
methods: {
// 一键生成按钮方法
ClickGenerate(){
const fs = require('fs')
let zipName = '软件工程学生信息.zip'
// 弹出dialog选择保存文件的位置
const { dialog } = require("electron").remote
let options = {
title: "软件工程学生信息", //下载文件名称
defaultPath: zipName //下载文件title
}
dialog.showSaveDialog(options, (result) => {
if (!result) {
this.$message.warning('下载任务已取消')
return
}
let path = getDirectory(result)
if (!fs.existsSync(path)) {
this.$message.warning('所选路径不存在!')
return
}
// 准备下载zip文件
this.downloadZip(result)
})
},
// 导出涉密人员zip
async downloadZip(savePath) {
// 准备生成zip
let AdmZip = require("adm-zip")
let zip = new AdmZip()
zip.writeZip(savePath)
//#region
// 生成软件工程一班学生信息并放入zip包中
let soft1buffer = this.creatSoftbuffer('1')
if (soft1buffer) {
zip.addFile('软件工程一班学生信息' + ".xlsx", soft1buffer, "")
}
// #endregion
zip.writeZip(savePath, (error) => {
if (error) {
this.$message.error('[下载异常]' + error.message)
return
}
this.$message.success('下载已完成')
})
},
// 生成excel文件流
creatSoftbuffer(name) {
let list = []
let date = new Date()
let Y = date.getFullYear() + '-';
let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
let D = date.getDate() + ' ';
let dqsj = Y + M + D // 获取当前时间
let soft1Datas = [
{ id: 1, name: "张三", age: '24', address: '哈尔滨市南岗区', grade: '软件一班' },
{ id: 2, name: "里斯", age: '22', address: '哈尔滨市呼兰区', grade: '软件一班' },
{ id: 3, name: "王二", age: '21', address: '哈尔滨市松北区', grade: '软件一班' },
...
] // 此处数据可从后台获取
switch (name) {
case '1':
list.push(["软件工程一班学生信息"]) //确定列名
list.push(["统计时间:", dqsj, "", "", ""]) //确定列名
list.push(["序号", "姓名", "年龄", "地址", "年级"]) //确定列名
let lock1 = 0
for (let i in soft1Datas) { //每一行的值
lock1 = lock1 + 1
let item = soft1Datas[i]
let column = [lock1, item["name"], item["age"], item["address"], item["grade"]]
list.push(column)
}
//Excel sheet页的名称
var sheet_name = "软件工程一班学生信息"
var sum = 5 // 列的数量,根据自身项目进行数据的更改
break
default:
console.log(0)
}
var sheet = XLSX.utils.aoa_to_sheet(list)
// 设置列宽(这里用到列的数量是用来设置不同列的不同宽度的)
let counts = soft1Datas.length + 5
sheet['!cols'] = []
sheet['!rows'] = []
for (let i = 1; i < sum; i++) {
sheet['!cols'].push({ wpx: 150 }) // 设置列宽
}
for (let j = 1; j < counts; j++) {
sheet['!rows'].push({ hpx: 14 }) // 设置列高
}
sheet['!rows'][0].hpx = 35
sheet['!rows'][1].hpx = 20
sheet['!rows'][2].hpx = 20
sheet['!rows'][3].hpx = 20
// 所有设置边框字体水平居中等样式
for (let key in sheet) {
if (sheet[key] instanceof Object) {
sheet[key].s = {
alignment: {
horizontal: 'center', // 水平居中
vertical: 'center' // 垂直居中
},
font: {
sz: 11, // 字号
name: '宋体' // 字体
},
border: { // 边框
top: {
style: 'thin'
},
bottom: {
style: 'thin'
},
left: {
style: 'thin'
},
right: {
style: 'thin'
}
}
}
}
}
// 标题样式修改
sheet.A1.s = {
font: {
name: '宋体',
sz: 16, // 字号
bold: true,
},
alignment: {
horizontal: 'center', // 水平居中
vertical: 'center' // 垂直居中
}
}
sheet['!merges'] = [
{ s: { r: 0, c: 0 }, e: { r: 0, c: 5 } }
];
//新建book
var work_book = XLSX.utils.book_new()
//将数据添加到工作薄
XLSX.utils.book_append_sheet(work_book, sheet, sheet_name)
const workbookArrayBuffer = workbook2ArrayBuffer(work_book)
//arrayBuffer转Buffer
var buf = new Buffer(workbookArrayBuffer.byteLength)
var view = new Uint8Array(workbookArrayBuffer)
for (var i = 0; i < buf.length; ++i) {
buf[i] = view[i]
}
return buf
}
}
electron中使用adm-zip将多个excel文件压缩进文件夹,使用XLSX以及XLSXStyle生成带样式excel文件的更多相关文章
- PHP 的解压缩ZipArchive中的extractTo()方法 LINUX+nginx环境中解压zip时文件丢失的问题
在项目中要用ZipArchive解压ZIP文件,起初測试环境在WINDOWS平台中,測试通过,换到 LINUX+nginx 的环境中时 就出问题了(ZIP包中有文件和目录一共3百多个文件,大部分是带汉 ...
- Electron中使用sql.js操作SQLite数据库
推荐sql.js——一款纯js的sqlite工具. 一.关于sql.js sql.js(https://github.com/kripken/sql.js)通过使用Emscripten编译SQLite ...
- Electron中Jquery的引入方式
原文链接http://huisky.com/blog/16122220522957 Electron默认启用了Node.js的require模块,而jQuery等新版本框架为了支持commondJS标 ...
- linux中tar命令(打包、压缩、解压)、zip和unzip、rar多种压缩文件
一.名词解释 打包:将一大堆文件或目录变成一个总的文件[tar命令] 压缩:将一个大的文件通过一些压缩算法变成一个小文件[gzip,bzip2等] Linux中很多压缩程序只能针对一个文件进行压缩,这 ...
- OTA升级中关于update.zip包的一些总结【转】
本文转载自:http://429564140.iteye.com/blog/2337165 update.zip包整理 一. update.zip包的目录结构 |----boot. ...
- 在electron中使用sqlite:sql.js简介
在electron中使用sqlite:sql.js简介 在开发electron应用的时候如果想要使用sqlite3,步骤上除了npm安装以外还要rebuild,比较麻烦.如果你想找一个开箱即用的sql ...
- Zip文件压缩(加密||非加密||压缩指定目录||压缩目录下的单个文件||根据路径压缩||根据流压缩)
1.写入Excel,并加密压缩.不保存文件 String dcxh = String.format("%03d", keyValue); String folderFileName ...
- 下载zip格式文件(压缩Excel文件为zip格式)
Mongodb配置文件参考这一篇:http://www.cnblogs.com/byteworld/p/5913061.html package util; import java.io.Buffer ...
- 关于ZIP大文件压缩
实测:4.76 GB一个单文件压缩没有什么问题. import java.io.File; import java.io.FileInputStream; import java.io.FileOut ...
- Java实现文件压缩与解压[zip格式,gzip格式]
Java实现ZIP的解压与压缩功能基本都是使用了Java的多肽和递归技术,可以对单个文件和任意级联文件夹进行压缩和解压,对于一些初学者来说是个很不错的实例. zip扮演着归档和压缩两个角色:gzip并 ...
随机推荐
- set 学习笔记
一.声明 1.头文件 \(include<set>//包括set和multiset两个容器\) 2.声明 \(set<int> s\) s自带一个维度 二.迭代器 对" ...
- 使用Java实现haskell-style的list
作为一个haskell这门函数式编程语言的爱好者,我特别喜欢它的list操作和推导功能.与传统面向对象或者过程语言不同的是,函数式语言通常喜欢把它们分为head.tail或者init.last等两部分 ...
- RAID5 IO处理之写请求代码详解
我们知道RAID5一个条带上的数据是由N个数据块和1个校验块组成,其校验块由N个数据块通过异或运算得出,这样才能在任意一个成员磁盘失效时通过其他N个成员磁盘恢复出用户写入的数据.这也就要求RAID5条 ...
- python-D3-语法入门1
Python语法注释 什么是注释 注释其实就是对一段代码的解释说明(注释是代码之母) 如何编写注释 方式1:解释说明文字前加警号 (pycharm中有快捷键ctrl+?) # 注释(单行注释) 方式2 ...
- Codeforces Round #751 (Div. 2)/CodeForces1602
CodeForces1602 Two Subsequences 解析: 题目大意 给你一个字符串 \(s\).你需要两个非空字符串 \(a\) 和 \(b\) 并且满足下面的条件: 字符串 \(a\) ...
- Codeforces Round #827 (Div. 4) A-G
比赛链接 A 题解 知识点:模拟. 时间复杂度 \(O(1)\) 空间复杂度 \(O(1)\) 代码 #include <bits/stdc++.h> #define ll long lo ...
- 驱动开发:内核LDE64引擎计算汇编长度
本章开始LyShark将介绍如何在内核中实现InlineHook挂钩这门技术,内核挂钩的第一步需要实现一个动态计算汇编指令长度的功能,该功能可以使用LDE64这个反汇编引擎,该引擎小巧简单可以直接在驱 ...
- 词云(WordCloud)
WordCloud的参数: font_path:可用于指定字体路径 width:词云的宽度,默认为 400: height:词云的⾼度,默认为 200: mask:蒙版,可⽤于定制词云的形状: min ...
- 16.python中的回收机制
python中的垃圾回收机制是以引用计数器为主,标记清除和分代回收为辅的 + 缓存机制 1.引用计数器 在python内部维护了一个名为refchain的环状双向链表,在python中创建的任何对象都 ...
- ironic组件硬件自检服务——ironic-inspector
介绍 ironic-inspector是一个用于硬件自检的辅助型服务,它可以对被ironic组件管理的裸金属节点进行硬件自检,通过在裸金属节点上运行内存系统,发现裸金属节点的硬件信息,例如CPU数量和 ...