0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIに頼り切って家計簿アプリを追加開発する。:画面作成

0
Last updated at Posted at 2026-05-22

はじめに

前回、家計簿アプリの設計を行いました(AIがやりました)
今回はその設計内容を元に取りあえず動く状態にします。

プロンプト

家計簿アプリの開発を行います。
最低限画面を表示したいため、コードを出力してください。
各画面の機能等は後ほど実装します。

要件は以下です。

・機能要件
 -開発:C#.net(windows form)
 -データ管理:SQLite3
・画面設計
 -メニュー画面
  -支出登録画面
  -支出一覧画面
・機能概要
 -メニュー画面
  -ボタン押下で各画面を表示する。
 -支出登録画面
  -支出情報を登録します。
   レシート等支出情報を画像で入力、OCR機能で各項目に自動入力を行います。
   OCRより入力された情報を人間が目視チェック、修正を行い登録します。
 -支出内保持情報
  -支出情報の一覧を表示します。
・支出情報内保持項目
 -日付
 -金額
 -支払方法
 -備考
 -商品一覧
  -商品名
  -商品区分
  -金額
  -数量
  -税率
  -備考

回答

以下は、まず「画面が起動し遷移できる最低限構成」のサンプルです。
機能本体(SQLite保存、OCR、一覧表示等)は後続実装を前提に、画面と土台クラスのみ作成しています。

構成は以下です。

KakeiboApp
├─ Program.cs
├─ Forms
│   ├─ MenuForm.cs
│   ├─ ExpenseEntryForm.cs
│   └─ ExpenseListForm.cs
│
├─ Models
│   ├─ Expense.cs
│   └─ ExpenseItem.cs
│
├─ Services
│   ├─ DatabaseService.cs
│   └─ OcrService.cs
│
└─ App.config

NuGet

まず以下をインストールしてください。

  • SQLite
  • OCR

推奨:

System.Data.SQLite
Tesseract
OpenCvSharp4
OpenCvSharp4.runtime.win

Program.cs

using System;
using System.Windows.Forms;
using KakeiboApp.Forms;

namespace KakeiboApp
{
    internal static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            Application.Run(new MenuForm());
        }
    }
}

Models/Expense.cs

using System;
using System.Collections.Generic;

namespace KakeiboApp.Models
{
    public class Expense
    {
        public int Id { get; set; }

        public DateTime ExpenseDate { get; set; }

        public decimal Amount { get; set; }

        public string PaymentMethod { get; set; }

        public string Note { get; set; }

        public List<ExpenseItem> Items { get; set; }
            = new List<ExpenseItem>();
    }
}

Models/ExpenseItem.cs

namespace KakeiboApp.Models
{
    public class ExpenseItem
    {
        public int Id { get; set; }

        public string ProductName { get; set; }

        public string Category { get; set; }

        public decimal Amount { get; set; }

        public int Quantity { get; set; }

        public decimal TaxRate { get; set; }

        public string Note { get; set; }
    }
}

Services/DatabaseService.cs

using System.Data.SQLite;

namespace KakeiboApp.Services
{
    public class DatabaseService
    {
        private readonly string _connectionString
            = "Data Source=kakeibo.db;Version=3;";

        public void Initialize()
        {
            using (var connection = new SQLiteConnection(_connectionString))
            {
                connection.Open();

                string expenseTable = @"
CREATE TABLE IF NOT EXISTS Expenses (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    ExpenseDate TEXT,
    Amount REAL,
    PaymentMethod TEXT,
    Note TEXT
);";

                string itemTable = @"
CREATE TABLE IF NOT EXISTS ExpenseItems (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    ExpenseId INTEGER,
    ProductName TEXT,
    Category TEXT,
    Amount REAL,
    Quantity INTEGER,
    TaxRate REAL,
    Note TEXT
);";

                using (var command = new SQLiteCommand(expenseTable, connection))
                {
                    command.ExecuteNonQuery();
                }

                using (var command = new SQLiteCommand(itemTable, connection))
                {
                    command.ExecuteNonQuery();
                }
            }
        }
    }
}

