ITEXT7 生成PDF ,添加背景图,表格居中,以及分页表格断开的处理,图片并排, 页眉处理

转载请注明文章出处,谢谢!

公司要求给客户生成PDF报告,本来是使用itext5,html转为pdf, 但是最后一张需要添加背景图,一直没有找到判断是否是最后一张或者说给整个pdf最后添加一页空白页的方法, 最后只能使用itext7,手动写PDF报告,网上也有很多教程,但是有些东西还是找不到,整了几天,搞出来满足需求的,仅此记录一下

效果图

 

 

 

 

 

 

 

 

一些图片以及字体位置

 

 

pom

        <!--itext7全家桶-->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext7-core</artifactId>
            <version>7.1.15</version>
            <type>pom</type>
        </dependency>    
PDFTestController 测试类
package com.example.note.pdf;

import com.example.note.pdf.domain.Constants;
import com.example.note.pdf.domain.PdfTestInfo;
import com.example.note.pdf.domain.entity.PDFTest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

/**
 * @author wqqing
 * @date 2022/8/30 16:17
 */
@RestController
@RequestMapping("pdf-test")
public class PDFTestController {

    @GetMapping("/")
    public void test() throws Exception {
        PdfTestInfo info = new PdfTestInfo();
        //字体路径
        String path = this.getClass().getClassLoader().getResource("").getPath();
        info.setStFondPath(path + Constants.SONGTI_FONTS_PATH);
        info.setWryhFondPath(path + Constants.YAHEI_FONTS_PATH);

        List<PDFTest> tableDatas = Arrays.asList(
                new PDFTest(1l, "english", "yingwen", "asgdag"),
                new PDFTest(2l, "中文测试", "中文测试", "中文呀")
        );
        info.setTableDatas(tableDatas);

        List<String> images = Arrays.asList(
                ImageHelpers.imageToBase64(path+"/image/1.png"),
                ImageHelpers.imageToBase64(path+"/image/2.png"),
                ImageHelpers.imageToBase64(path+"/image/3.png"),
                ImageHelpers.imageToBase64(path+"/image/4.png")

        );
        info.setImages(images);
        info.setImage1(path+"/image/image1.png");
        info.setImage2(path+"/image/image2.jpg");
        GeneratePDFReport.generatePdf(info);

    }
}
View Code

实体类

PDFTest模拟数据库查询出来的数据信息
package com.example.note.pdf.domain.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.example.note.pdf.domain.IgnoreFiled;
import com.example.note.pdf.domain.SeqNo;
import lombok.Data;

/**
 * @author wqqing
 * @date 2022/8/30 16:06
 */
@Data
public class PDFTest {
    @IgnoreFiled
    @TableId
    private Long id;

    @SeqNo(1)//统一处理的时候 获取表格数据 按照数值大小顺序获取属性
    private String name;

    @SeqNo(2)
    private String desc;

    @SeqNo(3)
    private String info;

    public PDFTest(){

    }

    public PDFTest(Long id, String name, String desc, String info) {
        this.id = id;
        this.name = name;
        this.desc = desc;
        this.info = info;
    }
}
View Code
PdfTestInfo pdf数据信息
package com.example.note.pdf.domain;

import com.example.note.pdf.domain.entity.PDFTest;
import lombok.Data;

import java.util.List;

/**
 * @author wqqing
 * @date 2022/8/30 16:18
 */
@Data
public class PdfTestInfo {

    private List<PDFTest> tableDatas;

    private List<String> images;

    private String stFondPath;

    private String wryhFondPath;

    private String image1;

    private String image2;

}
View Code

自定义注解,方便查询类的属性值

package com.example.note.pdf.domain;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author wqqing
 * @date 2022/8/26 13:10
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface IgnoreFiled {
}
View Code
package com.example.note.pdf.domain;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author wqqing
 * @date 2022/8/26 13:06
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SeqNo {
     int value();
}
View Code
Constants 常量类
package com.example.note.pdf.domain;

/**
 * @author wqqing
 * @date 2022/8/16 11:14
 */
