Vue前端实现excel的导入、导出、打印功能_前端打印excel

2401_84433974 2024-06-15 15:33:02 阅读 59

}

// 指定单元格样式

if (key === ‘A1’) {

sheet[key].s = {

…sheet[key].s,

fill: { //背景色

fgColor: { rgb: ‘E4DFEC’ }

}

}

}

// 列宽

let colsP = titles.map(item => {

let obj = {

‘wch’: 25 //列宽

}

return obj;

})

sheet[‘!cols’] = colsP;//列宽

// // 每列的列宽

// sheet[“!cols”] = [{

// wpx: 70 //单元格列宽

// }, {

// wpx: 70

// }, {

// wpx: 70

// }, {

// wpx: 70

// }, {

// wpx: 150

// }, {

// wpx: 120

// }];

}

let fileName = ‘Excel文件.xlsx’

let sheetName = ‘Excel文件’

this.openDownload(this.sheet2blob(sheet, sheetName), fileName);

},

sheet2blob (sheet, sheetName) {

let wb = XLSX.utils.book_new();

wb.SheetNames.push(sheetName)

wb.Sheets[sheetName] = sheet;

// 必须使用xlsx-style才能生成指定样式

var wbout = XLSXStyle.write(wb, { bookType: ‘’, bookSST: false, type: ‘binary’ })

var blob = new Blob([s2ab(wbout)], { type: “” }, sheetName);

// 字符串转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 blob;

},

openDownload (url, saveName) {

if (typeof url == “object” && url instanceof Blob) {

url = URL.createObjectURL(url); // 创建blob地址

}

var aLink = document.createElement(“a”);

aLink.href = url;

aLink.download = saveName || “”; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效

var event;

if (window.MouseEvent) event = new MouseEvent(“click”);

else {

event = document.createEvent(“MouseEvents”);

event.initMouseEvent(

“click”,

true,

false,

window,

0,

0,

0,

0,

0,

false,

false,

false,

false,

0,

null

);

}

aLink.dispatchEvent(event);

}

},

}

### 2. 结合el-table,根据勾选的内容,导出excel表格**html和css就不写了,主要记录下js功能实现的过程**

// 导出函数

