1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Java poi实现合并word文档 兼容图片合并(java实现word导出)

Java poi实现合并word文档 兼容图片合并(java实现word导出)

时间:2022-08-15 02:06:20

相关推荐

Java poi实现合并word文档 兼容图片合并(java实现word导出)

需求,今天有个需求,实现word文档批量导出,并附带图片,这里的批量导出是指导出一份word文档存在多分相同类型的数据。实现方式,定义一份word文档模板,使用占位符方式来替换文本内容。问题,怎么实现word文档合并?,及兼容图片?

这里稍微剖析下原理:上面合并的原理是,将word文档转换为xml字符串,然后把要合并的文档的xml进行拼接,生成新的文档。之所以图片无法合并是因为xml只保存了图片的基本信息及Id,但没有保存图片的具体二进制数据。所以解决思路是如何将文档中的图片合并到目标文档中。话不多说,直接鲁代码吧!!!

这里有个简单的:/weixin_41802726/article/details/95599630

package testModel;

import java.io.ByteArrayInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.util.HashMap;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.Map.Entry;

import org.apache.poi.POIXMLDocument;

import org.apache.poi.openxml4j.opc.OPCPackage;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.xmlbeans.XmlOptions;

import org.openxmlformats.schemas.wordprocessingml.x.main.CTBody;

/**

*

* poi 版本 3.14

*/