public class Constants {
    /**宋体**/
    public static String SONGTI_FONTS_PATH = "font/simsun.ttc,0";
    /**雅黑**/
    public static String YAHEI_FONTS_PATH = "/font/msyh.ttc,0";

}
View Code
PDFStyleContants pdf样式常量信息
package com.example.note.pdf.domain;

import com.itextpdf.kernel.colors.Color;
import com.itextpdf.kernel.colors.DeviceRgb;

/**
 * @author wqqing
 * @date 2022/8/25 16:43
 */
public class PDFStyleContants {
    /**右边距**/
    public static float MARGIN_RIGHT = 40;
    /**左边距**/
    public static float MARGIN_LEFT = 40;
    /**上边距**/
    public static float MARGIN_TOP = 40;
    /**下边距**/
    public static float MARGIN_BOTTOM = 40;
    /**内容中文字体大小**/
    public static float CONTENT_FONT_SIZE = 16;
    /**标题中文字体大小**/
    public static float TITLE_FONT_SIZE = 18;
    /**红色**/
    public static Color RED = Color.convertRgbToCmyk(new DeviceRgb(java.awt.Color.RED));
    /**深蓝色**/
    public static Color MAX_BLUE = Color.convertRgbToCmyk(new DeviceRgb(17, 30,65));
    /**白色**/
    public static Color WHITE = Color.convertRgbToCmyk(new DeviceRgb(java.awt.Color.WHITE));
    /**黑色**/
    public static Color BLACK = Color.convertRgbToCmyk(new DeviceRgb(java.awt.Color.BLACK));
    /**灰色**/
    public static Color GRAY = Color.convertRgbToCmyk(new DeviceRgb(216, 216,216));
    /**页眉字体大小**/
    public static float HEADER_FONT_SIZE = 12;

}
View Code
HeaderFooterHanlder 页眉处理
package com.example.note.pdf;

import com.example.note.pdf.domain.PDFStyleContants;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Tab;
import com.itextpdf.layout.element.TabStop;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TabAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;

/**
 * @author wqqing
 * @date 2022/8/29 10:31
 */
public class HeaderFooterHanlder implements IEventHandler {
    /**字体**/
    private final PdfFont pdfFont;
    /**左侧表头**/
    private final String leftHeader;
    /**右侧表头**/
    private final String rightHeader;

