Contents

วิธีสร้างตัวติดตามค่าใช้จ่ายโดยใช้ Python

เครื่องมือติดตามค่าใช้จ่ายเป็นเครื่องมือสำคัญที่ช่วยให้บุคคลและธุรกิจจัดการธุรกรรมทางการเงินของตน ด้วยตัวติดตามค่าใช้จ่าย คุณสามารถสร้างงบประมาณ จัดหมวดหมู่ค่าใช้จ่าย และวิเคราะห์รูปแบบการใช้จ่ายได้

สำรวจวิธีการสร้างแอปพลิเคชันอินเทอร์เฟซผู้ใช้แบบกราฟิก (GUI) ข้ามแพลตฟอร์มสำหรับการติดตามค่าใช้จ่ายโดยใช้ภาษาการเขียนโปรแกรม Python

โมดูล Tkinter, CSV และ Matplotlib

ในการสร้างแอปพลิเคชันติดตามค่าใช้จ่ายนี้ จำเป็นต้องใช้ไลบรารี Tkinter, CSV และ Matplotlib

Tkinter ช่วยให้นักพัฒนาสามารถสร้างแอปพลิเคชันเดสก์ท็อปที่น่าดึงดูดใจได้ โดยจัดเตรียมส่วนประกอบกราฟิกที่หลากหลาย เช่น ปุ่ม ป้ายกำกับ และช่องป้อนข้อความ ส่วนต่อประสานที่ใช้งานง่ายทำให้กระบวนการสร้างแอปพลิเคชันเพื่อวัตถุประสงค์ต่างๆ ง่ายขึ้น

โมดูล CSV เป็นแพ็คเกจ Python โดยธรรมชาติที่นำเสนอฟังก์ชันที่เกี่ยวข้องกับการตีความและองค์ประกอบของไฟล์ Comma-Separated Value (CSV) ซึ่งใช้กันอย่างแพร่หลายในการแลกเปลี่ยนข้อมูลระหว่างแอปพลิเคชันและระบบที่หลากหลาย เนื่องจากความเรียบง่ายและความเข้ากันได้กับแพลตฟอร์มต่างๆ

Matplotlib เป็นเครื่องมืออันทรงพลังสำหรับการสร้างการแสดงภาพแบบไดนามิก รวมถึงกราฟ พล็อต และแผนภูมิ ซึ่งสามารถปรับปรุงเพิ่มเติมได้โดยการรวมเข้ากับ OpenCV เพื่อเพิ่มพูนความเชี่ยวชาญในเทคนิคการจัดการภาพขั้นสูง

หากต้องการติดตั้งโมดูลเหล่านี้ ให้รัน:

pip install tk matplotlib 

กำหนดโครงสร้างของแอปติดตามค่าใช้จ่าย

ต้นกำเนิดของซอร์สโค้ดของโปรเจ็กต์นี้อยู่ภายในพื้นที่เก็บข้อมูล GitHub ที่กำหนด ซึ่งทำหน้าที่เป็นแหล่งเก็บข้อมูลดิจิทัลสำหรับไฟล์และเอกสารที่เกี่ยวข้องทั้งหมด

ในการเริ่มต้น เราจะนำเข้าโมดูลที่จำเป็น จากนั้นเราจะสร้างคลาสที่เรียกว่า ExpenseTrackerApp ซึ่งกำหนดชื่อและขนาดของแอปพลิเคชัน ต่อไป เราจะกำหนดคู่ของรายการตามลำดับ รายการหนึ่งประกอบด้วยรายจ่ายที่บันทึกไว้ทั้งหมด ในขณะที่อีกรายการหนึ่งครอบคลุมประเภทการเงินต่างๆ ตัวแปรสตริงซึ่งมีชื่อเรียกว่า category\_var ก็ได้ถูกสร้างขึ้นเช่นกัน โดยมีการตั้งค่าเริ่มต้นที่สอดคล้องกับหมวดหมู่หลักในรายการของเรา สุดท้ายนี้ เราเรียกกระบวนการ create\_widgets ขึ้นมาเพื่อสร้างอินเทอร์เฟซผู้ใช้แบบกราฟิกขึ้นมา

 import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import csv
