GASでGoogleスライドのスキップスライド以外をPDF化する

GASでGoogleスライドのスキップスライド以外をPDF化するアイキャッチ画像

Googleスライドを作っているとき、発表には使わないけど、残しておきたいスライドはスキップ設定することってありますよね。

Googleスライドでスキップスライドが途中に入っている様子
10,12,14枚目がスキップ設定済み

[ファイル]→[ダウンロード]→[PDFドキュメント]でPDF化すると、スキップ設定したスライドも含めてPDF化されてしまいます。

Googleスライドに標準で搭載されれているPDF化するボタン

そこで、スキップ設定したスライド以外をPDF化するGASコードを作りました。

目次

スキップ設定したスライド以外をPDF化するGASコード

以下のコードをGASの編集画面にペーストすれば、動きます。使い方は、コードの後に記載します。

/**
 * メニューに機能を追加する
 */
function onOpen() {
  const ui = SlidesApp.getUi();                                                       // UIを取得
  ui.createMenu('GASメニュー')                                                         // メニューを作成
    .addItem('非スキップスライドのみでPDFを作成', 'createPdfWithNonSkippedSlides')   // メニュー項目を追加
    .addToUi();                                                                       // UIに追加
}

// 定数の定義
const CONFIG = Object.freeze({
  TEMP_SUFFIX    : "_一時コピー",               // 一時ファイルの接尾辞
  OUTPUT_SUFFIX  : "_非スキップバージョン",     // 出力ファイル名の接尾辞
  PDF_MIME_TYPE  : "application/pdf",           // PDFのMIMEタイプ
  SAVE_FOLDER_URL: 'PDFを保存するGoogleドライブのURLに差し替える' // PDFを保存するドライブURL
});

/**
 * テスト関数 - UIからPDF作成を実行する
 */
function createPdfWithNonSkippedSlides() {
  try {
    const ui = SlidesApp.getUi();                                                    // UIを取得
    
    // 確認ダイアログを表示
    const response = ui.alert(
      'スキップされていないスライドのみでPDFを作成',
      'スキップされていないスライドだけを含むPDFを作成しますか?',
      ui.ButtonSet.YES_NO
    );
    
    if (response === ui.Button.YES) {
      // PDFを作成
      const pdfFile = processSlides();                                // PDF作成関数を呼び出し
      
      // 成功メッセージを表示
      ui.alert(
        '完了',
        `PDFが作成されました!\n\nファイル: ${pdfFile.getName()}\nURL:\n${pdfFile.getUrl()}`,
        ui.ButtonSet.OK
      );
    }
  } catch (error) {
    SlidesApp.getUi().alert(`エラーが発生しました: ${error.message}`);                 // エラーメッセージを表示
  }
}


/**
 * Googleスライドのスキップされていないスライドだけを含めたPDFを生成する
 * @param {Object} options - PDFエクスポートのオプションパラメータ
 * @param {string} [options.filename] - 出力PDFファイル名(省略時はプレゼンテーション名 + " - 非スキップバージョン")
 * @param {GoogleAppsScript.Drive.Folder} [options.folder] - 保存先フォルダ(省略時はルートフォルダ)
 * @returns {GoogleAppsScript.Drive.File} 作成されたPDFファイル
 */