public class WordUtil {

public static CustomXWPFDocument generateWord(Map<String, Object> param, String template) {

CustomXWPFDocument doc = null;

try {

OPCPackage pack = POIXMLDocument.openPackage(template);

doc = new CustomXWPFDocument(pack);

if (param != null && param.size() > 0) {

//处理段落

List<XWPFParagraph> paragraphList = doc.getParagraphs();

processParagraphs(paragraphList, param, doc);

//处理表格

Iterator<XWPFTable> it = doc.getTablesIterator();

while (it.hasNext()) {

XWPFTable table = it.next();

List<XWPFTableRow> rows = table.getRows();

for (XWPFTableRow row : rows) {

List<XWPFTableCell> cells = row.getTableCells();

for (XWPFTableCell cell : cells) {

List<XWPFParagraph> paragraphListTable = cell.getParagraphs();

processParagraphs(paragraphListTable, param, doc);

}

}

}

}

} catch (Exception e) {

e.printStackTrace();

}

return doc;

}

/**

* 处理段落

*

* @param paragraphList

*/

public static void processParagraphs(List<XWPFParagraph> paragraphList, Map<String, Object> param, CustomXWPFDocument doc) {

if (paragraphList != null && paragraphList.size() > 0) {

for (int i =0; i<paragraphList.size();i++) {

XWPFParagraph paragraph = paragraphList.get(i);

List<XWPFRun> runs = paragraph.getRuns();

for (int j = 0; j<runs.size();j++) {

XWPFRun run = runs.get(j);

String text = run.getText(0);

if (text != null) {

//System.out.println("读取文本:"+text);

boolean isSetText = false;

for (Entry<String, Object> entry : param.entrySet()) {

String key = entry.getKey();

if (text.indexOf(key) != -1) {

isSetText = true;

Object value = entry.getValue();

if (value instanceof String) {//文本替换

text = text.replace(key, value.toString());

} else if (value instanceof Map) {//图片替换

//System.out.println("开始进行图片替换.....");

text = text.replace(key, "");

Map pic = (Map) value;

int width = Integer.parseInt(pic.get("width").toString());

int height = Integer.parseInt(pic.get("height").toString());

int picType = getPictureType(pic.get("type").toString());

byte[] byteArray = (byte[]) pic.get("content");

ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);

try {

//int ind = doc.addPicture(byteInputStream,picType);

//doc.createPicture(ind, width , height,paragraph);

String ind = doc.addPictureData(byteInputStream, picType);

int id = doc.getNextPicNameNumber(picType);

doc.createPicture(ind, id, width, height, paragraph);

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

if (isSetText) {

run.setText(text, 0);

}

}

}

}

}

}

/**

* 根据图片类型,取得对应的图片类型代码

*

* @param picType

* @return int

*/

private static int getPictureType(String picType) {

int res = CustomXWPFDocument.PICTURE_TYPE_PICT;

if (picType != null) {

if (picType.equalsIgnoreCase("png")) {

res = CustomXWPFDocument.PICTURE_TYPE_PNG;

} else if (picType.equalsIgnoreCase("dib")) {

res = CustomXWPFDocument.PICTURE_TYPE_DIB;

} else if (picType.equalsIgnoreCase("emf")) {

res = CustomXWPFDocument.PICTURE_TYPE_EMF;

} else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) {

res = CustomXWPFDocument.PICTURE_TYPE_JPEG;

} else if (picType.equalsIgnoreCase("wmf")) {

res = CustomXWPFDocument.PICTURE_TYPE_WMF;

}

}

return res;

}

/**

* 将输入流中的数据写入字节数组

*

* @param in

* @return

*/

public static byte[] inputStream2ByteArray(InputStream in, boolean isClose) {

byte[] byteArray = null;

try {

int total = in.available();

byteArray = new byte[total];

in.read(byteArray);

} catch (IOException e) {

e.printStackTrace();

} finally {

if (isClose) {

try {

in.close();

} catch (Exception e2) {

System.out.println("关闭流失败");

}

}

}

return byteArray;

}

public static void appendBody(XWPFDocument src, XWPFDocument append) throws Exception {

CTBody src1Body = src.getDocument().getBody();

CTBody src2Body = append.getDocument().getBody();

List<XWPFPictureData> allPictures = append.getAllPictures();

// 记录图片合并前及合并后的ID

Map<String,String> map = new HashMap<>();

for (XWPFPictureData picture : allPictures) {

//String before = append.getPackageRelationship().getId();

String before = append.getRelationId(picture);

//将原文档中的图片加入到目标文档中

String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);

map.put(before, after);

}

appendBody(src1Body, src2Body,map);

}

private static void appendBody(CTBody src, CTBody append,Map<String,String> map) throws Exception {

XmlOptions optionsOuter = new XmlOptions();

optionsOuter.setSaveOuter();

String appendString = append.xmlText(optionsOuter);

String srcString = src.xmlText();

String prefix = srcString.substring(0,srcString.indexOf(">")+1);

String mainPart = srcString.substring(srcString.indexOf(">")+1,srcString.lastIndexOf("<"));

String sufix = srcString.substring( srcString.lastIndexOf("<") );

String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));

if (map != null && !map.isEmpty()) {

//对xml字符串中图片ID进行替换

for (Map.Entry<String, String> set : map.entrySet()) {

addPart = addPart.replace(set.getKey(), set.getValue());

}

}

//将两个文档的xml内容进行拼接

CTBody makeBody = CTBody.Factory.parse(prefix+mainPart+addPart+sufix);

src.set(makeBody);

}

}

package testModel;

import java.io.IOException;

import java.io.InputStream;

import org.apache.poi.openxml4j.opc.OPCPackage;

import org.apache.poi.xwpf.usermodel.XWPFDocument;

import org.apache.poi.xwpf.usermodel.XWPFParagraph;

import org.apache.xmlbeans.XmlException;

import org.apache.xmlbeans.XmlToken;

import org.openxmlformats.schemas.drawingml.x.main.CTNonVisualDrawingProps;

import org.openxmlformats.schemas.drawingml.x.main.CTPositiveSize2D;

import org.openxmlformats.schemas.drawingml.x.wordprocessingDrawing.CTInline;

/**

* 自定义 XWPFDocument,并重写 createPicture()方法

*/

