poi xml模板 操作pdf_尝试使用Apache poi制作简单的PDF文档

在尝试使用Apache POI创建PDF文档时遇到XWPFConverterException异常。问题在于使用的PdfOptions和PdfConverter不是Apache POI的一部分,而是来自opensagres。解决方案是使用更新的fr.opensagres.poi.xwpf.converter.pdf库,并确保添加必要的样式文档、页面属性和表格网格设置。代码示例展示了如何修正后成功创建PDF文档。
摘要由CSDN通过智能技术生成

I see the internet is riddled with people complaining about apache's pdf products, but I cannot find my particular usecase here. I am trying to do a simple Hello World with apache poi. Right now my code is as follows:

public ByteArrayOutputStream export() throws IOException {

//Blank Document

XWPFDocument document = new XWPFDocument();

//Write the Document in file system

ByteArrayOutputStream out = new ByteArrayOutputStream();;

//create table

XWPFTable table = document.createTable();

XWPFStyles styles = document.createStyles();

styles.setSpellingLanguage("English");

//create first row

XWPFTableRow tableRowOne = table.getRow(0);

tableRowOne.getCell(0).setText("col one, row one");

tableRowOne.addNewTableCell().setText("col two, row one");

tableRowOne.addNewTableCell().setText("col three, row one");

//create second row

XWPFTableRow tableRowTwo = table.createRow();

tableRowTwo.getCell(0).setText("col one, row two");

tableRowTwo.getCell(1).setText("col two, row two");

tableRowTwo.getCell(2).setText("col three, row two");

//create third row

XWPFTableRow tableRowThree = table.createRow();

tableRowThree.getCell(0).setText("col one, row three");

tableRowThree.getCell(1).setText("col two, row three");

tableRowThree.getCell(2).setText("col three, row three");

PdfOptions options = PdfOptions.create();

PdfConverter.getInstance().convert(document, out, options);

out.close();

return out;

}

and the code that calls this is:

public ResponseEntity convertToPDFPost(@ApiParam(value = "DTOs passed from the FE" ,required=true ) @Valid @RequestBody ExportEnvelopeDTO exportDtos) {

if (exportDtos.getProdExportDTOs() != null) {

try {

FileOutputStream out = new FileOutputStream("/Users/kornhaus/Desktop/test.pdf");

out.write(exporter.export().toByteArray());

out.close();

} catch (IOException e) {

e.printStackTrace();

}

return new ResponseEntity(responseFile, responseHeaders, HttpStatus.OK);

}

return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);

}

}

On this line here: out.write(exporter.export().toByteArray());

the code throws an exception:

org.apache.poi.xwpf.converter.core.XWPFConverterException: java.io.IOException: Unable to parse xml bean

I have no clue what's causing this, where to even look for this kind of documentation. I have been coding a decade plus and never had such difficulty with what should be a simple Java library. Any help would be great.

解决方案

The main problem with this is that those PdfOptions and PdfConverter are not part of the apache poi project. They are developed by opensagres and first versions were badly named org.apache.poi.xwpf.converter.pdf.PdfOptions and org.apache.poi.xwpf.converter.pdf.PdfConverter. Those old classes were not updated since 2014 and needs version 3.9 of apache poi to be used.

But the same developers provide fr.opensagres.poi.xwpf.converter.pdf, which is much more current and works using the latest stable release apache poi 3.17. So we should using this.

But since even those newer PdfOptions and PdfConverter are not part of the apache poi project, apache poi will not testing those with their releases. And so the default *.docx documents created by apache poi lacks some content which PdfConverter needs.

There must be a styles document, even if it is empty.

There must be section properties for the page having at least the page size set.

Tables must have a table grid set.

To fulfilling this we must add some code additionally in our program. Unfortunately this then needs the full jar of all of the schemas ooxml-schemas-1.3.jar as mentioned in Faq-N10025.

And because we need changing the underlaying low level objects, the document must be written so underlaying objects will be committed. Else the XWPFDocument which we hand over the PdfConverter will be incomplete.

Example:

import java.io.*;

import java.math.BigInteger;

//needed jars: fr.opensagres.poi.xwpf.converter.core-2.0.1.jar,

// fr.opensagres.poi.xwpf.converter.pdf-2.0.1.jar,

// fr.opensagres.xdocreport.itext.extension-2.0.1.jar,

// itext-2.1.7.jar

import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;

import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;

//needed jars: apache poi and it's dependencies

// and additionally: ooxml-schemas-1.3.jar

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

import org.apache.poi.util.Units;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

public class XWPFToPDFConverterSampleMin {

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

XWPFDocument document = new XWPFDocument();

// there must be a styles document, even if it is empty

XWPFStyles styles = document.createStyles();

// there must be section properties for the page having at least the page size set

CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();

CTPageSz pageSz = sectPr.addNewPgSz();

pageSz.setW(BigInteger.valueOf(12240)); //12240 Twips = 12240/20 = 612 pt = 612/72 = 8.5"

pageSz.setH(BigInteger.valueOf(15840)); //15840 Twips = 15840/20 = 792 pt = 792/72 = 11"

// filling the body

XWPFParagraph paragraph = document.createParagraph();

//create table

XWPFTable table = document.createTable();

//create first row

XWPFTableRow tableRowOne = table.getRow(0);

tableRowOne.getCell(0).setText("col one, row one");

tableRowOne.addNewTableCell().setText("col two, row one");

tableRowOne.addNewTableCell().setText("col three, row one");

//create CTTblGrid for this table with widths of the 3 columns.

//necessary for Libreoffice/Openoffice and PdfConverter to accept the column widths.

//values are in unit twentieths of a point (1/1440 of an inch)

//first column = 2 inches width

table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(2*1440));