function processSlides(options = {}) {

  try {
    // 現在開いているプレゼンテーションを取得
    const presentation     = SlidesApp.getActivePresentation();                     // 現在のプレゼンテーションを取得
    const presentationId   = presentation.getId();                                  // プレゼンテーションIDを取得
    const presentationName = presentation.getName();                                // プレゼンテーション名を取得

    // フォルダURLからフォルダIDを抽出して保存先フォルダを取得
    const folderId = extractFolderIdFromUrl(CONFIG.SAVE_FOLDER_URL);                // フォルダURLからIDを抽出
    const outputFolder = DriveApp.getFolderById(folderId);                          // 出力先フォルダを取得
    
    // 出力ファイル名を設定
    const outputFilename = options.filename || presentationName + CONFIG.OUTPUT_SUFFIX + "_" + Utilities.formatDate(new Date, 'JST', 'yyyyMMddHHmm');  // ファイル名を設定

    Logger.log(`プレゼンテーション「${presentationName}」からPDFを作成します...`);

    // 一時コピーを作成
    const tempFile = createTemporaryCopy_(presentationId, presentationName + CONFIG.TEMP_SUFFIX);  // プレゼンテーションの一時コピーを作成
    
    // スキップされたスライドを削除
    removeSkippedSlides_(tempFile.getId());                                         // スキップされたスライドを削除

    // PDFにエクスポート(REST APIで直接エクスポートする方法に変更)
    const pdfBlob = exportSlidesToPdf_(tempFile.getId());                           // 改良されたPDFエクスポート関数を使用
    
    // PDFファイルを保存
    const pdfFile = outputFolder.createFile(pdfBlob);                               // PDFファイルを保存
    pdfFile.setName(outputFilename);                                                // ファイル名を設定
    
    // 一時ファイルを削除
    tempFile.setTrashed(true);                                                      // 一時ファイルをゴミ箱に移動
    
    Logger.log(`PDFファイル「${outputFilename}」を作成しました: ${pdfFile.getUrl()}`);

    return pdfFile;                                                                 // 作成したPDFファイルを返す
  } catch (error) {
    throw new Error(`PDFの作成中にエラーが発生しました: ${error.message}`);           // エラーを再スロー
  }
}

/**
 * プレゼンテーションの一時コピーを作成する
 * @param {string} presentationId - コピー元のプレゼンテーションID
 * @param {string} tempName - 一時コピーの名前
 * @returns {GoogleAppsScript.Drive.File} 作成された一時コピーファイル
 * @private
 */
function createTemporaryCopy_(presentationId, tempName) {
  try {
    // プレゼンテーションをファイルとして取得
    const originalFile = DriveApp.getFileById(presentationId);                      // 元のファイルを取得
    
    // ファイルをコピー
    const tempFile = originalFile.makeCopy(tempName);                               // 一時コピーを作成
    
    Logger.log(`一時コピー「${tempName}」を作成しました`);
    return tempFile;                                                                // 作成した一時コピーを返す
  } catch (error) {
    throw new Error(`一時コピーの作成に失敗しました: ${error.message}`);             // エラーを再スロー
  }
}

/**
 * プレゼンテーションからスキップされたスライドを削除する
 * @param {string} presentationId - 対象のプレゼンテーションID
 * @private
 */
function removeSkippedSlides_(presentationId) {
  try {
    // プレゼンテーションを開く
    const presentation = SlidesApp.openById(presentationId);                        // プレゼンテーションを開く
    const slides = presentation.getSlides();                                        // すべてのスライドを取得
    
    // 削除するスライドを特定(後ろから処理することで、インデックスのずれを回避)
    const slidesToRemove = [];                                                      // 削除対象のスライドを格納する配列
    for (let i = slides.length - 1; i >= 0; i--) {
      const slide = slides[i];                                                      // スライドを取得
      if (slide.isSkipped()) {                                                      // スライドがスキップ設定されているか確認
        slidesToRemove.push(slide);                                                 // スキップされているスライドを配列に追加
      }
    }
    
    // スキップされたスライドを削除
    for (const slide of slidesToRemove) {
      slide.remove();                                                               // スライドを削除
    }

    presentation.saveAndClose();
    
    Logger.log(`${slidesToRemove.length}枚のスキップされたスライドを削除しました`);
  } catch (error) {
    throw new Error(`スキップされたスライドの削除に失敗しました: ${error.message}`);   // エラーを再スロー
  }
}

/**
 * プレゼンテーションをPDFとしてエクスポートする(改良版)
 * @param {string} presentationId - エクスポート対象のプレゼンテーションID
 * @returns {GoogleAppsScript.Base.Blob} PDFのBlob
 * @private
 */
