【GAS】フォルダ内のGoogleスライドを連結して一つのファイルにする

## １ 目的
Google apps Scriptで、複数のGoogleスライドを連結します。
プレゼンテーションファイル（Googleスライド）をつなげることは手動でできますが、たくさんファイルがあると面倒です。そこで、一つのフォルダに入ったスライドをすべて連結するスクリプトを書きました。Googleスライドのコンテナバインドプロジェクトです。

## ２ 準備
Googleスライドには、1枚だけスライドを作り、説明などを書くのに使います。連結対象のGoogleスライドのファイルは、Googleドライブのフォルダに入れ、そのフォルダのURLがわかるようにしておきます。元のGoogleスライドは、そのまま残ります。フォルダにGoogleスライド以外のファイルがあっても大丈夫です。


## ３ スクリプト
```JavaScript:slide_c.gs
'use strict';

//カスタムメニューを表示する
function onOpen() {
  const ui = SlidesApp.getUi();
  const menu = ui.createMenu('☆カスタムメニュー'); //表示名
  menu.addItem('スライド連結','combine_slides'); //メニューに追加するボタン
  menu.addToUi();
}

//メイン
function combine_slides(){
  const mypresen = SlidesApp.getActivePresentation();
  const myui = SlidesApp.getUi();
  const response = myui.prompt('連結するファイルが入っているGoogleドライブURLは？','例:https://drive.google.com/drive/folders/****************', myui.ButtonSet.OK_CANCEL);
  // CANCELなら処理中止
  if (response.getSelectedButton() == myui.Button.CANCEL) {
    return;
  }
  const myurl = response.getResponseText(); //入力されたURL
  //URLからフォルダのID取得
  const folder_id = getFolderId(myurl);
  //フォルダ内のファイルを取得
  const myfiles = DriveApp.getFolderById(folder_id).getFiles();
  //取得したファイルの処理
  for (let i = 0; myfiles.hasNext(); i++) {
    let s_file = myfiles.next();
    let mimetype = s_file.getMimeType();
    if (mimetype.match(/presentation/)) {
      let target_file = SlidesApp.openById(s_file.getId()); //プレゼンテーションファイル
      let target_slides = target_file.getSlides(); //対象ファイルのスライドすべて
      //このファイルに、対象ファイルのスライドを追加する
      for (let j = 0; j < target_slides.length; j++) {
        mypresen.appendSlide(target_slides[j]);
      }
    }
  }

//新しいプレゼンファイルを作る
  const mypresen2 = make_newfile();
//このプレゼンファイルの2枚目以降のスライドを新しいプレゼンファイルにコピー
  const mypresenSlides = mypresen.getSlides(); //このプレゼンのすべてのスライド
  const slidesToMove = mypresenSlides.slice(1); //1枚目を除いたスライド
  const num = slidesToMove.length;
  for (let i = 0;i < num;i++) {
    let oneSlide = slidesToMove[i];
    let copiedSlide = oneSlide.duplicate(); //スライド複製
    mypresen2.appendSlide(copiedSlide); //新プレゼンに追加
  }
//このプレゼンの2枚目以降のスライドを削除
  const mypresenSlides2 = mypresen.getSlides();
  const num2 = mypresenSlides2.length; //現在のスライド枚数
  for (let i = num2-1;i > 0;i--) {
    mypresen.getSlides()[i].remove();
  }
//終了を知らせる
  myui.alert('新しいファイルがマイドライブに作成されました。', myui.ButtonSet.OK);
}

//新しいプレゼンテーションファイルを作成し1枚目に作成日時を入れる
function make_newfile() {
  const today = new Date();
  const date1 = 'yyyy-MM-dd_HH:mm:ss';
  const date2 = Utilities.formatDate(today, 'JST', date1);
  const newfilename = 'newSlides_' + date2; //新ファイル名
  const newpresen = SlidesApp.create(newfilename);
  const copiedfileId = DriveApp.getFileById(newpresen.getId()); //新ファイルID
  //1枚目に新しいスライドを追加し、作成年月日時間を追記
  const mytext = '作成:' + date2; //スライドに入れるテキスト
  newpresen.insertSlide(0, SlidesApp.PredefinedLayout.BLANK); //1枚目にスライド追加
  const myslide = newpresen.getSlides()[0]; //追加したスライド
  //文字を入れる
  const shape1 = myslide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 10,100,600,60);
  const text1 = shape1.getText();
  text1.setText(mytext);
  text1.getTextStyle().setBackgroundColor('#0000ff').setForegroundColor('#ffffff').setFontSize(32);
  //新しいプレゼンに2枚目以降があれば削除
  const newpresenSlides = newpresen.getSlides();
  const count = newpresenSlides.length;
  if(count > 1) {
    let i = count - 1;
    for (i;i > 0;i--) {
      newpresen.getSlides()[i].remove();
    }
  }
  return newpresen;
}

//GoogleドライブのフォルダURLからフォルダのIdを返す
function getFolderId(folderUrl) {
  //URLからフォルダIDを抽出
  const folderIdRegex = /\/folders\/([^/?]+)/;
  const match = folderUrl.match(folderIdRegex);
  if (match) {
    return match[1]; //フォルダIDを返す
  } else {
    return null;
  }
}
```
onOpen は、ファイルを開いた時に、メニューにカスタムメニューを追加する関数です。表示された「⭐︎カスタムメニュー」から「スライド連結」を選べばcombine_slidesが実行されます。カスタムメニューはメニューバーの一番右に出ますので、画面を小さくしていると隠れていることがあります。

combine_slidesがメインの関数です。まず、連結したいファイルがあるフォルダのURLを入力させ、そのフォルダ内のファイルがプレゼンテーションファイルであれば、スライドをこのファイルに追加していきます。追加が終わったら、新しいプレゼンテーションファイルを作り、このファイルに追加していたスライドをコピーして、新しいファイルに追加します。その後、このファイルに追加・コピーしていたスライドを削除します。最後に、新しいファイルがマイファイルにできた旨、ダイアログを出します。

make_newfileは、連結先の新しいプレゼンテーションファイルを作る関数で、combine_slideの中から使用されます。新しいファイルはマイドライブに出来、ファイル名はnewfilenameに設定していますが、年月日等を入れたものです。スライドが1枚あり、テキストボックスに作成年月日時を入れています。新しいファイルを作った時点で1枚スライドはあるのですが、どういうスライドができているのか等不確実なので、1枚目にスライドを作成した後、2枚目は削除する形にしています。

getFolderIdは、GoogleドライブフォルダのURLからフォルダIDを返す関数で、combine_slideの中から使用されます。フォルダのURLは 
https://drive.google.com/drive/folders/[ID] 
という形なので、
https://drive.google.com/drive/folders/
だけ除いてやればいいかと最初思っていたのですが、IDの後に文字列が付いていることがあります。例えば、デスクトップ下にピンどめしたアイコンからGoogleドライブを起動した場合、?lfhs=2 がくっついていました。

## ４ 参考

- [【GASで時短】フォルダ内のスライドをすべて連結する](https://myfunc.jp/items/00103/index.html)
- [【GAS】複数ファイルに分散したスライドを１つのファイルに自動でまとめる](https://qiita.com/Dagger_ko1/items/b7cdb3dffbe3f3562e1e) (@Dagger_ko1)