【pdf】Java代碼生成PDF

目錄

依賴

創建單元格

表格數據行輔助添加方法

創建表頭單元格

創建下劃線

創建帶下劃線的文字

創建PDF


依賴

<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.4.2</version>
</dependency>
<dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.13</version>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version>
</dependency>

創建單元格

    /*** 創建單元格** @param text            顯示值* @param font            字體* @param horizontalAlign 值水平顯示位置(例:Element.ALIGN_CENTER => 居中)* @param verticalAlign   值垂直顯示位置(例:Element.ALIGN_MIDDLE => 居中)* @param minHeight       最小行高* @return PdfPCell*/private static PdfPCell createCell(String text, Font font, int horizontalAlign, int verticalAlign, float minHeight) {Paragraph para = new Paragraph(text, font);para.setAlignment(horizontalAlign);para.setLeading(para.getLeading() * 1.2f);PdfPCell cell = new PdfPCell(para);cell.setHorizontalAlignment(horizontalAlign);// 水平居中cell.setVerticalAlignment(verticalAlign);// 垂直居中cell.setMinimumHeight(minHeight);  // 設置最小高度
//        cell.setPadding(0);// 內邊距cell.setBorderWidth(0.5f);// 單元格邊框寬度cell.setNoWrap(false);// 自動換行return cell;}

表格數據行輔助添加方法

    /*** 輔助添加表格數據行* @param table     表格* @param col1      列1值* @param col2      列2值* @param col3      列3值* @param font      字體*/private static void addTableRow(PdfPTable table, String col1, String col2, String col3, Font font) {// 有幾列幾個 table.addCell 方法table.addCell(createCell(col1, font, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f));table.addCell(createCell(col2, font, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f));table.addCell(createCell(col3, font, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f));}
    /*** 輔助添加表格行數據* @param table                 表格* @param tableHeaderNumber     表格表頭列數* @param font                  字體* @param horizontalAlign       值水平顯示位置(例:Element.ALIGN_CENTER => 居中)* @param verticalAlign         值垂直顯示位置(例:Element.ALIGN_MIDDLE => 居中)* @param minHeight             最小行高* @param column                單元格數據,x列傳入x個使用【,】隔開*/private static void addTableRow(PdfPTable table,int tableHeaderNumber, Font font, int horizontalAlign, int verticalAlign, float minHeight, String... column) {if (column.length == 1 && column[0].isEmpty()) {// 只傳入一個【""】值if (tableHeaderNumber > 0) {// 表頭列數 <= 0 時,不創建空行數據for (int i = 0; i < tableHeaderNumber; i++) {// 根據表頭列數生成對應的空行數據,值為【" "】(為""時不會創建空行數據)table.addCell(createCell(" ", font, horizontalAlign, verticalAlign, minHeight));}}}else {for (String s : column) {table.addCell(createCell(s, font, horizontalAlign, verticalAlign, minHeight));}}}

創建表格表頭

    /*** 創建表頭單元格** @param table           表* @param text            顯示值* @param font            字體* @param bgColor         單元格背景色* @param horizontalAlign 值水平顯示位置(例:Element.ALIGN_CENTER => 居中)* @param verticalAlign   值垂直顯示位置(例:Element.ALIGN_MIDDLE => 居中)* @param height          行高*/private static void createTableHeader(PdfPTable table, String text, Font font, BaseColor bgColor, int horizontalAlign, int verticalAlign, float height) {Paragraph para = new Paragraph(text, font);para.setAlignment(horizontalAlign);PdfPCell cell = new PdfPCell(para);cell.setBackgroundColor(bgColor);cell.setHorizontalAlignment(horizontalAlign);// 水平居中cell.setVerticalAlignment(verticalAlign);// 垂直居中cell.setMinimumHeight(height);  // 設置最小高度cell.setBorderWidth(0.5f);// 單元格邊框寬度
//        cell.setFixedHeight(height);  // 固定行高,文字超出高度不會顯示
//        cell.setPadding(8);// 內邊距
//        cell.setNoWrap(false);// 自動換行table.addCell(cell);}

創建下劃線

    /*** 創建下劃線** @param width 寬* @param font  字體* @return Chunk*/private static Chunk createUnderlineChunk(float width, Font font) {Chunk underlineChunk = new Chunk(" ");underlineChunk.setHorizontalScaling(width); // 設置寬度underlineChunk.setUnderline(0.5f, -1f);// param-1:線寬 param-2:線位置,基于行底部,負數下調正數上調underlineChunk.setFont(font);// 設置字體return underlineChunk;}
    /*** 使用PdfContentByte自定義繪制下劃線** @param writer PdfWriter* @param width  寬度* @return Chunk*/private static Chunk createCustomDrawnLine(PdfWriter writer, float width) {// 創建一個空白Chunk作為占位符Chunk placeholder = new Chunk(" ");// 添加自定義繪制功能placeholder.setGenericTag(" ");writer.setPageEvent(new PdfPageEventHelper() {@Overridepublic void onGenericTag(PdfWriter writer, Document document,Rectangle rect, String text) {// 獲取畫布PdfContentByte canvas = writer.getDirectContent();canvas.saveState();// 設置下劃線樣式canvas.setLineWidth(0.5f);canvas.setColorStroke(BaseColor.BLACK);// 計算下劃線位置float y = rect.getBottom() - 3; // 在文本下方3點處float x1 = rect.getLeft();float x2 = x1 + width;// 繪制下劃線canvas.moveTo(x1, y);canvas.lineTo(x2, y);canvas.stroke();canvas.restoreState();}});return placeholder;}

創建帶下劃線的文字

    /*** 創建帶下劃線的文字塊* @param text      文字* @param font      字體* @return          Chunk*/private static Chunk createUnderlinedText(String text, Font font){Chunk textChunk = new Chunk(text, font);textChunk.setUnderline(0.5f, -1f);// 設置下劃線:線寬0.5,位置在基線下方1點return textChunk;}

創建PDF

創建 Document 對象、pdf寫入器

        Document document = new Document(PageSize.A4, 90, 90, 80, 50);// 創建文檔對象(A4紙大小,邊距:左, 右, 上, 下)PdfWriter writer = PdfWriter.getInstance(document, Files.newOutputStream(Paths.get(dest)));// 創建PDF寫入器
//        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));PageNumberEventHandler eventHandler = new PageNumberEventHandler();writer.setPageEvent(eventHandler);// 打開文檔document.open();

設置字體,避免中文不顯示問題

        // 字體,中文字體,避免文字不顯示BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);Font titleFont = new Font(baseFont, 18, Font.BOLD);// 標題字體Font subtitleFont = new Font(baseFont, 12);// 副標題字體Font contentFont = new Font(baseFont, 12);// 正文字體Font headerFont = new Font(baseFont, 12);// 表頭字體Font footerFont = new Font(baseFont, 12);// 頁腳字體

標題、副標題定義?

        // 標題Paragraph title = new Paragraph("Leslie Lee", titleFont);title.setAlignment(Element.ALIGN_CENTER);// 左右居中title.setSpacingAfter(5f); // 設置段后間距document.add(title);// 副標題Paragraph subtitle = new Paragraph("(風華絕代)", subtitleFont);subtitle.setAlignment(Element.ALIGN_CENTER);subtitle.setSpacingAfter(25f);document.add(subtitle);

?正文段落

        // 添加內容段落Paragraph content = new Paragraph();content.setAlignment(Element.ALIGN_JUSTIFIED); // 段落兩端對齊content.add(new Chunk("風華絕代、風流倜儻、玉樹臨風", contentFont));content.add(Chunk.NEWLINE);// 換行,兩個效果為空一行content.add(Chunk.NEWLINE);

?正文中添加帶下劃線的文字

        content.add(createUnderlinedText(text,contentFont));// 正文添加帶下劃線的文字,需這樣單獨添加

表格——創建表格

        PdfPTable table = new PdfPTable(3);// 創建表格 x列table.setWidthPercentage(100); // 表格寬度占頁面百分比table.setSpacingBefore(5f);  // 表格前間距table.setSpacingAfter(10f);   // 表格后間距table.setSplitLate(false); // 防止單元格在分頁時被拆分table.setSplitRows(true);  // 允許行拆分
//        table.setHeaderRows(1); // 前 x 行作為表頭,跨頁時重復

表格——創建表頭-上面的方法

        addTableHeader(table, "代表作", headerFont, null, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f);// 添加表頭單元格,幾列就幾個 addTableHeader 方法addTableHeader(table, "時間", headerFont, null, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f);// 添加表頭單元格,幾列就幾個 addTableHeader 方法addTableHeader(table, "角色", headerFont, null, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f);// 添加表頭單元格,幾列就幾個 addTableHeader 方法

?表格——創建單元格-上面的方法

        addTableRow(table, "絕代風華", "1956-09-12", "Cheung Kwok Wing", contentFont);// 添加表格數據,幾行就幾個 addTableRow 方法

?添加頁腳

        // 添加頁腳Paragraph footer = new Paragraph("【風華絕代】", footerFont);footer.setAlignment(Element.ALIGN_CENTER);document.add(footer);

?添加圖片

        // 添加圖片(可選)try {String imagePath = "img.jpg"; // 替換為實際圖片路徑Image img = Image.getInstance(imagePath);img.scaleToFit(100, 100); // 調整圖片大小img.setAbsolutePosition(36, 36); // 左下角位置document.add(img);} catch (Exception e) {System.err.println("圖片添加失敗: " + e.getMessage());}

?關閉文檔

        document.close();// 關閉文檔

?頁碼處理類

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;import java.io.IOException;/**     頁碼處理* @author Leslie Lee* @version 2003/04/01* @date 1956/09/12*/
public class PageNumberEventHandler extends PdfPageEventHelper {private final Font footerFont;// 頁腳字體private PdfTemplate totalPagesTemplate;// 用于存儲總頁數的模板private final BaseFont baseFont;// 基礎字體public PageNumberEventHandler() throws DocumentException, IOException {super();baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);footerFont = new Font(baseFont, 10, Font.NORMAL, BaseColor.DARK_GRAY);}@Overridepublic void onOpenDocument(PdfWriter writer, Document document) {totalPagesTemplate = writer.getDirectContent().createTemplate(30, 17);// 創建用于總頁數的模板}@Overridepublic void onEndPage(PdfWriter writer, Document document) {PdfContentByte canvas = writer.getDirectContent();// 獲取PDF內容canvas.saveState();// 保存當前狀態// 創建頁碼文本String footerText = writer.getPageNumber() + " /";// 當前頁碼// 設置頁腳位置(居中底部)float x = (document.left() + document.right()) / 2;// 文檔中間位置float y = document.bottom() - 20;// 文檔底部上移 20 的位置ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, new Phrase(footerText, footerFont), x, y, 0);// 添加頁碼文本float pageTextWidth = baseFont.getWidthPoint(footerText, 9);// 計算頁碼文本寬度// 添加總頁數模板(占位符)canvas.addTemplate(totalPagesTemplate, x + pageTextWidth / 2 + 3, y);  // 計算位置 x為左右位置(數大越右、數小越左) y為垂直位置(減數為下調、加數為上調)// 添加"頁"字
//            canvas.beginText();
//            canvas.setFontAndSize(baseFont, 9);
//            canvas.setColorFill(BaseColor.DARK_GRAY);
//            canvas.showTextAligned(Element.ALIGN_CENTER, "頁", x + pageTextWidth / 2 + 22, y, 0);
//            canvas.endText();// 添加頁碼左標題
//            String titleText = "";
//            ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(titleText, footerFont), document.left(), y, 0);// 添加頁碼右標題
//            String companyText = "";
//            ColumnText.showTextAligned(canvas, Element.ALIGN_RIGHT, new Phrase(companyText, footerFont), document.right(), y, 0);// 添加頁腳分隔線
//            canvas.setLineWidth(0.5f);// 分隔線粗細
//            canvas.setColorStroke(BaseColor.LIGHT_GRAY);// 灰色
//            canvas.moveTo(document.left(), y + 10);// 坐標起點  參數1:開始位置(左右) 參數2:高度(上下) 正數上調負數下調
//            canvas.lineTo(document.right(), y + 10);// 坐標終點 參數1:結束位置(左右) 參數2:高度(上下) 正數上調負數下調
//            canvas.stroke();// 恢復狀態canvas.restoreState();}/*** 文檔關閉時,寫入總頁數到模板*/@Overridepublic void onCloseDocument(PdfWriter writer, Document document) {totalPagesTemplate.beginText();totalPagesTemplate.setFontAndSize(baseFont, 10);totalPagesTemplate.setColorFill(BaseColor.DARK_GRAY);totalPagesTemplate.showText(String.valueOf(writer.getPageNumber())); // 有幾頁封面就減幾,沒有封面不減totalPagesTemplate.endText();}
}

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Leslie Lee 隨筆

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84469.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84469.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84469.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vite 的“心臟移植”:Rolldown

1. 現狀&#xff1a;你擱這兒玩雙截棍呢&#xff1f; 現在Vite這逼樣&#xff1a;開發用esbuild&#xff0c;生產用Rollup&#xff0c;精分現場是吧&#xff1f;大型項目尼瑪啟動慢成狗&#xff0c;請求多到炸穿地心&#xff0c;生產/dev環境差異能讓你debug到原地升天&#x…

【網絡安全】文件上傳型XSS攻擊解析

引言 文件上傳功能作為現代Web應用的核心交互模塊&#xff0c;其安全防護水平直接關系到系統的整體安全性。本文基于OWASP、CVE等權威研究&#xff0c;結合2024-2025年最新漏洞案例&#xff0c;系統剖析了文件上傳場景下的XSS攻擊技術演進路徑。研究揭示&#xff1a;云原生架構…

Java 集合框架底層數據結構實現深度解析

Java 集合框架&#xff08;Java Collections Framework, JCF&#xff09;是支撐高效數據處理的核心組件&#xff0c;其底層數據結構的設計直接影響性能與適用場景。本文從線性集合、集合、映射三大體系出發&#xff0c;系統解析ArrayList、LinkedList、HashMap、TreeSet等核心類…

Dify動手實戰教程(進階-知識庫:新生入學指南)

目錄 進階-知識庫&#xff1a;新生入學指南 1.創建知識庫 2.創建Agent 去年agent智能體爆火&#xff0c;我自己也使用了多款智能體產品來搭建agent解決生活中的實際問題&#xff0c;如dify、coze等等。dify作為一個開源的框架得到了大量的應用&#xff0c;如一些需要隱私保護…

Vue3+TypeScript+ Element Plus 從Excel文件導入數據,無后端(點擊按鈕,選擇Excel文件,由前端解析數據)

在 Vue 3 TypeScript Element Plus 中實現文件導入功能&#xff0c;可以通過以下步驟完成&#xff1a; 1. 安裝依賴 bash 復制 下載 npm install xlsx # 用于解析Excel文件 npm install types/xlsx -D # TypeScript類型聲明 2. 組件實現 vue 復制 下載 <templ…

一些torch函數用法總結

1.torch.nonzero(input, *, as_tupleFalse) 作用&#xff1a;在PyTorch中用于返回輸入張量中非零元素的位置索引。 返回值&#xff1a;返回一個張量&#xff0c;每行代表一個非零元素的索引。 參數含義&#xff1a; &#xff08;1&#xff09;input:輸入的PyTorch 張量。 …

moments_object_model_3d這么理解

這篇文章是我對這個算子的理解,和三個輸出結果分別用在什么地方 算子本身 moments_object_model_3d( : : ObjectModel3D, MomentsToCalculate : Moments) MomentsToCalculate:對應三個可選參數,分別是 1, mean_points: 就是點云在xyz方向上坐標的平均值 2, central_m…

性能測試|數據說話!在SimForge平臺上用OpenRadioss進行汽車碰撞仿真,究竟多省時?

Radioss是碰撞仿真領域中十分成熟的有限元仿真軟件&#xff0c;可以對工程中許多非線性問題進行求解&#xff0c;例如汽車碰撞、產品跌落、導彈爆炸、流固耦合分析等等。不僅可以提升產品的剛度、強度、碰撞的安全性能等&#xff0c;還可以在降低產品研發成本的同時提升研發效率…

數據結構學習——KMP算法

//KMP算法 #include <iostream> #include <string> #include <vector> #include <cstdlib>using namespace std;//next數組值的推導void getNext(string &str, vector<int>& next){int strlong str.size();//next數組的0位為0next[0]0;…

博士,超28歲,出局!

近日&#xff0c;長沙市望城區《2025年事業引才博士公開引進公告》引發軒然大波——博士崗位年齡要求28周歲及以下&#xff0c;特別優秀者也僅放寬至30周歲。 圖源&#xff1a;網絡 這份規定讓眾多"高齡"博士生直呼不合理&#xff0c;并在社交平臺掀起激烈討論。 圖源…

使用Nuitka打包Python程序,編譯為C提高執行效率

在 Python 的世界里&#xff0c;代碼打包與發布一直是開發者關注的重要話題。前面我們介紹了Pyinstaller的使用&#xff0c;盡管 PyInstaller 是最常用的工具之一&#xff0c;但對于性能、安全性、兼容性有更高要求的項目&#xff0c;Nuitka 正迅速成為更優的選擇。本文將全面介…

基于機器學習的惡意請求檢測

好久沒寫文章了&#xff0c;忙畢業設計ING&#xff0c;終于做好了發出來。 做了針對惡意URL的檢測&#xff0c;改進了楊老師這篇參考文獻的惡意請求檢測的方法 [網絡安全自學篇] 二十三.基于機器學習的惡意請求識別及安全領域中的機器學習-CSDN博客 選擇使用了XGBoost算法進…

深入理解XGBoost(何龍 著)學習筆記(五)

深入理解XGBoost&#xff08;何龍 著&#xff09;學習筆記&#xff08;五&#xff09; 本文接上一篇&#xff0c;內容為線性回歸&#xff0c;介紹三部分&#xff0c;首先介紹了"模型評估”&#xff0c;然后分別提供了線性回歸的模型代碼&#xff1a;scikit-learn的Linear…

工業級MySQL基準測試專家指南

工業級MySQL基準測試專家指南 一、深度風險識別增強版 風險類型典型表現進階檢測方案K8s存儲性能抖動PVC卷IOPS驟降50%使用kubestone進行CSI驅動壓力測試HTAP讀寫沖突OLAP查詢導致OLTP事務超時用TPCH+Sysbench混合負載測試冷熱數據分層失效壓縮表查詢耗時激增10倍監控INNODB_C…

Spring WebFlux和Spring MVC的對比

原文網址&#xff1a;Spring WebFlux和Spring MVC的對比-CSDN博客 簡介 本文介紹Spring WebFlux和Spring MVC的區別。 Webflux&#xff1a;是異步非阻塞的&#xff08;IO多路復用&#xff09;&#xff0c;基于Netty。適合網絡轉發類的應用&#xff0c;比如&#xff1a;網關。…

解析401 Token過期自動刷新機制:Kotlin全棧實現指南

在現代Web應用中&#xff0c;Token過期導致的401錯誤是影響用戶體驗的關鍵問題。本文將手把手實現一套完整的Token自動刷新機制&#xff0c;覆蓋從原理到實戰的全過程。 一、為什么需要Token自動刷新&#xff1f; 當用戶使用應用時&#xff0c;會遇到兩種典型場景&#xff1a;…

《解構線性數據結構的核心骨架:從存儲模型到操作范式的深度解析》

線性數據結構概述 線性數據結構是數據元素按線性順序排列的集合,每個元素有唯一的前驅和后繼(除首尾元素)。常見類型包括數組、隊列、鏈表和棧,每種結構在存儲和操作上具有獨特特性。 線性表:顧名思義,線性表就是數據排成像一條線的結構。每個線性表上的數據最多只有前和后…

HW藍隊工作流程

HW藍隊工作流程 由多領域安全專家組成攻擊隊&#xff0c;在保障業務系統安全的前提下&#xff0c;直接在真實網絡環境開展對抗&#xff0c;對參演單位目標系進行可控、可審計的網絡安全實戰攻擊&#xff0c;通過攻防演習檢驗參演單位的安全防護和應急處置能力&#xff0c;提高…

語音相關-瀏覽器的自動播放策略研究和websocket研究

策略詳情 媒體參與度 AudioContext音頻API的實現 new Audio音頻API的實現 相關實踐 網頁端 使用new Audio創建的音頻對象進行音頻播放的時候&#xff0c;如果用戶沒有與頁面進行交互&#xff0c;那么會報錯如下&#xff1a; 使用AudioContext創建的對象播放音頻&#xff0c;…

Linux操作系統網絡服務模塊一DHCP服務概述

前言&#xff1a; 在Linux網絡服務體系架構中&#xff0c;?DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;?? 作為核心服務之一&#xff0c;承擔著局域網內主機網絡參數動態分配的關鍵任務。其設計初衷是解決傳統手動配置IP地址的效率瓶頸與錯誤風…