fireHDで家計簿作成⑤ GoogleSpreadSheetをpythonで動かす
取り急ぎコードだけ
import gspread from oauth2client.service_account import ServiceAccountCredentials import datetime import json class GSP_OPE(): def __init__(self,\ JsonPath = '/storage/emulated/0/Documents/python/project1/gsp_kakeibo.json',\ SheetName = 'kakeibo',\ DataLabel = ['購入日', '購入店', '商品名', 'カテゴリ', '重要度', '支払い方法', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', '登録日'],\ LastUpdateLogPath = '/storage/emulated/0/Documents/python/project1/lastlog.txt',\ SPREADSHEET_KEY = '10aZg3j9CaW_tLHEe3CsvJ8u64LXHDx6RRQ6z4aZWO9Y'): scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive'] credentials = ServiceAccountCredentials.from_json_keyfile_name(JsonPath, scope) gc = gspread.authorize(credentials) self.wks = gc.open_by_key(SPREADSHEET_KEY) #gc = gspread.service_account(filename = JsonPath) #self.wks = gc.open(SheetName) self.actv_sht = self.wks.worksheet('data') self.wks_data = self.wks.worksheet('data') self.wks_ddl = self.wks.worksheet('dropdownlist') self.logfile = LastUpdateLogPath self.data_lb = DataLabel def target_sheet(self, target_sheet_str = None, target_sheet_num = None): if target_sheet == None and target_sheet_num == None: return 'error 0000' if target_sheet_str != None and target_sheet_num == None: try: self.actv_sht = self.wks.worksheet(target_sheet_str) return 'change' except: return 'error0002' if target_sheet_str == None and target_sheet_num != None: try: self.actv_sht = self.wks.get_worksheet(target_sheet_str) return 'change' except: return 'error 0004' if target_sheet_str != None and target_sheet_num != None: return 'error 0006' def serch_row(self, target_word = None, target_column = None, serch_last_row_flag = False, last_update_row = 1): #return the number of row if target_word == None and target_column == None and serch_last_row_flag == False: return 'error 0020' elif target_word != None and target_column == None: return 'error 0040' elif target_word != True and serch_last_row_flag == True: return 'error 0060' """ unimprement if target_word <> None and target_column == None: #WS.cell(row, col).value row,col >= 1 row = 1 break_flag = False while(1): max_col = self.serch_column(target_row = row, last_update_column = True) if mac_col == 0: return [row, 0] for col in range(1, max_col + 1): if self.actv_sht.cell(row, col).value == target_word: return [row, col] row = row + 1 """ row = last_update_row if target_word != None and target_column != None: while(1): if self.actv_sht.cell(row, target_column).value == target_word: return [row, target_column] if self.actv_sht.cell(row, target_column).value == None: return [0, 0] row = row + 1 if serch_last_row_flag == True and target_column != None: while(2): if self.actv_sht.cell(row, target_column).value == None: return [row, target_column] row = row + 1 if serch_last_row_flag == True: while(3): if self.actv_sht.cell(row, len(self.data_lb)).value == None: return [row, 0] row = row + 1 return 'error 0080' def serch_column(self, target_word = None, target_row = None, serch_last_column_flag = False, last_update_column = 1): #return the number of row if target_word == None and target_row == None and serch_last_column_flag == False: return 'error 0200' elif target_word != None and target_row == None: return 'error 0400' elif target_word != True and serch_last_column_flag == True: return 'error 0600' col = last_update_column if target_word != None and target_row != None: while(1): if self.actv_sht.cell(target_row, col).value == target_word: return [target_row, col] if self.actv_sht.cell(target_row, col).value == None: return [0, 0] col = col + 1 if serch_last_column_flag == True and target_row != None: while(2): if self.actv_sht.cell(target_row, col).value == None: return [target_row, col] col = col + 1 return 'error 0800' def write_data(self, row = 1, column = 1, data = "write"): self.actv_sht.update_cell(row, column, data) def read_data(self, row = 1, column = 1, data = "write"): return self.actv_sht.cell(target_row, col).value def write_array(self, row = 1, column = 1, arr = [['w','r'],['i','g'],['t','!']]): for n in range(len(arr)): #row for m in range(len(arr[n])): #column self.actv_sht.update_cell(row + n, column + m, arr[n][m]) def read_array(self, row1 = 1, row2 = 5, column1 = 1, column2 = 5): buf = [[]] for n in range(row1, row2 + 1): buf2 = [] for m in range(column1, column2 + 1): buf2.append(self.actv_sht.cell(n, m).value) buf.append(buf2) buf.pop(0) return buf def save_log(self, arr): with open(self.logfile, "a") as f: writer = f.write(datetime.datetime.now(JST).strftime('%Y/%m/%d') + '::' + str(arr) + '\n') def serch_word(self, serch_word = '1'): return self.actv_sht.find(serch_word) def get_all_val_row(self, row= 1): return self.actv_sht.row_values(row) def get_all_val_col(self, col= 1): return self.actv_sht.col_values(col) def main(): gsp = GSP_OPE() gsp.write_data(row = 2, column = 1, data = "write") print('ok') gsp.write_array(row = 2, column = 2, arr = [['w','r'],['i','g'],['t','!']]) print('ok2') print(gsp.read_array(row1 = 2, row2 = 6, column1 = 1, column2 = 6)) if __name__ == "__main__": main()
fireHDで家計簿作成④ 記録するもの
google spread sheetには
購入日
購入店
商品名
カテゴリ
重要度
支払い方法
登録日
を記録する。日付以外はドロップダウンリストを作りたい。
登録日は確実に登録されるため、チェック用に使用する。
項目を追加する可能性があるため、登録日は15列目あたりに記載する。
sheet1にはデータを羅列する。
sheet2にはGUI表示用のドロップダウンリストを作成する。
データ量が膨大になった時に最終行を探すのが大変なため、ログファイル(.txt)をローカルに残す。
このログファイルには最終更新の行と投稿時間を記録する。
gsp操作のプログラムはオブジェクト指向っぽくかく。
インスタンス化する時に
jsonファイルを使って認証する。
各シートも変数としてわかりやすくする。
タグも定義しとく。
データログのパスも定義しとく。ついでに最終更新行も取得しとく。
メソッドはとりあえず
モード選択
アクティブシートの変更
行を検索してその番号を返す
列を検索してその番号を返す(使わないかも)
特定のワードのセルを返す
指定したセルに書き込む
指定したセルを読み込む
範囲指定したセルを読み込み配列で返す
範囲指定したセルと受け取った配列を書き込む
データログに保存する
シートを保存する
シートを閉じる
を用意する。
行を検索するメソッド
引数
検索ワード
検索列
最終行取得フラグ
最終更新行
処理パターン1:
検索ワードと検索列が与えられる
処理パターン2:
最終行取得フラグと検索列が与えられる
処理パターン3:
最終行取得フラグが与えられる
エラーパターン:
検索ワードと最終行が同時に与えられる
検索ワードと検索列のいずれかのみ与えられる
ー検索列と最終行フラグが両立するので、検索ワードがあって検索列が無いパターンのみエラー処理
何も与えられない
【息抜き】ハード食パン作成中
参考
分量を調整
強力粉… 365g
ドライイースト… 3g
モルトパウダー… 3g
砂糖… 7g
塩… 7g
水… 250g
無塩バター… 10g
↓強力粉
↓モルトパウダー
混ぜる順番と捏ね時間、発酵時間はレシピ通りに行った。一次発酵が少々過発酵だったかも知れない。
モルトパウダーは水(分量内)で溶かして投入した。
水の温度は40℃程度に調整した。
ドライイーストと塩は離して投入した。
砂糖の上にドライイーストを乗せた。
発酵温度は室温発酵で25〜28℃
オーブンの発酵機能で35℃
生地がベタついた。
スキムミルク入ってないからかな?
水の量をもっと減らしてもいいのかも知れない。
モルトパウダーも多すぎたのかな?
↓発酵途中
↓30分後
↓焼き上がり(油足りなくてくっついちゃった)
fireHDで家計簿作成③ fireHDでTkinter
アンドロイドVNCをいれました。
無料なのにタッチ操作が割りと快適だからです。
暫定の画面
以下ソースコード
termuxで実行してアンドロイドVNCで覗く。
import tkinter as tk from tkinter import ttk from tkinter import messagebox import sys class Sizeset(): """ fo = {'font' : 'times new roman', 'size' : 18, 'tickness' : 'bold'},\ wt = 200, hg = 100,\ fc = 'green',\#FontColor fg = 'green',\#ActiveFontColor unimplemented bg = 'black',\#not ActiveBackColor ag = 'blue',\#ActiveBackColor ac = 'w', 'nw', 'n', 'ne', 'w', 'e', 'sw', 's', 'se', 'center' jf = tk.CENTER ,tk.LEFT, tk.RIGHT rf = relief:'flat', 'raised', 'sunken', 'groove', 'ridge', 'solid' """ def __init__(\ self,\ fo = {'font' : 'times new roman', 'size' : 18, 'tickness' : 'bold'},\ wt = 200, hg = 100,\ fc = 'green',\ fg = 'green',\ bg = 'black',\ ag = 'blue',\ ac = 'center',\ jf = tk.CENTER,\ rf = 'sunken'\ ): self.__FontOption = fo self.__Width = wt self.__Height = hg self.__FontColor = fc self.__ActiveFontColor = fg self.__BackGround = bg self.__ActiveBackGround = ag self.__Anchor = ac self.__Justify = jf self.__Relief = rf def fontoption(self): return self.__FontOption def width(self): return self.__Width def height(self): return self.__Height def fontcolor(self): return self.__FontColor def activefontcolor(self): return self.__ActiveFontColor def frontcolor(self): return self.__BackGround def backcolor(self): return self.__ActiveBackGround def anchor(self): return self.__Anchor def justify(self): return self.__Justify def relief(self): return self.__Relief class OyaFrame(tk.Frame): def __init__(self, master = None): super().__init__(master) """ fc = 'black',\#FontColor fg = 'black',\#ActiveFontColor bg = 'green',\#not ActiveBackColor ag = 'blue',\#ActiveBackColor ac = 'w',\#Anchor jf = tk.CENTER,\#Justify rf = 'SUNKEN'#relief """ self.monitor_height = self.master.winfo_screenheight() self.monitor_width = self.master.winfo_screenwidth() self.master.geometry(str(self.monitor_width)+'x'+str(self.monitor_height-50)) BS = Sizeset(fo = {'font' : 'times new roman', 'size' : 48, 'tickness' : 'normal'},\ wt = self.monitor_width / 3, hg = self.monitor_height / 6 ,\ fc = 'black',\ fg = 'black',\ bg = 'green2',\ ag = 'green3',\ ac = 'center',\ jf = tk.CENTER,\ rf = 'sunken'\ ) #style = ttk.Style() #style.configure('office.TButton', font=20, anchor='w') #print(self.monitor_height,self.monitor_width) #self.master.geometry('1920x1080') # ボタンの作成 Button_Text = ['登録', '修正', '解析', '終了'] Button_Command = {0:self.Button0, 1:self.Button1, 2:self.Button2, 3:self.Button3} self.button = [] for n in range(len(Button_Text)): self.button.append(tk.Button(self.master,\ text = Button_Text[n],\ fg = BS.fontcolor(),\ activeforeground = BS.activefontcolor(),\ bg = BS.frontcolor(),\ activebackground = BS.backcolor(),\ font=(BS.fontoption()['font'], BS.fontoption()['size'], BS.fontoption()['tickness']),\ anchor = BS.anchor(),\ justify = BS.justify(),\ relief = BS.relief(),\ command = Button_Command[n] )) self.button[n].place(x = self.monitor_width/10,\ y = self.monitor_height / 8 + (BS.height() * 1.1) * n ,\ width = BS.width(), height =BS.height()) print(len(self.button)) #Button Comand def Button0(self): #resistor messagebox.showinfo('event', 'Button0 was Pushed!') print('Button0 was Pushed!') def Button1(self): #revise messagebox.showinfo('event', 'Button1 was Pushed!') print('Button1 was Pushed!') def Button2(self): #analysis messagebox.showinfo('event', 'Button2 was Pushed!') print('Button2 was Pushed!') def Button3(self): #close messagebox.showinfo('event', 'Button3 was Pushed!') self.master.destroy() sys.exit() def main(): root = tk.Tk() app = OyaFrame(master = root) app.mainloop() if __name__ == "__main__": main()
キャッシュ溜まったら
pip cache purge
fireHDで家計簿作成②
*termuxにはデスクトップの環境設定がない。
設定する必要がある。
**まずVNCをインストールする。
以下のコマンドを入力する。
pkg install x11-repo
pkg install tigervnc
**VNCサーバーを起動する。
以下のコマンドを入力する。
vncserver
または
vncserver :1 -geometry 1280x720
vncserver :1 -geometry 1920x1080
***※補足
稼働中のvncserverの確認は以下のコマンドを入力する。
vncserver -list
vncserverを停止するには以下のコマンドを入力する。
vncserver -kill :1
export DISPLAY=":1"
**Window Managerを入れる。
以下のコマンドを入力する。
pkg install twm
pkg install aterm
**VNCサーバーの待機ポートを確認
localhost:1だったら「5901」になる。
※参考
デフォルトでは、VNCサーバーはTCPポート5900 + nでVNCビューアからの接続を待機します。ここで、nはディスプレイ番号です(通常は0)。つまり、VNCサーバーのディスプレイ番号が0の場合はTCPポート5900で、ディスプレイ番号が1の場合はTCP-5901で通信します。使用するファイアウォールのドキュメントを参照して、これらのポートが開放されていることを確認してください。
vncviewerをインストールしてログインする。
vncviewerのapkをどっかから調達する。
fireHDで家計簿作成① FireHD用家計簿ソフト作成の原案
Python 使えるようにしたし、家計簿ソフトでも作ろうかな。
Termaxで起動する。
データはgoogle spread sheetに蓄積させる。他の機器からもアクセスできるようにするため。
FireHDから直接編集できないためgoogl spread sheetのライブラリを使用する。
データは下の通り
日付 購入日(2022/01/01)等と入力
購入店 店の名前
商品名 適当に
カテゴリ 食品、衣料品、雑貨他
重要度 段階 0:無くてもいい 1:あったら便利 2:必要不可欠
登録日 登録した日
モード選択[登録]→登録画面
モード選択[修正]→修正モード画面→日付指定で情報表示画面→上書きモード画面
モード選択[解析]→解析モード画面→解析モード[随時追加予定]
登録画面
情報表示画面
上書きモード画面
情報表示画面では日付を指定して表示を押すとドロップダウンリストに一覧が出てくる。
情報を選んで修正を押すと上書きモード画面モードへ。
詳細はまた練ろうかな。