見出し画像

【Swift5】Googleスプレッドシート(GAS)でセルの情報を取得する/POST通信で更新する【Xcode12】

前回の記事はこちらです。

Googleスプレッドシートのデータを取得する

    static func getShareSheetData(){
       let mainAPIHost: String = "https://script.google.com/macros/s/---/exec" // デプロイしたURLを設定してください。

       var request = URLRequest(url: URL(string: mainAPIHost)!)
       request.httpMethod = "GET"
       let task = URLSession.shared.dataTask(with: request) { data, response, error in
           guard let jsonData = data else { return }

           struct Result: Codable {
               var deckRecipes: [deckRecipe]
           }

           do {
               let deckRecipes = try JSONDecoder().decode(Result.self, from: jsonData)
               DataManager.shared.convertShareDeckModel(list: deckRecipes.deckRecipes)
               print(deckRecipes)
           } catch {
               print(error.localizedDescription)
           }
       }
       task.resume()
   }
   
   struct deckRecipe: Codable {
   var id: String
   var decktitle: String
   var deckrecipeid: String
   var createdate: String
   var memo: String
   var isfav: String
}

ちなみにGoogleスプレッドシートはこのようになっています。

shareDeckRecipeList_-_Google_スプレッドシート

列名(カラム名)がカスタムモデルと対応していますね。

ちなみにGoogleスプレッドシートのスクリプトでは以下のようにGetを書いております。

function doGet(e){
   var result = JSON.stringify({'deckRecipes': getVitalDatas()});
   return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);
}

多分'deckRecipes'がSwift側と一致する必要がありそうです。(エラー起こりまくりでした)

Googleスプレッドシートのデータを更新(追加する)

まずGoogleスプレッドシート側のスクリプトを追加します。


function doPost(e) {
 var jsonString = e.postData.getDataAsString();
 var data = JSON.parse(jsonString);

 var id = data.id;
 var decktitle = data.decktitle;
 var deckrecipeid = data.deckrecipeid;
 var createdate = data.createdate;
 var memo = data.memo;
 var isfav = data.isfav;

 // シート取得
 var ss = SpreadsheetApp.openById(SpreadsheetApp.getActiveSpreadsheet().getId());
 var sheet = ss.getSheetByName("sheets1");
 
 // データ入力
 sheet.appendRow([id, decktitle, deckrecipeid, createdate, memo, isfav]);
}

ちなみに今回は1個でのデータ登録・追加の挙動しかないので、1件ずつの登録・追加を想定しています。(Swiftの送信側で配列で送っているので、多分2件以上の一括登録も行けます)

Swiftでの書き方はこちらです。

func requestAsyncJson(model : DeckModel,
                success: @escaping (Dictionary<String, Any>) -> (), // 通信成功時のクロージャ
                failure: @escaping (Error) -> ()){    // 通信失敗時のクロージャ

       // URLはデプロイしたURLを使ってください。
       guard let url = URL(string: "https://script.google.com/macros/s/---/exec") else {
           return failure(NetworkError.invalidURL)
       }
       var request = URLRequest(url: url)  //Requestを生成
       request.httpMethod = "POST" // 何も設定しないとGETリクエストになるがコードのサンプルのため、明示的に書いている。

       request.addValue("application/json", forHTTPHeaderField: "Content-Type")

       let params:[String:Any] = [
           "id": model.duckRecipeId,
           "decktitle": model.deckTitle,
           "deckrecipeid": model.duckRecipeId,
           "createdate": model.createDate,
           "memo": model.memo,
           "isfav": "OK",
       ]

       request.httpBody = try! JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)

       URLSession.shared.dataTask(with: request, completionHandler: {data , response, error in
           
           if let error = error {
               print(error.localizedDescription)
               failure(error)
               return
           }
           
           guard let data = data,
                 let response = response as? HTTPURLResponse else {
               print("データもしくはレスポンスがnilの状態です")
               failure(NetworkError.unknown)
               return
           }
           
           if response.statusCode == 200 {
               do {
                   // 本当は値を取り出して成否など見るのですが、WebAPI側で返却していないので空のDictを返却しています。
                   // 詳細は後述の記事見てください。
                   let dict: Dictionary<String, Any> = ["isSuccess": "isSuccess"]
                   // コールバックを行う
                   success(dict)
               } catch let error {
                   failure(error)
               }
               
           } else {
               print("statusCode:\(response.statusCode)")
               failure(NetworkError.unknown)
           }
       }).resume()
   }
   

呼び出し側の処理はこうです。

        APIRequest().requestAsyncJson(model: self.deckModel! , success: {(dictionary) in
           // 通信成功時のクロージャ
           print(dictionary)
           self.showAlertView(message: "通信に成功しました。")
        }) { (error) in
           // 通信失敗時のクロージャ
           print(error)
           self.showAlertView(message: "通信に失敗しました。")
        }
        
        

以前書いた記事はこちらです。


いいなと思ったら応援しよう!