見出し画像

Googleスライドの各ページを画像データとしてJSONで取り出す話

はい、かーでぃです。今回の投稿は、以前投稿した「Babylonでプレゼン資料」に関連した記事になります。

どう関係しているかというと…
「Babylonでプレゼン資料」では、コード内にBASE64でJPEG画像を埋め込んでいました。
それもやり方の1つなのですが、スライドを修正するたびに画像に落としてBASE64変換して…と、まぁ面倒です。せっかくなら、JSONで取得できれば修正がそのまま反映されるので、めっちゃ楽ですよね?

ということで、今日はそのあたりの記事です。

さて、なんかいいサービスないかなぁ~と、楽して行こうと考えたわけですが………「ない!!!」
いや、探し方が悪いだけかもしれないけど、自分が探した中ではなかったです。
で、仕方ないので、どーすっべかなぁ…と考えたら、GASならなんかあるのでは…ということで、ChatGPT先生に聞いてみましたw

まぁ、何回か手直しのやり取りはありましたが、概ねうごくコードを生成してくれました。必要となるスライドIDは、URLの下記の部分ですね。

https://docs.google.com/presentation/d/{スライドID}/edit
// --------------------
// 以下の定数を設定必須
// --------------------
const presentationId = 'スライドID';  // スライドのプレゼンテーションIDを入力してください

function doGet() {
  const jsondata = exportSlidesAsJson();

  // JSONで戻すためのおまじない
  ContentService.createTextOutput();
  const output = ContentService.createTextOutput();
  output.setMimeType(ContentService.MimeType.JSON);
  output.setContent(jsondata);

  return output;
}

// ----------------------------------------------------------------
// スライドを取り出してJSON化する
// ----------------------------------------------------------------
function exportSlidesAsJson() {
  // スライドのプレゼンテーションを開く
  const presentation = SlidesApp.openById(presentationId);
  
  // スライドのページ数を取得
  const pageCount = presentation.getSlides().length;
  
  // JSONオブジェクトを初期化
  var slidesJson = {
    slides: []
  };
  
  // 各スライドを処理
  for (var i = 0; i < pageCount; i++) {
    const slide = presentation.getSlides()[i];
    
    // スライドをJPEG画像にエクスポート
    const imageUrl = exportSlideAsImage(presentationId,slide);
    
    // スライド情報をJSONオブジェクトに追加
    slidesJson.slides.push({
      index: i + 1,
      imageUrl: imageUrl
    });
  }
  
  // JSONオブジェクトを文字列に変換
  var jsonString = JSON.stringify(slidesJson);
  
  // JSONを返す(もしくは他の処理を実行する)
  //console.log(jsonString);
  return jsonString;
}

// ----------------------------------------------------------------
// スライドを画像としてエクスポートする
// ----------------------------------------------------------------
function exportSlideAsImage(presentationId,slide) {
  const slideId = slide.getObjectId();
  const imageUrl = 'https://docs.google.com/presentation/d/' + presentationId + '/export/' + slideId + '?pageid=' + slideId + '&format=jpeg';
  
  const options = {
    headers: {
      Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
    }
  };
 
  const response = UrlFetchApp.fetch(imageUrl, options);
  const blob = response.getBlob();
  const encoded = Utilities.base64Encode(blob.getBytes());
  return encoded;
}

これを、ウェブアプリとしてデプロイしてあげると、URLが発行されるので、それを叩くと下記のようなJSONが出力されます。

{"slides":[{"index":1,"imageUrl":"/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBw...

BASE64のJPEGデータとして扱うには、ヘッダ情報(?)が必要なので、データを取得した先で保管してあげます。

    let globalData = new Array();
    (async () => {
        const response = await fetch('https://script.google.com/macros/s/{スライドID}/exec');
        const data = await response.json();

        for(const obj of data['slides']){
            globalData.push("data:image/jpeg;base64,"+obj.imageUrl)
        }
    })()

これでBASE64で変換されたJPEGデータが、JSON経由で取得できます。

※2023/7/8 追記
他のスライドで実行したところ、デプロイまでは動くのですが、実際に動かすと401エラーが出てしまいました。
これ、スライドが共有になっていないと出るエラーですので、これに陥ってしまった方は一度共有設定を確認することをオススメします!
(下記のようになっていればOKのはずです)

こちらの記事も参考にさせていただきました!
ありがとうございます。


この記事が気に入ったらサポートをしてみませんか?