itextpdf 5.5.10使用PdfStamper类时中文不显示问题

itextpdf 5.5.10使用PdfStamper类时中文不显示问题

最近做了一个业务场景,生成支付的电子回单,业务逻辑为根据银行方的接口返回的电子回单数据,填充PDF模板,生成PDF文件。遇到了中文不显示或者只显示中文的问题,研究了三四个小时终于解决了,其实特别简单,只是网上相关的资料太少了,itextpdf的代码注释也一言难尽,所以特此记录下解决方法。

生成PDF模板:https://www.pdfescape.com/

网站可以免费免注册使用,创建一个空的pdf,按需添加页面元素,支持文本、线、下拉框、多选框等
模板效果图
装填PDF模板并生成PDF的代码如下:

    /**
     * 根据模板装填并生成pdf文件
     * @author zhangt
     */
    public static File generatePdfFile2Local(String templatePath,
                                      String templateName ,
                                      String filePath ,
                                      String fileName ,
                                      Consumer<AcroFields> consumer) throws IOException, DocumentException {
        //填充pdf
        PdfReader reader = null;
        PdfStamper stamper = null;
        File generateFile = null;
         try {
            reader = new PdfReader(templatePath+"/"+templateName);
            if(!new File(filePath).exists()){
                new File(filePath).mkdirs();
            }
            generateFile = new File(filePath,fileName);
            if(!generateFile.exists() || !generateFile.isFile()){
                generateFile.createNewFile();
            }
            stamper = new PdfStamper(reader,new FileOutputStream(generateFile));
            //取出模板中的属性字段
            AcroFields fields = stamper.getAcroFields();
            //填充数据
            consumer.accept(fields);
            stamper.setFormFlattening(false);
            return generateFile;
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        }finally {
            if(stamper != null){
                stamper.close();
            }
            if(reader != null){
                reader.close();
            }
        }
        return generateFile;
    }

打开生成的PDF文件,发现里面的中文字段都不显示(或者点一下才能显示),看了itextpdf的源码,注释实在是太少了,研究了一会决定百度下。尝试了几个都不对,后来在一个博主的文章中找到了一行代码:

//中文字体
BaseFont baseFont = BaseFont.CreateFont("C:\\WINDOWS\\Fonts\\simsun.ttc,1",BaseFont.IDENTITY_H,
BaseFont.EMBEDDED);

form.AddSubstitutionFont(baseFont);

果断尝试下,发现确实能显示中文了,只不过其他的数字都不显示了 。。。
之前试的时候其实遇到了这种情况,只需要设置一个属性就好了

 stamper.setFormFlattening(false);

完整代码如下:

  /**
     * 根据模板装填并生成pdf文件
     * @author zhangt
     */
    public static File generatePdfFile2Local(String templatePath,
                                      String templateName ,
                                      String filePath ,
                                      String fileName ,
                                      Consumer<AcroFields> consumer) throws IOException, DocumentException {
        //填充pdf
        PdfReader reader = null;
        PdfStamper stamper = null;
        File generateFile = null;
        //中文字体
        BaseFont baseFont = BaseFont.createFont("C:\\WINDOWS\\Fonts\\simsun.ttc,1",BaseFont.IDENTITY_H,
                BaseFont.EMBEDDED);
        try {
            reader = new PdfReader(templatePath+"/"+templateName);
            if(!new File(filePath).exists()){
                new File(filePath).mkdirs();
            }
            generateFile = new File(filePath,fileName);
            if(!generateFile.exists() || !generateFile.isFile()){
                generateFile.createNewFile();
            }
            stamper = new PdfStamper(reader,new FileOutputStream(generateFile));
            //取出模板中的属性字段
            AcroFields fields = stamper.getAcroFields();
            fields.addSubstitutionFont(baseFont);
            //填充数据
            consumer.accept(fields);
            stamper.setFormFlattening(false);
            return generateFile;
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        }finally {
            if(stamper != null){
                stamper.close();
            }
            if(reader != null){
                reader.close();
            }
        }
        return generateFile;
    }

遇到这种代码注释和相关文档都很少的包真的难受,还是要多多阅读源码,提升代码思想,也许遇到这种小问题思路就开阔多了 。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是一个使用 iTextPDF 5.5.10 导出 PDF 表格的示例工具类,其中包含支持单元格合并的方法: ```java import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.PageSize; import com.itextpdf.text.pdf.PdfPCell; import com.itextpdf.text.pdf.PdfPTable; import com.itextpdf.text.pdf.PdfWriter; import java.io.FileNotFoundException; import java.io.FileOutputStream; public class PDFExporter { public static void exportTableToPDF(String filePath, String[] header, String[][] data) { Document document = new Document(PageSize.A4.rotate()); try { PdfWriter.getInstance(document, new FileOutputStream(filePath)); document.open(); PdfPTable table = new PdfPTable(header.length); table.setWidthPercentage(100); for (String column : header) { PdfPCell cell = new PdfPCell(); cell.setPhrase(new com.itextpdf.text.Paragraph(column)); table.addCell(cell); } for (int row = 0; row < data.length; row++) { for (int column = 0; column < data[row].length; column++) { PdfPCell cell = new PdfPCell(); cell.setPhrase(new com.itextpdf.text.Paragraph(data[row][column])); table.addCell(cell); } } document.add(table); } catch (DocumentException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { document.close(); } } public static void mergeCells(PdfPTable table, int row1, int col1, int row2, int col2) { for (int row = row1; row <= row2; row++) { for (int col = col1; col <= col2; col++) { if (row == row1 && col == col1) { continue; } PdfPCell cell = table.getRow(row).getCells()[col]; cell.setPhrase(null); cell.setPadding(0); cell.setBorder(PdfPCell.NO_BORDER); } } PdfPCell cell = table.getRow(row1).getCells()[col1]; cell.setRowspan(row2 - row1 + 1); cell.setColspan(col2 - col1 + 1); } } ``` 调用 `exportTableToPDF` 方法可以将一个二维字符串数组导出为一个 PDF 表格文件,其中第一个参数是文件路径,第二个参数是表头数组,第三个参数是数据数组。 调用 `mergeCells` 方法可以将表格中的多个单元格合并为一个单元格,其中第一个参数是目标表格,第二个参数是起始行号,第三个参数是起始列号,第四个参数是结束行号,第五个参数是结束列号。 例如,如果要将第 2 行第 3、4、5 列合并为一个单元格,可以这样调用 `mergeCells` 方法: ```java PDFExporter.mergeCells(table, 1, 2, 1, 4); ``` 其中 `table` 是导出 PDF 表格的 `PdfPTable` 对象。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值