• 使用PDFBox封装一个简单易用的工具类快速生成pdf文件


    一、PDFbox说明

    1、坐标

    文档左下角为坐标原点,x轴向右从0增加,y轴向上增加

    2、线

    以起始位置至终点一条线,线宽以垂直于起始至终止连线方向发散,例如线宽20,起始位置(0,10),终止位置(500,10)则线实际所占位置为(0,0),(0,20),(500,0),(500,20)所围成的长方形区域

    3、图

    图位置以左下角为原点向右上方发散

    4、字

    字的位置以左下角为原点向右上方发散

            // 横线
            contentStream.moveTo(0, 10);
            contentStream.lineTo(540, 10);
            contentStream.stroke();
     
            // 竖线
            contentStream.moveTo(10, 0);
            contentStream.lineTo(10, 540);
            contentStream.stroke();
     
            // 斜线
            contentStream.moveTo(0, 0);
            contentStream.lineTo(540, 540);
            contentStream.stroke();
     
            // 图片
            final byte[] imageByte = IOUtils.toByteArray(Objects.requireNonNull(DrawTableUtils.class.getClassLoader().getResourceAsStream("yellow.png")));
            final PDImageXObject image = PDImageXObject.createFromByteArray(document, imageByte, "yellow.png");
            contentStream.drawImage(image, 20, 0, 50, 50);
            // 文字
            contentStream.beginText();
            contentStream.setFont(PDType1Font.HELVETICA_BOLD, 10);
            contentStream.newLineAtOffset(0, 10);
            String text = "This is the sample document and we are adding content to it.";
            contentStream.showText(text);
            contentStream.endText();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    5、字体加载

    1、ttf类型字体加载

           InputStream inFont = DrawTableUtils.class.getClassLoader().getResourceAsStream(fontName);
            PDType0Font normalFont = PDType0Font.load(document, inFont);
            PDType0Font boldFont = null;
    
    • 1
    • 2
    • 3

    2.otf类型字体加载

            InputStream normalStream = DrawTableUtils.class.getClassLoader().getResourceAsStream(fontName);
            assert normalStream != null;
            OpenTypeFont normalOtfFont = new OTFParser(false, true).parse(normalStream);
            PDType0Font normalFont = PDType0Font.load(document, normalOtfFont, false);
    
    • 1
    • 2
    • 3
    • 4

    6、jfreechart图表转字节数组

    JFreeChart chart = new JFreeChart(title, xyplot);
    // 图例字体清晰
    chart.setTextAntiAlias(true);
    chart.setBackgroundPaint(Color.WHITE);
    TextTitle textTitle = chart.getTitle();
    textTitle.setFont(new Font("黑体", Font.PLAIN, 20));
    BufferedImage bufferedImage = chart.createBufferedImage(600, 300);
    byte[] bytes = ChartUtilities.encodeAsPNG(bufferedImage);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    7、依赖

    		<dependency>
    			<groupId>org.apache.pdfboxgroupId>
    			<artifactId>pdfboxartifactId>
    			<version>2.0.28version>
    		dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    二、PDFbox样式

    1、文字颜色

    Color color = new Color(255,0,0);
    contentStream.setNonStrokingColor(color);
    
    • 1
    • 2

    2、线颜色

    Color color = new Color(255, 0, 0);
    contentStream.setStrokingColor(color);
    
    • 1
    • 2

    3、线样式

     float[] a={
       3,5};
            contentStream.setLineDashPattern(a, 0);
            contentStream.moveTo(0, 20);
            contentStream.lineTo(540, 20);
            contentStream.stroke();
     
            contentStream.setLineDashPattern(a, 20);
            contentStream.moveTo(0, 50);
            contentStream.lineTo(540, 50);
            contentStream.stroke();
     
            float[] b={
       3};
            contentStream.setLineDashPattern(b, 20);
            contentStream.moveTo(0, 80);
            contentStream.lineTo(540, 80);
            contentStream.stroke();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    contentStream.setLineDashPattern(a, 0);

    第一个参数 a={3,5} 3表明虚线宽度为3,5表明虚线间隔为5 。当a={3}时表明虚线宽度为3,间隔为3

    第二个参数0表明虚线偏移量

    三、工具类

    边框样式

    public enum BorderStyle {
       
     
        SOLID(new float[]{
       }, 0),
        DOTTED(new float[]{
       1}, 1),
        DASHED(new float[]{
       5,2}, 1);
     
        private final float[] pattern;
        private final int phase;
     
        BorderStyle(float[] pattern, int phase) {
       
            this.pattern = pattern;
            this.phase = phase;
        }
     
        public float[] getPattern() {
       
            return pattern;
        }
     
        public int getPhase() {
       
            return phase;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    对齐样式

    public enum HorizontalAlignment {
       
     
        LEFT, CENTER, RIGHT
     
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

     
    @Data
    public class PdfTable {
       
        /**
         * 行
         */
        private List<PdfRow> rows;
        /**
         * 字体
         */
        private String font;
        public void addRow(PdfRow row){
       
            rows.add(row);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    @Data
    @Builder
    public class PdfRow {
       
        /**
         * 列
         */
        private List<PdfColumn> pdfColumns;
        /**
         * 行高
         */
        private float height;
        /**
         * 边框样式,仅下边框生效
         */
        private BorderStyle borderStyle;
        /**
         * 边框颜色
         */
        @Builder.Default
        private Color boderColor=Color.BLACK;
        /**
         * 下边框是否生效
         */
        private boolean downBorder;
     
        public void addColumn(PdfColumn pdfColumn){
       
            pdfColumns.add(pdfColumn);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    @Data
    @Builder
    public class PdfColumn {
       
        /**
         * 背景颜色
         */
        @Builder.Default
        private Color backGround = Color.WHITE;
        /**
         * 边框颜色
         */
        @Builder.Default
        private Color borderColor = Color.BLACK;
        /**
         * 文字颜色
         */
        @Builder.Default
        private Color textColor= Color.BLACK;
        /**
         * 加粗
         */
        @Builder.Default
        private boolean block=false;
        /**
         * 文字大小
         */
        @Builder.Default
        private float fontSize=10F;
        /**
         * 偏移
         */
        @Builder.Default
        private float offset=0F;
        /**
         * 文字位置
         */
        @Builder.Default
        private HorizontalAlignment align =HorizontalAlignment.CENTER;
        /**
         * 自动宽度
         */
        @Builder.Default
        private boolean autoWidth=false;
        /**
        * 自动换行
        */
        @Builder.Default
        private boolean autoWidth=false;
        /**
         * 左边框
         */
        private boolean leftBorder;
        /**
         * 右边框
         */
        private boolean rightBorder;
        /**
         * 名称
         */
        private String name;
        /**
         * 宽度,仅在自动宽度未生效时启用
         */
        private float width;
        /**
         * 图片,图片生效时其他属性均不生效
         */
        private PdfColumnImage columnImage;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    图片列

    @Data
    @Builder
    public class PdfColumnImage {
       
        /**
         * 图片名称/路径
         */
        private String image;
        /**
         * x轴位置
         */
        private float x;
        /**
         * y轴位置
         */
        private float y;
        /**
         * 图片宽度
         */
        private float width;
        /**
         * 图片高度
         */
        private float height;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    pdf工具类

    public class DrawTableUtils {
       
     
        /**
         * 页边距
         */
        private static final float PADDING = 30;
        /**
         * 下表格线偏移
         */
        private static final float DOWN_LINE_PADDING = 0.5f;
        /**
         * 边框宽度
         */
        private static final float BORDER_WIDTH = 1;
        /**
         * 生成PDF
         *
         * @param table pdf数据
         * @throws IOException
         */
        public static void createDocument(PdfTable table) throws IOException {
       
            // 初始化文档
            PDDocument document = new PDDocument();
            final PDPage page = new PDPage(PDRectangle.A4);
            document.addPage(page);
            // 字体
            String fontName = table.getFont();
            InputStream inFont = org.bmc.DrawTableUtils.class.getClassLoader().getResourceAsStream(fontName);
            PDType0Font font = PDType0Font.load(document, inFont);
            // 页
            int pageNum = 1;
            // 初始化文档位置
            org.bmc.DrawTableUtils.Position position = new org.bmc.DrawTableUtils.Position(PADDING, page.getMediaBox().getHeight() - PADDING, 0);
            PDPageContentStream contentStream = new PDPageContentStream(document, page);
     
            for (PdfRow row : table.getRows()) {
       
                // 分页
                if (position.startY <= PADDING * 2) {
       
                    pageNum++;
                    PDPage pdPage = new PDPage(PDRectangle.A4);
                    document.addPage(pdPage);
                    position.startY = page.getMediaBox().getHeight() - PADDING;
                    contentStream.close();
                    contentStream = new PDPageContentStream(document, pdPage);
                }
     
                drawLine(row, document, contentStream, position, font);
     
                if (row.isDownBorder()) {
       
                    drawDrownBorder(contentStream, page, row, position);
                }
     
     
            }
            contentStream.close();
            // 页脚
            drawPageFoot(document, pageNum, font);
            // 保存文档
            document.save("D:/mypdf.pdf");
            document.close();
        }
     
     
        /**
         * 生成表格下框,以行为单位
         *
         * @param contentStream 流
         * @param page          页
         * @param row           行
         * @param position      位置
         * @throws IOException
         */
        private static void drawDrownBorder(PDPageContentStream contentStream, PDPage page, PdfRow row, org.bmc.DrawTableUtils.Position position) throws IOException {
       
            contentStream.
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
  • 相关阅读:
    Python---函数的作用,定义,使用步骤(调用步骤)
    java基于springboot高校学术交流论坛maven
    线性调频雷达回波仿真+脉冲压缩仿真
    windows下nginx基本指令
    锥坡 锥坡 锥坡
    MyBatis
    Hadoop源码解析
    语义分割 语义通信 增强模型图片处理
    面试经典sql(大数据):连续登陆问题
    MyBatis笔记目录
  • 原文地址:https://blog.csdn.net/weixin_44001965/article/details/136511007