public class CustomXWPFDocument extends XWPFDocument {

public CustomXWPFDocument(InputStream in) throws IOException {

super(in);

}

public CustomXWPFDocument() {

super();

}

public CustomXWPFDocument(OPCPackage pkg) throws IOException {

super(pkg);

}

/**

* @param id

* @param width 宽

* @param height 高

* @param paragraph 段落

*/

public void createPicture(String blipId, int id, int width, int height,XWPFParagraph paragraph) {

final int EMU = 9525;

width *= EMU;

height *= EMU;

//String blipId = getAllPictures().get(id).getPackageRelationship().getId();

CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline();

String picXml = "" +

"<a:graphic xmlns:a=\"/drawingml//main\">" +

" <a:graphicData uri=\"/drawingml//picture\">" +

" <pic:pic xmlns:pic=\"/drawingml//picture\">" +

"<pic:nvPicPr>" +

"<pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>" +

"<pic:cNvPicPr/>" +

"</pic:nvPicPr>" +

"<pic:blipFill>" +

"<a:blip r:embed=\"" + blipId + "\" xmlns:r=\"/officeDocument//relationships\"/>" +

"<a:stretch>" +

" <a:fillRect/>" +

"</a:stretch>" +

"</pic:blipFill>" +

"<pic:spPr>" +

"<a:xfrm>" +

" <a:off x=\"0\" y=\"0\"/>" +

" <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>" +

"</a:xfrm>" +

"<a:prstGeom prst=\"rect\">" +

" <a:avLst/>" +

"</a:prstGeom>" +

"</pic:spPr>" +

" </pic:pic>" +

" </a:graphicData>" +

"</a:graphic>";

// CTGraphicalObjectData graphicData =

inline.addNewGraphic().addNewGraphicData();

XmlToken xmlToken = null;

try {

xmlToken = XmlToken.Factory.parse(picXml);

} catch (XmlException xe) {

xe.printStackTrace();

}

inline.set(xmlToken);

inline.setDistT(0);

inline.setDistB(0);

inline.setDistL(0);

inline.setDistR(0);

CTPositiveSize2D extent = inline.addNewExtent();

extent.setCx(width);

extent.setCy(height);

CTNonVisualDrawingProps docPr = inline.addNewDocPr();

docPr.setId(id);

docPr.setName("Picture" + id);

docPr.setDescr("Generated");

}

}

package testModel;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import org.apache.poi.xwpf.usermodel.XWPFDocument;

import com.pactera.utils.DateUtil;

public class Demo {

public static void main(String[] args) throws Exception {

System.out.println("---------------start-------------------");

// 目标文档的输出路径

FileOutputStream fopts = new FileOutputStream("D:\\opensour\\apache-tomcat-8.0.30\\webapps\\file-service\\uploadfile\\word\\b.docx",true);

// 定义文档集合对象,将多个word拼接

List<XWPFDocument> documentList = new ArrayList<>();

// 模拟多个word

for (int i = 1; i <= 4; i++) {

Map<String, Object> param = new HashMap<>();

param.put("${projectName}", "xx项目");

param.put("${roomName}", "00"+i+"房");

param.put("${weixiu}", "维修单位");

param.put("${providerName}", "勇弟");

param.put("${createTime}", DateUtil.getCurrentTime());

param.put("${createTime}", DateUtil.getCurrentTime());

param.put("${weixiu}", "维修完成");

param.put("${engineerName}", "张三"+i);

// 图片路劲 多张图片

String fileUrl = "C:\\"+i+".png";

System.out.println(fileUrl);

// 设置图片的基本属性,如果没有图片 则忽略

Map<String,Object> header = new HashMap<String, Object>();

header.put("width", 100);

header.put("height", 150);

header.put("type", "png");

header.put("content", WordUtil.inputStream2ByteArray(new FileInputStream(fileUrl), true));

param.put("${image}",header);

// 读取word文档的模板

CustomXWPFDocument doc = WordUtil.generateWord(param, "D:\\opensour\\apache-tomcat-8.0.30\\webapps\\file-service\\uploadfile\\word\\orderModel2.docx");

documentList.add(doc);

}

XWPFDocument firstDoc = documentList.get(0);

// CTBody src1Body = firstDoc.getDocument().getBody();

for (int i = 1; i < documentList.size(); i++) {

// 多分文档拼接 将第一份与其它进行拼接,需设置分页符

documentList.get(i).createParagraph().setPageBreak(true);

// CTBody src2Body = documentList.get(i).getDocument().getBody();

WordUtil.appendBody(firstDoc,documentList.get(i));

}

firstDoc.write(fopts);

fopts.close();

System.out.println("---------------end-------------------");

}

}

实现效果如下:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。