Google Slidesでスクリプトから全ページにタイトル挿入してみた


実現したこと

初投稿です!弊社では資料の共有にGoogle Slidesを使っております。
しかし、Google SlidesはPowerPointに比べてまだまだ使っている人が少なく、アドオンも充実していません。
効率化と資料のデザイン統一のために、テンプレートも作成しましたが、デフォルトでは使いづらいです。

そこで、GASを使って機能をいろいろと増やしました。
今回は、タイトルの自動入力についてです。

表紙に書いたタイトルを全ページに反映する

今回作成したのは、表紙に書いた資料のタイトル(今回は「プレゼンのタイトル」としています)を、各ページの上部に自動で入れるという機能です。
もちろん1ページずつ入れていっても良いですし、スライドをコピペしても良いですが、それでは文言が変わった時に全ページを修正する必要あって面倒です。
スライドマスタで設定しておいても良いんですけど、個人的にテンプレートのスライドマスタをいじるのはあまり好きじゃないので(一般ユーザーは提供されたテンプレートの中身変えるだけで、マスタはいじらない思想です)、スクリプトで作りました。

プレゼンの表紙

一般ページ

ページ左上に入っている「プレゼンのタイトル」というのが、1クリックで追加されたり、更新されたりします。

コード

function onOpen(e) {
  SlidesApp.getUi().createAddonMenu()
      .addItem('タイトルを更新する', 'updateTitle')
      .addToUi();
}

function updateTitle(){
  // タイトルテキストを入れる場所設定
  const TITLE_TOP = 5;
  const TITLE_LEFT = 10;
  const TITLE_WIDTH = 600;
  const TITLE_HEIGHT = 20;

  // 全体タイトル情報を取得
  var slides = SlidesApp.getActivePresentation().getSlides();
  var presentationTitle = slides[0].getShapes()[0].getText().asString();

  // 各区切りページのタイトルに全体タイトルを代入
  slides.forEach(function(slide){
    var shapes = slide.getShapes();
    var is_updated = false;

    //存在する場合は更新(場所で判断)
    shapes.forEach(function(shape){
      if(shape.getTop() === TITLE_TOP && shape.getLeft() === TITLE_LEFT){
        shape.getText().setText(presentationTitle);
        is_updated = true;
        return;
      }
    });

    // 存在しない場合は新規作成
    if(!is_updated){
      var insertedTextBox = slide.insertTextBox(presentationTitle, TITLE_LEFT, TITLE_TOP, TITLE_WIDTH, TITLE_HEIGHT);
      // タイトルの書式を設定
      insertedTextBox.getText().getTextStyle()
        .setFontSize(18)
        .setForegroundColor("#FFFFFF");
    }
  });
}

説明

アドオンメニューへの追加

function onOpen(e) {
  SlidesApp.getUi().createAddonMenu()
      .addItem('タイトルを更新する', 'updateTitle')
      .addToUi();
}

これを入れておくと、ファイルを開いたときにメニューに今回の機能を自動で追加してくれます。
(認証を求められたり、認証設定が必要かも)

タイトルの作成・更新

function updateTitle(){
  // タイトルテキストを入れる場所設定
  const TITLE_TOP = 5;
  const TITLE_LEFT = 10;
  const TITLE_WIDTH = 600;
  const TITLE_HEIGHT = 20;

  // 全体タイトル情報を取得
  var slides = SlidesApp.getActivePresentation().getSlides();
  var presentationTitle = slides[0].getShapes()[0].getText().asString();

  // 各区切りページのタイトルに全体タイトルを代入
  slides.forEach(function(slide){
    var shapes = slide.getShapes();
    var is_updated = false;

    //存在する場合は更新(場所で判断)
    shapes.forEach(function(shape){
      if(shape.getTop() === TITLE_TOP && shape.getLeft() === TITLE_LEFT){
        shape.getText().setText(presentationTitle);
        is_updated = true;
        return;
      }
    });

    // 存在しない場合は新規作成
    if(!is_updated){
      var insertedTextBox = slide.insertTextBox(presentationTitle, TITLE_LEFT, TITLE_TOP, TITLE_WIDTH, TITLE_HEIGHT);
      // タイトルの書式を設定
      insertedTextBox.getText().getTextStyle()
        .setFontSize(18)
        .setForegroundColor("#FFFFFF");
    }
  });
}

各スライドをループしながら、スライドに含まれるシェイプが今回設定したものか確認しています。
今回設定したタイトルシェイプがない場合には新規作成し、既に存在する(TOP,LEFT位置で判断しています)場合には、文字を更新しています。
slideやshapeというクラスが用意されているので、以下のドキュメントを見ながらやればたぶんできるかと。
https://developers.google.com/apps-script

わかりづらかったところ

slideクラスとpageクラス

Google Slidesのapps scriptでは様々なクラスが用意されていますが、slideクラスとpageクラスがあって、どっちだよ!ってなりました。
slideは普通のスライド、pageはスライドだけでなくマスタやレイアウトなども含めたものだそうです。

テキストスタイルの設定

      insertedTextBox.getText().getTextStyle()
        .setFontSize(18)
        .setForegroundColor("#FFFFFF");

とやっていますが、getTextでTextRangeオブジェクトが取得できるのですが、そこからgetTextStyleでテキストスタイルを取得した後にスタイルをセットしています。
getTextでは書いてある文字が取得できるのではなく、文字も含めたTextRangeオブジェクトが取れるというのが少しわかりづらかったです。

ページ番号の取得

ページ番号をスマートに取得することができませんでした。
(変数持たせてループで取得とかはできましたが・・・)
1ページ目にはタイトル入れないようにするとかしたかったのですが、今回は断念。
どなたかやりかたご存じでしたら教えてください(´;ω;`)

その他

他にも目次機能つくって、機能一覧をサイドバーにまとめたりしています。
今回初投稿ということでとりあえず投稿してみたかったので、GASについて書きましたが、余裕ができたらそのあたりについても書きたいですね。

追記

今回、プレゼンのタイトルを以下のように取得しましたが、人によってはshapeの位置など違うと思うのでお気を付けください!

var slides = SlidesApp.getActivePresentation().getSlides();
var presentationTitle = slides[0].getShapes()[0].getText().asString();