export async function exportBtn (payloadList) {

// payloadList是table表格勾选的内容数组

if (payloadList.length === 0) {

this.$message({

type: ‘warning’,

message: ‘请选择要导出的记录!’

})

} else {

// 最终生成sheet的aoelist

let finalList = []

// 一、准备枚举值

// 1.写死

let ywlxenum = [

{ label: ‘预审选址’, value: ‘YSXZ’ },

{ label: ‘土地储备’, value: ‘TDCBGM’ },

{ label: ‘农转用报批’, value: ‘YDBP’ },

{ label: ‘规划条件’, value: ‘GHTJ’ },

{ label: ‘行政划拨’, value: ‘XZHB’ },

{ label: ‘公开出让’, value: ‘GKCR’ },

{ label: ‘建设用地规划许可’, value: ‘JSYDGHXK’ },

{ label: ‘建设工程规划类许可证核发’, value: ‘JSGCGHXK’ },

{ label: ‘建设工程竣工规划核实’, value: ‘JGGHHY’ },

{ label: ‘竣工验收备案’, value: ‘JGYSBA’ }

]

// 2.通过请求获取

let ydxzenum = []

await getEnumByValue({ value: ‘TDLYXZ’ }).then(data => {

ydxzenum = mapListFunc(data.fieldEnum)

})

// 二、通过请求获取数据

let resList = [] // 保存请求数据

for (let i = 0; i < payloadList.length; i++) {

await this.queryInfo({ id: payloadList[i].xmguid }).then(res => {

// 这里是判断了返回值里还包含了list数组

if (res.data.bizGhtjGhqkList.length !== 0) {

let bizGhtjGhqkList = res.data.bizGhtjGhqkList

bizGhtjGhqkList.forEach(item => {

resList.push({ …res.data.bizSlsq, …res.data.bizGhtj, …item })

})

} else {

resList.push({ …res.data.bizSlsq, …res.data.bizGhtj })

}

})

}

// 三、映射关系list

let mappingList = [

{ field: ‘xmmc’, value: ‘项目名称’, merge: true }, // merge代表单元格是否合并

{ field: ‘ydxz’, value: ‘用地性质’, enum: true, merge: true }, // enum代表是否是枚举值

{ field: ‘dkbh’, value: ‘地块编号’ },

]

// 四、添加标题

let titleList = []

mappingList.forEach(item => {

titleList.push(item.value)

})

finalList.push(titleList)

// 五、添加内容

resList.forEach(row => {

// 行的list

let ctnList = []

let hyfltemp = []

let ydxztemp = []

mappingList.forEach(item => {

if (item.enum) {

// 带枚举值的处理

switch (item.field) {

case ‘hyfl’:

hyfltemp = row[item.field] && row[item.field].split(‘,’)

ctnList.push(queryEnumVal(hyflenum, hyfltemp && hyfltemp[(hyfltemp.length - 1)]))

break

case ‘ydxz’:

ydxztemp = row[item.field] && row[item.field].split(‘,’)

ctnList.push(queryEnumVal(ydxzenum, ydxztemp && ydxztemp[(ydxztemp.length - 1)]))

break

case ‘pzjg’:

ctnList.push(queryEnumVal(pzjgenum, row[item.field]))

break

case ‘ywlx’:

ctnList.push(queryEnumVal(ywlxenum, row[item.field]))

break

case ‘cbywlx’:

ctnList.push(queryEnumVal(cbywlxenum, row[item.field]))

break

default:

break

}

} else {

// 常规

ctnList.push(row[item.field])

}

})

finalList.push(ctnList)

})

// 六、处理合并单元格

let mergeArr = []

let { indices } = unipFunc(resList, ‘xmguid’)

mappingList.forEach((item, index) => {

if (item.merge) {

indices.forEach(itemlist => {

if (itemlist.length > 1) {

mergeArr.push({

s: { r: itemlist[0] + 1, c: index },

e: { r: itemlist[itemlist.length - 1] + 1, c: index }

})

}

})

}

})

// 七、生成sheet

let sheet = XLSX.utils.aoa_to_sheet(finalList)

// 八、合并单元格和添加样式

sheet[‘!merges’] = mergeArr

Object.keys(sheet).forEach((item, index) => {

if (sheet[item].t) {

sheet[item].s = { // 对齐方式相关样式

alignment: {

vertical: ‘center’, // 垂直对齐方式

horizontal: ‘center’ // 水平对齐方式

// wrapText: true // 自动换行

}

}

}

})

// 九、导出excel

openDownloadDialog(sheet2blob(sheet), new Date().getTime() + ‘.xlsx’ || ‘表名.xlsx’)

}

}

function queryEnumVal (enumList, field) {

// 获取枚举值对应的key

let enumVal = ‘’

enumList.forEach(item => {

if (item.value === field) {

enumVal = item.label

}

})

return enumVal

}

function mapListFunc (params) {

// 处理枚举值

let list = []

list = params.map(item => {

item.value = item.enumValue

item.label = item.enumName

return item

})

return list

}

// 处理数据重复值

function unipFunc (list, objKey) {

let key = {} // 存储的 key 是type的值,value是在indeces中对应数组的下标

let indices = [] // 数组中每一个值是一个数组,数组中的每一个元素是原数组中相同type的下标

list.map((item, index) => {

// 根据对应字段 分类(type)

let itemKey = item[objKey]

let _index = key[itemKey]

if (_index !== undefined) {

indices[_index].push(index)

} else {

key[itemKey] = indices.length

indices.push([index])

}

})

// 归类结果

let result = []

let resultIndex = []

indices.map((item) => {

item.map((index) => {

if (item.length > 1) {

result.push(list[index])

resultIndex.push(index)

}

})

})

return { result, resultIndex, indices }

}

// 下载excel

function openDownloadDialog (url, saveName) {

if (typeof url === ‘object’ && url instanceof Blob) {

url = URL.createObjectURL(url) // 创建blob地址

}

var aLink = document.createElement(‘a’)

aLink.href = url

aLink.download = saveName || ‘’ // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效

var event

if (window.MouseEvent) event = new MouseEvent(‘click’)

else {

event = document.createEvent(‘MouseEvents’)

event.initMouseEvent(‘click’, true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)

}

aLink.dispatchEvent(event)

}

