讀取word模板,填充數據后導出


一、需求說明

      定期生成word報告,報告中含有文本、表格、圖表等元素,依次獲取進行替換,保留原有樣式,生成新的word文檔

二、引入依賴

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.1</version>
        </dependency>
         <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.1</version>
        </dependency>   
                <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.1</version>
        </dependency> 

三、word模板樣式

 類似此種樣式,有文本、圖表、表格

四、代碼

4.1 工具類

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;

import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFChart;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumData;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumVal;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTStrData;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTStrVal;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTColor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHpsMeasure;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTParaRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShd;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVerticalJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;

/**
 * poi生成word的工具類
 */
public class PoiWordTools {

    private static final BigDecimal bd2 = new BigDecimal("2");


    /**
     * 調用替換柱狀圖數據
     */
    public  static void replaceBarCharts(POIXMLDocumentPart poixmlDocumentPart,
                                        List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
        XWPFChart chart = (XWPFChart) poixmlDocumentPart;
        chart.getCTChart();

        //根據屬性第一列名稱切換數據類型
        CTChart ctChart = chart.getCTChart();
        CTPlotArea plotArea = ctChart.getPlotArea();

        CTBarChart barChart = plotArea.getBarChartArray(0);
        List<CTBarSer> BarSerList = barChart.getSerList();  // 獲取柱狀圖單位

        //刷新內置excel數據
        refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新頁面顯示數據
        refreshBarStrGraphContent(barChart, BarSerList, listItemsByType, fldNameArr, 1);

    }
    
    
    /**
     * 雙柱圖
     */
    public void replaceTwoBarCharts(POIXMLDocumentPart poixmlDocumentPart,
            List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
            XWPFChart chart = (XWPFChart) poixmlDocumentPart;
            chart.getCTChart();
            
            //根據屬性第一列名稱切換數據類型
            CTChart ctChart = chart.getCTChart();
            CTPlotArea plotArea = ctChart.getPlotArea();
            
            CTBarChart barChart = plotArea.getBarChartArray(0);
            List<CTBarSer> BarSerList = barChart.getSerList();  // 獲取柱狀圖單位
            
            //刷新內置excel數據
            refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
            //刷新頁面顯示數據
            refreshBarStrGraphContent(barChart, BarSerList, listItemsByType, fldNameArr, 1);
            
            CTBarChart barCharttwo = plotArea.getBarChartArray(0);
            List<CTBarSer> BarSerListtwo = barChart.getSerList();  // 獲取柱狀圖單位
            
            //刷新內置excel數據
            refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
            //刷新頁面顯示數據
            refreshBarStrGraphContent(barCharttwo, BarSerListtwo, listItemsByType, fldNameArr, 2);

}
    
    



    /**
     * 調用替換折線圖數據
     */
    public static void replaceLineCharts(POIXMLDocumentPart poixmlDocumentPart,
                                         List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
        XWPFChart chart = (XWPFChart) poixmlDocumentPart;
        chart.getCTChart();

        //根據屬性第一列名稱切換數據類型
        CTChart ctChart = chart.getCTChart();
        CTPlotArea plotArea = ctChart.getPlotArea();

        CTLineChart lineChart = plotArea.getLineChartArray(0);
        List<CTLineSer> lineSerList = lineChart.getSerList();   // 獲取折線圖單位

        //刷新內置excel數據
        refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新頁面顯示數據
        refreshLineStrGraphContent(lineChart, lineSerList, listItemsByType, fldNameArr, 1);

    }


    /**
     * 調用替換餅圖數據
     */
    public  void replacePieCharts(POIXMLDocumentPart poixmlDocumentPart,
                                         List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
        XWPFChart chart = (XWPFChart) poixmlDocumentPart;
        chart.getCTChart();

        //根據屬性第一列名稱切換數據類型
        CTChart ctChart = chart.getCTChart();
        CTPlotArea plotArea = ctChart.getPlotArea();

        CTPieChart pieChart = plotArea.getPieChartArray(0);
        List<CTPieSer> pieSerList = pieChart.getSerList();  // 獲取餅圖單位

        //刷新內置excel數據
        refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新頁面顯示數據
        refreshPieStrGraphContent(pieChart, pieSerList, listItemsByType, fldNameArr, 1);

    }


    /**
     * 調用替換柱狀圖、折線圖組合數據
     */
    public  void replaceCombinationCharts(POIXMLDocumentPart poixmlDocumentPart,
                                        List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
        XWPFChart chart = (XWPFChart) poixmlDocumentPart;
        chart.getCTChart();

        //根據屬性第一列名稱切換數據類型
        CTChart ctChart = chart.getCTChart();
        CTPlotArea plotArea = ctChart.getPlotArea();
        CTBarChart barChart = plotArea.getBarChartArray(0);
        List<CTBarSer> barSerList = barChart.getSerList();  // 獲取柱狀圖單位
        //刷新內置excel數據
       refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新頁面顯示數據
        refreshBarStrGraphContent(barChart, barSerList, listItemsByType, fldNameArr, 1);


        CTLineChart lineChart = plotArea.getLineChartArray(0);
        List<CTLineSer> lineSerList = lineChart.getSerList();   // 獲取折線圖單位
        //刷新內置excel數據
        refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新頁面顯示數據
        refreshLineStrGraphContent(lineChart, lineSerList, listItemsByType, fldNameArr, 2);

    }


