0

我需要你的帮助,我有一个代码(见下文),它使用 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 正在尝试恢复

错误

输出

4

2 回答 2

1

在一个锚点中, 的索引col1总是需要低于 的col2并且 的索引row1需要低于 的row2。锚点中的绘制线总是从左上角到右下角。如果需要,您可以垂直翻转它们。

因此,如果需要从B14to绘制一条线G4,您可以创建一个 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();

 }
}

结果:

在此处输入图像描述

于 2020-01-08T08:58:21.387 回答
0

我也想分享一下我刚刚学到的东西,

这是正确的 shape.getCTShape().getSpPr().getXfrm().setFlipV(true);

但你也可以使用 ShapeTypes.LINE_INV;

于 2020-01-08T09:44:36.333 回答