记账程序2.0
需求背景:
為了更好的解放雙手,提高記賬效率,本人想要制作一個基于python的自動化記賬程序,用于統計本人每星期、每月、每年,甚至是每日的盈虧記錄,目前該程序是處于半自動化狀態,后期會逐漸更新,爭取全套流程純自動化,不需要過多的人工參與,擺脫苦哈哈記賬統計的耗時任務
需求總目標:
日賬目:連接常用的支付通信軟件,將自己每花費一筆,就自動歸類在一個臨時存儲位置,然后這個臨時存儲位置可以用excel格式記錄存儲,并將其下載到指定的電腦桌面位置
星期賬目:對一星期的花銷和盈收做出統計,并用圖的方式展示各種類花銷情況和收入情況
月賬目:對一個月(即四個星期)的花銷和盈收做出統計,并用圖的方式展示各種類花銷情況和收入情況
年賬目:對一年(即12個月)的花銷和盈收做出統計,并用圖的方式展示各種類花銷情況和收入情況
嘮嗑本次記賬程序2.0出現背景:
上次寫過一篇記賬程序1.0,我對其中含有的漏洞進行填坑。這里有傳送門:自動化記賬程序1.0,簡短回顧一下,上次的程序只是對一星期的的總收支和總收入搜集并統計,并實時計算出剩余的余額還有多少。可是這未免過于單調,因為這個只能是簡單描述,并不能讓人更加清晰知道自己的收入是在哪一塊占據的多?自己的支出是在哪一塊占據的多?并且純數字的展示,會不會對數字不敏感的人不友好呀(比如說本人)
本次記賬程序2.0的目標:
對上次的記賬程序1.0做出改進,額外增加對收/支種類的展述和對收/支種類的數據統計,并疊加對一星期總收入、總支出和剩余額的柱狀圖呈現,和對收/支出種類的數據統計的餅圖呈現。
具體內容
前期準備工作
這次實現記賬程序2.0的準備工作,是基于上次的記賬程序1.0,這里有傳送門:自動化記賬程序1.0;除此之外,還要額外下載一個新python庫,名為xlsxwriter庫,這個庫秒殺之前我給你們介紹的xlwt庫,它不僅能寫入數據,還能繪圖,也支持xlsx格式的文件。如何下載,這里我因為篇幅原因,就只拋出核心代碼:pip install xlsxwriter,具體如何操作,可以回顧我上一篇文章,這里有傳送門:自動化記賬程序1.0。
編碼思路:
在實現自動化記賬程序時,容我先捋清一下思路:
1.思想認識上,這個是基于上一篇文章的思路并進行改良,額外新增對一星期收/支類別統計,并以可視化圖形呈現的,第一次看這篇文章的一定要回顧上一期我寫過的記賬程序1.0呀【重要事情說三遍~】
2.對新增部分首先要對原本excel模板做出改進
3.記錄單表情況下,對收/支種類的名稱獲取,并將其中涉及到每個收/支的金額做統計
4.然后擴大范圍,從記錄單表到擴大到多表(即從2021年5月30號到2021年6月5號的記賬表)
5.接下來就是對圖形的繪制了,這里包括繪制收入、支出和剩余利潤的柱形圖和收/支的類別數據的餅圖
6.并將統計到的數據結果使用xlsxwriter庫寫入到excel表中,當然,本次不會再使用xlwt庫,將會對原本程序1.0的寫入excel代碼做出改變
7.打包成.exe腳本,這里就不會詳細介紹實現過程,只拋出核心代碼和結果,不懂的可翻閱我寫過的記賬程序1.0【重要事情說四遍~~】
開始編碼:
編碼思路認識清楚后,就愉快編碼了:
excel模板改造
以上這副圖是程序1.0的excel模板
以上這幅圖是改良后,程序2.0的excel模板
這個在接下來程序定位獲取數據的時候很重要,如果是小白,可以對照查看
導入第三方庫
這里要導入三個python庫,分別是xlrd庫、calendar、xlsxwriter
導入庫的源碼如下【含注釋,最好手動敲寫】
對收/支出種類描述做單表統計
要實現收/支出種類描述做單表統計,可以先從如何實現支出種類描述的單表統計開始,思路是:
打開文件-->選擇要統計數據的表格-->獲取數據-->用函數來進行封裝
對單表的支出種類描述統計的源碼如下【含注釋,最好手動敲寫】:
同理,獲取單表收入種類的方法也是類似的。
對單表的收入種類描述統計的源碼如下【含注釋,最好手動敲寫】:
對收/支出種類金額做單表統計
這個問題和剛才講述如何對收/支出種類描述做單表統計的問題有異曲同工支出,處理的方式依舊是:
打開文件-->選擇要統計數據的表格-->獲取數據-->用函數來進行封裝
對單表的支出種類金額統計的源碼如下【含注釋,最好手動敲寫】:
# 獲取單張表的支出金額 def get_single_pay_series(pay_url):# pay_url為支出表的路徑# 確定文件路徑excel_url = str(pay_url)# 打開xlsx的文件data = xlrd.open_workbook(excel_url)#打開第一張表table = data.sheets()[0]# 獲取第四行的種類數據【從0開始】pay_series = table.row_values(3)# 去除種類列表里的空值:while "" in pay_series:pay_series.remove("")# 獲取第六行的種類支出金額數據【從0開始】pay_series_val = table.row_values(5)# 去除種類列表里的空值:while "" in pay_series_val:pay_series_val.remove("")# 將支出種類和支出種類金額,用字典存儲起來pay_series_dict = dict(zip(pay_series[1:],pay_series_val[1:]))return pay_series_dict對單表的收入種類金額統計的源碼如下【含注釋,最好手動敲寫】:
# 獲取單張表的收入金額 def get_single_income_series(income_url):# income_url為收入表的路徑# 確定文件路徑excel_url = str(income_url)# 打開xlsx的文件data = xlrd.open_workbook(excel_url)#打開第一張表table = data.sheets()[0]# 獲取第八行的種類數據【從0開始】income_series = table.row_values(7)# 去除種類列表里的空值:while "" in income_series:income_series.remove("")# 獲取第十行的種類支出金額數據【從0開始】income_series_val = table.row_values(9)# 去除種類列表里的空值:while "" in income_series_val:income_series_val.remove("")# 將支出種類和支出種類金額,用字典存儲起來income_series_dict = dict(zip(income_series[1:],income_series_val[1:]))return income_series_dict獲取一星期的表的收入和支出種類數據統計
從單表到對表,獲取的思路大概類似,唯一不同是對多個文件進去的處理,因為我依舊是遵照用時間來定義每天的記賬記錄,因此要對時間做處理,不懂的可翻閱我寫過的記賬程序1.0【重要事情說五遍~】,并且要用字典或者列表裝載結果,這里我兩種都有使用。
獲取一星期的表的收入和支出種類數據統計的源碼如下【含注釋,最好手動敲寫】:
# 獲取一星期的表的收入和支出種類數據統計# start取記賬的開始日期,如2021-5-23 # end取記賬的結束日期,如2021-5-29 def get_pay_and_income_series(start,end):# 存儲所有支出和收入的種類和值all_series_and_value = []# 分隔開始時間,分成年月日start_split = str(start).split("-")# 分隔結束時間,分成年月日end_split = str(end).split("-")# 確定結束文件的路徑end_excel_url = "../1日賬單/{}-{}-{}.xlsx".format(end_split[0],end_split[1],end_split[2])# 完整的支出種類名稱【以最后的結束文件為主】full_pay_series = get_full_pay_series(end_excel_url)# 完整的收入種類名稱【以最后的結束文件為主】full_income_series = get_full_income_series(end_excel_url)# 判斷開始和結束的月份是否一致if int(start_split[1]) == int(end_split[1]):# 獲取指定這個月的開始 到 結束的賬單名for this_day in range(int(start_split[2]),int(end_split[2])+1):#【this_day指的是月的天數】# 確定文件路徑this_excel_url = "../1日賬單/{}-{}-{}.xlsx".format(start_split[0],start_split[1],this_day)# 獲取單張表的支出種類和金額【索引從0開始】pay = get_single_pay_series(this_excel_url)# 遍歷單張表的支出種類名稱和金額for key,value in pay.items():# 如果支出種類名稱在完整的支出種類名稱中if key in full_pay_series:# 則取出他的值進行累計full_pay_series[key] += valueelse:# 否則保持不變full_pay_series[key]# 獲取單張表的收入種類和金額【索引從0開始】income = get_single_income_series(this_excel_url)# 遍歷單張表的支出種類名稱和金額for key,value in income.items():# 如果支出種類名稱在完整的支出種類名稱中if key in full_income_series:# 則取出他的值進行累計full_income_series[key] += valueelse:# 否則保持不變full_income_series[key]else:# 獲取這月的總天數this_month_day = calendar.monthlen(int(start_split[0]),int(start_split[1]))# 前部分:獲取指定月的開始 到 這月結束的賬單名for pre_day in range(int(start_split[2]),this_month_day+1):#【pre_day指的是這個月/年的天數】# 確定文件路徑pre_excel_url = "../1日賬單/{}-{}-{}.xlsx".format(start_split[0],start_split[1],pre_day)# 獲取單張表的支出種類和金額【索引從0開始】pay = get_single_pay_series(pre_excel_url)# 遍歷單張表的支出種類名稱和金額for key,value in pay.items():# 如果支出種類名稱在完整的支出種類名稱中if key in full_pay_series:# 則取出他的值進行累計full_pay_series[key] += valueelse:# 否則保持不變full_pay_series[key]# 獲取單張表的收入種類和金額【索引從0開始】income = get_single_income_series(pre_excel_url)# 遍歷單張表的支出種類名稱和金額for key,value in income.items():# 如果支出種類名稱在完整的支出種類名稱中if key in full_income_series:# 則取出他的值進行累計full_income_series[key] += valueelse:# 否則保持不變full_income_series[key]# 后部分:獲取新月的開始 到 指定月結束的賬單名for after_day in range(1,int(end_split[2])+1):#【after_day指的是新月/新年的天數】# 確定文件路徑after_excel_url = "../1日賬單/{}-{}-{}.xlsx".format(end_split[0],end_split[1],after_day)# 獲取單張表的支出種類和金額【索引從0開始】pay = get_single_pay_series(after_excel_url)# 遍歷單張表的支出種類名稱和金額for key,value in pay.items():# 如果支出種類名稱在完整的支出種類名稱中if key in full_pay_series:# 則取出他的值進行累計full_pay_series[key] += valueelse:# 否則保持不變full_pay_series[key]# 獲取單張表的收入種類和金額【索引從0開始】income = get_single_income_series(after_excel_url)# 遍歷單張表的支出種類名稱和金額for key,value in income.items():# 如果支出種類名稱在完整的支出種類名稱中if key in full_income_series:# 則取出他的值進行累計full_income_series[key] += valueelse:# 否則保持不變full_income_series[key]# 將一星期支出的種類和金額加入all_series_and_value列表中all_series_and_value.append(full_pay_series)# 將一星期收入的種類和金額加入all_series_and_value列表中all_series_and_value.append(full_income_series)return all_series_and_value注:如果想要檢測一下自己寫的方法是否可行,可以做一個局部測試,就是調用自己寫的函數來查看自己有沒有成功獲取自己想要的數據
# 簡單局部測試自己有無獲取到數據 result2 = get_pay_and_income_series("2021-5-30","2021-6-5") print(result2)以上是本人自己測試的代碼,僅作為參考,得到的效果圖如下:
繪制柱狀圖,用作對“支出-收入-利潤”的可視化呈現
這里是新增部分,繪圖主要抓住獲python教程取繪圖的數據,繪圖的系列數據(包含繪圖的x/y位置)、圖表的頭部標題和x/y軸的標題、圖表的風格和樣式(這個看個人需要,都是修飾和美化的)。
這部分,本人建議小白最好嘗試先用xlsxwriter庫繪制一個柱狀圖,懂其中的使用方法,再根據業務需要寫個函數封裝起來,方便直接使用。
“支出-收入-利潤”的柱形圖繪制的源碼如下【含注釋,最好手動敲寫】:
# 繪制柱狀圖 ''' 參數講解:sheet_name:為工作表名x_start_cell:為x軸的數據開始x_end_cell:為x軸的數據結束y_start_cell:為y軸的數據開始y_end_cell:為y軸的數據結束out_line_color:為柱狀圖的外框線【默認是yellow】bar_title:為設置柱狀圖的標題bar_x_axis:為設置X軸的名稱bar_y_axis:為設置Y軸的名稱tar_set_cell:為圖表安放的位置x_offset:設置X軸的偏移量【默認是25】y_offset:設置Y軸的偏移量【默認是10】 ''' def char_bar(sheet_name,x_start_cell,x_end_cell,y_start_cell,y_end_cell,bar_title,bar_x_axis,bar_y_axis,tar_set_cell,out_line_color="yellow",x_offset=25,y_offset=10):# 將其所有輸入的參數集合在同一個列表中,統統轉換成字符型數據origin_data = [sheet_name,x_start_cell,x_end_cell,y_start_cell,y_end_cell,out_line_color,bar_title,bar_x_axis,bar_y_axis,tar_set_cell]## 將列表里的數據統統轉換成字符型數據str_data = list(map(str,origin_data))## 創建一個柱狀圖(column chart)chart = workbook.add_chart({"type":"column"})## 配置第一個系列數據chart.add_series({ # "name":"={}!${}${}".format(str_data[0],str_data[1][0],str_data[1][1]),# 設置目標頭部屬性數據"categories":"={}!${}${}:${}${}".format(str_data[0],str_data[1][0],str_data[1][1],str_data[2][0],str_data[2][1]),# 設置x軸的數據"values":"={}!${}${}:${}${}".format(str_data[0],str_data[3][0],str_data[3][1],str_data[4][0],str_data[4][1]),# 設置y軸的數據"line":{"color":str_data[5]},# 設置柱狀圖的外框線})# 設置圖表的標題、X軸、Y軸的信息chart.set_title({"name":str_data[6]})chart.set_x_axis({"name":str_data[7]})chart.set_y_axis({"name":str_data[8]})## 設置圖表風格chart.set_style(1)# 把圖表插入到工作表,以及設置其偏移worksheet.insert_chart(str_data[9],chart,{"x_offset":x_offset,"y_offset":y_offset})繪制餅圖,用作對"支出的種類和金額"和"收入的種類和金額"的可視化呈現
餅圖和柱形圖繪制的思路是一致的,只不過選用的圖類型不一樣而已。
"支出的種類和金額"和"收入的種類和金額"的餅圖繪制的源碼如下【含注釋,最好手動敲寫】:
# 繪制餅圖 ''' 參數講解:sheet_name:為工作表名series_start_cell:為種類的數據開始series_end_cell:為種類的數據結束value_start_cell:為種類的數據體開始value_end_cell:為種類的數據體結束bar_title:為設置餅圖的標題tar_set_cell:為圖表安放的位置x_offset:設置X軸的偏移量【默認是25】y_offset:設置Y軸的偏移量【默認是10】 ''' def chart_pie(sheet_name,series_start_cell,series_end_cell,value_start_cell,value_end_cell,bar_title,tar_set_cell,x_offset=25,y_offset=10):# 將其所有輸入的參數集合在同一個列表中,統統轉換成字符型數據origin_data = [sheet_name,series_start_cell,series_end_cell,value_start_cell,value_end_cell,bar_title,tar_set_cell]## 將列表里的數據統統轉換成字符型數據str_data = list(map(str,origin_data))## 創建一個餅圖(pie chart)chart = workbook.add_chart({"type":"pie"})## 配置第一個系列數據chart.add_series({"categories":"={}!${}${}:${}${}".format(str_data[0],str_data[1][0],str_data[1][1],str_data[2][0],str_data[2][1]),# 獲取目標頭部屬性"values":"={}!${}${}:${}${}".format(str_data[0],str_data[3][0],str_data[3][1],str_data[4][0],str_data[4][1]),# 獲取里面的數據體})## 設置圖表的標題的信息chart.set_title({"name":str_data[5]})## 設置圖表的風格chart.set_style(10)## 把圖表插入到工作表,以及設置其偏移worksheet.insert_chart(str_data[6],chart,{"x_offset":x_offset,"y_offset":y_offset})數據寫入
恭喜你,直到這里,對前期的數據統計和數據繪圖就結束了,現在是直接將整理好的數據寫入并繪圖了
但是要注意,這里的數據寫入是用xlsxwriter庫編寫的,切記不可使用xlwt庫哦~
數據寫入的源碼如下【含注釋,最好手動敲寫】:
# 一星期內容匯總# start取記賬的開始日期,如2021-5-23 # end取記賬的結束日期,如2021-5-29 def write_pay_and_income(start,end):# 準備要寫入的數據## “支出-收入-利潤”的表頭headings1 = ["總支出","總收入","剩余利潤"]## 獲取一星期表的收入和支出的數據accounts_value = get_pay_and_income(start,end)## “支出-收入-利潤”的表體data1 = [accounts_value[0],accounts_value[1],accounts_value[1]-accounts_value[0]]## "支出的種類和金額"的表頭headings2 = ["支出種類","支出金額"]## "支出的種類和金額"的表體data2 = [list(get_pay_and_income_series(start,end)[0].keys()),list(get_pay_and_income_series(start,end)[0].values()),]## "收入的種類和金額"的表頭headings3 = ["收入種類","收入金額"]## "收入的種類和金額"的表體data3 = [list(get_pay_and_income_series(start,end)[1].keys()),list(get_pay_and_income_series(start,end)[1].values()),]# 段落樣式設計## 表頭header_style = {'bold':True,'font_name':"微軟雅黑",'border':True,'align':'center','valign':'vcenter','bg_color':'yellow'}header_style_set = workbook.add_format(header_style)# 樣式添加## 表體text_style = {'font_name':"微軟雅黑",'border':True,'align':'center','valign':'vcenter'}text_style_set = workbook.add_format(text_style)# 樣式添加# 設置H列的寬度為14worksheet.set_column("H:H",14)# 數據寫入## 單數據寫入worksheet.write(0,0,"一星期的收支情況分析")worksheet.write(0,4,"一星期的收/支出種類分析")worksheet.write(2,4,"支出種類",header_style_set)worksheet.write(3,4,"支出金額",header_style_set)worksheet.write(5,4,"收入種類",header_style_set)worksheet.write(6,4,"收入金額",header_style_set)## 多數據寫入### 寫入“支出-收入-利潤”的表頭worksheet.write_row("A3",headings1,header_style_set)### 寫入“支出-收入-利潤”的表體worksheet.write_row("A4",data1,text_style_set)### 寫入"支出的種類和金額"的表頭worksheet.write_row("F3",data2[0],text_style_set)### 寫入"支出的種類和金額"的表體worksheet.write_row("F4",data2[1],text_style_set)### 寫入"收入的種類和金額"的表頭worksheet.write_row("F6",data3[0],text_style_set)### 寫入"收入的種類和金額"的表體worksheet.write_row("F7",data3[1],text_style_set)# 繪圖## “支出-收入-利潤”的柱狀圖char_bar(sheet_name = "七天匯總",x_start_cell = "A3",x_end_cell="C3",y_start_cell = "A4",y_end_cell = "C4",out_line_color = "red",bar_title = "收支情況圖",bar_x_axis = "屬性",bar_y_axis = "數值",tar_set_cell="A10")## "支出的種類和金額"的餅圖chart_pie(sheet_name = "七天匯總",series_start_cell = "F3 ",series_end_cell = "L3",value_start_cell = "F4",value_end_cell = "L4",bar_title = "支出種類分析",tar_set_cell="I10")## "收入的種類和金額"的餅圖chart_pie(sheet_name = "七天匯總",series_start_cell = "F6 ",series_end_cell = "L6",value_start_cell = "F7",value_end_cell = "I7",bar_title = "收入種類分析",tar_set_cell="Q10")# 關閉文件workbook.close()自定義交互
當然以上這些都是用函數封裝好了的,如果要使用,必須要調用其中的函數才可以哦~
自定義交互的源碼如下【含注釋,最好手動敲寫】:
start_time = input("開始時間:")# 設定賬單統計開始時間,這里輸入"2021-5-30" end_time = input("結束時間:")# 設定賬單統計開始時間,這里輸入"2021-6-5" # 確定保存文件的路徑 save_url = "./{}到{}的匯總表.xlsx".format(start_time,end_time) # 準備工作薄 workbook = xlsxwriter.Workbook(save_url) # 創建sheet工作表【表名可寫可不寫,不寫默認是sheet1】 worksheet = workbook.add_worksheet("七天匯總") write_pay_and_income(start_time,end_time)生成.exe程序
到這里,你已經完成了核心的編碼過程,現在正是將你寫好的程序做成.exe程序吧。思路是:將.ipynb轉換成.py文件?將.py程序生成.exe文件,不懂的可翻閱我寫過的記賬程序1.0【重要事情不知說了幾遍了~~】
這里拋出的是將.py程序生成.exe的核心代碼,如下圖
效果圖如下:
結語
記賬系統2.0就算完成了,就終結了……嗎?嘻嘻,留個懸念,看自己能不能憋個大招,讓各位看官耳目一新~
總結
- 上一篇: 编译py-faster-rcnn的问题汇
- 下一篇: Pycharm中运行Python代码的几