    /**
     * 刷新折線圖數據方法
     *
     * @param typeChart
     * @param serList
     * @param dataList
     * @param fldNameArr
     * @param titleArr
     * @param showtailArr
     * @param ispercentArr
     * @param position
     * @return
     */
    public static boolean refreshLineStrGraphContent(Object typeChart,
                                                     List<?> serList, List<Map<String, String>> dataList, List<String> fldNameArr, int position) {

        boolean result = true;
        //更新數據區域
        for (int i = 0; i < serList.size(); i++) {
            //CTSerTx tx=null;
            CTAxDataSource cat = null;
            CTNumDataSource val = null;
            CTLineSer ser = ((CTLineChart) typeChart).getSerArray(i);
            //tx= ser.getTx();
            // Category Axis Data
            cat = ser.getCat();
            // 獲取圖表的值
            val = ser.getVal();
            // strData.set
            CTStrData strData = cat.getStrRef().getStrCache();
            CTNumData numData = val.getNumRef().getNumCache();
            strData.setPtArray((CTStrVal[]) null); // unset old axis text
            numData.setPtArray((CTNumVal[]) null); // unset old values

            // set model
            long idx = 0;
            for (int j = 0; j < dataList.size(); j++) {
                //判斷獲取的值是否為空
                String value = "0";
                if (new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))) != null) {
                    value = new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))).toString();
                }
                if (!"0".equals(value)) {
                    CTNumVal numVal = numData.addNewPt();//序列值
                    numVal.setIdx(idx);
                    numVal.setV(value);
                }
                CTStrVal sVal = strData.addNewPt();//序列名稱
                sVal.setIdx(idx);
                sVal.setV(dataList.get(j).get(fldNameArr.get(0)));
                idx++;
            }
            numData.getPtCount().setVal(idx);
            strData.getPtCount().setVal(idx);


            //賦值橫坐標數據區域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0)
                    .formatAsString("Sheet1", true);
            cat.getStrRef().setF(axisDataRange);

            //數據區域
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + position, i + position)
                    .formatAsString("Sheet1", true);
            val.getNumRef().setF(numDataRange);

        }
        return result;
    }


    /**
     * 刷新柱狀圖數據方法
     *
     * @param typeChart
     * @param serList
     * @param dataList
     * @param fldNameArr
     * @param titleArr
     * @param showtailArr
     * @param ispercentArr
     * @param position
     * @return
     */
    public static boolean refreshBarStrGraphContent(Object typeChart,
                                                    List<?> serList, List<Map<String, String>> dataList, List<String> fldNameArr, int position) {

        boolean result = true;
        //更新數據區域
        for (int i = 0; i < serList.size(); i++) {
            //CTSerTx tx=null;
            CTAxDataSource cat = null;
            CTNumDataSource val = null;
            CTBarSer ser = ((CTBarChart) typeChart).getSerArray(i);
            //tx= ser.getTx();
            // Category Axis Data
            cat = ser.getCat();
            // 獲取圖表的值
            val = ser.getVal();
            // strData.set
            CTStrData strData = cat.getStrRef().getStrCache();
            CTNumData numData = val.getNumRef().getNumCache();
            strData.setPtArray((CTStrVal[]) null); // unset old axis text
            numData.setPtArray((CTNumVal[]) null); // unset old values

            // set model
            long idx = 0;
            for (int j = 0; j < dataList.size(); j++) {
                //判斷獲取的值是否為空
                String value = "0";
                if (new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))) != null) {
                    value = new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))).toString();
                }
                if (!"0".equals(value)) {
                    CTNumVal numVal = numData.addNewPt();//序列值
                    numVal.setIdx(idx);
                    numVal.setV(value);
                }
                CTStrVal sVal = strData.addNewPt();//序列名稱
                sVal.setIdx(idx);
                sVal.setV(dataList.get(j).get(fldNameArr.get(0)));
                idx++;
            }
            numData.getPtCount().setVal(idx);
            strData.getPtCount().setVal(idx);


            //賦值橫坐標數據區域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0)
                    .formatAsString("Sheet1", true);
            cat.getStrRef().setF(axisDataRange);

            //數據區域
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + position, i + position)
                    .formatAsString("Sheet1", true);
            val.getNumRef().setF(numDataRange);

        }
        return result;
    }



    /**
     * 刷新餅圖數據方法
     *
     * @param typeChart
     * @param serList
     * @param dataList
     * @param fldNameArr
     * @param titleArr
     * @param showtailArr
     * @param ispercentArr
     * @param position
     * @return
     */
    public static boolean refreshPieStrGraphContent(Object typeChart,
                                                    List<?> serList, List<Map<String, String>> dataList, List<String> fldNameArr, int position) {

        boolean result = true;
        //更新數據區域
        for (int i = 0; i < serList.size(); i++) {
            //CTSerTx tx=null;
            CTAxDataSource cat = null;
            CTNumDataSource val = null;
            CTPieSer ser = ((CTPieChart) typeChart).getSerArray(i);

            //tx= ser.getTx();
            // Category Axis Data
            cat = ser.getCat();
            // 獲取圖表的值
            val = ser.getVal();
            // strData.set
            CTStrData strData = cat.getStrRef().getStrCache();
            CTNumData numData = val.getNumRef().getNumCache();
            strData.setPtArray((CTStrVal[]) null); // unset old axis text
            numData.setPtArray((CTNumVal[]) null); // unset old values

            // set model
            long idx = 0;
            for (int j = 0; j < dataList.size(); j++) {
                //判斷獲取的值是否為空
                String value = "0";
                if (new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))) != null) {
                    value = new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))).toString();
                }
                if (!"0".equals(value)) {
                    CTNumVal numVal = numData.addNewPt();//序列值
                    numVal.setIdx(idx);
                    numVal.setV(value);
                }
                CTStrVal sVal = strData.addNewPt();//序列名稱
                sVal.setIdx(idx);
                sVal.setV(dataList.get(j).get(fldNameArr.get(0)));
                idx++;
            }
            numData.getPtCount().setVal(idx);
            strData.getPtCount().setVal(idx);


            //賦值橫坐標數據區域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0)
                    .formatAsString("Sheet1", true);
            cat.getStrRef().setF(axisDataRange);

            //數據區域
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + position, i + position)
                    .formatAsString("Sheet1", true);
            val.getNumRef().setF(numDataRange);
        }
        return result;
    }


    /**
     * 刷新內置excel數據
     *
     * @param chart
     * @param dataList
     * @param fldNameArr
     * @param titleArr
     * @param showtailArr
     * @param ispercentArr
     * @return
     */
    public static boolean refreshExcel(XWPFChart chart,
                                       List<Map<String, String>> dataList, List<String> fldNameArr, List<String> titleArr) {
        boolean result = true;
        Workbook wb = new XSSFWorkbook();
        Sheet sheet = wb.createSheet("Sheet1");
        //根據數據創建excel第一行標題行
        for (int i = 0; i < titleArr.size(); i++) {
            if (sheet.getRow(0) == null) {
                sheet.createRow(0).createCell(i).setCellValue(titleArr.get(i) == null ? "" : titleArr.get(i));
            } else {
                sheet.getRow(0).createCell(i).setCellValue(titleArr.get(i) == null ? "" : titleArr.get(i));
            }
        }

        //遍歷數據行
        for (int i = 0; i < dataList.size(); i++) {
            Map<String, String> baseFormMap = dataList.get(i);//數據行
            //fldNameArr字段屬性
            for (int j = 0; j < fldNameArr.size(); j++) {
                if (sheet.getRow(i + 1) == null) {
                    if (j == 0) {
                        try {
                            sheet.createRow(i + 1).createCell(j).setCellValue(baseFormMap.get(fldNameArr.get(j)) == null ? "" : baseFormMap.get(fldNameArr.get(j)));
                        } catch (Exception e) {
                            if (baseFormMap.get(fldNameArr.get(j)) == null) {
                                sheet.createRow(i + 1).createCell(j).setCellValue("");
                            } else {
                                sheet.createRow(i + 1).createCell(j).setCellValue(baseFormMap.get(fldNameArr.get(j)));
                            }
                        }
                    }
                } else {
                    BigDecimal b = new BigDecimal(baseFormMap.get(fldNameArr.get(j)));
                    double value = 0d;
                    if (b != null) {
                        value = b.doubleValue();
                    }
                    if (value == 0) {
                        sheet.getRow(i + 1).createCell(j);
                    } else {
                        sheet.getRow(i + 1).createCell(j).setCellValue(b.doubleValue());
                    }
                }
            }

        }
        // 更新嵌入的workbook
        POIXMLDocumentPart xlsPart = chart.getRelations().get(0);
        OutputStream xlsOut = xlsPart.getPackagePart().getOutputStream();

        try {
            wb.write(xlsOut);
            xlsOut.close();
        } catch (IOException e) {
            e.printStackTrace();
            result = false;
        } finally {
            if (wb != null) {
                try {
                    wb.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    result = false;
                }
            }
        }
        return result;
    }


    /**
     * 設置表格樣式
     *
     * @param cell
     * @param fontName
     * @param fontSize
     * @param fontBlod
     * @param alignment
     * @param vertical
     * @param fontColor
     * @param bgColor
     * @param cellWidth
     * @param content
     */
    public  void setWordCellSelfStyle(XWPFTableCell cell, String fontName, String fontSize, int fontBlod,
                                            String alignment, String vertical, String fontColor,
                                            String bgColor, long cellWidth, String content) {

        //poi對字體大小設置特殊,不支持小數,但對原word字體大小做了乘2處理
        BigInteger bFontSize = new BigInteger("24");
        if (fontSize != null && !fontSize.equals("")) {
            //poi對字體大小設置特殊,不支持小數,但對原word字體大小做了乘2處理
            BigDecimal fontSizeBD = new BigDecimal(fontSize);
            fontSizeBD = bd2.multiply(fontSizeBD);
            fontSizeBD = fontSizeBD.setScale(0, BigDecimal.ROUND_HALF_UP);//這里取整
            bFontSize = new BigInteger(fontSizeBD.toString());// 字體大小
        }
        //=====獲取單元格
        CTTc tc = cell.getCTTc();
        //====tcPr開始====》》》》
        CTTcPr tcPr = tc.getTcPr();//獲取單元格里的<w:tcPr>
        if (tcPr == null) {//沒有<w:tcPr>,創建
            tcPr = tc.addNewTcPr();
        }

        //  --vjc開始-->>
        CTVerticalJc vjc = tcPr.getVAlign();//獲取<w:tcPr>  的<w:vAlign w:val="center"/>
        if (vjc == null) {//沒有<w:w:vAlign/>,創建
            vjc = tcPr.addNewVAlign();
        }
        //設置單元格對齊方式
        vjc.setVal(vertical.equals("top") ? STVerticalJc.TOP : vertical.equals("bottom") ? STVerticalJc.BOTTOM : STVerticalJc.CENTER); //垂直對齊

        CTShd shd = tcPr.getShd();//獲取<w:tcPr>里的<w:shd w:val="clear" w:color="auto" w:fill="C00000"/>
        if (shd == null) {//沒有<w:shd>,創建
            shd = tcPr.addNewShd();
        }
        // 設置背景顏色
        shd.setFill(bgColor.substring(1));
        //《《《《====tcPr結束====

        //====p開始====》》》》
        CTP p = tc.getPList().get(0);//獲取單元格里的<w:p w:rsidR="00C36068" w:rsidRPr="00B705A0" w:rsidRDefault="00C36068" w:rsidP="00C36068">

        //---ppr開始--->>>
        CTPPr ppr = p.getPPr();//獲取<w:p>里的<w:pPr>
        if (ppr == null) {//沒有<w:pPr>,創建
            ppr = p.addNewPPr();
        }
        //  --jc開始-->>
        CTJc jc = ppr.getJc();//獲取<w:pPr>里的<w:jc w:val="left"/>
        if (jc == null) {//沒有<w:jc/>,創建
            jc = ppr.addNewJc();
        }
        //設置單元格對齊方式
        jc.setVal(alignment.equals("left") ? STJc.LEFT : alignment.equals("right") ? STJc.RIGHT : STJc.CENTER); //水平對齊
        //  <<--jc結束--
        //  --pRpr開始-->>
        CTParaRPr pRpr = ppr.getRPr(); //獲取<w:pPr>里的<w:rPr>
        if (pRpr == null) {//沒有<w:rPr>,創建
            pRpr = ppr.addNewRPr();
        }
        CTFonts pfont = pRpr.getRFonts();//獲取<w:rPr>里的<w:rFonts w:ascii="宋體" w:eastAsia="宋體" w:hAnsi="宋體"/>
        if (pfont == null) {//沒有<w:rPr>,創建
            pfont = pRpr.addNewRFonts();
        }
        //設置字體
        pfont.setAscii(fontName);
        pfont.setEastAsia(fontName);
        pfont.setHAnsi(fontName);

        CTOnOff pb = pRpr.getB();//獲取<w:rPr>里的<w:b/>
        if (pb == null) {//沒有<w:b/>,創建
            pb = pRpr.addNewB();
        }
        //設置字體是否加粗
        pb.setVal(fontBlod == 1 ? STOnOff.ON : STOnOff.OFF);

        CTHpsMeasure psz = pRpr.getSz();//獲取<w:rPr>里的<w:sz w:val="32"/>
        if (psz == null) {//沒有<w:sz w:val="32"/>,創建
            psz = pRpr.addNewSz();
        }
        // 設置單元格字體大小
        psz.setVal(bFontSize);
        CTHpsMeasure pszCs = pRpr.getSzCs();//獲取<w:rPr>里的<w:szCs w:val="32"/>
        if (pszCs == null) {//沒有<w:szCs w:val="32"/>,創建
            pszCs = pRpr.addNewSzCs();
        }
        // 設置單元格字體大小
        pszCs.setVal(bFontSize);
        //  <<--pRpr結束--
        //<<<---ppr結束---

        //---r開始--->>>
        List<CTR> rlist = p.getRList(); //獲取<w:p>里的<w:r w:rsidRPr="00B705A0">
        CTR r = null;
        if (rlist != null && rlist.size() > 0) {//獲取第一個<w:r>
            r = rlist.get(0);
        } else {//沒有<w:r>,創建
            r = p.addNewR();
        }
        //--rpr開始-->>
        CTRPr rpr = r.getRPr();//獲取<w:r w:rsidRPr="00B705A0">里的<w:rPr>
        if (rpr == null) {//沒有<w:rPr>,創建
            rpr = r.addNewRPr();
        }
        //->-
        CTFonts font = rpr.getRFonts();//獲取<w:rPr>里的<w:rFonts w:ascii="宋體" w:eastAsia="宋體" w:hAnsi="宋體" w:hint="eastAsia"/>
        if (font == null) {//沒有<w:rFonts>,創建
            font = rpr.addNewRFonts();
        }
        //設置字體
        font.setAscii(fontName);
        font.setEastAsia(fontName);
        font.setHAnsi(fontName);

        CTOnOff b = rpr.getB();//獲取<w:rPr>里的<w:b/>
        if (b == null) {//沒有<w:b/>,創建
            b = rpr.addNewB();
        }
        //設置字體是否加粗
        b.setVal(fontBlod == 1 ? STOnOff.ON : STOnOff.OFF);
        CTColor color = rpr.getColor();//獲取<w:rPr>里的<w:color w:val="FFFFFF" w:themeColor="background1"/>
        if (color == null) {//沒有<w:color>,創建
            color = rpr.addNewColor();
        }
        // 設置字體顏色
        if (content.contains("↓")) {
            color.setVal("43CD80");
        } else if (content.contains("↑")) {
            color.setVal("943634");
        } else {
            color.setVal(fontColor.substring(1));
        }
        CTHpsMeasure sz = rpr.getSz();
        if (sz == null) {
            sz = rpr.addNewSz();
        }
        sz.setVal(bFontSize);
        CTHpsMeasure szCs = rpr.getSzCs();
        if (szCs == null) {
            szCs = rpr.addNewSz();
        }
        szCs.setVal(bFontSize);
        //-<-
        //<<--rpr結束--
        List<CTText> tlist = r.getTList();
        CTText t = null;
        if (tlist != null && tlist.size() > 0) {//獲取第一個<w:r>
            t = tlist.get(0);
        } else {//沒有<w:r>,創建
            t = r.addNewT();
        }
        t.setStringValue(content);
        //<<<---r結束---
    }

}
View Code

