With Apache POI 5.2.5, in an XMLSlideShow
, I am able to create few basic shapes, like triangle, rectangle. But for some reason, unable to create balloons and callouts.
Here is relevant piece of code (in Kotlin
)
val slideShow: SlideShow<*, *> = XMLSlideShow()
val slide = slideShow.createSlide()
var autoShape = slide.createAutoShape()
autoShape.shapeType = ShapeType.ACCENT_CALLOUT_1
autoShape.fillColor = Color.BLUE
autoShape.anchor = Rectangle(100, 400, 50, 50)
autoShape = slide.createAutoShape()
autoShape.shapeType = ShapeType.BALLOON
autoShape.fillColor = Color.GREEN
autoShape.anchor = Rectangle(200, 400, 50, 50)
autoShape = slide.createAutoShape()
autoShape.shapeType = ShapeType.BENT_ARROW
autoShape.fillColor = Color.YELLOW
autoShape.anchor = Rectangle(300, 400, 50, 50)
// this is working
autoShape = slide.createAutoShape()
autoShape.shapeType = ShapeType.ROUND_1_RECT
autoShape.fillColor = Color.CYAN
autoShape.anchor = Rectangle(400, 400, 50, 50)
val line = slide.createAutoShape()
line.shapeType = ShapeType.LINE
line.anchor = Rectangle(250, 250, 100, 200)
line.fillColor = Color(0, 128, 0)
It can be something very basic attribute or a property which I am missing, but unable to figure out as I am new the library. Any pointers are much appreciated.
The idea behind org.apache.poi.sl.usermodel.ShapeType was to protect both, the old binary OLE *.ppt
file format as well as the current Office Open XML *.pptx
file format. But as Microsoft is not really good in providing backwards compatibility, some of the old binary PowerPoint shape types are not usable using the current PowerPoint versions. Some simply will not be displayed and some not even have got a ooxmlId. For the latter current PowerPoint throws an error while opening the file when used in *.pptx
file.
If you check the output of:
for (ShapeType shapeType : ShapeType.values()) {
System.out.println(shapeType.name());
System.out.print("Native " + shapeType.nativeId);
System.out.println(" - " + shapeType.nativeName);
System.out.print("OOXML " + shapeType.ooxmlId);
System.out.println(" - " + shapeType.getOoxmlName());
System.out.println("----------------------------");
}
you wil see that some of the shape types only have nativeId
and ooxmlId
is -1
. Those cannot be used using XMLSlideShow
but using HSLFSlideShow
only. Vice versa some have ooxmlId
and nativeId
is -1
. Those cannot be used using HSLFSlideShow
but using XMLSlideShow
only.
Following example creates auto-shapes using all possible shape types. When used with SlideShow slideShow = new HSLFSlideShow(); FileOutputStream out = new FileOutputStream("./CreatePPTXShapeTypes.ppt");
, then for binary *.ppt
and when used with SlideShow slideShow = new XMLSlideShow(); FileOutputStream out = new FileOutputStream("./CreatePPTXShapeTypes.pptx");
then for current *.pptx
.
import java.io.FileOutputStream;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.hslf.usermodel.*;
import java.awt.Rectangle;
import java.awt.Color;
public class CreatePowerPointShapeTypes {
public static void main(String[] args) throws Exception {
try (
SlideShow slideShow = new XMLSlideShow(); FileOutputStream out = new FileOutputStream("./CreatePPTXShapeTypes.pptx");
//SlideShow slideShow = new HSLFSlideShow(); FileOutputStream out = new FileOutputStream("./CreatePPTXShapeTypes.ppt");
) {
Slide slide = slideShow.createSlide();
int x = 20;
int y = 20;
int width = 100;
int height = 100;
for (ShapeType shapeType : ShapeType.values()) {
if ((slideShow instanceof XMLSlideShow && shapeType.ooxmlId > -1) ||
(slideShow instanceof HSLFSlideShow && shapeType.nativeId > -1)) {
AutoShape autoShape = slide.createAutoShape();
autoShape.setText(shapeType.name());
autoShape.setShapeType(shapeType);
autoShape.setFillColor(Color.BLUE);
autoShape.setAnchor(new Rectangle(x, y, width, height));
x = x + width + 5;
if (x > 600) {
x = 20;
y = y + height + 5;
}
if (y > 400) {
slide = slideShow.createSlide();
x = 20;
y = 20;
}
}
}
slideShow.write(out);
}
}
}