先看效果图:方法都是一样的,所以数据只做了前两组
第一步需要准备模版:
新建一个word插入图表,选择想要的图表。
编辑图表:营业额表示数字,季度表示文字。其他的样式编辑可根据自己的需求更改,这里略过
代码如下:
依赖
<dependencies> <!--poi--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>jfree</groupId> <artifactId>jcommon</artifactId> <version>1.0.16</version> </dependency> <!-- https://mvnrepository.com/artifact/jfree/jfreechart --> <dependency> <groupId>jfree</groupId> <artifactId>jfreechart</artifactId> <version>1.0.13</version> </dependency> </dependencies>d
代码:
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; 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.xddf.usermodel.chart.*; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xwpf.usermodel.XWPFChart; import org.apache.poi.xwpf.usermodel.XWPFDocument; import java.io.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class PieChart { public static void main(String[] args) throws Exception { // 1、创建word文档对象 String filePath = "D:\\words\\cakeshapeword.docx"; String outputUrl = "D:\\output\\cakeshapeword.docx"; List<Map<String, Object>> chartsList = new ArrayList<>(); List<String> keys = new ArrayList<>(); keys.add("一月"); keys.add("二月"); keys.add("三月"); keys.add("四月"); keys.add("五月"); List<Integer> values = new ArrayList<>(); values.add(100); values.add(150); values.add(130); values.add(190); values.add(200); chartsList = putMsgToMap(keys,values); createWord(filePath,outputUrl,chartsList); } public static void createWord(String filePath, String outputUrl, List<Map<String, Object>> chartsList) throws IOException, InvalidFormatException { InputStream is = new FileInputStream(filePath); XWPFDocument doc = new XWPFDocument(is); List<XWPFChart> charts = doc.getCharts(); // 获取第一个图 XWPFChart chart0 = charts.get(0); Workbook wordWb = chart0.getWorkbook(); Sheet wordSheet0 = wordWb.getSheetAt(0); // 循环数据 赋值 wordSheet0 = extracted(chartsList, wordSheet0); chart0 = extracted(chart0, chartsList, (XSSFSheet) wordSheet0); // 获取第二个图,没有做封装,需要的自己处理 XWPFChart chart1 = charts.get(1); Workbook wordWb1 = chart1.getWorkbook(); Sheet wordSheet1 = wordWb1.getSheetAt(0); List<String> keys = new ArrayList<>(); keys.add("云大怒"); keys.add("吕布"); keys.add("赵云"); keys.add("典韦"); keys.add("关羽"); List<Integer> values = new ArrayList<>(); values.add(100); values.add(98); values.add(96); values.add(94); values.add(93); List<Map<String, Object>> chartsList1 = putMsgToMap(keys,values); wordSheet1 = extracted(chartsList1, wordSheet1); chart1 = extracted(chart1, chartsList1, (XSSFSheet) wordSheet1); // 获取第N个图 此处略过 File outputFile = new File(outputUrl); try (OutputStream outputStream = new FileOutputStream(outputFile)) { doc.write(outputStream); } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } /** * 饼状图循环赋值 * @param chartsList1 数据 * @param wordSheet1 sheet页 * @return */ public static Sheet extracted(List<Map<String, Object>> chartsList1, Sheet wordSheet1) { for (int i = 0; i < chartsList1.size(); i++){ Row row = wordSheet1.getRow(i+1); if(null != row){ row = wordSheet1.createRow(i+1); } Map<String,Object> dataMap = chartsList1.get(i); for (int y =0;y<dataMap.size();y++){ Cell cell; if(row.getCell(y) == null){ cell = row.createCell(y); }else{ cell = row.getCell(y); } String key = y == 0 ?"name":"value"; if(key.equals("name")){ cell.setCellValue(dataMap.get(key)+""); }else { cell.setCellValue((int)dataMap.get(key)); } } } return wordSheet1; } /** * 刷新饼图数据 * @param chart0 * @param chartsList * @param wordSheet * @return */ public static XWPFChart extracted(XWPFChart chart0, List<Map<String, Object>> chartsList, XSSFSheet wordSheet) { // 刷新图表缓存 XDDFChartData chartData = chart0.getChartSeries().get(0); XDDFChartData.Series series = chartData.getSeries().get(0); CellRangeAddress nameRangeAddress = new CellRangeAddress(1, chartsList.size(),0,0); CellRangeAddress valueRangeAddress = new CellRangeAddress(1, chartsList.size(),1,1); XDDFDataSource lineName = XDDFDataSourcesFactory.fromStringCellRange(wordSheet,nameRangeAddress); XDDFNumericalDataSource lineVal = XDDFDataSourcesFactory.fromNumericCellRange(wordSheet,valueRangeAddress); //替换原有的数据 series.replaceData(lineName,lineVal); chart0.plot(chartData); return chart0; } /** * 把数值放进 map 里 * @param name * @param values * @return */ public static List<Map<String,Object>> putMsgToMap(List<String> name,List<Integer> values ){ List<Map<String,Object>> chartsList = new ArrayList<>(); for (int i = 0; i < name.size(); i++) { Map<String,Object> map = new HashMap(); map.put("name",name.get(i)); map.put("value",values.get(i)); chartsList.add(map); } return chartsList; } }
注意:如果有多个图表在一起,那么排序的顺序不是你图表在word里的顺序,word有自己的排序,条形第一,面积第二。其他的自行测试看看。我用的是正版微软word。其他的word我没测试过。