【问题标题】:Shrink text on overflow on a shape in Power Point在 Powerpoint 中的形状溢出时缩小文本
【发布时间】:2021-09-28 15:46:26
【问题描述】:

我有一个使用 Apache POI 的 Java 应用程序,它会生成一个 PPT(PowerPoint 演示文稿),其中包含这些形状上的形状和文本。我希望这些文本自动适应相应的形状。在 PowerPoint 中肯定有一个选项,它工作正常并称为“溢出时收缩文本”

使用 Apache POI,我可以从代码中设置此选项。下面的例子:

private void drawRectWithText(XSLFSlide slide, int x, int y, int width, int height, String text) {
    XSLFAutoShape shape1 = slide.createAutoShape();
    Rectangle rect1 = new Rectangle(x, y, width, upperRectHeight);
    shape1.setAnchor(rect1.getBounds2D());
    shape1.setShapeType(ShapeType.RECT);
    shape1.setText(text);
    shape1.setTextDirection(TextDirection.HORIZONTAL);
    shape1.setVerticalAlignment(VerticalAlignment.MIDDLE);
    XSLFTextParagraph xslfTextParagraph = shape1.getTextParagraphs().get(0);
    xslfTextParagraph.setTextAlign(TextParagraph.TextAlign.CENTER);
    xslfTextParagraph.setFontAlign(FontAlign.AUTO);
    XSLFTextShape xslfTextShape = xslfTextParagraph.getParentShape();
    xslfTextShape.setTextAutofit(TextAutofit.NORMAL); // <-- This sets the 'Shrink text on overflow'
    xslfTextShape.setAnchor(rect1.getBounds2D());
}

这确实正确设置了“溢出时收缩文本”选项,但什么也没发生,文本不会收缩。

当我打开生成的 PPT 时,文本有原来的大小,并且溢出,但我可以看到设置了正确的选项。但是,如果我在此形状上设置任何内容或重置幻灯片,文本会突然缩小。因此,该选项设置正确,直到我刷新形状才会生效。

Apache POI 中有没有办法以某种方式强制刷新形状?或者有没有其他方法可以实现“溢出时收缩文本”的行为?

我正在使用 Apache POI 5.0。

【问题讨论】:

    标签: java apache-poi


    【解决方案1】:

    在 Office Open XML 绘图中,Normal AutoFit 需要一个 fontScale 属性,该属性指定文本正文中每次运行的原始字体大小的百分比。如果省略此属性,则暗示值为 100%。 Apache POI 没有设置字体比例的方法,也不会自动计算字体比例。所以省略了。只有 PowerPoint 的 GUI 会在必要时自动计算字体比例。

    要提出一种解决方法,可以使用XSLFTextShape.resizeToFitText 来计算矩形的大小,以适应所有文本。如果该大小大于给定大小,则计算所需的字体比例以适应较小的矩形中的文本。但是XSLFTextShape.resizeToFitText会调整形状大小,所以之后需要重新设置想要的大小。

    例子:

    import java.io.FileOutputStream;
    
    import org.apache.poi.xslf.usermodel.*;
    import org.apache.poi.sl.usermodel.*;
    
    import java.awt.Rectangle;
    import java.awt.geom.Rectangle2D;
    
    public class CreatePPTXTextShape {
        
     static void drawRectWithText(XSLFSlide slide, int x, int y, int width, int height, String text) {
      XSLFAutoShape shape = slide.createAutoShape();
      Rectangle rect = new Rectangle(x, y, width, height);
      shape.setAnchor(rect.getBounds2D());
      shape.setShapeType(ShapeType.RECT);
      shape.setText(text);
      shape.setTextDirection(TextShape.TextDirection.HORIZONTAL);
      shape.setVerticalAlignment(VerticalAlignment.MIDDLE);
      shape.setTextAutofit(TextShape.TextAutofit.NORMAL); // <-- This sets the 'Shrink text to overflow'
      
      // calculate the needed font scaling
      Rectangle2D rect2D = shape.resizeToFitText();
      double upscaledHeight = rect2D.getHeight(); // needed height to fit the text in
      double hScale = 1d;
      if (upscaledHeight > height) hScale = height / upscaledHeight;
      System.out.println(hScale);
      // set font scale
      shape.getTextBody().getXmlObject().getBodyPr().getNormAutofit().setFontScale(hScale * 100000);
      // shape.resizeToFitText() had resized the shape, so set wanted size again
      shape.setAnchor(rect.getBounds2D());
      
      XSLFTextParagraph xslfTextParagraph = shape.getTextParagraphs().get(0);
      xslfTextParagraph.setTextAlign(TextParagraph.TextAlign.CENTER);
     }
    
     public static void main(String[] args) throws Exception {
    
      SlideShow slideShow = new XMLSlideShow();
    
      XSLFSlide slide = (XSLFSlide)slideShow.createSlide();
    
      drawRectWithText(slide, 100, 100, 50, 50, "This is a test text.");
      
      drawRectWithText(slide, 100, 200, 100, 50, "This is a longer test text.");
      
      drawRectWithText(slide, 300, 100, 50, 100, "This is a much longer test text.");
    
      FileOutputStream out = new FileOutputStream("./CreatePPTXTextShape.pptx");
      slideShow.write(out);
      out.close();
      slideShow.close();
     }
    }
    

    【讨论】:

    • 像魅力一样工作!谢谢!然而,这并不能完美地模仿“溢出时收缩文本”的行为。如果执行此代码,打开生成的 PPT 并开始编辑文本,或重置幻灯片,文本会更改。如果你有足够的空间,不仅是大小,还有行高和换行符。
    • @Márk Farkas:不,这并不能完美地模仿“溢出时收缩文本”的行为。正如我在回答中所说,这是一种解决方法,因为直到现在apache poi 中还没有实现这种行为。我怀疑它会很快实施。一个实现需要渲染,直到现在在apache poi 中并不经常实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-21
    • 1970-01-01
    • 2021-05-16
    • 2016-02-04
    • 1970-01-01
    相关资源
    最近更新 更多