<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.poi.xwpf.converter.pdf-gae</artifactId>
<version>2.0.2</version>
</dependency>
2、WordOutputUtil 工具类
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.math.BigInteger;
import java.util.List;
public class WordOutputUtil {
public static void setBigTitle(XWPFDocument doc, String bigTitle, String authorName) {
XWPFParagraph bigTitleParagraph = doc.createParagraph();
bigTitleParagraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun titleFun = bigTitleParagraph.createRun();
titleFun.setText(bigTitle);
setBigTitleFontStyle(titleFun);
titleFun.addBreak();
titleFun = bigTitleParagraph.createRun();
titleFun.setText(authorName);
setBigTitleTextFontStyle(titleFun);
public static void setTitleText(XWPFParagraph paragraph, String titleText) {
XWPFRun titleFun = paragraph.createRun();
titleFun.setText(titleText);
setTitleFontStyle(titleFun);
public static void setTableTitle(XWPFDocument doc, String tableTitleName) {
XWPFParagraph bigTitleParagraph = doc.createParagraph();
bigTitleParagraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun titleFun = bigTitleParagraph.createRun();
titleFun.addBreak();
titleFun.setText(tableTitleName);
setTableTitleFontStyle(titleFun);
public static void setGroupTitle(XWPFParagraph paragraph, String tableTitleName) {
XWPFRun titleFun = paragraph.createRun();
titleFun.addBreak();
titleFun.addTab();
titleFun.setText(tableTitleName);
setTitleFontStyle(titleFun);
public static void setText(XWPFParagraph paragraph, String text) {
XWPFRun textFun = paragraph.createRun();
textFun.addBreak();
textFun.addTab();
textFun.setText(text);
setTextFontStyle(textFun);
public static XWPFTable createTable(XWPFDocument doc, int rows, int cols) {
XWPFTable table = doc.createTable(rows, cols);
CTTblGrid grid = table.getCTTbl().getTblGrid();
if (grid == null) {
table.getCTTbl().addNewTblGrid();
setTableWidthAndHAlign(table, "8288", STJc.CENTER);
return table;
* @Description: 设置表格总宽度与水平对齐方式
public static void setTableWidthAndHAlign(XWPFTable table, String width, STJc.Enum enumValue) {
CTTblPr tblPr = getTableCTTblPr(table);
CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW();
if (enumValue != null) {
CTJc cTJc = tblPr.addNewJc();
cTJc.setVal(enumValue);
tblWidth.setW(new BigInteger(width));
tblWidth.setType(STTblWidth.DXA);
for (XWPFTableRow row : table.getRows()) {
for(XWPFTableCell cell : row.getTableCells()) {
CTTblWidth ctTblWidth = cell.getCTTc().addNewTcPr().addNewTcW();
ctTblWidth.setW(new BigInteger(width));
ctTblWidth.setType(STTblWidth.DXA);
* @Description: 得到Table的CTTblPr, 不存在则新建
public static CTTblPr getTableCTTblPr(XWPFTable table) {
CTTbl ttbl = table.getCTTbl();
CTTblPr tblPr = ttbl.getTblPr() == null ? ttbl.addNewTblPr() : ttbl.getTblPr();
return tblPr;
* 合并表格单元格
* @param table 表格对象
* @param startRow 开始行
* @param endRow 结束行
* @param startCol 开始列
* @param endCol 结束列
public static void mergeTableCellsAndRow(XWPFTable table, int startRow, int endRow, int startCol, int endCol) {
for (int rowIndex = startRow; rowIndex <= endRow; rowIndex++) {
XWPFTableRow row = table.getRow(rowIndex);
for (int cellIndex = startCol; cellIndex <= endCol; cellIndex++) {
XWPFTableCell cell = row.getCell(cellIndex);
if (cellIndex == startCol) {
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
} else {
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
for (int rowIndex = startRow; rowIndex <= endRow; rowIndex++) {
XWPFTableRow row = table.getRow(rowIndex);
XWPFTableCell cell = row.getCell(startCol);
if (rowIndex == startRow) {
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
} else {
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
* 往表格中填充数据
* @param table
* @param tableData
* @Author Huangxiaocong 2018年12月16日
public static void setTableData(XWPFTable table, List<List<Object>> tableData) {
List<XWPFTableRow> rowList = table.getRows();
for (int i = 0; i < rowList.size(); i++) {
if (i >= tableData.size())
break;
List<Object> list = tableData.get(i);
List<XWPFTableCell> cellList = rowList.get(i).getTableCells();
for (int j = 0; j < cellList.size(); j++) {
if (j >= list.size())
break;
XWPFParagraph cellParagraph = cellList.get(j).getParagraphArray(0);
XWPFRun cellParagraphRun = cellParagraph.createRun();
setTableTextFontStyle(cellParagraphRun);
cellParagraphRun.setText(String.valueOf(list.get(j)));
public static void setBigTitleFontStyle(XWPFRun fun) {
fun.setBold(true);
fun.setColor("000000");
fun.setFontSize(20);
fun.setFontFamily("黑体");
public static void setBigTitleTextFontStyle(XWPFRun fun) {
setFontStyle(fun, 12, false);
public static void setTitleFontStyle(XWPFRun fun) {
fun.setTextPosition(20);
setFontStyle(fun, 12, true);
public static void setTableTitleFontStyle(XWPFRun fun) {
fun.setBold(true);
fun.setColor("000000");
fun.setFontSize(12);
fun.setFontFamily("黑体");
public static void setTableTextFontStyle(XWPFRun fun) {
fun.setBold(false);
fun.setColor("000000");
fun.setFontSize(10);
fun.setFontFamily("仿宋");
public static void setTextFontStyle(XWPFRun fun) {
setFontStyle(fun, 12, false);
public static void setFontStyle(XWPFRun fun, int fontSize, boolean isBold) {
fun.setBold(isBold);
fun.setColor("000000");
fun.setFontSize(fontSize);
fun.setFontFamily("宋体");
3、测试代码
import com.top.ckdemo.ck.common.WordOutputUtil;
import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
* docx转pdf
public class Docx2Pdf {
public static void main(String[] args) {
String modelPath = "E:/模板.docx";
String outPath = "E:/转换结果.pdf";
docx2Pdf(modelPath, outPath);
public static void docx2Pdf(String modelPath, String outPath) {
try {
File file = new File(modelPath);
XWPFDocument doc = new XWPFDocument(new FileInputStream(file));
XWPFParagraph paragraph = doc.getLastParagraph();
paragraph.removeRun(0);
String bigTitle = "这是大标题";
String authorName = "这是作者小标题";
WordOutputUtil.setBigTitle(doc, bigTitle, authorName);
XWPFParagraph paragraph1 = doc.createParagraph();
paragraph1.setVerticalAlignment(TextAlignment.CENTER);
XWPFParagraph paragraph2 = doc.createParagraph();
paragraph2.setVerticalAlignment(TextAlignment.CENTER);
XWPFParagraph paragraph3 = doc.createParagraph();
paragraph3.setVerticalAlignment(TextAlignment.CENTER);
String titleText = "一、内容1";
WordOutputUtil.setTitleText(paragraph1, titleText);
titleText = "二、内容2";
WordOutputUtil.setTitleText(paragraph2, titleText);
titleText = "三、内容3";
WordOutputUtil.setTitleText(paragraph3, titleText);
List<List<Object>> list = new ArrayList<List<Object>>();
List<Object> rowList = new ArrayList<>();
rowList.add("1");
rowList.add("2");
rowList.add("3");
list.add(rowList);
WordOutputUtil.setTableTitle(doc, "表1-1");
XWPFTable table = WordOutputUtil.createTable(doc, 3, 10);
WordOutputUtil.setTableData(table, list);
OutputStream os = new FileOutputStream(new File(outPath));
PdfOptions options = PdfOptions.create();
PdfConverter.getInstance().convert(doc, os, options);
doc.write(os);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
需要注意的是,表格合并的时候,如果是横向合并的话,字数太多或者列数太多会出现段落不齐的情况,竖向合并不会,所以请自行选择是否横向合并。
File.Copy(“source”, “targetFileName”, true);//文件拷贝,true表示当文件存在时“覆盖”,如果不加true,则文件存在报异常。
File.Exists();//判断文件是否存在
File.Move(“source”,“target”);//移动(剪切),思考如何为文件重命名?文件的剪切是可以跨磁盘的。
File.Delete...
在word编辑写个变量ACCOUNTINGMETHOD1,然后用WordReplaceUtil.getCTSym(“Wingdings 2”, “F052”)去替换就是打勾的复选框
busRecord.put(“ACCOUNTINGMETHOD1”, WordReplaceUtil.getCTSym(“Wingdings 2”, “F052”));
没打勾的复选框
busRecord.put(“A...
今天运行项目时出现的这个问题,java.lang.IllegalStateExceptio,第一次见到这个异常,
错误原因:该异常表示,当前对客户端的响应已经结束,不能在响应已经结束(或说消亡)后再向 客户端(实际上是缓冲区)输出任何内容。
具体分析:首先解释下flush(),我们知道在使用读写流的时候数据先被读入内存这个缓冲区中, 然后再写入文件,但是当数据读完时不代表数据已经写入文件完...
使用Apache poi解析word文档为html文件时出现空指针异常:
org.apache.poi.xwpf.converter.core.XWPFConverterException: java.lang.NullPointerException
at org.apache.poi.xwpf.converter.xhtml.XHTMLConverter.convert(XHTMLC...
异常一:java.lang.IllegalStateException:Cannot forward a response that is already committed
异常二:IllegalStateException:response already commited
异常三:IllegalStateException:getOutputStream(
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.poi.xwpf.usermodel.XWPFRun;
public class DocxToPdfConverter {
public static void main(String[] args) throws Exception {
// 读取docx文件
FileInputStream fis = new FileInputStream(new File("input.docx"));
XWPFDocument document = new XWPFDocument(fis);
// 创建PDF文档
PDDocument pdfDocument = new PDDocument();
PDPageTree pages = pdfDocument.getPages();
PDPage pdfPage = new PDPage(PDRectangle.A4);
pages.add(pdfPage);
// 创建PDF内容流
PDPageContentStream contentStream = new PDPageContentStream(pdfDocument, pdfPage);
// 遍历docx文件中的段落
for (XWPFParagraph para : document.getParagraphs()) {
// 获取段落中的文本
String text = para.getText();
// 创建PDF文本对象
contentStream.beginText();
contentStream.setFont(PDType1Font.HELVETICA, 12);
contentStream.newLineAtOffset(50, 700);
// 添加文本到PDF中
contentStream.showText(text);
contentStream.endText();
// 关闭PDF内容流
contentStream.close();
// 保存PDF文档
pdfDocument.save(new FileOutputStream(new File("output.pdf")));
// 关闭PDF文档
pdfDocument.close();
此代码将读取名为 `input.docx` 的Word文档并将其转换为名为 `output.pdf` 的PDF文件。您可以根据需要修改此代码以满足您的需求。
报错:Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed betwee