纯前端导出Excel并修改样式

news2024/11/26 18:34:44

之前写过一篇前端导出:Vue实现导出功能(无后端配合) ,但是当时没考虑到样式的问题,后来要求导出的Excel单元格的样式也需要调整,尤其是宽度,第一想到的就是xlsx-style这个包,之前也没用过,这次用一下试着调一下宽度等样式,刚安装上就嘎嘎报错~~~,下面就介绍一下该库是使用,踩坑解决...

首先安装: 

npm i file-saver -S
npm i xlsx -S
npm i xlsx-style -S

然后引入 

import * as XLSX from 'xlsx'
import FileSaver from 'file-saver'
import XLSXS from 'xlsx-style'

如果仅仅是为了导出,不修改样式,也就是不引入 xlsx-style 这个库 是没有问题的,但是引入了 xlsx-style之后,直接报错,项目直接跑不起来,首先报错如下: 

1. Module not found: Error: Can't resolve './cptable' 

解决: 

只需在vue.config.js中添加如下 

configureWebpack: {
  // 解决 Module not found: Error: Can't resolve './cptable' 
  externals: {
    './cptable': 'var cptable'
  }
}

接着还有错,

2. Module not found: Error: Can't resolve 'fs' 

解决: 

接着在vue.config.js中添加 

configureWebpack: {
  // 解决 Module not found: Error: Can't resolve './cptable'
  externals: {
    './cptable': 'var cptable'
  },
  // 解决 Module not found: Error: Can't resolve 'fs' 
  resolve: {
    fallback: {
      fs: false
    }
  }
}

再重新跑一下,哎呦呵,跑起来了,但是给出了个警告 

 

它让我们安装一下 crypto-browserify 这个东东,再配置一下, 应该就可以避免了吧,唉,我这里暂时没管它, 毕竟项目跑起来了,项目和人有一个能跑的就可以啦,哈哈哈哈哈哈哈哈哈哈哈...有时间再看下吧。。

当我们跑起来之后,然后使用的时候,就得使用xlsx-style中的write方法了,但是使用的时候浏览器控制台还是报错了,如下:

这个时候就得去修改源码了,位置在 node_modules/xlsx-style/xlsx.js中1339行的位置处: 

if(typeof jszip === 'undefined') jszip = require('./js'+'zip').JSZip;
修改为:
if(typeof jszip === 'undefined') jszip = require('./jszip.js');

但是我们这样只是修改我们自己的本地,下次再装依赖的时候还得重新去改,不可能每次都去这改,显然是行不通的,这时候我们就可以在package.json中scripts中添加一个脚本,有个 postinstall  钩子,在我们执行完npm install后会执行postinstall对应的脚本,所以我们可以在这里做处理。

首先我们在项目根目录下新建 lib/xlsx-style/xlsx.js,然后将node_modules/xlsx-style/xlsx.js拷贝过来一份,我们修改 lib/xlsx-style/xlsx.js 中的代码,将1339行修改掉,然后在scripts中添加postinstall

"scripts": {
  "serve": "vue-cli-service serve",
  "build": "vue-cli-service build",
  "lint": "vue-cli-service lint",
  "postinstall": "node install-xlsx-style-xlsx.js"
},

然后在根目录下新建 install-xlsx-style-xlsx.js 


const path = require('path')
const fs = require('fs')

const xlsxStyleModulesPath = path.join(__dirname, 'node_modules/xlsx-style/xlsx.js')
const xlsxStyleLibPath = path.join(__dirname, 'lib/xlsx-style/xlsx.js')

fs.writeFileSync(xlsxStyleModulesPath, fs.readFileSync(xlsxStyleLibPath))

这样就可以了,之后再安装依赖的时候就会自动替换掉node_modules/xlsx-style/xlsx.js。

key简介
v原始值(有关更多信息,请参见“数据类型”部分)
w格式化文本
t单元格类型:b布尔值,n数字,e错误,s字符串,d日期
f单元格公式
r富文本编码
h富文本格式的HTML呈现
c与单元格相关的评论
z与单元格关联的数字格式字符串
l单元超链接对象(Target含链接,tooltip工具提示)
s单元格的样式/主题

 

接下来就是方法的封装:

闲话不多说了,直接上代码: 

1.  这个是我们只需要把要打印的表格dom和下载的文件名称(name.xlsx)传入即可

但是这个只能打印当前的数据 


import * as XLSX from 'xlsx'
import FileSaver from 'file-saver'
import XLSXS from 'xlsx-style'
 
export default function(dom, fileName) {
  let tableDom = dom.cloneNode(true)
  let elTableFixedRight = tableDom.querySelector(".el-table__fixed-right")
  let elTableFixed = tableDom.querySelector(".el-table__fixed")
  if(elTableFixedRight) tableDom.removeChild(elTableFixedRight);
  if(elTableFixed) tableDom.removeChild(elTableFixed);
  let wb = XLSX.utils.table_to_book(tableDom, { raw: true, sheet: '运行日志表' })
  setExcelStyle(wb['Sheets']['运行日志表']) // 设置样式
  let wbout = XLSXS.write(wb, {  // 使用 xlsx-style 中的write方法
    bookType: 'xlsx',
    bookSST: false,
    type: 'binary'
  })
  try {
    FileSaver.saveAs( new Blob([s2ab(wbout)], { type: "application/octet-stream" }), fileName);
  } catch(e) {
    console.error(e, wbout, '----->>>')
  }
}