// 字符串转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

}

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

function sheet2blob (sheet, sheetName) {

sheetName = sheetName || ‘sheet1’

let workbook = XLSX.utils.book_new()

workbook.SheetNames.push(sheetName)

workbook.Sheets[sheetName] = sheet

// 生成excel的配置项

var wopts = {

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

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

type: ‘binary’

}

var wbout = XLSXStyle.write(workbook, wopts)

var blob = new Blob([s2ab(wbout)], { type: ‘application/octet-stream’ })

return blob

}

> > **参考**> > > 1. 带样式的导出参考代码: > <https://blog.csdn.net/weixin_39246975/article/details/121639072>> 2. 别人对xlsx-style的二次封装: > <https://blog.csdn.net/weixin_51947053/article/details/127370479>> > > ## 五、打印功能### 1.直接使用window自带的打印功能: window.print()

点击下面的按钮,可将页面进行打印

打印内容

打印内容

打印内容

打印内容

### 2.使用打印插件:vue-print-nb#### 1、安装 vue-print-nb:

// vue2.x 版本

npm install vue-print-nb --save

// vue3.x 版本

npm install vue3-print-nb --save

#### 2、在项目中引入 vue-print-nb:

// vue2.x版本 – 全局引入:在项目中入口文件 main.js 文件中全局引入 vue-print-nb

import Vue from ‘vue’

import Print from ‘vue-print-nb’

Vue.use(Print)

// 局部引入报错,还不知道咋解决,建议是全局引入

// vue2.x版本 – 在需要打印功能的页面引入 vue-print-nb

import print from ‘vue-print-nb’

export default{

directives: { print }

}

// vue3.x版本 – 全局引入:在项目中入口文件 main.js 文件中全局引入 vue3-print-nb

import {createApp} from ‘vue’

import App from ‘./App’

import Print from ‘vue3-print-nb’

const app = createApp(App)

app.use(Print)

app.mount(‘#app’)

// vue3.x版本 – 在需要打印功能的页面引入 vue3-print-nb

import print from ‘vue3-print-nb’

export default{

directives: { print }

}

#### 3、使用 vue-print-nb 实现打印功能##### ① 实现方式1:打印区域设置id, 打印按钮绑定此 id

点击下面的按钮,可将div里的内容区域进行打印

<div id="printDiv"> <p>打印内容 </p> <p>打印内容 </p> <p>打印内容 </p> <p>打印内容 </p></div><button v-print="'#printDiv'">打印id为printDiv的div区域内容</button>

##### ② 实现方式2:打印区域设置id, 打印按钮进行打印配置

点击下面的按钮,可将div里的内容区域进行打印

<div id="printDiv"> <p>打印内容 </p> <p>打印内容 </p> <p>打印内容 </p> <p>打印内容 </p></div><button v-print="'printSet'">打印id为printDiv的div区域内容</button>

##### ③ 打印网址:打印指定url(同一个同源策略)对应的内容 打印网址

##### ④ 打印预览功能 打印+预览功能

##### ⑤ 打印异步url 打印+预览功能

##### ⑥ 实现区域不打印方式

打印内容区域

打印内容区域

打印内容区域

打印内容区域

打印内容区域

实现区域不打印方式1:设置class为 no-print 即可实现该区域不打印 <p class="no-print">不要打印的内容区域</p> // 实现区域不打印方式2: 自定义不打印区域的class名 <p class="do-not-print-div">不要打印的内容区域</p>

前端框架

前端框架太多了,真的学不动了,别慌,其实对于前端的三大马车,Angular、React、Vue 只要把其中一种框架学明白,底层原理实现,其他两个学起来不会很吃力,这也取决于你以后就职的公司要求你会哪一个框架了,当然,会的越多越好,但是往往每个人的时间是有限的,对于自学的学生,或者即将面试找工作的人,当然要选择一门框架深挖原理。

以 Vue 为例,我整理了如下的面试题。

Vue部分截图

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。