グーグルドライブにみんなでファイルを登録するのは良いんだけれど、
一体誰が何を入れたのかわからなくなって、サテハテ?となったので作った。
大まかな方針(ざっくり)
- スクリプトをメニューから起動できるようにする
- 新シート(今日日付)を作る
- フォルダの一覧を配列に取得する
- フォルダの一覧配列を使い、ファイル一覧を取得し、スプレッドシートに書き出す
- ファイル名だけじゃなく、登録者、登録日も載る
- リンクをクリックすればプレビューも
<だいたいこんな感じになる>
コード
// メニューに表示させる
function onOpen(e){
var arr = [
{name: "リスト作成", functionName: "listAllMain"}
];
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.addMenu("スクリプト", arr);
}
// メイン処理
function listAllMain() {
insertNewSheet();
listAllFandF();
}
// 新シートを挿入、今日日付
function insertNewSheet() {
// 日付取得
var td = new Date();
// YYYYMMDD形式に変換(考えた人、賢いなあ)
var year_str = td.getFullYear();
var month_str = td.getMonth()+ 1; // monthはなんと0-11
var day_str = td.getDate();
month_str = ('0' + month_str).slice(-2);
day_str = ('0' + day_str).slice(-2);
format_str = 'YYYYMMDD';
format_str = format_str.replace(/YYYY/g, year_str);
format_str = format_str.replace(/MM/g, month_str);
format_str = format_str.replace(/DD/g, day_str);
// 一番左にスプレッドシートを作成、名称はYYYYMMDD
var objSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
objSpreadsheet.insertSheet(format_str, 0);
// あまり綺麗じゃないんだけど、一番左のシートをアクティブにする
SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].activate();
}
// 開始フォルダの下の全てのフォルダを取得後、全てのファイルを取得
// http://excel-ubara.com/apps_script1/GAS038.html と037を参考にした
function listAllFandF() {
var sheet = SpreadsheetApp.getActiveSheet();
var key = "xxxxxxxxxxxxxxxxxxxxxxxxx"; // 探索を開始するフォルダ(固定してる)
var stt = DriveApp.getFolderById(key);
var name = "";
var i = 0; // 配列の行位置を記録している
var j = 0; // 配列を上から拾って、サブフォルダ探索。探索は配列の二行目から行う
var folderlist = new Array(); //フォルダリストを格納する配列
sheet.clear() //シートをクリア
// 一行目を配列に書き出す(開始フォルダ)
folderlist.push([stt, key]);
// nameに開始フォルダ追加する
name = stt + " > ";
// フォルダリストを配列に書き出す
do {
//フォルダ一覧を取得
var folders = DriveApp.searchFolders("'"+key+"' in parents");
//フォルダ一覧からフォルダを順に取り出し、配列にフォルダ名称とIdを出力
while(folders.hasNext()){
i++;
var folder = folders.next();
var tmparray = new Array();
tmparray.push(name + folder.getName());
tmparray.push(folder.getId());
folderlist.push(tmparray);
}
//配列の上から順にフォルダ名称(>をつける)とIdを取り出す
j++;
// j(配列を取りに行こうとする行数)がi(配列の行数、ゼロから始まる)と同じか小さいなら
if(j <= i){
name = folderlist[j][0] + " > ";
key = folderlist[j][1];
}
} while (j <= i); //配列を最後まで舐める
// folderlist配列(フォルダリスト)を使って、フォルダ下にあるファイルを取得しシートに吐き出し
j = 1; //シートへの出力行
// ヘッダ記入:直書きで汚くて申し訳ない
sheet.getRange(j, 1).setValue("フォルダ");
sheet.getRange(j, 2).setValue("ファイル");
sheet.getRange(j, 3).setValue("作成日");
sheet.getRange(j, 4).setValue("オーナー");
sheet.getRange(j, 5).setValue("URL");
j++;
// ボディ記入
for (i=0; i<=folderlist.length-1; i++) {
var key = DriveApp.getFolderById(folderlist[i][1]).getId();
var files = DriveApp.searchFiles("'"+key+"' in parents");
while(files.hasNext()){
var file = files.next();
sheet.getRange(j, 1).setValue(folderlist[i][0]);
sheet.getRange(j, 2).setValue(file.getName());
sheet.getRange(j, 3).setValue(file.getDateCreated());
sheet.getRange(j, 4).setValue(file.getOwner().getName());
sheet.getRange(j, 5).setValue(file.getUrl());
j++;
}
}
}
解説。ってコメントにほとんど書いちゃったけど
メニューからスクリプト実行できるようにする
// メニューに表示させる
function onOpen(e){
var arr = [
{name: "リスト作成", functionName: "listAllMain"}
];
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.addMenu("スクリプト", arr);
}
なんかまあ、おまじない。
listAllMain関数を呼び出させている。
スクリプトを実行したら、まずは(今日日付の)新シートを作る
// 新シートを挿入、今日日付
function insertNewSheet() {
// 日付取得
var td = new Date();
// YYYYMMDD形式に変換(考えた人、賢いなあ)
var year_str = td.getFullYear();
var month_str = td.getMonth()+ 1; // monthはなんと0-11
var day_str = td.getDate();
month_str = ('0' + month_str).slice(-2);
day_str = ('0' + day_str).slice(-2);
format_str = 'YYYYMMDD';
format_str = format_str.replace(/YYYY/g, year_str);
format_str = format_str.replace(/MM/g, month_str);
format_str = format_str.replace(/DD/g, day_str);
tdに今日の日付を取得して、そこから年月日の文字列を取得。
最後に気づいてギャボーてなったのは、月が0-11であること。
JavaScript、すげ。
月と日を2桁の文字列で取得して、YYYMMDDという文字列に対し置換。
この処理はどこかで見つけたのだけれど、賢いなあ。
// 一番左にスプレッドシートを作成、名称はYYYYMMDD
var objSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
objSpreadsheet.insertSheet(format_str, 0);
// あまり綺麗じゃないんだけど、一番左のシートをアクティブにする
SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].activate();
}
そしてスプレッドシートを作成。
スプレッドシート名称を指定してアクティブにしたかったけど、わからなくて。
不本意ながら、一番左のシートをアクティブにするという邪道な感じ。
そしてフォルダ一覧を配列に取得
大まかには
- フォルダ一覧配列(folderlist)→フォルダ一覧(folders)→フォルダ1つ(folder)
var sheet = SpreadsheetApp.getActiveSheet();
var key = "xxxxxxxxxxxxxxxxxxxxxxxxx"; // 探索を開始するフォルダ(固定してる)
var stt = DriveApp.getFolderById(key);
var name = "";
var i = 0; // 配列の行位置を記録している
var j = 0; // 配列を上から拾って、サブフォルダ探索。探索は配列の二行目から行う
var folderlist = new Array(); //フォルダリストを格納する配列
keyには、探索を開始するフォルダのIdを指定。
汚いんだけれど、固定で入力。
iはfolderlistに何行入っているか(幾つのフォルダを見つけたか)が記録される。
iという変数にするべきではない気がする(けど作ってしまった)。
jはfolderlistから1行ずつ行を拾う時のカウンタになってる。
// 一行目を配列に書き出す(開始フォルダ)
folderlist.push([stt, key]);
// nameに開始フォルダ追加する
name = stt + " > ";
配列の1行目を書く。
// フォルダリストを配列に書き出す
do {
//フォルダ一覧を取得
var folders = DriveApp.searchFolders("'"+key+"' in parents");
//フォルダ一覧からフォルダを順に取り出し、配列にフォルダ名称とIdを出力
while(folders.hasNext()){
i++;
var folder = folders.next();
var tmparray = new Array();
tmparray.push(name + folder.getName());
tmparray.push(folder.getId());
folderlist.push(tmparray);
}
//配列の上から順にフォルダ名称(>をつける)とIdを取り出す
j++;
// j(配列を取りに行こうとする行数)がi(配列の行数、ゼロから始まる)と同じか小さいなら
if(j <= i){
name = folderlist[j][0] + " > ";
key = folderlist[j][1];
}
} while (j <= i); //配列を最後まで舐める
ここが(オリジナルのソースをなかなか読み解けなくて)悩んだ。要は
- 探索開始フォルダの下にあるフォルダを、配列に入れる
- 配列を上から1行取り(1行目はスキップ)、その配列が指しているフォルダの下にあるフォルダを、配列に入れる
- これがややこしい……誰か図で書いてー、ですね
- 配列の次の1行を取り、その配列が指しているフォルダの下にあるフォルダを、配列に入れる
- ということを、配列の終わりまでやる
-
j++;
のタイミングでi > j
になってしまい、エラー(そんな行はない!と言われる)のでif文で回避
-
後は配列を1行ずつ処理して、ファイルリストを吐き出す
// folderlist配列(フォルダリスト)を使って、フォルダ下にあるファイルを取得しシートに吐き出し
j = 1; //シートへの出力行
// ヘッダ記入:直書きで汚くて申し訳ない
sheet.getRange(j, 1).setValue("フォルダ");
sheet.getRange(j, 2).setValue("ファイル");
sheet.getRange(j, 3).setValue("作成日");
sheet.getRange(j, 4).setValue("オーナー");
sheet.getRange(j, 5).setValue("URL");
j++;
ヘッダ行をスプレッドシートに書く。直打ちで汚くて申し訳ない。
// ボディ記入
for (i=0; i<=folderlist.length-1; i++) {
var key = DriveApp.getFolderById(folderlist[i][1]).getId();
var files = DriveApp.searchFiles("'"+key+"' in parents");
while(files.hasNext()){
var file = files.next();
sheet.getRange(j, 1).setValue(folderlist[i][0]);
sheet.getRange(j, 2).setValue(file.getName());
sheet.getRange(j, 3).setValue(file.getDateCreated());
sheet.getRange(j, 4).setValue(file.getOwner().getName());
sheet.getRange(j, 5).setValue(file.getUrl());
j++;
}
}
- folderlistから1行取り出し、
- そのフォルダの下にあるファイルを全部取得し、
- スプレッドシートに書く。
の繰り返し。
スピード
だいたい500ファイル弱で、5分ぐらいかかっているような気がする(気分)。
参考にしたサイト
http://excel-ubara.com/apps_script1/GAS037.html
http://excel-ubara.com/apps_script1/GAS038.html
最初、GAS038にコードが載っていて、こりゃあ良いやと思って使ってみたところ、
思った通りに動かずスタック。
GAS037に立ち戻って、コードをあれこれ書き直して動くようにしてみた。
パズルー。