import matplotlib.pyplot as plt

class ExpenseTrackerApp(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Expense Tracker")
        self.geometry("1300x600")
        self.expenses = []
        self.categories = [
            "Food",
            "Transportation",
            "Utilities",
            "Entertainment",
            "Other",
        ]
        self.category_var = tk.StringVar(self)
        self.category_var.set(self.categories[0])
        self.create_widgets()

เมธอด create\_widgets ทำหน้าที่เป็นองค์ประกอบสำคัญในการสร้างอินเทอร์เฟซผู้ใช้ภายในแอปพลิเคชัน เพื่อสร้างกรอบสำหรับการแสดงข้อมูลที่เกี่ยวข้องกับค่าใช้จ่าย เราต้องสร้างองค์ประกอบภาพซึ่งประกอบด้วยกรอบที่รองรับรายละเอียดเฉพาะที่เกี่ยวข้องกับบันทึกเหล่านี้ โดยเฉพาะ เราจะพัฒนาวิดเจ็ตป้ายกำกับแยกกันหกรายการ แต่ละรายการได้รับการออกแบบมาเพื่อนำเสนอข้อมูลที่เกี่ยวข้อง เช่น หัวข้อ มูลค่าทางการเงิน คำอธิบาย หมวดหมู่ วันที่ และผลรวมโดยรวม การกำหนดองค์ประกอบหลักให้กับป้ายกำกับแต่ละป้ายถือเป็นสิ่งสำคัญ ในขณะเดียวกันก็ระบุข้อความและลักษณะการพิมพ์ตามลำดับด้วย

ในการสร้างอินเทอร์เฟซที่มีการป้อนข้อความ 3 รายการและเมนูแบบเลื่อนลง ให้สร้างการเชื่อมต่อระหว่างรายการหลังกับตัวแปรชื่อ category\_var เริ่มต้นด้วยการกำหนดเค้าโครงสำหรับแต่ละองค์ประกอบเหล่านี้ ระบุรูปแบบและขนาดแบบอักษรตามลำดับดังนี้:1. สร้างวิดเจ็ตรายการสามรายการ และกำหนดคอนเทนเนอร์พาเรนต์ ตัวเลือกการจัดรูปแบบ และข้อจำกัดด้านความกว้างให้กับแต่ละวิดเจ็ต สร้างวิดเจ็ต Combobox กำหนดคอนเทนเนอร์หลัก รายการตัวเลือกที่มีอยู่ รูปแบบแบบอักษร และข้อกำหนดด้านมิติ3. เชื่อมโยง Combobox กับตัวแปร category\_var เพื่อให้แน่ใจว่าการเลือกภายในเมนูแบบเลื่อนลงจะอัปเดตแบบเรียลไทม์ตามการโต้ตอบของผู้ใช้

     def create_widgets(self):
        self.label = tk.Label(
            self, text="Expense Tracker", font=("Helvetica", 20, "bold")
        )
        self.label.pack(pady=10)
        self.frame_input = tk.Frame(self)
        self.frame_input.pack(pady=10)
        self.expense_label = tk.Label(
            self.frame_input, text="Expense Amount:", font=("Helvetica", 12)
        )
        self.expense_label.grid(row=0, column=0, padx=5)
        self.expense_entry = tk.Entry(
            self.frame_input, font=("Helvetica", 12), width=15
        )
        self.expense_entry.grid(row=0, column=1, padx=5)
        self.item_label = tk.Label(
            self.frame_input, text="Item Description:", font=("Helvetica", 12)
        )
        self.item_label.grid(row=0, column=2, padx=5)
        self.item_entry = tk.Entry(self.frame_input, font=("Helvetica", 12), width=20)
        self.item_entry.grid(row=0, column=3, padx=5)
        self.category_label = tk.Label(
            self.frame_input, text="Category:", font=("Helvetica", 12)
        )
        self.category_label.grid(row=0, column=4, padx=5)
        self.category_dropdown = ttk.Combobox(
            self.frame_input,
            textvariable=self.category_var,
            values=self.categories,
            font=("Helvetica", 12),
            width=15,
        )
        self.category_dropdown.grid(row=0, column=5, padx=5)
        self.date_label = tk.Label(
            self.frame_input, text="Date (YYYY-MM-DD):", font=("Helvetica", 12)
        )
        self.date_label.grid(row=0, column=6, padx=5)
        self.date_entry = tk.Entry(self.frame_input, font=("Helvetica", 12), width=15)
        self.date_entry.grid(row=0, column=7, padx=5) 

สร้างอินเทอร์เฟซผู้ใช้ที่มีส่วนประกอบต่อไปนี้:ปุ่มที่มีป้ายกำกับ “เพิ่มค่าใช้จ่าย” ที่เพิ่มค่าใช้จ่ายลงในรายการ ปุ่มที่มีป้ายกำกับ “แก้ไขค่าใช้จ่าย” ที่แก้ไขค่าใช้จ่ายที่มีอยู่ในรายการ ปุ่มที่มีป้ายกำกับ “ลบค่าใช้จ่าย” ที่จะลบรายการ ค่าใช้จ่ายจากรายการ ปุ่มที่มีป้ายกำกับ “บันทึกค่าใช้จ่าย” ซึ่งจะบันทึกค่าใช้จ่ายทั้งหมดในรายการ ปุ่มที่มีป้ายกำกับ “แสดงแผนภูมิค่าใช้จ่าย” ที่แสดงแผนภูมิค่าใช้จ่ายในรายการ กรอบที่ล้อมรอบปุ่มเหล่านี้พร้อมชื่อ “ผู้จัดการค่าใช้จ่าย”".

รวมฟังก์ชันการทำงานของการสร้างแถบเลื่อนแนวตั้งซึ่งวางตำแหน่งทางด้านขวามือของพื้นที่เนื้อหาหลักของ GUI ช่วยให้สามารถนำทางเนื้อหาภายในกล่องรายการได้อย่างราบรื่น การใช้เทคนิคการเสริมที่เหมาะสม ช่วยให้มั่นใจในการนำเสนอด้วยภาพที่เหมาะสมที่สุด นอกจากนี้ เมื่ออัปเดตป้ายกำกับทั้งหมดด้วยข้อมูลใหม่ ให้ทำการปรับเปลี่ยนที่จำเป็นเพื่อรักษาความสอดคล้องกันทั่วทั้งอินเทอร์เฟซ

         self.add_button = tk.Button(self, text="Add Expense", command=self.add_expense)
        self.add_button.pack(pady=5)
        self.frame_list = tk.Frame(self)
        self.frame_list.pack(pady=10)
        self.scrollbar = tk.Scrollbar(self.frame_list)
        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.expense_listbox = tk.Listbox(
            self.frame_list,
            font=("Helvetica", 12),
            width=70,
            yscrollcommand=self.scrollbar.set,
        )
        self.expense_listbox.pack(pady=5)
        self.scrollbar.config(command=self.expense_listbox.yview)
        self.edit_button = tk.Button(
            self, text="Edit Expense", command=self.edit_expense
        )
        self.edit_button.pack(pady=5)
        self.delete_button = tk.Button(
            self, text="Delete Expense", command=self.delete_expense
        )
        self.delete_button.pack(pady=5)
        self.save_button = tk.Button(
            self, text="Save Expenses", command=self.save_expenses
        )
        self.save_button.pack(pady=5)
        self.total_label = tk.Label(
            self, text="Total Expenses:", font=("Helvetica", 12)
        )
        self.total_label.pack(pady=5)
        self.show_chart_button = tk.Button(
            self, text="Show Expenses Chart", command=self.show_expenses_chart
        )
        self.show_chart_button.pack(pady=5)
        self.update_total_label() 

กำหนดฟังก์ชันการทำงานของตัวติดตามค่าใช้จ่าย

รวมข้อมูลโค้ดที่กำหนดลงในอินเทอร์เฟซของแอปพลิเคชันที่มีอยู่เพื่อเป็นวิธีการบันทึกค่าใช้จ่ายตามหมวดหมู่และวันที่ที่ระบุ จากนั้นการตรวจสอบข้อมูลที่ป้อนจะถูกเพิ่มลงในรายการไดนามิกที่แสดงภายในอินเทอร์เฟซผู้ใช้แบบกราฟิก จากนั้นจะลบภาระผูกพันในการป้อนข้อมูลด้วยตนเองเพิ่มเติมออกจาก ผู้ใช้.

มิฉะนั้นจำเป็นต้องแสดงการแจ้งเตือนว่าค่า"ค่าใช้จ่าย"และ"วันที่"ไม่สามารถเว้นว่างได้ ต่อไปนี้ ควรดำเนินการเรียกใช้ฟังก์ชันเพื่อ update\_total\_label

     def add_expense(self):
        expense = self.expense_entry.get()
        item = self.item_entry.get()
        category = self.category_var.get()
        date = self.date_entry.get()
        if expense and date:
            self.expenses.append((expense, item, category, date))
            self.expense_listbox.insert(
                tk.END, f"{expense}-{item}-{category} ({date})"
            )
            self.expense_entry.delete(0, tk.END)
            self.item_entry.delete(0, tk.END)
            self.date_entry.delete(0, tk.END)
        else:
            messagebox.showwarning("Warning", "Expense and Date cannot be empty.")
        self.update_total_label() 

ในการแก้ไขค่าใช้จ่ายที่มีอยู่ภายในฐานข้อมูลบันทึก เราสามารถใช้วิธีที่เรียกว่า"แก้ไข\_ค่าใช้จ่าย"วิธีนี้จะดึงข้อมูลดัชนีของเรกคอร์ดที่เลือกและรับค่าใช้จ่ายที่เกี่ยวข้อง จากนั้นจะแจ้งให้ผู้ใช้ป้อนค่าใหม่สำหรับค่าใช้จ่ายผ่านกล่องโต้ตอบ หากผู้ใช้ระบุค่าใช้จ่ายใหม่ วิธีการจะอัพเดตรายการค่าใช้จ่ายด้วยข้อมูลนี้ สุดท้าย วิธีการนี้เรียกใช้ฟังก์ชัน"refresh\_list"เช่นเดียวกับรูทีนย่อย"update\_total\_label"เพื่อให้แน่ใจว่าการเปลี่ยนแปลงทั้งหมดสะท้อนให้เห็นอย่างถูกต้องในแอปพลิเคชัน

     def edit_expense(self):
        selected_index = self.expense_listbox.curselection()
        if selected_index:
            selected_index = selected_index[0]
            selected_expense = self.expenses[selected_index]
            new_expense = simpledialog.askstring(
                "Edit Expense", "Enter new expense:", initialvalue=selected_expense[0]
            )
            if new_expense:
                self.expenses[selected_index] = (
                    new_expense,
                    selected_expense[1],
                    selected_expense[2],
                    selected_expense[3],
                )
                self.refresh_list()
                self.update_total_label() 

เพื่อใช้งานฟังก์ชันที่อธิบายไว้ในข้อมูลโค้ดที่กำหนด เราจะกำหนดวิธีการที่เรียกว่า delete\_expense ซึ่งจะดึงดัชนีของบันทึกที่เลือกและรับค่าใช้จ่ายที่เกี่ยวข้อง จากนั้นเราจะส่งดัชนีนี้ไปยังฟังก์ชันเพื่อให้สามารถลบออกจากกล่องรายการได้ ต่อไปนี้ เราจะเรียกใช้ฟังก์ชัน update\_total\_label เพื่อให้แน่ใจว่าป้ายกำกับทั้งหมดได้รับการอัปเดตตามนั้น

     def delete_expense(self):
        selected_index = self.expense_listbox.curselection()
        if selected_index:
            selected_index = selected_index[0]
            del self.expenses[selected_index]
            self.expense_listbox.delete(selected_index)
            self.update_total_label() 

แน่นอน! ต่อไปนี้คือตัวอย่างวิธีที่คุณสามารถนำไปใช้ใน Python โดยใช้ Flask และ SQLAlchemy:pythonfrom flask import gfrom sqlalchemy import create_engine, Column, Integer, String, ForeignKeyfrom sqlalchemy.orm import sessionmaker, allowancefrom datetime import datetimeclass User(db.Model): tablename=‘users’id=Column(‘id’, Integer, primary_key=True)name=Column(’name’, String)email=Column(’email’, String)created_at=คอลัมน์(‘created_at’, DateTime, default=datetime.utcnow)updated_at=คอลัมน์ (‘updated_at’, DateTime, onupdate=datetime.utcnow)

     def refresh_list(self):
        self.expense_listbox.delete(0, tk.END)
        for expense, item, category, date in self.expenses:
            self.expense_listbox.insert(
                tk.END, f"{expense}-{item}-{category} ({date})"
            ) 

เพื่อปรับแต่งข้อความที่ให้มา ฉันจำเป็นต้องมีบริบทเพิ่มเติมเกี่ยวกับสิ่งที่คุณต้องการให้ฉันทำกับข้อมูลโค้ดนี้ อย่างไรก็ตาม นี่คือความพยายามของฉันในการทำให้ข้อความที่ให้มาฟังดูซับซ้อนมากขึ้น:pythondef update_total_label(expenses):total=sum(expenses)return Totaldef save_expenses(filename=“expenses.csv”, allowances=None):if not allowances:expenses=[ ]# เปิดไฟล์ CSV ที่ระบุหรือสร้างขึ้นใหม่หากไม่มีอยู่ ลอง:ด้วย open(ชื่อไฟล์, “w”) เป็น f:writer=csv.writer(f)# เขียนส่วนหัว rowwriter.writerow([…])

     def update_total_label(self):
        total_expenses = sum(float(expense[0]) for expense in self.expenses)
        self.total_label.config(text=f"Total Expenses: USD {total_expenses:.2f}")

    def save_expenses(self):
        with open("expenses.csv", "w", newline="") as csvfile:
            writer = csv.writer(csvfile)
            column_headers = ["Expense Amount", "Item Description", "Category", "Date"]
            writer.writerow(column_headers)
            for expense in self.expenses:
                writer.writerow(expense)) 

