Java使用POI导出word文档中的表格示例

Java导出word文档中表格

支持表格、饼图、折线、文字

public class PoiWordTools {
	public void start(String tempPath, String resultPath) {

        try (InputStream inputStream = this.getClass().getResourceAsStream(tempPath)) {

            assert inputStream != null;
            XWPFDocument doc = new XWPFDocument(inputStream);

            //表格
            List<List<String>> tableList = new ArrayList<List<String>>(){{
                add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
                add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
                add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
                add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
                add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
                add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
            }};
            this.drawWordTable(doc, 0, tableList);

            //饼图
            Map<String, Number> peiData = new HashMap<String, Number>(){{
                put("英语", 66);
                put("语文", 89);
                put("数学", 99);
                put("物理", 88);
                put("化学", 70);
                put("生物", 91);
                put("音乐", 83);
                put("美术", 60);
            }};
            this.drawPieChart(doc, 0, peiData, "标题");

            File file = new File(resultPath);
            if (file.exists()) {
                file.delete();
            }
            // 保存结果文件
            try (FileOutputStream fos = new FileOutputStream(resultPath)) {
                doc.write(fos);
            } catch (IOException e) {
                e.printStackTrace();
            }
            doc.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

	/**
     * 折线图Demo
     * @param doc
     * @throws IOException
     * @throws InvalidFormatException
     */
    public void doChartLine(XWPFDocument doc) throws IOException, InvalidFormatException {
        String[] series1 = {"测试折线1","测试折线2","测试折线3"};//每条线的名称

        String title1="测试折线图1";

        //y轴
        List<Number[]> value1 = new ArrayList<>();//每一条折现图,第一个表3条,需要和图中条数一样

        //第一张图的y轴
        Number[] n1={1,2,3,5};
        Number[] n2={4,2,1,4};
        Number[] n3={5.8,6.2,1,0.2};
        value1.add(n1);
        value1.add(n2);
        value1.add(n3);

        //x轴
        String[] x1={"1","2","3","4"};

        drawLineChart(doc, 0, series1, x1, value1, title1);
    }

	/**
     * word中插入表格数据行
     * @param doc 文档
     * @param chartNum 处理第几个表格
     * @param tableList 数据集合
     */
    public void drawWordTable(XWPFDocument doc, int chartNum, List<List<String>> tableList) {
        List<XWPFTable> tables = doc.getTables();

        XWPFTable  table = tables.get(chartNum);

        //创建行,根据需要插入的数据添加新行,不处理表头
        for (int i = 1; i <= tableList.size(); i++) {
            XWPFTableRow row = table.getRow(i);
            if (row == null) {
                table.createRow();
            }
        }
        //遍历表格插入数据
        int rows = tableList.size() + 1;
        for (int i = 1; i < rows; i++) {

            List<XWPFTableCell> cells = table.getRow(i).getTableCells();
            for (int j = 0; j < cells.size(); j++) {
                XWPFTableCell cell = cells.get(j);
                cell.setText(tableList.get(i - 1).get(j));
                //表格样式一致-->没有此段表格会默认左对齐
                //有此段会使表格格式一致
                CTTc cttc = cell.getCTTc();
                CTTcPr ctPr = cttc.addNewTcPr();
                ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
                cttc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
            }
        }
    }

	/**
     * 饼图的生成
     * @param doc 文档
     * @param chartNum 处理第几个图
     * @param KyeData 数据 <系列名, 数据>
     * @param titleText 标题
     * @throws IOException 异常
     * @throws InvalidFormatException 异常
     */
    public void drawPieChart(XWPFDocument doc, int chartNum, Map<String, Number> KyeData, String titleText) throws IOException, InvalidFormatException {

        XWPFChart chart = doc.getCharts().get(chartNum);

        XSSFWorkbook workbook = chart.getWorkbook();
        XSSFSheet sheet = workbook.getSheetAt(0);

        int i = 1;
        for (Map.Entry<String, Number> item : KyeData.entrySet()) {
            XSSFRow row = sheet.createRow(i++);
            row.createCell(0).setCellValue(item.getKey());
            row.createCell(1).setCellValue(item.getValue().doubleValue());
        }


        XDDFChartData chartData2 = chart.getChartSeries().get(0);
        XDDFChartData.Series s2 = chartData2.getSeries().get(0);
        XDDFDataSource<String> cat2 = XDDFDataSourcesFactory.fromStringCellRange(sheet,
                new CellRangeAddress(1, KyeData.size(), 0, 0));
        XDDFNumericalDataSource<Double> val2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
                new CellRangeAddress(1,KyeData.size(),1,1));
        s2.replaceData(cat2,val2);
        chart.setTitleText(titleText);
        chart.plot(chartData2);
    }
	
	/**
     * 折线图的生成
     * @param doc 文档
     * @param chartNum 处理第几个图
     * @param series 折线名称
     * @param categories x轴数据
     * @param values y轴数据
     * @param chartTitle 图表的标题
     */
    private void drawLineChart(XWPFDocument doc, int chartNum, String[] series, String[] categories, List<Number[]> values, String chartTitle) {

        //获取第1个图表
        XWPFChart chart = doc.getCharts().get(chartNum);

        List<XDDFChartData> data = chart.getChartSeries();

        //这里一般获取第一个,我们这里是折线图就是XDDFLineChartData
        XDDFLineChartData line = (XDDFLineChartData) data.get(0);

        int numOfPoints = categories.length;

        String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));

        XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
        for (int i = 0; i < values.size(); i++) {
            String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, i + 1, i + 1));
            Number[] value = values.get(i);
            XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(value, valuesDataRange, i + 1);
            //图表中的系列
            XDDFChartData.Series ser;
            ser = line.getSeries().get(i);
            ser.replaceData(categoriesData, valuesData);
            //修改系列标题
            CellReference cellReference = chart.setSheetTitle(series[i], 1);
            ser.setTitle(series[i], cellReference);
        }

        chart.plot(line);
        //折线图标题
        chart.setTitleText(chartTitle);
        chart.setTitleOverlay(false);
    }
	
	/**
     * 替换word文档中的文字
     * @param doc 文档
     * @param dataMap 数据集合 <模板中的key, 要替换的内容>
     */
    public void drawString(XWPFDocument doc, Map<String, String> dataMap) {

        //获取word文档 每一段(词)的迭代器
        Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
        while(iterator.hasNext()){ //遍历迭代器 获取非表格中的每一个词对规定好的${}格式进行匹配
            XWPFParagraph paragraph = iterator.next();
            replaceCode(paragraph, dataMap);
        }

        //获取表格的迭代器
        Iterator<XWPFTable> itTable = doc.getTablesIterator();
        while(itTable.hasNext()){ //遍历迭代器以获取每个word中的表格
            XWPFTable table = itTable.next();     //表格对象
            int rcount = table.getNumberOfRows(); //获取表格的行总数
            for(int i = 0;i < rcount;i++){
                XWPFTableRow row = table.getRow(i); //读取表格中的每一行
                List<XWPFTableCell> cells = row.getTableCells(); //获取一行中的所有单元格
                for(XWPFTableCell cell : cells){    //遍历单元格
                    //单元格中有段落,要做段落处理
                    List<XWPFParagraph> paragraphs = cell.getParagraphs();  //获取单元格中的每一个单词 以进行匹配用来替换的数据Map集合
                    for(XWPFParagraph paragraph : paragraphs){
                        this.replaceCode(paragraph, dataMap);
                    }
                }
            }
        }

    }

	/**
     * 替换方法
     * @param paragraph
     * @param contentMap
     */
    private void replaceCode(XWPFParagraph paragraph,Map<String,String> contentMap){

        //获取一个词的操作对象 runs
        List<XWPFRun> runs = paragraph.getRuns();
        for(XWPFRun run:runs){

            //通过操作对象runs获取该词中的文本
            String oneParaString = run.getText(run.getTextPosition());

            //如果是空字符串或者该词中不包括"$"符号则跳过本次循环
            if(StrUtil.isBlank(oneParaString) || !oneParaString.contains("$")){
                continue;
            }

            //该词中存在"$",将文本数据与替换的Map数据进行匹配,例(该词为${username},那么将替换为Ychiha)
            for(Map.Entry<String,String> entry : contentMap.entrySet()){
                oneParaString = oneParaString.replace("${" + entry.getKey() + "}", entry.getValue());
            }
            //操作对象替换数据
            run.setText(oneParaString,0);

        }
    }

}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值