[C#]Google Sheets Api(OAuth)でシート作成!

C# C#

google spreadsheet apiを使ってspreadsheetをマイドライブに作ってみたので、

  1. spreadsheetにアクセスするときの種類の説明
  2. google developer consoleでの設定
  3. spreadsheetにapiでアクセスして(OAuth)シートを作成するまで

をまとめてみました。

公式ドキュメントはこちらです。

spreadsheetにアクセスする種類

api keyでアクセス

下記の通り、apiキーでやれることが少ないようなので使うことはあまりなさそうでした。

apiキーでspreadsheet作成…

api keyでspreadsheetが作成できるかと思いましたが、
公式ドキュメント(リクエスト承認)のところを見ると、

アプリケーションがプライベートデータを要求する場合、
その要求は、そのデータへのアクセス権を持つ認証されたユーザーによって承認される必要があります。

アプリケーションが公開データをリクエストする場合、リクエストは承認される必要はありませんが、APIキーなどの識別子を伴う必要があります。

(機械翻訳) 

となっているので、無理そうですね…

ウェブ公開されているspreadsheetならapiキーだけで、編集できるのかもしれないですね…

OAuthでアクセス

OAuthでアクセストークンを取ってアクセスする方法です。
C#からアクセスに行くと、ブラウザからユーザー認証が開いて、認証するとトークンが取得され、シートの編集や作成ができるようになります。

OAuthについて

OAuth認証についてはQiitaにすごくわかりやすい記事があるので、こちらをご覧ください。

Service Accountでアクセス

google developer consoleからサービスアカウントを作って、サービスアカウントからアクセスする方法です。

アクセストークンを取ったりする必要がなく、(ブラウザを開いて認証がない)

メールアドレスでスプレッドシートを共有しておくと編集はすることが可能です。
oauthでspreadsheetを作成する時と同じようにプログラムを書くと、権限エラーで作成したファイルが見れませんでした。

Service Accountでspreadsheetを作成する時はgoogle driveのフォルダに権限を与えておいて、
権限のあるフォルダにgoogle drive apiからアクセスして作成という流れになりました。

google developer consoleでの設定

プロジェクトを作成後、[APIとサービス有効化]からgoogle sheets apiを有効にします。

認証情報作成で[OAuthクライアントIDの作成]を選んで、アプリケーションの種類をデスクトップにします。
(この後にOAuth同意画面で設定が必要だったかも…)

[JSONをダウンロード]からキーをダウンロードして
このキーをC#プロジェクトに追加し、オプションでビルド時に常にコピーされるようにしておきます。

OAuthでアクセスして、spreadsheet作成

今回はOAuthでアクセスして、自分のドライブにスプレッドシートを作成するまでを行っています。
C#でSheets Apiを使うので、NugetでGoogle.Sheets.Api.v4を導入する必要があります。

Service Accountからは、また別記事で書こうと思います。

ソース

ソースは下記のような感じで記載しました。全文はgithubに置いてます。

SpreadSheetOAuthController.cs

public class SpreadSheetOAuthController
{
    private readonly string[] _scopes = { SheetsService.Scope.Spreadsheets };
    private SheetsService _sheetsService;

    /// <summary>
    /// AzureFunctionでSpread Sheetを作成
    /// </summary>
    /// <param name="req"></param>
    /// <param name="log"></param>
    /// <returns></returns>
    [FunctionName("SpreadCreate")]
    public IActionResult SpreadCreate(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "spread_create")] HttpRequest req, ILogger log)
    {
        // Create Google Sheets API service.
        _sheetsService = new SheetsService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = ConnectSpreadSheetOAuth(),
            ApplicationName = "TestCreateSheet",
        });


        var requestBody = new Spreadsheet
        {
            Properties = new SpreadsheetProperties()
        };

        requestBody.Properties.Title = "CreateMySheet";

        var request = _sheetsService.Spreadsheets.Create(requestBody);
        var response = request.Execute();

        return new ObjectResult(JsonConvert.SerializeObject(response));
    }

    /// <summary>
    /// Spread Sheetにアクセストークンを取得して接続
    /// </summary>
    /// <returns></returns>
    private UserCredential ConnectSpreadSheetOAuth()
    {
        UserCredential credential;

        using (var stream =
            new FileStream("oauth_desctop_appkey.json", FileMode.Open, FileAccess.Read))
        {
            string credPath = "token.json";
            credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                GoogleClientSecrets.Load(stream).Secrets,
                _scopes,
                "user",
                CancellationToken.None,
                new FileDataStore(credPath, true)).Result;
            Console.WriteLine("Credential file saved to: " + credPath);
        }

        return credential;
    }
}

説明

spreadsheetにアクセスまで

17行目あたりから接続するための処理を行っていて、spreadsheetにアクセスするためにSheetsServiceをnewしています。
HttpClientInitializerに、認証情報をセットする箇所で自作関数のConnectSpreadSheetOAuthを呼んでアクセストークンを作成して、認証情報を返しています。

ConnectSpreadSheetOAuthではoauth_desctop_appkey.json(google developer consoleからダウンロード)のキーを読み取って、googleにアクセスしてtoken.jsonでトークンを取得します。
この時にブラウザが開いて、ユーザー選択画面が表示されます。

ApplicationNameは決まりはなく何でもいいみたいでした。

ファイルを作成する箇所

24行目から29行目でリクエスト情報を作成しています。やっているのはシートの名前を付けているくらいです。
(requestBody.Properties.Titleに名前をセット)

_sheetsService.Spreadsheets.Createにリクエストを渡して、Executeを呼び出すとシートが作成されます。
最後にObjectResultでレスポンスを呼び出したブラウザなりにjson形式で返すようにしてみました。

エラーやハマりポイント

リダイレクトURLエラー(400: redirect_uri_mismatch)

OAuth認証[OAuth クライアント ID の作成]の時にアプリケーションの種類をウェブアプリケーションにして
リダイレクトURLを正しく設定したつもりでしたが、このエラーが発生しました。

回避策として、上記でやっているようにアプリケーションの種類をデスクトップアプリケーションで作成すると回避できました。

spreadsheetが参照しかできない…

_scopes = { SheetsService.Scope.SpreadsheetsReadonly };

みたいな形で、スコープがReadOnlyになっていると、読み取りのみなので下記のようにします。

_scopes = { SheetsService.Scope.Spreadsheets };

上記のように書くと、表示・編集・作成・削除の一通りの権限が与えられます。

動作確認

実行すると、アカウントを選択する画面が出てきます…

選択すると、リクエスト許可の画面が出てきます…
(確認されていないアプリの注意画面が出たら、詳細から進めます..)

レスポンスで、200OKが返ってきました。

スプレッドシートを確認に行くと…

名前を付けたファイルが出来上がりました!

サンプル

コメント

タイトルとURLをコピーしました