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,各種報錯,終於除錯成功。
歡迎交流!

相關文章