欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)生成pdf并解決表格分割的問題

 更新時(shí)間:2023年11月30日 08:18:55   作者:苦瓜不苦077  
這篇文章主要為大家詳細(xì)介紹了如何利用Java實(shí)現(xiàn)生成pdf,并解決表格分割的問題,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

Maven依賴

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version>
</dependency>

<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf</artifactId>
    <version>9.1.16</version>
</dependency>

自定義ftl模板

該模板是由html頁面直接后綴而成,模版名稱定為template-01.ftl

注意事項(xiàng)

中文亂碼問題

需要在模板中添加font-family: SimSun, serif;標(biāo)簽,可解決中文亂碼問題

body {
    /*解決中文亂碼*/
    font-family: SimSun, serif;
    /*自動(dòng)換行*/
    word-break: break-all;
}

頁眉和頁腳

其實(shí)頁眉和頁腳可以通過定義的ftl模板來實(shí)現(xiàn)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
    <style>
        /*頁眉的上下左右邊距*/
        @page {
            margin: 30mm 20mm 30mm 20mm;
        }
        @page {
            /*頁眉*/
            @top-center {
                content: element(header)
            }
            /*頁腳*/
            @bottom-center {
                content: element(footer)
            }
        }
        /*頁眉*/
        #header {
            position: running(header);
            margin-top: 10mm;
        }
        /*頁腳*/
        #footer {
            position: running(footer);
        }
        /*分頁*/
        #page-number:before {
            content: counter(page);
        }
        /*分頁*/
        #page-count:before {
            content: counter(pages);
        }
    </style>
</head>
<body>
<!--頁眉-->
<div id="header">
    深圳市xxx有限公司
    <hr/>
</div>
<!--頁腳-->
<div id="footer">
    頁碼<span id="page-number"></span>/<span id="page-count"></span>
</div>
</body>
</html>

完整ftl模板頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
    <style>
        /*頁眉的上下左右邊距*/
        @page {
            margin: 30mm 20mm 30mm 20mm;
        }
        @page {
            /*頁眉*/
            @top-center {
                content: element(header)
            }
            /*頁腳*/
            @bottom-center {
                content: element(footer)
            }
        }
        /*頁眉*/
        #header {
            position: running(header);
            margin-top: 10mm;
        }
        /*頁腳*/
        #footer {
            position: running(footer);
        }
        /*分頁*/
        #page-number:before {
            content: counter(page);
        }
        /*分頁*/
        #page-count:before {
            content: counter(pages);
        }
        * {
            padding: 0;
            margin: 0;
        }
        body {
            /*解決中文亂碼*/
            font-family: SimSun, serif;
            /*自動(dòng)換行*/
            word-break: break-all;
        }
        .main {
            width: 100%;
            height: auto;
            margin: 0 auto;
            text-align: center;
        }
        table {
            width: 100%;
            border-collapse: collapse;
        }
        td, th {
            line-height: 20px;
            padding: 7px 5px;
            border: 1px solid #999999;
        }
    </style>
</head>
<body>
<!--頁眉-->
<div id="header">
    深圳市xxx有限公司
    <hr/>
</div>
<!--頁腳-->
<div id="footer">
    頁碼<span id="page-number"></span>/<span id="page-count"></span>
</div>
<div class="main">
    <h1>深圳市xxx有限公司</h1>
    <p style="margin: 30px 0 50px 0;text-align: left;">
        人在世俗的世界中行走著,在慢慢流逝的時(shí)間里靜靜等待著成年那一刻的全速奔跑。可漫長(zhǎng)的等待過后卻發(fā)現(xiàn),形形色色的欲望與世俗觀念像橡皮泥一樣粘在身上,越積越重,最后竟無限膨脹,束縛了我們的雙腿,減緩了我們的步伐。我們不能輕松上路,也不能全速奔跑。它們甚至遮蔽住我們的雙眼,遮掩住我們純真的心,讓我們的腳步開始凌亂,旋轉(zhuǎn)在燈紅酒綠的花花世界里……
    </p>
    <table>
        <thead>
        <tr>
            <th>姓名</th>
            <th>年齡</th>
            <th>性別</th>
        </tr>
        </thead>
        <tbody>
        <#if !data?? || (data?size==0)>
            <tr>
                <td colspan="3">無</td>
            </tr>
        <#else>
            <#list data as item>
                <tr>
                    <td>${item.name}</td>
                    <td>${item.age}</td>
                    <td>${item.sex}</td>
                </tr>
            </#list>
        </#if>
        </tbody>
    </table>
