データベースの内容をコンボボックスに表示

[戻る]
天草 銀 [E-Mail] 2002/07/12(金) 12:05:37
お助けくださいm(_ _)m

Windows2000
VC++6.0
MFC
ダイアログベース

現在、ダイアログ画面上に
・コンボボックス
・Microsoft ADO Data Control 6.0 (SP4) (OLEDB)
・Microsoft DataGrid Control 6.0 (SP4) (OLEDB)
がそれぞれ1つずつ配置しています。

ADOのプロパティの設定は
(一般)
IDは
IDC_ADODC1
(全般)
ODBCソースデータソース名を使用するで
販売管理データベース
を指定しています
(レコードソース)
コマンドタイプが
8 - adCmdUnknown
コマンドテキスト(SQL)が
Select 担当者コード from 社員マスター

ADOのメンバ変数は
コントロールIDは
IDC_ADODC1
タイプは
CAdodc
メンバは
m_adodc1

DataGridのプロパティの設定は
(全ページ)
DataSourceがIDC_ADODC1

DataGridのメンバ変数は
コントロールIDは
IDC_DATAGRID1
タイプは
CDatagrid
メンバは
m_grid1

コンボボックスのドロップダウンの幅は大きくしてあります

コンボボックスのドロップダウンを押された時の処理は以下のようにしてあります
void CSub2Dlg::OnDropdownCombo1() 
{
    // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
    short row2;
    int i;
    CString tantou;
    CComboBox* p = (CComboBox*)GetDlgItem(IDC_COMBO1);
    p->ResetContent();
    row2 = m_grid1.GetVisibleRows();   // 行数
    for(i = 0; i < row2; i++)
    {
        m_grid1.SetCol(0);             // 列
        m_grid1.SetRow(i);             // 行
        tantou = m_grid1.GetText();
        p->InsertString(-1, tantou);
    }
}

ダイアログ画面上でDataGridの大きさを充分にとっている時は正常に動きます

しかし、やりたいことはDataGridを小さくして見せなくしコンボボックスだけを表示て
ドロップダウン時にデータベースの内容を表示させたいのです。

DataGridの大きさを極小にした場合にコンボボックスに1列しか表示されません
SetColを使うとDataGridで見えてる範囲しか表示されないので、他に何か良い方法は
ありますか? 教えていただきたいですm(_ _)m

wood 2002/07/12(金) 12:35:57
DataGridとComboBoxの表示幅には特に関係と言う物は無いのではないでしょうか

>m_grid1.SetCol(0);             // 列
>m_grid1.SetRow(i);             // 行
>tantou = m_grid1.GetText();
このコーディングですけど
m_grid1.GetText();の返却値がStringなのであれば

for(i = 0; i < row2; i++) {
   m_grid1.SetRow(i); 
     tantou.Format("%s %s %s",m_grid1.SetCol(0),m_grid1.SetCol(1),
                                     m_grid1.SetCol(2));
     p->InsertString(-1, tantou);
}

こんな感じのコーディングって可能でしょうか

質問の趣旨と違っていたらごめんなさい

wood 2002/07/12(金) 12:40:54
追伸
データグリッドコントロールと同じく列を区切りたいのなら前記の内容じゃダメです
コンボboxをリストコントロールにしないと

天草 銀 [E-Mail] 2002/07/12(金) 13:38:18
>このコーディングですけど
>m_grid1.GetText();の返却値がStringなのであれば

>for(i = 0; i < row2; i++) {
>   m_grid1.SetRow(i); 
>     tantou.Format("%s %s %s",m_grid1.SetCol(0),m_grid1.SetCol(1),
>                                     m_grid1.SetCol(2));
>     p->InsertString(-1, tantou);
>}

>こんな感じのコーディングって可能でしょうか

ん〜・・・僕の表現力が足らなくて申し訳ないですm(_ _)m
以下のSQL文で販売管理データベースの社員マスターというテーブルの担当者コードだけを
DataGridへ入れます
Select 担当者コード from 社員マスター

だからSetCol(0)ではゼロ番目しか指定していません

要するに担当者コードだけをコンボボックスに表示させたいのでございます。
row2 = m_grid1.GetVisibleRows();   // 行数
この処理を行った場合、DataGridの縦の幅を充分にとらないと表示してる範囲での数しかrow2
に入ってこないのです。
こうなるとデータベースに非常に多くの件数が登録されている場合、全部をコンボボックスに表
示することができません。。。

僕が行っている処理以外にデータベースの内容をうまくコンボボックスに入れるやり方はないで
すか?
もしくはこのままでもうまくやれる方法はないですか?
お助けくださいm(_ _)m

? 2002/07/12(金) 13:46:16
よくわからないのですが
DataGridは小さくするよりプロパティかShowWindowで非表示にしてみたら?

>DataGridの大きさを極小にした場合にコンボボックスに1列しか表示されません
row2行あるけど2行目からは空白が入っているということかな?

DataGridに関連付けられているデータベースから直接データを取得すれば
よさそうですが、この辺りは無知なので・・・。

天草 銀 [E-Mail] 2002/07/12(金) 14:01:03
>DataGridは小さくするよりプロパティかShowWindowで非表示にしてみたら?
はい。一応非表示にはしています。
ですがダイアログ画面の大きさ以内の大きさまでしか広がらないので、
もしデータベースのデータがその大きさでは表示しきれない程の数があった場合、
結局DataGridの表示しうる範囲でしかコンボボックスに入れられないことになります。。。

