PoiDocxDemo【Android將表單數據生成Word文檔的方案之二(基於Poi4.0.0),目前只能java生成】

版權聲明:本文爲HaiyuKing原創文章,轉載請註明出處!html

前言

這個是《PoiDemo【Android將表單數據生成Word文檔的方案之二(基於Poi4.0.0)】》的擴展,上一篇是根據doc模板生成doc文件,這個是根據docx模板生成docx文件。java

注意:目前只能java生成,集成到Android項目中,運行報錯【暫時未解決】:apache

Process: com.why.project.poidocxdemo, PID: 13762
    java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/xml/stream/XMLEventFactory;
        at org.apache.poi.openxml4j.opc.internal.marshallers.PackagePropertiesMarshaller.<clinit>(PackagePropertiesMarshaller.java:41)
        at org.apache.poi.openxml4j.opc.OPCPackage.<init>(OPCPackage.java:140)
        at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:103)
        at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:298)
        at org.apache.poi.ooxml.util.PackageHelper.open(PackageHelper.java:37)
        at org.apache.poi.xwpf.usermodel.XWPFDocument.<init>(XWPFDocument.java:142)

前期準備

參考《PoiDemo【Android將表單數據生成Word文檔的方案之二(基於Poi4.0.0)】api

區別在於,模板的佔位有所不用【docx模板文件不須要$符號】:ide

代碼分析

參考《PoiDemo【Android將表單數據生成Word文檔的方案之二(基於Poi4.0.0)】測試

使用步驟

1、項目組織結構圖

注意事項:spa

一、  導入類文件後須要change包名以及從新import R文件路徑.net

二、  Values目錄下的文件(strings.xml、dimens.xml、colors.xml等),若是項目中存在,則複製裏面的內容,不要整個覆蓋3d

2、導入步驟

一、將poi相關jar文件導入項目中【Demo採用的是module方式】

引用jar文件參考《【Android Studio安裝部署系列】十7、Android studio引用第三方庫、jar、so、arr文件excel

注意:

解析docx文件,須要引用下面的jar文件:

  • poi-4.0.0.jar
  • poi-ooxml-4.0.0.jar
  • poi-ooxml-schemas-4.0.0.jar
  • ooxml-lib目錄下的curvesapi-1.05.jar、xmlbeans-3.0.1.jar
  • lib目錄下的commons-collections4-4.2.jar
  • 下載的commons-compress-1.18.jar

commons-compress-1.18.jar下載地址:http://commons.apache.org/proper/commons-compress/download_compress.cgi

二、將製做的模板文件複製到D:/temp目錄下

 

三、將PoiUtils.java文件複製到項目中

