C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: DataGridViewでデータを置き換えする方法


(過去ログ 176 を表示中)

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■100988 / inTopicNo.1)  DataGridViewでデータを置き換えする方法
  
□投稿者/ hi (1回)-(2022/12/07(Wed) 19:53:43)

分類:[.NET 全般] 

        開発環境:Microsoft Visual Studio 2019
    開発言語:C#
    クライアントマシン:Windows10
    データベース:SQLサーバ

以下コードの一部です。

       public F05_教育項目閲覧()
        {
            InitializeComponent();
            実病院.cmbXにセットする(cmb病院, 1, "A30");
            dgvQ項目.AutoGenerateColumns = false;
            dgvQ項目.RowTemplate.Height = 35;
        }
    private void btn全体像を表示する_Click(object sender, EventArgs e)
        {
            クリア();
            if (cmb病院.SelectedIndex == -1)
            {
                実共通.ErrorMSGを表示する("病院が未選択");
                cmb病院.Focus();
                return;
            }
            if (txt研修CD検索2.Text == "")
            {
                実項目.Q呼び出す();
                dgvQ項目.DataSource = 実項目.Q項目;
                実研修.呼び出す(cmb病院.Text);
            }
            else
            {
                実項目.Q呼び出す();
                dgvQ項目.DataSource = 実項目.Q項目;
                実研修.呼び出す2(cmb病院.Text, txt研修CD検索2.Text);
            }
                int n = 実研修.M研修.Rows.Count;//行数
                int j = 2;
                int l = 2;
           

            for (int i = 0; i < n+1; i++)
            {
                //DataGridViewTextBoxColumn列を作成する
                DataGridViewTextBoxColumn textColumn = new DataGridViewTextBoxColumn();
                //データソースの"Column1"をバインドする
                textColumn.DataPropertyName = "Column"+ i;
                //名前とヘッダーを設定する
                textColumn.Name = "Column"+ i;
                textColumn.HeaderText = "Column"+ i;
                textColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                //列を追加する
                dgvQ項目.Columns.Add(textColumn);
            }
            for (int i = 0; i < n; i++)
            {
                dgvQ項目.Columns[j].HeaderText = 実研修.M研修.Rows[i]["研修名"].ToString();
                j++;
            }
    }
        void クリア()
        {
                int n = 実研修.M研修.Rows.Count;
            for (int i = 2; i < n; i++)
            
               dgvQ項目.Columns[i].HeaderText = "";
               dgvQ項目.DataSource = null;

        }
 コンボボックスで病院を選択し、ボタン(btn全体像を表示する)を押すと研修項目が縦の列に研修名が横の列に入るようになっています。その際、研修CD検索のテキストボックスに研修CDの一部を入力し、もう一度ボタンを押すと、選択した病院の研修の中で入力した研修CDと部分一致する研修を抽出し、横の列に表示できるようにしたいです。
 しかし、以上のコードでは2回以上ボタンを押すと列と行がどんどん追加されていってしまいます。
どうすればいいのでしょうか。
  dgvQ項目.Rows.Clear()や dgvQ項目.Columns.Clear()も試しましたが、結果は同じでした。
 どうかご教授ください。

引用返信 編集キー/
■100992 / inTopicNo.2)  Re[1]: DataGridViewでデータを置き換えする方法
□投稿者/ WebSurfer (2592回)-(2022/12/07(Wed) 23:14:20)
No100988 (hi さん) に返信

何を何で作っているか書いてください。
(例: Windows 10 の Visual Studio 2022 で Windows Forms アプリをターゲットフレーム
ワーク .NET Framework 4.8 で作っています・・・とか)

どういう構成になっているか書いてください。
(例: SQL Server ⇔ SqlDataAdapter ⇔ DataTable ⇔ BindingSource ⇔ DataGridView)

引用返信 編集キー/
■100998 / inTopicNo.3)  Re[1]: DataGridViewでデータを置き換えする方法
□投稿者/ 魔界の仮面弁士 (3508回)-(2022/12/08(Thu) 10:03:21)
No100988 (hi さん) に返信
> 以下コードの一部です。
不明瞭な変数がいくつかありますが、おそらく
 F05_教育項目閲覧 → Form 名。DataGridView(dgvQ項目)、ComboBox(cmb病院)、Button(btn全体像を表示する)を持つ。
 実研修 → 型付DataSet。"M研修"という DataTable を持ち、partial で "呼び出す"/"呼び出す2" メソッドを実装。
 実共通 および 実病院  → 独自作成したヘルパークラス?