เพื่อให้เห็นภาพการกระจายรายจ่ายรายเดือนในหมวดหมู่ต่างๆ เราสามารถใช้วิธีที่เรียกว่า show\_expenses\_chart ซึ่งใช้เป็นอินพุตในรายการ ค่าใช้จ่าย ขั้นแรก เรามานิยามพจนานุกรมชื่อ category\_totals กันก่อน ซึ่งจะทำหน้าที่เป็นตัวนับในการสะสมค่าใช้จ่ายรวมสำหรับการใช้จ่ายแต่ละประเภท เราจะวนซ้ำรายการในรายการ ค่าใช้จ่าย โดยแปลงจำนวนค่าใช้จ่ายแต่ละรายการจากสตริงเป็นแบบทศนิยม สำหรับแต่ละหมวดหมู่ หากมีอยู่ในพจนานุกรม category\_totals เราจะเพิ่มค่าคีย์ให้กับผลรวมที่มีอยู่ มิฉะนั้น เราจะสร้างคู่คีย์-ค่าใหม่ซึ่งแสดงถึงจำนวนค่าใช้จ่ายปัจจุบัน

     def show_expenses_chart(self):
        category_totals = {}
        for expense, _, category, _ in self.expenses:
            try:
                amount = float(expense)
            except ValueError:
                continue
            category_totals[category] = category_totals.get(category, 0) \+ amount 

