后台生成单个Word文档
在实际项目开发中经常会遇到一种场景,客户希望点击页面上的生成文件按钮,执行程序动态填充数据到Word模板,直接在后台生成Word文档,而无需显示Word文档。目前网上有一些针对此需求的方案,但每个方案都存在很多各自的问题。
与其他方案对比
采用 Jacob 生成Word文档方案动态生成的Word文档,与PageOffice一样,文档格式是最完美的,因为都是调用的Office原生接口生成的文件,所以生成的是原汁原味的Word文档,但是Jacob局限于 windows 平台,往往许多 Java 程序运行于 Linux 等其他操作系统,而且Jacob的代码复杂、运行稳定性差且不安全,因为调用Office的自动化接口需要服务器端安装Office软件,服务器自动化调用有很大的风险,容易导致Office进程死锁、页面无响应、阻塞Web服务进程,从而影响整个网站的吞吐量,如果再考虑到多个用户同时并发操作生成Word文档的情况,Jacob程序对服务器端造成的压力足以卡死整个网站,并且Web Server需配置交互账户权限。针对这个问题,微软在MSDN上公开声明Word、Excel不适宜运行在服务进程里,因为Word、Excel仅被设计为桌面运行的程序。而PageOffice在客户端运行,100%的标准托管代码,服务器端不用安装Office,也不用引入自动化类型库,所以运行安全稳定,不必担心Web服务崩溃的风险。另外服务器自动化调用的API接口复杂难用,参数传递繁琐;而PageOffice提供了简化的对象调用模型,所以调用代码简单,开发效率高,运行稳定可靠。服务器自动化编程对于定位Word、Excel要填充内容的位置和定位要读取内容的位置比较困难,而PageOffice的简易对象模型可以轻松定位,精确填充和读取文档内容。所以Jacob已经是一个十几年前就淘汰的技术,仅限于个人研究,无法应用于实际项目。
再就是使用OpenXML SDK、POI、iText等开源库的方案。OpenXML SDK是Microsoft提供的一组库和工具,用于创建、修改和提取Office Open XML格式的文件,但是操作OpenXML SDK需要对Open XML文档结构有一定的了解,因此在处理Word文档时可能需要编写大量的代码,使用OpenXML SDK还需要学习Open XML标记语言和SDK的API,这可能需要一些时间和精力来掌握,并且由于 OpenXML SDK 是用 C# 编写的,因此在 Java 中直接调用 OpenXML SDK 是很困难的。而使用 POI 生成文档对服务器的压力很大,而且它的 Excel 处理勉强可以, Word 模块还局限于读取 Word 的文本内容,写 Word 文件的功能就更弱;另一个致命的问题是,处理 doc 格式和处理 docx 格式的类几乎完全不同,要分开针对不同的格式写不同的代码,这就意味着用户上传的 docx 格式文件如果使用了 doc 的扩展名,程序马上崩溃。目前已知POI用来解析.doc、.xls那部分的组件是残缺不全的并且也已经不再更新了。而且 POI 结构混乱,编码比较复杂,开发过程非常消耗时间和精力。从性能上看,POI使用的xml处理对象本身就消耗内存,它要把整个文档都加载到内存,加上其他开销,比实际Word、Excel文档还大,遇到打开较大的Word、Excel文档时,JVM很容易内存溢出。而iText是一个用于处理PDF文件的Java库,它是可以操作Word文档,但是iText主要是用来处理PDF文档的,不支持Excel,且对于Word支持很有限,iText 生成的 Word 文件在不同版本的 Word 软件中可能会出现排版或样式兼容性的问题。iText 也需要较大的学习曲线,特别是对于没有使用过该库的开发人员来说。总的来说,使用开源库方案存在调用代码复杂、中文乱码,功能较弱等许多问题,最大的问题还是在生成文件的格式、样式、排版等方面存在很大问题,由于这些方案不是直接调用原生Office接口操作文件内容的,所以即使已经有一个模板文档做基础了,但是生成的文档中字体、样式、段落等还是会出现错乱的情况,尤其是处理页眉页脚、表格等内容时,出现的排版格式问题会更大。
所以针对这一系列的问题,PageOffice 开发了 FileMaker 组件,该组件完全符合 PageOffice 的架构设计,提供了最简单的对象模型,没有任何学习成本。FileMaker 在客户端后台填充数据到Office模板生成文档并自动上传到服务器,不会打开显示生成的文档。由于FileMaker是调用Office原生接口操作文档内容的,所以生成的是原汁原味的Office文档格式,而且由于FileMaker调用的是客户端电脑上的Office,所以服务器上无需安装Office软件,也不要求服务器必须是Windows平台,生成文档的工作不会对服务器端造成任何压力,更不存在并发问题,实现了完美生成文档的目的,且避免了上述的所有问题。
FileMakerCtrl 和 PageOfficeCtrl 的区别
FileMakerCtrl 本质上就是一个没有界面的 PageOfficeCtrl,也是调用客户端 Office 程序处理文件的,FileMakerCtrl和PageOfficeCtrl都可以实现对文档进行动态填充、动态转 PDF 等功能,唯一的区别就是 FileMakerCtrl 在线打开填充和转换文档的时候,Web页面不会打开显示文档内容,而 PageOfficeCtrl 会弹出窗口打开显示文档内容。
PageOffice的解决方案
下面就以生成一份荣誉证书的效果为例,介绍一下如何使用FileMaker组件动态生成Word文档。
需求效果:用户点击生成word文件按钮,执行程序把某公司信息动态填充到荣誉证书模板中,生成一份荣誉证书文件。
荣誉证书模板如下图所示,为了简单起见,模板中只使用了公司名称来代表公司的所有信息,所以只用了一个数据区域“PO_company”来标记公司名称的位置。
点击按钮后,执行把公司信息动态填充到Word模板中生成荣誉证书的后台代码(比如:FileMakerSingle.jsp),在服务器端文件夹下生成一份荣誉证书文件:maker.doc,文件内容如下图所示。
后端代码
- 在后端编写代码实现文档动态填充(比如FileMakerSingle.jsp),关键代码如下:
// 获取id后可以根据id从数据库中查询公司信息,为简单起见,就不再演示
String id = request.getParameter("id");
FileMakerCtrl fmCtrl = new FileMakerCtrl(request);
WordDocument doc = new WordDocument();
//给数据区域赋值,即把数据填充到模板中相应的位置
doc.openDataRegion("PO_company").setValue("北京卓正志远软件有限公司");
fmCtrl.setSaveFilePage("SaveMaker.jsp");
fmCtrl.setWriter(doc);
fmCtrl.fillDocument("doc/template.doc", DocumentOpenType.Word);
- 保存文件:在SaveFilePage指向的地址接口中,创建FileSaver对象保存文件。
FileSaver fs = new FileSaver(request, response);
String fileName = "maker" + fs.getFileExtName();
fs.saveToFile(request.getSession().getServletContext().getRealPath("FileMakerSingle/doc") + "/" + fileName);
fs.close();
前端代码
编写前端网页代码,调用执行后端生成文件代码,并实现生成文件进度条的效果。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<script type="text/javascript" src="../pageoffice.js"></script>
<script type="text/javascript">
function ConvertFile() {
document.getElementById("Button1").disabled = true;
CallFileMaker({
url: "FileMakerSingle.jsp?id=1", //FileMakerSingle.jsp实现动态生成文件
success: function () {
setProgress(100);
},
progress: function (pos) {
setProgress(pos);
},
error: function (msg) {
console.log("error occurred: "+msg);
}
});
}
function setProgress(percent) {
var progressBar = document.getElementById("progressBar");
progressBar.style.width = percent + '%';
progressBar.innerText = percent + '%';
}
</script>
<style>
#progressBarContainer {
width: 500px;
background-color: #e0e0e0;
border-radius: 5px;
padding: 3px;
margin: 10px auto;
}
#progressBar {
height: 20px;
width: 0%;
background-color: #76b900;
border-radius: 5px;
text-align: center;
line-height: 20px; /* 使文字垂直居中 */
color: white;
}
</style>
</head>
<body>
<div style="text-align: center;">
<input id="Button1" type="button" value="生成Word文件" onclick="ConvertFile()"/>
<div id="progressBarContainer">
<div id="progressBar"></div>
</div>
</div>
</body>
</html>
参考链接:后台生成单个Word文档
后台生成单个Word文档的更多相关文章
- Android开发——使用Jword生成本地word文档
本文主要介绍如何使用Jword生成本地word文档,这里涉及到Jword的使用技巧,本文给出相应的代码,需要的朋友可以参考下. 为什么使用Jword呢?因为IText .Freemark在安卓平台上压 ...
- java生成复杂word文档
在Web应用中,有时需要按照固定的模板将数据导出到Word,如流程审批单,在流程处理完成后将处理过程按照流程单的要求导出,有时程序中需要实现生成 标准Word文档,要求能够打印,并且保持页面样式不变, ...
- 调用Microsoft.Office.Interop.Word生成自定义Word文档
具体思路: 1.先制作Word模版,使用文本框+书签的方式来设计模版: 2.模版制作完之后,根据模版生成新文件,使用File.Copy方法,生成.doc格式新文件: 3.后台取得数据,参照网页渲染的方 ...
- NPOI插件生成导出word文档
因为之前没有接触NPOI过这个插件,所以几乎都是自己一边百度摸索一边学习. 这个插件对于Excel的数据导入和导出,可以说是很方便了, 但是对于导出word文档,可以说是很少的,百度了很多....也不 ...
- 向Docx4j生成的word文档添加图片和布局--第一部分
原文标题:Adding images and layout to your Docx4j-generated word documents, part 1 原文链接:http://blog.iprof ...
- 前端调用后台接口下载word文档的两种方法
1传统的ajax虽然能提交到后台,但是返回的数据被解析成json,html,text等字符串,无法响应浏览器下载.就算使用bob模拟下载,数据量大时也不方便 废话不多说:上代码(此处是Layui监听提 ...
- 向Docx4j生成的word文档中添加布局--第二部分
原文标题:Adding layout to your Docx4j-generated word documents, part 2 原文链接:http://blog.iprofs.nl/2012/1 ...
- [转载]Java动态生成word文档(图文并茂)
很多情况下,软件开发者需要从数据库读取数据,然后将数据动态填充到手工预先准备好的Word模板文档里,这对于大批量生成拥有相同格式排版的正式文件非常有用,这个功能应用PageOffice的基本动态填充功 ...
- [原创]Java动态生成word文档(图文并茂)
很多情况下,软件开发者需要从数据库读取数据,然后将数据动态填充到手工预先准备好的Word模板文档里,这对于大批量生成拥有相同格式排版的正式文件非常有用,这个功能应用PageOffice的基本动态填充功 ...
- JAVAWEB使用FreeMarker利用ftl把含有图片的word模板生成word文档,然后打包成压缩包进行下载
这是写的另一个导出word方法:https://www.cnblogs.com/pxblog/p/13072711.html 引入jar包,freemarker.jar.apache-ant-zip- ...
随机推荐
- 数据库操作入门:PyMongo 和 MongoDB 的基本用法
MongoDB MongoDB是一种流行的NoSQL数据库,它将数据存储在类似JSON的文档中,使数据库非常灵活和可扩展 PyMongo Python需要一个MongoDB驱动程序来访问MongoDB ...
- 详解Java Chassis 3与Spring Cloud的互操作
本文分享自华为云社区<Java Chassis 3技术解密:与Spring Cloud的互操作>,作者: liubao68. Java Chassis 3一个很重要的设计原则:利用架构的韧 ...
- HDC2021技术分论坛:吐司盒子?芝士码?HarmonyOS音视频测试来啦
作者:lifusheng,用户体验技术专家 当下,音视频无处不在,很多设备和应用都涉及音视频.因而,对于HarmonyOS开发者们来说,如何对鸿蒙生态产品进行音视频测试是一个非常重要的问题. 华为Ha ...
- mysql 必知必会整理—sql 通配符[四]
前言 简单介绍一下sql 高级过滤. 正文 首先简单介绍一下通配符,用来匹配值的一部分的特殊字符. 搜索模式(search pattern)① 由字面值.通配符或两者组合构成的搜索条件. 前面介绍操作 ...
- Unable to determine application id: com.android.tools.idea.run.ApkProvisionException: No outputs for the main artifact of variant: debug
前言 遇到这种情况极大可能属于gradle 与 android studio版本不匹配的情况. 因为我是在升级android studio遇到的这个问题. 方法 一个方法是:降低android stu ...
- VulnHub-Jangow-01-1.0.1打靶记录
知识点 NMAP参数 -sV 获取系统信息 -sT TCP扫描可能会留下日志记录 -sC 使用默认脚本(在-A模式下不需要) -p1-xxx 扫描端口号 -p- ==>等价于 -p1-65535 ...
- leetcode:763. 划分字母区间
763. 划分字母区间 字符串 S 由小写字母组成.我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段.返回一个表示每个字符串片段的长度的列表. 示例 1: 输入: S = & ...
- 好的 MySQL 兼容性可以做到什么程度? PolarDB-X 如何做生态兼容
简介: 2003 年淘宝网成立之后,业务飞速发展,其后台架构也进行了多次迭代.2009 年之前,淘宝网后台的数据库架构是经典的 IOE 组合.IOE 是指 IBM 的小型机. Oracle 的数据库加 ...
- 如何使用 PTS 快速发起微服务压测
简介:本文讲阐述什么是微服务架构.微服务架构对系统稳定性带来的影响,以及用性能测试验证稳定性的必要性.用户进行微服务压测的痛点和 PTS 的独特优势.云上使用 PTS 快速发起微服务压测的步骤,以及 ...
- 好云推荐官丨飞天加速之星怎样选择云服务器ECS?
编者按:本文来自"好云推荐官"活动的技术博主投稿,作者(昵称天狼)曾入选首届"飞天加速之星",获得飞天人气奖. 你是否还在苦苦地寻找一家合适的云厂商,寻找合 ...