Java指定格式的pdf导出

一、导出工具类

传入参数为需要渲染的数据,以及模板的位置。
需要准备好字体文件,同项目一起打包。可以在”控制面板\外观和个性化\字体“中找到想要的字体
其中工具类传入的参数示例为:

List<QuestionExportVO> questionExportVOList  = new ArrayList<>();          
Map<String, Object> data = new HashMap<>();
data.put("questionExportVOList", questionExportVOList);
baos = PDFTemplateUtil.createPDF(data, "QuestionReplyDetails.ftl");
public class PDFTemplateUtil {
    /**
     * 通过模板导出pdf文件
     *
     * @param data 数据
     * @throws Exception
     */
    public static ByteArrayOutputStream createPDF(Object data, String templateName) throws Exception {
        // 创建一个FreeMarker实例, 负责管理FreeMarker模板的Configuration实例
        Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // 指定FreeMarker模板文件的位置
        cfg.setClassForTemplateLoading(PDFTemplateUtil.class, "/templates");
        ITextRenderer renderer = new ITextRenderer();
        try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            // 设置 css中 的字体样式(暂时仅支持宋体和黑体) 必须,不然中文不显示
            renderer.getFontResolver().addFont("/templates/font/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            renderer.getFontResolver().addFont("/templates/font/calibrib.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            // 设置模板的编码格式
            cfg.setEncoding(Locale.CHINA, "UTF-8");
            // 获取模板文件
            Template template = cfg.getTemplate(templateName, "UTF-8");
            StringWriter writer = new StringWriter();

            // 将数据输出到html中
            template.process(data, writer);
            writer.flush();

            String html = writer.toString();
            // 把html代码传入渲染器中
            renderer.setDocumentFromString(html);
            renderer.layout();

            renderer.createPDF(out, false);
            renderer.finishPDF();
            out.flush();
            return out;
        }
    }
}

二、配置模板

根据需求画出想要的界面,注意并不是html,而是ftl格式(可以先画一个html,画出想要的格式后,再改造成ftl)。
其中有很多ftl格式才有的标签,用于实现数据渲染。可以做到动态增加表格,比如:

<#list detail.images as image>
          <#if image ??>
               <img style="width: 99%;padding-left: 2px;padding-top: 2px;" src="${image}" alt="image"/>
          </#if>
</#list>

<#list detail.images as image>代表在集合中循环操作,??代表如果对象存在(不为null)的话

${(child.conclusion)!''}则代表如果为null的时候,则用空字符串作为默认输出值

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8"/>
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: SimSun;
            padding: 30px 20px 0;
        }

        section {
            display: block;
        }

        .preface p {
            line-height: 30px;
            display: inline-block;
        }

        section > table {
            page-break-inside: auto;
            -fs-table-paginate: paginate;
            border-spacing: 0;
            cellspacing: 0;
            cellpadding: 0;
            border-collapse: collapse;
            table-layout: fixed;
            width: 100%;
            font-size: 13px;
            text-align: left;
            word-wrap: break-word;
        }

        section table td {
            padding: 5px 0;
        }

        section table tr {
            page-break-inside: avoid;
            page-break-after: auto;
        }

        .topTitle section {
            width: 30%;
            font-size: 13px;
            display: inline-block;
            margin-top: 20px;
        }

        .outTitle section {
            font-size: 13px;
            display: inline-block;
        }

        .detail {
            margin-top: 20px;
        }

        .box3 img {
            width: 100%;
        }

        .box3 p {
            font-size: 12px;
        }

        img {
            width: 50%;
        }
    </style>
</head>

<body>

<#if questionExportVOList ??>
    <section class="detail">
        <table border="1" cellspacing="0" cellpadding="0">
            <#list questionExportVOList as data>
                <tr style="font-weight: bold;font-size: 14px;text-align: center;">
                    <td colspan="2" width="100%">问题归属成果:${(data.stageOutcomeName)!''}</td>
                </tr>
                <#list data.questionDetails as detail>
                    <tr>
                        <td colspan="2" width="100%" style="font-family: Calibri;font-weight: bold;font-size: 12px;background-color:yellow;">&nbsp;&nbsp;${(detail.serialNumber)!''}</td>
                    </tr>
                    <tr>
                        <th rowspan="7">
                            <#list detail.images as image>
                                <#if image ??>
                                    <img style="width: 99%;padding-left: 2px;padding-top: 2px;" src="${image}" alt="image"/>
                                </#if>
                            </#list>

                        </th>
                        <td><b style="font-size: 12px;">问题所属图纸或模型:</b>${(detail.fileName)!''}</td>
                    </tr>
                    <tr>
                        <td><b style="font-size: 12px;">问题标题:</b>${(detail.questionTitle)!''}</td>
                    </tr>
                    <tr>
                        <td><b style="font-size: 12px;">问题描述:</b>${(detail.questionDesc)!''}</td>
                    </tr>
                    <tr>
                        <td>专业:${(detail.major)!''}</td>
                    </tr>
                    <tr>
                        <td>知悉人员:${(detail.knowingStaff)!''}</td>
                    </tr>
                    <tr>
                        <td>主责人员:${(detail.participants)!''}</td>
                    </tr>
                    <tr>
                        <td>上传附件:${(detail.attachmentName)!''}</td>
                    </tr>
                    <#if detail.children ??>
                        <#list detail.children as child>
                            <tr style="font-weight: bold;font-size: 12px;">
                                <td colspan="2" width="100%">${(child.operate)!''}</td>
                            </tr>
                            <#if child.conclusion ??>
                                <tr>
                                    <td>复核人员:${(child.createBy)!''}</td>
                                    <#if child.conclusion == "同意">
                                        <td>复核结论:<b style="color: green;">${(child.conclusion)!''}</b></td>
                                    <#else >
                                        <td>复核结论:<b style="color: red;">${(child.conclusion)!''}</b></td>
                                    </#if>
                                </tr>
                            <#else >
                                <tr>
                                    <td colspan="2" width="100%">回复人员:${(child.createBy)!''}</td>
                                </tr>
                            </#if>
                            <#if child.replyContent ??>
                                <tr>
                                    <td colspan="2" width="100%">${(child.replyContent)!''}</td>
                                </tr>
                            </#if>
                        </#list>
                    </#if>
                </#list>
            </#list>
        </table>
    </section>
</#if>

</body>

</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容