Itextpdf添加页眉页脚页码

项目需要样式比较复杂,刚开始因为时间比较紧所以采用了Itextpdf插件代码生成pdf ,实话说过程十分繁琐,因为pdf文件样式比较多,表格也比较多,各种的表格,还有就是页眉页脚页码都要自己找页面位置坐标但是又不能像html那样方便更改查看样式,只能改一点导出来看看合适不,然后再改再导出来看。
私下调研了很多,现在罗列一下我所用到的一些样式处理,希望可以帮助需要做这个功能的朋友少踩坑,少尝试,直接出完美pdf报告。

  1. 封面
    Itextpdf添加页眉页脚页码_第1张图片
  2. 首页Itextpdf添加页眉页脚页码_第2张图片
    封面右上角那个图片可以换成logo,我做的大概是这样的一个样子,上代码
//定义 页面大小,以及页边距左右上下
package com.example.demo.controller;

import com.example.demo.config.PDFConfig;
import com.example.demo.utils.PDFBuilder;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.draw.LineSeparator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author hongli.zhang
 * @create 2020/5/26 13:02
 **/

@RestController
@RequestMapping("/businessApplication/")
public class PdfContrller {

    @Autowired
    PDFConfig config;//这个是配置类,里面设置了需要用到的字体和logo图片的绝对路径
    public static void setImg(PdfWriter writer, String path, float fitWidth, float fitHeight, float absoluteX, float absoluteY) {
        try {
            Image image = Image.getInstance(path);
            image.setAlignment(Image.MIDDLE);
            image.scaleToFit(fitWidth, fitHeight);
            image.setAbsolutePosition(absoluteX, absoluteY);
            writer.getDirectContent().addImage(image);
        }catch(Exception e){
        }
    }
    @GetMapping("/test")
    public void test(HttpServletRequest requ, HttpServletResponse resp) throws DocumentException {

//设置页面大小为A4纸大小,以及页边距左右上下
        Document document = new Document(PageSize.A4, 100F, 100F, 80F, 120F);
        PdfWriter writer = null;
        try {
            FileOutputStream out = new FileOutputStream("E:\\new.pdf");
            writer = PdfWriter.getInstance(document, out);
        } catch ( IOException | DocumentException e) {
            e.printStackTrace();
        }
        // 定义页眉和页脚页码事件,PDFBuilder代码在后面
        PDFBuilder builder = new PDFBuilder();
        //设置页面监听事件
        writer.setPageEvent(builder);

        document.open();
        //换行
        Paragraph newLine = new Paragraph("\n");
        float tableWidthPercentage = 100f; //表格的整体宽度

        //表格背景色
        BaseColor green = new BaseColor(175, 215, 136);
        BaseColor blue = new BaseColor(148, 170, 214);

        //图标
        setImg(writer, config.getLogo(), 130, 100, document.getPageSize().getRight(230), 700);
        //所需字体
        String fontPath = config.getCalibri();
        String fontBlodPath = config.getCalibrib();
        BaseFont bf = null;
        BaseFont blodbf = null;
//        BaseFont chineseFont = null;
//        BaseFont chineseBlodFont = null;
        try {
            bf = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            blodbf = BaseFont.createFont(fontBlodPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
//            chineseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        }
        Font coverFont = new Font(blodbf, 30, Font.NORMAL);
        Font titleFont = new Font(blodbf, 16, Font.NORMAL);
        Font coverTiletFontMarked = new Font(blodbf, 16f, Font.NORMAL, new BaseColor(148, 170, 214));
        Font textFontBold = new Font(blodbf, 10.5f, Font.NORMAL);
        Font textFont = new Font(bf, 10.5f, Font.NORMAL);
        Font textFontGray = new Font(blodbf, 10.5f, Font.NORMAL, new BaseColor(215, 215, 215));
        Font chapterFont = new Font(blodbf, 14f, Font.NORMAL);
//        Font coverFont = new Font(chineseFont, 30, Font.NORMAL);
//        Font titleFont = new Font(chineseFont, 16, Font.NORMAL);
//        Font coverTiletFontMarked = new Font(chineseFont, 16f, Font.NORMAL, new BaseColor(148, 170, 214));
//        Font textFontBold = new Font(chineseFont, 10.5f, Font.NORMAL);
//        Font textFont = new Font(chineseFont, 10.5f, Font.NORMAL);
//        Font textFontGray = new Font(chineseFont, 10.5f, Font.NORMAL, new BaseColor(215, 215, 215));
//        Font chapterFont = new Font(chineseFont, 14f, Font.NORMAL);


        //封面
        Paragraph cover = new Paragraph("\n\n\n"+"CompanyName In Here HAHAHAHAH"+"\nMy Company REPORT",coverFont);
        cover.setAlignment(Element.ALIGN_CENTER);
        Paragraph paragraph1 = new Paragraph("\n\n\nREPORT DATE: " +"2020/05/03 12:02:15", titleFont);
        paragraph1.setAlignment(Element.ALIGN_RIGHT);
        cover.add(paragraph1);
        cover.add(new LineSeparator(5f, 100, new BaseColor(148, 170, 214), Element.ALIGN_CENTER, 30f));
        cover.add(newLine);
        Paragraph paragraph2 = new Paragraph("REPORT ID: " + "B124568744", coverTiletFontMarked);
        paragraph2.setAlignment(Element.ALIGN_RIGHT);
        cover.add(paragraph2);
        document.add(cover);


        document.newPage();
        //添加首页
        Paragraph home = new Paragraph(new Chunk("MY Report\n", chapterFont));
        home.add(new Chunk("Report Type: Entity\n\n", textFontGray));
        home.add(new Chunk("Company Name:\n", textFontBold));
        home.add(new Chunk("JKLJI HJKHK NJNJ UHIU", titleFont));
        document.add(home);
//        document.add(line);

        document.add(newLine);
        document.add(newLine);
        PdfPTable riskDashTb = new PdfPTable(2);
        riskDashTb.setWidths(new float[]{0.4f, 0.6f});// 每个单元格占多宽
        riskDashTb.setWidthPercentage(tableWidthPercentage);
        riskDashTb.addCell(getCell(new Phrase("level", textFontBold), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("countryCode", textFont), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("Amount", textFontBold), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("nationality", textFont), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("Converted Credit Amount", textFontBold), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("addr", textFont), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("currency", textFontBold), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("busiZip", textFont), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("level", textFontBold), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("countryCode", textFont), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("Amount", textFontBold), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("nationality", textFont), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("Converted Credit Amount", textFontBold), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("addr", textFont), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("currency", textFontBold), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("busiZip", textFont), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("level", textFontBold), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("countryCode", textFont), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("Amount", textFontBold), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("nationality", textFont), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("Converted Credit Amount", textFontBold), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("addr", textFont), blue, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("currency", textFontBold), null, 1, 1));
        riskDashTb.addCell(getCell(new Phrase("busiZip", textFont), null, 1, 1));
        document.add(riskDashTb);
        document.add(newLine);

        document.add(new Paragraph("Note: The sdsd sdsd dsds is sd through a sdsds model that sdsd the sdsd of dsd of the sdsdsd company. aaa Amount is asas asa on sds saa dsdand other sdsd information.", textFont));
        document.add(newLine);
        Paragraph end = new Paragraph("End of the My Report", titleFont);
        end.setAlignment(Element.ALIGN_CENTER);
        document.add(end);
        document.close();

//            resp.getWriter().print("success");
    }


    private PdfPCell getCell(Phrase phrase, BaseColor color, int colSpan, int rowSpan) {
        PdfPCell cells = new PdfPCell(phrase);
        cells.setUseAscender(true);
        cells.setMinimumHeight(20f);
        cells.setHorizontalAlignment(Element.ALIGN_LEFT);
        cells.setVerticalAlignment(5);
        cells.setColspan(colSpan);
        cells.setRowspan(rowSpan);
        cells.setNoWrap(false);
        if (color != null) {
            cells.setBackgroundColor(color);
        }
        return cells;
    }


}

接下来是页眉页脚事件的代码PDFBUilder
因为页眉页脚都是带格式的,所以需要一点一点拼接起来,页眉中需要添加logo图片,位置是通过代码中的x,y坐标指定的

package com.example.demo.utils;

import com.example.demo.config.PDFConfig;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 设置页面附加属性
 *
 * @author hongli.zhang
 * @create 2020/5/18 21:00
 **/
@Component
public class PDFBuilder extends PdfPageEventHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(PDFBuilder.class);

    public Phrase header;

    public Phrase footer;

    // 模板
    public PdfTemplate total;

    // 基础字体对象
    public BaseFont bf = null;

    // 利用基础字体生成的字体对象,一般用于生成中文文字
    public Font fontDetail = null;

    public PDFBuilder() {

    }

    public PDFBuilder(Phrase header, Phrase footer) {
        this.header = header;
        this.footer = footer;
    }

    public void setHeader(Phrase header) {
        this.header = header;
    }

    public void setFooter(Phrase footer) {
        this.footer = footer;
    }

    /**
     * 文档打开时创建模板
     *
     * @param writer
     * @param document
     */
    public void onOpenDocument(PdfWriter writer, Document document) {
        total = writer.getDirectContent().createTemplate(50, 50);// 共 页 的矩形的长宽高
    }

    /**
     * 关闭每页的时候,写入页眉,页脚。
     *
     * @param writer
     * @param document
     */
    public void onEndPage(PdfWriter writer, Document document) {
        this.addPage(writer, document);
        //this.addWatermark(writer);
    }

    public static void setImg(PdfWriter writer, String path, float fitWidth, float fitHeight, float absoluteX, float absoluteY) {
        try {
            Image image = Image.getInstance(path);
            image.setAlignment(Image.MIDDLE);
            image.scaleToFit(fitWidth, fitHeight);
            image.setAbsolutePosition(absoluteX, absoluteY);
            writer.getDirectContent().addImage(image);
        } catch (Exception e) {
            LOGGER.error("[ERROR] Set Img : img file does not exist.");
        }
    }

    //加分页
    public void addPage(PdfWriter writer, Document document) {
        PDFConfig config = InjectUtil.getInstance().getConfig();
        if (document.getPageNumber() > 1) {
            try {
                bf = BaseFont.createFont(config.getCalibri(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            BaseFont blodf = null;
            try {
                blodf = BaseFont.createFont(config.getCalibrib(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            fontDetail = new Font(bf, 9, Font.NORMAL);// 数据体字体
            Font titleFnot = new Font(blodf, 10.5f, Font.NORMAL);
            Font blodFnot = new Font(blodf, 9f, Font.NORMAL);
            Font font = new Font(bf, 10.5f, Font.NORMAL);

            setImg(writer, "D:\\ceshi.jpg", 85, 45, 65, 785);
            Phrase pageNumberPh = new Phrase(String.valueOf(document.getPageNumber() - 1), fontDetail);
            float center = document.getPageSize().getRight() / 2;//页面的水平中点
            float left = document.getPageSize().getLeft(90);//页面的z左边距
            float headerleft = document.getPageSize().getLeft(180);//页面的z左边距
            float right = document.getPageSize().getRight(90);//页面的z左边距
            float top = document.getPageSize().getTop() - 36;
            float bottom = document.getPageSize().getBottom() + 36;

            header = new Paragraph("Beijing XXXX Information Technology Hn.,JKI.", titleFnot);
            Paragraph header1 = new Paragraph("5f, building C2, hkhkjhd Industrial Park,", font);
            Paragraph header2 = new Paragraph("No. 44, Changhu Road, Jiangxi Industrial Park", font);
            Paragraph header3 = new Paragraph("www.xxx.com", font);
            Paragraph header4 = new Paragraph("China (sss) xxxxxxxxxxxx Dgyhi Code Zone", font);
            Paragraph header5 = new Paragraph("400-1234-567", font);
            Paragraph footer1 = new Paragraph("Acnnecfds Kdjklsnf", blodFnot);
            Paragraph footer2 = new Paragraph("The dfdfdf fddffdfdf by fdfdf in thfdfiscxcx fdfd is based on fdfd fdfd has been fdf fdfdf fdfdfdfd erwerwerwerwrww",
                    new Font(bf, 9, Font.NORMAL));
            Paragraph footer3 = new Paragraph("ffdfdf and fdfdf fffdfd. fdsf fdfd fdfdf xcxcfdfd fdf fdf fdfd to fdfd that the dfdfdssxx is fdfdfdf and werwerwe",
                    new Font(bf, 9, Font.NORMAL));
            Paragraph footer4 = new Paragraph("seewwdrr, we fdf fdfdf fdfd any fdfdfdxcx for fddfdfdfd, fdfdf, fdferere rererer or rer-rere rer and a werwerwer",
                    new Font(bf, 9, Font.NORMAL));
            Paragraph footer5 = new Paragraph("rerer or rer of the rererer in rere rerer cxcxcxcxrer rere the retg of tfhe fffgvfgddsss on its sdfsd. The dddddw ",
                    new Font(bf, 9, Font.NORMAL));
            Paragraph footer6 = new Paragraph("information dsfsdf is DSFSDS DFFDDD and Sdcxvxcvdfdfsd not be dfsdfsdf to any sdfsdf sdfsdfsd the dsfsdfsfdsdfee ",
                    new Font(bf, 9, Font.NORMAL));
            Paragraph footer7 = new Paragraph("erdsfsdfsd. sdfsdf dsfsdf & dsfsdf dsfsdf sdfsdf of any sfddsfsdf dfdfdfdf the dfdf of the inforfmationssdeeetyy ",
                    new Font(bf, 9, Font.NORMAL));
//            Paragraph footer8 = new Paragraph("dfdfddff in this report.", new Font(bf, 9, Font.NORMAL));
            Paragraph footer9 = new Paragraph("[fdddfdfdfdf]", blodFnot);

//                ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, headerImg, center, top, 0); //页眉图标
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, header, headerleft, top + 13, 0); //页眉标题
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, header1, headerleft, top - 3, 0); //页眉内容
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, header2, headerleft, top - 15, 0); //页眉
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_RIGHT, header3, right, top - 15, 0); //页眉
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, header4, headerleft, top - 30, 0); //页眉
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_RIGHT, header5, right, top - 30, 0); //页眉
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_RIGHT, pageNumberPh, right, bottom + 65, 0); //页码
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, footer1, center, bottom + 60, 0); //页脚标题
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, footer2, left, bottom + 50, 0); //页脚
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, footer3, left, bottom + 40, 0); //页脚
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, footer4, left, bottom + 30, 0); //页脚
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, footer5, left, bottom + 20, 0); //页脚
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, footer6, left, bottom + 10, 0); //页脚
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, footer7, left, bottom, 0); //页脚
//            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, footer8, left, bottom - 10, 0); //页脚
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, footer9, center, bottom - 20, 0); //页脚
        }
    }

    //加水印
    public void addWatermark(PdfWriter writer) {
        // 水印图片
        Image image;
        try {
            image = Image.getInstance("");
            PdfContentByte content = writer.getDirectContentUnder();
            content.beginText();
            // 开始写入水印
            for (int k = 0; k < 5; k++) {
                for (int j = 0; j < 4; j++) {
                    image.setAbsolutePosition(150 * j, 170 * k);
                    content.addImage(image);
                }
            }
            content.endText();
        } catch (IOException | DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /*
     *
     *
     * TODO 关闭文档时,替换模板,完成整个页眉页脚组件
     * @see PdfPageEventHelper#onCloseDocument(PdfWriter,
     *      Document)
     */


    public void onCloseDocument(PdfWriter writer, Document document) {
        // 7.最后一步了,就是关闭文档的时候,将模板替换成实际的 Y 值,至此,page x of y 制作完毕,完美兼容各种文档size。
        total.beginText();
        total.setFontAndSize(bf, 9);// 生成的模版的字体、颜色
        String foot2 = " " + (writer.getPageNumber()) + " 页"; //页脚内容拼接  如  第1页/共2页
        total.showText(foot2);// 模版显示的内容
        total.endText();
        total.closePath();
    }
}

大概覆盖了大部分的功能,当然还有给字体加背景色,字体加颜色,和比较复杂的表格制作
比如需要将list中的数据按年份横排
Itextpdf添加页眉页脚页码_第3张图片
我罗列出来可能需要用到的网站地址,

你可能感兴趣的:(java)