GASでGoogleスプレッドシートからGoogleスライドを生成する際、画像オブジェクトの置き換えができない件

タイトルが長くなりましたが、Googleスプレッドシート→Googleスライドとして変換するGASプログラムを書いていました。そこで問題は、Googleスライドにテキストを置換するのはいいのですが、画像オブジェクトがうまくいかなかったんです。

これを作っているのは、GoogleスプレッドシートでExcelでリスト化していけば、スライドが自動的に作れるのと、画像も扱えるので超便利ということを狙ってやっています。

それらをほぼ解決(これが正しいかは不明)できたので共有メモとして残しておきます。意外にGoogleスライドを扱うネタが見られなかったので何かヒントになれば幸いです。

発生した問題

問題を整理すると、

  • shape(シェープ図形)などの(画像でない)オブジェクトはテキストを扱って、置換することは問題なくできている
  • しかし画像イメージ(画像オブジェクト)はどこを置き換えたらいいかが不明(プロパティ等が分からない)

という感じです。

テキスト系はいけるけど、画像ができんぞ!ということでした。

課題や不明点

Googleドライブの画像ファイルを取得して挿入するとかはできるが、画像オブジェクトの位置などは個別に設定が必要でテンプレートが使いづらそう

これは何を言っているかというと、挿入して直接画像ファイルを入れるのはいいんですよね。ただ今回はGASでテンプレートスライドを作ってまして、そのスライドに基づいて画像オブジェクトの位置も決めたいという感じです。

テンプレートがないならこれでもいいのですけどね。というところでした。

そもそも、画像内部のURLなどいじれるかが不明

画像オブジェクトがある時にその画像ファイル=ソースファイルがいじれるかとかできるかが不明ということでした。

検証したこと

getImages()メソッドでURLから画像を挿入できる

slide.getImages()[0].replace(image_url); 

という感じで、Googleスライドオブジェクトに対して、getImages()でいけばいける感じがしました。replaceとして、URLを引数でいれればいいと。

Googleドライブの画像ファイルを使う

このURLにはGoogleドライブで入れた画像URLを入ればいいというか、そもそも外部ファイル=公開されているものというものならこれは考えなくていいところです。

で、問題は、このGoogleドライブは内部ファイルなので結構手間です。というのは、以下のようなエラーが多発しました。

例外エラー:1 Exception: URL (ここにGoogleドライブの画像URL)で画像を取得できませんでした。画像が有効で一般公開されていることをご確認ください

Googleドライブからの取得エラー:GASでのエラー

公開にしていてもこうなるので、上の「一般公開」は関係なさそうです。

なおここでいうURLは、直接Googleドライブ画像のURLを入れればいいのでなく、ちょっと加工が必要なのが面倒ですね。

InsertImageというスライドに入れるメソッドならいけるか?

これは駄目でした。以下の記事を参考にしてみましたが、画像を直接スライドに入れるのはいいのですが、スライド単位でなくて、スライドにある画像オブジェクトに対して行いたかったからですね。

ご参考:[Google Apps Script]Google ドライブにある画像をスライドに挿入する

Sleepで遅延を入れたらエラーが出ない?

上の例外エラー対策として、遅延を入れてしっかり時間をとっていけばいいのかなと思ったんですが、うまくいくときといかないときがありました。

ここで気づいたのは、スクリプトエディタで関数を実行するのと、Googleスプレッドシートで実行ボタンを置いて動かすのは違う(後者のほうがエラーが出ない)という感じです。なぜかは不明です。

Googleドライブなどのキャッシュもあるかなと。例えばGoogleドライブの画像ファイルを削除しても、ゴミ箱にあるとうまくいかないかもで、完全に削除しないといけないみたいなところもありそうかなと。

なお、Sleep関数はないので自作する必要があります。遅延を入れるということですね。例えば以下のようにやっています。

// 処理のスリープ例
function sleep(staySecond){
    var now = Utilities.formatDate(new Date(), "Asia/Tokyo", "YYYY/MM/DD HH:mm:ss");
    Utilities.sleep(staySecond);
    now = Utilities.formatDate(new Date(), "Asia/Tokyo", "YYYY/MM/DD HH:mm:ss");
}

上であればstaySecondに1000と入れれば、1000ミリ秒=1秒の待ちになります。

動いたコード

参考までに動いたコードを部分的ですが載せておきます。コピペで動くわけではないのでご注意を。

図形オブジェクトなどShapeのテキスト置き換え

var shape = presentation.getPageElementById(id).asShape();
shape.getText().setText(data)

こんな感じで、shapeというオブジェクト変数を使って、あとはそこにsetTextするdataを指定するだけです。dataは文字列ですね。getTextでsetTextというのは気持ち悪いかもしれませんが、これでテキスト系はオッケーという感じです。

idは別にオブジェクトIDを指定する必要がありますが、そこは省略します。

画像オブジェクトなど画像はこうする

var img = presentation.getPageElementById(id).asImage();
        
img.setLeft(10);
img.setTop(50);
img.replace(image_url);
img.setHeight(300);
img.setWidth(200);

image_urlは別途指定が必要です。僕が指定したのはGoogleドライブの画像ファイルでした。

ここでLeftとかTopとかHeightとかWidthとか指定していますが、これをしないとスライドが出来るたびに、下にずれたり画像オブジェクトのサイズが変わる(小さくなる)ということがありました。よって、こうやって固定値を入れることで回避しました。画像の追加としては不要なのですが、スライド上に乗るということでは必須かもしれません。

細かいですが、HeightとWidthを指定するだけしても良さそうじゃないですか。ただそれをするとTopが下にズレていくという現象になりました(笑)内部的にずれるのか原因は不明です。

なお、これで問題という問題は起きていませんが、サイズを固定することにより、「自動的に画像サイズをリサイズ」するので、間延びした感じになることもあります。これはGoogleスライド側でテンプレートスライドにある画像オブジェクトのプロパティを設定出来れば治るのかな?と思ったのですがうまくできなかったですね。

最終的な懸念点

これでエラーが出ないことが多いので(ただしスクリプトエディタから直接実行すると例外エラーがなぜか出るので、Googleスプレッドシートに実行ボタンを押してやる)いいかなと思っています。

ただ、問題は遅延を入れつつとやると、スライドが多くなって例えば30枚あると、遅延3秒で90秒かかりますから、GASの制限が確か5分か6分だったのでそれにかかるかなーという感じです。

参考にしたもの

以下参考になりました。ありがとうございます。

[GAS]字幕作成用 スプレッドシートからスライドを自動生成は、テキストのスライド化ができるよねという確認になりました。シンプルなスライド化の参考になります。

GASを使ってフォームの回答から自動的に自己紹介スライド(写真付き)を作成するは、画像が扱えることということで、最も参考になった記事でした。最後に「たまに画像の置き換えが上手くいかないことがある」というのがあるのですが、まさにそれは体験したところでした。ちなみに自分が体験したのは、GASのスクリプトエディタを直接叩いたり、何度も実行しているとエラーが多くなる印象がありました。Googleドライブのファイルを扱う時、キャッシュが悪さをしているかもしれないなくらいの感覚です。

以上何かヒントになれば幸いです。

タイトルとURLをコピーしました