Using itext5 to export PDF form documents

Posted by nuttynibbles on Thu, 16 Jan 2020 12:09:47 +0100

Recently, I got a requirement, which needs to export PDF documents. There are many ways to realize it on the market. After testing and research, I decided to use itext5 to realize it. If I don't say much, I'll do what I say.

1. Dependent import

<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

Here's the description: the above dependency is mainly to achieve PDF generation, and the following dependency is related to Chinese font;

2.PDF table export implementation

1. export PDF
//            1. Open the document and set basic properties
            Document document = new Document();
//            2. Set request header and encode file name
            response.setContentType("application/pdf;charset=UTF-8");
            response.setHeader("Content-Disposition", 
            "attachment; filename=" + java.net.URLEncoder.encode("" + 
            recordDto.getTitle() + ".pdf", "UTF-8"));
//            3. Write out the pdf instance to the browser through the stream
            PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());

So far, the export PDF has been implemented, but there is nothing in the PDF. Understand this, and the next step is to "feed" the document (the response here is HttpServletResponse).

2. Page beautification
//              The wirter here is the writer above
            writer.setViewerPreferences(PdfWriter.PageModeUseThumbs);
            writer.setPageSize(PageSize.A4);

The display thumbnail of the document and the size of the document are set as A4;

3. Chinese font setting
public static Font getPdfChineseFont() throws Exception {
        BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",
                BaseFont.NOT_EMBEDDED);
        Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);
        fontChinese.setColor(BaseColor.BLACK);
        fontChinese.setSize(11);
        return fontChinese;
    }

This method sets the Chinese font style. Interested students can try other styles, such as: font color, size, font can be modified;

4. Output form content to document
//			Open document first
document.open();
//			Add table data to the document
private static void printBasicInfo(ShopApplyRecordDto recordDto, Document document, Font font) throws DocumentException {
//			Data in tables
        Object[][] basicDatas = {
                {"Title","xxx Apply", "Approval number","1234"},
                {"Applicant","Xiao Ming", "Application shop","xxx Market"},
                {"Date of application","2020/1/16", "Approval result","Agree!")}};
//			Width of each cell
        float[] widthss = {50, 200, 50, 200};
//          Create a table with four cell s per row
        PdfPTable basicTable = new PdfPTable(widthss);
//			Outer loop table row
        for (int i = 0; i < basicDatas.length; i++) {
//			Inner loop each row of specific data
            for (int j = 0; j < basicDatas[i].length; j++) {
//          Create a new cell
                PdfPCell cell = new PdfPCell();
//			This method is to uniformly set the table and cell styles. The following will be written  
                setTableStyle(basicTable, cell);
//			Format of data to be filled in cell
                Paragraph paragraph = 
                new Paragraph(StrUtil.toString(basicDatas[i][j]), font);
//  		Set cell value
                cell.setPhrase(paragraph);
//			Add cell s to the table
                basicTable.addCell(cell);
            }
        }
//			Add table to document
        document.add(basicTable);
    }
//			Close document at end
document.close();

Now the exported PDF has tables like this:

Of course, your style will be ugly. Next, let's set the style.

5. Table and cell style settings
public static void setTableStyle(PdfPTable table, PdfPCell cell) {
//			Set table style
        table.setLockedWidth(true);
        table.setTotalWidth(500);
        table.setHorizontalAlignment(Element.ALIGN_LEFT);
//			Set cell style
        cell.setMinimumHeight(35);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setBackgroundColor(BaseColor.WHITE);
        cell.setBorder(0);
        cell.setBorderWidthTop(0.1f);
        cell.setBorderWidthBottom(0.1f);
        cell.setBorderWidthLeft(0.1f);
        cell.setBorderWidthRight(0.1f);
        cell.setBorderColorBottom(BaseColor.BLACK);
        cell.setBorderColorLeft(BaseColor.BLACK);
        cell.setBorderColorRight(BaseColor.BLACK);
        cell.setBorderColorTop(BaseColor.BLACK);
        cell.setPadding(3);
    }