หากต้องการสร้างการแสดงการกระจายค่าใช้จ่ายในชุดข้อมูลอย่างเป็นหมวดหมู่ เราสามารถใช้ฟังก์ชัน pie ของ matplotlib ได้ ฟังก์ชันนี้ช่วยให้สามารถสร้างแผนภูมิวงกลมตามจำนวนค่าใช้จ่ายที่กำหนดและหมวดหมู่ที่เกี่ยวข้อง ด้วยการตั้งค่าพารามิเตอร์ต่างๆ เช่น autopct , เท่ากับ และชื่อของแผนภูมิ ผู้ใช้จะสามารถปรับแต่งวิธีที่เอาต์พุตสุดท้ายจะปรากฏได้

         categories = list(category_totals.keys())
        expenses = list(category_totals.values())
        plt.figure(figsize=(8, 6))
        plt.pie(
            expenses, labels=categories, autopct="%1.1f%%", startangle=140, shadow=True
        )
        plt.axis("equal")
        plt.title(f"Expense Categories Distribution (USD)")
        plt.show() 

ใช้ความสามารถของคลาส ExpenseTrackerApp โดยสร้างอินสแตนซ์ จากนั้นเปิดใช้งานลูปเหตุการณ์ Tkinter ด้วยเมธอด mainloop() ซึ่งจะคอยตรวจสอบการโต้ตอบของผู้ใช้อย่างต่อเนื่องจนกระทั่งถึงเวลาที่อินเทอร์เฟซแบบกราฟิกปิด

 if __name__ == "__main__":
    app = ExpenseTrackerApp()
    app.mainloop() 

