1. はじめに
この Codelab の目標は、Cloud Storage への CSV ファイルのアップロードに応答する Cloud Functions の関数を作成し、その内容を読み取り、Sheets API を使用して Google スプレッドシートを更新する方法を理解することです。
これは、通常は手動で「CSV としてインポート」する自動化とみなすことができます。示します。これにより、データが利用可能になり次第、スプレッドシートでデータ(別のチームが作成したもの)をすぐに分析できるようになります。
実装は次のようになります。
2. 設定と要件
セルフペース型の環境設定
- Cloud Console にログインし、新しいプロジェクトを作成するか、既存のプロジェクトを再利用します(Gmail アカウントまたは G Suite アカウントをお持ちでない場合は、アカウントを作成する必要があります)。
プロジェクト ID を忘れないようにしてください。プロジェクト ID はすべての Google Cloud プロジェクトを通じて一意の名前にする必要があります(上記の名前はすでに使用されているので使用できません)。以降、このコードラボでは PROJECT_ID
と呼びます。
- 次に、Google Cloud リソースを使用するために、Cloud Console で課金を有効にする必要があります。
このコードラボを実行しても、費用はほとんどかからないはずです。このチュートリアル以外で請求が発生しないように、リソースのシャットダウン方法を説明する「クリーンアップ」セクションの手順に従うようにしてください。Google Cloud の新規ユーザーは、300 米ドル分の無料トライアル プログラムをご利用いただけます。
3. Google スプレッドシートを作成して構成し、API を有効にする
まず、新しいスプレッドシート ドキュメントを作成します(このシートはどのユーザーにも属すことができます)。作成したら、ID を覚えておきます。作成する関数の環境変数として使用されます。
GCP Console の [API とサービス] に移動し、新しく作成したプロジェクトで Google Sheets API を有効にします。[API ライブラリ]をセクション :
[IAM と管理者」[サービス アカウント] に移動してApp Engine のデフォルトのサービス アカウントのメールアドレスをメモします。形式は your-project-id@appspot.gserviceaccount.com
です。もちろん、このアクション専用の独自のサービス アカウントを作成することもできます。
最後に、[Share] を使用して、このサービス アカウントにスプレッドシートの編集権限を付与します。ボタン :
この設定では、Cloud Functions の関数を記述し、このサービス アカウントを使用するように構成します。これにより、先ほど作成したスプレッドシート ドキュメントに書き込むことができます。
4. Storage バケットを作成する
Cloud Functions の関数が新しい CSV ファイルをモニタリングするバケットを作成しましょう。
コンソールで、左側のメニューを使用して [Storage] に移動します。:
次に、csv2sheet-POSTFIX
という新しいバケットを作成します(POSTFIX を一意の名前に置き換えます)。他のすべての設定は、デフォルト値に設定されます。
5. Cloud Functions の関数を作成する
これで、特定の Cloud Storage バケットへのファイルのアップロードでトリガーされる csv2sheet
という Cloud Functions の関数を作成できます。Node.js 8 でコードを記述する場合、Cloud コンソールのインライン エディタで直接非同期関数を使用します。
トリガーを「Cloud Storage」に設定してくださいバケット名を前のステップで作成したものに変更します。
また、csv2sheet
に書き込む関数のエントリポイントも更新します。
次に、関数本体を に変更します。
- Cloud Storage と Sheets API を
csv2sheet
関数をasync
としてマークします。- Cloud Storage イベント メタデータから
fileName
を取得し、作成する新しいシートの名前を取得します。
const {google} = require("googleapis");
const {Storage} = require("@google-cloud/storage")
exports.csv2sheet = async (data, context) => {
var fileName = data.name;
// basic check that this is a *.csv file, etc...
if (!fileName.endsWith(".csv")) {
console.log("Not a .csv file, ignoring.");
return;
}
// define name of new sheet
const sheetName = fileName.slice(0, -4);
// TODO!
};
ここでの async
は、後ほど説明するように await
を使用するために必要です。
この関数を作成する際、重要なオプションには次のようなものがあります(画面下部にある [詳細] リンクをクリック)。
- プルダウンを使用して、上記のサービス アカウントを選択します
SPREADSHEET_ID
という環境変数を定義します。これは、前に作成したスプレッドシート ドキュメントと一致する必要があります。
最後の設定ステップとして、package.json
のコンテンツに Cloud Storage と Google Sheet API の 2 つの依存関係を指定します(コンソールのインライン エディタの PACKAGE.JSON タブを使用します)。
{
"name": "csv2sheet",
"version": "0.0.42",
"dependencies": {
"googleapis": "^51.0.0",
"@google-cloud/storage": "^5.0.1"
}
}
説明どおりにすべて設定したら [作成]をクリックします!1 分後に関数が作成され、デプロイされます。
6. 認証と Sheets API を設定する
インライン エディタを使用して Cloud Functions の関数でさらにコードを記述する前に、適切な Storage スコープとスプレッドシート スコープで Google Client API の作成をブロックする必要があります(これは async
関数の一部です)。
コンソールの関数エディタで、[編集] をクリックします。csv2sheet
関数の本文に次のコードを追加します。
// block on auth + getting the sheets API object
const auth = await google.auth.getClient({
scopes: [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/devstorage.read_only"
]
});
そこから Sheets API クライアントを作成できます。
const sheetsAPI = google.sheets({version: 'v4', auth});
7. Sheets API を使用して空のシートを作成する
Sheets API クライアントを使用すると、ドキュメント内にシンプルな新しいシートを作成できますが、先に進む前に、用語について簡単に触れておきます。
- スプレッドシートは実際のドキュメントであり、その識別子(上記で説明。ドキュメントの URL に表示されます)で参照されます。
- シートはドキュメント内のタブの 1 つで、名前(タブ名)またはシートの作成時に生成された識別子で参照できます。
これを念頭に置いて、次の関数では、Sheets API クライアントを使用して、26 列、2,000 行の空のシートを 2 番目(通常はデフォルトの「Sheet1」の後)に作成し、最初の行を固定します(インライン エディタを使用して関数に追加します)。
function addEmptySheet(sheetsAPI, sheetName) {
return new Promise((resolve, reject) => {
const emptySheetParams = {
spreadsheetId: process.env.SPREADSHEET_ID,
resource: {
requests: [
{
addSheet: {
properties: {
title: sheetName,
index: 1,
gridProperties: {
rowCount: 2000,
columnCount: 26,
frozenRowCount: 1
}
}
}
}
]
}
};
sheetsAPI.spreadsheets.batchUpdate( emptySheetParams, function(err, response) {
if (err) {
reject("The Sheets API returned an error: " + err);
} else {
const sheetId = response.data.replies[0].addSheet.properties.sheetId;
console.log("Created empty sheet: " + sheetId);
resolve(sheetId);
}
}
);
});
}
スプレッドシートへの参照をハードコードする代わりに、以前に作成した SPREADSHEET_ID
環境変数を使用していることに注意してください。
この特定のシートに対する以降のリクエストのために、sheetId
を記憶する必要があります。また、シート名は一意である必要があり、sheetName
という名前のシートがすでに存在する場合は作成に失敗します。
Sheets API の batchUpdate
関数はドキュメントを操作する一般的な方法です。詳しくはこちらをご覧ください。
8. ストレージ CSV ファイルからデータを読み取る
データをダンプする場所ができたので、インライン エディタで Cloud Functions の関数をさらに開発し、Cloud Storage API を使用して、アップロードしたファイルから実際のデータを取得し、文字列に保存します。
function readCSVContent(sheetsAPI, file, sheetName) {
return new Promise((resolve, reject) => {
const storage = new Storage();
let fileContents = new Buffer('');
storage.bucket(file.bucket).file(file.name).createReadStream()
.on('error', function(err) {
reject('The Storage API returned an error: ' + err);
})
.on('data', function(chunk) {
fileContents = Buffer.concat([fileContents, chunk]);
})
.on('end', function() {
let content = fileContents.toString('utf8');
console.log("CSV content read as string : " + content );
resolve(content);
});
});
}
9. 新しく作成したシートにデータを入力する
次に、同じ Sheet Client API と先ほど収集したデータを使用して、作成したシートにデータを入力します。これを機に、シートの列にスタイルも追加します(最上段のフォントサイズを変更して、太字にします)。
function populateAndStyle(sheetsAPI, theData, sheetId) {
return new Promise((resolve, reject) => {
// Using 'batchUpdate' allows for multiple 'requests' to be sent in a single batch.
// Populate the sheet referenced by its ID with the data received (a CSV string)
// Style: set first row font size to 11 and to Bold. Exercise left for the reader: resize columns
const dataAndStyle = {
spreadsheetId: process.env.SPREADSHEET_ID,
resource: {
requests: [
{
pasteData: {
coordinate: {
sheetId: sheetId,
rowIndex: 0,
columnIndex: 0
},
data: theData,
delimiter: ","
}
},
{
repeatCell: {
range: {
sheetId: sheetId,
startRowIndex: 0,
endRowIndex: 1
},
cell: {
userEnteredFormat: {
textFormat: {
fontSize: 11,
bold: true
}
}
},
fields: "userEnteredFormat(textFormat)"
}
}
]
}
};
sheetsAPI.spreadsheets.batchUpdate(dataAndStyle, function(err, response) {
if (err) {
reject("The Sheets API returned an error: " + err);
} else {
console.log(sheetId + " sheet populated with " + theData.length + " rows and column style set.");
resolve();
}
});
});
}
このコードを Cloud Functions に追加すると、99% 完了です。
データとスタイル設定の両方が複数の requests
として 1 つの Sheets API の batchUpdate
呼び出しに統合されている点に注目してください。これにより、より効率的でアトミックな更新が可能になります。
また、作成したシートのサイズと一致する編集範囲も定義しています。つまり、26 列(シートの作成時に使用された columnCount
値)を超えるコンテンツは、この特定のコードでは失敗します。
問題がなければ、以下を行うことができます。
- 更新した関数を保存する
- バケットに CSV ファイルをドロップします。
- スプレッドシートに対応するデータがポップアップ表示されます。
10. すべてを組み合わせてフローをテストする
先ほど説明した関数の呼び出しは、元の csv2sheet
関数で連続したブロッキング呼び出しとして実行できます。
const sheetId = await addEmptySheet(sheetsAPI, sheetName);
const theData = await readCSVContent(sheetsAPI, data, sheetName);
await populateAndStyle(sheetsAPI, theData, sheetId);
関数のソースコード全体が必要な場合は、こちらから入手できます(すべてを 1 セットにまとめた方が簡単でしょう)。
すべてを整えたら、CSV ファイルを適切なバケットにアップロードし、スプレッドシートがファイルのコンテンツを含む新しいシートに更新されるのを確認します。お手元にない場合は、CSV ファイルのサンプルをご利用ください。
バケットに複数のファイルをアップロードして、どうなるか見てみましょう。
11. これで、インフラストラクチャを破棄する時間
冗談です。破棄するためのインフラストラクチャはありません。すべてサーバーレスで行われています。
必要に応じて、Cloud Functions の関数と作成したバケット、またはプロジェクト全体を削除できます。
12. 次のステップ
この Codelab は終了です。適切な API を使用して Google スプレッドシートを更新するため、Cloud Functions の関数で Cloud Storage バケットへのアップロードをリッスンする手順を説明します。
フォローアップ情報として以下をご確認ください。
- Cloud Functions の入門ガイドを確認する(ベスト プラクティスを含む)
- Cloud Functions のチュートリアルの 1 つを使用する。
- Google Sheets API を見る
この Codelab で問題が発生した場合は、左下にあるリンクを使用してお気軽にお知らせください。
フィードバックの提供にご協力をお願いいたします。