Apache POI - 在 Word 文件中编辑图表数据时,返回表单中定义的数据 [英] Apache POI - When editing chart data in a Word file, it returns to the data defined in the form

查看:19
本文介绍了Apache POI - 在 Word 文件中编辑图表数据时,返回表单中定义的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发了一个包含图表的 Word 函数.在 Word 文件中编辑图表数据时,返回到表单中定义的数据.

步骤如下:

  • 我编辑了 word(docx) xml 数据和工作簿.
  • 我打开microsoft office - 显示数据正常.
  • 我点击图表数据编辑功能 - 它返回原始数据.

库 - o​​oxml-schemas-1.3, poi-4.0.0-SNAPSHOT

public static void main(String[] args) 抛出异常 {//TODO 自动生成的方法存根String inFilePath = "../file/temp/TEMP_Chart_Simple.docx";String outFilePath = "../file/out/NEW_Chart_" + System.currentTimeMillis() + ".docx";映射<字符串,映射<字符串,字符串>>CHART_MAP_DATA = 新的 LinkedHashMap<>();映射<字符串,字符串>inData = new LinkedHashMap<>();inData.put("1", "8.3");inData.put("2", "7.3");CHART_MAP_DATA.put("temp", inData);路径 path = Paths.get(inFilePath);byte[] byteData = Files.readAllBytes(path);//从 byte[] 读取为 XWPFDocumentXWPFDocument 文档 = 新 XWPFDocument(new ByteArrayInputStream(byteData));XWPFChart xChart = null;CTChart ctChart = null;XSSFWorkbook wb = null;for (POIXMLDocumentPart 部分:document.getRelations()) {如果(XWPFChart 的部分实例){xChart = (XWPFChart) 部分;wb = xChart.getWorkbook();ctChart = xChart.getCTChart();if(getTitle(ctChart).equals("FIELD_CHART")) {休息;}}}CTPlotArea plotArea = ctChart.getPlotArea();列表arBarChart = plotArea.getBarChartList();列表arBarSer = arBarChart.get(0).getSerList();if(CHART_MAP_DATA != null && !CHART_MAP_DATA.isEmpty()) {设置<字符串>键 = CHART_MAP_DATA.keySet();迭代器<字符串>itKeys = keys.iterator();while(itKeys.hasNext()) {String inKey = itKeys.next();映射<字符串,字符串>barData = CHART_MAP_DATA.get(inKey);setBarChartData(ctChart, serCnt, inKey, barData);}}XSSFSheet 表 = wb.getSheetAt(0);sheet.getRow(1).getCell(1).setCellValue(8.3);sheet.getRow(2).getCell(1).setCellValue(7.3);FileOutputStream fos = new FileOutputStream(new File(outFilePath));文档写(fos);fos.close();文档.close();}public static void setBarChartData(CTChart ctChart, int serIdx, String series, Map data) {CTPlotArea plotArea = ctChart.getPlotArea();列表arBarChart = plotArea.getBarChartList();如果(arBarChart.size()> 0){列表arBarSer = arBarChart.get(0).getSerList();CTBarSer barSer = arBarSer.get(serIdx);CTSerTx serTx = barSer.getTx();CTStrRef strRef = serTx.getStrRef();CTStrData strData = strRef.getStrCache();列表arStrVal = strData.getPtList();for(int b=0; b<arStrVal.size(); b++) {arStrVal.get(b).setV(series);}CTAxDataSource 数据源 = barSer.getCat();CTStrRef dStrRef = dataSource.getStrRef();boolean isCatDataTypeStr = true;列表arDStrVal = 空;列表arDNumVal = 空;CTStrData dStrData = null;CTNumData dNumData = null;if(dStrRef != null) {dStrData = dStrRef.getStrCache();arDStrVal = dStrData.getPtList();dStrData.getPtCount().setVal(data.size());if(arDStrVal.size() > data.size()) {for(int i=arDStrVal.size(); i>data.size(); i--) {dStrData.removePt(i-1);}}isCatDataTypeStr = true;} 别的 {CTNumRef dNumRef = dataSource.getNumRef();dNumData = dNumRef.getNumCache();arDNumVal = dNumData.getPtList();dNumData.getPtCount().setVal(data.size());if(arDNumVal.size() > data.size()) {for(int i=arDNumVal.size(); i>data.size(); i--) {dNumData.removePt(i-1);}}isCatDataTypeStr = false;}CTNumDataSource numDataSource = barSer.getVal();CTNumRef numRef = numDataSource.getNumRef();CTNumData numData = numRef.getNumCache();列表arNumVal = numData.getPtList();numData.getPtCount().setVal(data.size());if(arNumVal.size() > data.size()) {for(int i=arNumVal.size(); i>data.size(); i--) {numData.removePt(i-1);}}设置<字符串>键 = data.keySet();迭代器<字符串>itKeys = keys.iterator();int valSize = 0;如果(isCatDataTypeStr){valSize = arDStrVal.size();} 别的 {valSize = arDNumVal.size();}int idx = 0;while(itKeys.hasNext()) {String stKey = itKeys.next();如果(valSize > idx){如果(isCatDataTypeStr){arDStrVal.get(idx).setV(stKey);} 别的 {arDNumVal.get(idx).setV(stKey);}} 别的 {如果(isCatDataTypeStr){CTStrVal val = dStrData.addNewPt();val.setIdx(idx);val.setV(stKey);} 别的 {CTNumVal val = dNumData.addNewPt();val.setIdx(idx);val.setV(stKey);}}if(arNumVal.size() > idx) {arNumVal.get(idx).setV(data.get(stKey));} 别的 {CTNumVal val = numData.addNewPt();val.setIdx(idx);val.setV(data.get(stKey));}idx++;}}}公共静态字符串getTitle(CTChart图表){CTTitle 标题 = chart.getTitle();如果(标题!= null){CTTx tx = title.getTx();CTTextBody tb = tx.getRich();返回 tb.getPArray(0).getRArray(0).getT();}返回 "";}

解决方案

Using apache poi 4.0.1 改变

代码:

import java.io.FileInputStream;导入 java.io.FileOutputStream;导入 org.apache.poi.xwpf.usermodel.*;导入 org.apache.poi.xddf.usermodel.chart.*;导入 org.apache.poi.xssf.usermodel.*;导入 org.apache.poi.ss.util.CellReference;导入 org.apache.poi.ss.util.CellRangeAddress;公共类 WordChangeChartData {public static void main(String[] args) 抛出异常 {String filePath = "TEMP_Chart_SimpleBar.docx";//有 2 个系列、3 个类别的模板图表String filePathNew = "New_Chart_Simple.docx";Object[][] data = new Object[][] {//2系列,3类{"", "male", "female"},//系列标题{"health", 123d, 234d},//类别 1{"amount", 345d, 123d},//类别 2{"size", 180d, 160d}//类别 3};XWPFDocument 文档 = new XWPFDocument(new FileInputStream(filePath));XWPFChart 图表 = document.getCharts().get(0);XSSFWorkbook chartDataWorkbook = chart.getWorkbook();String sheetName = chartDataWorkbook.getSheetName(0);XSSFSheet chartDataSheet = chartDataWorkbook.getSheet(sheetName);if (chart.getChartSeries().size() == 1) {//只有一个图表数据XDDFChartData chartData = chart.getChartSeries().get(0);if (chartData.getSeries().size() == 2) {//精确的两个系列int rMin = 1;INT rMax = 3;//设置新的类别数据(两个系列)XDDFCategoryDataSource 类别 = null;int c = 0;for (int r = rMin; r  0) {if (chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().size() > c)chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().get(c).setName(series1Title);}series1.setTitle(series1Title, new CellReference(sheetName, 0, c, true, true));//在图表中//设置新值XDDFNumericalDataSource值 = 空;for (int r = rMin; r  0) {if (chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().size() > c)chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().get(c).setName(series2Title);}series2.setTitle(series2Title, new CellReference(sheetName, 0, c, true, true));//在图表中//设置新值for (int r = rMin; r 

结果:

I have developed a Word function that includes a Chart. When editing chart data in a Word file, it returns to the data defined in the form.

Here are the steps:

  • I edit word(docx) xml data and workbook.
  • I open microsoft office - the data shown is normal.
  • I click Chart data edit function - it returns the original data.

library - ooxml-schemas-1.3, poi-4.0.0-SNAPSHOT

public static void main(String[] args) throws Exception {
    // TODO Auto-generated method stub

    String inFilePath = "../file/temp/TEMP_Chart_Simple.docx";
    String outFilePath = "../file/out/NEW_Chart_" + System.currentTimeMillis() + ".docx";

    Map<String, Map<String, String>> CHART_MAP_DATA = new LinkedHashMap<>();
    Map<String, String> inData = new LinkedHashMap<>();
    inData.put("1", "8.3");
    inData.put("2", "7.3");

    CHART_MAP_DATA.put("temp", inData);

    Path path = Paths.get(inFilePath);
    byte[] byteData = Files.readAllBytes(path);

    // read as XWPFDocument from byte[]
    XWPFDocument document = new XWPFDocument(new ByteArrayInputStream(byteData));

    XWPFChart xChart = null;
    CTChart ctChart = null;
    XSSFWorkbook wb = null;

    for (POIXMLDocumentPart part : document.getRelations()) {
        if (part instanceof XWPFChart) {
            xChart = (XWPFChart) part;
            wb = xChart.getWorkbook();
            ctChart = xChart.getCTChart();

            if(getTitle(ctChart).equals("FIELD_CHART")) {
                break;
            }
        }
    }

    CTPlotArea plotArea = ctChart.getPlotArea();

    List<CTBarChart> arBarChart = plotArea.getBarChartList();
    List<CTBarSer> arBarSer = arBarChart.get(0).getSerList();

    if(CHART_MAP_DATA != null && !CHART_MAP_DATA.isEmpty()) {
        Set<String> keys = CHART_MAP_DATA.keySet();
        Iterator<String> itKeys = keys.iterator();

        while(itKeys.hasNext()) {
            String inKey = itKeys.next();
            Map<String, String> barData = CHART_MAP_DATA.get(inKey);
            setBarChartData(ctChart, serCnt, inKey, barData);
        }
    }

    XSSFSheet sheet = wb.getSheetAt(0);
    sheet.getRow(1).getCell(1).setCellValue(8.3);
    sheet.getRow(2).getCell(1).setCellValue(7.3);

    FileOutputStream fos = new FileOutputStream(new File(outFilePath));
    document.write(fos);

    fos.close();
    document.close();
}

public static void setBarChartData(CTChart ctChart, int serIdx, String series, Map<String, String> data) {
    CTPlotArea plotArea = ctChart.getPlotArea();

    List<CTBarChart> arBarChart = plotArea.getBarChartList();

    if(arBarChart.size() > 0) {
        List<CTBarSer> arBarSer = arBarChart.get(0).getSerList();
        CTBarSer barSer = arBarSer.get(serIdx);    
        CTSerTx serTx = barSer.getTx();
        CTStrRef strRef = serTx.getStrRef();
        CTStrData strData = strRef.getStrCache();
        List<CTStrVal> arStrVal = strData.getPtList();
        for(int b=0; b<arStrVal.size(); b++) {
            arStrVal.get(b).setV(series);
        }

        CTAxDataSource dataSource = barSer.getCat();
        CTStrRef dStrRef = dataSource.getStrRef();

        boolean isCatDataTypeStr = true;
        List<CTStrVal> arDStrVal = null;
        List<CTNumVal> arDNumVal = null;
        CTStrData dStrData = null;
        CTNumData dNumData = null;

        if(dStrRef != null) {
            dStrData = dStrRef.getStrCache();
            arDStrVal = dStrData.getPtList();

            dStrData.getPtCount().setVal(data.size());
            if(arDStrVal.size() > data.size()) {
                for(int i=arDStrVal.size(); i>data.size(); i--) {
                    dStrData.removePt(i-1);
                }
            }

            isCatDataTypeStr = true;
        } else {
            CTNumRef dNumRef = dataSource.getNumRef();
            dNumData = dNumRef.getNumCache();
            arDNumVal = dNumData.getPtList();

            dNumData.getPtCount().setVal(data.size());
            if(arDNumVal.size() > data.size()) {
                for(int i=arDNumVal.size(); i>data.size(); i--) {
                    dNumData.removePt(i-1);
                }
            }

            isCatDataTypeStr = false;
        }

        CTNumDataSource numDataSource = barSer.getVal();
        CTNumRef numRef = numDataSource.getNumRef();
        CTNumData numData = numRef.getNumCache();
        List<CTNumVal> arNumVal = numData.getPtList();

        numData.getPtCount().setVal(data.size());
        if(arNumVal.size() > data.size()) {
            for(int i=arNumVal.size(); i>data.size(); i--) {
                numData.removePt(i-1);
            }
        }

        Set<String> keys = data.keySet();
        Iterator<String> itKeys = keys.iterator();

        int valSize = 0;
        if(isCatDataTypeStr) {
            valSize = arDStrVal.size();
        } else {
            valSize = arDNumVal.size();
        }

        int idx = 0;
        while(itKeys.hasNext()) {
            String stKey = itKeys.next();

            if(valSize > idx) {
                if(isCatDataTypeStr) {
                    arDStrVal.get(idx).setV(stKey);
                } else {
                    arDNumVal.get(idx).setV(stKey);
                }
            } else {
                if(isCatDataTypeStr) {
                    CTStrVal val = dStrData.addNewPt();
                    val.setIdx(idx);
                    val.setV(stKey);
                } else {
                    CTNumVal val = dNumData.addNewPt();
                    val.setIdx(idx);
                    val.setV(stKey);
                }
            }

            if(arNumVal.size() > idx) {
                arNumVal.get(idx).setV(data.get(stKey));
            } else {
                CTNumVal val = numData.addNewPt();
                val.setIdx(idx);
                val.setV(data.get(stKey));
            }

            idx++;
        }
    }
}

public static String getTitle(CTChart chart) {
    CTTitle title = chart.getTitle();
    if (title != null) {
        CTTx tx = title.getTx();
        CTTextBody tb = tx.getRich();

        return tb.getPArray(0).getRArray(0).getT();
    }

    return "";
}

解决方案

Using apache poi 4.0.1 changing XDDFChart data needs parallel updating all changes in underlying chart data workbook and the chart itself. The chart holds the cached data while the workbook holds the source data. But both is possible using the high level apache poiclasses. No access to underlying XML beans needed.

Example

Word template which has template chart having 2 series and 3 categories:

Code:

import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.CellRangeAddress;

public class WordChangeChartData {

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

  String filePath = "TEMP_Chart_SimpleBar.docx"; // has template chart having 2 series, 3 categories
  String filePathNew = "New_Chart_Simple.docx";

  Object[][] data = new Object[][] { // 2 series, 3 categories
   {"", "male", "female"}, // series titles
   {"health", 123d, 234d}, // category 1
   {"amount", 345d, 123d}, // category 2
   {"size", 180d, 160d} // category 3
  };

  XWPFDocument document = new XWPFDocument(new FileInputStream(filePath));

  XWPFChart chart = document.getCharts().get(0);
  XSSFWorkbook chartDataWorkbook = chart.getWorkbook();
  String sheetName = chartDataWorkbook.getSheetName(0);
  XSSFSheet chartDataSheet = chartDataWorkbook.getSheet(sheetName);

  if (chart.getChartSeries().size() == 1) { // only one chart data
   XDDFChartData chartData = chart.getChartSeries().get(0);
   if (chartData.getSeries().size() == 2) { // exact two series

    int rMin = 1;
    int rMax = 3;

    // set new category data (both series)
    XDDFCategoryDataSource category = null;
    int c = 0;
    for (int r = rMin; r < rMax+1; r++) {
     chartDataSheet.getRow(r).getCell(c).setCellValue((String)data[r][c]); // in sheet
    }
    category = XDDFDataSourcesFactory.fromStringCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); // in chart

    // series 1
    XDDFChartData.Series series1 = chartData.getSeries().get(0);
    c = 1;
    // set new title
    String series1Title = (String)data[0][c];
    chartDataSheet.getRow(0).getCell(c).setCellValue(series1Title); // in sheet
    if (chartDataSheet.getTables().size() > 0) {
     if (chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().size() > c)
      chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().get(c).setName(series1Title);
    }
    series1.setTitle(series1Title, new CellReference(sheetName, 0, c, true, true)); // in chart

    // set new values
    XDDFNumericalDataSource<Double> values = null;
    for (int r = rMin; r < rMax+1; r++) {
     chartDataSheet.getRow(r).getCell(c).setCellValue((Double)data[r][c]); // in sheet
    }
    values = XDDFDataSourcesFactory.fromNumericCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); 
    series1.replaceData(category, values);
    series1.plot(); //in chart

    // series 2
    XDDFChartData.Series series2 = chartData.getSeries().get(1);
    c = 2;
    // set new title
    String series2Title = (String)data[0][c];
    chartDataSheet.getRow(0).getCell(c).setCellValue(series2Title); // in sheet
    if (chartDataSheet.getTables().size() > 0) {
     if (chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().size() > c)
      chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().get(c).setName(series2Title);
    }
    series2.setTitle(series2Title, new CellReference(sheetName, 0, c, true, true)); // in chart

    // set new values
    for (int r = rMin; r < rMax+1; r++) {
     chartDataSheet.getRow(r).getCell(c).setCellValue((Double)data[r][c]); // in sheet
    }
    values = XDDFDataSourcesFactory.fromNumericCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); 
    series2.replaceData(category, values);
    series2.plot(); // in chart

   }
  }

  FileOutputStream out = new FileOutputStream(filePathNew); 
  document.write(out);
  out.close();
  document.close();
 }

}

Result:

这篇关于Apache POI - 在 Word 文件中编辑图表数据时,返回表单中定义的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