在 Android 上管理演示文稿占位符
概述
占位符是一种形状,用于在演示文稿模板中保留特定类型内容的位置。常见示例包括标题、正文、图片、图表和通用内容占位符。与普通形状不同,占位符可以从版式幻灯片或母版幻灯片继承其位置、大小、格式以及其他设置。
Aspose.Slides 通过 IShape.getPlaceholder 方法公开占位符信息。该方法返回一个 IPlaceholder 对象,若为普通形状则返回 null。使用 IPlaceholder.getType 可确定占位符的预期内容类型。
在知道占位符类型后,形状接口仍然很重要:
- 空的文本、图片、图表或内容占位符通常由 IAutoShape 表示。
- 已填充的图片占位符可以由 IPictureFrame 表示。
- 已填充的图表占位符可以由 IChart 表示。
- 内容占位符可以包含多种内容。应同时检查 IPlaceholder.getType 和运行时形状接口,而不要假设每个占位符都是 IAutoShape。
Warning
IPlaceholder.getType 描述占位符的角色;它并不保证形状的运行时类型。访问文本、图片、图表、表格或媒体特定成员之前,请始终进行类型检查。了解占位符继承
占位符形成层次结构:
- 母版幻灯片定义可复用的样式,并在某些情况下定义母版级占位符。
- 版式幻灯片定义供一个或多个普通幻灯片使用的布局,并可继承自母版。
- 普通幻灯片包含该幻灯片的占位符,并可继承自其版式。
调用 IShape.getBasePlaceholder 可在此层次结构中向上移动一级。幻灯片占位符通常返回其版式占位符;版式占位符可以返回其母版占位符。当形状没有基占位符时,该方法返回 null。
以下示例列出第一张幻灯片上的占位符并报告其基占位符:
import com.aspose.slides.*;
Presentation presentation = new Presentation("template.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
for (IShape shape : slide.getShapes()) {
IPlaceholder placeholder = shape.getPlaceholder();
if (placeholder == null) {
continue;
}
byte placeholderType = placeholder.getType();
String typeName = shape.getClass().getSimpleName();
String slidePlaceholderMessage = "Slide placeholder: " + placeholderType + "; shape interface: " + typeName;
System.out.println(slidePlaceholderMessage);
IShape layoutPlaceholder = shape.getBasePlaceholder();
if (layoutPlaceholder != null) {
IPlaceholder layoutPlaceholderInfo = layoutPlaceholder.getPlaceholder();
Byte layoutPlaceholderType = layoutPlaceholderInfo == null ? null : layoutPlaceholderInfo.getType();
String layoutPlaceholderMessage = " Layout placeholder: " + layoutPlaceholderType;
System.out.println(layoutPlaceholderMessage);
IShape masterPlaceholder = layoutPlaceholder.getBasePlaceholder();
if (masterPlaceholder != null) {
IPlaceholder masterPlaceholderInfo = masterPlaceholder.getPlaceholder();
Byte masterPlaceholderType = masterPlaceholderInfo == null ? null : masterPlaceholderInfo.getType();
String masterPlaceholderMessage = " Master placeholder: " + masterPlaceholderType;
System.out.println(masterPlaceholderMessage);
}
}
}
} finally {
presentation.dispose();
}
在普通幻灯片上编辑占位符会为该幻灯片创建或更改本地覆盖。编辑相关的版式或母版可能会影响仍然继承该设置的所有幻灯片。普通形状本身没有基占位符,仅因为它占据相同坐标而不会开始继承。
移除占位符状态
在适配模板时,使用 IShape.removePlaceholder 将现有对象保留为普通形状。其 getPlaceholder 方法返回 null,但形状仍保留在幻灯片的集合中。相反,使用 IShapeCollection.remove 会将形状从该集合中删除。
以下示例需要一个包含至少一张幻灯片且第一张幻灯片上有非空文本占位符的 template.pptx。使用从其版式或母版继承格式的占位符,可观察移除该关系的效果。示例检查相同的形状是否仍然存在,对现在的普通形状再次调用该方法,并保存结果。
Warning
移除占位符状态并不会自动保留继承的外观设置。下面的示例有意保持这些设置不变,因此输出可能看起来不同。一个位置和大小完全继承的形状在调用后可能出现坐标和尺寸为零,虽然仍在集合中,但会变得不可见。import com.aspose.slides.*;
Presentation presentation = new Presentation("template.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
boolean found = false;
for (int index = 0; index < slide.getShapes().size(); index++) {
IShape candidate = slide.getShapes().get_Item(index);
if (!(candidate instanceof IAutoShape)) {
continue;
}
IAutoShape shape = (IAutoShape) candidate;
ITextFrame textFrame = shape.getTextFrame();
if (shape.getPlaceholder() == null ||
textFrame == null ||
textFrame.getText() == null ||
textFrame.getText().isEmpty()) {
continue;
}
int shapeCount = slide.getShapes().size();
shape.removePlaceholder();
System.out.println("Placeholder removed: " + (shape.getPlaceholder() == null));
System.out.println("Same shape retained: " + (slide.getShapes().get_Item(index) == shape));
System.out.println("Shape count unchanged: " + (slide.getShapes().size() == shapeCount));
// 在普通形状上调用此方法没有效果。
shape.removePlaceholder();
found = true;
break;
}
if (found) {
presentation.save("placeholder-status-removed.pptx", SaveFormat.Pptx);
} else {
System.out.println("No nonempty text placeholder was found on the first slide.");
}
} finally {
presentation.dispose();
}
对于匹配的占位符,所有三个检查都会打印 true。文本仍然保留,但继承的位置、大小、旋转、字体、段落对齐、文本框边距、垂直锚点、填充和线条设置在移除占位符关系后可能会改变。例如,继承的标题格式可能会回退为普通文本格式。有关版式的更多信息,请参阅 Slide Layout。
为保留预期的外观,在调用之前捕获解析后的位置、大小和旋转,并将所需的有效格式值复制到单独的变量中。通过 IPortionFormat.getEffective、IParagraphFormat.getEffective、ITextFrameFormat.getEffective、IFillFormat.getEffective 和 ILineFormat.getEffective 检索这些值。不要仅依赖有效格式对象,因为在移除关系后,它们的文本格式值可能会改变。随后将捕获的值显式应用到普通形状,包括字体族、大小、样式、颜色、段落设置、文本框设置、填充和线条等模板使用的属性。
继承的形状几何也可能需要通过 IGeometryShape.setShapeType 显式设置。对于矩形文本占位符,这意味着分配 ShapeType.Rectangle;仅恢复填充和线条可能不足以恢复可见的矩形。带有额外效果或更复杂格式的模板也需要相应处理这些设置。
在占位符中更改文本
标题、居中标题、副标题、正文和文本占位符通常支持文本。使用前请检查是否为 IAutoShape,再调用其 getTextFrame 方法。
以下示例更新第一张幻灯片上的第一个标题占位符并保存结果:
import com.aspose.slides.*;
Presentation presentation = new Presentation("template.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape titleShape = null;
for (IShape shape : slide.getShapes()) {
if (!(shape instanceof IAutoShape)) {
continue;
}
IAutoShape autoShape = (IAutoShape) shape;
IPlaceholder placeholder = autoShape.getPlaceholder();
if (placeholder == null) {
continue;
}
byte placeholderType = placeholder.getType();
if (placeholderType == PlaceholderType.Title || placeholderType == PlaceholderType.CenteredTitle) {
titleShape = autoShape;
break;
}
}
if (titleShape == null) {
throw new IllegalStateException("The first slide does not contain a title placeholder.");
}
titleShape.getTextFrame().setText("Quarterly Business Review");
presentation.save("title-placeholder-updated.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
此模式避免将图片、图表、表格或媒体占位符强制转换为 IAutoShape。它还通过用途识别占位符,而不是依赖脆弱的形状索引。
在版式上设置提示文本
提示文本是设计时显示在空占位符中的指示,例如 Click to add title。请在版式占位符上设置自定义提示文本,而不是尝试通过普通幻灯片的形状集合访问它。通过 ISlide.getLayoutSlide 获取版式,然后遍历 ILayoutSlide.getShapes 返回的集合。
以下示例更改第一张幻灯片使用的版式上的标题和副标题提示文本:
import com.aspose.slides.*;
Presentation presentation = new Presentation("template.pptx");
try {
ILayoutSlide layoutSlide = presentation.getSlides().get_Item(0).getLayoutSlide();
for (IShape shape : layoutSlide.getShapes()) {
if (!(shape instanceof IAutoShape)) {
continue;
}
IAutoShape autoShape = (IAutoShape) shape;
IPlaceholder placeholder = autoShape.getPlaceholder();
if (placeholder == null) {
continue;
}
byte placeholderType = placeholder.getType();
if (placeholderType == PlaceholderType.Title || placeholderType == PlaceholderType.CenteredTitle) {
autoShape.getTextFrame().setText("Enter a concise slide title");
} else if (placeholderType == PlaceholderType.Subtitle) {
autoShape.getTextFrame().setText("Enter a subtitle or reporting period");
}
}
presentation.save("custom-placeholder-prompts.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
提示文本并非普通幻灯片内容。它用于 PowerPoint 等编辑应用中的空占位符。一旦用户或程序提供了真实内容,提示文本将不再显示。更改提示文本也不会替换使用该版式的幻灯片上已有的文本。
更新图片占位符
需要处理两种情况:
- 如果图片占位符已经填充并由 IPictureFrame 表示,则通过 IPictureFillFormat.getPicture 和 ISlidesPicture.setImage 替换图像。
- 如果仍是空占位符,则使用 IShapeCollection.addPictureFrame 在占位符坐标处添加图片框,并移除空占位符。
下面的示例同时支持这两种情况并保存演示文稿:
import com.aspose.slides.*;
import java.io.FileInputStream;
Presentation presentation = new Presentation("picture-template.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
IShape picturePlaceholder = null;
for (IShape shape : slide.getShapes()) {
IPlaceholder placeholder = shape.getPlaceholder();
if (placeholder != null && placeholder.getType() == PlaceholderType.Picture) {
picturePlaceholder = shape;
break;
}
}
if (picturePlaceholder == null) {
throw new IllegalStateException("The first slide does not contain a picture placeholder.");
}
IPPImage image;
try (FileInputStream imageStream = new FileInputStream("replacement.png")) {
image = presentation.getImages().addImage(imageStream);
}
if (picturePlaceholder instanceof IPictureFrame) {
IPictureFrame pictureFrame = (IPictureFrame) picturePlaceholder;
pictureFrame.getPictureFormat().getPicture().setImage(image);
} else {
slide.getShapes().addPictureFrame(ShapeType.Rectangle, picturePlaceholder.getX(), picturePlaceholder.getY(), picturePlaceholder.getWidth(), picturePlaceholder.getHeight(), image);
slide.getShapes().remove(picturePlaceholder);
}
presentation.save("picture-placeholder-updated.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
为一个空占位符创建的替代对象是本地图片框,而不是新占位符,因为 IShape.getPlaceholder 并未提供设置器。它保留了保留的位置,但不再继承占位符特有的行为。如果保留占位符关系至关重要,请先在 PowerPoint 中准备并填充占位符,然后使用 Aspose.Slides 更新生成的 IPictureFrame。
有关图像透明度、裁剪以及其他图片特定效果,请参阅 Manage Picture Frames。这些操作属于图片框或图片填充,而不是占位符元数据。
处理图表和内容占位符
已填充的图表占位符可以由 IChart 表示。以下示例通过占位符类型和运行时接口同时查找此类图表,更改其标题并保存文件:
import com.aspose.slides.*;
Presentation presentation = new Presentation("chart-template.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
IChart placeholderChart = null;
for (IShape shape : slide.getShapes()) {
if (!(shape instanceof IChart)) {
continue;
}
IChart chart = (IChart) shape;
IPlaceholder placeholder = chart.getPlaceholder();
if (placeholder != null && placeholder.getType() == PlaceholderType.Chart) {
placeholderChart = chart;
break;
}
}
if (placeholderChart == null) {
throw new IllegalStateException("The first slide does not contain a populated chart placeholder.");
}
placeholderChart.setTitle(true);
placeholderChart.getChartTitle().addTextFrameForOverriding("Quarterly Revenue");
presentation.save("chart-placeholder-updated.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
通用内容占位符通常具有 PlaceholderType.Object。在 PowerPoint 中,它充当多个内容类型的启动器,包括图表、表格、图示、图片和媒体。填充后,请检查实际的形状接口以了解其包含的内容。特定版式还可能公开 PlaceholderType.Chart、PlaceholderType.Table、PlaceholderType.Picture、PlaceholderType.Media、PlaceholderType.Diagram。
Aspose.Slides 不会仅通过更改 IPlaceholder.getType 将空的 IAutoShape 占位符转换为 IChart;类型无法通过接口更改。若要以编程方式填充空的图表或内容区域,请在占位符坐标处添加所需对象,然后移除空占位符。以下示例演示了对图表的操作:
import com.aspose.slides.*;
Presentation presentation = new Presentation("content-template.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
IShape targetPlaceholder = null;
for (IShape shape : slide.getShapes()) {
IPlaceholder placeholder = shape.getPlaceholder();
if (placeholder == null) {
continue;
}
byte placeholderType = placeholder.getType();
if (placeholderType == PlaceholderType.Chart || placeholderType == PlaceholderType.Object) {
targetPlaceholder = shape;
break;
}
}
if (targetPlaceholder == null) {
throw new IllegalStateException("The first slide does not contain a chart or content placeholder.");
}
IChart chart = slide.getShapes().addChart(ChartType.ClusteredColumn, targetPlaceholder.getX(), targetPlaceholder.getY(), targetPlaceholder.getWidth(), targetPlaceholder.getHeight());
chart.setTitle(true);
chart.getChartTitle().addTextFrameForOverriding("Quarterly Revenue");
slide.getShapes().remove(targetPlaceholder);
presentation.save("content-placeholder-replaced-with-chart.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
添加的图表是普通本地图表。它占据占位符的区域,但不继承自版式占位符。需要替换其类别、系列或工作簿数据时,请使用专门的 chart management articles。
完整示例:更新文本或图像内容
下面的端到端示例打开模板,搜索第一张幻灯片上的标题或图片占位符,检查占位符和形状类型,更新相应内容并保存输出。示例刻意避免假设形状索引或将每个占位符强制转换为相同接口。
import com.aspose.slides.*;
import java.io.FileInputStream;
Presentation presentation = new Presentation("template.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
boolean updated = false;
for (IShape shape : slide.getShapes()) {
IPlaceholder placeholder = shape.getPlaceholder();
if (placeholder == null) {
continue;
}
byte placeholderType = placeholder.getType();
if ((placeholderType == PlaceholderType.Title || placeholderType == PlaceholderType.CenteredTitle) && shape instanceof IAutoShape) {
IAutoShape titleShape = (IAutoShape) shape;
titleShape.getTextFrame().setText("Quarterly Business Review");
updated = true;
break;
}
if (placeholderType == PlaceholderType.Picture) {
IPPImage image;
try (FileInputStream imageStream = new FileInputStream("replacement.png")) {
image = presentation.getImages().addImage(imageStream);
}
if (shape instanceof IPictureFrame) {
IPictureFrame pictureFrame = (IPictureFrame) shape;
pictureFrame.getPictureFormat().getPicture().setImage(image);
} else {
slide.getShapes().addPictureFrame(ShapeType.Rectangle, shape.getX(), shape.getY(), shape.getWidth(), shape.getHeight(), image);
slide.getShapes().remove(shape);
}
updated = true;
break;
}
}
if (!updated) {
throw new IllegalStateException("No supported title or picture placeholder was found on the first slide.");
}
presentation.save("placeholder-content-updated.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
FAQ
什么是基占位符?
基占位符是版式或母版上对应的形状,其他占位符从其继承。使用 IShape.getBasePlaceholder 可检索它。普通本地形状返回 null,因为它不属于占位符层次结构。
我可以通过编辑版式占位符来更改所有幻灯片的标题吗?
可以通过版式更改继承的格式或提示文本,但实际的标题内容存储在普通幻灯片上。要替换整个演示文稿的标题文本,需要遍历幻灯片并更新每个标题占位符。
如何管理日期、幻灯片编号、页眉和页脚占位符?
在相应的幻灯片、版式、母版、备注或讲义范围内使用页眉和页脚管理器。请参阅 Manage Presentation Header and Footer 获取完整示例。