4.2 調用類

package com.censoft.app.wordreport;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.XWPFChart;
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 org.apache.xmlbeans.XmlCursor;
import org.springframework.util.StringUtils;

import com.censoft.app.wordreport.util.PoiWordTools;

public class PoiJdWordTable {

    public static void main(String[] args) throws Exception {
    

    String[] nds = new String[]{"2018年","2019年"};
    String[] qq = new String[]{"全區"};
    String jidus[] = new String[]{"2018年第3季度","2018年第4季度","2019年第1季度","2019年第2季度"};
    String[] yuedus = new String[]{"2018年07月","2018年08月","2018年09月","2018年10月","2018年11月","2018年12月","2019年01月","2019年02月","2019年03月","2019年04月","2019年05月","2019年06月"};
        String[] jds = new String[]{"萬壽路街道",
            "上地街道",
            "東升鎮",
            "中關村街道",
            "八里庄街道",
            "北下關街道",
            "北太平庄街道",
            "四季青鎮",
            "學院路街道",
            "曙光街道",
            "永定路街道",
            "海淀街道",
            "海淀鎮",
            "清華園街道",
            "清河街道",
            "溫泉鎮",
            "燕園街道",
            "甘家口街道",
            "田村路街道",
            "紫竹院街道",
            "羊坊店街道",
            "花園路街道",
            "蘇家坨鎮",
            "西三旗街道",
            "西北旺鎮",
            "青龍橋街道",
            "香山街道",
            "馬連窪街道"};
        
        for(int i=0;i<jds.length;i++){
             for (int j = 0; j < nds.length; j++) {
            String returnurl = "D:/word/封面/生成/街道(年度)/"+nds[j].replace("年", "")+jds[i]+"樓宇報告.docx"; // 結果文件
                final String templateurl = "D:/word/封面/年度報告封面.docx"; // 模板文件
                Map<String, String> textMap = new HashMap<String,String>();
                textMap.put("key1", jds[i]);
                textMap.put("key2", nds[j]);
                method(templateurl,returnurl,textMap);
        }
           /* for (int j = 0; j < jidus.length; j++) {
            String returnurl = "D:/word/封面/生成/街道(季度)/"+jds[i]+"樓宇"+jidus[j]+"報告.docx"; // 結果文件
                final String templateurl = "D:/word/封面/季度報告封面.docx"; // 模板文件
                Map<String, String> textMap = new HashMap<String,String>();
                textMap.put("key1", jds[i]);
                textMap.put("key2", jidus[j]);
                method(templateurl,returnurl,textMap);
        }
            for (int j = 0; j < yuedus.length; j++) {
            String returnurl = "D:/word/封面/生成/街道(月度)/"+jds[i]+yuedus[j]+"報告.docx"; // 結果文件
                final String templateurl = "D:/word/封面/月度報告封面.docx"; // 模板文件
                Map<String, String> textMap = new HashMap<String,String>();
                textMap.put("key1", jds[i]);
                textMap.put("key2", yuedus[j]);
                method(templateurl,returnurl,textMap);
        }*/
        }
      /*  for(int i=0;i<qq.length;i++){
            for (int j = 0; j < nds.length; j++) {
            String returnurl = "D:/word/封面/生成/全區(年度)/"+nds[j]+qq[i]+"樓宇年度報告.docx"; // 結果文件
                final String templateurl = "D:/word/封面/年度報告封面.docx"; // 模板文件
                Map<String, String> textMap = new HashMap<String,String>();
                textMap.put("key1", qq[i]);
                textMap.put("key2", nds[j]);
                method(templateurl,returnurl,textMap);
        }
            for (int j = 0; j < jidus.length; j++) {
            String returnurl = "D:/word/封面/生成/全區(季度)/"+qq[i]+"樓宇"+jidus[j]+"報告.docx"; // 結果文件
                final String templateurl = "D:/word/封面/季度報告封面.docx"; // 模板文件
                Map<String, String> textMap = new HashMap<String,String>();
                textMap.put("key1", qq[i]);
                textMap.put("key2", jidus[j]);
                method(templateurl,returnurl,textMap);
        }
            for (int j = 0; j < yuedus.length; j++) {
            String returnurl = "D:/word/封面/生成/全區(月度)/"+qq[i]+yuedus[j]+"報告.docx"; // 結果文件
                final String templateurl = "D:/word/封面/月度報告封面.docx"; // 模板文件
                Map<String, String> textMap = new HashMap<String,String>();
                textMap.put("key1", qq[i]);
                textMap.put("key2", yuedus[j]);
                method(templateurl,returnurl,textMap);
        }
        }*/

    
    }
    
