python
株の評価額を自動で管理したかったのでpythonからGoogle Sheetsを操作する方法を調べた。 調べてみると実はあまり事例がなかったのと、Pythonでのチュートリアル以上の良いドキュメントが見当たらなかった。 そのため施行錯誤しつつ以下の一次資料を参考に実装した。
セットアップを随分前に行ったので記憶が無い。 公式チュートリアルに記載のある、Google Sheets APIの有効化は確実に行っているがその他OAuth関連のセットアップはやっていない気がする。 この記事に記載のある通り、 サービスアカウントを作成したあとに、対象のスプレッドシートの共有管理からサービスアカウントのアドレスを編集者として登録するだけで大丈夫な気がする。
SheetID、シート名、認証情報を引数に取ってset_value, get_valueで操作するシンプルなクラス。 スコープを指定していないが、今回は直接Spreadsheetからサービスアカウントの編集を許可しているせいか問題なく動いてしまった。 OAuthを使ってユーザーから操作の認可を受ける場合などにはおそらく必要になるのだろう。(よくしらない)
import json
import os.path
from google.oauth2.service_account import Credentials
from googleapiclient.discovery import build
class SpreadSheetError(Exception):
pass
class OffsetTable:
def __init__(self, sheet_id: str, sheet_name: str, credential_str: str) -> None:
self.sheet_id = sheet_id
self.sheet_name = sheet_name
# Init credential
credential = parse_credential(credential_str)
# Init sheet
service = build('sheets', 'v4', credentials=credential)
self.sheet = service.spreadsheets()
def set_value(self, x: int, y: int, value: any) -> None:
try:
address = f"{self.sheet_name}!R{x}C{y}"
body = {"values": [[value]]}
self.sheet.values().update(spreadsheetId=self.sheet_id, range=address, body=body, valueInputOption="RAW").execute()
except Exception as e:
raise SpreadSheetError(f"Failed to access sheet: {e}")
def get_value(self, x: int, y: int) -> any:
try:
address = f"{self.sheet_name}!R{x}C{y}"
result = (
self.sheet.values()
.get(spreadsheetId=self.sheet_id, range=address)
.execute()
)
values = result.get('values', [])
if not values:
raise RuntimeError('Failed to access sheet.')
return values[0]
except Exception as e:
raise SpreadSheetError(f"Failed to access sheet: {e}")
def parse_credential(credential: str) -> Credentials:
# 環境変数に無理に入れていたりすると余計なクォテーションがついている可能性があるので落とす
credential = credential.strip("\"\'\n ")
token_dict = json.loads(credential)
credentials = Credentials.from_service_account_info(token_dict)
return credentials
全部実装したあとにライブラリがあることを知った。絶望。