api methods are still relatively easy to understand. I won't go into details here. If you don't understand, you can try your own settings to make your own style.

6. Setting of header and page number

This shows that the api of itext2 and itext5 are quite different. There is a special HeaderFooter class to set the style in version 2. There is no such class in version 5. Instead, there is an event processing class such as PdfPageEventHelper. Please don't confuse these two versions of api. They are incompatible with each other;
First, write a subclass of PdfPageEventHelper to print the header page number:

public class HeaderFooter extends PdfPageEventHelper {
//			Here are business-related attributes that can be ignored
    private ShopApplyRecordDto recordDto;
    private SysUserInfo userInfo;
//			In most cases, the header value is dynamic. Here, parameters can be passed during initialization
    public HeaderFooter(ShopApplyRecordDto recordDto, SysUserInfo userInfo) {
        this.recordDto = recordDto;
        this.userInfo = userInfo;
    }

    public HeaderFooter() {
    }

    public ShopApplyRecordDto getRecordDto() {
        return recordDto;
    }

    public void setRecordDto(ShopApplyRecordDto recordDto) {
        this.recordDto = recordDto;
    }

    public SysUserInfo getUserInfo() {
        return userInfo;
    }

    public void setUserInfo(SysUserInfo userInfo) {
        this.userInfo = userInfo;
    }
//			This method is the key to the implementation of header and page number: it means that the method will be executed every time the page ends
    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        Font font = null;
        try {
            font = getPdfChineseFont();
        } catch (Exception e) {
            e.printStackTrace();
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd  HH:mm");
//			Set header: in this case, you can use space to realize the header of three positions in the middle left and right. In fact, you can write three. You can control the location of the header through element. Align? Left () / document. Top (), which can set the specific location of the header similar to the up and down adjustment of html. You can try more
        ColumnText.showTextAligned(writer.getDirectContent(), 
        Element.ALIGN_LEFT,
        new Phrase("Project:" + recordDto.getMallName() + "                                                    Printing time:" + format.format(new Date()) + "                                   Printer:" + userInfo.getUserName(), font),
        document.left(),
        document.top() + 3, 0);
//			Get a box called "art"			
        Rectangle rect = writer.getBoxSize("art");
//			Set page number: the page number position here has been set, and you can use it directly. As for the page number realization of 1 / 20 effect, it is very complicated. If you need it, please Baidu / Google yourself
        ColumnText.showTextAligned(writer.getDirectContent(),
        Element.ALIGN_CENTER, 
        new Phrase(String.format("%d", writer.getPageNumber())),
        (rect.getLeft() + rect.getRight()) / 2, 
        rect.getBottom() - 18, 0);
    }

    public static Font getPdfChineseFont() throws Exception {
        BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",
                BaseFont.NOT_EMBEDDED);
        Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);
        fontChinese.setColor(BaseColor.BLACK);
        fontChinese.setSize(11);
        return fontChinese;
    }
}

Next, simply set our HeaderFooter to the PdfWriter object:

//			Create a new HeaderFooter and pass the required parameters
HeaderFooter headerFooter = new HeaderFooter(recordDto, userInfo);
//			Create a new box
Rectangle rect = new Rectangle(36, 54, 559, 788);
//			Set the name to "art". This is the box that get s on it
writer.setBoxSize("art", rect);
writer.setPageEvent(headerFooter);
//			This can set the margin of the content
document.setMargins(45f, 45f, 65f, 50f);
7. Effect display

8. summary

OK, it's fully realized by printing PDF documents here. In fact, itext5 has many functions, such as text, pictures and links. If you need to go to the official documents, you can also leave a message to ask me what's wrong with my first blog. I hope you can put it forward in the message, so that I can correct it in time, so as not to make mistakes.

Published 1 original article, won 1 praise, visited 5
Private letter follow

Topics: Java Google