    public static void method(String templateurl,String returnurl,Map<String, String> textMap) throws IOException, InvalidFormatException{
    
    InputStream is = new FileInputStream(new File(templateurl));
        XWPFDocument doc = new XWPFDocument(is);

        // 替換word模板數據
        replaceFm(doc,textMap);

        // 保存結果文件
        try {
            File file = new File(returnurl);
            if (file.exists()) {
            file.delete();
            }
            FileOutputStream fos = new FileOutputStream(returnurl);
            doc.write(fos);
            fos.close();
            doc.close();
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    
    }
    
    public static void replaceFm(XWPFDocument doc,Map<String, String> textMap)
        throws InvalidFormatException, IOException {
     doParagraphs(doc,textMap); // 處理段落文字數據,包括文字
     System.out.println("文本替換完成");
    }

    /**
     * @Description: 替換段落和表格中
     */
    public static void replaceAll(XWPFDocument doc,List<List<Map<String, String>>> listtable,List<List<Map<String, String>>> listchart,Map<String, String> textMap)
        throws InvalidFormatException, IOException {
     doParagraphs(doc,textMap); // 處理段落文字數據,包括文字
     System.out.println("文本替換完成");
     doTables(doc, listtable); //表格
     System.out.println("表格替換完成");
     doCharts(doc,listchart); // 處理圖表數據,柱狀圖、折線圖、餅圖啊之類的
    }
    
    public static void replaceFgs(XWPFDocument doc,List<List<Map<String, String>>> listtable,List<List<Map<String, String>>> listchart,Map<String, String> textMap)
        throws InvalidFormatException, IOException {
     doParagraphs(doc,textMap); // 處理段落文字數據,包括文字
     System.out.println("文本替換完成");
     doTables(doc, listtable); //表格
     System.out.println("表格替換完成");
     doChartsFgs(doc,listchart); // 處理圖表數據,柱狀圖、折線圖、餅圖啊之類的
    }

    /**
     * 處理table
     */
    public static void doTables(XWPFDocument doc,List<List<Map<String, String>>> list)
        throws InvalidFormatException, IOException {
    List<XWPFTable> tables = doc.getTables();
    for (int i = 0; i < tables.size(); i++) {
        XWPFTable table = tables.get(i);
        // 獲取表頭
        XWPFTableRow header = table.getRow(0);

        if (list.size() > i) {
        for (int h = 1; h <= list.get(i).size(); h++) {
            table.createRow();
        }
        List<XWPFTableRow> rows = table.getRows();
        /*for (int j = 0; j < list.get(i).size(); j++) {
            // XWPFTableRow row = table.getRow(i+1);
            Map<String, String> map = list.get(i).get(j);
            for (int k = 0; k < header.getTableCells().size(); k++) {
            String text = String.valueOf(map.get("key" + String.valueOf(k + 1)));
            if(text.endsWith(".0")){
                text=text.replace(".0", "");
            }
            if("null".equals(text)){
                text="";
            }
            
            rows.get(j + 1).getTableCells().get(k).setText(text);
            }
        }*/
        for (int j = 0; j < list.get(i).size(); j++) {
            // XWPFTableRow row = table.getRow(i+1);
            List<XWPFTableCell> cellList = rows.get(j + 1).getTableCells();
            Map<String, String> map = list.get(i).get(j);
            for (int k = 0; k < header.getTableCells().size(); k++) {
                String text = String.valueOf(map.get("key" + String.valueOf(k + 1)));
                if(text.endsWith(".0")){
                    text=text.replace(".0", "");
                }
                if("null".equals(text)){
                    text="";
                }
                XWPFTableCell cell = cellList.get(k);
                new PoiWordTools().setWordCellSelfStyle(cell, "微軟雅黑", "11", 0, "left", "m", "#000000", "#FFFFFF", 10, text);
            }
        }
        }

    }

    }

    /**
     * 處理段落文字
     * 
     * @param doc
     * @throws InvalidFormatException
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static void doParagraphs(XWPFDocument doc,
        Map<String, String> textMap) throws InvalidFormatException,
        IOException {
    /* textMap.put("fgs", "第一房管所"); */
    /** ----------------------------處理段落------------------------------------ **/
    List<XWPFParagraph> paragraphList = doc.getParagraphs();
    if (paragraphList != null && paragraphList.size() > 0) {
        for (XWPFParagraph paragraph : paragraphList) {
        List<XWPFRun> runs = paragraph.getRuns();
        for (XWPFRun run : runs) {
            String text = run.getText(0);
            if (text != null) {
            // 替換文本信息
            String key = text.replaceAll("\\{\\{", "").replaceAll("}}", "");
            if (!StringUtils.isEmpty(textMap.get(key))) {
                run.setText(textMap.get(key), 0);
            }
            }
        }
        }
    }
    }

