分别使用docx4j,jacob将文字与图片插入word中书签位置
项目中需要将一段文字,与人员的签名(图片)插入到上传的word中,上网查询了一下,有许多种方式可以向word中插入文字,发现docx4j与jacob都为比较常见的解决方案,于是就先使用的docx4j进行了文字与图片的插入,在自己开发的机器上docx4j插入文字与图片均成功了,但是在部署到服务器上的时候,使用docx4j插入图片的时候,一直出现一个图片无法插入的bug,没有解决掉,于是就又使用的jacob进行尝试,然后成功了。将两种对word进行操作的工具进行一下总结。
安装: docx4j要简单于jacob。docx4j只需要pom文件中添加即可,jacob需要pom添加后在本机jre的bin目录下安装一个dll文件。
代码量:两者使用同一功能的代码量差不多。
资料:百度下jacob的资料要比docx4j多一些,docx4j英文的资料多一些,在github下也可以找到docx4j。
一、docx4j的插入操作
docx4j安装时候,只需要向pom中添加依赖即可。
pom文件:
<groupId>org.docx4j</groupId>
<artifactId>docx4j</artifactId>
<version>3.3.1</version>
</dependency>
插入图片:
/**
* Method Description:使用docx4j插入图片
*
* @param templatePath
* // 模板文件路径
* @param targetPath
* // 生成的文件路径
* @param bookmarkName
* // 书签名
* @param imagePath
* void // 图片路径
* @throws Exception
* @Author: 张昊亮
* @Date: 2018年5月17日 下午4:17:20
*/
public void insertPicture(String templatePath, String targetPath, String bookmarkName, String imagePath) throws Exception { // 载入模板文件
WordprocessingMLPackage wPackage = WordprocessingMLPackage.load(new FileInputStream(templatePath));
// 提取正文
MainDocumentPart mainDocumentPart = wPackage.getMainDocumentPart();
Document wmlDoc = (Document) mainDocumentPart.getJaxbElement();
Body body = wmlDoc.getBody();
// 提取正文中所有段落
List<Object> paragraphs = body.getContent();
// 提取书签并创建书签的游标
RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
new TraversalUtil(paragraphs, rt);
// 遍历书签
for (CTBookmark bm : rt.getStarts()) {
// 这儿可以对单个书签进行操作,也可以用一个map对所有的书签进行处理
if (bm.getName().equals(bookmarkName)) {
// 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
InputStream is = new FileInputStream(imagePath);
byte[] bytes = IOUtils.toByteArray(is);
// 创建一个行内图片
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
// createImageInline函数的前四个参数我都没有找到具体啥意思
// 最有一个是限制图片的宽度,缩放的依据
Inline inline = imagePart.createImageInline(null, null, 0, 1, false, 800);
// 获取该书签的父级段落
P p = (P) (bm.getParent());
ObjectFactory factory = new ObjectFactory();
// R对象是匿名的复杂类型,然而我并不知道具体啥意思,估计这个要好好去看看ooxml才知道
R run = factory.createR();
// drawing理解为画布
Drawing drawing = factory.createDrawing();
drawing.getAnchorOrInline().add(inline);
run.getContent().add(drawing);
p.getContent().add(run);
}
}
wPackage.save(new FileOutputStream(targetPath));
}
插入文字:
/**
* Method Description:使用docx4j插入文字
*
* @param templatePath
* //模板文件位置
* @param targetPath
* //生成文件位置
* @param words
* //添加的文字内容
* @param bookmarkName
* //书签名称
* @throws Docx4JException
* @throws FileNotFoundException
*
* @Author: 张昊亮
* @Date: 2018年5月21日 上午10:02:51
*/
public void insertWords(String templatePath, String targetPath, String words, String bookmarkName) throws FileNotFoundException,
Docx4JException { // 载入模板文件
WordprocessingMLPackage wPackage = WordprocessingMLPackage.load(new FileInputStream(templatePath));
// 提取正文
MainDocumentPart mainDocumentPart = wPackage.getMainDocumentPart();
Document wmlDoc = (Document) mainDocumentPart.getJaxbElement();
Body body = wmlDoc.getBody();
// 提取正文中所有段落
List<Object> paragraphs = body.getContent();
// 提取书签并创建书签的游标
RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
new TraversalUtil(paragraphs, rt);
// 遍历书签
for (CTBookmark bm : rt.getStarts()) {
// 这儿可以对单个书签进行操作,也可以用一个map对所有的书签进行处理
if (bm.getName().equals(bookmarkName)) {
ObjectFactory factory = new ObjectFactory();
P p = (P) (bm.getParent()); // 添加到了标签处
R r = factory.createR();
Text t = new Text();
t.setValue(words);
r.getContent().add(t);
p.getContent().add(r);
wPackage.getMainDocumentPart().getContent().add(p);
}
}
wPackage.save(new FileOutputStream(targetPath));
}
二、使用jacob进行插入操作
jacob在安装的时候需要,有jar包还有dll文件。
jacob包文件下载:链接:https://pan.baidu.com/s/1v0ZYsVYSu_BO5rB252ufvA 密码:mlfs

