======================
FileSaver.js(保存文件)
保存文件:https://github.com/eligrey/FileSaver.js
安装
安装到项目
npm install file-saver --save
或者cdn引入
<script src="./public/cdn/file/FileSaver.js"></script>
引入
如果是npm安装,使用时可以通过import引入
import { saveAs } from "file-saver";
如果是cdn引入,会给你的全局对象(浏览器就是window)添加一个saveAs函数,直接用
window.saveAs
使用
主要是通过函数saveAs( Blob/File/Url, 文件名 , [选项]) 进行操作
选项只有:{ autoBom: true },转换成Unicode,只有blob type 为 charset=utf-8 有效。
如通过二进制格式blob,保存成文件
var blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
saveAs(blob, "hello world.txt");//其他格式也可以,比如表格xlsx
保存成图片
var canvas = document.getElementById("my-canvas")
canvas.toBlob(function(blob) {
saveAs(blob, "pretty image.png");
});
// 或
FileSaver.saveAs("https://httpbin.org/image", "image.jpg");
=======================
ExcelJS(强大,但慢)
https://github.com/exceljs/exceljs
安装
无需安装,外部引入即可
在index.htm内引入
<script src="./public/cdn/file/FileSaver.js"></script>
<script src="./public/cdn/file/exceljs.min.js"></script>
导出xlsx
//1、表格数据为json
let jsonData = [
{id:1,name:'yjl',sex:'男'},
{id:2,name:'xj',sex:'女'},
];
//2、创建工作簿
let workbook = new ExcelJS.Workbook();
//3、工作簿加入工作表
let worksheet = workbook.addWorksheet('sheet1');
//4、定义列
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 },
{ header: 'Sex', key: 'sex', width: 10 }
];
//5、根据数据,给行赋值
for (let r in jsonData) {
worksheet.addRow(jsonData[r]);
}
//6、导出
workbook.xlsx.writeBuffer()
.then((data) => {
const buff = new Blob([data],{type: "text/plain;charset=utf-8"});
saveAs(buff, "hello world.xlsx");
}).catch((err)=>{
console.log("err: ",err);
})
导入
Vue3.0 版本 + TS 版本(不需要TS的话可以自己去掉 lang=’ts’)
<template>
<div>
<!-- 弹出选择文件按钮 -->
<input
id="importBtn"
ref="importBtn"
type="file"
accept=".xlsx,.xls"
style="display: none"
@change="importSelect"
/>
<!-- 显示的假按钮 -->
<a-button type="primary" @click="importBtnClick" v-bind="props.btnProps">
{{ props.btnText }}
</a-button>
</div>
</template>
<script lang='ts'>
export default {
inheritAttrs: false,
name: "importBtn"
}
</script>
<script setup lang='ts'>
import { ref } from "vue"
import ExcelJS from "exceljs"
import utils from '@/utils'
/** 父组件传入参数 */
const props = defineProps({
/** 按钮 文本 */
btnText: {
type: String,
default: "导入Excel"
},
/** 文件大小判断, 单位MB ,0为不限制 */
fileSizeLimit:{
type:Number,
default:0
},
/** 按钮 属性 */
btnProps: {
default: {}
}
})
const emits = defineEmits(["selectFile"])
/** 显示的假按钮 点击时,触发选择文件 */
const importBtnClick = () => {
// 重要,重置已选取的路径,因为触发导入事件是通过change改变触发,如果不重置路径,那么重复选同一个文件时会不执行后续代码
let impBtn = document.getElementById("importBtn") as HTMLInputElement | null
if (impBtn) {
impBtn.value = ""
impBtn.click()
}
}
// 导入按钮事件
function importSelect() {
// 1、通过input打开选择文件窗口,获取文件信息
let readFile = document.getElementById("importBtn") as HTMLInputElement
// 2、判断用户是否选择了文件
if (readFile?.files && readFile.files[0]) {
// console.log("用户选择了文件", readFile.files[0])
let tempReadFile = readFile.files[0]
// 判断选择的文件类型
if (tempReadFile.type != "application/vnd.ms-excel" && tempReadFile.type as any != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
utils.notice.showErrorMessage("选择的文件类型不正确")
return
}
// 判断文件大小限制
if ( props.fileSizeLimit !=0 && tempReadFile.size>props.fileSizeLimit) {
utils.notice.showErrorMessage(`选择的文件大小超过了 ${props.fileSizeLimit}MB `)
return
}
// 3、创建工作簿
let workbookRead = new ExcelJS.Workbook()
// 4、使用JS的web API FileReader 读取文件信息
let reader = new FileReader()
// 5、设定FileReader读取时的操作,调用读操作(如readAsArrayBuffer)时就会执行这段
reader.onload = function (event) {
//读取时是传入读取的事件,事件里面.target.result就是用户选择文件的内容
let fileData = event?.target?.result as ArrayBuffer
if (fileData) {
//7、用工作簿读取文件内容,通过ArrayBuffer的方式读取
workbookRead.xlsx.load(fileData).then((res) => {
// console.log("res: ", res)
// 把数据提交父组件
emits("selectFile",res)
})
}
}
// 6、调用FileReader读取文件,用readAsArrayBuffer的方法,把内容变成ArrayBuffer
reader.readAsArrayBuffer(readFile.files[0])
} else {
utils.notice.showErrorMessage("选择文件异常",2)
console.log("readFile.files",readFile?.files)
}
}
</script>
<style lang='less'>
</style>
工作簿 WorkBook
基本文件信息
//文件信息
workbook.creator = 'Me'; //创建人
workbook.lastModifiedBy = 'Her'; //最后修改人
workbook.created = new Date(1985, 8, 30); //创建时间
workbook.modified = new Date(); //修改时间
workbook.lastPrinted = new Date(2016, 9, 27); //最后打印时间
workbook.properties.date1904 = true;// 将工作簿日期设置为 1904 年日期系统,默认是用1900年
添加、删除工作表
const sheet = workbook.addWorksheet('My Sheet'); //把工作表sheet添加到工作簿workbook,并且命名为My Sheet
workbook.removeWorksheet(sheet.id); //删除工作表
工作表 WorkSheet
列 column
行 row
单元格 cell
表格 table
其他设置、样式
=======================
SheetJS(简单,快速)
https://github.com/SheetJS/sheetjs (要用到保存文件)
文档:https://docs.sheetjs.com/docs
引入模块
推荐通过npm安装
npm install --save https://cdn.sheetjs.com/xlsx-0.18.9/xlsx-0.18.9.tgz
导出表格
//1、假设表格数据为json
let jsonData = [
{id:1,name:'叶杰麟',sex:'man'},
{id:2,name:'xj',sex:'women'},
];
//2、创建工作表Sheet
let sheet = XLSX.utils.json_to_sheet(jsonData);
//3、创建工作簿workBook
let wb = XLSX.utils.book_new();
//4、把工作表Sheet,放入工作簿workBook内
XLSX.utils.book_append_sheet(wb, sheet, 'sheet1')
//5、将工作簿workBook 和 导出选项一起写入
let wbout = XLSX.write(wb, {type: 'binary'})
//6、创建一个String 转换成 ArrayBuffer的函数
function StringToArrayBuffer(string) {
let buf = new ArrayBuffer(string.length);
let view = new Uint8Array(buf);
for (let i = 0; i != string.length; ++i) {
view[i] = string.charCodeAt(i) & 0xff;
}return buf;
}
//7、把 workBook和导出选项 转换成 Blob
let blob = new Blob([StringToArrayBuffer(wbout)], {type: "text/plain;charset=utf-8"});
//8、导出
saveAs(blob, "hello world.xlsx");//其他格式也可以,比如表格xlsx
导入表格
导入表格按钮示例,点击后弹出选择文件对话框,选择文件后通过emits(selectFile) 把结果返回给父组件使用
<template>
<div>
<!-- 弹出选择文件按钮 -->
<input
id="importBtn"
ref="importBtn"
type="file"
accept=".xls,.xlsx"
style="display: none"
@change="importSelect"
/>
<!-- 显示的假按钮 -->
<a-button type="primary" @click="importBtnClick" v-bind="props.btnProps">
{{ props.btnText }}
</a-button>
</div>
</template>
<script lang='ts'>
export default {
inheritAttrs: false,
name: "importBtn"
}
</script>
<script setup lang='ts'>
import { ref } from "vue"
import * as XLSX from 'xlsx'
import utils from "@/utils"
/** 父组件传入参数 */
const props = defineProps({
/** 按钮 文本 */
btnText: {
type: String,
default: "导入Excel"
},
/** 文件大小判断, 单位MB ,0为不限制 */
fileSizeLimit: {
type: Number,
default: 0
},
/** 按钮 属性 */
btnProps: {
default: {}
}
})
const emits = defineEmits(["selectFile","handleLoading"])
/** 显示的假按钮 点击时,触发选择文件 */
const importBtnClick = () => {
// 重要,重置已选取的路径,因为触发导入事件是通过change改变触发,如果不重置路径,那么重复选同一个文件时会不执行后续代码
let impBtn = document.getElementById("importBtn") as HTMLInputElement | null
if (impBtn) {
impBtn.value = ""
impBtn.click()
}
}
// 导入按钮事件
function importSelect() {
emits("handleLoading",true)
// 1、通过input打开选择文件窗口,获取文件信息
let readFile = document.getElementById("importBtn") as HTMLInputElement
// 2、判断用户是否选择了文件
if (readFile?.files && readFile.files[0]) {
// console.log("用户选择了文件", readFile.files[0])
let tempReadFile = readFile.files[0]
// 判断选择的文件类型
if (
tempReadFile.type != "application/vnd.ms-excel" &&
(tempReadFile.type as any) !=
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
) {
utils.notice.showErrorMessage("选择的文件类型不正确")
emits("handleLoading",false)
return
}
// 判断文件大小限制
if (props.fileSizeLimit != 0 && tempReadFile.size > props.fileSizeLimit) {
utils.notice.showErrorMessage(
`选择的文件大小超过了 ${props.fileSizeLimit}MB `
)
emits("handleLoading",false)
return
}
// 3、使用JS的web API FileReader 读取文件信息
let reader = new FileReader()
// 4、设定FileReader读取时的操作,调用读操作(如readAsArrayBuffer)时就会执行这段
reader.onload = function (event) {
//读取时是传入读取的事件,事件里面.target.result就是用户选择文件的内容
let fileData = event?.target?.result as ArrayBuffer
if (fileData) {
// 7、用sheetJS 的方式读取内容
let res = XLSX.read(fileData)
console.log('导入按钮的res',res)
emits("selectFile", res)
emits("handleLoading",false)
}
}
// 5、调用FileReader读取文件,用readAsArrayBuffer的方法,把内容变成ArrayBuffer
reader.readAsArrayBuffer(readFile.files[0])
} else {
utils.notice.showErrorMessage("选择文件异常", 2)
// console.log("readFile.files", readFile?.files)
emits("handleLoading",false)
}
}
</script>
<style lang='less'>
</style>
表格选项
单元格 Cell
单元格对象通过sheet[‘A1’]表示,如下图:
其他设置中:
单元地址对象存储为{c:c,r:r},其中c和r分别是0索引列和行号。
例如,单元地址B5由对象{c:1,r:4}表示。
单元格区域对象存储为{s:s,e:e},其中s是第一个单元格,e是范围中的最后一个单元格。范围包括在内。
例如,范围A3:B7由对象{s:{c:0,r:2},e:{c:1,r:6}}表示。
值的类型
属性 | 描述 |
---|---|
v |
单元格显示的值 |
w |
格式化文本 |
t |
b 布尔, e 错误, n 数值, d 日期, s 文本, z 空白单元格(默认不会生成)。所有解析器的默认行为是生成数字形式的日期,将cellDates设置为true将强制生成器存储日期。 |
f |
cell formula encoded as an A1-style string (if applicable) |
F |
range of enclosing array if formula is array formula (if applicable) |
r |
rich text encoding (if applicable) |
h |
HTML rendering of the rich text (if applicable) |
c |
comments associated with the cell |
z |
number format string associated with the cell (if requested) |
l |
cell hyperlink object (.Target holds link, .Tooltip is tooltip) |
s |
单元格样式 |
e错误值 | 错误说明 |
---|---|
0x00 |
#NULL! |
0x07 |
#DIV/0! |
0x0F |
#VALUE! |
0x17 |
#REF! |
0x1D |
#NAME? |
0x24 |
#NUM! |
0x2A |
#N/A |
0x2B |
#GETTING_DATA |
工作表 sheet
打印边距 margins
//2、创建工作表Sheet
let sheet = XLSX.utils.json_to_sheet(jsonData);
//设置打印边距,左边距、右边距、上边距、下边距、页眉、页脚
sheet["!margins"]={left:0, right:0, top:0,bottom:0,header:0,footer:0};
单元格合并 merges
存放一些单元格合并信息,是一个数组。
每个数组由包含s和e构成的对象组成,s表示开始start,e表示结束end,r表示行row,c表示列colmn,从0开始的;
//2、创建工作表Sheet
let sheet = XLSX.utils.json_to_sheet(jsonData);
sheet['!merges']=[
{
s:{r:4,c:1},
e:{r:5,c:2}
},
]