前端使用xlsx-js-style导出Excel,带样式,并处理合并单元格边框显示不全和动态插入表头解决
一、在学习之前,先给出一些学习/下载地址:
xlsx-js-style下载地址
https://github.com/gitbrent/xlsx-js-style
或者
https://www.npmjs.com/package/xlsx-js-style
SheetJS中文教程:
https://xlsx.nodejs.cn/docs/csf/cell
二、先看样式
页面HTML显示

2.1 导出带边框的表格Excel显示样式:

2.2 表格插入表头操作Excel显示样式

三、全部代码:
<html>
<head><script src="dist/xlsx.bundle.js"></script><style type="text/css">.tbexport {border-collapse: collapse;width: 500px;}.tbexport th, td {border: 1px solid #ddd;padding: 8px;text-align: left;}.tbexport2 {border-collapse: collapse;width: 100%;}.tbexport2 th, td {border: 1px solid #ddd;text-align: left;}</style><scriptsrc="https://code.jquery.com/jquery-3.7.1.min.js"integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="crossorigin="anonymous"></script>
<!-- 如果这个jquery连接不上,可以自己下载一个--><head>
<body>
<table id="TableToExport" class="tbexport"><tr><td>序号</td><td>名称</td><td>测试1</td><td>测试2</td><td>测试3</td><td>测试4</td></tr><tr><td>1</td><td>bb</td><td>345</td><td>566</td><td>777</td><td>888</td></tr><tr><td>2</td><td>bb</td><td rowspan="3">999</td><td>566</td><td>777</td><td>888</td></tr><tr><td>3</td><td>bb</td><td>999</td><td>1010</td><td>111</td></tr><tr><td>4</td><td>bb</td><td>333</td><td>44</td><td>55</td></tr><tr><td colSpan="2">合计</td><td>22</td><td>77</td><td>88</td><td>99</td></tr>
</table><style type="text/css">.datatable{}.datatable td{padding:10px;border:1px solid #000}.datatable thead td {background-color:#f0f0f0}
</style><button id="sheetjsexport" onclick = "myExportExcel()"><b>合并单元格导出带边框</b></button><button onclick = "myExportExcel2()"><b>导出带表头表格</b></button>
<script>var MyStyle = {borderStyle:{border: {top: {style: 'thin',color: {auto: 1}},left: {style: 'thin',color: {auto: 1}},right: {style: 'thin',color: {auto: 1}},bottom: {style: 'thin',color: {auto: 1}}},},centerStyle: {alignment: {horizontal: "center",vertical: "center"}},leftStyle :{alignment: {horizontal: "left",vertical: "center"},},rightStyle : {alignment: {horizontal: "right",vertical: "center"},},boldStyle : { //设置一级标题样式font: {// sz: 12,bold: true,// color: {rgb: "000000"}}},smallStyle : { //设置一级标题样式font: {sz: 9,bold: false,color: {rgb: "222222"}}},titleStyle : { //设置一级标题样式font: {sz: 14,bold: true,// color: {rgb: "000000"}},alignment: {horizontal: "center",vertical: "center"},},title2Style : { //设置二级标题样式font: {bold: true,// color: {rgb: "000000"}},alignment: {horizontal: "center",vertical: "center"},},bgStyle : {fill:{fgColor: {rgb: "EEECE1"}},}
};function checkEmptyItem(ws ){var range = XLSX.utils.decode_range(ws['!ref']);
// // 计算最大列号var maxCol = range.e.c; // 'e' 代表结束列,'c' 是列号的字段var maxRow = range.e.r;//不加时,合并单元格边框会缺少for(let i = 0; i<=maxRow; i++){for(let j = 0;j<=maxCol; j++){if (ws[XLSX.utils.encode_cell({r: i, c: j})] == undefined) {ws[XLSX.utils.encode_cell({r: i, c: j})] ={t: 's', v: "", z: XLSX.utils.encode_cell({r: i, c: j})};}}}return ws;
}function myExportExcel()
{/* Create worksheet from HTML DOM TABLE */var wb = XLSX.utils.table_to_book(document.getElementById("TableToExport"),{sheet:'测试',raw:true})/* Export to file (start a download) */var ws = wb.Sheets["测试"]; // get the currentconst range = XLSX.utils.decode_range(ws['!ref']);
// // 计算最大列号const maxCol = range.e.c; // 'e' 代表结束列,'c' 是列号的字段const maxRow = range.e.r;let arr = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M","N","O","P"] //总共多少列//设置公共样式ws = checkEmptyItem(ws);for (let i = 1; i <= maxRow+1; i++) {for(j = 0;j<=maxCol; j++){var item = arr[j];let str = item + i;if (ws[str]) {var cellStyle = { };cellStyle = $.extend(cellStyle, MyStyle.borderStyle) ;cellStyle = $.extend(cellStyle, MyStyle.centerStyle) ;if(i==1){cellStyle = $.extend(cellStyle, MyStyle.title2Style) ;ws['!cols'][j]={wpx:120};//设置列的高度}}Object.assign(ws[str], {s: cellStyle});}ws['!rows'][i-1] = { hpx:30 };//设置行的高度}XLSX.writeFile(wb, "SheetJSTable.xlsx");
}
//导出带表头样式
function myExportExcel2() {/* Create worksheet from HTML DOM TABLE */var wb = XLSX.utils.table_to_book(document.getElementById("TableToExport"), {sheet: '测试',raw: true,origin: {c: 0, r: 1}}); //从第1列,第三行开始var ws = wb.Sheets["测试"]; // get the current// 要插入的新行数据const newRow = ['测试完成情况'];
//添加1行合并单元格内容var nMergeLength = ws["!merges"].length;ws["!merges"][nMergeLength] = XLSX.utils.decode_range("A1:F1");
// 表头设置值ws[XLSX.utils.encode_cell({r: 0, c: 0})] ={t: 's', v: newRow[0], z: XLSX.utils.encode_cell({r: 0, c: 0})};
//设置表头样式Object.assign(ws["A1"], {s: MyStyle.titleStyle});ws['!rows'][0] = {hpx: 50};const range = XLSX.utils.decode_range(ws['!ref']);
// // 计算最大列号const maxCol = range.e.c; // 'e' 代表结束列,'c' 是列号的字段const maxRow = range.e.r;let arr = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P"] //总共多少列ws = checkEmptyItem(ws);//设置公共样式for (let i = 2; i <= maxRow + 1; i++) {for (j = 0; j <= maxCol; j++) {var item = arr[j];let str = item + i;if (ws[str]) {var cellStyle = {};cellStyle = $.extend(cellStyle, MyStyle.borderStyle);cellStyle = $.extend(cellStyle, MyStyle.centerStyle);if (i == 2) {cellStyle = $.extend(cellStyle, MyStyle.title2Style, MyStyle.bgStyle);ws['!cols'][j] = {wpx: 120};//设置列的高度}}Object.assign(ws[str], {s: cellStyle});}ws['!rows'][i - 1] = {hpx: 30};//设置行的高度}XLSX.writeFile(wb, "SheetJSTable.xlsx");
}
</script>
===================================================</body></html>
四、关键代码说明:
4.1. 这里主要是为了合并单元格时,给空单元格设置一个空值,不然加边框时就不会显示
function checkEmptyItem(ws ){var range = XLSX.utils.decode_range(ws['!ref']);
// // 计算最大列号var maxCol = range.e.c; // 'e' 代表结束列,'c' 是列号的字段var maxRow = range.e.r;//不加时,合并单元格边框会缺少for(let i = 0; i<=maxRow; i++){for(let j = 0;j<=maxCol; j++){if (ws[XLSX.utils.encode_cell({r: i, c: j})] == undefined) {ws[XLSX.utils.encode_cell({r: i, c: j})] ={t: 's', v: "", z: XLSX.utils.encode_cell({r: i, c: j})};}}}return ws;
}
4.2 如果需要插入表头:
a) 加这句的意思是从第1行,第0列开始导出表格,意思就是给表头预留一行:
var wb = XLSX.utils.table_to_book(document.getElementById(“TableToExport”), {
sheet: '测试',
raw: true,
origin: {c: 0, r: 1}
});
b) 给表头设置值和加入样式:
//添加1行合并单元格内容
var nMergeLength = ws["!merges"].length;ws["!merges"][nMergeLength] = XLSX.utils.decode_range("A1:F1");
// 表头设置值
ws[XLSX.utils.encode_cell({r: 0, c: 0})] ={t: 's', v: newRow[0], z: XLSX.utils.encode_cell({r: 0, c: 0})};
//设置表头样式
Object.assign(ws["A1"], {s: MyStyle.titleStyle});ws['!rows'][0] = {hpx: 50};
下载地址:
https://download.csdn.net/download//89804082
相关文章:
前端使用xlsx-js-style导出Excel,带样式,并处理合并单元格边框显示不全和动态插入表头解决
一、在学习之前,先给出一些学习/下载地址: xlsx-js-style下载地址 https://github.com/gitbrent/xlsx-js-style 或者 https://www.npmjs.com/package/xlsx-js-style SheetJS中文教程: https://xlsx.nodejs.cn/docs/csf/cell 二、先看样…...
自动化工具ansible部署和实践
1 介绍和部署 1.1 介绍 ansible的功能 我爱你在当今的IT自动化领域,Ansible无疑是一个无法被忽视的重要角色。其便利性和高效性受到了广大开发者和系统管理员的一致好评,成为了配置管理和应用部署的首选工具。然而,对于一些初学者来说&#…...
无人机推流直播平台EasyDSS视频技术如何助力冬季森林防火
冬季天干物燥,大风天气频繁,是森林火灾的高发期。相比传统的人力巡查,无人机具有更高的灵敏度和准确性,尤其在夜间或浓雾天气中,依然能有效地监测潜在火源。 无人机可以提供高空视角和实时图像传输,帮助巡…...
React Fiber
React Fiber 是 React 16 引入的全新重写的协调(Reconciliation)算法的实现,旨在改善 React 的更新机制和性能,尤其是在复杂应用和大量更新的场景下。它使得 React 更加灵活、可调度,能够实现优先级控制和中断更新等特…...
【前端】JavaScript 中的 map() 方法:高级解析与应用
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端 文章目录 💯前言💯map() 方法的定义与核心特性1.1 方法定义1.2 主要特性 💯map() 方法的语法与高级用法2.1 基本语法2.2 简化写法与箭头函数2.3 结合链式操作 💯ma…...
《智能体开发实战(高阶)》四、系统化的日志周报智能体开发计划
智能体扩展与完善规划 为了将前几个章节的智能体逐步扩展为支持整个公司团队使用的高效工具,以下是分阶段的完善与扩写规划。每个阶段旨在提升功能覆盖范围、处理能力和用户体验,并为企业提供实际价值。 阶段一:基础功能完善 目标:巩固现有功能,提升健壮性和适用性。 支…...
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球最受欢迎的Web服务器软件,支持约30.2%的所有活跃网站。凭借其可靠性、灵活性和强大的功能,Apache数十年来一直是互联网的中坚力量。 一、Apache Web服务器的工作原理 Apache Web服务器的工作原理如下: 接收HTTP请求࿱…...
Mybatis——(2)
2.2 Mybatis 工具类(了解) 为了简化MyBatis的开发,可将MyBatis进一步封装。 import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apa…...
景联文科技入选中国信通院发布的“人工智能数据标注产业图谱”
近日,由中国信息通信研究院、中国人工智能产业发展联盟牵头,联合中国电信集团、沈阳市数据局、保定高新区等70多家单位编制完成并发布《人工智能数据标注产业图谱》。景联文科技作为人工智能产业关键环节的代表企业,入选图谱中技术服务板块。…...
修改浏览器地址栏参数
Vue 修改当前页面地址栏参数 function updateUrlParameter(param: string, value: string) {const url new URL(window.location.href); // 获取当前页面的 URL// 解析哈希部分const hash url.hash ? url.hash.slice(1) : "";const [path, queryString] hash.sp…...
Spring Boot教程之二十五: 使用 Tomcat 部署项目
Spring Boot – 使用 Tomcat 部署项目 Spring Boot 是一个基于微服务的框架,在其中创建可用于生产的应用程序只需很少的时间。Spring Boot 建立在 Spring 之上,包含 Spring 的所有功能。如今,它正成为开发人员的最爱,因为它是一个…...
解决 Git 默认不区分文件名大小写的问题
不得不说 Git 默认不区分文件名大小写真是一个大坑,由于之前的项目目录比较乱,项目下的文件夹命名都不规范,这两天一直在整理,然后今天从服务器将项目重新 clone 下来后发现,之前将所有文件名首字母改成大写的改动全部…...
python学opencv|读取图像(十二)BGR图像转HSV图像
【1】引言 前述已经学习了opencv中图像BGR相关知识,文章链接包括且不限于下述: python学opencv|读取图像(六)读取图像像素RGB值_opencv读取灰度图-CSDN博客 python学opencv|读取图像(七)抓取像素数据顺利…...
信息安全工程师-选择题考点总结
密码理论知识 基础理论 一个密码系统至少由明文、密文、加密算法、解密算法和密钥五个部分组成,而其安全性是由密钥决定的。 按照密钥特征的不同,密码体制分为:对称密码体制和非对称密码体制。 按照对明文加密方式的不同,密码体制分为:流密码和分组密码。 非对称密码体…...
重学SpringBoot3-WebClient配置与使用详解
更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-WebClient配置与使用详解 1. 简介2. 环境准备2.1 依赖配置 3. WebClient配置3.1 基础配置3.2 高级配置3.3 retrieve()和exchange()区别 4. 使用示例4.1 …...
springBoot中的日志级别在哪里配置
在Spring Boot中,日志级别的配置可以通过多种方式来实现,主要包括在配置文件中设置、使用自定义的logback配置文件,以及在代码中动态配置等。以下是一些具体的配置方法: 一、在配置文件中设置日志级别 Spring Boot默认使用appli…...
统一身份安全管理体系的业务协同能力
随着集团企业数字化组织转型深化,各组织机构间业务协同程度提升。研发业务协同、数据驱动生产决策等数字化生产协作工作体系得以展开,企业内数据流转加快。企业对统一身份安全管理体系的业务协同管理和支撑能力要求提升: 统一身份管理流程需…...
JAVA课堂笔记23(IO流 (java.io包中))
第五章:IO流 (java.io包中) 三、字符流 1. 字符流的父类(抽象类): Reader:字符输入流 对应的操作为读操作 功能方法:read方法 Writer:字符输出流 对应的操作为写操作 功能方法:write方法 …...
C# DLT645 97/07数据采集工具
电表模拟器 97协议测试 07协议测试 private void btnSend_Click(object sender, EventArgs e) {string addr txtAddr.Text.Trim();string data txtDataFlg.Text.Trim();byte control 0x01;switch (cmbControl.SelectedIndex){case 0: control (byte)0x01; break;// 97协议c…...
中后台管理信息系统:Axure12套高效原型设计框架模板全解析
中后台管理信息系统作为企业内部管理的核心支撑,其设计与实现对于提升企业的运营效率与决策能力具有至关重要的作用。为了满足多样化的中后台管理系统开发需求,一套全面、灵活的原型设计方案显得尤为重要。本文将深入探讨中后台管理信息系统通用原型方案…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