    public static void doCharts(XWPFDocument doc,
        List<List<Map<String, String>>> list) throws FileNotFoundException {
    /** ----------------------------處理圖表------------------------------------ **/
    String[] params = {"title","數量(幢)","建築面積(萬平方米)"};
    String[] params2 = {"title","套數","建築面積(萬平方米)"};
    String[] params3 = {"title","建築面積(萬平方米)"};
    String[] params4 = {"title","數量"};
    String[] params5 = {"title","套數占比","建築面積占比"};
    
    doChartsOne(doc,list.get(0),0,params);
    System.out.println("圖1替換完成");
    doChartsTwo(doc,list.get(1),1,params3);
    System.out.println("圖2替換完成");
    doChartsOne(doc,list.get(2),2,params);
    System.out.println("圖3替換完成");
    doChartsOne(doc,list.get(3),3,params);
    System.out.println("圖4替換完成");
    doChartsOne(doc,list.get(4),4,params);
    System.out.println("圖5替換完成");
    doChartsOne(doc,list.get(5),5,params);
    System.out.println("圖6替換完成");
    doChartsOne(doc,list.get(6),6,params);
    System.out.println("圖7替換完成");
    doChartsOne(doc,list.get(7),7,params);
    System.out.println("圖8替換完成");
    doChartsOne(doc,list.get(8),8,params2);
    System.out.println("圖9替換完成");
    doChartsThree(doc,list.get(9),9,params5);
    System.out.println("圖10替換完成");
    doChartsOne(doc,list.get(10),10,params);
    System.out.println("圖11替換完成");
    doChartsOne(doc,list.get(11),11,params);
    System.out.println("圖12替換完成");
    doChartsOne(doc,list.get(12),12,params);
    System.out.println("圖13替換完成");
    doChartsTwo(doc,list.get(13),13,params4);
    System.out.println("圖14替換完成");
    }
    
