項目中需要將一段文字,與人員的簽名(圖片)插入到上傳的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[] {});
}
