Created
March 3, 2023 01:58
-
-
Save Tomokatsu-Sakamoto/2c20ae4b6ea821435fa46dd7f8b3a462 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' // 変数の宣言を強制 | |
const THUMB_W = 320; // サムネイル画像の幅 | |
const THUMB_H = 180; // サムネイル画像の高さ | |
function onOpen() { | |
Logger.log("[開始] メニュー項目を追加"); | |
SpreadsheetApp.getUi() | |
.createMenu('スピーカーノート操作') | |
.addItem('ID の確認', 'getSlideName') | |
.addSeparator() | |
.addItem('シートに取得', 'getSpeakerNotesText') | |
.addItem('スライドへ書き出し', 'setSpeakerNotesText') | |
.addSeparator() | |
.addItem('シートのクリア', 'clearSheet') | |
.addToUi(); | |
Logger.log("[終了] メニュー項目を追加"); | |
} | |
/** | |
* 指定された ID から、スライドの名前を取得する。 | |
*/ | |
function getSlideName() { | |
const sheet = SpreadsheetApp.getActiveSheet(); // 現在のシートを取得 | |
const slideID = sheet.getRange('B1').getValue(); // 対象となるスライドの ID | |
const slide = SlidesApp.openById(slideID); // 対象となるスライドを開く | |
sheet.getRange('C1').setValue(slide.getName()); // セル C1 にスライドの名前を設定 | |
} | |
/** | |
* シートをクリアする ※ただし、A1:B1 は除く | |
*/ | |
function clearSheet() { | |
const sheet = SpreadsheetApp.getActiveSheet(); // 現在のシートを取得 | |
let maxCol = sheet.getMaxColumns(); | |
let maxRow = sheet.getLastRow(); | |
sheet.getRange('C1').clearContent(); // セル C1 をクリア | |
if (maxRow > 1) { | |
sheet.setRowHeights(2, maxRow - 1, 21); // サムネイル画像の高さはデフォルト値の 21 | |
sheet.setColumnWidth(3, THUMB_W); // サムネイル画像の 幅 は 320 のまま | |
// 現在のシートの内容を、2行目以降クリア | |
let range = sheet.getRange(2, 1, maxRow - 1, maxCol); | |
console.info('(' + maxCol + ',' + maxRow + ') ' + range.getA1Notation()); | |
range.clearContent(); | |
} | |
} | |
/** | |
* スライドの内容からスピーカーノートを抽出して、スプレッドシートに書き出す。 | |
*/ | |
function getSpeakerNotesText() { | |
const sheet = SpreadsheetApp.getActiveSheet(); // 現在のシートを取得 | |
const slideID = sheet.getRange('B1').getValue(); // 対象となるスライドの ID | |
const slide = SlidesApp.openById(slideID); // 対象となるスライドを開く | |
let targetFolderId = searchFolder(slide); // 出力先のフォルダをチェックする | |
const targetFolder = DriveApp.getFolderById(targetFolderId); // 新しいファイルを保存するフォルダ | |
console.info('targetFolderId : ' + targetFolderId); | |
clearSheet(); // 一旦、シートをクリアする | |
getSlideName(); // スライドのタイトルを取得 | |
// スライドの内容からスピーカーノートを抽出して、スプレッドシートに書き出す。 | |
let slides = slide.getSlides(); // スライドをすべて取得 | |
for (let i = 0; i < slides.length; i++) { // スライドの枚数分だけくり返す | |
// スライドのサムネイル画像を生成する | |
let res = Slides.Presentations.Pages.getThumbnail(slideID, slides[i].getObjectId()); | |
// 画像データを取得 | |
// https://developers.google.com/slides/api/reference/rest/v1/presentations.pages/getThumbnail | |
let fileName = '#' + String(i + 1).padStart(3, '0') + ' ' + slide.getName(); // ファイル名 | |
let response = UrlFetchApp.fetch(res.contentUrl); // 生成したサムネイル画像をダウンロード | |
let fileBlob = response.getBlob().setName(fileName); | |
// 取得した画像をGoogle Driveにアップロード | |
let file = DriveApp.createFile(fileBlob); // 画像ファイルをマイドライブに作成 | |
targetFolder.addFile(file); // 作成したファイルを、指定のフォルダに移動 | |
// IMAGE 関数のためにアクセス権を設定 | |
// https://developers.google.com/apps-script/reference/drive/file#setsharingaccesstype,-permissiontype | |
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW); | |
sheet.appendRow( // 取得した内容で行を追加 | |
[ | |
i + 1, // スライド番号 | |
slides[i].getNotesPage() // ノートページを取得 | |
.getSpeakerNotesShape() // スピーカーノートを含む形状を取得 | |
.getText() // テキスト コンテンツを取得 | |
.asString(), // 生のテキスト | |
// IMAGE 関数でページのサムネイルを生成 | |
`=IMAGE("https://drive.google.com/uc?export=download&id=${file.getId()}",4,${THUMB_H},${THUMB_W})`, | |
] | |
); | |
} | |
sheet.setRowHeights(2, sheet.getLastRow() - 1, THUMB_H); // サムネイル画像の高さは 180 | |
sheet.setColumnWidth(3, THUMB_W); // サムネイル画像の 幅 は 320 | |
sheet.getRange(2, 1, sheet.getLastRow() - 1, 3).setVerticalAlignment('top'); // 垂直方向は「上」 | |
} | |
/** | |
* スプレッドシートの内容からスライドのスピーカーノートを更新する。 | |
*/ | |
function setSpeakerNotesText() { | |
const sheet = SpreadsheetApp.getActiveSheet(); // 現在のシートを取得 | |
const slideID = sheet.getRange('B1').getValue(); // 対象となるスライドの ID | |
const slide = SlidesApp.openById(slideID); // 対象となるスライドを開く | |
// スプレッドシートの内容からスライドのスピーカーノートを更新する。 | |
let slides = slide.getSlides(); // スライドをすべて取得 | |
for (let i = 0; i < slides.length; i++) { // スライドの枚数分だけくり返す | |
slides[i].getNotesPage() // ノートページを取得 | |
.getSpeakerNotesShape() // スピーカーノートを含む形状を取得 | |
.getText() // テキスト コンテンツを取得 | |
.setText( // テキストを設定する | |
sheet.getRange(i + 2, 2).getValue() // シートの該当セルの内容 | |
); | |
} | |
} | |
/***************************************************************************** | |
* 指定されたフォルダが存在しているのかをチェック | |
* 1. 出力先となるフォルダが存在しているかをチェックし、存在していなければ | |
* 作成する | |
* | |
* @param {Spreadsheet} ss 処理対象となるスプレッドシート | |
* @return {String} 出力先のフォルダの ID | |
*/ | |
function searchFolder(ss) { | |
////////////////////////////////////////////////////////////////////////////// | |
// 1. 出力先となるフォルダが存在しているかをチェックし、存在していなければ作成する | |
const fileName = ss.getName(); // ファイル名を取得する | |
const fileId = ss.getId(); // スプレッドシートのファイル ID を取得 | |
let targetFolder; // 戻り値となるチェック対象のフォルダ ID | |
// スプレッドシートのファイル ID から保存されているフォルダの ID を取得 | |
let parentFolder = DriveApp.getFileById(fileId).getParents(); | |
let folderId = parentFolder.next().getId(); | |
// スプレッドシートの名前でフォルダが存在しているのかを確認 | |
const folderIterator = DriveApp.getFolderById(folderId).getFoldersByName(fileName); | |
if (folderIterator.hasNext()) { | |
// 存在する場合 | |
targetFolder = folderIterator.next(); | |
} | |
else { | |
// 存在しない場合 → フォルダを作成する | |
Logger.log("フォルダを作成する:" + fileName); | |
targetFolder = DriveApp.getFolderById(folderId).createFolder(fileName); | |
} | |
return targetFolder.getId(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment