この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
社内で利用するシステムを作成するにあたり、Google スプレッドシートにあるデータを CSV 形式に変換して S3 にアップロードする処理の作成を依頼されたため、 タイトルにある Google Apps Script から AWS SDK for JavaScript を使って S3 にデータをアップロードしてみました。 なお前提として筆者は、Google Apps Script も JavaScript も初心者であるため、掲載されたコードにいけてない部分があったとしてもご容赦ください。 拙いソースコードではありますが、どこかで同じように困っている誰かの役に立てれば幸いです。
前提条件
- 特定のスプレッドシートでしか利用しないため、Google Apps Script は Container-bound とする
- Google スプレッドシートへのアクセスに既に認証機構があるため、スクリプト側では "accessKeyId" および "secretAccessKey" をハードコーディングしている
- オブジェクトをアップロードする S3 Bucket に対して CORS の設定が行われていること(参考情報:ブラウザの JavaScript)
- 指定バケットへオブジェクトアップロード権限が与えられた IAM ユーザーの「アクセスキーID」と「シークレットアクセスキー」を取得済みであること
- 同僚から教えて貰った GitHub の情報 (Cannot load SDK into Google Apps Script · Issue #620 · aws/aws-sdk-js)を参考とした
実装
- 以下、コード.gs のソースコードを示します。
var app = SpreadsheetApp;
function onOpen(e){
showContentApp();
}
function showContentApp(){
var html = HtmlService.createHtmlOutputFromFile('sample').setWidth(100).setHeight(100);
app.getActiveSpreadsheet().show(html);
}
function getSpreadsheetData(){
// スクリプトが紐付いているスプレッドシートの参照を取得
var ss = SpreadsheetApp.getActiveSpreadsheet();
// スクリプト実行時にアクティブなシートの参照を取得
var sheet = ss.getActiveSheet();
// データを取得 getRange(行番号,列番号,範囲の行数,列数) A1:B3000
var data = sheet.getRange(1,1,3000,2).getValues();
return data;
}
onOpen() が呼ばれると、showContentApp() 内で、sample.html が読み込まれ以下のイメージにある Upload S3 ボタンが含まれたウィンドウが表示されます。 getSpreadsheetData() は、sample.html 内から呼ばれる関数でありコメントに記載のとおり A1 から B3000 までのセルの範囲に含まれるデータ(Array の2次元配列)が返ります。
入力データは、イメージ内に表示されているとおり "ID" と "メールアドレス" です。
- 以下、sample.html のソースコードを示します。
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.122.0.min.js"></script>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script type="text/javascript">//<![CDATA[
$(function()
{
$("#btn").on('click', function()
{
AWS.config.region = 'ap-northeast-1';
AWS.config.maxRetries = 3;
AWS.config.update({
accessKeyId: 'ID',
secretAccessKey: 'KEY'
});
// Create S3 object
var s3 = new AWS.S3();
// getSpreadsheetData SuccessHandler
function onSuccess(body){
if( !body ) return;
var csv = '';
var count = body.length;
// convert Array object to string (CSV format)
for(var i=0;i<count;i++){
csv += '"' + body[i].join('","') + '"\n';
}
// Create S3 putObject params
var params = {
Bucket: 'test',
Key: "test.csv",
Body: csv
};
s3.putObject(params, function(err, data)
{
if(err)
{
console.dir(err);
console.log('Request ID:', data.RequestId);
$("#status").html("Error");
}
$("#status").html("Success");
});
} // End of onSuccess()
// getSpreadsheetData FailureHandler
function onFailure(e){
console.log(e, 'getSpreadsheetData()');
} // End of onFailure()
// execute getSpreadsheetData function in コード.gs
google.script.run.withSuccessHandler(onSuccess).withFailureHandler(onFailure).getSpreadsheetData();
});
});
//]]></script>
<button id="btn">Upload S3</button>
<p></p>
<div id="status"></div>
HTML 内で、AWS SDK for JavaScript(aws-sdk-2.122.0.min.js)を読み込んでいます。 ウィンドウ内の Upload S3 ボタンをクリックすると S3 オブジェクトが作成されます。次にコード.gs 内の getSpreadsheetData() が非同期で呼び出され 関数の処理が成功しデータが返ってきた場合、onSuccess() が実行されます。スプレッドシートの行数回だけデータを展開し、CSV のフォーマットに変換した String を組み立てます。 データが作成されたら S3 の putObject() を呼び出し CSV データを送信します。処理が成功すれば、ボタン下に "Success" を表示します。
S3 に転送された CSV データは、以下のとおりです。
"id1","id1@example.com"
"id2","id2@example.com"
"id3","id3@example.com"
"id4","id4@example.com"
"id5","id5@example.com"
"id6","id6@example.com"
期待した通りに CSV データが、S3 へアップロードされました。
さいごに
「はじめに」でもお伝えしましたが、筆者は、Google Apps Script も JavaScript も初心者です。 Google Apps Script は人生初のコーディングで、JavaScript は少し触ったことがある程度です。 掲載しているコードは、まだまだ改善の余地があることは重々承知の上で、思い切って公開してみました。 繰り返しとなりますが、どこかで同じように困っている誰かの役に立てれば幸いです。
参考情報
- Class: AWS.S3 — AWS SDK for JavaScript
- Container-bound Scripts | Apps Script | Google Developers
- Class google.script.run (Client-side API) | Apps Script | Google Developers
- Libraries | Apps Script | Google Developers
- [Google Apps Script]スプレッドシート上にウィンドウを表示する | 初心者備忘録 #HTML ファイルを読み込み、ウィンドウを表示する部分のコードを参考にさせて頂きました。
ではでは