GASとスプレッドシートでFirestoreにドキュメントID指定でデータを流し込む関数を作る

## はじめに

この記事は下記の記事を参考（ほぼコピペ）に書いたコードから
ドキュメントIDを指定してデータを流し込もむコードに修正するコードを書くだけの記事です。

基本的なやり方は下記を御覧ください。
[Firestoreのテストデータ投入をGASで楽にする](https://qiita.com/pro_matuzaki/items/f6d43ff18f970f906357)

## ドキュメントID指定

下記のコードは [Firestoreのテストデータ投入をGASで楽にする](https://qiita.com/pro_matuzaki/items/f6d43ff18f970f906357) を参考に下準備が完了している前提でコードを書いていきます。

### 要点

1. スプレッドシートに`docId`という項目を他のフィールドと同様に指定する（型はstringでいい）
2. `var docId = data.docId || ''`で指定がアレば変数に入れる
3. `if(docId != '') {}`の中で`docId`が指定されている場合の処理を書く
4. フィールドに`docId`が不要であれば削除する`delete data.docId`
5. `{コレクション名}/{ドキュメントID}`になる変数を作り`firestore.createDocument();`の第一引数に入れる

### ソースコード

```js
// カラム名定義
var FIELD_ROW_START = 1;
var FIELD_COL_START = 1;
// 型
var FIELD_TYPE_ROW = 2;
// データの開始行・列
var DATA_ROW_START = 3;
var DATA_COL_START = 1;

// フィールド情報key
var KEY_I_NAME = 'implName'; //実装名
var KEY_TYPE = 'type'; // 型

// 対象シート
var SHEET = "Users";

function myFunction() {
  // firestore接続情報
  var email = "(dlしたJSONにあるclient_emailの値)";
  var key = "(dlしたJSONにあるprivate_keyの値。-----BEGIN PRIVATE KEY-～END PRIVATE KEY-----\nまで全部入れます)";
  var projectId = "(dlしたJSONにあるproject_idの値)";

  // 対象シート
  var sheet = getSheet(SHEET);
  // コレクション名=シート名とする
  var collectionName = sheet.getName();

  // 入力データ領域でループ
  var rowEnd = sheet.getDataRange().getLastRow();

  for(var i = 0; i <= rowEnd - DATA_ROW_START; i++) {
    // 一行ずつ読み込み&登録
    var data =  buildOneRecord(sheet, i);
    // docIdが無ければ自動生成
    var docId = data.docId || '';

    var firestore = FirestoreApp.getFirestore(email, key, projectId);
    var path="";
    if(docId != '') {
      // docId指定の時は「コレクション/{docId}」になるようにする
      path = "/" + docId;
      // フィールドにdocIdが不要であれば連想配列から削除する
      delete data.docId
    }
    // 1レコード登録
    firestore.createDocument(collectionName + path, data);
  }
}

/**
* 1レコードの読み込み
* sheet : 対象シート
* dataNumber: 取り込みデータの行インクリメント数
*/
function buildOneRecord(sheet, dataNumber) {

  // データ領域の最終列
  var colEnd = sheet.getDataRange().getLastColumn();

  var ret = {};
  //フィールド情報を取得しておく
  var fields = getFieldsInfo(sheet);
  Logger.log(dataNumber);
  //一括で読み込み
  var rec = sheet.getSheetValues(DATA_ROW_START + dataNumber, DATA_COL_START, 1, colEnd - DATA_COL_START + 1);
  Logger.log(rec);
  var r = {}
  for(var i = 0; i < fields.length; i++){
    var field = fields[i];
    if(field[KEY_TYPE] == 'array') { 
      // TODO:配列の時
      // 
    } else if(field[KEY_TYPE] == 'map') {
      // TODO:mapの時
      //
    } else if(rec[0][i] && rec[0][i] != '') {
      // その他の場合は値があるもののみ格納する 
      r[field[KEY_I_NAME]] = rec[0][i];;
    }
  }
  return r;
}

/**
* フィールド情報を取得する
* @sheet: シート
*/
function getFieldsInfo(sheet) {
  var colEnd = sheet.getDataRange().getLastColumn();
  var fields = sheet.getSheetValues(FIELD_ROW_START, FIELD_COL_START, FIELD_TYPE_ROW - FIELD_ROW_START + 1, colEnd);

  var f = [];
  for(var i = 0; i < fields[0].length; i++) {
    var logicalName = null;
    var implName = null;
    var type = null;

    if(fields[0][i] != '') {
      // フィールド名
      fieldName = fields[0][i];
      // 型
      fieldType = fields[1][i];

      // 戻り値用値の整形
      var m = {}
      m[KEY_I_NAME] = fieldName;
      m[KEY_TYPE] = fieldType;
      f.push(m);
    }
  }
  return f;
}

/**
* 処理対象のシートを取得する
* @sheetName: 対象シート名
*/
function getSheet(sheetName) {
  if(getSheet.sheet) { return getSheet.sheet; }
  getSheet.sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); 
  return getSheet.sheet;
}
```