スライドのグループ化された要素の特定の文字列を変更するためのコードを書きました。
結構意外とハマりポイントがあってもう書きたくないのでメモ。
実際はスプレッドシート情報を反映させるという使い方をしています。
グループ化せずに処理することも可能ですが、
グループ化していた方が、指定したスライドで getPageElements()
したときに
取得する要素数が少なく、グループ内の構造と処理内容が同じであれば、
グループ化するメリットはあるかなと思っています。
グループ内の特定の文字を変更
元々getTitleでやっていましたが、オブジェクトが変わるとタイトルは消えてしまうので、
記載されているテキストが一致したら変更するというコードに変更しました。
function myFunction() {
const pre = SlidesApp.getActivePresentation();
const slide = pre.getSlides()[1]; //2ページ目取得
const elems = slide.getPageElements();
for(const elem of elems) {
if(elem.getPageElementType().toString() == 'GROUP') {
replaceText_(elem);
}
}
}
/**
* グループのオブジェクトを渡して、各子要素のテキストが一致した場合に置換
*
* @param {Object} グループのオブジェクト
*/
function replaceText_(groupElem) {
const elemsInGroup = groupElem.asGroup().getChildren();
let text;
for(const elem of elemsInGroup) {
console.log(elem.getPageElementType().toString());
if (elem.getPageElementType().toString() !== 'SHAPE') continue;
text = elem.asShape().getText();
switch (text.asString()) {
case 'PJ名\n':
text.replaceAllText(text.asString(), 'PJ名_変更');
break;
case '氏名\n':
text.replaceAllText(text.asString(), '氏名_変更');
break;
case 'しめい\n':
text.replaceAllText(text.asString(), 'しめい_変更');
break;
case '目標\n':
text.replaceAllText(text.asString(), '目標_変更');
break;
case '実績\n':
text.replaceAllText(text.asString(), '実績_変更');
break;
case '達成率\n':
text.replaceAllText(text.asString(), '達成率_変更');
break;
}
}
}
理由はわからないですが、各テキストの後ろに改行が入るという
謎の仕様があったため一致条件の中に\n
を加えています。
if文を下記のように処理しても大丈夫です。
if(/PJ名\s/.test(text.asString())) {
//処理
} else if (/氏名\s/.test(text.asString())) {
//処理
}
写真の差し替えも行う場合
function myFunction() {
const pre = SlidesApp.getActivePresentation();
const slide = pre.getSlides()[1]; //2ページ目取得
const elems = slide.getPageElements();
for(const elem of elems) {
if(elem.getPageElementType().toString() == 'GROUP') {
replaceText_(elem);
}
}
}
/**
* グループのオブジェクトを渡して、各子要素のテキストが一致した場合に置換
*
* @param {Object} グループのオブジェクト
*/
function replaceText_(groupElem) {
const elemsInGroup = groupElem.asGroup().getChildren();
let text;
const pictureObj = getPictures_('フォルダID');
for(const elem of elemsInGroup) {
console.log(elem.getPageElementType().toString());
if (elem.getPageElementType().toString() === 'SHAPE') {
text = elem.asShape().getText();
switch (text.asString()) {
case 'PJ名\n':
text.replaceAllText(text.asString(), 'PJ名_変更');
break;
case '氏名\n':
text.replaceAllText(text.asString(), '氏名_変更');
break;
case 'しめい\n':
text.replaceAllText(text.asString(), 'しめい_変更');
break;
case '目標\n':
text.replaceAllText(text.asString(), '目標_変更');
break;
case '実績\n':
text.replaceAllText(text.asString(), '実績_変更');
break;
case '達成率\n':
text.replaceAllText(text.asString(), '達成率_変更');
break;
}
} else if (elem.getPageElementType().toString() === 'IMAGE') {
elem.asImage().replace(pictureObj['写真の名前']);
}
}
}
/**
* フォルダ内の名前とBlobデータをオブジェクトで返す
*
* @param {String} フォルダID
* @return {Object} key:拡張子を除いた写真の名前, value:写真のblobオブジェクト
*/
function getPictures_(folderId) {
const folder = DriveApp.getFolderById(folderId);
const files = folder.getFiles();
const obj = {};
while (files.hasNext()) {
const file = files.next();
obj[file.getName().replace(/\..+/g, '')] = file.getBlob();
}
return obj;
}