我正在设置一个 Google AppScript 来自动执行一些报告。 我正在检索一些数据,然后想根据需要创建幻灯片来报告所有数据。
我用作模板的演示文稿具有不同的 3 列布局,其中包含列标题的副标题占位符和列文本的正文占位符。
使用这些字段的替代文本,我能够在某种程度上发现幻灯片的布局。
function getPlaceholders(layout) {
layout.getPlaceholders().forEach((e, i) => {
Logger.log("[%s] %s %s", i, e.getPageElementType(), p.getDescription());
});
}
将打印类似
[0.0] SHAPE Header 1
的内容,其中 Column 1 header
是我为该占位符设置的 Alt 文本。
但是我遇到了两个问题:
下面的脚本将仅添加 2 张幻灯片。 第一张幻灯片将填写字段
标头 0-2 | 标头 0-0 | 标头 0-1 |
---|---|---|
身体0-2 | 身体0-0 | 正文0-1 |
第二张幻灯片的字段中不包含任何文本,因为脚本似乎无法发现它们。
function test(g) {
let styles = [
"CUSTOM_1",
"CUSTOM_1_2",
"CUSTOM_1_2_1",
"CUSTOM_1_2_1_1"
]
styles.forEach((style, index) => {
let newslide = g.addSlide(g.getLayout(style))
Logger.log("[%s] %s", index, style);
newslide.getPlaceholders().forEach((p, i) => {
// Won't print alt text as those aren't carried from template layouts to actual slides
Logger.log(" [%s] %s %s %s", i, p.getPageElementType(), p.getTitle(), p.getDescription());
});
for (let i = 0; i < 3; i++) {
newslide.getPlaceholder(SlidesApp.PlaceholderType.SUBTITLE, i).asShape().getText().setText(`Header ${index}-${i}`);
newslide.getPlaceholder(SlidesApp.PlaceholderType.BODY, i).asShape().getText().setText(`Body ${index}-${i}`);
}
});
}
这将报告例如
10:04:39 AM Info [0.0] CUSTOM_1
10:04:39 AM Info [0.0] SHAPE
10:04:39 AM Info [1.0] SHAPE
10:04:39 AM Info [2.0] SHAPE
10:04:39 AM Info [3.0] SHAPE
10:04:39 AM Info [4.0] SHAPE
10:04:39 AM Info [5.0] SHAPE
10:04:39 AM Info [6.0] SHAPE
10:04:40 AM Info [1.0] CUSTOM_1_2
10:04:40 AM Info [0.0] SHAPE
10:04:40 AM Info [1.0] SHAPE
10:04:40 AM Info [2.0] SHAPE
10:04:40 AM Info [3.0] SHAPE
10:04:40 AM Info [4.0] SHAPE
10:04:40 AM Info [5.0] SHAPE
10:04:40 AM Info [6.0] SHAPE
10:04:40 AM Error
TypeError: Cannot read properties of null (reading 'asShape')
(anonymous) @ App.gs:115
test @ App.gs:106
main @ App.gs:132
第二张幻灯片上的占位符似乎未被识别为
SlidesApp.PlaceholderType.SUBTITLE
类型。
所以我修改了for循环如下:
for (let i = 0; i < 3; i++) {
newslide.getPlaceholders()[2*i].asShape().getText().setText(`Header ${index}-${i}`);
newslide.getPlaceholders()[2*i+1].asShape().getText().setText(`Body ${index}-${i}`);
}
然而,这仍然不会产生漂亮的幻灯片,因为元素的顺序仍然不合乎逻辑。
幻灯片 1
标头 0-2 | 标头 0-0 | 标头 0-1 |
---|---|---|
身体0-2 | 身体0-0 | 正文0-1 |
幻灯片 2
身体1-0 | 标题 1-1 | 标头 1-0 |
---|---|---|
标题 1-2 | 主体1-2 | 点击添加文字 |
幻灯片 3
标题 2-1 | 标头 2-0 | 身体2-0 |
---|---|---|
点击添加文字 | 标题 2-2 | 本体2-2 |
幻灯片 4
标题 3-1 | 标头 3-0 | 身体3-0 |
---|---|---|
点击添加文字 | 标题 3-2 | 身体3-2 |
我想要实现的是能够以编程方式按逻辑顺序填充这些幻灯片。 IE。 (伪代码)
let index = 0;
let slide;
report.forEach((r) => {
if (index == 0) { slide = addSlide(layout_x) };
slide.placeholder(type=subhead)[index].setText(r.title);
slide.placeholder(type=body)[index].setText(r.content);
index = (index + 1) % 3;
});
TL;博士;
如何设置演示文稿模板,以便获得占位符元素的一致且符合逻辑的顺序?
作为替代标题和描述的另一种方法,我想建议使用布局中对象的对象 ID。当布局设置为幻灯片时,布局的对象 ID 可以视为parentObjectId 的值。当从布局中检索对象(例如,它们的形状)时,可以检索对象 ID、标题和描述。使用它们,可以获得与每个标题对应的每个对象ID。由此,即使布局设置为幻灯片,也可以使用parentObjectId获知插入对象的来源。当这反映在一个简单的示例脚本中时,它会变成如下所示。
请准备以下自定义布局。并且,将每个形状的标题设置为“subtitle1”,“body1”,“subtitle2”,“body2”。
请将创建的自定义布局设置到Google幻灯片的第一页。如下。
为了将文本正确插入到每个占位符中,使用以下示例脚本。请将自定义布局名称设置为
layoutName
。并且,请将标题和插入的文本分别设置为键和值。
在此示例中,“示例标题 1”、“示例正文 1”、“示例标题 2”、“示例正文 2”的文本被插入到“副标题 1”、“正文 1”、“副标题 2”、“分别是body2”。
function myFunction() {
// Please set your custom layout name.
const layoutName = "CUSTOM";
// Please set the title and the inserted text as the key and value, respectively.
const object = {
subtitle1: "sample title 1",
body1: "sample body 1",
subtitle2: "sample title 2",
body2: "sample body 2",
};
// Create an object including the parent object ID and the inserting text.
const s = SlidesApp.getActivePresentation();
const layout = s.getLayouts().find(e => e.getLayoutName() == layoutName);
const newObject = layout.getPageElements().reduce((o, e) => (o[e.getObjectId()] = object[e.getTitle()] || "", o), {});
// Insert the texts to each object of the placeholder.
const slide = s.getSlides()[0]; // As a sample, 1st page is used.
slide.getShapes().forEach(s => {
const parentObjectId = s.getParentPlaceholder().getObjectId();
if (newObject[parentObjectId]) {
s.getText().setText(newObject[parentObjectId]);
}
});
}
当该脚本运行到上述输入情况时,得到如下结果。