Java导出word文档(POI&Spire.Doc)
导出Word文档整理
前言
业务需要将数据库中存的图片导出成word文档,并给这些图片按照文件名生成目录。以下为解决方案,通常在导出文件时,poi使用的频率较高,可以导出各类模板类的和非模板类的文件,但是在导出word,并生成目录的时候发现其解决问题方式相对来说比较复杂。所以,通过调查后发现Spire.Doc,可以实现当前业务需求。以下是本次问题解决整理。
Apache POI
添加依赖
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
示例代码
public static void main(String[] args) throws IOException{
XWPFDocument document= new XWPFDocument();
FileOutputStream out = new FileOutputStream(new File("F:\\Sources\\test.docx"));
//添加标题
XWPFParagraph titleParagraph = document.createParagraph();
//设置段落居中
titleParagraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun titleParagraphRun = titleParagraph.createRun();
titleParagraphRun.setText("Java PoI");
titleParagraphRun.setColor("000000");
titleParagraphRun.setFontSize(20);
XWPFParagraph firstParagraph = document.createParagraph();
XWPFRun run = firstParagraph.createRun();
run.setText("Java POI 生成word文件。");
run.setColor("696969");
run.setFontSize(16);
//设置段落背景颜色
CTShd cTShd = run.getCTR().addNewRPr().addNewShd();
cTShd.setVal(STShd.CLEAR);
cTShd.setFill("97FFFF");
XWPFParagraph paragraph1 = document.createParagraph();
XWPFRun paragraphRun1 = paragraph1.createRun();
paragraphRun1.setText("\r");
//基本信息表格
XWPFTable infoTable = document.createTable();
//去表格边框
infoTable.getCTTbl().getTblPr().unsetTblBorders();
//列宽自动分割
CTTblWidth infoTableWidth = infoTable.getCTTbl().addNewTblPr().addNewTblW();
infoTableWidth.setType(STTblWidth.DXA);
infoTableWidth.setW(BigInteger.valueOf(9072));
//表格第一行
XWPFTableRow infoTableRowOne = infoTable.getRow(0);
infoTableRowOne.getCell(0).setText("职位");
infoTableRowOne.addNewTableCell().setText(": Java 开发工程师");
//表格第二行
XWPFTableRow infoTableRowTwo = infoTable.createRow();
infoTableRowTwo.getCell(0).setText("姓名");
infoTableRowTwo.getCell(1).setText(": seawater");
//表格第三行
XWPFTableRow infoTableRowThree = infoTable.createRow();
infoTableRowThree.getCell(0).setText("生日");
infoTableRowThree.getCell(1).setText(": xxx-xx-xx");
//表格第四行
XWPFTableRow infoTableRowFour = infoTable.createRow();
infoTableRowFour.getCell(0).setText("性别");
infoTableRowFour.getCell(1).setText(": 男");
//表格第五行
XWPFTableRow infoTableRowFive = infoTable.createRow();
infoTableRowFive.getCell(0).setText("现居地");
infoTableRowFive.getCell(1).setText(": xx");
CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
XWPFHeaderFooterPolicy policy = new XWPFHeaderFooterPolicy(document, sectPr);
XWPFParagraph pic = document.createParagraph();
pic.setAlignment(ParagraphAlignment.CENTER);
XWPFRun picRun = pic.createRun();
List<String> filePath = new ArrayList<String>();
filePath.add("D:\\Pictures\\20170314171319_TP2nY.jpeg");
filePath.add("D:\\Pictures\\20161213154536_AGv84.jpg");
filePath.add("D:\\Pictures\\20151212225934_VhQcM.jpeg");
filePath.add("D:\\Pictures\\20150926115124_fYZ4U.jpeg");
for (String str:filePath) {
picRun.setText(str);
picRun.addPicture(
new FileInputStream(str),XWPFDocument.PICTURE_TYPE_JPEG,
str,
Units.toEMU(450),
Units.toEMU(300)
//添加页眉
CTP ctpHeader = CTP.Factory.newInstance();
CTR ctrHeader = ctpHeader.addNewR();
CTText ctHeader = ctrHeader.addNewT();
String headerText = "ctpHeader";
ctHeader.setStringValue(headerText);
XWPFParagraph headerParagraph = new XWPFParagraph(ctpHeader, document);
//设置为右对齐
headerParagraph.setAlignment(ParagraphAlignment.RIGHT);
XWPFParagraph[] parsHeader = new XWPFParagraph[1];
parsHeader[0] = headerParagraph;
policy.createHeader(XWPFHeaderFooterPolicy.DEFAULT, parsHeader);
//添加页脚
CTP ctpFooter = CTP.Factory.newInstance();
CTR ctrFooter = ctpFooter.addNewR();
CTText ctFooter = ctrFooter.addNewT();
String footerText = "ctpFooter";
ctFooter.setStringValue(footerText);
XWPFParagraph footerParagraph = new XWPFParagraph(ctpFooter, document);
headerParagraph.setAlignment(ParagraphAlignment.CENTER);
XWPFParagraph[] parsFooter = new XWPFParagraph[1];
parsFooter[0] = footerParagraph;
policy.createFooter(XWPFHeaderFooterPolicy.DEFAULT, parsFooter);
document.write(out);
out.close();
}
生成效果
优缺点
- 优点
-
通常较为常用的导入导出文件。比较稳定
-
缺点
- 导出word文件在生成目录的时候,处理较为复杂
Sprie.Doc for JAVA
添加 Free Spire.PDF for Java 依赖
第一种方式:通过官网 下载jar 文件包。下载后,解压文件,将lib文件夹下的Spire.Pdf.jar文件导入Java程序。
第二种方式:通过 maven仓库安装导入 。
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>3.3</version>
</dependency>
</dependencies>
示例代码
/**
* 导出文件
* @param condition
* @return
@PostMapping(value = "/exportInfoToWord")
public void exportInfoToWord(@RequestBody HashMap<String,String> condition, HttpServletResponse response) throws IOException {
//创建Word文档
Document doc = new Document();
//添加一个目录的section
Section section = doc.addSection();
Paragraph para = section.addParagraph();
TextRange tr = para.appendText("目 录");
//设置字体大小和颜色
tr.getCharacterFormat().setTextColor(Color.black);
tr.getCharacterFormat().setFontName("宋体");
tr.getCharacterFormat().setFontSize(20);
para.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
//设置段后间距
para.getFormat().setAfterSpacing(10);
//添加段落
para = section.addParagraph();
//通过指定最低的Heading级别1和最高的Heading级别3,创建包含Heading 1、2、3,制表符前导符和右对齐页码的默认样式的Word目录。标题级别范围必须介于1到9之间
para.appendTOC(1, 3);
// 获取http客户端
CloseableHttpClient client = HttpClients.createDefault();
List<String> fileAddress = new ArrayList<String>();
fileAddress.add("http://114.116.236.37:9000/image/file/676faf54-105a-4f36-8efe-3e73729eb69f.jpg");
fileAddress.add("http://114.116.236.37:9000/image/file/962d7ea0-1222-418a-9297-9eee48d6bc85.jpeg");
fileAddress.add("http://114.116.236.37:9000/image/file/a5c6f1c6-ba1e-4178-a791-eb539afb4042.jpeg");
for (String address : fileAddress) {
//添加一个section
section = doc.addSection();
//添加一个段落
para = section.addParagraph();
para.appendText(address);
//应用Heading 1样式到段落
para.applyStyle(BuiltinStyle.Heading_1);
section.addParagraph();
// 通过httpget方式来实现我们的get请求
HttpGet httpGet = new HttpGet(address);
//设置请求头信息
httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");
// 通过client调用execute方法,得到我们的执行结果就是一个response,所有的数据都封装在response里面了
CloseableHttpResponse httpResponse = client.execute(httpGet);
// HttpEntity 是一个中间的桥梁,在httpClient里面,是连接我们的请求与响应的一个中间桥梁,所有的请求参数都是通过HttpEntity携带过去的
// 所有的响应的数据,也全部都是封装在HttpEntity里面
HttpEntity entity = httpResponse.getEntity();
InputStream in = entity.getContent();
//添加图片段落
Paragraph paraPicture = section.addParagraph();
DocPicture picture = paraPicture.appendPicture(in);
//设置图片宽度
picture.setWidth(490f);
//设置图片高度
picture.setHeight(400f);
//添加第一个段落
Paragraph paraText = section.addParagraph();
//给第一个段落和第二个段落设置水平居中对齐方式
paraPicture.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
paraText.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
//设置第一个段落的段后间距
paraPicture.getFormat().setAfterSpacing(15f);
//释放资源
EntityUtils.consume(entity);
//获取第一个节中的页脚
HeaderFooter footer = doc.getSections().get(0).getHeadersFooters().getFooter();
//添加段落到页脚
Paragraph footerParagraph = footer.addParagraph();
//添加文字、页码域和总页数域到段落
footerParagraph.appendText("第");
footerParagraph.appendField("page number", FieldType.Field_Page);
footerParagraph.appendText("页");
footerParagraph.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
//设置目录页码数字格式为罗马数字
doc.getSections().get(0).getPageSetup().setPageNumberStyle(PageNumberStyle.Roman_Lower);
//设置内容页码数字格式为阿拉伯数字
doc.getSections().get(1).getPageSetup().setPageNumberStyle(PageNumberStyle.Arabic);
//设置第二节页码从新开始编码,并设置起始页码数字
doc.getSections().get(1).getPageSetup().setRestartPageNumbering(true);
doc.getSections().get(1).getPageSetup().setPageStartingNumber(1);
//更新目录
doc.updateTableOfContents();
//保存到临时固定地址
String path = "F:\\tempDocFiles";
File dir = new File(path);
if (!dir.exists()) {
dir.mkdir();
//临时文件路径
String filePath = path + File.separator + UUID.randomUUID();
doc.saveToFile(filePath + ".docx", FileFormat.Docx);
//重新读取文档,进行操作
InputStream is = new FileInputStream(filePath + ".docx");
XWPFDocument document = new XWPFDocument(is);
//以上Spire.Doc 生成的文件会自带警告信息,这里来删除Spire.Doc 的警告
document.removeBodyElement(0);
//输出word内容文件流,提供下载
response.reset();
response.setContentType("application/x-msdownload");
String fileName = "" + System.currentTimeMillis() + ".docx";
response.addHeader("Content-Disposition", "attachment; filename=" + fileName);
delFile(dir);
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
OutputStream servletOS = null;
try {
servletOS = response.getOutputStream();
document.write(ostream);
servletOS.write(ostream.toByteArray());