【问题标题】:Multiple connectors between Apache POI shapesApache POI 形状之间的多个连接器
【发布时间】:2021-03-04 17:30:12
【问题描述】:

最近我正在使用带有 Spring Boot 的 Apache POI,我遇到了一个问题。我想表示实体之间的数据库连接,但在可视化多个连接时遇到了问题。
所以我的基本问题是分离连接。

这是我的起点:1

你看不到,但这两个矩形之间有多个连接,但由于起点和终点相同,它们是相互覆盖的。

生成的 XML 代码如下:

<p:cxnSp>
   <p:nvCxnSpPr>
       <p:cNvPr name="Connector 7" id="7" />
       <p:cNvCxnSpPr>
           <a:stCxn id="2" idx="3" />
           <a:endCxn id="3" idx="1" />
       </p:cNvCxnSpPr>
       <p:nvPr />
   </p:nvCxnSpPr>
   <p:spPr>
       <a:xfrm flipV="1">
           <a:off y="2199409" x="2616200" />
           <a:ext cy="1318491" cx="2413000" />
       </a:xfrm>
       <a:prstGeom prst="curvedConnector3">
           <a:avLst />
       </a:prstGeom>
       <a:ln w="9525">
           <a:solidFill>
               <a:srgbClr val="000000" />
           </a:solidFill>
       </a:ln>
   </p:spPr>
</p:cxnSp> 

所以我想要做的是将弯曲连接器的中点设置为不同的值,就像在这张图片中一样(我在示例中手动执行此操作): 2

我尝试将其他一些 GeomGuide 元素添加到连接器,但结果是一个不稳定的 pptx 文件:

<a:prstGeom prst="curvedConnector3">
    <a:avLst>
        <a:gd name="adj1" fmla="val 57365" />
    </a:avLst>
</a:prstGeom>

为此相关的java代码sn-p:

XSLFConnectorShape connector1 = slide.createConnector();
CTNonVisualConnectorProperties cx = ctConnector.getNvCxnSpPr().getCNvCxnSpPr();
        CTConnection start = cx.addNewStCxn();
        start.setId(shapeIdStart);
        start.setIdx(rel.getStartSide());

        CTConnection end = cx.addNewEndCxn();
        end.setId(shapeIdEnd);
        end.setIdx(rel.getEndSide());


         CTGeomGuideList ctGeomGuideList = ctConnector.getSpPr().getPrstGeom().getAvLst();
         CTGeomGuide ctGeomGuide = ctGeomGuideList.addNewGd();
         ctGeomGuide.setName("adj");
         ctGeomGuide.setFmla("val 45000");

【问题讨论】:

  • 未提供Minimal, Reproducible Example,因此无法回答。但我想一定是ctGeomGuide.setName("adj1");
  • 谢谢,我没有写这个,但我尝试了这个参数名称,但仍然没有工作。我将更新我的答案以使其可重现。
  • edit您的问题:提供完整的代码(格式正确)并澄清您当前的问题。我们需要看看你的目标缺少什么。意味着set the curved connectors midpoint in a different values 您需要两条曲线,它们都具有与 2 个矩形的相同连接点,但 具有不同的 "curvatures" = 一条是正的并向上弯曲,另一条是负的并向下弯曲。这个问题不是和fmla属性设置的formula有关吗?

标签: java spring-boot apache-poi powerpoint ecma


【解决方案1】:

您提供的代码 sn-p 不完整。因此,尚不清楚这是否是唯一的问题。但是ctGeomGuide.setName("adj"); 无论如何都是错误的。调整手柄已编号,并且没有仅称为adj 的调整手柄。必须是ctGeomGuide.setName("adj1");

以下代码是 Minimal, Reproducible Example,它可以工作并创建您想要的结果。

import java.io.FileOutputStream;

import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.sl.usermodel.*;
import org.openxmlformats.schemas.presentationml.x2006.main.*;
import org.openxmlformats.schemas.drawingml.x2006.main.*;

import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.awt.Color;

public class CreatePPTXConnectorShapes {
    
