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

Java實(shí)現(xiàn)將列表數(shù)據(jù)導(dǎo)出為PDF文件并添加水印

 更新時(shí)間:2024年02月15日 08:15:03   作者:→_→BéLieve  
這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)把列表數(shù)據(jù)導(dǎo)出為PDF文件,同時(shí)加上PDF水印,文中的示例代碼講解詳細(xì),需要的可以參考下

一、實(shí)現(xiàn)效果

二、遇到的問題

1.實(shí)現(xiàn)導(dǎo)出PDF主體代碼參考:Java純代碼實(shí)現(xiàn)導(dǎo)出PDF功能,下圖是原作者實(shí)現(xiàn)的效果

2.導(dǎo)出報(bào)錯(cuò)Font 'STSong-Light' with 'UniGB-UCS2-H' is not recognized.。參考文末補(bǔ)充內(nèi)容

網(wǎng)上都是說jar包的版本不對(duì),導(dǎo)致的字體兼容性問題。換了jar包版本發(fā)現(xiàn)沒效果,后來索性直接把字體下載到本地直接引入。

3.jar包發(fā)布到服務(wù)器上導(dǎo)出PDF的時(shí)候發(fā)生報(bào)錯(cuò)BOOT-INF/classes!/fonts/SimSun.ttf not exists。

可以看到字體文件在jar目錄下面是有的,但是發(fā)現(xiàn)classes后面多了個(gè)嘆號(hào)。這是引入外部字體方式不對(duì),后改用問題2參考文章的第三種寫法就沒問題了。

添加水印參考:itextpdf5.5.13給pdf添加圖片水印、添加文字水印(平鋪)、添加文字水?。▎蝹€(gè))、添加頁(yè)眉、頁(yè)腳、頁(yè)眉事件、添加圖片

三、測(cè)試數(shù)據(jù)展示

list:子節(jié)點(diǎn)數(shù)據(jù)
0 = {BasBudgetDetailVo@16046} "BasBudgetDetailVo(budgetId=2064535550, functionId=231231232, budgetQuantity=3, totalPrice=2664.00, functionName=功能1, functionDescription=功能1描述, functionUnit=套, functionPrice=888.00, parentId=231234512, functionSort=1)"
1 = {BasBudgetDetailVo@16047} "BasBudgetDetailVo(budgetId=2039369726, functionId=231236478, budgetQuantity=1, totalPrice=888.00, functionName=功能1, functionDescription=功能1描述, functionUnit=套, functionPrice=888.00, parentId=231234879, functionSort=1)"
2 = {BasBudgetDetailVo@16048} "BasBudgetDetailVo(budgetId=2039369725, functionId=231236473, budgetQuantity=1, totalPrice=888.00, functionName=功能2, functionDescription=功能2描述, functionUnit=套, functionPrice=888.00, parentId=231234879, functionSort=2)"
3 = {BasBudgetDetailVo@16049} "BasBudgetDetailVo(budgetId=2056146943, functionId=231231241, budgetQuantity=1, totalPrice=888.00, functionName=功能2, functionDescription=功能2描述, functionUnit=套, functionPrice=888.00, parentId=231234512, functionSort=2)"
4 = {BasBudgetDetailVo@16050} "BasBudgetDetailVo(budgetId=2047758334, functionId=231236487, budgetQuantity=1, totalPrice=888.00, functionName=功能3, functionDescription=功能3描述, functionUnit=套, functionPrice=888.00, parentId=231234512, functionSort=3)"
5 = {BasBudgetDetailVo@16051} "BasBudgetDetailVo(budgetId=2039369724, functionId=231231245, budgetQuantity=1, totalPrice=888.00, functionName=功能3, functionDescription=功能3描述, functionUnit=套, functionPrice=888.00, parentId=231234879, functionSort=3)"
6 = {BasBudgetDetailVo@16052} "BasBudgetDetailVo(budgetId=2047758333, functionId=231231597, budgetQuantity=1, totalPrice=888.00, functionName=功能4, functionDescription=功能4描述, functionUnit=套, functionPrice=888.00, parentId=231234512, functionSort=4)"
7 = {BasBudgetDetailVo@16053} "BasBudgetDetailVo(budgetId=2030981118, functionId=231233154, budgetQuantity=1, totalPrice=888.00, functionName=功能4, functionDescription=功能4描述, functionUnit=套, functionPrice=888.00, parentId=231234879, functionSort=4)"
8 = {BasBudgetDetailVo@16054} "BasBudgetDetailVo(budgetId=2030981117, functionId=231234596, budgetQuantity=1, totalPrice=888.00, functionName=功能5, functionDescription=功能5描述, functionUnit=套, functionPrice=888.00, parentId=231234879, functionSort=5)"
9 = {BasBudgetDetailVo@16055} "BasBudgetDetailVo(budgetId=2030981116, functionId=231235487, budgetQuantity=1, totalPrice=888.00, functionName=功能6, functionDescription=功能6描述, functionUnit=套, functionPrice=888.00, parentId=231234879, functionSort=6)"