    public static void doChartsFgs(XWPFDocument doc,
        List<List<Map<String, String>>> list) throws FileNotFoundException {
    /** ----------------------------處理圖表------------------------------------ **/
    String[] params = {"title","數量(幢)","建築面積(萬平方米)"};
    String[] params2 = {"title","套數","建築面積(萬平方米)"};
    String[] params3 = {"title","建築面積(萬平方米)"};
    String[] params4 = {"title","數量"};
    String[] params5 = {"title","數量(幢)","占街鎮比重"};
    String[] params6 = {"title","完成月度更新樓宇數量(幢)"};
    doChartsOne(doc,list.get(0),0,params);
    System.out.println("圖1替換完成");
    doChartsTwo(doc,list.get(1),1,params4);
    System.out.println("圖2替換完成");
    doChartsTwo(doc,list.get(2),2,params3);
    System.out.println("圖3替換完成");
    doChartsOne(doc,list.get(3),3,params);
    System.out.println("圖4替換完成");
    doChartsOne(doc,list.get(4),4,params5);
    System.out.println("圖5替換完成");
    doChartsOne(doc,list.get(5),5,params);
    System.out.println("圖6替換完成");
    doChartsOne(doc,list.get(6),6,params);
    System.out.println("圖7替換完成");
    doChartsThreeSingle(doc,list.get(7),7,params3);
    System.out.println("圖8替換完成");
    doChartsOne(doc,list.get(8),8,params);
    System.out.println("圖9替換完成");
    doChartsOne(doc,list.get(9),9,params5);
    System.out.println("圖10替換完成");
    doChartsOne(doc,list.get(10),10,params);
    System.out.println("圖11替換完成");
    doChartsOne(doc,list.get(11),11,params2);
    System.out.println("圖12替換完成");
    doChartsOne(doc,list.get(12),12,params2);
    System.out.println("圖13替換完成");
    doChartsOne(doc,list.get(13),13,params5);
    System.out.println("圖14替換完成");
    doChartsThreeSingle(doc,list.get(14),14,params3);
    System.out.println("圖15替換完成");
    doChartsThreeSingle(doc,list.get(15),15,params6);
    System.out.println("圖16替換完成");
    }

