一. Maven
<dependencies>
<!--poi-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>
二.基础使用
String filePath = "C:\\Users\\S\\Desktop\\test.docx";
//通过文件流读取一个Docx
XWPFDocument xwpfDocument = new XWPFDocument(new FileInputStream(filePath));
//读取 Docx 中的表格列表
XWPFTable table = xwpfDocument.getTables().get(0);
//在表格后新建一行 获取第0个单元格 设置文本为 Hello
table.createRow().getCell(0).setText("Hello");
//获取表格中的第一行 第0个单元格 添加一个新的段落 设置文本为World
table.getRow(1).getCell(0).addParagraph().createRun().setText("World")
//除了文字段落外,还可以在单元格中添加图片
//添加 icon 图片
//新建一个单元格 并在里面新建一个段落
XWPFParagraph xwpfParagraph = row.addNewTableCell().addParagraph();
XWPFRun run = xwpfParagraph.createRun();
//new URL(图片链接).openStream()获取文件流
InputStream is = new URL(v.get("icon").toString()).openStream();
if (is != null) {
//通过 addPicture 方法添加图片
//addPicture(文件流,图片类型,图片名称,宽,高)
run.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, v.get("icon").toString(), Units.toEMU(30), Units.toEMU(30));
run.addBreak();
}
进行模板填充
例如现在的Word模板 其中一些位置固定的信息就可以使用{{Key}} 来标记一下,然后通过代码进行统一填充
String filePath = "C:\\Users\\S\\Desktop\\test.docx";
//这里创建的是 XWPFTemplate
XWPFTemplate document = XWPFTemplate.compile(new FileInputStream(filename));
HashMap<String, Object> map = new HashMap<>();
map.put("Name","Lee");
map.put("Age","20");
map.put("test1","Hello");
map.put("test2","Word");
//通过 render方法 对模板进行填充
document.render(map);
//最后写出文件
FileOutputStream fileOutputStream = new FileOutputStream(filename);
document.write(fileOutputStream);
document.close();
填充完的文件,如果map中没有的值 默认就为空白了
三.多个Word追加合并
mergeWord:
public static void mergeWord(List<File> fileList,File newFile){
try {
OutputStream dest = new FileOutputStream(newFile);
ArrayList<XWPFDocument> documentList = new ArrayList<>();
XWPFDocument doc = null;
for (File file : fileList) {
FileInputStream in = new FileInputStream(file.getPath());
OPCPackage open = OPCPackage.open(in);
XWPFDocument document = new XWPFDocument(open);
documentList.add(document);
}
if(fileList.size() >= 2){
for (int i = 0; i < documentList.size(); i++) {
doc = documentList.get(0);
if(i == 0){
//首页直接分页,不再插入首页文档内容
documentList.get(i).createParagraph().createRun().addBreak(BreakType.TEXT_WRAPPING);
}else if(i == documentList.size()-1){
//尾页不再分页,直接插入最后文档内容
appendBody(doc,documentList.get(i));
}else{
documentList.get(i).createParagraph().createRun().addBreak(BreakType.TEXT_WRAPPING);
appendBody(doc,documentList.get(i));
}
}
}
doc = documentList.get(0);
assert doc != null;
doc.write(dest);
} catch (Exception e) {
e.printStackTrace();
}
}
appendBody:
/**
* 把文件中的图片拿出来
*
* @param src 源文档Document
* @param append 追加文档Document
* @throws Exception
*/
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<String,String>();
for (XWPFPictureData picture : allPictures) {
String before = append.getRelationId(picture);
//将原文档中的图片加入到目标文档中
String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
map.put(before, after);
}
appendBody(src1Body, src2Body,map);
}
appendBody:
/**
* 把图片ID替换一下 避免冲突
*
* @param src 源文档Body
* @param append 追加内容Body
* @param map 图片列表Map
* @throws Exception
*/
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);
}
调用方法
List<File> files1 = new ArrayList<>();
//这里添加的为需要合并的文件路径(包含文件名)
//例如:"C:\\Users\\S\\Desktop\\test.docx"
file.add(filePath);
file.add(filePath2);
mergeWord(files1, new File(filePath));
四.将Word文档专为PDF
WordToPdfUtil
public class WordToPdfUtil {
private static final Logger LOG = LoggerFactory.getLogger(WordToPdfUtil.class);
private static BPTemplateUtil bpTemplateUtil;
/**
* 获取license
* @return boolean 结果
*/
private static boolean getLicense() {
boolean result = false;
try {
// 凭证
String licenseStr =
"<License>\n" +
" <Data>\n" +
" <Products>\n" +
" <Product>Aspose.Total for Java</Product>\n" +
" <Product>Aspose.Words for Java</Product>\n" +
" </Products>\n" +
" <EditionType>Enterprise</EditionType>\n" +
" <SubscriptionExpiry>20991231</SubscriptionExpiry>\n" +
" <LicenseExpiry>20991231</LicenseExpiry>\n" +
" <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>\n" +
" </Data>\n" +
" <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>\n" +
"</License>";
InputStream license = new ByteArrayInputStream(licenseStr.getBytes("UTF-8"));
License asposeLic = new License();
asposeLic.setLicense(license);
result = true;
} catch (Exception e) {
LOG.error("error:", e);
}
return result;
}
/**
* Word转换为PDF
* @param filePath 文件路径(包含文件名)
*/
public static void word2Pdf(String filePath) throws IOException {
File file = new File(filePath);
FileInputStream fileInputStream = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile(file.getName(), fileInputStream);
FileOutputStream fileOS = null;
String filePat;
// 验证License
if (!getLicense()) {
LOG.error("验证License失败!");
return;
}
try {
Document doc = new Document(multipartFile.getInputStream());
String[] split = multipartFile.getName().split(".docx");
String join = String.join("", split);
filePath = BPTemplateUtil.getPath()+join+".pdf";
fileOS = new FileOutputStream(filePath);
// 保存转换的pdf文件
doc.save(fileOS, SaveFormat.PDF);
} catch (Exception e) {
LOG.error("error:", e);
} finally {
try {
if(fileOS != null){
fileOS.close();
}
} catch (IOException e) {
LOG.error("error:", e);
}
}
}
}
更多详细的操作可以参考API文档:
https://tool.oschina.net/apidocs/apidoc?api=apache-POI