ทดสอบคุณสมบัติต่างๆ ของ Python Expense Tracker

เมื่อดำเนินการโปรแกรม จะมีการเปิดตัวอินเทอร์เฟซผู้ใช้แบบกราฟิก (GUI) ซึ่งมีฟิลด์อินพุตสำหรับบันทึกรายละเอียดที่เกี่ยวข้องกับค่าใช้จ่าย เช่น คำอธิบายรายการ หมวดหมู่ และวันที่ นอกเหนือจากกล่องข้อความสำหรับป้อนค่าตัวเลข โดยการพิมพ์ข้อมูลนี้และคลิกที่ปุ่ม"เพิ่มค่าใช้จ่าย"เราสามารถคาดหวังได้ว่ารายการใหม่จะถูกผนวกเข้ากับกล่องรายการ นอกจากนี้ โปรแกรมจะอัปเดตผลรวมของค่าใช้จ่ายที่บันทึกไว้ทั้งหมดอย่างต่อเนื่องเพื่อความสะดวกของคุณ

/th/images/adding-entries-to-expense-tracker.jpg

เมื่อเลือกรายการค่าใช้จ่ายที่ต้องการแล้ว โปรดคลิกที่ปุ่ม"แก้ไขค่าใช้จ่าย"เพื่อเริ่มกระบวนการแก้ไข ซึ่งจะพร้อมท์กล่องโต้ตอบที่ช่วยให้คุณสามารถแก้ไขรายละเอียดของรายการค่าใช้จ่ายแต่ละรายการที่เลือกภายในบริบทที่มีอยู่