//other columns (2 in this case) also each 2 inches width

for (int col = 1 ; col < 3; col++) {

table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(2*1440));

}

//create second row

XWPFTableRow tableRowTwo = table.createRow();

tableRowTwo.getCell(0).setText("col one, row two");

tableRowTwo.getCell(1).setText("col two, row two");

tableRowTwo.getCell(2).setText("col three, row two");

//create third row

XWPFTableRow tableRowThree = table.createRow();

tableRowThree.getCell(0).setText("col one, row three");

tableRowThree.getCell(1).setText("col two, row three");

tableRowThree.getCell(2).setText("col three, row three");

paragraph = document.createParagraph();

//trying picture

XWPFRun run = paragraph.createRun();

run.setText("The picture in line: ");

InputStream in = new FileInputStream("samplePict.jpeg");

run.addPicture(in, Document.PICTURE_TYPE_JPEG, "samplePict.jpeg", Units.toEMU(100), Units.toEMU(30));

in.close();

run.setText(" text after the picture.");

paragraph = document.createParagraph();

//document must be written so underlaaying objects will be committed

ByteArrayOutputStream out = new ByteArrayOutputStream();

document.write(out);

document.close();

document = new XWPFDocument(new ByteArrayInputStream(out.toByteArray()));

PdfOptions options = PdfOptions.create();

PdfConverter converter = (PdfConverter)PdfConverter.getInstance();

converter.convert(document, new FileOutputStream("XWPFToPDFConverterSampleMin.pdf"), options);

document.close();

}

}

Using XDocReport

Another way would be using the newest version of opensagres/xdocreport as described in Converter only with ConverterRegistry:

import java.io.*;

import java.math.BigInteger;

//needed jars: xdocreport-2.0.1.jar,

// odfdom-java-0.8.7.jar,

// itext-2.1.7.jar

import fr.opensagres.xdocreport.converter.Options;

import fr.opensagres.xdocreport.converter.IConverter;

import fr.opensagres.xdocreport.converter.ConverterRegistry;

import fr.opensagres.xdocreport.converter.ConverterTypeTo;

import fr.opensagres.xdocreport.core.document.DocumentKind;

//needed jars: apache poi and it's dependencies

// and additionally: ooxml-schemas-1.3.jar

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

import org.apache.poi.util.Units;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

public class XWPFToPDFXDocReport {

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

XWPFDocument document = new XWPFDocument();

// there must be a styles document, even if it is empty

XWPFStyles styles = document.createStyles();

// there must be section properties for the page having at least the page size set

CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();

CTPageSz pageSz = sectPr.addNewPgSz();

pageSz.setW(BigInteger.valueOf(12240)); //12240 Twips = 12240/20 = 612 pt = 612/72 = 8.5"

pageSz.setH(BigInteger.valueOf(15840)); //15840 Twips = 15840/20 = 792 pt = 792/72 = 11"

// filling the body

XWPFParagraph paragraph = document.createParagraph();

//create table

XWPFTable table = document.createTable();

//create first row

XWPFTableRow tableRowOne = table.getRow(0);

tableRowOne.getCell(0).setText("col one, row one");

tableRowOne.addNewTableCell().setText("col two, row one");

tableRowOne.addNewTableCell().setText("col three, row one");

//create CTTblGrid for this table with widths of the 3 columns.

//necessary for Libreoffice/Openoffice and PdfConverter to accept the column widths.

//values are in unit twentieths of a point (1/1440 of an inch)

//first column = 2 inches width

table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(2*1440));

//other columns (2 in this case) also each 2 inches width

for (int col = 1 ; col < 3; col++) {

table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(2*1440));

}

//create second row

XWPFTableRow tableRowTwo = table.createRow();

tableRowTwo.getCell(0).setText("col one, row two");

tableRowTwo.getCell(1).setText("col two, row two");

tableRowTwo.getCell(2).setText("col three, row two");

//create third row

XWPFTableRow tableRowThree = table.createRow();

tableRowThree.getCell(0).setText("col one, row three");

tableRowThree.getCell(1).setText("col two, row three");

tableRowThree.getCell(2).setText("col three, row three");

paragraph = document.createParagraph();

//trying picture

XWPFRun run = paragraph.createRun();

run.setText("The picture in line: ");

InputStream in = new FileInputStream("samplePict.jpeg");

run.addPicture(in, Document.PICTURE_TYPE_JPEG, "samplePict.jpeg", Units.toEMU(100), Units.toEMU(30));

in.close();

run.setText(" text after the picture.");

paragraph = document.createParagraph();

//document must be written so underlaaying objects will be committed

ByteArrayOutputStream out = new ByteArrayOutputStream();

document.write(out);

document.close();

// 1) Create options DOCX 2 PDF to select well converter form the registry

Options options = Options.getFrom(DocumentKind.DOCX).to(ConverterTypeTo.PDF);

// 2) Get the converter from the registry

IConverter converter = ConverterRegistry.getRegistry().getConverter(options);

// 3) Convert DOCX 2 PDF

InputStream docxin= new ByteArrayInputStream(out.toByteArray());

OutputStream pdfout = new FileOutputStream(new File("XWPFToPDFXDocReport.pdf"));

converter.convert(docxin, pdfout, options);

docxin.close();

pdfout.close();

}

}

October 2018:

This code works using apache poi 3.17. It cannot work using apache poi 4.0.0 due to changings in apache poi which were not taken in account until now in fr.opensagres.poi.xwpf.converter as well as in fr.opensagres.xdocreport.converter.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值