といったところでしょうか。


> 研修項目が縦の列に研修名が横の列に入るようになっています。
どういう状態なのかわかるよう、具体例を挙げて
「期待する表示結果」と「実際の表示結果」を例示していただけますか?


> しかし、以上のコードでは2回以上ボタンを押すと列と行がどんどん追加されていってしまいます。
「実研修.呼び出す/呼び出す2」や『実項目.Q呼び出す();』を
どのように実装しているのかが明らかにされていないので、
提示されているコードだけでは、どこに間違いがあるのかを指摘できません…。
それぞれの中身を簡潔に示してもらえると判断しやすいです。



行が追加されるのは、DataTable に「以前取得した行データ」が残ったまま、
新たな行を書き加えているからと推察してみます。

たとえば 型付 DataSet の TableAdapter を使っている場合は、Fill する前に
ClearBeforeFill プロパティを true にして、以前の DataTable インスタンスを
クリアするようにしないと、行データが追記されていきます。
DataTable に PrimaryKey が設定されていない場合は猶のこと。

あるいは TableAdapter で Get 系メソッドを使っている場合、もしくは
SQL を動的生成するために DataAdapter を使っているようなケースにおいては、
データベースに問い合わせた結果を「既存の DataTable インスタンス」に読み込ませているか
「そのたびに新しい DataSet (あるいは DataTable) を new して渡しているのか」で
話が変わってきます。


以前の問い合わせ結果を無視して、最新の情報のみを得たいのであれば、
ロード前に既存の DataTable の中身をクリアするか、もしくは
新しく DataTable インスタンスを new しなおすようにしてみてください。

以前の問い合わせ結果に対して、最新データを差分的に書き加えたい場合は
DataSet の Merge メソッドを試してみてください。
https://learn.microsoft.com/ja-jp/dotnet/framework/data/adonet/dataset-datatable-dataview/merging-dataset-contents


> 選択した病院の研修の中で入力した研修CDと部分一致する研修を抽出し、
> 横の列に表示できるようにしたいです。
「横の列に表示」というのが、どういう表示結果を期待しているのか分かりませんでした。

既存の DataTable に対して列を増減したいのであれば、DataTable の Columns プロパティに対して
.Add なり .Remove/.RemoveAt なりを呼び出すことができます。

あるいは、部分一致しているかどうかを表すためのチェックボックス列があって、
一致するものだけにチェックを入れるといったパターンでしょうか?
その場合はループ処理で判断して true / false を切り替えていくことができます。

あるいは列数を変更したいのではなく、すでに取得済みの DataTable に対して
行データの絞り込みを行いたいのでしょうか?データベースへの再問い合わせは不要で、
BindingSource や DataView の Filter プロパティを使って絞り込むことができます。



> if (txt研修CD検索2.Text == "")
> {
>   実項目.Q呼び出す();
>   dgvQ項目.DataSource = 実項目.Q項目;
>   実研修.呼び出す(cmb病院.Text);
> }
> else
> {
>   実項目.Q呼び出す();
>   dgvQ項目.DataSource = 実項目.Q項目;
>   実研修.呼び出す2(cmb病院.Text, txt研修CD検索2.Text);
> }

本題とは無関係ですが、上記のパターンなら、
if で分岐するのは実研修だけで良いかと。

 実項目.Q呼び出す();
 dgvQ項目.DataSource = 実項目.Q項目;
 if (txt研修CD検索2.Text == "") {
   実研修.呼び出す(cmb病院.Text);
 } else {
   実研修.呼び出す2(cmb病院.Text, txt研修CD検索2.Text);
 }


また、呼び出す と呼び出す2 という 2 つのメソッドを設けるのではなく、
 void 呼び出す2(string a, string b = "") { … }
のようにしておき、第二引数が "" だった時の分岐を実研修側に任せるようにすれば、
btn全体像を表示する_Click 側で if 文判定を行う必要も無くなるかと。




> データベース:SQLサーバ
正しい表記は、「SQLサーバ」ではなく「SQL Server」です。
また、Microsoft でのカタカナ表記は「サーバ」ではなく「サーバー」です。
https://bit.ly/3UAykAZ
https://atmarkit.itmedia.co.jp/news/200807/25/microsoft.html


> 開発言語:C#
シーシャープという言語名を表記する際には、
"C#" [U+0043, U+FF03] (音楽記号のシャープ) ではなく
"C#" [U+0043, U+0023] (ナンバーサイン) の文字で記述するのが一般的な記法です。