// 设置导出Excel样式 这里主要是关注单元格宽度
function setExcelStyle(data) {
  let borderAll = {
    //单元格外侧框线
    top: {
      style: "thin",
    },
    bottom: {
      style: "thin",
    },
    left: {
      style: "thin",
    },
    right: {
      style: "thin",
    },
  }
  data['!cols'] = []
  for(let key in data) {
    if(data[key].constructor === Object) {
      data[key].s = {
        // border: borderAll,  // 边框
        alignment: {
          horizontal: "center", //水平居中对齐
          vertical: "center", // 垂直居中
        },
        font: {
          sz: 11,
        },
        bold: true,
        numFmt: 0
      }
      data["!cols"].push({ wpx: 160 }); // 单元格宽度
    }
  }
}


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
}

2. 这个是我们可以自定义导出数据(一般表格会分页展示数据,如果按照上面的方式 只会导出当前页的,如果想导出所有数据 就使用该方法)传入数据list和一个导出的文件名

我们要遍历传入的list,所以里面的字段还需要根据自己的去修改一下 

// 导出Excel
export function exportExcel(tableList, fileName) {
  let tableData = [['故障报警', '设备名称', '故障内容', '系统', '状态', '开始时间', '结束时间']]
  tableList.forEach(item => {
    tableData.push([ item.alarm, item.equipname, item.point, item.system, item.status, item.starttime, item.endtime ])
  })
  let ws = XLSX.utils.aoa_to_sheet(tableData)
  setExcelStyle(ws) // 设置样式
  let wb = XLSX.utils.book_new()
  XLSX.utils.book_append_sheet(wb, ws)
  let wbout = XLSXS.write(wb, {
    bookType: 'xlsx',
    bookSST: false,
    type: 'binary'
  })
  try {
    FileSaver.saveAs( new Blob([s2ab(wbout)], { type: "application/octet-stream" }), fileName);
  } catch(e) {
    console.error(e, wbout, '----->>>')
  }
}

// 设置导出Excel样式 这里主要是关注单元格宽度
function setExcelStyle(data) {
  let borderAll = {
    //单元格外侧框线
    top: {
      style: "thin",
    },
    bottom: {
      style: "thin",
    },
    left: {
      style: "thin",
    },
    right: {
      style: "thin",
    },
  }
  data['!cols'] = []
  for(let key in data) {
    if(data[key].constructor === Object) {
      data[key].s = {
        // border: borderAll,  // 边框
        alignment: {
          horizontal: "center", //水平居中对齐
          vertical: "center", // 垂直居中
        },
        font: {
          sz: 11,
        },
        bold: true,
        numFmt: 0
      }
      data["!cols"].push({ wpx: 180 }); // 单元格宽度
    }
  }
}


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
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/153746.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python基础篇---生成器和模块

生成器对象 生成器对象其本质是自定义迭代器,就是需要我们自己写代码产生的迭代器。 生成器对象也是节省存储空间的 特性与迭代器对象一致。 def index():print(第一次输出)yield 1print(第二次输出)yield 2 1 2 3 4 5 6 7 8 9 10 当我们没有加括号调用之前&…

学习JavaScript,有哪些好的博客或者网站推荐?

前言 特意制作了一个Js整体的学习路线以及相关知识点博客讲解以及各类网站学习的资源整合,希望对你有帮助哈~ 废话少说,我们直接进入正题,先放上路线导图: 部分重要知识点 基础性知识 声明变量 null 和 undefined 详解JavaS…

code warrior IDE win10 64位安装保姆级教程

以下安装步骤是在win10 64位系统运行程序默认安装在C盘第1步:第2步:将PE_Plugin.dll文件复制到com文件夹中,路径如下:C:\Program Files(x86)\Freescale\CodeWarrior for Microcontrollers V6.3\bin\plugins\com第3步:以…

Blender里的三种绑定 (三)骨骼

文章目录Blender里的三种绑定.骨骼.骨骼基础.骨骼的父子关系.挤出骨骼.细分骨骼.骨骼分层.骨骼分组.骨骼约束.骨骼被遮挡.对称骨骼.为模型绑定骨骼.刚体物体,只跟随骨骼的移动,不随骨骼移动发生形变,如机械.软体物体,跟随骨骼的移…

手写RPC框架第7版-框架容错性相关设计

源代码地址:https://github.com/lhj502819/IRpc/tree/v8 系列文章: 注册中心模块实现路由模块实现序列化模块实现过滤器模块实现自定义SPI机制增加框架的扩展性的设计与实现基于线程和队列提升框架并发处理能力框架容错性相关设计通过SpringBoot-Starte…

数据结构:关于空间复杂度的例题计算

1、计算冒泡排序的空间复杂度 答案:该程序空间复杂度为O(1)。 解析:该程序在栈空间所申请的临时变量空间只有三个,也就是看成常数个,所以是O(1)。如下图所示 2、动态开辟N个数的数组空间复杂度 答案:该程序空间复杂度…

【UE4 第一人称射击游戏】31-更好的UI界面

素材资料地址:链接:https://pan.baidu.com/s/1epyD62jpOZg-o4NjWEjiyg密码:jlhr上一篇:【UE4 第一人称射击游戏】30-简单的任务提示功能本篇效果:步骤:在UE中新建一个“HUD_Export”文件夹,将所…

《码出高效:java开发手册》七 - 并发与多线程

前言 现代CPU运算速度以百亿计,家用计算机和操作系统也是数十进程,数百线程,程序相应也需要采用多线程和并发的技术 并发和并行:并发是指某个时间段,多任务处理;并行是指同时处理多任务的能力;…

接口测试项目实战与经典面试题解析,挑战 BAT 大厂必会!

近年来,接口测试技术体系已在各大互联网企业落地普及,各种新接口框架不断涌现,业界也形成了不少成熟方案和成功案例。当前 BAT 大厂在招聘测试人员时,接口测试技能和项目经验是必考重点,直接影响到职级评定和薪资水平&…

2023/1/10 Vue学习笔记6 - 路由基本使用

1 路由的简介-router 1、路由就是一组key-value的对应关系。 2、多个路由,需要经过路由器的管理。 SPA (single page web application)应用 - 单页面web应用 {"key":"/class","value":"班级组件" }1.vue-rout…

kali中wpscan工具使用

一.wpscan工具简介 wpscan是一款专门针对wordpress的扫描工具,采用ruby语言编写,能够扫描worpress网站中包括主题漏洞、插件漏洞以及wordpress网站本身存在的漏洞。wpscan还可以扫描wordpress网站启用的插件和其他功能。 在Kali Linux系统中&#xff0…

关于distinct——去除重复记录

distinct译为:不同的,有区别的;在SQL语句中表示去除重复记录的意思 举例:在员工表emp中查询所有的工作岗位。 分析:在员工表中的工作岗位字段下有重复的工作岗位,我们在查询的时候就希望将重复的工作岗位显…

数据库取证——MySQL基础知识

目录 一、数据库基础知识 (一)数据库(DB) (二)数据库管理系统(DBMS) (三)数据库系统(DBS) (四) 数据库的…

【Unity云消散】简单理论基础:实现边缘光

写在前面 既然想要实现云的消散效果,那么边缘光如何计算也是一个重点。 在Unity Shader入门精要的14章,介绍轮廓线渲染就介绍了——轮廓边检测,而边缘光也是需要先检测出轮廓边再进行的。 Unity3D Shader系列之边缘光RimLight 这篇博客给…

Go专家编程读书小记

文章目录协程进程和线程进程:进程间通信:线程:区别:协程GMP模型调度策略内存管理内存分配span:cache:central:heap:垃圾回收常见的垃圾回收算法:三色标记:垃圾…

【NI Multisim 14.0原理图设计基础——查找元器件】

目录 序言 一、查找元器件 🍍1.浏览元器件 🍍2.搜索元器件 🍍 3.显示找到的元器件及其所属元器件库 🍍 4.加载找到元器件的所属元器件库 序言 NI Multisim最突出的特点之一就是用户界面友好。它可以使电路设计者方便、快捷地…

大资金现金管理的利器:稳定币网格做市策略

数量技术宅团队在CSDN学院推出了量化投资系列课程 欢迎有兴趣系统学习量化投资的同学,点击下方链接报名: 量化投资速成营(入门课程) Python股票量化投资 Python期货量化投资 Python数字货币量化投资 C语言CTP期货交易系统开…

从一条记录说起—— InnoDB 记录结构

准备工作 到现在为止,MySQL对于我们来说还是一个黑盒,我们只负责使用客户端发送请求并等待服务器返回结果,表中的数据到底存到了哪里?以什么格式存放的?MySQL是以什么方式来访问的这些数据?这些问题我们统…

springboot构造树形结构数据并查询的方法

因为项目需要,页面上需要树形结构的数据进行展示(类似下图这样),因此需要后端返回相应格式的数据。 不说废话,直接开干!!! 我这里用的是springboot+mybatis-plus+mysql,示例的接口是查询一级权限以及二级权限、三级权限整个权限树… 下面是导入的maven依赖 <depe…

SSD核心设计

摘要本文介绍了此类设计选择的分类&#xff0c;并使用跟踪驱动的模拟器和从实际系统中提取的工作负载跟踪分析各种配置的可能性能。我们发现SSD性能和生命周期对工作负载非常敏感&#xff0c;并且通常较高的复杂系统问题出现在存储堆栈中甚至在分布式系统中&#xff0c;与设备固…