如何在 Google 幻灯片中对占位符元素进行排序以便在 Google Apps 脚本中使用

问题描述 投票:0回答:1

我正在设置一个 Google AppScript 来自动执行一些报告。 我正在检索一些数据,然后想根据需要创建幻灯片来报告所有数据。

我用作模板的演示文稿具有不同的 3 列布局,其中包含列标题的副标题占位符和列文本的正文占位符。

假设幻灯片布局与下图类似。 drawing of slide layout

使用这些字段的替代文本,我能够在某种程度上发现幻灯片的布局。

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 文本。

Subtitle placeholderAlt text

但是我遇到了两个问题:

  • 占位符元素的顺序不遵循幻灯片的视觉顺序。
    在第一张幻灯片上,标题和正文的顺序是 2-0-1
  • 布局似乎存在一些错误,某些字段未被识别为占位符,即使幻灯片确实在这些字段中显示了默认占位符文本。
    似乎从上一张幻灯片复制字段会导致此问题,我需要为每个布局手动重做所有字段。

下面的脚本将仅添加 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
类型。

Example drawing

所以我修改了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

Example drawing

我想要实现的是能够以编程方式按逻辑顺序填充这些幻灯片。 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;博士;

如何设置演示文稿模板,以便获得占位符元素的一致且符合逻辑的顺序?

javascript google-apps-script google-apps google-slides google-slides-api
1个回答
0
投票

作为替代标题和描述的另一种方法,我想建议使用布局中对象的对象 ID。当布局设置为幻灯片时,布局的对象 ID 可以视为parentObjectId 的值。当从布局中检索对象(例如,它们的形状)时,可以检索对象 ID、标题和描述。使用它们,可以获得与每个标题对应的每个对象ID。由此,即使布局设置为幻灯片,也可以使用parentObjectId获知插入对象的来源。当这反映在一个简单的示例脚本中时,它会变成如下所示。

1.布局示例

请准备以下自定义布局。并且,将每个形状的标题设置为“subtitle1”,“body1”,“subtitle2”,“body2”。

enter image description here

2.设置布局

请将创建的自定义布局设置到Google幻灯片的第一页。如下。

enter image description here

3.示例脚本

为了将文本正确插入到每个占位符中,使用以下示例脚本。请将自定义布局名称设置为

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]);
    }
  });
}

4.测试

当该脚本运行到上述输入情况时,得到如下结果。

enter image description here

注:

  • 这是一个简单的示例脚本,用于解释我的方法。所以,请根据您的实际情况进行修改。

参考:

© www.soinside.com 2019 - 2024. All rights reserved.