 private static XSLFConnectorShape createConnector(XSLFSlide slide, XSLFAutoShape shape1, XSLFAutoShape shape2) {
  XSLFConnectorShape connector = slide.createConnector();
  connector.setShapeType(ShapeType.CURVED_CONNECTOR_3);
  connector.setAnchor(new Rectangle2D.Double( //connector is diagonal in a rectangle
   shape1.getAnchor().getMaxX(), // top left x of that rectangle is x position of right edge of shape1
   shape2.getAnchor().getCenterY(), // top left y of that rectangle is center y of shape2 as shape2 is above shape1
   shape2.getAnchor().getX()-shape1.getAnchor().getMaxX(), // width of that rectanle is x of shape2 minus x position of right edge of shape1 as shape2 is right of shape1
   shape1.getAnchor().getCenterY()-shape2.getAnchor().getCenterY() // height of that rectanle is center y of shape1 minus center y of shape2 as shape2 is above shape1
   ));
  connector.setFlipVertical(true); // the rectangle needs to be flipped vertically as the connector shall be diagonal from bottom left to top right

  CTConnector ctConnector = (CTConnector)connector.getXmlObject();
  CTNonVisualConnectorProperties cx = ctConnector.getNvCxnSpPr().getCNvCxnSpPr();
  CTConnection start = cx.addNewStCxn();
  start.setId(shape1.getShapeId());
  start.setIdx(3); // connecting point 3 is center of right edge
  CTConnection end = cx.addNewEndCxn();
  end.setId(shape2.getShapeId());
  end.setIdx(1); // connecting point 1 is center of left edge
  return connector;  
 }

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

  XMLSlideShow slideShow = new XMLSlideShow();

  XSLFSlide slide = slideShow.createSlide();

  XSLFAutoShape shape1 = slide.createAutoShape();
  shape1.setShapeType(ShapeType.RECT);
  shape1.setFillColor(Color.GREEN);
  shape1.setAnchor(new Rectangle(50, 150, 150, 100));
  
  XSLFAutoShape shape2 = slide.createAutoShape();
  shape2.setShapeType(ShapeType.RECT);
  shape2.setFillColor(Color.GREEN);
  shape2.setAnchor(new Rectangle(500, 50, 150, 100));
  
  // first connector 
  XSLFConnectorShape connector1 = createConnector(slide, shape1, shape2);
  CTConnector ctConnector = (CTConnector)connector1.getXmlObject(); 
  CTGeomGuideList ctGeomGuideList = ctConnector.getSpPr().getPrstGeom().getAvLst();
  CTGeomGuide ctGeomGuide = ctGeomGuideList.addNewGd();
  ctGeomGuide.setName("adj1");
  ctGeomGuide.setFmla("val 45000");
  
  //second connector
  XSLFConnectorShape connector2 = createConnector(slide, shape1, shape2);
  ctConnector = (CTConnector)connector2.getXmlObject();  
  ctGeomGuideList = ctConnector.getSpPr().getPrstGeom().getAvLst();
  ctGeomGuide = ctGeomGuideList.addNewGd();
  ctGeomGuide.setName("adj1");
  ctGeomGuide.setFmla("val 57365");

  FileOutputStream out = new FileOutputStream("CreatePPTXConnectorShapes.pptx");
  slideShow.write(out);
  out.close();
 }
}

结果:

【讨论】:

  • 注释良好的示例代码。不确定问题/问题是否仅与 Shape Guide 名称 有关 (CtGeomGuide#name)。根据MS OOXML docsname 仅用作参考,因此&lt;a:gd name="adj1" fmla="val 57365" /&gt; 似乎有效。
  • @hc_dev:是的,&lt;a:gd name="adj1" fmla="val 57365" /&gt; 有效,但 &lt;a:gd name="adj" fmla="val 57365" /&gt; 无效。在这种情况下,形状指南具有特殊含义,它的名称必须引用可用的调整手柄。
猜你喜欢
  • 1970-01-01
  • 2022-08-23
  • 1970-01-01
  • 1970-01-01
  • 2013-09-24
  • 1970-01-01
  • 1970-01-01
  • 2016-05-01
相关资源
最近更新 更多