---
日本工業規格 JIS X 3015 "プログラミング言語C#"
→序文 6 [頭字語及び略語]
》 C#は,“しーしゃーぷ”と発音する。
》 C#は,LATIN CAPITAL LETTER C (U+0043)の次にNUMBER SIGN # (U+0023)を書く。
---
ECMA-334 "C# Language Specification" および
ISO/IEC 23270:2006 "Information technology -- Programming languages -- C#"
→Introduction 6. [Acronyms and abbreviations]
》 The name C# is pronounced “C Sharp”.
》 The name C# is written as the LATIN CAPITAL LETTER C (U+0043) followed by the NUMBER SIGN # (U+0023).
---
https://qiita.com/yoshi389111/items/b17140e704d7c0f91d6b
https://kazama.hatenablog.com/entry/20060816/p1
https://qiita.com/yoshi389111/items/b17140e704d7c0f91d6b
引用返信 編集キー/
■101001 / inTopicNo.4)  Re[2]: DataGridViewでデータを置き換えする方法
□投稿者/ hi (3回)-(2022/12/08(Thu) 11:52:32)
No100998 (魔界の仮面弁士 さん) に返信
> ■No100988 (hi さん) に返信

> どういう状態なのかわかるよう、具体例を挙げて
> 「期待する表示結果」と「実際の表示結果」を例示していただけますか?
分かりやすく学校として例えると
「授業テーブル」に{ID,授業コード,学校名,授業名,教科,単元}={1,数A-2022-1,A学校,一年生数学Aその1,数学A,確率},{2,数B-2022-1,A学校,二年生数学Bその1,数学B,数列},{3,数A-2022-1,B学校,一年生数学Aその1,数学A,確率}
「単元テーブル」に{教科,単元}={数学A,確率},{数学A,整数},{数学A,図形},{数学B,数列},{数学B,ベクトル}
というテーブルがあったときに、
「期待する表示結果」としては、@コンボボックスで学校名「A学校」を選択し、ボタンを押すと左の列から教科、単元の一覧が表示され、3列目からはヘッダーに授業名が表示されます。(3列目のヘッダーは一年生数学Aその1、4列目のヘッダーは二年生数学Bその1)下記がイメージです。

教科  単元   一年生数学Aその1 二年生数学Bその1
数学A 確率
数学A 整数
数学A 図形
数学B 数列
数学B ベクトル

次に、Aコンボボックスの横にあるテキストボックス内に検索したい授業コードの一部「数A」を入力して、もう一度ボタンを押すと左の列から教科、単元の一覧は変わらず表示され、3列目からはヘッダーには入力した授業コードと部分一致する授業だけが表示されます。


教科  単元   一年生数学Aその1
数学A 確率
数学A 整数
数学A 図形
数学B 数列
数学B ベクトル

しかし、「実際の表示結果」は@では

教科  単元   一年生数学Aその1 二年生数学Bその1
数学A 確率
数学A 整数
数学A 図形
数学B 数列
数学B ベクトル

Aでは下記のように表示されますが、dgvQ項目.Columns[i].HeaderText = "";でヘッダーをクリアしているのでボタンを押すたびに列がどんどん追加されていっています。

教科  単元   一年生数学Aその1 
数学A 確率
数学A 整数
数学A 図形
数学B 数列
数学B ベクトル
数学A 確率
数学A 整数
数学A 図形
数学B 数列
数学B ベクトル

> 「実研修.呼び出す/呼び出す2」や『実項目.Q呼び出す();』を
> どのように実装しているのかが明らかにされていないので、
> 提示されているコードだけでは、どこに間違いがあるのかを指摘できません…。
> それぞれの中身を簡潔に示してもらえると判断しやすいです。

情報不足でした。それぞれ下記のようになっています。

        public void Q呼び出す()
        {
            string sql = "SELECT * FROM Q分類";
            db.adM分類.SelectCommand = new OdbcCommand(sql, db.odbcConnection1);
            db.adM分類.Fill(Q項目);
        }

        public void 呼び出す2(string 病院名,string 研修CD)
        {
            M研修.Clear();
            string sql = " SELECT * FROM T研修";
            sql += " WHERE 病院名='" + 病院名 + "'";
            sql += "AND 研修CD LIKE '%" + 研修CD + "%'";
            db.adT研修.SelectCommand = new OdbcCommand(sql, db.odbcConnection1);
            db.adT研修.Fill(M研修);
        }

すみません。分かるところだけ回答いたしました。よろしくお願いいたします。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -