トップ回答者
DataGridViewで前の行のデータを保存したい

質問
-
DataGridViewでJANコード(13桁)を入力すると、商品名、単価がDBファイルから読み込まれるようになっています
しかし、以下のソースコードで実行すると、2個目の商品を登録した際に1個目の商品の行が上書きされてしまいます
直前のデータを保存し、きちんと行に表示したままにするにはどうすればよいのでしょうか?
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Data.OleDb; namespace TestDatabaseApp_5 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private DataTable dt = new DataTable(); private int cnt = 0; private DataSet ds = new DataSet(); private void Btn1_Click(object sender, EventArgs e) { } private void Form1_Load(object sender, EventArgs e) { //フォームをロードした際にtxtBox1にフォーカスする this.ActiveControl = this.txtBox1; } private void txtBox1_TextChanged(object sender, EventArgs e) { if (txtBox1.TextLength == 13) { OleDbConnection conn = new OleDbConnection(); OleDbCommand comm = new OleDbCommand(); long LJAN; LJAN = Convert.ToInt64(txtBox1.Text); LJAN = long.Parse(txtBox1.Text); int len; //LJANの長さを調べる len = (LJAN == 0) ? 1 : ((int)Math.Log10(LJAN) + 1); conn.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\user2\Documents\Documents\TestData_2.accdb"; // MDB名など dataGridView1.AutoGenerateColumns = false; DataGridViewColumn column = new DataGridViewTextBoxColumn(); // 接続します。 conn.Open(); // SELECT文を設定します。 comm.CommandText = "SELECT * FROM test_data"; comm.Connection = conn; OleDbDataAdapter oda = new OleDbDataAdapter(); oda.SelectCommand = comm; // 結果を表示します。 //DataSet ds = new DataSet(); oda.Fill(ds, "data"); DataView dv = new DataView(); //もしも入力された文字(LJAN)が13桁だったら if (len == 13) { //DataViewでidがLJANの値と一致するものをフィルターする dv = new DataView(ds.Tables[0], "id=" + LJAN, null, DataViewRowState.CurrentRows); cnt += 1; //DataGridViewのソース設定 dataGridView1.DataSource = dv; //「商品名」列にnameを、「単価」列にpriceを表示する dataGridView1.Columns[3].DataPropertyName = "price"; dataGridView1.Columns[1].DataPropertyName = "name"; // 接続を解除します。 conn.Close(); dataGridView_Sum(); //DataViewに行を追加 DataRowView dtrv = dv.AddNew(); dataGridView_AddNext(); //dataGridView1.DataSource = null; } //もしも入力された文字(LJAN)が13桁だったら、txtBox1に入力された値を全選択する if (len >= 13) { txtBox1.SelectAll(); } } } private void Btn1_Click_1(object sender, EventArgs e) { } private void dataGridView_AddNext() { dataGridView1.RowCount.ToString(); } private void dataGridView_Sum() { int sum = 0; for (int i = 0; i < dataGridView1.Rows.Count; ++i) { sum += Convert.ToInt32(dataGridView1.Rows[i].Cells[3].Value); } txtBox2.Text = sum.ToString(); } } }
回答
-
DataViewに条件がひとつしか設定されておらず、過去に検索した条件が考慮されていません。そのため最新の条件の結果のみが表示されてます。
複数の条件を設定していくのは面倒なので、DataViewでのフィルタはやめて、データベースからの読み出しに対して条件設定(WHERE)した方が楽です。public partial class Form1 : Form { public Form1() { InitializeComponent(); } private DataTable dt = new DataTable(); private int cnt = 0; private DataSet ds = new DataSet(); private void Form1_Load(object sender, EventArgs e) { dataGridView1.AutoGenerateColumns = false; //「商品名」列にnameを、「単価」列にpriceを表示する dataGridView1.Columns[3].DataPropertyName = "price"; dataGridView1.Columns[1].DataPropertyName = "name"; //フォームをロードした際にtxtBox1にフォーカスする this.ActiveControl = this.txtBox1; } private string path = @"D:\Users\J\Documents\データベース7.accdb"; //private string path= @"C:\Users\user2\Documents\Documents\TestData_2.accdb"; // MDB名など private void txtBox1_TextChanged(object sender, EventArgs e) { string text = txtBox1.Text.Trim(); if (text.Length != 13) { //入力された文字(LJAN)が13桁ではなかったら return; } for (int i = 0; i < text.Length; i++) { if (!char.IsDigit(text[i])) { MessageBox.Show("数字以外が入力されています"); return; } } long LJAN = long.Parse(text); OleDbConnection conn = new OleDbConnection(); OleDbCommand comm = new OleDbCommand(); conn.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path; conn.Open(); // SELECT文を設定します。 //データベースからJANコードの一致するレコードのみ検索するようにWHEREで条件を設定する comm.CommandText = "SELECT * FROM test_data WHERE id=\"" + text + "\""; //パラメータークエリのが良いけどまずは条件検索を理解する comm.Connection = conn; OleDbDataAdapter oda = new OleDbDataAdapter(); oda.SelectCommand = comm; //dataという名前のDataTableに結果を読み込む //すでにdataというテーブルがあるならdataテーブルに追加読み込みされる oda.Fill(ds, "data"); conn.Close(); DataTable data = ds.Tables["data"]; //this.dt=data; if (this.dataGridView1.DataSource != data) { //DataSourceにはDataTableのまま設定(追加で読み込んでいくんで1回だけDataSourceに設定すればいい) this.dataGridView1.DataSource = data; } dataGridView_Sum(); txtBox1.SelectAll(); int newCount = data.Rows.Count; if (cnt == newCount) { MessageBox.Show("JANコードが見つかりませんでした"); } cnt = newCount; } private void dataGridView_Sum() { int sum = 0; for (int i = 0; i < dataGridView1.Rows.Count; ++i) { sum += Convert.ToInt32(dataGridView1.Rows[i].Cells[3].Value); } txtBox2.Text = sum.ToString(); } }
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク chmod_777 2017年12月17日 23:41
すべての返信
-
DataViewに条件がひとつしか設定されておらず、過去に検索した条件が考慮されていません。そのため最新の条件の結果のみが表示されてます。
複数の条件を設定していくのは面倒なので、DataViewでのフィルタはやめて、データベースからの読み出しに対して条件設定(WHERE)した方が楽です。public partial class Form1 : Form { public Form1() { InitializeComponent(); } private DataTable dt = new DataTable(); private int cnt = 0; private DataSet ds = new DataSet(); private void Form1_Load(object sender, EventArgs e) { dataGridView1.AutoGenerateColumns = false; //「商品名」列にnameを、「単価」列にpriceを表示する dataGridView1.Columns[3].DataPropertyName = "price"; dataGridView1.Columns[1].DataPropertyName = "name"; //フォームをロードした際にtxtBox1にフォーカスする this.ActiveControl = this.txtBox1; } private string path = @"D:\Users\J\Documents\データベース7.accdb"; //private string path= @"C:\Users\user2\Documents\Documents\TestData_2.accdb"; // MDB名など private void txtBox1_TextChanged(object sender, EventArgs e) { string text = txtBox1.Text.Trim(); if (text.Length != 13) { //入力された文字(LJAN)が13桁ではなかったら return; } for (int i = 0; i < text.Length; i++) { if (!char.IsDigit(text[i])) { MessageBox.Show("数字以外が入力されています"); return; } } long LJAN = long.Parse(text); OleDbConnection conn = new OleDbConnection(); OleDbCommand comm = new OleDbCommand(); conn.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path; conn.Open(); // SELECT文を設定します。 //データベースからJANコードの一致するレコードのみ検索するようにWHEREで条件を設定する comm.CommandText = "SELECT * FROM test_data WHERE id=\"" + text + "\""; //パラメータークエリのが良いけどまずは条件検索を理解する comm.Connection = conn; OleDbDataAdapter oda = new OleDbDataAdapter(); oda.SelectCommand = comm; //dataという名前のDataTableに結果を読み込む //すでにdataというテーブルがあるならdataテーブルに追加読み込みされる oda.Fill(ds, "data"); conn.Close(); DataTable data = ds.Tables["data"]; //this.dt=data; if (this.dataGridView1.DataSource != data) { //DataSourceにはDataTableのまま設定(追加で読み込んでいくんで1回だけDataSourceに設定すればいい) this.dataGridView1.DataSource = data; } dataGridView_Sum(); txtBox1.SelectAll(); int newCount = data.Rows.Count; if (cnt == newCount) { MessageBox.Show("JANコードが見つかりませんでした"); } cnt = newCount; } private void dataGridView_Sum() { int sum = 0; for (int i = 0; i < dataGridView1.Rows.Count; ++i) { sum += Convert.ToInt32(dataGridView1.Rows[i].Cells[3].Value); } txtBox2.Text = sum.ToString(); } }
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク chmod_777 2017年12月17日 23:41