Android iText向pdf模板插入数据和图片

2021-01-25

一、需求

这些日志在写App程序,有这么一个需求,就是需要生成格式统一的一个pdf文件,并向固定表格中填充数据,并且再在pdf中追加两页图片。

二、方案

手工设计一个pdf模板,这个具体步骤就不再赘述,可以网上搜索。说一下模板制作的简单步骤:

1、 用word制作你需要的表单模板
2、 把word制作好的表单模板,另存为pdf格式。
3、 用pdf编辑器(我用的迅捷pdf编辑器),打开pdf,然后进行表单编辑,在需要填充数据的的表格放入文本控件。
4、 另存为pdf模板。

这个模板就是App读取并进行操作的pdf模板,通过这个模板就可以把数据填充到pdf中,并重新生成一个新的pdf文件。

三、下面是代码部分,用到的jar包请看我的其他博文介绍,这里就不再赘述。

android.icu.text.SimpleDateFormat simpleDateFormat =
                new android.icu.text.SimpleDateFormat("HHmmss");// HH:mm:ss
        //设置默认时区
        simpleDateFormat.setTimeZone(android.icu.util.TimeZone.getTimeZone("GMT+8:00"));
        //获取当前时间
        Date date2 = new Date(System.currentTimeMillis());
        String sim2 = simpleDateFormat.format(date2);

        String folderName_WaterImage = "WaterImage";
        String folderName_WaterDB = "WaterDB";
        String folderName_WaterPdf = "WaterPdf";

        File sdCardDir_PdfTemplate = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOWNLOADS), folderName_WaterDB);
        File sdCardDir_WaterPdf = new File(Environment.getExternalStorageDirectory(),
                folderName_WaterPdf);
        File sdCardDir_WaterImage = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOWNLOADS), folderName_WaterImage);

        //模板路径
        String templatePath = sdCardDir_PdfTemplate + "/" + "WaterTemplate.pdf";
        //生成的新文件路径
        String newPDFPath = sdCardDir_WaterPdf + "/" +
                mWaterInfo.SamplingDate + "_" + mWaterInfo.WellNumber + "_" + sim2 + ".pdf";

        String imagePath1 = sdCardDir_WaterImage + "/" + "Image" + id + "_1";
        String imagePath2 = sdCardDir_WaterImage + "/" + "Image" + id + "_2";

        /**
         * 使用中文字体
         * 如果是利用 AcroFields填充值的不需要在程序中设置字体,在模板文件中设置字体为中文字体就行了
         */
        BaseFont bf = null;
        try {
            bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //Font FontChinese = new Font(bf, 12, Font.NORMAL);

        //下面是我需要填充的数据,String格式
        String[] strDate = mWaterInfo.SamplingDate.split("-");
        String[] str = {
                mWaterInfo.WellNumber, mWaterInfo.Longitude + "," + mWaterInfo.Latitude,
                strDate[0], strDate[1], strDate[2], mWaterInfo.SamplingTime,
                mWaterInfo.SampleMethods, mWaterInfo.SampleDepth, mWaterInfo.Temperature,
                mWaterInfo.Weather, mWaterInfo.WaterLevel, mWaterInfo.WaterTemp1,
                mWaterInfo.ORP1, mWaterInfo.DO1, mWaterInfo.pH1, mWaterInfo.CT1, mWaterInfo.NTU1,
                mWaterInfo.Smell, mWaterInfo.Thing, mWaterInfo.Color, mWaterInfo.SamplingName,
                mWaterInfo.RecordingName, mWaterInfo.ReagenInfo, mWaterInfo.bkInfo};
        //这个是pdf模板制作时,插入的文本控件名称
        String[] it = new String[]{
                "Text1", "Text2", "Text3", "Text4", "Text5", "Text6", "Text7",
                "Text8", "Text9", "Text10", "Text11", "Text12", "Text13", "Text14", "Text15",
                "Text16", "Text17", "Text18", "Text19", "Text20", "Text21", "Text22",
                "Text23", "Text24"};

        PdfReader reader = new PdfReader(templatePath);//对pdf进行读写
        PdfStamper pdfStamper = null;
        try {
            pdfStamper = new PdfStamper(reader, new FileOutputStream(new File(newPDFPath)));
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        AcroFields acroFields = pdfStamper.getAcroFields();  //获取pdf表单
        Map<String, String> formData = new HashMap<>();
        //formData.put("identify_number", identify.getId_number());


        int len = it.length;
        //把所有的控件都填入相应的数据
        for (int i = 0; i < len; i++) {
            acroFields.setFieldProperty(it[i], "textfont", bf, null);
            try {
                acroFields.setField(it[i], str[i]);
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        }

        PdfContentByte overContent2 = pdfStamper.getUnderContent(2);//追加一页
        PdfContentByte overContent3 = pdfStamper.getUnderContent(3);//追加一页
        Image idFontImg2 = Image.getInstance(imagePath1);//获取图片封装对象
        Image idFontImg3 = Image.getInstance(imagePath2);//获取图片封装对象
        Rectangle rectangleIdFont;

        rectangleIdFont = new Rectangle(PageSize.A4.getWidth(), PageSize.A4.getHeight());

        //设置图片位置,及缩放
        idFontImg2.scaleToFit(rectangleIdFont.getWidth(), rectangleIdFont.getHeight());
        idFontImg3.scaleToFit(rectangleIdFont.getWidth(), rectangleIdFont.getHeight());
        try {
            float x = rectangleIdFont.getLeft();
            float y = rectangleIdFont.getBottom();
            idFontImg2.setAbsolutePosition(x, y);
            idFontImg3.setAbsolutePosition(x, y);
            overContent2.addImage(idFontImg2);//将图片添加到pdf
            overContent3.addImage(idFontImg3);//将图片添加到pdf
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        //addMaterMark(reader, pdfStamper, bfChinese, timeWater);//追加水印
        pdfStamper.setFormFlattening(true); //设置表单之后不可编辑
        try {
            pdfStamper.close();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        reader.close();


        Toast.makeText(this, "导出pdf成功", Toast.LENGTH_LONG).show();

四、

程序调试了三四天,中间是各种问题,各种bug,各种报错,终于调试成功。
欢迎交流!