GASでGoogleDriveのサブフォルダとファイル一覧を出力する

 タイトルのまんまです。以前、EXCELで似たようなことをしていたのでGASではどうするのかなぁと思ってやってみました。まぁほとんど丸パクリです。とりあえず、また使うかもしれないので自分用にメモです。しかしGASでGoogleDriveのファイル一覧嘗め回そうとすると3分かかってしまう。数が多いと6分制限に引っかかるのでこれでは使えない。せいぜい100ファイルとか数が少ないところで使う分にはいいけどダイナミックな場合は何回かに分割してやらないと少し厳しいかもしれない。

◆GAS


//設定値取得
const SHEET_URL = SpreadsheetApp.getActiveSpreadsheet().getUrl();
const ss = SpreadsheetApp.openByUrl(SHEET_URL);
const SETTING_SHEET = ss.getSheetByName('設定')
const TARGET_FOLDER_ID = SETTING_SHEET.getRange('B2').getValue();
const SAVE_FOLDER_ID = SETTING_SHEET.getRange('B3').getValue();
const SAVE_FILE_NAME = SETTING_SHEET.getRange('B4').getValue();
const SAVE_SHEET_NAME = SETTING_SHEET.getRange('B5').getValue();

function writeSheet(values, labels, sheetUrl, sheetname, width) {
  /* スプレッドシートに書き出し */
  try {
    if (values.length > 0) {
      // シートを追加する
      let spreadSheet = SpreadsheetApp.openByUrl(sheetUrl);
      let sheet = set_sheet(sheetUrl,sheetname);
      // 1行目だけヘッダ追加
      let headerCheck = sheet.getLastRow();
      if (headerCheck == 0) {
        sheet.appendRow(labels);
      }
      let lastRow = sheet.getLastRow();
      // 追加したシートに書き出し
      values.forEach(function (value) {
        sheet.appendRow(value);
      });
      const n = labels.length;
      // カラム整形
      let j = 0;
      for (let i = 1; i <= n; i++) {
        //sheet.autoResizeColumns(i,1);
        sheet.setColumnWidth(i, width[j]);
        j =++j;
      }
      return true;
    }
  } catch (e) {
    Logger.log("message:" + e.message + "\nlineNumber:" + e.lineNumber + "\nstack:" + e.stack);
    return false;
  }
}

function set_sheet(sheetUrl,name) {
  /* 同じ名前のシートがなければ作成 */
  try {
    let spreadSheet = SpreadsheetApp.openByUrl(sheetUrl);
    let sheet = spreadSheet.getSheetByName(name)
    if (sheet) return sheet
    sheet = spreadSheet.insertSheet();
    sheet.setName(name);
    return sheet;
  } catch (e) {
    Logger.log("message:" + e.message + "\nlineNumber:" + e.lineNumber + "\nstack:" + e.stack);
    return false;
  }
}

function getSpreadsheetURL(folderId, fileName) {
  /* スプレッドシートが存在していなければ作成、既に存在していれば開く */
  try {
    let target = findSpreadsheetByName(folderId,fileName)
    if (target==false){
      //新規作成・フォルダ指定がない場合はスクリプトと同じフォルダにファイル作成
      const newSS = SpreadsheetApp.create(fileName);
      const file = DriveApp.getFileById(newSS.getId()); 
      DriveApp.getFolderById(folderId).addFile(file)
      DriveApp.getRootFolder().removeFile(file)
      return file.getUrl();
    }else{
      //既存シートオープン
      return target;
    }
  } catch (e) {
    Logger.log("message:" + e.message + "\nlineNumber:" + e.lineNumber + "\nstack:" + e.stack);
    return false;
  }
}

function findSpreadsheetByName(id, name) {
  /* ファイル名からスプレッドシート検索 */
  let folder = DriveApp.getFolderById(id);
  let files = folder.getFilesByName(name);
  while (files.hasNext()) {
    let file = files.next();
    if ('application/vnd.google-apps.spreadsheet' == file.getMimeType()) {
      const ss = SpreadsheetApp.openById(file.getId());
      return ss.getUrl()
    }
  }
  return false;
}

