java - 如何通过Java POI在excel中移动图表的位置

标签 java excel charts apache-poi

我想通过 java POI 在 excel 中添加行,我尝试使用 shiftRows() 函数和 createRow() 函数

enter image description here
这两个函数都可以在 excel 中添加行,但图表下方的位置保持不变

我也喜欢移动(下移)图表的位置

我用的是poi 3.9版本

任何人都可以给我建议或想法来移动该图表图像的位置

事实上,图表的数据范围也没有改变。我不仅需要移动图表的位置,还需要增加图表的数据范围

谢谢!!

enter image description here

最佳答案

确定图表位置的绘图 anchor 的移动是可能的。 void insertRowsShiftShapes(Sheet sheet, int startRow, int n) 方法对所有受行插入过程影响的绘图 anchor 执行此操作。

如前所述,更正受插入工作表中的行影响的图表数据范围很复杂。它没有经过很好的测试,还没有准备好。但我会将其作为工作草案提供。我希望它是进一步编程的有用起点。

要运行代码,需要 ooxml-schemas-1.3.jar,如 apache poi FAQ 中所述

对我来说 ooxml-schema 对象文档的一个很好的资源是 grepcode

示例:CTTwoCellAnchor , CTPieChart , CTPieSer

import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

import java.io.*;

import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieSer;

import java.util.List;

class InsertRowsAboveChart {

 //a method for shift rows and shift all anchors in drawing below the shifted rows
 private static void insertRowsShiftShapes(Sheet sheet, int startRow, int n) {
  java.util.List<CTTwoCellAnchor> drawingAnchors = ((XSSFDrawing)sheet.getDrawingPatriarch()).getCTDrawing().getTwoCellAnchorList();
  for (CTTwoCellAnchor drawingAnchor : drawingAnchors) {
   int fromRow = drawingAnchor.getFrom().getRow();
   int toRow = drawingAnchor.getTo().getRow();
   if (fromRow >= startRow) {
    drawingAnchor.getFrom().setRow(fromRow + n);
    drawingAnchor.getTo().setRow(toRow + n);
   }
  }
  sheet.shiftRows(startRow, sheet.getLastRowNum(), n);
  correctDataRangesOfCharts(sheet, startRow, n);
 }

 //a method for correcting data ranges for charts which are affected of the shifted rows
 //!!working draft, not ready yet!!
 private static void correctDataRangesOfCharts(Sheet sheet, int startRow, int n) {
  java.util.List<XSSFChart> charts = ((XSSFDrawing)sheet.getDrawingPatriarch()).getCharts();
  for (XSSFChart chart : charts) {

   //pie charts
   java.util.List<CTPieChart> piecharts = chart.getCTChart().getPlotArea().getPieChartList();
   for (CTPieChart piechart : piecharts) {
    java.util.List<CTPieSer> pieseries = piechart.getSerList();
    for (CTPieSer pieserie : pieseries) {
     boolean strRefchanged = false;
     if (pieserie.getCat().isSetMultiLvlStrRef()) {
      String strRef = pieserie.getCat().getMultiLvlStrRef().getF();
      //todo: this only corrects the end row of the ranges, should also correct start row if affected
      int strRefEndRow = Integer.parseInt(strRef.substring(strRef.lastIndexOf('$') + 1));
      if (strRefEndRow >= startRow) {
       strRef = strRef.substring(0, strRef.lastIndexOf('$') +1) + (strRefEndRow + n);    
       pieserie.getCat().getMultiLvlStrRef().setF(strRef);
       strRefchanged = true;
      }
     } else if (pieserie.getCat().isSetStrRef()) {
      String strRef = pieserie.getCat().getStrRef().getF();
      int strRefEndRow = Integer.parseInt(strRef.substring(strRef.lastIndexOf('$') + 1));
      if (strRefEndRow >= startRow) {
       strRef = strRef.substring(0, strRef.lastIndexOf('$') +1) + (strRefEndRow + n);    
       pieserie.getCat().getStrRef().setF(strRef);
       strRefchanged = true;
      }
     }
     if (strRefchanged) {
      String numRef = pieserie.getVal().getNumRef().getF();
      int numRefEndRow = Integer.parseInt(numRef.substring(numRef.lastIndexOf('$') + 1));
      if (numRefEndRow >= startRow) {
       numRef = numRef.substring(0, numRef.lastIndexOf('$') +1) + (numRefEndRow + n);    
       pieserie.getVal().getNumRef().setF(numRef);
      }
     }
    }
   }
   //pie charts end

  }
 }

 public static void main(String[] args) {
  try {

   InputStream inp = new FileInputStream("Workbook.xlsx");
   Workbook wb = WorkbookFactory.create(inp);

   Sheet sheet = wb.getSheetAt(0);

   //sheet.shiftRows(3, 5, 4);
   insertRowsShiftShapes(sheet, 2, 4);

   FileOutputStream fileOut = new FileOutputStream("Workbook.xlsx");
   wb.write(fileOut);
   wb.close();

  } catch (InvalidFormatException ifex) {
  } catch (FileNotFoundException fnfex) {
  } catch (IOException ioex) {
  }
 }
}

关于java - 如何通过Java POI在excel中移动图表的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38824829/

相关文章:

c# - 使用枚举(构建列表)

java - 从字符串数组的 ArrayList 中删除字符串的可能逻辑?

vba - 如果过滤器中没有值,则退出 sub

Excel图表: Ordering by values (automatically)

javascript - 向空人力车图表添加数据

java - 为什么 JMX 报告的 JVM 堆使用最大值会随时间变化?

java - Spring/Hibernate 同一个实体不同的数据库结构

excel - 如何在Excel中使用自引用进行条件格式化

perl - 如何通过 Excel 中的 ActiveX 控件运行 Perl 脚本?

php - mysql图表上个月每小时的平均订单数