Services/OcrService.cs

namespace KakeiboApp.Services
{
    public class OcrService
    {
        public void ExecuteOcr(string imagePath)
        {
            // TODO:
            // Tesseract OCR実装予定

            // 例:
            // ・店舗名取得
            // ・商品一覧取得
            // ・金額取得
            // ・日付取得
        }
    }
}

Forms/MenuForm.cs

using System;
using System.Windows.Forms;

namespace KakeiboApp.Forms
{
    public class MenuForm : Form
    {
        private Button btnExpenseEntry;
        private Button btnExpenseList;

        public MenuForm()
        {
            InitializeComponent();
        }

        private void InitializeComponent()
        {
            Text = "家計簿アプリ - メニュー";
            Width = 400;
            Height = 250;
            StartPosition = FormStartPosition.CenterScreen;

            btnExpenseEntry = new Button();
            btnExpenseEntry.Text = "支出登録";
            btnExpenseEntry.Width = 200;
            btnExpenseEntry.Height = 40;
            btnExpenseEntry.Top = 40;
            btnExpenseEntry.Left = 80;
            btnExpenseEntry.Click += BtnExpenseEntry_Click;

            btnExpenseList = new Button();
            btnExpenseList.Text = "支出一覧";
            btnExpenseList.Width = 200;
            btnExpenseList.Height = 40;
            btnExpenseList.Top = 100;
            btnExpenseList.Left = 80;
            btnExpenseList.Click += BtnExpenseList_Click;

            Controls.Add(btnExpenseEntry);
            Controls.Add(btnExpenseList);
        }

        private void BtnExpenseEntry_Click(object sender, EventArgs e)
        {
            var form = new ExpenseEntryForm();
            form.ShowDialog();
        }

        private void BtnExpenseList_Click(object sender, EventArgs e)
        {
            var form = new ExpenseListForm();
            form.ShowDialog();
        }
    }
}

Forms/ExpenseEntryForm.cs

using System;
using System.Windows.Forms;

namespace KakeiboApp.Forms
{
    public class ExpenseEntryForm : Form
    {
        private TextBox txtDate;
        private TextBox txtAmount;
        private TextBox txtPaymentMethod;
        private TextBox txtNote;

        private DataGridView dgvItems;

        private Button btnSelectImage;
        private Button btnOcr;
        private Button btnSave;

        public ExpenseEntryForm()
        {
            InitializeComponent();
        }