function getFiletree(folderid){
/* 基準フォルダから下のフォルダ階層をすべてリストアップする */
try {
    let key = folderid;
    let stt = DriveApp.getFolderById(key);
    let name = "";
    let i = 0;
    let j = 0;
    let folderlist = [];
    let result = [];

    // 開始フォルダ
    folderlist.push([stt, key]);
    name = stt + '/';

    do {
      //フォルダ一覧取得
      let folders = DriveApp.searchFolders("'"+key+"' in parents");
      //フォルダ一覧からフォルダ名称とIdを取得
      while(folders.hasNext()){
        i++;
        let folder = folders.next();
        let tmparray = new Array();
        tmparray.push(name + folder.getName());
        tmparray.push(folder.getId());
        folderlist.push(tmparray);
      }
      //フォルダ名称とIdを取り出す
      j++;
      if(j <= i){
        name = folderlist[j][0] + '/';
        key = folderlist[j][1];
      }
    } while (j <= i);
    
    let fileArray = [];
    //ファイル情報取得
    for (i=0; i<=folderlist.length-1; i++) {
      let key = DriveApp.getFolderById(folderlist[i][1]).getId();
      let files = DriveApp.searchFiles("'"+key+"' in parents");
      while(files.hasNext()){
        fileArray = [];
        let file = files.next();
        fileArray.push(folderlist[i][0]);
        fileArray.push(file.getName());
        fileArray.push(file.getUrl());
        result.push(fileArray);
        j++;
      }
    }
    return result
  } catch (e) {
    let msg = e.message;
    Logger.log("message:" + e.message + "\nlineNumber:" + e.lineNumber + "\nstack:" + e.stack);
    Browser.msgBox('エラーが発生しました\\n'+ msg);
  }
}

function main() {
  try {
    //探索対象フォルダIDチェック
    if(TARGET_FOLDER_ID === ''){
      Browser.msgBox('フォルダIDを設定してください。');
      SpreadsheetApp.getActiveSheet().getRange("B2").activate();
      return;
    }
    const id = TARGET_FOLDER_ID;
    //フォルダ名(フォルダID指定がなければスプレッドシートの存在するフォルダのIDを取得)
    let folderId = ''
    if(SAVE_FOLDER_ID === ''){
      const ssId = ss.getId();
      const parentFolder = DriveApp.getFileById(ssId).getParents();
      folderId = parentFolder.next().getId();
    }else{
      folderId = SAVE_FOLDER_ID;
    }
    //ファイル名(指定がなければ固定名称)
    let fileName = '';
    if(SAVE_FILE_NAME === ''){
      fileName = "ファイル一覧";
    }else{
      fileName = SAVE_FILE_NAME;
    }
    let sheetUrl = getSpreadsheetURL(folderId, fileName) 
    //シート名(指定がなければファイル名を設定)
    let sheetName = ''
    if(SAVE_SHEET_NAME === ''){
      sheetName = fileName;
    }else{
      sheetName = SAVE_SHEET_NAME
    }
    //ラベルと枠幅設定
    const title = ["保管先フォルダ","ファイル","URL"];
    const width = [500,600,800];
    // 処理開始    
    let response = Browser.msgBox("完了までに3分程度かかります。\\n処理を開始してよろしいですか?", Browser.Buttons.YES_NO);
    if(response=='yes'){
      const data = getFiletree(id);
      writeSheet(data, title, sheetUrl, sheetName, width)
      Browser.msgBox('処理が完了しました。');
    }else{
      return;
    }
  } catch (e) {
    let msg = e.message;
    Logger.log("message:" + e.message + "\nlineNumber:" + e.lineNumber + "\nstack:" + e.stack);
    Browser.msgBox('エラーが発生しました\\n'+ msg);
  }
}

◆参考サイト

・ファイル処理

https://blog.hikozaru.com/2018/04/google-apps-script.html

https://www.gesource.jp/weblog/?p=8156

https://blog.awm.jp/2016/11/08/gas/

https://somachob.com/get-fileid/


・再帰処理関連

https://benri-life.com/2019/12/recursive-processing/

https://4to.pics/article/post/98

https://teratail.com/questions/82163

https://www.366service.com/jp/qa/e0a60363ca94d370395b8cd54f96c133

https://kunsen.net/2020/10/10/post-3327/


・サブフォルダ処理

https://qiita.com/hann-solo/items/88e16a014eba198f3494

https://officeforest.org/wp/2019/02/02/google-apps-script%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%81%AE%E6%8E%A2%E7%B4%A2/


・ポップアップ

http://tsujitaku50.hatenablog.com/entry/2017/02/19/170120

https://qiita.com/nakagawa1017/items/8b966af00fe271ff05fb


コメント

このブログの人気の投稿

証券外務員1種勉強(計算式暗記用メモ)

マクロ経済学(IS-LM分析)