>row2行あるけど2行目からは空白が入っているということかな?
えぇ〜・・・っと、
row2 = m_grid1.GetVisibleRows();   // 行数
この処理では、DataGridの表示してる分の行数がrow2に入ってくるので、
DataGridが3行表示している縦幅なら3がrow2に入り、コンボボックスにはその3つのデータ
が表示されます。

>DataGridに関連付けられているデータベースから直接データを取得すれば
>よさそうですが、この辺りは無知なので・・・。
ホントは僕もそれがやりたいのですが!!!そのやり方がわからないものでこのようなことにな
っております・・・。
これができればわざわざDataGridを使用せずに済むと思うのですが・・・

でも今のところどちらの方法でも、できればOKなので、
どなたかご存知の方がおりましたらお助けくださいm(_ _)m

第3水準 2002/07/12(金) 16:47:46
>データベースから直接データを取得すればよさそう
CDatabaseクラスとCRecordsetクラスを使っていいのなら
こんな感じでしょうか。
エラーチェックとか全然してませんけど(^^;

#include "afxdb.h"

CDatabase    cdb;
CRecordset    crs(&cdb);
CComboBox *cbp = (CComboBox*)GetDlgItem(IDC_COMBO1);
CString    data;
CString SqlString;

// コンボボックス初期化
cbp->ResetContent();

// DBオープン    
cdb.Open("hogehoge",FALSE,TRUE,"ODBC;",FALSE);    
     //↑hogehogeは対象DBのユーザデータソース名です。適宜変更してください

// レコードセットオープン
SqlString.Format("Select 担当者コード from 社員マスター");
crs.Open(CRecordset::snapshot,(LPCTSTR)SqlString,CRecordset::readOnly);

// データが無くなるまでループ
while(!crs.IsEOF()){
    // データ読み込み
    crs.GetFieldValue((short)0,data);

    // コンボボックスに追加
    cbp->InsertString(-1,data);

    // カレントレコードの移動
    crs.MoveNext();
}

// レコードセット&DBのクローズ
crs.Close();
cdb.Close();

// コンボボックスのデフォルト値設定
cbp->GetLBText(0,data);
cbp->SetWindowText(data);

各クラスの詳細はMSDNを参照してください。

天草 銀 [E-Mail] 2002/07/12(金) 17:44:50
第3水準さんありがとうございますm(_ _)m
今見たのでまだ内容は見ていませんが、もう会社から出なければいけないので、
月曜日にちゃんと読ませていただきます!!!
それでは失礼いたします。

wood 2002/07/12(金) 22:20:29
ADO(例題の少ない)をわざわざ使っているのだから、ADOで必ず実現したい
のかと思ってましたけどADO(OLEDB)ではなく、ODBCでデータが取得できれば
それでよかったんですか?
それだったら、以前このラウンジで質問したことの応用で済むんじゃないですか

wood 2002/07/12(金) 22:29:33
http://www.athomejp.com/goldfish/
このリンクのMFC→Data Base
のところ参考になりませんか

まどか 2002/07/13(土) 22:50:30
DataGrid にバウンドされた ADODC のレコードセットからデータを取ってくる例
(担当者コードが char であるという仮定です。それとエラー処理なし。)

#include "_recordset.h"
#include "fields.h"
#include "field.h"

C_Recordset rsClone;
_variant_t vString, vString2;    
COleVariant var;

//直接 DataGrid のレコードセットを動かすと画面がちらつくので
//クローンを作る
rsClone = m_adodc1.GetRecordset().Clone(adLockReadOnly);
rsClone.MoveFirst();

var = "担当者コード"; //目的のフィールド名
while(!rsClone.GetEof()){
   vString = rsClone.GetFields().GetItem(var).GetValue();
 // 担当者コードのデータ型がintなどの場合は違った変換が必要
   cbp->InsertString(-1,(char*)_bstr_t(vString.bstrVal));
   rsClone.MoveNext();
}
rsClone.Close();

実際は、DataGrid 通さなくても、ADODC から直接持って来れます。
その場合は、クローンを作る必要もなく、

m_adodc1.GetRecordset().GetFields().GetItem(var).GetValue();

これで持って来れます。最も面倒臭いのは、型変換部分だけだと
思います。こういう事ではないのでしょうか。
DataGrid は、使いづらいですね・・。

天草 銀 [E-Mail] 2002/07/15(月) 17:43:18
皆様、ご回答ありがとうございましたm(_ _)m
まことに残念ながら、今日からLinuxの勉強をしろ!とのお達しがあり、会社で堂々とVC++の勉
強ができなくなりました・・・。
だのでこのラウンジも会社ではなかなか見れなくなりそうです。
今も上司の目を盗んで書いております(笑)
まだまだこれからだというのにホントに参りました・・・。
ですがせっかくここまでやったので、会社以外で勉強はしていきたいと思っています。
これまでの経過を印刷して家で読みたいと思っています。
このラウンジではこれからもお世話になりたいと思っているので、見かけた時はどうぞご教授お
願いいたします。
それでは失礼いたします。
皆様、ありがとうございました。

古いスレッドには追加発言できません。