vue前端实现导出页面为word(两种方法)
将vue页面导出为word文档,不用写模板,直接导出即可。
第一种方法(简单版)
第一步:安装所需依赖
npm install html-docx-js -S
npm install file-saver -S
第二步:创建容器,页面使用方法(简单版:导出内容为纯文字,没有表格、图片这些东西)
第二步:创建容器,页面使用方法(复杂版:导出内容带有表格和图片的情况 【使用了tinymce富文本编辑器会有表格和图片,然后需要导出带有表格和图片的word文档】)
注意:使用v-html更新元素的 innerHTML,html结构会被解析为标签
以下是需要导出的内容(exportContent):
<div id="managerReport"class="checkInfoStyle"><div v-html="exportContent"></div></div>
把exportContent 内容导出为word文档
下边直接写导出方法了:
// 第一种方法wordDownload1 () {this.$nextTick(() => {const htmlContent = document.getElementById("managerReport") // managerReport id要对应// 注意:直接导出表格没有边框并且不是100%撑满的,所以需要做以下的处理// 查找并修改表格的样式const tables = htmlContent.querySelectorAll('table');tables.forEach(table => {table.style.borderCollapse = 'collapse'table.style.width = '100%'table.querySelectorAll('td, th').forEach((cell, index) => {if (cell){cell.style.border = '1px solid black'cell.style.padding = '8px'}})})// 拿到需要导出的内容let htmlString = htmlContent.innerHTML// 注意:以下操作是为了解决导出内容为两端对齐的情况,如果导出内容某一行中有几个字,那这几个字就会两端对齐,格式就错乱了// 考虑到是因为<br>标签才会两端对齐,所以做如下的操作(去除<br>标签[br标签是换行标签],把内容加到<div>标签内)const regex = /([^>]*?)<br.*?>/gi; // 找到结束标签 ‘ <br /> ’ 和开始标签 ‘ > ’ 中间的内容,把这部分内容放到div标签内htmlString = htmlString.replace(regex, (match, p1) => { // p1就是找到的br标签中间的内容let ret = ''if (p1.trim()){ret += `<div>${p1}</div>` // 把找到的内容放到div标签内} else {ret += `<div> </div>` // 不加此步骤,如果导出内容中间有空行就会解析不了,直接吞掉空行了}return ret})// 将HTML转换为Blob对象const blob = htmlDocx.asBlob(htmlString);saveAs(blob, `${this.editData.cTopicC}(${this.editData.dDate}).docx`)})},// 第二种方法wordDownload2 () {this.$nextTick(() => {const htmlContent = document.getElementById("managerReport")// 查找并修改表格的样式const tables = htmlContent.querySelectorAll('table')tables.forEach(table => {table.style.borderCollapse = 'collapse'table.style.width = '100%'table.querySelectorAll('td, th').forEach((cell, index) => {if (cell){cell.style.border = '1px solid black'cell.style.padding = '8px'}})})//去除<br>标签,内容加到<div>标签内const brs = htmlContent.querySelectorAll('br')brs.forEach(br => {const parent = br.parentNode //获取父节点let textNode = br.previousSibling //前一个兄弟节点// while (textNode && textNode.nodeType !== Node.TEXT_NODE) {// textNode = textNode.previousSibling; //循环查找,直到找到一个文本节点或没有更多的兄弟节点// }if (textNode && textNode.nodeType === Node.TEXT_NODE && textNode.textContent.trim()){ //找到文本节点,并且内容不为空const div = document.createElement('div')div.textContent = textNode.textContentparent.insertBefore(div, br)parent.removeChild(textNode) //移除原有的文本节点,避免内容重复} else {const div = document.createElement('div')div.innerHTML = ' 'parent.insertBefore(div, br)}parent.removeChild(br)})const htmlContentCopy = htmlContent.cloneNode(true)const imgs = htmlContentCopy.querySelectorAll('img')imgs.forEach(img => {let docxWidth = 620if (img.width > docxWidth){img.height = img.height * docxWidth / img.widthimg.width = docxWidth}})// 将HTML转换为Blob对象const blob = htmlDocx.asBlob(htmlContentCopy.innerHTML)saveAs(blob, `${this.editData.cTopicC}(${this.editData.dDate}).docx`)})},
注意:在当前页面引入依赖
import FileSaver from "file-saver";
import htmlDocx from "html-docx-js/dist/html-docx";**
问题:用此方法,最近遇到了一个问题,就是导出内容很少的情况,比如:导出内容只有一行或者两行、三行,并且每行只有几个字的情况,导出内容就成乱码了。如果有遇到此种情况并且有解决方案的大佬,感谢评论区分享。
第二种方法(需要使用jquery)
第一步:安装所需依赖
npm install jquery --save
npm install file-saver
第二步:创建两个js文件,一个是jquery文件(jq.js),一个是插件js的文件(jquery.wordexport.js),我把这两个js文件都放到utils文件夹下,注意:使用的时候一定要注意引用路径。这两个js文件代码我都放到文章最后(有一个插件没有依赖包,所以需要自己创建一个js文件(jquery.wordexport.js))
第三步:在需要导出的页面引入文件
import $ from "@/utils/jq"; // 文件引入路径一定要正确,这是第二步创建的js文件(jq.js)
import saveAs from "file-saver/dist/FileSaver";
import "@/utils/jquery.wordexport"; // 文件引入路径一定要正确,这是第二步创建的js文件(jquery.wordexport.js)
第四步:页面使用方法
注意:如果导出的时候出现bug,大多是因为文件路径引入有问题,再次排查路径引入
jq.js
import $ from "jquery";window.$ = $;window.jQuery = $;
export default $;
jquery.wordexport.js
if (typeof jQuery !== "undefined" && typeof saveAs !== "undefined") {(function ($) {$.fn.wordExport = function (fileName) {fileName = typeof fileName !== 'undefined' ? fileName : "jQuery-Word-Export";var static = {mhtml: {top:"Mime-Version: 1.0
Content-Base: " +location.href +'
Content-Type: Multipart/related; boundary="NEXT.ITEM-BOUNDARY";type="text/html"--NEXT.ITEM-BOUNDARY
Content-Type: text/html; charset="utf-8"
Content-Location: ' +location.href +"<!DOCTYPE html>
" +'<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
_html_</html>',head:'<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
_styles_
</style>
<!--[if gte mso 9]><xml><w:WordDocument><w:View>Print</w:View><w:TrackMoves>false</w:TrackMoves><w:TrackFormatting/><w:ValidateAgainstSchemas/><w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid><w:IgnoreMixedContent>false</w:IgnoreMixedContent><w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText><w:DoNotPromoteQF/><w:LidThemeOther>EN-US</w:LidThemeOther><w:LidThemeAsian>ZH-CN</w:LidThemeAsian><w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript><w:Compatibility><w:BreakWrappedTables/><w:SnapToGridInCell/><w:WrapTextWithPunct/><w:UseAsianBreakRules/><w:DontGrowAutofit/><w:SplitPgBreakAndParaMark/><w:DontVertAlignCellWithSp/><w:DontBreakConstrainedForcedTables/><w:DontVertAlignInTxbx/><w:Word11KerningPairs/><w:CachedColBalance/><w:UseFELayout/></w:Compatibility><w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel><m:mathPr><m:mathFont m:val="Cambria Math"/><m:brkBin m:val="before"/><m:brkBinSub m:val="--"/><m:smallFrac m:val="off"/><m:dispDef/><m:lMargin m:val="0"/> <m:rMargin m:val="0"/><m:defJc m:val="centerGroup"/><m:wrapIndent m:val="1440"/><m:intLim m:val="subSup"/><m:naryLim m:val="undOvr"/></m:mathPr></w:WordDocument></xml><![endif]--></head>
',body: "<body>_body_</body>",},};var options = {maxWidth: 624,//最大宽度};// Clone selected element before manipulating itvar markup = $(this).clone();// Remove hidden elements from the outputmarkup.each(function () {var self = $(this);if (self.is(':hidden'))self.remove();});// Embed all images using Data URLsvar images = Array();var img = markup.find('img');// var img = new Image(); 用这一行的话,WPS不显示图片,用上面的——只兼容office Word。var mhtmlBottom = "
";for (var i = 0; i < img.length; i++) {// Calculate dimensions of output imagevar w = Math.min(img[i].width == 0 ? options.maxWidth : img[i].width, options.maxWidth);var h = (img[i].height == 0 ? options.defaultLength : img[i].height) * (w / (img[i].width == 0 ? options.maxWidth : img[i].width));// Create canvas for converting image to data URLvar canvas = document.createElement("CANVAS");canvas.width = w;canvas.height = h;// Draw image to canvasvar context = canvas.getContext('2d');context.drawImage(img[i], 0, 0, w, h);// Get data URL encoding of imagevar uri = canvas.toDataURL("image/png");// console.log(i+":"+uri);$(img[i]).attr("src", img[i].src);img[i].width = w;img[i].height = h;mhtmlBottom += "--NEXT.ITEM-BOUNDARY
";mhtmlBottom += "Content-Location: " + uri + "
";mhtmlBottom += "Content-Type: " + uri.substring(uri.indexOf(":") + 1, uri.indexOf(";")) + "
";mhtmlBottom += "Content-Transfer-Encoding: " + uri.substring(uri.indexOf(";") + 1, uri.indexOf(",")) + "";mhtmlBottom += uri.substring(uri.indexOf(",") + 1) + "";}mhtmlBottom += "--NEXT.ITEM-BOUNDARY--";//TODO: load css from included stylesheetvar styles = "";// Aggregate parts of the file togethervar fileContent = static.mhtml.top.replace("_html_", static.mhtml.head.replace("_styles_", styles) + static.mhtml.body.replace("_body_", markup.html())) + mhtmlBottom;// Create a Blob with the file contentsvar blob = new Blob([fileContent], {type: "application/msword;charset=utf-8"});saveAs(blob, fileName + ".doc"); // 注意:不要改成docx,不然会打不开!!!};})(jQuery);
} else {if (typeof jQuery === "undefined") {console.error("jQuery Word Export: missing dependency (jQuery)");}if (typeof saveAs === "undefined") {console.error("jQuery Word Export: missing dependency (FileSaver.js)");}
}
相关文章:

vue前端实现导出页面为word(两种方法)
将vue页面导出为word文档,不用写模板,直接导出即可。 第一种方法(简单版) 第一步:安装所需依赖 npm install html-docx-js -S npm install file-saver -S第二步:创建容器,页面使用方法(简单版࿱…...

22. Three.js案例-创建旋转的圆环面
22. Three.js案例-创建旋转的圆环面 实现效果 知识点 WebGLRenderer (WebGL渲染器) THREE.WebGLRenderer 是Three.js中最常用的渲染器,用于将场景渲染到WebGL画布上。 构造器 new THREE.WebGLRenderer(parameters) 参数类型描述parametersObject可选参数对象&…...

Elasticsearch:使用阿里 infererence API 及 semantic text 进行向量搜索
在之前的文章 “Elasticsearch 开放推理 API 新增阿里云 AI 搜索支持”,它详细描述了如何使用 Elastic inference API 来针对阿里的密集向量模型,稀疏向量模型, 重新排名及 completion 进行展示。在那篇文章里,它使用了很多的英文…...

Linux WEB服务器的部署及优化
1.用户常用关于web的信息 1.1.什么是www www是world wide web的缩写,及万维网,也就是全球信息广播的意思。 通常说的上网就是使用www来查询用户所需要的信息。 www可以结合文字、图形、影像以及声音等多媒体,超链接的方式将信息以Internet…...

人工智能大模型LLM开源资源汇总(持续更新)
说明 目前是大范围整理阶段,所以存在大量机翻说明,后续会逐渐补充和完善资料,减少机翻并增加说明。 Github上的汇总资源(大部分英文) awesome-production-machine-learning 此存储库包含一系列精选的优秀开源库&am…...

目标跟踪算法:SORT、卡尔曼滤波、匈牙利算法
目录 1 目标检测 2 卡尔曼滤波 3《从放弃到精通!卡尔曼滤波从理论到实践》视频简单学习笔记 3.1 入门 3.2 进阶 3.2.1 状态空间表达式 3.2.2 高斯分布 3.3 放弃 3.4 精通 4 匈牙利算法 5 《【运筹学】-指派问题(匈牙利算法)》视…...

Java版-图论-拓扑排序与有向无环图
拓扑排序 拓扑排序说明 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列…...

GTC2024 回顾 | 优阅达携手 HubSpot 亮相上海,赋能企业数字营销与全球业务增长
从初创企业入门到成长型企业拓展,再到 AI 驱动智能化运营,HubSpot 为企业的每步成长提供了全方位支持。 2024 年 11 月下旬,备受瞩目的 GTC2024 全球流量大会(上海)成功举办。本次大会汇聚了全国内多家跨境出海领域企业…...

eclipse启动的时候,之前一切很正常,但突然报Reason: Failed to determine a suitable driver class的解决
1、之前项目都是启动正常的,然后运行以后发现启动不了了,还会报错: 2、这个Reason: Failed to determine a suitable driver class,说是没有合适的驱动class spring:datasource:url: jdbc:sqlserver://192.168.1.101:1433;databa…...
_tkinter.TclError: can‘t find package tkdnd Unable to load tkdnd library.解决办法
Traceback (most recent call last): File “tkinterdnd2\TkinterDnD.py”, line 55, in _require _tkinter.TclError: can’t find package tkdnd During handling of the above exception, another exception occurred: Traceback (most recent call last): File “1.导入总表…...

VBA高级应用30例应用在Excel中的ListObject对象:向表中添加注释
《VBA高级应用30例》(版权10178985),是我推出的第十套教程,教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开,这套教程案例与理论结合,紧贴“实战”,并做“战术总结”,以…...
folly库Conv类型转换源码解析
1,普通类型转换 例子1: bool boolV = true;EXPECT_EQ(to<bool>(boolV), true);int intV = 42;EXPECT_EQ(to<int>(intV), 42);float floatV = 4.2f;EXPECT_EQ(to<float>(floatV), 4.2f);double doubleV = 0.42;EXPECT_EQ(to<double>(doubleV), 0.42)…...
UE4 骨骼网格体合并及规范
实现代码 // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "SkeletalMeshMerge.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "AceMeshCom…...

Java版企业电子招标采购系统源业码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis
功能描述 1、门户管理:所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含:招标公告、非招标公告、系统通知、政策法规。 2、立项管理:企业用户可对需要采购的项目进行立项申请,并提交审批,查看所…...
通过源码⼀步⼀步分析 ArrayList 扩容机制
ArrayList 是 Java 中常用的集合类,它底层实现是基于数组的。为了处理元素的动态增加,ArrayList 会在容量不足时进行扩容。以下是通过源码逐步分析 ArrayList 扩容机制的过程。 1. ArrayList 类的基本结构 ArrayList 继承自 AbstractList,实…...
源码分析之Openlayers中默认Controls控件渲染原理
概述 Openlayers 中默认的三类控件是Zoom、Rotate和Attribution 源码分析 defaults方法 Openlayers 默认控件的集成封装在defaults方法中,该方法会返回一个Collection的实例,Collection是一个基于数组封装了一些方法,主要涉及到数组项的添…...
中间件的分类与实践:从消息到缓存
目录 一. 中间件的基本概念 二. 中间件的主要类型 (1)消息中间件(Message-Oriented Middleware, MOM): (2)数据库中间件: (3)Web中间件: &a…...

京东e卡 h5st 4.96
声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 有相关问题请第一时间头像私信联系我删…...
《CSS 知识点》滚动条仅在 hover 时才显示(宽度不改变)
很简单! 滚动条的滑动小方块背景色默认透明,仅在hover时设置背景色; 滚动条的轨道背景色默认透明,仅在hover时设置背景色; /*滚动条的滑动小方块*/ ::-webkit-scrollbar-thumb {background: transparent; } /*hover…...

手里有病理切片+单细胞测序的数据,如何开展医工交叉的研究?
小罗碎碎念 这一期推文研究一个问题:病理如何与单细胞结合? 病理与单细胞的结合,时常出现在今年的各大顶刊中。 关于这一领域的研究,其实19年就开始了。我把部分低质量的文献做了剔除,但是也基本能反应这一领域的受关注…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...