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-29

はじめに

前回までで、家計簿アプリの設計からOCR処理までの実装を行いました(AIがやりました)
今回は登録処理を実装します。

プロンプト

支出登録画面の登録ボタンの動作を実装したい。
コードを出力してください。

回答

以下は:

支出登録画面の「登録」ボタン

の実装例です。

実装内容:

  • SQLiteへ支出情報登録
  • 支出明細登録
  • トランザクション対応
  • DataGridViewから商品一覧取得
  • 入力チェック

を含みます。


前提

NuGet追加:

System.Data.SQLite

テーブル構成


Expenses

CREATE TABLE Expenses
(
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    ExpenseDate TEXT,
    TotalAmount REAL,
    PaymentMethod TEXT,
    Note TEXT
);

ExpenseItems

CREATE TABLE ExpenseItems
(
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    ExpenseId INTEGER,
    ProductName TEXT,
    Category TEXT,
    Amount REAL,
    Quantity INTEGER,
    TaxRate INTEGER,
    Note TEXT
);

DBHelper.cs

新規作成。

using System.Data.SQLite;

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

        public static SQLiteConnection GetConnection()
        {
            return new SQLiteConnection(
                _connectionString);
        }
    }
}

ExpenseItemModel.cs

namespace KakeiboApp.Models
{
    public class ExpenseItemModel
    {
        public string ProductName { get; set; }

        public string Category { get; set; }

        public decimal Amount { get; set; }

        public int Quantity { get; set; }

        public int TaxRate { get; set; }

        public string Note { get; set; }
    }
}

ExpenseRegisterForm.cs


using追加

using System.Data.SQLite;
using KakeiboApp.Data;
using KakeiboApp.Models;

登録ボタンイベント

private void btnRegister_Click(
    object sender,
    EventArgs e)
{
    try
    {
        RegisterExpense();

        MessageBox.Show(
            "登録しました。");

        ClearForm();
    }
    catch (Exception ex)
    {
        MessageBox.Show(
            ex.Message,
            "エラー");
    }
}

RegisterExpense

private void RegisterExpense()
{
    ValidateInput();

    using SQLiteConnection conn =
        DbHelper.GetConnection();

    conn.Open();

    using SQLiteTransaction tran =
        conn.BeginTransaction();

    try
    {
        long expenseId =
            InsertExpense(conn);

        InsertExpenseItems(
            conn,
            expenseId);

        tran.Commit();
    }
    catch
    {
        tran.Rollback();
        throw;
    }
}

支出登録

private long InsertExpense(
    SQLiteConnection conn)
{
    string sql =
    @"
    INSERT INTO Expenses
    (
        ExpenseDate,
        TotalAmount,
        PaymentMethod,
        Note
    )
    VALUES
    (
        @ExpenseDate,
        @TotalAmount,
        @PaymentMethod,
        @Note
    );

    SELECT last_insert_rowid();
    ";

    using SQLiteCommand cmd =
        new SQLiteCommand(sql, conn);

    DateTime date =
        dtpDate.Value.Date;

    decimal totalAmount =
        decimal.Parse(txtAmount.Text);

    cmd.Parameters.AddWithValue(
        "@ExpenseDate",
        date.ToString("yyyy-MM-dd"));

    cmd.Parameters.AddWithValue(
        "@TotalAmount",
        totalAmount);

    cmd.Parameters.AddWithValue(
        "@PaymentMethod",
        txtPaymentMethod.Text);

    cmd.Parameters.AddWithValue(
        "@Note",
        txtNote.Text);

    object result =
        cmd.ExecuteScalar();

    return (long)result;
}

明細登録

private void InsertExpenseItems(
    SQLiteConnection conn,
    long expenseId)
{
    foreach (DataGridViewRow row
        in dgvItems.Rows)
    {
        if (row.IsNewRow)
        {
            continue;
        }

        string productName =
            Convert.ToString(
                row.Cells["colProductName"].Value);

        if (string.IsNullOrWhiteSpace(
            productName))
        {
            continue;
        }

        string sql =
        @"
        INSERT INTO ExpenseItems
        (
            ExpenseId,
            ProductName,
            Category,
            Amount,
            Quantity,
            TaxRate,
            Note
        )
        VALUES
        (
            @ExpenseId,
            @ProductName,
            @Category,
            @Amount,
            @Quantity,
            @TaxRate,
            @Note
        );
        ";

        using SQLiteCommand cmd =
            new SQLiteCommand(sql, conn);

        cmd.Parameters.AddWithValue(
            "@ExpenseId",
            expenseId);

        cmd.Parameters.AddWithValue(
            "@ProductName",
            productName);

        cmd.Parameters.AddWithValue(
            "@Category",
            Convert.ToString(
                row.Cells["colCategory"].Value));

        cmd.Parameters.AddWithValue(
            "@Amount",
            ConvertDecimal(
                row.Cells["colAmount"].Value));

        cmd.Parameters.AddWithValue(
            "@Quantity",
            ConvertInt(
                row.Cells["colQuantity"].Value));

        cmd.Parameters.AddWithValue(
            "@TaxRate",
            ConvertInt(
                row.Cells["colTaxRate"].Value));

        cmd.Parameters.AddWithValue(
            "@Note",
            Convert.ToString(
                row.Cells["colItemNote"].Value));

        cmd.ExecuteNonQuery();
    }
}

入力チェック

private void ValidateInput()
{
    if (string.IsNullOrWhiteSpace(
        txtAmount.Text))
    {
        throw new Exception(
            "金額を入力してください。");
    }

    if (!decimal.TryParse(
        txtAmount.Text,
        out _))
    {
        throw new Exception(
            "金額が不正です。");
    }
}

変換Helper

private decimal ConvertDecimal(
    object value)
{
    if (value == null)
    {
        return 0;
    }

    decimal.TryParse(
        value.ToString(),
        out decimal result);

    return result;
}

private int ConvertInt(
    object value)
{
    if (value == null)
    {
        return 0;
    }

    int.TryParse(
        value.ToString(),
        out int result);

    return result;
}

フォームクリア

private void ClearForm()
{
    txtAmount.Clear();

    txtPaymentMethod.Clear();

    txtNote.Clear();

    dgvItems.Rows.Clear();

    dtpDate.Value =
        DateTime.Now;
}

DataGridView列名

以下前提。

列名 内容
colProductName 商品名
colCategory 商品区分
colAmount 金額
colQuantity 数量
colTaxRate 税率
colItemNote 備考

OCR結果反映時

OCR後:

txtAmount.Text =
    result.TotalAmount.ToString();

dtpDate.Value =
    result.Date ?? DateTime.Now;

も追加すると連携できます。

起動、確認

起動、登録してみます。
image.png

image.png

最後に

次回はドラッグドロップでのレシート読み込みを実装します。

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?