📑

[Swift]スプレッドシートのデータをJSONに書き出して読み込む[gas]

2022/02/01に公開

概要

本題の通りスプレッドシートで管理しているデータをJSONで書き出し、プロジェクト内で読み込み、使用する方法をご紹介します。
エクセルやスプレッドシートでデータを管理していて、そのデータを元にアプリの開発をしたい場合などに有効かと思います。

概要は以下の通りです。
・スプレッドシートのデータをJSONに書き出す
・JSONファイルをXcodeにインポート
・JSONファイルを読み込み画面に表示させる

環境

・ macOS: Monterey
・ Xcode: 13.2

スプレッドシートのデータをJSONに書き出す

GASを使用して書き出します。

GASとはGoogle Apps Scriptの略です。以下公式より引用。
Apps Script は、Google Workspace の統合、自動化、拡張のためのビジネス ソリューションをすばやく簡単に構築するための唯一のローコード プラットフォームです。Apps Script を使えば、ビジネス ユーザーは本格的なソフトウェア開発の経験がなくても、Google Workspace 上にカスタム ソリューションを構築できます。Apps Script は、Gmail アカウントをお持ちであればどなたでもご利用いただけます。

Goodleのアカウントを持っていれば誰でも無料で使用する事ができます。
※もっと詳細を知りたい方は公式をどうぞ

今回はスプレッドシートから使用していきます。

以下手順+コード

データのあるスプレッドシートから拡張機能内にあるApps Scriptを選択します。

無題のプロジェクトが作られるので適当にプロジェクト名を付けます。
(初期画面)

今回はgs以外にHTMLも使用しますのでファイルを追加するボタンから追加していきます。

それぞれのコードは以下のように書いていきます。

toJSON.gs
//ダウンロードダイヤログ表示
function toJSON() {
  //ダイヤログテンプレート読み込み
  var dl_html = HtmlService.createTemplateFromFile("dl_dialog").evaluate();

  //ダイヤログ表示
  SpreadsheetApp.getUi().showModalDialog(dl_html, "JSONファイルをダウンロード");
}

//データ取得
function getData() {  
  //データ取得するシート(現在開いているシートを指定)
  var sheet = SpreadsheetApp.getActiveSheet();

  //行(横軸)と列(縦軸)の最大数を取得
  var maxRow = sheet.getLastRow();
  var maxColumn = sheet.getLastColumn();

  //JSON用のkey
  var keys = [];

  //データ格納配列
  var data = [];

  //2行目のkeyの名前取得
  //1行目は管理しやすいよう日本語で記述し、
  //JSON用のラベルは2行目で指定しているため
  //【getRange】の第1引数は【2】
  for (var x = 1; x <= maxColumn; x++) {
    keys.push(sheet.getRange(2, x).getValue());
  }
  
  //データの取得
  //実際のデータが3行目からなので【y = 3】から開始
  //getRange()を使って、3行目1セル ~ 最終行目の最終セルを範囲指定
  //maxRowは入力されているセルをカウントしているので必要でないセル2を引く
  var _values = sheet.getRange(3, 1, maxRow - 2, maxColumn).getValues();
  
  for(var i = 0; i < _values.length; i++){
    var json = {};
    for (var k = 0; k < _values[i].length; k++) {
      json[keys[k]] = _values[i][k];
    }
    data.push(json);
  }

  //整形してテキストにする
  return JSON.stringify(data , null, '\t');  
}
//スプレッドシート読み込み時に実行
function onOpen() {
  //メニューバーにJSON出力用メニューを追加
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "JSONで出力",
    functionName : "toJSON"
  }];
  spreadsheet.addMenu("JSON", entries);
};
dl_dialog.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script type='text/javascript'>
      //ダウンロード実行
      function handleDownload() {
        //JSONデータの取得
        var content = <?= getData(); ?>;
        //ダウンロード用URL生成
        var blob = new Blob([ content ], { "type" : "application/json"});
        document.getElementById("download").href = window.URL.createObjectURL(blob);
      }
  </script>
  </head>
  <body>
    <!-- JSONダウンロードボタン:json名は適宜設定してください-->
    <a id="download" href="#" download="JSONData.json" onclick="handleDownload()">ダウンロード</a>
  </body>
</html>

コードが書けたら(コピペで問題ないです)保存して実行します。
すると承認を求めてきますので、権限を確認を選択します。

使用したいアカウントを選択します。

警告がでるので詳細を選択します。

赤枠で囲んである部分を選択します。(プロジェクト名が表示されます)

許可をするとJSONファイルをDLできるようになります。

JSONファイルをXcodeにインポート

DLしたJSONファイルをインポートしていきます。ファイルをドラッグ&ドロップするだけです。
完了すると以下のようにファイルが追加された事を確認できます。

JSONファイルを読み込み画面に表示させる

読み込んだJSONファイルを表示させます。

UserData
class UserData: Codable {
    var id: Int
    var name: String
    var age: Int
    var category: Int
}
JSONLoad
class JSONLoad: ObservableObject {
    
    @Published var users: [UserData] = load("JSONData")
    
}

func load<T: Decodable>(_ filename: String) -> T {
    let data: Data
    //プロジェクト内にあるJSONファイルのパスを取得
    guard let file = Bundle.main.url(forResource: filename, withExtension: "json")
    else {
        fatalError("ファイルが見つかりません:\(filename)")
    }
    //JSONのデータを読み込む
    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("読み込みに失敗しました:\(filename) \nerror:\(error)")
    }
    //Decode処理
    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("JSONを読み込む事ができませんでした: \nerror:\(error)")
    }
}

View
struct ContentView: View {
    @ObservedObject var jsonViewModel = JSONLoad()
    var body: some View {
        VStack {
            Text("JSON Loader")
            List {
                ForEach(0..<jsonViewModel.users.count) { num in
                    HStack {
                        Text("ID:\(jsonViewModel.users[num].id)")
                        Text("Name:\(jsonViewModel.users[num].name)")
                        Text("Age:\(jsonViewModel.users[num].age)")
                        Text("Category:\(jsonViewModel.users[num].category)")
                    }
                    .font(.system(size: 15))
                }
            }
        }
    }
}

完成画面

まとめ

JSON読み込む勉強になった。笑
ローカルで大量のデータを使用したい場合は便利かと^^

Discussion