    /**
     * 處理圖表 
     * 柱圖折線圖組合圖
     * @param doc
     * @throws FileNotFoundException
     */
    public static void doChartsOne(XWPFDocument doc,List<Map<String, String>> listBasicData,int i,String[] params)
        throws FileNotFoundException {
    /** ----------------------------處理圖表------------------------------------ **/

    // 數據准備
    List<String> titleArr = new ArrayList<String>();// 標題
    titleArr.add(params[0]);
    titleArr.add(params[1]);
    titleArr.add(params[2]);

    List<String> fldNameArr = new ArrayList<String>();// 字段名
    fldNameArr.add("item1");
    fldNameArr.add("item2");
    fldNameArr.add("item3");

    // 數據集合
    List<Map<String, String>> listItemsByType = new ArrayList<Map<String, String>>();

    for (Map<String, String> map : listBasicData) {
        Map<String, String> base = new HashMap<String, String>();
        base.put("item1", map.get(params[0]));
        base.put("item2", String.valueOf(map.get(params[1])));
        base.put("item3", String.valueOf(map.get(params[2])));
        if(base.get("item2").equals("null")){
        base.put("item2", "0");
        }
        if(base.get("item3").equals("null")){
        base.put("item3", "0");
        }
        listItemsByType.add(base);
    }
    
    // 獲取word模板中的所有圖表元素,用數組存放
    List<POIXMLDocumentPart> chartsList = new ArrayList<POIXMLDocumentPart>();
    // 動態刷新圖表
    List<POIXMLDocumentPart> relations = doc.getRelations();
    for (POIXMLDocumentPart poixmlDocumentPart : relations) {
        if (poixmlDocumentPart instanceof XWPFChart) { // 如果是圖表元素
        chartsList.add(poixmlDocumentPart);
        }
    }

    // 下標5的圖表-組合圖(柱狀圖+折線圖)
    POIXMLDocumentPart poixmlDocumentPart = chartsList.get(i);
    new PoiWordTools().replaceCombinationCharts(poixmlDocumentPart,titleArr, fldNameArr, listItemsByType);
    
    }

