POI填充word模板内容(文本、表格、图表)
1,pom引进poi组件(poi官网指出poi4.x.x版本抛弃了jdk1.7之前的版本,所以适应此版本需要将jdk升级)
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.0</version> </dependency>
2,word模板(template.docx)
3,实例化操作对象(XWPFDocument)
File tpl = new File("template.docx"); if(tpl.exists()){//模板文件存在 //读取模板文件 FileInputStream is = new FileInputStream(tpl); XWPFDocument xwpfDocument = new XWPFDocument(is); //使用xwpfDocument对象操作word文档 //。。。。。。。。。。。。。 }
4,对文本操作(doParagraph)
/** * @Method doParagraph * @Description 替换段落内容 (格式有要求:{字段} 为三个文本对象,找以'{'开始 '}'结尾 中间匹配的字段替换值) * @param dataMap(数据源) * @Return void * @Exception */ public void doParagraph(Map<String, Object> dataMap) throws InvalidFormatException, IOException { if (dataMap != null && dataMap.size() > 0) { List<XWPFParagraph> paragraphs = xwpfDocument.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { int leftIndex = -1;//'{'的位置索引 int rightIndex = -1;//'}'的位置索引 List<XWPFRun> runs = paragraph.getRuns(); int runIndex=0;//当前位置游标 for (XWPFRun run : runs) { String text = run.getText(0); if (text != null) { if (text.contains("{")) { leftIndex = runIndex; } if (text.contains("}")) { rightIndex = runIndex; } if(leftIndex>-1 && leftIndex <= rightIndex){ //遍历{}之间的文本 for(int i=leftIndex;i<=rightIndex;i++){ XWPFRun thisrun=runs.get(i); Object value = dataMap.get(thisrun.getText(0)); if (value != null) { thisrun.setText(value.toString(), 0); } } leftIndex = -1; rightIndex = -1; } } runIndex++; } } } }
5,对表格操作(doTable)
/** * @Method doTable * @Description 替换表格内容 * @param index(表格索引:第几个表格),dataMap(数据源) * @Return void * @Exception */ public void doTable(int index,List<Map<String, Object>> dataMap) throws InvalidFormatException, IOException { XWPFTable table = xwpfDocument.getTables().get(index); if (dataMap != null && dataMap.size() > 0) { List<XWPFTableRow> rows = table.getRows(); int rowIndex = 0;//寻找字段绑定行索引 String[] fields = null;////字段绑定行字段顺序(a,b,c) for (XWPFTableRow row : rows) { List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) { String key = cell.getText() .replaceAll("\\{", "") .replaceAll("}", ""); if (dataMap.get(0).get(key) != null) {//找到匹配 fields = new String[cells.size()]; break; } } if (fields != null && fields.length>0) {//找到,并获取字段 for(int i=0;i<fields.length;i++){ fields[i] = cells.get(i) .getText() .replaceAll("\\{", "") .replaceAll("}", ""); } break; }else { rowIndex++; } } if (rowIndex >= 0 && fields != null) { //从字段绑定行开始插入 for (Map<String, Object> rowdata : dataMap) { XWPFTableRow row = null; try { row = rows.get(rowIndex); } catch (Exception e) { row = table.createRow(); } if(row != null) { List<XWPFTableCell> cells = row.getTableCells(); int cellIndex = 0; for (XWPFTableCell cell : cells) { cell.removeParagraph(0); XWPFParagraph newPara=cell.addParagraph(); XWPFRun run=newPara.createRun(); Object value = rowdata.get(fields[cellIndex]); if(value != null){ run.setText(value.toString()); } cellIndex++; } } rowIndex++; } } } }
6,图表操作(doChart)
/** * @Method doChart * @Description 替换图表内容 * @param index(图表索引),categoryField 分类轴字段,seriesField 系列轴字段,dataMap(数据源) * @Return void * @Exception */ public void doChart(int index, String categoryField,//{"a"} String[] seriesField, //{"b","c"} List<Map<String, Object>> dataMap) throws InvalidFormatException, IOException { List<XWPFChart> charts= xwpfDocument.getCharts(); for (XWPFChart chart : charts) { //根据图表索引 String partname = chart.getPackagePart().getPartName().getName(); if(partname.contains("chart"+(index+1)+".xml")){ String[] categories = new String[dataMap.size()]; Number[][] seriesvalues = new Number[seriesField.length][dataMap.size()]; int dataIndex = 0; for (Map<String, Object> rowdata : dataMap) { categories[dataIndex] = rowdata.get(categoryField).toString(); int serieIndex = 0; for(String field:seriesField){ Object value = rowdata.get(field); if(value != null){ seriesvalues[serieIndex][dataIndex] = (Number) (value); } serieIndex++; } dataIndex++; } XDDFChartData chartData = chart.getChartSeries().get(0);//目前只做1个chartData情况 String categoryDataRange = chart.formatRange(new CellRangeAddress(1, categories.length, 0, 0)); XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0); List<XDDFChartData.Series> series = chartData.getSeries(); int serieIndex = 0; for (XDDFChartData.Series serie:series){ String valuesDataRange = chart.formatRange(new CellRangeAddress(1, categories.length, serieIndex + 1, serieIndex + 1)); XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(seriesvalues[serieIndex], valuesDataRange, serieIndex + 1); //赋值 serie.replaceData(categoriesData,valuesData); serie.plot(); serieIndex++; } } } }