<dependency>
<groupId>com.jacob</groupId>
<artifactId>jacob</artifactId>
<version>1.18</version>
</dependency>
maven项目,添加pom依赖后,需要将jacob-1.18-x64.dll 文件放入项目所在电脑的jre的bin目录下,方可运行。
插入图片:
注:图片在资料中没有查询到的在书签位置插入,而是使用的用图片去替换文字。
/**
* Method Description:使用jacob插入图片
*
* @param templatePath
* //模板文件位置
* @param targetPath
* //生成文件位置
* @param word
* // 查询文字的地方
* @param imagePath
* void // 图片路径
*
* @Author: 张昊亮
* @Date: 2018年5月23日 下午4:18:27
*/
public void insertPicByjacob(String templatePath, String targetPath, String word, String imagePath) { System.out.println("启动word...");
ActiveXComponent app = null;
Dispatch doc = null;
// 模板的路径
String openPath = templatePath;
// 要保存的文件的路径
String toFileName = targetPath;
Dispatch docs = null;
if (app == null || app.m_pDispatch == 0) {
app = new ActiveXComponent("Word.Application");
app.setProperty("Visible", new Variant(false));
app.setProperty("DisplayAlerts", new Variant(false));
}
if (docs == null) {
// 获得documents对象
docs = app.getProperty("Documents").toDispatch();
}
doc = Dispatch.invoke(docs, "Open", Dispatch.Method, new Object[] { openPath, new Variant(false), new Variant(true) }, new int[1])
.toDispatch();
System.out.println("打开文档..." + openPath);
Dispatch selection = app.getProperty("Selection").toDispatch();
Dispatch find = Dispatch.call(selection, "Find").toDispatch();// 获得Find组件
Dispatch.put(find, "Text", word); // 查找字符串
Dispatch.put(find, "MatchWholeWord", "True"); // 全字匹配
boolean bl = Dispatch.call(find, "Execute").getBoolean(); // 执行查询
if (bl) {
Dispatch inLineShapes = Dispatch.get(selection, "InLineShapes").toDispatch();
Dispatch picture = Dispatch.call(inLineShapes, "AddPicture", imagePath).toDispatch();
}
// 保存文件//new variant() 参数 0Doc 12、16Docx 17pdf
Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] { targetPath, new Variant(12) }, new int[1]);
Dispatch.call((Dispatch) doc, "Close", new Variant(false));
System.out.println("关闭文档");
if (app != null)
app.invoke("Quit", new Variant[] {});
}
插入文字:
/**
* Method Description:使用jacob插入文字
*
* @param templatePath
* //模板文件位置
* @param targetPath
* //生成文件位置
* @param words
* //要插入的内容
* @param bookmarkName
* void // 书签名
*
* @Author: 张昊亮
* @Date: 2018年5月24日 下午5:15:25
*/
public void insertWordByjacob(String templatePath, String targetPath, String words, String bookmarkName) { System.out.println("启动word...");
ActiveXComponent app = null;
Dispatch doc = null;
// 模板的路径
String openPath = templatePath;
// 要保存的文件的路径
String toFileName = targetPath;
Dispatch docs = null;
if (app == null || app.m_pDispatch == 0) {
app = new ActiveXComponent("Word.Application");
app.setProperty("Visible", new Variant(false));
app.setProperty("DisplayAlerts", new Variant(false));
}
if (docs == null) {
// 获得documents对象
docs = app.getProperty("Documents").toDispatch();
}
doc = Dispatch.invoke(docs, "Open", Dispatch.Method, new Object[] { openPath, new Variant(false), new Variant(true) }, new int[1])
.toDispatch();
System.out.println("打开文档..." + openPath);
Dispatch activeDocument = app.getProperty("ActiveDocument").toDispatch();
Dispatch bookMarks = app.call(activeDocument, "Bookmarks").toDispatch();
Dispatch rangeItem = Dispatch.call(bookMarks, "Item", bookmarkName).toDispatch();
Dispatch range = Dispatch.call(rangeItem, "Range").toDispatch();
Dispatch.put(range, "Text", new Variant(words));
// 保存文件//new variant() 参数 0Doc 12、16Docx 17pdf
Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] { targetPath, new Variant(12) }, new int[1]);
Dispatch.call((Dispatch) doc, "Close", new Variant(false));
System.out.println("关闭文档");
if (app != null)
app.invoke("Quit", new Variant[] {});
}
分别使用docx4j,jacob将文字与图片插入word中书签位置的更多相关文章
- 控制图片在latex中的位置
如何做到自己控制图片在latex中的位置? 方法:在 \begin{figure} 后面加参数 [h!] 即 \begin{figure}[h!] % Requires \usepackage{gra ...
- 解决图片插入word文档后清晰度降低的问题
解决图片插入word文档后清晰度降低的问题 在默认情况下,word程序会自动压缩插入word文档中的图片以减小整个word文档的.当我们需要插入word文档中的图片保持原始清晰度时,可以通过设置wor ...
- ppt图片在word中不能正常显示,只显示为矩形框的解决方法
word中插入的其他图片是好的,但是从ppt复制粘贴过来的图片只显示个框. 解决方法:以下红框中内容去选中.
- 把图片在word中显示
如下: //放入word中 #region word ThreadPool.QueueUserWorkItem(//使用线程池 (P_temp) =>//使用lambda表达式 { G_wa = ...
- 开发笔记:PDF生成文字和图片水印
背景 团队手里在做的一个项目,其中一个小功能是用户需要上传PDF文件到文件服务器上,都是一些合同或者技术评估文档,鉴于知识版权和防伪的目的,需要在上传的PDF文件打上水印, 这时候我们需要提供能力给客 ...
- C# 操作Word书签(二)——插入图片、表格到书签;读取、替换书签
概要 书签的设置可以帮助我们快速的定位某段文字,使用起来很方便,也很节省时间.在前一篇文章“C# 如何添加/删除Word书签”中介绍了插入.删除书签的方法,本篇文章将对C# 操作Word书签的功能做进 ...
- Java 在Word中添加多行图片水印
Word中设置水印效果时,不论是文本水印或者是图片水印都只能添加单个文字或者图片到Word页面,效果比较单一,本文通过Java代码示例介绍如何在页面中添加多行图片水印效果,即水印效果以多个图片平铺到页 ...
- 使用Emacs中的org-mode写cnblogs之图片插入
.title { text-align: center; margin-bottom: .2em } .subtitle { text-align: center; font-size: medium ...
- C#中按模板操作Word —— 如何向Word中插入图片
一.Word对象模型的重叠性分析 本文主要介绍通过书签Bookmark向Word文档中插入图片的方法.在此之前我们先简单讨论下Word对象模型的重叠性.如果你对Word对象模型还不熟悉,请参考本专栏第 ...
随机推荐
- HDU.1847 Good Luck in CET-4 Everybody! ( 博弈论 SG分析)
HDU.1847 Good Luck in CET-4 Everybody! ( 博弈论 SG分析) 题意分析 简单的SG分析 题意分析 简单的nim 博弈 博弈论快速入门 代码总览 //#inclu ...
- 前端学习 -- 内联框架iframe
内联框架iframe 可以向一个页面中引入其他的外部页面 内联框架中的内容不会被搜索引擎所检索,所以开发中尽量不要使用内联框架 <iframe></iframe> 属性: sr ...
- Web前端之Javascript详解20180330
一.javascript概述 javascript是基于对象和事件的脚本语言. 特点: 1.安全性(不允许直接访问本地硬盘(因为是被远程的浏览器解释)),它可以做的就是信息的动态交互 2.跨平台性(只 ...
- 适用于vue项目的打印插件
此方法只适用于现代浏览器,IE10以下就别用了 // 使用时请尽量在nickTick中调用此方法 //打印 export default (refs, cb) => { let cloneN i ...
- shell 循环语句
1.while 2.for 3.until 4.select while #!/bin/bash # 显示一系列数字 count=1 while [ $count -le 6 ]; do echo $ ...
- Chapter9(顺序容器) --C++Prime笔记
PS:删除元素的成员函数并不检查其参数.在删除元素之前,程序员必须确保它们是存在的. 1.迭代器的范围是[begin,end)左闭右开. 2.对构成迭代器的要求: ①它们指向同一个容器中的元素或者容器 ...
- Redis 创建多个端口 链接redis端口
默认的是6379 可以用6380,6381开启多个 1.开启 ./redis-server ../etc/redis.6380.conf & 2.链接 redis-cli -p 6380 查看 ...
- vue中的slot与slot-scope
深入理解vue中的slot与slot-scope vue+element-ui+slot-scope或原生实现可编辑表格 vue插槽详解
- Python入门系列教程(二)字符串
字符串 1.字符串输出 name = 'xiaoming' print("姓名:%s"%name) 2.字符串输入 userName = raw_input('请输入用户名:') ...
- 《设计模式》-原则二:里氏代换原则(LSP)
回顾一下上一节说的“开闭原则” 说的是 一个软件要遵循对修改关闭 对新功能扩展的原则. 这一次来说说 “里氏代换原则” 意思是说:子类型必须能代替他们的基类. 看了半天的例子 好像 是懂非懂啊...相 ...