一、需求說明
定期生成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結束--- } }
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); } }