function exportSlidesToPdf_(presentationId) {
  try {
    // Advanced Drive APIを使用してエクスポート
    const token = ScriptApp.getOAuthToken();                                           // OAuth2トークンを取得
    
    // 直接Drive APIを使用してエクスポート
    const apiEndpoint = `https://www.googleapis.com/drive/v3/files/${presentationId}/export`;  // APIエンドポイント
    const params = {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${token}`                                             // 認証ヘッダー
      },
      muteHttpExceptions: true                                                         // HTTPエラーを抑制
    };
    
    // PDFとしてエクスポート
    const response = UrlFetchApp.fetch(`${apiEndpoint}?mimeType=application/pdf`, params);  // PDFとしてエクスポート
    
    // HTTPステータスコードをチェック
    const responseCode = response.getResponseCode();                                    // レスポンスコードを取得
    if (responseCode !== 200) {
      const responseText = response.getContentText();                                   // エラーメッセージを取得
      throw new Error(`APIエラー (${responseCode}): ${responseText}`);                  // エラーをスロー
    }
    
    // レスポンスからBlobを取得
    return response.getBlob().setName(`presentation.pdf`);                             // BlobをPDFとして返す
  } catch (error) {
    throw new Error(`PDFエクスポートに失敗しました: ${error.message}`);                 // エラーを再スロー
  }
}

/**
 * URLからGoogle DriveのフォルダIDを抽出する。
 * @param {string} url Google DriveフォルダのURL
 * @return {string} フォルダID
 */
function extractFolderIdFromUrl(url) {
  try {
    // URLから末尾のクエリパラメータを削除
    let folderUrl = url.split('?')[0];

    // '/folders/'より後ろの文字列を抽出する
    return folderUrl.split('/folders/')[1];
  } catch (error) {
    Logger.log(`フォルダURLの解析エラー:\n${error.stack}`);
    throw error;
  }
}

使い方

このGASを作った後に、Googleスライドの標準機能でスキップスライドを除外してPDF化する方法を見つけました。

その手順も紹介しておきます。

STEP
16行目をPDFを保存したいGoogleドライブのフォルダURLと差し替える

コードの16行目にある「PDFを保存するGoogleドライブのURLに差し替える」という部分を、PDFを保存したいGoogleドライブのフォルダURLに差し替えてください。

Googleスライドのスキップスライド以外をPDF化するGASの使い方手順0

差し替えると、以下のような感じになります。

Googleスライドのスキップスライド以外をPDF化するGASの使い方手順0.5
STEP
onOpenが選択されている状態で実行ボタンを押す
Googleスライドのスキップスライド以外をPDF化するGASの使い方手順1
STEP
スライドをリロードする
Googleスライドのスキップスライド以外をPDF化するGASの使い方手順2
STEP
メニュ欄にある[GASメニュー]→[非スキップスライドのみでPDFを作成]を押す
Googleスライドのスキップスライド以外をPDF化するGASの使い方手順3

GASの実行が終わるのを待つと、Gogoleドライブの指定フォルダにPDFが保存されます。

手動でスキップスライド以外をPDF化する方法

STEP
[ファイル]→[印刷プレビュー]
Googleスライドのスキップスライド以外をPDF化する操作手順1
STEP
[スキップしたスライドを含める]をクリックし解除する

[スキップしたスライドを含める]が黄色くなっている場合は、スキップしたスライドがPDFに含まれてしまいます。

Googleスライドのスキップスライド以外をPDF化する操作手順2

黄色い部分をクリックすると、解除されます。

Googleスライドのスキップスライド以外をPDF化する操作手順3
STEP
[PDF形式でダウンロード]をクリックする
Googleスライドのスキップスライド以外をPDF化する操作手順4

ダウンロードが始まります。

  • URLをコピーしました!

\ まずは無料で相談してみる /

この記事を書いた人

GASやVBAを使って、スプレッドシートやExcel作業を自動化しています。自分のつくったプログラムが、誰かの時間を節約できたらうれしいです。また、SEOライターとして、節約メディアや視覚障害メディアで執筆しています。広島県広島市在住。

目次