package com.why.main;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class PoiUtils {
    
    //測試
    public static void main(String[] args) {
        String templetDocPath = "D:/temp/請假單模板1.docx";
        String targetDocPath = "D:/temp/請假單1.docx";
        
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("writeDate", "2018年10月14日");
        dataMap.put("name", "HaiyuKing");
        dataMap.put("dept", "移動開發組");
        dataMap.put("leaveType", "☑倒休 √年假 ✔事假 ☐病假 ☐婚假 ☐產假 ☐其餘");
        dataMap.put("leaveReason", "倒休一天。");
        dataMap.put("leaveStartDate", "2018年10月14日上午");
        dataMap.put("leaveEndDate", "2018年10月14日下午");
        dataMap.put("leaveDay", "1");
        dataMap.put("leaveLeader", "贊成");
        dataMap.put("leaveDeptLeaderImg", "贊成!");
        
        PoiUtils.writeToDocx(templetDocPath,targetDocPath,dataMap);
        
        try {
            PoiUtils.readDocx(targetDocPath);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 經過XWPFDocument對內容進行訪問。對於XWPF文檔而言,用這種方式進行讀操做更佳。
     * @throws Exception
     */
    public static void readDocx(String templetDocPath) throws Exception {
        InputStream is = new FileInputStream(templetDocPath);
        XWPFDocument doc = new XWPFDocument(is);
        List<XWPFParagraph> paras = doc.getParagraphs();
        for (XWPFParagraph para : paras) {
            //當前段落的屬性
            System.out.println("para=="+para.getText());
        }
        //獲取文檔中全部的表格
        List<XWPFTable> tables = doc.getTables();
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        for (XWPFTable table : tables) {
            //獲取表格對應的行
            rows = table.getRows();
            for (XWPFTableRow row : rows) {
                //獲取行對應的單元格
                cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    System.out.println("cell=="+cell.getText());;
                }
            }
        }
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 生成一個docx文件
     * @param templetDocPath  模板文件的完整路徑
     * @param targetDocPath 生成的目標文件的完整路徑
     * @param dataMap 替換的數據*/
    public static void writeToDocx(String templetDocPath, String targetDocPath, Map<String,Object> dataMap){
        try
        {
            //獲得模板doc文件的HWPFDocument對象
            InputStream in = new FileInputStream(templetDocPath);
            writeToDocx(in,targetDocPath,dataMap);
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 生成一個docx文件,主要用於直接讀取asset目錄下的模板文件,不用先複製到sd卡中
     * @param templetDocInStream  模板文件的InputStream
     * @param targetDocPath 生成的目標文件的完整路徑
     * @param dataMap 替換的數據*/
    public static void writeToDocx(InputStream templetDocInStream, String targetDocPath, Map<String,Object> dataMap){
        try
        {
            //獲得模板doc文件的HWPFDocument對象
            XWPFDocument HDocx = new XWPFDocument(templetDocInStream);
            //替換段落裏面的變量  
            replaceInPara(HDocx, dataMap);  
            //替換表格裏面的變量  
            replaceInTable(HDocx, dataMap);  
            
            //寫到另外一個文件中
            OutputStream os = new FileOutputStream(targetDocPath);  
            //把doc輸出到輸出流中
            HDocx.write(os);
            os.close();
            templetDocInStream.close();
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    
    /** 
    * 替換段落裏面的變量 
    * @param doc 要替換的文檔 
    * @param params 參數 
    */  
    private static void replaceInPara(XWPFDocument doc, Map<String, Object> params) {  
        Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();  
        XWPFParagraph para;  
        while (iterator.hasNext()) {  
            para = iterator.next();  
            replaceInPara(para, params);  
        }  
    }
    
    
    
    /**
     * 替換段落裏面的變量
     * @param para 要替換的段落
     * @param params 參數
     */
    private static void replaceInPara(XWPFParagraph para, Map<String, Object> params) {
        List<XWPFRun> runs;
        System.out.println("para.getParagraphText()=="+para.getParagraphText());
        
        runs = para.getRuns();
        for (int i=0; i<runs.size(); i++) {
            XWPFRun run = runs.get(i);
            String runText = run.toString();
            System.out.println("runText=="+runText);
            
            // 替換文本內容,將自定義的$xxx$替換成實際文本
            for(Map.Entry<String, Object> entry : params.entrySet())
            {
                runText = runText.replace(entry.getKey(), entry.getValue()+"");
                //直接調用XWPFRun的setText()方法設置文本時,在底層會從新建立一個XWPFRun,把文本附加在當前文本後面,
                //因此咱們不能直接設值,須要先刪除當前run,而後再本身手動插入一個新的run。
                para.removeRun(i);
                para.insertNewRun(i).setText(runText);
            }
        }
    }
    
    /** 
    * 替換表格裏面的變量 
    * @param doc 要替換的文檔 
    * @param params 參數 
    */  
   private static void replaceInTable(XWPFDocument doc, Map<String, Object> params) {  
      Iterator<XWPFTable> iterator = doc.getTablesIterator();  
      XWPFTable table;  
      List<XWPFTableRow> rows;  
      List<XWPFTableCell> cells;  
      List<XWPFParagraph> paras;  
      while (iterator.hasNext()) {  
         table = iterator.next();  
         rows = table.getRows();  
         for (XWPFTableRow row : rows) {  
            cells = row.getTableCells();  
            for (XWPFTableCell cell : cells) {  
                paras = cell.getParagraphs();  
                for (XWPFParagraph para : paras) {  
                   replaceInPara(para, params);  
                }  
            }  
         }  
      }  
   }  

}
PoiUtils.java

四、運行

 

五、效果【生成的docx文件有問題,以前的樣式全失效了

混淆配置

暫無

參考資料

Android使用ApachePOI組件讀寫Worddoc和docx文件

Android 下使用 Poi 讀取高版本excel

Java:封裝POI實現word的docx文件的簡單模板功能

使用POI讀寫word docx文件

POI操做word2007(docx)文件的文本和圖片

項目demo下載地址

連接:https://pan.baidu.com/s/165hpn3kZssxVvHIF9RNtkQ 提取碼:3mmj

相關文章
相關標籤/搜索