    /**
     * 處理圖表 餅圖
     * 
     * @param doc
     * @throws FileNotFoundException
     */
    public static void doChartsTwo(XWPFDocument doc,List<Map<String, String>> listBasicData,int i,String[] params)
        throws FileNotFoundException {
    /** ----------------------------處理圖表------------------------------------ **/
    // 數據准備
    List<String> titleArr = new ArrayList<String>();// 標題
    titleArr.add(params[0]);
    titleArr.add(params[1]);
    List<String> fldNameArr = new ArrayList<String>();// 字段名
    fldNameArr.add("item1");
    fldNameArr.add("item2");

    // 數據集合
    List<Map<String, String>> listItemsByType = new ArrayList<Map<String, String>>();

    for (Map<String, String> map : listBasicData) {
        Map<String, String> base = new HashMap<String, String>();
        base.put("item1", map.get("title"));
        base.put("item2", String.valueOf(map.get("value")));
        if(base.get("item2").equals("null")){
        base.put("item2", "0");
        }
        listItemsByType.add(base);
    }

    // 獲取word模板中的所有圖表元素,用數組存放
    List<POIXMLDocumentPart> chartsList = new ArrayList<POIXMLDocumentPart>();
    // 動態刷新圖表
    List<POIXMLDocumentPart> relations = doc.getRelations();
    for (POIXMLDocumentPart poixmlDocumentPart : relations) {
        if (poixmlDocumentPart instanceof XWPFChart) { // 如果是圖表元素
        chartsList.add(poixmlDocumentPart);
        }
    }
    // 餅圖
    POIXMLDocumentPart poixmlDocumentPart4 = chartsList.get(i);
    new PoiWordTools().replacePieCharts(poixmlDocumentPart4, titleArr,
        fldNameArr, listItemsByType);
    }

    /**
     * 處理圖表 
     * 柱圖
     * @param doc
     * @throws FileNotFoundException
     */
    public static void doChartsThree(XWPFDocument doc,List<Map<String, String>> listBasicData,int i,String[] params)
        throws FileNotFoundException {
    /** ----------------------------處理圖表------------------------------------ **/
    // 數據准備
    List<String> titleArr = new ArrayList<String>();// 標題
    titleArr.add(params[0]);
    titleArr.add(params[1]);
    titleArr.add(params[2]);

    List<String> fldNameArr = new ArrayList<String>();// 字段名
    fldNameArr.add("item1");
    fldNameArr.add("item2");
    fldNameArr.add("item3");

    // 數據集合
    List<Map<String, String>> listItemsByType = new ArrayList<Map<String, String>>();

    for (Map<String, String> map : listBasicData) {
        Map<String, String> base = new HashMap<String, String>();
        base.put("item1", map.get(params[0]));
        base.put("item2", String.valueOf(map.get(params[1])));
        base.put("item3", String.valueOf(map.get(params[2])));
        listItemsByType.add(base);
        if(base.get("item2").equals("null")){
        base.put("item2", "0");
        }
        if(base.get("item3").equals("null")){
        base.put("item3", "0");
        }
    }
    // 獲取word模板中的所有圖表元素,用數組存放
    List<POIXMLDocumentPart> chartsList = new ArrayList<POIXMLDocumentPart>();
    // 動態刷新圖表
    List<POIXMLDocumentPart> relations = doc.getRelations();
    for (POIXMLDocumentPart poixmlDocumentPart : relations) {
        if (poixmlDocumentPart instanceof XWPFChart) { // 如果是圖表元素
        chartsList.add(poixmlDocumentPart);
        }
    }
    
    POIXMLDocumentPart poixmlDocumentPart = chartsList.get(i);
    new PoiWordTools().replaceBarCharts(poixmlDocumentPart, titleArr, fldNameArr, listItemsByType);
    }
    
    /**
     * 單柱圖
     * @param doc
     * @param listBasicData
     * @param i
     * @param params
     * @throws FileNotFoundException
     */
    public static void doChartsThreeSingle(XWPFDocument doc,List<Map<String, String>> listBasicData,int i,String[] params)
        throws FileNotFoundException {
    /** ----------------------------處理圖表------------------------------------ **/
    // 數據准備
    List<String> titleArr = new ArrayList<String>();// 標題
    titleArr.add(params[0]);
    titleArr.add(params[1]);

    List<String> fldNameArr = new ArrayList<String>();// 字段名
    fldNameArr.add("item1");
    fldNameArr.add("item2");

    // 數據集合
    List<Map<String, String>> listItemsByType = new ArrayList<Map<String, String>>();

    for (Map<String, String> map : listBasicData) {
        Map<String, String> base = new HashMap<String, String>();
        base.put("item1", map.get(params[0]));
        base.put("item2", String.valueOf(map.get(params[1])));
        listItemsByType.add(base);
        if(base.get("item2").equals("null")){
        base.put("item2", "0");
        }
    }
    // 獲取word模板中的所有圖表元素,用數組存放
    List<POIXMLDocumentPart> chartsList = new ArrayList<POIXMLDocumentPart>();
    // 動態刷新圖表
    List<POIXMLDocumentPart> relations = doc.getRelations();
    for (POIXMLDocumentPart poixmlDocumentPart : relations) {
        if (poixmlDocumentPart instanceof XWPFChart) { // 如果是圖表元素
        chartsList.add(poixmlDocumentPart);
        }
    }
    
    POIXMLDocumentPart poixmlDocumentPart = chartsList.get(i);
    new PoiWordTools().replaceBarCharts(poixmlDocumentPart, titleArr, fldNameArr, listItemsByType);
    }

}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM