見出し画像

【GAS】Google Apps Script 活用事例 各シート内容の説明を残したまま、スプレッドシート内の目次を作成するスクリプト

スクリーンショット 2021-10-30 20.30.50

E列のシート内容のみ、チームの各々のメンバーに手入力で更新してもらい、最新のシート名と並び順が、目次の並び順と常に一致するスクリプトを書きました。

ロジック

1. 全てのシート名、URLを取得して貼り付ける
2. 更新日時でsortする
3. 重複削除前の情報を一旦取得する
4. 重複削除前の2次元配列からE列が空白以外の行を取得する
5. URLが一致したら、シート内容を転記する

スクリプト全文はこんな感じ

/**
* スプレッドシート内に非表示のシートを含め、目次を作成する
* 
*/

function generateSheetIndex() {
 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
 const baseUrl     = spreadsheet.getUrl();

 //シートをアクティブにして、左から1番目に移動する
 const indexSheet = spreadsheet.getSheetByName('目次');
 spreadsheet.setActiveSheet(indexSheet, true);
 spreadsheet.moveActiveSheet(1);

 //全てのシートを取得
 const sheets = spreadsheet.getSheets();
 const values = [['No.', 'シート名', 'URL', '更新日時', 'シート内容']];


 // 目次シートを除くため i は 1 から開始
 for(let i = 1; i < sheets.length; i++) {

   /*必要に応じて、ここから後述のスクリプトと入れ替え*/

   const number    = i;
   const sheet     = sheets[i];
   const sheetName = sheet.getName();
   const d         = new Date();
   const date      = Utilities.formatDate(d, 'JST', 'yyyy/MM/dd HH:mm');
   const sheetUrl  = baseUrl + '#gid=' + sheet.getSheetId();
   values.push([number, sheetName, sheetUrl, date]);

   /*ここまで*/

 }//for

 const lastRow = indexSheet.getLastRow() + 1;
 console.log(`最終行: ${lastRow}`);

 //初回 目次シートが白紙の場合
 if(lastRow === 1){
   indexSheet.getRange(1, 1, values.length, values[0].length).setValues(values);

 }else if(1 < lastRow){
 
   //2回目以降の実行 新しく追加されたシートだけが最終行に追加される
   //見出し行を削除後、シート名、URLなどを貼り付け
   const headerRow = values.shift(); 
   indexSheet.getRange(lastRow, 1, values.length, values[0].length).setValues(values);


   //主にfor文内で使用
   const index = {
     number:    headerRow.indexOf('No.'),
     sheetName: headerRow.indexOf('シート名'),
     url:       headerRow.indexOf('URL'),
     date:      headerRow.indexOf('更新日時'),
     contents:  headerRow.indexOf('シート内容')
   };
   console.log(index);


   //getRangeの指定で使用
   const column = {
     date:     index.date + 1,
     contents: index.contents + 1,
     url:      index.url + 1
   };

   console.log(column);


   //シート内容の記載がある行だけを取得
   const range    = indexSheet.getRange(2, 1, indexSheet.getLastRow() -1, indexSheet.getLastColumn());
   const original = range.getDisplayValues();

   //シート内容についての説明が入力されている箇所を取得
   const filtered = original.filter(row => row[index.contents]);
   console.log(`index.contents ${index.contents}`);
   console.log(filtered);

   //2行目以降を、更新日時でsortする
   range.sort([
     {column: column.date, ascending: false}
   ]);

   //URLが一致する行を重複とみなし削除する。
   range.removeDuplicates([column.url]);

   //重複削除後のシートの値を取得する
   const cleanedValues = indexSheet.getDataRange().getDisplayValues();

   console.log(`シートの枚数: ${sheets.length}`);

   for(let i = 0; i < filtered.length; i++){
     for(let j = 0; j < cleanedValues.length; j++){
     //jがシートの枚数以上になったら、処理を中断する
     //目次シートの分マイナスする
       if(sheets.length < j)break;

       //urlが一致したら、setValuesで貼り付け
       if(filtered[i][index.url] === cleanedValues[j][index.url]){
         const row = j + 1;
         const targetRange = indexSheet.getRange(row, column.contents);

         console.log(`${filtered[i][index.sheetName]} === ${cleanedValues[j][index.sheetName]}`);
         console.log(`${targetRange.getA1Notation()}`);
         targetRange.setValue(filtered[i][index.contents]);

       }//if
     }//for_j
   }//for_i
 }//else
}//end

非表示を含む全てのシートに連番を振るスクリプト

スクリーンショット 2021-10-30 21.08.34

   //シート名に連番をつける
   const number = i;
   const originalSheetName = sheet.getName().replace(/.*】/, '');
   sheet.setName(`【 ${number}${originalSheetName}`);


   //リネーム後のシート名を取得
   const newSheetName      = sheet.getName();
   const d                 = new Date();
   const date              = Utilities.formatDate(d, 'JST', 'yyyy/MM/dd HH:mm');
   const sheetUrl          = baseUrl + '#gid=' + sheet.getSheetId();
   values.push([number, newSheetName, sheetUrl, date]);
   
入れ替え場所の目安については、下記文言をCtrl + Fで探してみてください。
/*必要に応じて、ここから後述のスクリプトと入れ替え*/ 

今現在、表示中のシートにのみ連番を振るスクリプト

スクリーンショット 2021-10-31 6.19.16

function setSheetNewName(){
 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
 const sheets      = spreadsheet.getSheets();
 let number        = 0;
 let string        = '';

 for(const sheet of sheets){
   if(sheet.isSheetHidden() === true){

     console.log(`${sheet.getName()} は非表示です。`);
     string += `${sheet.getName()} は非表示のため、スキップしました。\\n`;

     continue;

   }else if(sheet.getName() !== '目次'){
     number += 1;
     const originalSheetName = sheet.getName().replace(/.*】/, '');
     const newName           = `【 ${number}${originalSheetName}`;
     sheet.setName(newName);
     
     console.log(`${originalSheetName}${sheet.getName()} にリネーム完了\\n`);
     string += `${originalSheetName}${sheet.getName()} にリネーム完了\\n`;
   }
 }
 Browser.msgBox(string);
}

全てのシート名から連番を一旦消す

function setSheetNewName2(){
 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
 const sheets      = spreadsheet.getSheets();
 for(const sheet of sheets){
   const original = sheet.getName().replace(/.*】/, '');
   sheet.setName(original);
 }
}

実務で使うことないと思っていたけど、スクリプトがどんなケースでも上手くいくかシートの並び順を順不同にしたいというニーズが生じました。


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