Android iText向pdf模板插入數據和圖片

一、需求

這些日誌在寫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,各種報錯,終於調試成功。
歡迎交流!