</div>
</body>
</html>

PDF工具類

字體包SimSun.ttc、ArialUni.ttf自行下載

package org.example;
import com.lowagie.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Locale;
/**
 * @author 苦瓜不苦
 * @date 2023/11/28 18:33
 **/
public class PDFUtil {
    /**
     * 模板生成器
     *
     * @param createFile 生成文件的路徑
     * @param ftlName    模板名稱
     * @param object     數(shù)據(jù)
     */
    public static void processTemplate(String createFile, String ftlName, Object object) {
        Configuration configuration = null;
        StringWriter writer = null;
        ByteArrayOutputStream outputStream = null;
        try {
            // 初始化模版
            configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            writer = new StringWriter();
            outputStream = new ByteArrayOutputStream();
            // 加載模板目錄
            configuration.setClassForTemplateLoading(MainApi.class, "/module");
            configuration.setClassicCompatible(true);
            ITextRenderer renderer = new ITextRenderer();
            // 設(shè)置字體
            ITextFontResolver fontResolver = renderer.getFontResolver();
            fontResolver.addFont("fonts/SimSun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            fontResolver.addFont("fonts/ArialUni.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            configuration.setEncoding(Locale.CHINA, "UTF-8");
            // 讀取模板文件
            Template template = configuration.getTemplate(ftlName, "UTF-8");
            // 寫入數(shù)據(jù)到模板中
            template.process(object, writer);
            writer.flush();
            // 獲取填充好數(shù)據(jù)的html頁面
            String html = writer.toString();
            renderer.setDocumentFromString(html);
            renderer.layout();
            // 通過html頁面字符串轉(zhuǎn)換成pdf文件
            renderer.createPDF(outputStream);
            renderer.finishPDF();
            return outputStream.toByteArray();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (Objects.nonNull(outputStream)) {
                    outputStream.close();
                }
                if (Objects.nonNull(writer)) {
                    writer.close();
                }
                if (Objects.nonNull(configuration)) {
                    configuration.clone();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

調(diào)用測(cè)試

public class Main {
    public static void main(String[] args) {
        String fromFile = "./" + System.currentTimeMillis() + ".pdf";
        String toFile = "template-01.ftl";
        List<JSONObject> data = new ArrayList<>();
        for (int i = 0; i < 60; i++) {
            JSONObject object = new JSONObject();
            object.set("name", "張三");
            object.set("sex", "男");
            object.set("age", "18");
            data.add(object);
        }
        JSONObject object = new JSONObject();
        object.set("data", data);
        byte[] bytes = PDFUtil.processTemplate(toFile, object);
        File file = FileUtil.writeBytes(bytes, fromFile);
        System.err.println(file);
    }
}

擴(kuò)展情況

以上代碼即可生成好一份PDF文檔了,但是會(huì)存在一些問題,

表格的形式會(huì)被自動(dòng)切割,出現(xiàn)以下情況

按照不同的需求,可以使用不同的方式來處理。

一是,當(dāng)被分頁時(shí),每頁都需要一個(gè)標(biāo)題的存在。

二是,分頁的頭部和尾部需要閉合起來

還有擴(kuò)展于圖片水印或者文字水印的需求

圖片水印方法

/**
 * 添加圖片水印
 *
 * @param bytes pdf字節(jié)
 * @return
 */
public static byte[] appendImageWatermark(byte[] bytes) {
    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
        PdfReader reader = new PdfReader(bytes);
        PdfStamper stamper = new PdfStamper(reader, byteArrayOutputStream);
        // 加載水印圖片
        URL url = PDFUtil.class.getClassLoader().getResource("fonts/bg.png");
        Image image = Image.getInstance(url);
        // 設(shè)置等比縮放 圖片大小
        image.scalePercent(20);
        // 自定義大小
        // image.scaleAbsolute(200,100);
        // 設(shè)置旋轉(zhuǎn)弧度
        image.setRotation(0);
        // 設(shè)置旋轉(zhuǎn)角度
        image.setRotationDegrees(0);
        // 創(chuàng)建PdfGState對(duì)象并設(shè)置透明度
        PdfGState gState = new PdfGState();
        // 填充透明度
        gState.setFillOpacity(0.3f);
        // 描邊透明度
        gState.setStrokeOpacity(0.3f);
        // PDF總頁數(shù)
        int total = reader.getNumberOfPages() + 1;
        for (int i = 1; i < total; i++) {
            Rectangle pageRect = reader.getPageSizeWithRotation(i);
            PdfContentByte content = stamper.getOverContent(i);
            content.saveState();
            content.setGState(gState);
            // 設(shè)置圖片水印
            // 獲取pdf每頁的長(zhǎng)寬
            float width = pageRect.getWidth();
            float top = pageRect.getTop();
            // 獲取縮放之后水印圖片的長(zhǎng)寬
            float scaledWidth = image.getScaledWidth();
            float scaledHeight = image.getScaledHeight();
            // 通過計(jì)算將水印添加到中間
            float x = (width - scaledWidth) / 2;
            float y = (top - scaledHeight) / 2;
            content.addImage(image, scaledWidth, 60, 0, scaledHeight, x, y);
            content.restoreState();
        }
        stamper.close();
        reader.close();
        return byteArrayOutputStream.toByteArray();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

文字水印方法

/**
 * 添加文字水印
 *
 * @param bytes pdf字節(jié)
 * @param text  水印文字
 * @param size  文字大小
 * @return
 */
public static byte[] appendTextWatermark(byte[] bytes, String text, Integer size) {
    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
        PdfReader reader = new PdfReader(bytes);
        PdfStamper stamper = new PdfStamper(reader, byteArrayOutputStream);
        // 創(chuàng)建PdfGState對(duì)象并設(shè)置透明度
        PdfGState gState = new PdfGState();
        // 填充透明度
        gState.setFillOpacity(0.3f);
        // 描邊透明度
        gState.setStrokeOpacity(0.3f);
        // 加載字體
        BaseFont baseFont = BaseFont.createFont("fonts/ArialUni.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // PDF總頁數(shù)
        int total = reader.getNumberOfPages() + 1;
        for (int i = 1; i < total; i++) {
            Rectangle pageRect = reader.getPageSizeWithRotation(i);
            PdfContentByte content = stamper.getOverContent(i);
            content.saveState();
            // 獲取pdf每頁的長(zhǎng)寬
            float width = pageRect.getWidth();
            float top = pageRect.getTop();
            // 通過計(jì)算將水印添加到中間
            float x = (width - (size * text.length())) / 2;
            float y = (top - size) / 2;
            // 設(shè)置字體水印
            content.beginText();
            content.setGState(gState);
            // 字體
            content.setFontAndSize(baseFont, size);
            // 顏色
            content.setColorFill(Color.BLACK);
            // 水印位置
            content.showTextAligned(Element.ALIGN_LEFT, text, x, y, 30);
            content.endText();
            content.restoreState();
        }
        stamper.close();
        reader.close();
        return byteArrayOutputStream.toByteArray();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

表格分頁被切割問題-方式一

在ftl模板中的style標(biāo)簽中添加css樣式

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

同一個(gè)表格在分頁時(shí),會(huì)被自動(dòng)添加上下邊框

表格分頁被切割問題-方式二

在ftl模板中的style標(biāo)簽中添加css樣式,需要注意的是表格的標(biāo)題需要使用thead標(biāo)簽包裹,表格其他行用tbody標(biāo)簽包裹

<style>
table {
    page-break-inside: auto;
    -fs-table-paginate: paginate;
    border-spacing: 0;
}
tr {
    page-break-inside: avoid;
    page-break-after: auto;
}
</style>
<body>
<table>
    <thead>
    <tr>
        <th>姓名</th>
        <th>年齡</th>
        <th>性別</th>
    </tr>
    </thead>
    <tbody>
    <#if !data?? || (data?size==0)>
        <tr>
            <td colspan="3">無</td>
        </tr>
    <#else>
        <#list data as item>
            <tr>
                <td>${item.name}</td>
                <td>${item.age}</td>
                <td>${item.sex}</td>
            </tr>
        </#list>
    </#if>
    </tbody>
</table>
</body>

被分頁時(shí),表格的標(biāo)題也會(huì)攜帶下來

以上就是Java實(shí)現(xiàn)生成pdf并解決表格分割的問題的詳細(xì)內(nèi)容,更多關(guān)于Java生成pdf的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺析Java中對(duì)象的創(chuàng)建與對(duì)象的數(shù)據(jù)類型轉(zhuǎn)換

    淺析Java中對(duì)象的創(chuàng)建與對(duì)象的數(shù)據(jù)類型轉(zhuǎn)換

    這篇文章主要介紹了Java中對(duì)象的創(chuàng)建與對(duì)象的數(shù)據(jù)類型轉(zhuǎn)換,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-01-01
  • Springboot MDC+logback實(shí)現(xiàn)日志追蹤的方法

    Springboot MDC+logback實(shí)現(xiàn)日志追蹤的方法

    MDC(Mapped Diagnostic Contexts)映射診斷上下文,該特征是logback提供的一種方便在多線程條件下的記錄日志的功能,這篇文章主要介紹了Springboot MDC+logback實(shí)現(xiàn)日志追蹤的方法,需要的朋友可以參考下
    2024-04-04
  • SpringBoot項(xiàng)目中的多數(shù)據(jù)源支持的方法

    SpringBoot項(xiàng)目中的多數(shù)據(jù)源支持的方法

    本篇文章主要介紹了SpringBoot項(xiàng)目中的多數(shù)據(jù)源支持的方法,主要介紹在SpringBoot項(xiàng)目中利用SpringDataJpa技術(shù)如何支持多個(gè)數(shù)據(jù)庫的數(shù)據(jù)源,有興趣的可以了解一下
    2017-10-10
  • Mybatis攔截器實(shí)現(xiàn)公共字段填充的示例代碼

    Mybatis攔截器實(shí)現(xiàn)公共字段填充的示例代碼

    本文介紹了使用Spring Boot和MyBatis實(shí)現(xiàn)公共字段的自動(dòng)填充功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • Java 中的 print() 和 println()

    Java 中的 print() 和 println()

    這篇文章主要介紹了Java 中的 print() 和 println(),Java 中的 print()和println()方法用于在控制臺(tái)上顯示文本,下面來看看它們之間到底有什么區(qū)別吧,需要的朋友也可以參考一下
    2021-11-11
  • Java基礎(chǔ)篇之List集合舉例詳解

    Java基礎(chǔ)篇之List集合舉例詳解

    Java中的List集合是一種常用的數(shù)據(jù)結(jié)構(gòu),它提供了一種有序、可重復(fù)的元素集合,下面這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)篇之List集合的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • Java解析word,獲取文檔中圖片位置的方法

    Java解析word,獲取文檔中圖片位置的方法

    下面小編就為大家分享一篇Java解析word,獲取文檔中圖片位置的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Spring獲取管理對(duì)象常用方法詳解

    Spring獲取管理對(duì)象常用方法詳解

    這篇文章主要介紹了Spring獲取管理對(duì)象常用方法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Spring Boot中單例類實(shí)現(xiàn)對(duì)象的注入方式

    Spring Boot中單例類實(shí)現(xiàn)對(duì)象的注入方式

    這篇文章主要介紹了Spring Boot中單例類實(shí)現(xiàn)對(duì)象的注入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Springmvc自定義異常處理器實(shí)現(xiàn)流程解析

    Springmvc自定義異常處理器實(shí)現(xiàn)流程解析

    這篇文章主要介紹了Springmvc自定義異常處理器實(shí)現(xiàn)流程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07

最新評(píng)論