java - Apache POI 打印线条形状问题

标签 java apache-poi

我需要你的帮助,我有一个代码(见下文),可以使用 Java 中的 Apache POI 在 Excel 的单元格中添加带有箭头的线条形状。看我的代码。但导出后,然后打开 Excel,对话框中的此消息会抛出“从/xl/drawings/drawing3.xml 部件绘图(绘图形状)”。请查看屏幕截图。

// create workbook
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet( "Node" );
CreationHelper helper = wb.getCreationHelper();
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();

//anchor from
//parent
anchor.setCol1( gParentCell.getColumnIndex() + 1 );
anchor.setRow1( gParentCell.getRowIndex() );

anchor.setDy1( Units.toEMU( 7.2 ) );

//anchor to
//child
anchor.setCol2( this.col );
anchor.setRow2( this.row );

anchor.setDy2( Units.toEMU( 7.2 ) );

XSSFSimpleShape shape = ((XSSFDrawing)drawing).createSimpleShape((XSSFClientAnchor)anchor);
shape.setShapeType( ShapeTypes.LINE );
shape.setLineWidth(1);
shape.setLineStyle(0);

// draw the arrow
CTShapeProperties shapeProperties = shape.getCTShape().getSpPr();

CTLineEndProperties lineEndProperties = org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties.Factory.newInstance();
lineEndProperties.setType(STLineEndType.TRIANGLE);

// print arrow
CTLineProperties lineProperties = shapeProperties.getLn();
lineProperties.setTailEnd(lineEndProperties);

Excel is trying to recover

the error

Output

最佳答案

在 anchor 中,col1 的索引始终需要低于 col2 的索引,并且 row1 的索引需要更低比 row2 之一。 anchor 中绘制的线始终从左上到右下。如果需要,您可以垂直翻转它们。

因此,例如,如果需要从 B14G4 绘制一条线,您可以创建一个 anchor B4:G14,然后绘制该线然后垂直翻转形状。

shape.getCTShape().getSpPr().getXfrm().setFlipV(true);

完整示例:

import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.ShapeTypes;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.drawingml.x2006.main.*;

import java.io.FileOutputStream;

class CreateExcelLineShapesArrows {

 static XSSFSimpleShape drawLine(XSSFCell fromCell, XSSFCell toCell) {
  XSSFWorkbook wb = fromCell.getSheet().getWorkbook();
  XSSFCreationHelper helper = wb.getCreationHelper();
  XSSFSheet sheet = fromCell.getSheet();
  XSSFDrawing drawing = sheet.createDrawingPatriarch();
  XSSFClientAnchor anchor = helper.createClientAnchor();

  int fromCol = Math.min(fromCell.getColumnIndex(), toCell.getColumnIndex());
  int toCol = Math.max(fromCell.getColumnIndex(), toCell.getColumnIndex());
  int fromRow = Math.min(fromCell.getRow().getRowNum(), toCell.getRow().getRowNum());
  int toRow = Math.max(fromCell.getRow().getRowNum(), toCell.getRow().getRowNum());

  anchor.setCol1(fromCol);
  anchor.setRow1(fromRow); // anchor starts top left of this cell
  anchor.setDy1(Units.toEMU(sheet.getRow(fromRow).getHeightInPoints()/2)); //plus 1/2 row height
  anchor.setCol2(toCol);
  anchor.setRow2(toRow);// anchor ends top left of this cell
  anchor.setDy2(Units.toEMU(sheet.getRow(toRow).getHeightInPoints()/2)); //plus 1/2 row height

  XSSFSimpleShape shape = drawing.createSimpleShape(anchor);
  shape.setShapeType(ShapeTypes.LINE);
  shape.setLineWidth(1);
  shape.setLineStyleColor(0, 0, 0);

  if (fromCell.getRow().getRowNum() > toCell.getRow().getRowNum()) { // if fromCell's row is below toCells's row, then flip vertically
   shape.getCTShape().getSpPr().getXfrm().setFlipV(true);
  }

  return shape;
 }

 static void setTailEndTriangle(XSSFSimpleShape shape) {
  CTShapeProperties shapeProperties = shape.getCTShape().getSpPr();
  CTLineProperties lineProperties = shapeProperties.getLn();
  CTLineEndProperties lineEndProperties = CTLineEndProperties.Factory.newInstance();
  lineEndProperties.setType(STLineEndType.TRIANGLE);
  //lineEndProperties.setLen(STLineEndLength.LG);
  //lineEndProperties.setW(STLineEndWidth.LG);
  lineProperties.setTailEnd(lineEndProperties);
 }

 static void setHeadEndTriangle(XSSFSimpleShape shape) {
  CTShapeProperties shapeProperties = shape.getCTShape().getSpPr();
  CTLineProperties lineProperties = shapeProperties.getLn();
  CTLineEndProperties lineEndProperties = CTLineEndProperties.Factory.newInstance();
  lineEndProperties.setType(STLineEndType.TRIANGLE);
  //lineEndProperties.setLen(STLineEndLength.LG);
  //lineEndProperties.setW(STLineEndWidth.LG);
  lineProperties.setHeadEnd(lineEndProperties);
 }

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

  XSSFWorkbook wb = new XSSFWorkbook();

  XSSFSheet sheet = wb.createSheet("Sheet1");

  XSSFCell cellG4 = sheet.createRow(3).createCell(6); cellG4.setCellValue("Test A");
  XSSFCell cellA14 = sheet.createRow(13).createCell(0); cellA14.setCellValue("Test");
  XSSFCell cellB14 = sheet.getRow(13).createCell(1);
  XSSFCell cellG23 = sheet.createRow(22).createCell(6); cellG23.setCellValue("Test B");

  XSSFSimpleShape shape = drawLine(cellB14, cellG23);
  setTailEndTriangle(shape);
  shape = drawLine(cellB14, cellG4);
  setTailEndTriangle(shape);

  FileOutputStream out = new FileOutputStream("CreateExcelLineShapesArrows.xlsx");
  wb.write(out);
  out.close();
  wb.close();

 }
}

结果:

enter image description here

关于java - Apache POI 打印线条形状问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59640436/

相关文章:

java - 为什么在尝试使用 Apache POI 打开 Excel 文件时出现异常 "IOException: ZIP entry size is too large"?

java - 以编程方式发送 Mule 消息(以前为 : Accessing mule http endpoint from java)

java - 如何使用 Jansi 库?

java - 如何在没有 Java 的情况下在纯 Kotlin 中实现接口(interface) null 与 throw 调度

java - 用Java从ZIP压缩包中提取UTF-16编码的文件

java - 使用可变参数传递参数对而不会遇到错误的模式

java - 是否可以在List中放入两个变量类型?

java - 无法使用 HSSF Java 删除 Excel 工作表

groovy - java.lang.LinkageError Groovy 2.4.14 Apache poi 3.17 jdk 1.8.0_92 http-builder 0.7.1

java - 如何获取 HSSFCell apache POI API 的 Excel 范围名称?