        private void InitializeComponent()
        {
            Text = "支出登録";
            Width = 1000;
            Height = 700;
            StartPosition = FormStartPosition.CenterScreen;

            Label lblDate = new Label();
            lblDate.Text = "日付";
            lblDate.Top = 20;
            lblDate.Left = 20;

            txtDate = new TextBox();
            txtDate.Top = 40;
            txtDate.Left = 20;
            txtDate.Width = 200;

            Label lblAmount = new Label();
            lblAmount.Text = "金額";
            lblAmount.Top = 80;
            lblAmount.Left = 20;

            txtAmount = new TextBox();
            txtAmount.Top = 100;
            txtAmount.Left = 20;
            txtAmount.Width = 200;

            Label lblPayment = new Label();
            lblPayment.Text = "支払方法";
            lblPayment.Top = 140;
            lblPayment.Left = 20;

            txtPaymentMethod = new TextBox();
            txtPaymentMethod.Top = 160;
            txtPaymentMethod.Left = 20;
            txtPaymentMethod.Width = 200;

            Label lblNote = new Label();
            lblNote.Text = "備考";
            lblNote.Top = 200;
            lblNote.Left = 20;

            txtNote = new TextBox();
            txtNote.Top = 220;
            txtNote.Left = 20;
            txtNote.Width = 300;

            dgvItems = new DataGridView();
            dgvItems.Top = 280;
            dgvItems.Left = 20;
            dgvItems.Width = 920;
            dgvItems.Height = 300;

            dgvItems.ColumnCount = 6;

            dgvItems.Columns[0].Name = "商品名";
            dgvItems.Columns[1].Name = "商品区分";
            dgvItems.Columns[2].Name = "金額";
            dgvItems.Columns[3].Name = "数量";
            dgvItems.Columns[4].Name = "税率";
            dgvItems.Columns[5].Name = "備考";

            btnSelectImage = new Button();
            btnSelectImage.Text = "画像選択";
            btnSelectImage.Top = 600;
            btnSelectImage.Left = 20;

            btnSelectImage.Click += BtnSelectImage_Click;

            btnOcr = new Button();
            btnOcr.Text = "OCR実行";
            btnOcr.Top = 600;
            btnOcr.Left = 140;

            btnOcr.Click += BtnOcr_Click;

            btnSave = new Button();
            btnSave.Text = "登録";
            btnSave.Top = 600;
            btnSave.Left = 260;

            btnSave.Click += BtnSave_Click;

            Controls.Add(lblDate);
            Controls.Add(txtDate);

            Controls.Add(lblAmount);
            Controls.Add(txtAmount);

            Controls.Add(lblPayment);
            Controls.Add(txtPaymentMethod);

            Controls.Add(lblNote);
            Controls.Add(txtNote);

            Controls.Add(dgvItems);

            Controls.Add(btnSelectImage);
            Controls.Add(btnOcr);
            Controls.Add(btnSave);
        }

        private void BtnSelectImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();

            dialog.Filter = "画像ファイル|*.png;*.jpg;*.jpeg";

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                MessageBox.Show($"選択画像: {dialog.FileName}");
            }
        }

        private void BtnOcr_Click(object sender, EventArgs e)
        {
            MessageBox.Show("OCR実行(未実装)");
        }

        private void BtnSave_Click(object sender, EventArgs e)
        {
            MessageBox.Show("登録処理(未実装)");
        }
    }
}

Forms/ExpenseListForm.cs

using System.Windows.Forms;

namespace KakeiboApp.Forms
{
    public class ExpenseListForm : Form
    {
        private DataGridView dgvExpenses;

        public ExpenseListForm()
        {
            InitializeComponent();
        }

        private void InitializeComponent()
        {
            Text = "支出一覧";
            Width = 1000;
            Height = 700;
            StartPosition = FormStartPosition.CenterScreen;

            dgvExpenses = new DataGridView();

            dgvExpenses.Dock = DockStyle.Fill;
            dgvExpenses.ColumnCount = 5;

            dgvExpenses.Columns[0].Name = "日付";
            dgvExpenses.Columns[1].Name = "金額";
            dgvExpenses.Columns[2].Name = "支払方法";
            dgvExpenses.Columns[3].Name = "備考";
            dgvExpenses.Columns[4].Name = "商品数";

            Controls.Add(dgvExpenses);
        }
    }
}

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>

次に実装すべき機能

次段階では以下順序がおすすめです。

  1. SQLite初期化
  2. 支出登録保存
  3. 支出一覧取得
  4. OCR実装
  5. OCR→DataGridView自動反映
  6. Excel出力
  7. 商品カテゴリマスタ
  8. 検索機能
  9. 月別集計
  10. グラフ表示

OCR実装時のおすすめ構成

OCRは以下構成が扱いやすいです。

画像
 ↓
OpenCvSharp
  ・傾き補正
  ・ノイズ除去
  ・二値化
 ↓
Tesseract OCR
 ↓
正規表現解析
 ↓
Expenseへ反映

レシートOCRは「画像前処理」が精度にかなり影響します。
単純OCRより、OpenCV併用を推奨します。

起動確認

起動するとこんな感じです。
image.png

image.png

image.png

最後に

次回はOCR取り込みを作成していこうと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?