如何通过 Apache POI 将文本大纲添加到 Powerpoint 中的文本:

How to add text outlines to text within Powerpoint via Apache POI:

有谁知道我们如何使用 Apache POI 向 powerpoint 模板 (ppxt) 中的文本添加轮廓(text outline)?到目前为止我收集到的是 XSLFTextRun class 没有方法来 get/ set 给定 运行 元素的文本大纲。

因此,我只能保留以下字体/文本样式:

def fontStyles(textBox: XSLFTextBox, textRun: XSLFTextRun): Unit = {
    val fontFamily = textRun.getFontFamily
    val fontColor = textRun.getFontColor
    val fontSize = textRun.getFontSize
    val fontBold = textRun.isBold
    val fontItalic = textRun.isItalic
    val textAlign = textRun.getParagraph.getTextAlign

    textBox.getTextParagraphs.foreach { p =>
      p.getTextRuns.foreach { tr =>
        tr.setFontFamily(fontFamily)
        tr.setFontColor(fontColor)
        tr.setFontSize(fontSize)
        tr.setBold(fontBold)
        tr.setItalic(fontItalic)
        tr.getParagraph.setTextAlign(textAlign)
      }
    }
  }

是否可以添加文本大纲?

如有任何帮助/建议,我们将不胜感激。

Apache poi 使用标的 ooxml-schemas 类。这些是根据 Office Open XML 标准自动生成的。所以他们比高级XSLF类更完整。当然它们就没那么方便了。

所以如果某些东西没有在高层 XSLF 类 中实现,我们可以获取底层 CT 类 并使用它们来实现。在 XSLFTextRun 的情况下,我们可以获得 CTRegularTextRun 对象。然后我们可以查看是否已经有 运行 个属性。如果没有,我们添加一个。然后我们看看是否已经设置了大纲。如果是这样,我们取消设置,因为我们想设置新的。然后我们设置一个新的大纲。这只是一条具有特殊颜色的线。该行由 CTLineProperties 对象表示。所以我们需要有方法来创建 CTLineProperties,将 CTLineProperties 设置为 XSLFTextRun 并从 XSLFTextRun.

获取 CTLineProperties

使用 Java 代码的完整示例:

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.sl.usermodel.*;

import java.awt.Rectangle;

public class PPTXTextRunOutline {
    
 static org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties createSolidFillLineProperties(java.awt.Color color) {
  // create new CTLineProperties
  org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties lineProperties 
   = org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties.Factory.newInstance();
  // set line solid fill color
  lineProperties.addNewSolidFill().addNewSrgbClr().setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
  return lineProperties;
 }
    
 static void setOutline(XSLFTextRun run, org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties lineProperties) {
  // get underlying CTRegularTextRun object
  org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun ctRegularTextRun 
   = (org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun)run.getXmlObject();
  // Are there run properties already? If not, add one.
  if (ctRegularTextRun.getRPr() == null) ctRegularTextRun.addNewRPr();
  // Is there outline set already? If so, unset it, because we are creating it new.
  if (ctRegularTextRun.getRPr().isSetLn()) ctRegularTextRun.getRPr().unsetLn();
  // set a new outline
  ctRegularTextRun.getRPr().setLn(lineProperties);  
 }
 
  static org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties getOutline(XSLFTextRun run) {
  // get underlying CTRegularTextRun object
  org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun ctRegularTextRun 
   = (org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun)run.getXmlObject();
  // Are there run properties already? If not, return null.
  if (ctRegularTextRun.getRPr() == null) return null;
  // get outline, may be null
  org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties lineProperties = ctRegularTextRun.getRPr().getLn();
  // make a copy to avoid orphaned exceptions or value disconnected exception when set to its own XML parent
  if (lineProperties != null) lineProperties = (org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties)lineProperties.copy();
  return lineProperties;
 }

 // your method fontStyles taken to Java code
 static void fontStyles(XSLFTextRun templateRun, XSLFTextShape textShape) {
  String fontFamily = templateRun.getFontFamily();
  PaintStyle fontColor = templateRun.getFontColor();
  Double fontSize = templateRun.getFontSize();
  boolean fontBold = templateRun.isBold();
  boolean fontItalic = templateRun.isItalic();
  TextParagraph.TextAlign textAlign = templateRun.getParagraph().getTextAlign();
  org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties lineProperties = getOutline(templateRun);
  for (XSLFTextParagraph paragraph : textShape.getTextParagraphs()) {
   for (XSLFTextRun run : paragraph.getTextRuns()) {
    run.setFontFamily(fontFamily);
    if(run != templateRun) run.setFontColor(fontColor); // set PaintStyle has the issue which I am avoiding by using a copy of the underlying XML
    run.setFontSize(fontSize);
    run.setBold(fontBold);
    run.setItalic(fontItalic);
    run.getParagraph().setTextAlign(textAlign);
       
    setOutline(run, lineProperties);
   }
  }   
 }

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

  XMLSlideShow slideShow = new XMLSlideShow(new FileInputStream("./PPTXIn.pptx"));

  XSLFSlide slide = slideShow.getSlides().get(0);
  
  //as in your code, get a template text run and set its font style to all other runs in text shape
  if (slide.getShapes().size() > 0) {
   XSLFShape shape = slide.getShapes().get(0); 
   if (shape instanceof XSLFTextShape) {
    XSLFTextShape textShape = (XSLFTextShape) shape;
    XSLFTextParagraph paragraph = null;
    if(textShape.getTextParagraphs().size() > 0) paragraph = textShape.getTextParagraphs().get(0);
    if (paragraph != null) {
     XSLFTextRun run = null;
     if(paragraph.getTextRuns().size() > 0) run = paragraph.getTextRuns().get(0);
     if (run != null) {
      fontStyles(run, textShape);  
     }
    }        
   }
  }

  //new text box having outlined text from scratch
  XSLFTextBox textbox = slide.createTextBox(); 
  textbox.setAnchor(new Rectangle(100, 300, 570, 80));
  XSLFTextParagraph paragraph = null;
  if(textbox.getTextParagraphs().size() > 0) paragraph = textbox.getTextParagraphs().get(0);
  if(paragraph == null) paragraph = textbox.addNewTextParagraph(); 
  XSLFTextRun run = paragraph.addNewTextRun();
  run.setText("Test text outline");
  run.setFontSize(60d);
  run.setFontColor(java.awt.Color.YELLOW);
  setOutline(run, createSolidFillLineProperties(java.awt.Color.BLUE));
  
  FileOutputStream out = new FileOutputStream("./PPTXOit.pptx");
  slideShow.write(out);
  out.close();
 }
}

使用当前 apache poi 5.0.0.

进行测试和工作