はじめに
前回までで、家計簿アプリの設計から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;
も追加すると連携できます。
起動、確認
最後に
次回はドラッグドロップでのレシート読み込みを実装します。