    public HeaderFooterHanlder(PdfFont pdfFont, String leftHeader, String rightHeader){
        this.pdfFont = pdfFont;
        this.leftHeader = leftHeader;
        this.rightHeader = rightHeader;
    }

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent pdfDocumentEvent = (PdfDocumentEvent) event;
        PdfPage page = pdfDocumentEvent.getPage();
        PdfDocument pdfDocument = pdfDocumentEvent.getDocument();
        Document doc = new Document(pdfDocument);
        int pageNums = pdfDocument.getNumberOfPages();
        int pageNumber = pdfDocument.getPageNumber(page);
        try{
            //首页,最后一页不添加页眉
            if (pageNumber > 1 && pageNumber != pageNums) {
                Rectangle pageSize = pdfDocument.getDefaultPageSize();
                float pdfWidth = pageSize.getWidth();
                float pdfHeight = pageSize.getHeight();
                PdfCanvas pdfCanvas = new PdfCanvas(page.getLastContentStream(), page.getResources(), pdfDocument);
                pdfCanvas.setLineWidth(1.5f).setStrokeColor(PDFStyleContants.BLACK);
                float tableWidth = pdfWidth - doc.getRightMargin() - doc.getLeftMargin();
                /**页眉**/
                float x0 = doc.getRightMargin(), y0 = pdfHeight - doc.getTopMargin();
                pdfCanvas.moveTo(x0, y0).lineTo(pdfWidth - doc.getRightMargin(), y0).stroke();

                Table table = TableHelper.table(2, 30, true, tableWidth, HorizontalAlignment.CENTER, null, true,
                        PDFStyleContants.MARGIN_LEFT, y0, tableWidth);
                table.addCell(TableHelper.cell(1, 1, PDFHelpers.paragraph(leftHeader, false).setFont(pdfFont).setVerticalAlignment(VerticalAlignment.BOTTOM),
                        false, Border.NO_BORDER, TextAlignment.LEFT, null, VerticalAlignment.BOTTOM));
                Paragraph date = new Paragraph();
                date.setVerticalAlignment(VerticalAlignment.BOTTOM);
                date.add(new Tab()).addTabStops(new TabStop(1000, TabAlignment.RIGHT));
                date.add(rightHeader).setFont(pdfFont);
                table.addCell(TableHelper.cell(1, 1, date, false, Border.NO_BORDER,  null, null, VerticalAlignment.BOTTOM));
                table.setFixedPosition(doc.getLeftMargin(), pdfHeight - doc.getTopMargin(), tableWidth);
                doc.add(table);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
View Code
ImageHelpers 处理图片数据,可以处理base64以及URL两种格式,实现图片居中,图片并排显示
package com.example.note.pdf;

import com.example.note.pdf.domain.PDFStyleContants;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.layout.element.Image;
import sun.misc.BASE64Decoder;

import java.io.*;
import java.util.Base64;

/**
 * @author wqqing
 * @date 2022/8/25 16:50
 */
public class ImageHelpers {

    /**
     * 图片铺满整个页面
     * @param pdfDocument
     * @return
     * @throws Exception
     */
    public static Image generateBackgroudImage(String imagePath, PdfDocument pdfDocument) throws Exception{
        Image image = new Image(ImageDataFactory.create(base64TOByte(imagePath)));
        PageSize pageSize = pdfDocument.getDefaultPageSize();
        image.scaleToFit(pageSize.getWidth(), pageSize.getHeight());
        image.setMargins(0- PDFStyleContants.MARGIN_TOP, 0- PDFStyleContants.MARGIN_RIGHT,
                0- PDFStyleContants.MARGIN_BOTTOM, 0- PDFStyleContants.MARGIN_LEFT);
        return image;
    }

    /**
     * 图片转为base64编码
     * @param imagePath
     * @return
     * @throws Exception
     */
    public static byte[] base64TOByte(String imagePath) throws Exception{
        BASE64Decoder base64Decoder = new BASE64Decoder();
        return base64Decoder.decodeBuffer(imageToBase64(imagePath));
    }

    /**
     * 图片自适应
     * @param base64
     * @param autoScale
     * @return
     * @throws Exception
     */
    public static Image generateImage(String base64, boolean autoScale) throws Exception{
        BASE64Decoder base64Decoder = new BASE64Decoder();
        Image image = new Image(ImageDataFactory.create(base64Decoder.decodeBuffer(base64)));
        image.setAutoScale(autoScale);
        return image;
    }

    /**
     * 图片居中显示 目前用margin控制
     * @param base64
     * @param pageSize
     * @return
     */
    public static Image generateImage(String base64, PageSize pageSize) throws Exception{
        BASE64Decoder base64Decoder = new BASE64Decoder();
        Image image = new Image(ImageDataFactory.create(base64Decoder.decodeBuffer(base64)));
        float pageEmptyWidth =  pageSize.getWidth()- PDFStyleContants.MARGIN_LEFT- PDFStyleContants.MARGIN_RIGHT;
        float imageWidth = image.getImageWidth();
        if (imageWidth > pageEmptyWidth){
            image.setWidth(pageEmptyWidth);
        }else{
            float margin = (pageEmptyWidth-imageWidth)/2;
            image.setMarginRight(margin).setMarginLeft(margin);
        }

        return image;
    }
    /**
     * @Description: 将图片转换成base64编码的字符串
     * @param @param imageSrc 文件路径
     * @param @return
     * @return String
     * @throws IOException
     */
    public static String imageToBase64(String imageSrc) throws IOException{
        //判断文件是否存在
        File file=new File(imageSrc);
        if(!file.exists()){
            throw new FileNotFoundException("文件不存在!");
        }
        StringBuilder pictureBuffer = new StringBuilder();
        FileInputStream input=new FileInputStream(file);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] temp = new byte[1024];
        for(int len = input.read(temp); len != -1;len = input.read(temp)){
            out.write(temp, 0, len);
        }
        pictureBuffer.append(Base64.getEncoder().encodeToString(out.toByteArray()));
        input.close();
        return pictureBuffer.toString();
    }

}
View Code
TableHelper 表格相关数据处理,表格居中,默认值
package com.example.note.pdf;

import com.example.note.pdf.domain.IgnoreFiled;
import com.example.note.pdf.domain.PDFStyleContants;
import com.example.note.pdf.domain.SeqNo;
import com.itextpdf.kernel.colors.Color;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import com.itextpdf.layout.property.VerticalAlignment;
import org.apache.commons.collections4.CollectionUtils;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wqqing
 * @date 2022/8/25 20:07
 */
public class TableHelper {

    /**
     * 获取表头
     * @param table
     * @param rowspan
     * @param colspan
     * @param headers
     */
    public static void header(Table table, int rowspan, int colspan, List<String> headers){
        for(String head : headers){
            table.addHeaderCell(headCell(rowspan, colspan, head));
        }
    }

    /**
     * 内容处理
     * @param table
     * @param rowspan
     * @param colspan
     * @param texts
     */
    public static void content(Table table, int rowspan, int colspan, List<Object> texts){
        for(Object text : texts){
            table.addCell(cell(rowspan, colspan, text,false));
        }

    }

    /**
     * 处理表格头部数据
     * @param rowspan
     * @param colspan
     * @param text
     * @return
     */
    public static Cell headCell(int rowspan, int colspan, String text){
        return headCell(rowspan, colspan, 0, 0, text);
    }

    /**
     * 单元格
     * @param rowspan 行合并数
     * @param colspan 列合并数
     * @param height 高度
     * @param width 宽度
     * @param text 内容
     * @return
     */
    public static Cell headCell(int rowspan, int colspan, float height, float width, String text){
        return cell(rowspan, colspan, PDFHelpers.paragraph(text, true), height, width,  40, true, null, PDFStyleContants.GRAY);
    }

    /**
     * 单元格
     * @param rowspan 行合并数
     * @param colspan 列合并数
     * @param text 内容
     * @param bold 是否加粗
     * @return
     */
    public static Cell cell(int rowspan, int colspan, Object text, boolean bold){
        return cell(rowspan, colspan, PDFHelpers.paragraph(text, bold));
    }

    /**
     * 单元格
     * @param rowspan 行合并数
     * @param colspan 列合并数
     * @param text 内容
     * @return
     */
    public static Cell cell(int rowspan, int colspan, Paragraph text){
        return cell(rowspan, colspan, text, 0 ,0, 0);
    }

    /**
     * 单元格
     * @param rowspan 行合并数
     * @param colspan 列合并数
     * @param text 内容
     * @param height 高度
     * @param width 宽度
     * @param minHeight 最小高度
     * @return
     */
    public static Cell cell(int rowspan, int colspan, Paragraph text, float height, float width, float minHeight){
        return cell(rowspan, colspan, text, height, width, minHeight, true, null, null);
    }

    /**
     * 单元格
     * @param rowspan 行合并数
     * @param colspan 列合并数
     * @param text 内容
     * @param height 高度
     * @param width 宽度
     * @param minHeight 最小高度
     * @param isDefaultBorder 是否默认边康
     * @param border 自定义边框
     * @return
     */
    public static Cell cell(int rowspan, int colspan, Paragraph text, float height, float width, float minHeight, boolean isDefaultBorder, Border border){
        return cell(rowspan, colspan, text, height, width, minHeight, isDefaultBorder, border, null);
    }

    /**
     * 单元格处理
     * @param rowspan 行合并数
     * @param colspan 列合并数
     * @param text 内容
     * @param height 高度
     * @param width 宽度
     * @param minHeight 最小高度
     * @param isDefaultBorder 是否默认边框
     * @param border 自定义边框
     * @param background 背景
     * @return
     */
    public static Cell cell(int rowspan, int colspan, Paragraph text, float height, float width, float minHeight, boolean isDefaultBorder, Border border,
                            Color background){
        return cell(rowspan, colspan, text, height, width, minHeight, isDefaultBorder, border, background, null, null, null);
    }

    /**
     * 单元格处理
     * @param rowspan 行合并数
     * @param colspan 列合并数
     * @param text 内容
     * @param isDefaultBorder 是否默认边框
     * @param border 自定义边框
     * @param textAlignment 文字布局
     * @param horizontalAlignment 水平方式布局
     * @param verticalAlignment 垂直方向布局
     * @return
     */
    public static Cell cell(int rowspan, int colspan, Paragraph text, boolean isDefaultBorder, Border border, TextAlignment textAlignment, HorizontalAlignment horizontalAlignment,
                            VerticalAlignment verticalAlignment) {
        return cell(rowspan, colspan, text, 0, 0, 0, isDefaultBorder, border, null, textAlignment, horizontalAlignment, verticalAlignment);
    }

    /**
     * 默认为内容居中
     * @param rowspan 行合并数
     * @param colspan 列合并数
     * @param text 内容
     * @param height 高度
     * @param width 宽度
     * @param minHeight 最小高度
     * @param isDefaultBorder 是否默认边框
     * @param border 自定义边框
     * @param background 背景色
     * @param textAlignment 文字布局
     * @param horizontalAlignment 水平布局
     * @param verticalAlignment 垂直布局
     * @return
     */
    public static Cell cell(int rowspan, int colspan, Paragraph text, float height, float width, float minHeight, boolean isDefaultBorder, Border border,
                            Color background, TextAlignment textAlignment, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment){
        Cell cell = new Cell(rowspan, colspan);
        if(!isDefaultBorder){
            cell.setBorder(border);
        }
        if (0 != minHeight){
            cell.setMinHeight(minHeight);
        }
        if (null != textAlignment){
            cell.setTextAlignment(textAlignment);
        }else{
            cell.setTextAlignment(TextAlignment.CENTER);
        }
        if (null != horizontalAlignment){
            cell.setHorizontalAlignment(horizontalAlignment);
        }else{
            cell.setHorizontalAlignment(HorizontalAlignment.CENTER);
        }
        if (null != verticalAlignment){
             cell.setVerticalAlignment(verticalAlignment);
        }else {
            cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
        }
        if (null != background){
            cell.setBackgroundColor(background);
        }
        if (0 != height){
            cell.setHeight(height);
        }
        if (0 != width){
            cell.setWidth(width);
        }
        cell.setKeepTogether(true);
        cell.add(text);
        return cell;
    }

    /**
     * 默认数据处理
     * @param size
     * @param defaultValue
     */
    public static void defaultData(Table table, int rowspan, int colspan, int size, String defaultValue){
        for(int i =0; i<size; i++){
            table.addCell(cell(rowspan, colspan, defaultValue, false));
        }
    }

    /**
     *
     * @param table pdf表格
     * @param rowspan 行合并数
     * @param colspan 列合并数
     * @param colSize 列数
     * @param list 数据
     * @param t 数据类对象
     * @param <T>
     * @throws Exception
     */
    public static<T> void content(Table table, int rowspan, int colspan, int colSize, List<T> list, Class<T> t) throws Exception{
        if (CollectionUtils.isEmpty(list)){
            defaultData(table, rowspan, colspan, colSize, "-");
            return;
        }
        Field[] fields = t.getDeclaredFields();
        List<Field> fieldList = Arrays.stream(fields).filter(e->null == e.getAnnotation(IgnoreFiled.class)).sorted((f1, f2)->{
            int seq1 = f1.getAnnotation(SeqNo.class).value();
            int seq2 = f2.getAnnotation(SeqNo.class).value();
            return seq1 - seq2;
        }).collect(Collectors.toList());

        for(T data : list){
            for(Field field : fieldList){
                field.setAccessible(true);
                table.addCell(cell(rowspan, colspan, field.get(data), false));
            }
        }
    }

    /**
     * 没有表头的数据
     * @param table
     * @param rowspan
     * @param colspan
     * @param colSize
     * @param datas
     */
    public static void content(Table table, int rowspan, int colspan, int colSize, List<String> datas){
        if (CollectionUtils.isEmpty(datas)){
            defaultData(table, rowspan, colspan, colSize, "-");
            return;
        }
        for(String str : datas){
            table.addCell(cell(rowspan, colspan, str, false));
        }

    }

    /**
     * 处理图片表格数据
     * @param table
     * @param rowspan
     * @param colspan
     * @param imageList
     * @throws Exception
     */
    public static void imageContent(Table table, int rowspan, int colspan, List<String> imageList) throws Exception{
        for(String str : imageList){
            Image img = ImageHelpers.generateImage(str, true);
            img.setAutoScale(true);
            Cell imageCell = new Cell(rowspan,colspan);
            imageCell.setKeepTogether(true);
            imageCell.setWidth(img.getWidth());
            imageCell.setHeight(img.getImageHeight());
            imageCell.setBorder(Border.NO_BORDER);
            imageCell.add(img);

            table.addCell(imageCell);
        }
    }

    /**
     * 结论以及建议表格
     * @param table
     * @param conclusion
     */
    public static void conclusionContent(Table table, String title, String conclusion){
        //固定头部信息
        Cell headCell = headCell(1, 1, title);
        headCell.setTextAlignment(TextAlignment.LEFT);
        table.addHeaderCell(headCell);
        if (null == conclusion){
            conclusion = "";
        }
        table.addCell(cell(1, 1, PDFHelpers.paragraph(conclusion, false), 0, 0,  50).setTextAlignment(TextAlignment.LEFT)
                .setVerticalAlignment(VerticalAlignment.TOP));
    }

    /**
     * 生成表格
     * @param colSize 列数
     * @param height 高度
     * @param fixWidth 是否确定宽度
     * @param width 宽度
     * @param horizontalAlignment 水平对齐方式
     * @param verticalAlignment 垂直对齐方式
     * @param fixLayOut 是否固定布局
     * @return
     */
    public static Table table(int colSize, float height, boolean isFixWidth, float fixWidth, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment,
                              boolean fixLayOut, float left, float bottom, float width){
        Table table = new Table(colSize);
        if (0 != height){
            table.setHeight(height);
        }
        if (isFixWidth){
            table.setWidth(fixWidth);
        }else {
            table.setWidth(UnitValue.createPercentValue(100));
        }
        if (null != horizontalAlignment){
            table.setHorizontalAlignment(horizontalAlignment);
        }
        if (null != verticalAlignment){
            table.setVerticalAlignment(verticalAlignment);
        }
        if (fixLayOut){
            table.setFixedLayout();
            table.setFixedPosition(left, bottom, width);
        }
        return table;

    }

}
View Code
PDFHelpers 对于一些div, paragraph的统一处理
package com.example.note.pdf;

import com.example.note.pdf.domain.PDFStyleContants;
import com.itextpdf.kernel.colors.Color;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import com.itextpdf.layout.property.VerticalAlignment;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.List;

/**
 * @author wqqing
 * @date 2022/8/26 14:55
 */
public class PDFHelpers {

    /**
     * div 包含table
     * @param table 表格
     * @param isKeepTogether 是否可断开
     * @return
     */
    public static Div div(Table table, boolean isKeepTogether){
        Div div = new Div();
        div.setKeepTogether(isKeepTogether);
        div.add(table);
        return div;
    }

    /**
     * div包裹图片 避免被分割
     * @param image
     * @return
     */
    public static Div div(Image image){
        Div div = new Div();
        div.setHorizontalAlignment(HorizontalAlignment.CENTER).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER);
        div.add(image);
        return div;
    }

    /**
     * 生成表格
     * @param colSize 列数
     * @param titles 表头信息
     * @param datas 表数据
     * @param t 表数据对象
     * @param <T>
     * @return
     * @throws Exception
     */
    public static<T> Table tablee(int colSize, List<String> titles, List<T> datas, Class<T> t) throws Exception{
        Table table = TableHelper.table(colSize, 0, false, 0, null, null, false,0 ,0, 0);
        TableHelper.header(table,1, 1, titles);
        TableHelper.content(table, 1, 1, colSize, datas, t);
        return table;
    }

    /**
     * 没有表头的表数据
     * @param colSize 表列数
     * @param datas 表数据
     * @return
     * @throws Exception
     */
    public static Table tablee(int colSize, List<String> datas) throws Exception{
        Table table = TableHelper.table(colSize, 0, false, 0, null, null, false, 0, 0, 0);
        TableHelper.content(table, 1, 1, colSize, datas);
        return table;
    }

    /**
     * 结论与建议代码块
     * @param info
     * @return
     */
    public static Table conclusion(String info){
        Table conclusion = new Table(1);
        conclusion.setWidth(UnitValue.createPercentValue(100));
        TableHelper.conclusionContent(conclusion, "结论及建议:", info);
        return conclusion;
    }

    /**
     *
     * @param text 内容
     * @param bold 是否加粗
     * @return
     */
    public static Paragraph paragraph(Object text, boolean bold){
        return paragraph(text, 0, bold, false);
    }

    /**
     *
     * @param text 内容
     * @param fontSize 字体
     * @param bold 是否加粗
     * @return
     */
    public static Paragraph paragraph(Object text, float fontSize, boolean bold){
        return paragraph(text, fontSize, bold, true);
    }

    /**
     * 段落处理
     * @param text 内容
     * @param fontSize 字体大小
     * @param bold 是否加粗
     * @param indentation 是否缩进
     * @return
     */
    public static Paragraph paragraph(Object text, float fontSize, boolean bold, boolean indentation){
        return paragraph(text, fontSize, null, bold, indentation);
    }

    /**
     * 段落处理
     * @param text 内容
     * @param fontSize 字体大小
     * @param color 颜色
     * @param bold 是否加粗
     * @param indentation 是否缩进
     * @return
     */
    public static Paragraph paragraph(Object text, float fontSize, Color color, boolean bold, boolean indentation){
        Paragraph paragraph = new Paragraph();
        paragraph.add(text(text, fontSize, color, bold));
        if (indentation){
            paragraph.setFirstLineIndent(PDFStyleContants.CONTENT_FONT_SIZE * 2);
        }
        paragraph.setMultipliedLeading(1.5f);
        return paragraph;
    }

    public static Text text(Object text, Color color, boolean bold){
        return text(text, 0, color, bold);
    }

    /**
     * 特色文本处理
     * @param text 内容
     * @param color 字体
     * @param bold 是否加粗
     * @return
     */
    public static Text text(Object text, float fontSize, Color color, boolean bold){
        Text result = new Text(String.valueOf(text));
        if (null != color){
            result.setFontColor(color);
        }
        if (0 != fontSize){
            result.setFontSize(fontSize);
        }
        if (bold){
            result.setBold();
        }
        return result;
    }

    /**
     * 图片并排处理
     * @param colSize 并列数
     * @param images 图片信息
     * @return
     * @throws Exception
     */
    public static Table imageOnLine(int colSize, List<String> images) throws Exception{
        Table imageTable = new Table(colSize);
        TableHelper.imageContent(imageTable, 1, 1, images);
        return imageTable;
    }

    /**
     * 统一模块处理
     * @param document
     * @param title 标题
     * @param desc 描述
     * @param colSize 表列数
     * @param titles 表头
     * @param datas 表数据
     * @param t 表数据对象
     * @param images 图片信息
     * @param conclusion 结论
     * @param <T>
     * @throws Exception
     */
    public static<T> void common(Document document, String title, String desc, int colSize, List<String> titles, List<T> datas,
                                 Class<T> t, boolean isKeepTogether, List<String> images, boolean isSingeImage, String conclusion) throws Exception{
        if (StringUtils.isNotEmpty(title)){
            document.add(paragraph(title, PDFStyleContants.TITLE_FONT_SIZE, true, false));
        }

        if (StringUtils.isNotEmpty(desc)){
            document.add(paragraph(desc, 0, false, true));
        }
        if(null != datas){
            Div div = div(
                    tablee(colSize, titles, datas, t), isKeepTogether
            );
            document.add(div);
        }
        document.add(new Paragraph());
        //图片
        if (CollectionUtils.isNotEmpty(images)){
            if (isSingeImage){//图片单独显示
                for(String image : images){
                    Image image1 = ImageHelpers.generateImage(image, document.getPdfDocument().getDefaultPageSize());
                    document.add(div(image1));
                }
            }else {
                //图片并排
                document.add(imageOnLine(2, images));
            }
        }
        document.add(new Paragraph());
        //结论以及建议
        document.add(conclusion(conclusion));
    }

}
View Code
GeneratePDFReport 生成PDF报告
package com.example.note.pdf;

import com.example.note.pdf.domain.Constants;
import com.example.note.pdf.domain.PDFStyleContants;
import com.example.note.pdf.domain.PdfTestInfo;
import com.example.note.pdf.domain.entity.PDFTest;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.AreaBreakType;
import com.itextpdf.layout.property.TextAlignment;

import java.io.FileOutputStream;
import java.util.Arrays;


/**
 * @author wqqing
 * @date 2022/8/25 15:07
 */
public class GeneratePDFReport {

