Googleフォームの回答ファイルを共有ドライブに保存(移動)させたい!/GAS(業務の話)
業務でGoogleツールに
お世話になることが多い今日この頃。
メールからチャットからカレンダー、
スプレッドシートにフォーム、ドライブ...
ある日とうとうGoogleAppsScript
(プログラミング)に手を出さなければならない
日が来てしまいました。
きっかけは、Googleフォームに送ってもらった
ファイルを共有ドライブに保存しなければ
ならなくなったこと。
フォームの回答は、テキストだけなら
書き出すスプレッドシートを共有ドライブに
用意しておけばよかったのですが、
ファイルは必ずマイドライブにしか入らず...
フォーム送信と同時に
共有ドライブに移動させるという
プログラムを書かないといけなくなりました。
エンジニアは周りに何人もいるんですが、
みんな定常業務に追われているので、
自分の勉強も兼ねてチャレンジすることに。
やったこと
・スプレッドシートに書き出されたフォームの一番新しい回答(テキスト)を、別途新たにスプレッドシートを生成して転記、ファイル(スプレッドシート)を共有ドライブに移動
・アップロードしてもらったファイルのIDを、回答が書き出されたスプレッドシートから切り出して取得、そのファイルを共有ドライブに移動
紆余曲折あり、結局
・回答は、予めスプレッドシート上で
関数を使い、新しい順&縦横入れ替えで
並べ替えておく
↓
その範囲で新スプレッドシート作って転記、
移動
・ファイルはスプレッドシートに書き出された
リンクからID取得して移動
っていう手段で解決しました。
function autoCreateSheet(){
const sheetId="スプレッドシートのID";
const sheet=SpreadsheetApp.openById(sheetId);
//シート範囲取得
const rangeValue=sheet.getRange('新しい順!A1:B27').getDisplayValues();
//送信者氏名取得
const name=sheet.getRange('新しい順!B3').getDisplayValue();
//新シート作成
const newSheet=SpreadsheetApp.create(name);
const newSheetRange=newSheet.getRange('A1:B27').setValues(rangeValue);
const newSheetId=newSheet.getId();
//移動先フォルダ
const toFolderId='移動先フォルダのID';
const toFolder=DriveApp.getFolderById(toFolderId);
const personalFile=DriveApp.getFileById(newSheetId);
personalFile.moveTo(toFolder);
//ファイル移動
const frontUrl=sheet.getRange('新しい順!B26').getDisplayValue();
const index="=";
const frontIdSeparate=frontUrl.split(index);
const frontId=frontIdSeparate[1];
const frontFile=DriveApp.getFileById(frontId).setName((name)+"【表】");
frontFile.moveTo(toFolder);
const backUrl=sheet.getRange('新しい順!B27').getDisplayValue();
const backIdSeparate=backUrl.split(index);
const backId=backIdSeparate[1];
const backFile=DriveApp.getFileById(backId).setName((name)+"【裏】");
backFile.moveTo(toFolder);
}
最初に
プログラムは、回答を書き出されるスプレッドシートから
拡張機能>AppsScript
を開いて書きました。
そして、回答ごとにnewスプレッドシートを
生成した理由なんですが...
そもそもフォームの回答は、
あくまで入力してもらった情報。
その後変更があっても、直接いじることはできないので、
データ保管には使えません...
でもそれだととんでもなく不便なので、
変更/修正できるようにしたってところです。
どのみちフォーム送信時、一番新しい情報を書き出したいので、
スプレッドシート上で先に新しい順に並べ替え、
ついでに見やすいように縦横並べ替えた状態で、
そのまま新シートに転記するようにしました。
スプレッドシート上の関数は、
=TRANSPOSE(sort('回答'!A2:AA,1,false))
sortでタイムスタンプ順に並べ替え、
基準になるタイムスタンプは1列目なので1、falseは降順。
TRANSPOSEで行と列の縦横を逆に。
(A2:AAのところは任意の範囲で!)
多分getLastRowとか使って
最終行取得とかでできなくもないですが、
フォームの回答って横に羅列されて長くなって
結局見づらいじゃないですか。
ってことで先にスプレッドシートを
細工するっていう手段に出ました。
そしたら、プログラム上では毎回
同じ範囲を取得すればよいので
難しいことを考えなくてよい。
初心者なのでこのくらい
ハードルを下げて挑戦しました。
IDからスプレッドシートを取得
const sheetId="スプレッドシートのID";
const sheet=SpreadsheetApp.openById(sheetId);
スプレッドシートを開いていない時に
動いてほしいプログラムなので
(もはやいちいち開きたくない)、
アクティブなシート取得ではなく、
IDから絶対的に取得させます。
スプレッドシートのIDは、
開いて表示されている時のリンクを見て、
sheet/d/の先から、/editまでのスラッシュの間です。
(伝えづらい!!)
docs.google.com/spreadsheets/d/AsdfghJklZxcvbNmQwertYuiopAsdfghjkl/edit#gid=123123123
↑のマーカーついてるとこです。
(値はダミーです)
const sheetId='AsdfghJklZxcvbNmQwertYuiopAsdfghjkl';
で、これからsheetIdって言えばこれだよ!と宣言。
SpreadsheetApp.openByIdで、
宣言したIDからスプレッドシートを取得。
//シート範囲取得
const rangeValue=sheet.getRange('新しい順!A1:B27').getDisplayValues();
「sheet」が取得したスプレッドシート
(Spreadsheetオブジェクト)になります。
スプレッドシートの中の、
取得したい範囲(=あとで書き出したい範囲)を
getRange('シート名!範囲:範囲')
で取得。
そこに表示されてるテキストを取得したいので、
getDisplayValue()
一個ずつ宣言しながら書いてたんですが、
長くなっちゃったので.(ドット)でつないで
少しだけ短くしました。
ここから先は、rangeValueと言われたら、
一番新しい、あとで書き出したい情報の
テキストたちのことです。
//送信者名取得
const name=sheet.getRange('新しい順!B3').getDisplayValue();
これは普通に入力してもらったテキストを
取得しているだけです。
後で作ったスプレッドシートや、
送信してもらったファイルに
入力してもらった名前を付けたくて
取得しています。
送信されたファイルには、
googleアカウントの名前がついてくれるんですが、
本名と一致しなかったり、その後何かと
不便が生じたので、統一をはかった次第です。
ここから先は、nameと言われたら
入力してもらった名前のことです。
//新シート作成
const newSheet=SpreadsheetApp.create(name);
const newSheetRange=newSheet.getRange('A1:B27').setValues(rangeValue);
const newSheetId=newSheet.getId();
SpreadsheetApp.create(name)
”name”のところには任意の名前をつけられ、
テキストで指定する場合は””でくくります。
私は入力してもらった名前をそれぞれつけたかったので、
一個前で取得したnameを使いました。
そして、書き出したい範囲として取得したのと
同じ範囲を指定、
元の回答書き出しシートで
取得していたテキストをsetValues(rangeValue)で
新しいシートに転記します。
あとで共有ドライブに移動させたいので、
ついでにIDも「getId()」で取得しておきます。
ここから先は、「newSheetId」と言われたら
新しく作って情報書き出したスプレッドシートの
IDだよってことになりました。
//移動先フォルダ
const toFolderId='移動先フォルダのID';
const toFolder=DriveApp.getFolderById(toFolderId);
const personalFile=DriveApp.getFileById(newSheetId);
personalFile.moveTo(toFolder);
作ったシートや、送信してもらったファイルを
移動させる先の共有ドライブフォルダを宣言して、
さっき作った新しいスプレッドシートを
移動させています。
フォルダの取得も、考え方は最初にIDから
スプレッドシートを取得したときとおんなじ。
フォルダのIDは、フォルダを開いて、
表示されているリンクのfolders/
から先です。
toFolderIdと言われたら、
フォルダのIDだよってことにして、
それをもとにgetFolderById(toFolderId)で
移動先のフォルダを取得。
そいつをtoFolderと呼ぶことにします。
さっき作ったスプレッドシートのIDを
newSheetIdにしておいたので、それをもとに
getFileById(newSheetId)で新しくできたやつを取得、
personalFileと呼ぶことにします。
それをmoveTo(toFolder)でフォルダに移動。
toFolderは移動先のフォルダでしたね。
//ファイル移動
const frontUrl=sheet.getRange('新しい順!B26').getDisplayValue();
const index="=";
const frontIdSeparate=frontUrl.split(index);
const frontId=frontIdSeparate[1];
const frontFile=DriveApp.getFileById(frontId).setName((name)+"【表】");
frontFile.moveTo(toFolder);
フォームの回答にアップロードしてもらった
ファイルも共有ドライブに移動させたいのですが、
これを取得するのにとっても難儀しました。
結局、リンクを書き出されたスプレッドシートから
IDをどうにか抜き出して絶対的に取得、
そいつを移動させる手段で解決しました。
そもそものおなはし、
フォルダやファイルを探して取得するには、
プログラムを書く場所をスプレッドシートからでなく、
マイドライブから新規(+)>その他>AppsScript
から開かないと不可能だったんですが、
それに気づくのに2週間くらいかかりました...
二つアップロードしてもらうので、
同じこと二回書いてます。
まずは、表示されているリンク(テキスト)を
今までと同じように取得。
const frontUrl=sheet.getRange('シート名!セル番号').getDisplayValue();
リンクをfrontUrlと呼ぶことにして、
ひとまず表示されているテキストを
取得しています。
そしてそのリンクをよくよく見ると、
「=」から先がIDになっている...
ここで分割してIDからファイルを
絶対的に取得しようと思います。
まずは目印になる「=」を、
indexと呼ぶことにします。
const index="=";
そしてsplitを使って、二つに分割します。
const frontIdSeparate=frontUrl.split(index);
ほかにsliceとかあったんですが、
それだと「=」まで含まれてしまって
IDだけ切り抜けなかったので、
splitを使いました。
二つに分かれた文字列は、
[0]番目と[1]番目になっていて、
後ろ側が欲しいので[1]だけを指定。
frontIdと呼ぶことにします。
const frontId=frontIdSeparate[1];
あとはそれをもとにして
IDからファイルを絶対的に取得、
作ってたname使って名前を付けて(オプション)
moveToで同じように移動させるだけ。
const frontFile=DriveApp.getFileById(frontId).setName((name)+"【表】");
frontFile.moveTo(toFolder);
てな感じで、入力&アップロードしてもらったものを
共有ドライブに保存(実態は移動)することができました。
こんな書き方で伝わったでしょうか...
まだ繰り返しとか条件分岐とか、
プログラムっぽいプログラムには
手を出していないのでそこまで複雑でないですが、
基本的な考え方は理解できたかな...と思います。
本見てお勉強するより、
実際触って動かした方が身につくので、
是非挑戦しましょう^^
私も他にプログラム化したいものあるので
頑張ります...
ということで、今回はこの辺で!
この記事の投稿者
入社半年の採用アシスタント兼広報担当。
学歴高卒/完全未経験で拾っていただき、日々勉強しながら&調べながら発信中。
とりあえずITパスポートは入社後3週間ちょいで取得済。
最近は開発部門のテスト作業も手伝わせてもらえることに。
趣味は絵(アナログ)とカラオケ(週1~)と自転車(眺める専)、九州の実家には拾った猫3匹&カメ1匹が鎮座。