/th/images/selecting-and-editing-expense.jpg

การลบบันทึกค่าใช้จ่ายเฉพาะโดยคลิกที่ปุ่ม"ลบค่าใช้จ่าย"ซึ่งจะลบรายการที่เลือกออกจากรายการค่าใช้จ่าย

/th/images/selecting-and-deleting-expense.jpg

เมื่อคลิกที่ปุ่ม “แสดงแผนภูมิค่าใช้จ่าย” ซอฟต์แวร์จะสร้างการแสดงกราฟิกในรูปแบบของแผนภูมิวงกลมที่แสดงการกระจายรายจ่ายในหมวดหมู่ต่างๆ พร้อมด้วยชื่อและเปอร์เซ็นต์ตามลำดับ

/th/images/pie-chart-of-expenses.jpg

การปรับปรุงตัวติดตามค่าใช้จ่าย

เพื่อปรับปรุงประสบการณ์ผู้ใช้ เป็นไปได้ที่จะรวมฟังก์ชันการค้นหาที่ช่วยให้บุคคลสามารถค้นหาค่าใช้จ่ายเฉพาะตามคำอธิบาย มูลค่า การจำแนกประเภท หรือวันที่ได้ นอกจากนี้ คุณอาจมีตัวเลือกสำหรับการเรียงลำดับและการกรองบันทึกข้อมูล การปรับแอปพลิเคชันให้รองรับภาษาและรูปแบบสกุลเงินต่างๆ จะเป็นประโยชน์

พิจารณารวมฟังก์ชันการแจ้งเตือนไว้ในแอปพลิเคชัน เพื่อให้ผู้ใช้สามารถกำหนดเกณฑ์ที่ทำให้เกิดการแจ้งเตือนเมื่อถูกละเมิด การแจ้งเตือนเหล่านี้สามารถใช้เป็นคำเตือนเกี่ยวกับการใช้จ่ายเกินและช่วยระบุค่าใช้จ่ายที่ผิดปกติ