functionInfoList:根節(jié)點(diǎn)數(shù)據(jù)
0 = {BasFunctionInfo@16090} "BasFunctionInfo(functionId=231234512, functionName=模塊1, functionDescription=, functionUnit=0, functionPrice=0.00, createName=管理員, createBy=admin, createTime=Wed Jan 24 16:56:35 CST 2024, updateName=管理員, updateBy=admin, updateTime=Wed Jan 24 16:56:38 CST 2024, functionQuantity=null, functionSort=1, parentId=null)"
1 = {BasFunctionInfo@16091} "BasFunctionInfo(functionId=231234879, functionName=模塊2, functionDescription=, functionUnit=0, functionPrice=0.00, createName=管理員, createBy=admin, createTime=Wed Jan 24 16:56:35 CST 2024, updateName=管理員, updateBy=admin, updateTime=Wed Jan 24 16:56:38 CST 2024, functionQuantity=null, functionSort=2, parentId=null)"

matchList:當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn)數(shù)據(jù)

四、jar包引入

<!--導(dǎo)出pdf所需包-->
<dependency>
	<groupId>com.itextpdf</groupId>
	<artifactId>itextpdf</artifactId>
	<version>5.5.10</version>
</dependency>
<dependency>
	<groupId>com.itextpdf</groupId>
	<artifactId>itext-asian</artifactId>
	<version>5.2.0</version>
</dependency>
</dependencies>

五、外部字體引入

字體文件資源自己百度,直接搜SimSun.ttf字體下載不難找

六、代碼實(shí)現(xiàn)

private final ResourceLoader resourceLoader;

public BasBudgetDetailServiceImpl(ResourceLoader resourceLoader) {
    this.resourceLoader = resourceLoader;
}

/**
 * 導(dǎo)出pdf
 * 
 * @param response
 * @throws Exception
 */