    public static void main(String[] args) {
        try{
//            generatePdf();
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public static void generatePdf(PdfTestInfo info) throws Exception{

        FileOutputStream out = new FileOutputStream("D:/test.pdf");
        PdfFont pdfFont = PdfFontFactory.createFont(Constants.SONGTI_FONTS_PATH, PdfEncodings.IDENTITY_H);
        PdfWriter pdfWriter = new PdfWriter(out);
        PdfDocument pdfDocument = new PdfDocument(pdfWriter);
        Document document = new Document(pdfDocument, PageSize.A4);
        document.setMargins(PDFStyleContants.MARGIN_TOP, PDFStyleContants.MARGIN_RIGHT, PDFStyleContants.MARGIN_BOTTOM, PDFStyleContants.MARGIN_LEFT);
        document.setFont(pdfFont);
        document.setFontSize(PDFStyleContants.CONTENT_FONT_SIZE);
        //页眉处理
        pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new HeaderFooterHanlder(pdfFont, "页眉测试", "2022年08"));

        //首页加背景图
        commonPage(pdfDocument, document, info.getImage1(), "图片上带有文字", "wqq版权所有");
        //表格,图片以及段落处理
        handleData(document, info);

        //强制下一页
        document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
        //最后一页
        document.add(ImageHelpers.generateBackgroudImage(info.getImage2(), pdfDocument));
        document.close();


    }

    private static void handleData(Document document, PdfTestInfo info) throws Exception{
        document.add(PDFHelpers.paragraph("标题", 0, true, false));
        Paragraph paragraph = new Paragraph();
        paragraph.add("测试字体变色处理")
                .add(PDFHelpers.text("红色了", PDFStyleContants.RED, false));
        paragraph.setFirstLineIndent(PDFStyleContants.CONTENT_FONT_SIZE * 2);
        document.add(paragraph);
        //图片
        PDFHelpers.common(document, null, null, 3, Arrays.asList("名称", "描述", "信息"), info.getTableDatas(), PDFTest.class, true,
                info.getImages(),false, "结论与建议");
    }


    /**
     *
     * @param pdfDocument
     * @param document
     * @param desc
     * @param info
     * @throws Exception
     */
    private static void commonPage(PdfDocument pdfDocument, Document document,  String imagePath, String desc,
                                   String info) throws Exception {
        PdfFont pdfFont = PdfFontFactory.createFont(Constants.YAHEI_FONTS_PATH, PdfEncodings.IDENTITY_H);
        /**第一页处理**/
        document.add(ImageHelpers.generateBackgroudImage(imagePath, pdfDocument));
        //文字信息
        PdfPage start1 =pdfDocument.getPage(1);
        Canvas canva1 = new Canvas(start1, start1.getPageSize());
        canva1.setFontColor(PDFStyleContants.WHITE)
                .setFontSize(PDFStyleContants.CONTENT_FONT_SIZE)
                .setFont(pdfFont)
                .showTextAligned(new Paragraph().add(desc), 110, 130, TextAlignment.CENTER)
                .showTextAligned(new Paragraph().add(info), 105, 100, TextAlignment.CENTER);
        canva1.close();
    }
}
View Code

自己对itext7 也是第一次接触,有啥不对的,请大佬指教,转载请注明文章出处



posted on 2022-08-30 17:45  背着核的桃子  阅读(2573)  评论(0编辑  收藏  举报

导航