@Override
public void downloadPdf(HttpServletResponse response) throws Exception {
	// 業(yè)務(wù)數(shù)據(jù),根據(jù)需求查詢獲取
    // 子節(jié)點(diǎn)數(shù)據(jù)
    List<BasBudgetDetailVo> list;
    // 根子節(jié)點(diǎn)數(shù)據(jù)
    List<BasFunctionInfo> functionInfoList;

    // 定義全局的字體靜態(tài)變量
    Font content = null;
    Resource resource = resourceLoader.getResource("classpath:/fonts/SimSun.ttf");
    InputStream inputStream = resource.getInputStream();
    BaseFont bfChinese = null;
    try {
        // 字體
        bfChinese = BaseFont.createFont("SimSun.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, IOUtils.toByteArray(inputStream), null);
        content = new Font(bfChinese, 10, Font.NORMAL);
    } catch (Exception e) {
        e.printStackTrace();
    }
    BaseFont bf = null;
    Font font = null;
    try {
        //創(chuàng)建字體
        bf = BaseFont.createFont("SimSun.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, IOUtils.toByteArray(inputStream), null);
        //使用字體并給出顏色
        font = new Font(bf, 20, Font.BOLD, BaseColor.BLACK);
    } catch (Exception e) {
        e.printStackTrace();
    }
    Document document = new Document(new RectangleReadOnly(842F, 595F));
    try {
        PdfWriter pdfWriter = PdfWriter.getInstance(document, response.getOutputStream());
        //打開生成的pdf文件
        document.open();
        //設(shè)置標(biāo)題
        Paragraph paragraph = new Paragraph("這是標(biāo)題文檔標(biāo)題", font);
        paragraph.setAlignment(1);
        //引用字體
        document.add(paragraph);

        // 總額
        BigDecimal detailTotal = BigDecimal.valueOf(0);
        for (BasFunctionInfo functionInfo : functionInfoList) {
            // 匹配明細(xì)
            List<BasBudgetDetailVo> matchList = list.stream().filter(item ->
                            String.valueOf(item.getParentId()).equals(String.valueOf(functionInfo.getFunctionId())))
                    .collect(Collectors.toList());

            // 設(shè)置表格的列寬和列數(shù)
            float[] widths = {10f, 35f, 70f, 10f, 10f, 20f, 20f};
            PdfPTable table = new PdfPTable(widths);
            table.setSpacingBefore(20f);
            // 設(shè)置表格寬度為100%
            table.setWidthPercentage(100.0F);
            table.setHeaderRows(1);
            table.getDefaultCell().setHorizontalAlignment(1);
            //列表-表頭
            String[] titleList = new String[]{"序號(hào)", "功能名稱", "功能描述", "數(shù)量", "單位", "單價(jià)(元)", "總價(jià)(元)"};
            addTableTitle(table, content, titleList);
            // 模塊總額
            BigDecimal modelTotal = BigDecimal.valueOf(0);
            //列表數(shù)據(jù)
            if (matchList.size() > 0) {
                Integer index = 1;
                for (BasBudgetDetailVo item : matchList) {
                    PdfPCell cell1 = new PdfPCell(new Paragraph(String.valueOf(index), content));
                    PdfPCell cell2 = new PdfPCell(new Paragraph(item.getFunctionName(), content));
                    PdfPCell cell3 = new PdfPCell(new Paragraph(item.getFunctionDescription(), content));
                    PdfPCell cell4 = new PdfPCell(new Paragraph(String.valueOf(item.getBudgetQuantity()), content));
                    PdfPCell cell5 = new PdfPCell(new Paragraph(item.getFunctionUnit(), content));
                    PdfPCell cell6 = new PdfPCell(new Paragraph(String.valueOf(item.getFunctionPrice()), content));
                    BigDecimal totalPrice = item.getFunctionPrice().multiply(BigDecimal.valueOf(item.getBudgetQuantity()));
                    PdfPCell cell7 = new PdfPCell(new Paragraph(String.valueOf(totalPrice), content));
                    //單元格對(duì)齊方式
                    cell1.setFixedHeight(20);
                    cell1.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell1.setVerticalAlignment(Element.ALIGN_MIDDLE);

					// 文字長(zhǎng)度大于15的時(shí)候,設(shè)置表格行間距,底邊距離
                    if (item.getFunctionName().length() > 15) {
                        cell2.setLeading(0f, 1.5f);
                        cell2.setPaddingBottom(10);
                    }
                    cell2.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell2.setVerticalAlignment(Element.ALIGN_MIDDLE);
					
					// 文字長(zhǎng)度大于30的時(shí)候,設(shè)置表格行間距,底邊距離
                    if (item.getFunctionDescription().length() > 30) {
                        cell3.setLeading(0f, 1.5f);
                        cell3.setPaddingBottom(10);
                    }
                    cell3.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell3.setVerticalAlignment(Element.ALIGN_MIDDLE);

                    cell4.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell4.setVerticalAlignment(Element.ALIGN_MIDDLE);

                    cell5.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell5.setVerticalAlignment(Element.ALIGN_MIDDLE);

                    cell6.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell6.setVerticalAlignment(Element.ALIGN_MIDDLE);

                    cell7.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell7.setVerticalAlignment(Element.ALIGN_MIDDLE);

                    table.addCell(cell1);
                    table.addCell(cell2);
                    table.addCell(cell3);
                    table.addCell(cell4);
                    table.addCell(cell5);
                    table.addCell(cell6);
                    table.addCell(cell7);

                    // 序號(hào)
                    index++;

                    modelTotal = modelTotal.add(totalPrice);
                }
                // 合計(jì)行
                PdfPCell cell1 = new PdfPCell(new Paragraph("合計(jì)", content));
                cell1.setFixedHeight(20);
                cell1.setHorizontalAlignment(Element.ALIGN_CENTER);
                cell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
                // 空格
                PdfPCell cell2 = new PdfPCell(new Paragraph("", content));
                cell2.setFixedHeight(20);
                cell2.setHorizontalAlignment(Element.ALIGN_CENTER);
                cell2.setVerticalAlignment(Element.ALIGN_MIDDLE);
                // 數(shù)額
                PdfPCell cell3 = new PdfPCell(new Paragraph(String.valueOf(modelTotal), content));
                cell3.setFixedHeight(20);
                cell3.setHorizontalAlignment(Element.ALIGN_CENTER);
                cell3.setVerticalAlignment(Element.ALIGN_MIDDLE);
                table.addCell(cell1);
                table.addCell(cell2);
                table.addCell(cell2);
                table.addCell(cell2);
                table.addCell(cell2);
                table.addCell(cell2);
                table.addCell(cell3);

                detailTotal = detailTotal.add(modelTotal);
            }

            document.add(new Paragraph("\n"));
            document.add(new Paragraph("▋ " + functionInfo.getFunctionName(), content));
            document.add(table);
            document.add(new Paragraph("\n"));

            if (matchList.size() == 0) {
                document.add(new Paragraph("暫無(wú)數(shù)據(jù)", content));
            }
        }

        document.add(new Paragraph("\n"));
        document.add(new Paragraph("總計(jì):" + detailTotal + "元", content));

        // 加水印
        PdfContentByte waterMar = pdfWriter.getDirectContentUnder();
        String text = "天天想辭職月月拿全勤";
        addTextFullWaterMark(waterMar, text, bfChinese);

        document.close();
    } catch (DocumentException e) {
        e.printStackTrace();
        log.error("導(dǎo)出pdf失敗:{}", e);
    }
}

/**
 * 給表格添加表頭
 *
 * @param table
 * @param content
 * @param titleList
 */
public void addTableTitle(PdfPTable table, Font content, String[] titleList) {
    PdfPCell cell = null;
    for (String title : titleList) {
        cell = new PdfPCell(new Paragraph(title, content));
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setFixedHeight(20);
        cell.setNoWrap(false);
        table.addCell(cell);
    }
}

/**
 * 給pdf添加文字水印(平鋪)
 *
 * @param waterMar
 * @param text     水印文本
 * @throws Exception
 */
public static void addTextFullWaterMark(PdfContentByte waterMar, String text, BaseFont bf) {
    waterMar.beginText();

    PdfGState gs = new PdfGState();
    // 設(shè)置填充字體不透明度為0.2f
    gs.setFillOpacity(0.2f);
    waterMar.setFontAndSize(bf, 20);
    // 設(shè)置透明度
    waterMar.setGState(gs);
    // 設(shè)置水印對(duì)齊方式 水印內(nèi)容 X坐標(biāo) Y坐標(biāo) 旋轉(zhuǎn)角度
    for (int x = 0; x <= 900; x += 200) {
        for (int y = -50; y <= 800; y += 200) {
            waterMar.showTextAligned(Element.ALIGN_RIGHT, text, x, y, 35);
        }
    }

    // 設(shè)置水印顏色
    waterMar.setColorFill(BaseColor.GRAY);

    //結(jié)束設(shè)置
    waterMar.endText();
    waterMar.stroke();
}

七、知識(shí)補(bǔ)充

itext 生成 PDF使用外部字體

在 Spring Boot 項(xiàng)目中,使用 iTextPDF 庫(kù)的 BaseFont.createFont() 方法并使用外部字體,您需要將字體文件放置在項(xiàng)目的資源文件夾中,然后使用相對(duì)路徑來引用它們。

1.絕對(duì)路徑

BaseFont.createFont("C:\\Windows\\Fonts\\simfang.ttf",BaseFont.IDENTITY_H,BaseFont.EMBEDDED)

2.將字體文件放置在 src/main/resources/fonts 目錄下,讀取resource目錄下的字體

BaseFont baseFont = BaseFont.createFont("classpath:/fonts/simfang.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

注:此方式只有在打成jar時(shí)才生效

3.在 Spring Boot 項(xiàng)目中,您可以使用 ResourceLoader 來加載文件,而不必?fù)?dān)心文件路徑的問題。ResourceLoader 可以在任何環(huán)境中工作,無(wú)論是在 IDEA 中運(yùn)行還是在打包的 JAR 文件中運(yùn)行。

@Service
public class MyService {
 
    private final ResourceLoader resourceLoader;
 
    public MyService(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
 
    public void generatePdf() throws IOException, DocumentException {
        //第一種情況 以 .ttf結(jié)尾的字體
        Resource resource = resourceLoader.getResource("classpath:/fonts/simfang.ttf");
        InputStream inputStream = resource.getInputStream();
        // Use the input stream to create the BaseFont object
        BaseFont baseFont = BaseFont.createFont("simfang.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, inputStream, null);
 
    //第二種情況 以 .ttc結(jié)尾的字體
Resource resource1 = resourceLoader.getResource("classpath:/fonts/simsun.ttc");
        InputStream inputStream = resource1.getInputStream();
        // Use the input stream to create the BaseFont object
        BaseFont baseFont = BaseFont.createFont("simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, inputStream, null);
      
    }
}

以上就是Java實(shí)現(xiàn)將列表數(shù)據(jù)導(dǎo)出為PDF文件并添加水印的詳細(xì)內(nèi)容,更多關(guān)于Java列表數(shù)據(jù)導(dǎo)出為PDF的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • springAop實(shí)現(xiàn)講解(看這篇夠了)

    springAop實(shí)現(xiàn)講解(看這篇夠了)

    AOP面向切面編程是一種編程范式,它通過將通用的橫切關(guān)注點(diǎn)(如日志、事務(wù)、權(quán)限控制等)與業(yè)務(wù)邏輯分離,使得代碼更加清晰、簡(jiǎn)潔、易于維護(hù),這篇文章主要介紹了springAop實(shí)現(xiàn)講解(看這篇夠了),需要的朋友可以參考下
    2024-02-02
  • mybatis-plus 返回部分字段的解決方式

    mybatis-plus 返回部分字段的解決方式

    這篇文章主要介紹了mybatis-plus 返回部分字段的解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • mybatis如何對(duì)大量數(shù)據(jù)的游標(biāo)查詢

    mybatis如何對(duì)大量數(shù)據(jù)的游標(biāo)查詢

    這篇文章主要介紹了mybatis如何對(duì)大量數(shù)據(jù)的游標(biāo)查詢問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 在Java中使用Moshi?JSON庫(kù)的方法詳解

    在Java中使用Moshi?JSON庫(kù)的方法詳解

    Moshi?是一個(gè)可用于?Java?與?Kotlin?的?JSON?序列化與反序列化庫(kù),其主要使用?Kotlin?編寫,本文以樣例代碼的方式來演示該庫(kù)在?Java?中的使用,需要的朋友可以參考下
    2024-04-04
  • Spring?Security+JWT簡(jiǎn)述(附源碼)

    Spring?Security+JWT簡(jiǎn)述(附源碼)

    SpringSecurity是一個(gè)強(qiáng)大的可高度定制的認(rèn)證和授權(quán)框架,對(duì)于Spring應(yīng)用來說它是一套Web安全標(biāo)準(zhǔn),下面這篇文章主要給大家介紹了關(guān)于Spring?Security+JWT簡(jiǎn)述的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • Java中特殊運(yùn)算符及其應(yīng)用詳解

    Java中特殊運(yùn)算符及其應(yīng)用詳解

    當(dāng)涉及位操作和位級(jí)運(yùn)算時(shí),Java?提供了一組特殊的運(yùn)算符,即左移(<<)和右移(>>)運(yùn)算符,下面小編就帶大家深入了解一下它們的具體應(yīng)用吧
    2023-08-08
  • Oracle + Mybatis實(shí)現(xiàn)批量插入、更新和刪除示例代碼

    Oracle + Mybatis實(shí)現(xiàn)批量插入、更新和刪除示例代碼

    利用MyBatis動(dòng)態(tài)SQL的特性,我們可以做一些批量的操作,下面這篇文章主要給大家介紹了關(guān)于Oracle + Mybatis實(shí)現(xiàn)批量插入、更新和刪除的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2018-01-01
  • 詳解JVM之運(yùn)行時(shí)常量池

    詳解JVM之運(yùn)行時(shí)常量池

    JVM在運(yùn)行的時(shí)候會(huì)對(duì)class文件進(jìn)行加載,鏈接和初始化的過程。class文件中定義的常量池在JVM加載之后會(huì)發(fā)生什么神奇的變化呢?快來看一看吧。
    2021-06-06
  • Spring?BeanPostProcessor后處理器源碼解析

    Spring?BeanPostProcessor后處理器源碼解析

    這篇文章主要介紹了Spring?BeanPostProcessor后處理器源碼解析,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-09-09
  • SpringBoot自動(dòng)裝配原理詳解

    SpringBoot自動(dòng)裝配原理詳解

    這篇文章主要詳細(xì)介紹了SpringBoot的自動(dòng)裝配原理,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考一下
    2023-04-04

最新評(píng)論