■動作環境 :WindowsXP
■開発環境 :Visual C++6.0
■データベース:Access2000(ADO接続)
お世話になります。
Access2000で作成した ファイル名db1.mdbにある
社員マスタをVCのコンボボックスに表示させようとしています。
コンボボックスをダブルクリックして出来た関数の中でADOを介して
Accessに接続はしているのですがファイルへの接続方法以降
が分かりません。アドバイス助言よろしくお願い致します。
void CAppointmentDlg::OnEditchangeCombo1()
{
CAdoOperation AD; // ADOでアクセスを制御するクラスを AD で実
体化
AD.ConnectOpen(); // DBのコネクトを開く
}
/******************* ConnectOpen()の中身 *********************/
/ m_strProvider は以下をセット済み↓
/
/ Provider=Microsoft.Jet.OLEDB.4.0;Data Source = C:\\temp1\\db1.mdb; /
/****************************************************************/
bool CAdoOperation::ConnectOpen()
{
try {
// COMの初期化処理
::CoInitialize(NULL);
// ADOオブジェクトの生成
m_pConnect.CreateInstance(__uuidof(Connection));
m_pCommand.CreateInstance(__uuidof(Command));
m_pRecordset.CreateInstance(__uuidof(Recordset));
// データベースへの接続
m_pConnect->Mode = adModeReadWrite;
m_pConnect->Open(m_strProvider, L", L", adConnectUnspecified);
}
catch(_com_error &e){
AfxMessageBox(e.Description());
return FALSE; // 失敗
}
return TRUE; // 成功
}
/******* Accessのテーブル 社員マスタの中身 ******************/
社員番号 氏名
001 田中
002 佐藤
003 井上
これをVCのコンボボックスに表示させようとしています。
社員マスタのなにをコンボボックスに表示させるのでしょうか?
社員番号?氏名?
どちらにせよ、SELECT文をつかって、Recordsetを取得しなければ始まりませんが。
(m_pConnectのExecuteメソッドで取得できるはず。)
もしかして、
http://pegalabo.net/archives/VC/source/AdoOperation_cpp.html
を参考にされていますか?
そうでしたら、引用元を載せないとまずいですよ。
Blueさんありがとうございます。
コンボボックスには社員名を表示させようとしています。
<<m_pConnectのExecuteメソッドで取得できるはず
調べてみます。
こちらのHPを参考にしています。
http://pegalabo.net/archives/VC/source/AdoOperation_cpp.html
Executeを調べてみたのですが、詳しく載ってる箇所が見つからず
理解不十分なので参考になるHPがあればどなたか教えて下さい。
重ねて _bstr_t, _variant_t を調べたのですが
_bstr_tは COMで文字列を使用する時に使うもの?
http://72.14.253.104/search?q=cache:C9-UEwZN19cJ:luvtechno.net/h/%3FVC%252B%
252B%25A4%25C7%25CA%25B8%25BB%25FA%25CE%
25F3+SysAllocString&hl=ja&gl=jp&ct=clnk&cd=4&lr=lang_ja
_variant_tは DBの値を取得するもの?
http://72.14.235.104/search?
q=cache:y9RWwzW17PEJ:hp.vector.co.jp/authors/VA014436/prg_memo/database/ms/009.
html+_variant_t&hl=ja&gl=jp&ct=clnk&cd=4
こんな理解では不安なので、アドバイスお願い致します。
Execute文も情報が少なく第一引数がSQL文とゆう事が分かったぐらいで
上記の絡みもあり第二,第三引数の意味が分かりませんでした・・・
中途半端な理解ですが下記の関数を作成したました。
/***************** ConnectOpen()の中身 *****************/
/ CString TableName は以下をセット済み /
/ SELECT * FROM 社員マスタ /
/*************************************************************/
CString TableName
bool CAdoOperation::ComboSet(const CString TableName)
{
_bstr_t bstrQuery(TableName); // _bstr_t オブ
ジェクトに文字列を代入します。
_variant_t vRecsAffected(0L);
m_pRecordset = m_pConnect->Execute(bstrQuery, &vRecsAffected,
adOptionUnspecified);
while(!m_pRecordset->GetadoEOF())
{
}
return true;
}
コンパイル時に 'GetadoEOF' : '_Recordset' のメンバではありません。
が出てしまいます。
理由が分かりません誰か分かる方がいまいしたらよろしくお願い致します。
> http://pegalabo.net/archives/VC/source/AdoOperation_cpp.html
↑
このHP方法はADOオブジェクトを直接扱う方法でODBC初心者には難しいです。
ADOにこだわるならMFCの「CAdoDatabase」、
こだわらないのなら「CRecordset」を薦めます。
それならもっと詳しいHPが「GooGle」で検索すれば多く見つかるはずですし、
VC6.0付属のMSDNのCDでも十分だと思います。
>ADOにこだわるならMFCの「CAdoDatabase」、
は CDaoDatabase で DAOなのでは?(≒ADO)
>こだわらないのなら「CRecordset」を薦めます。
は ODBC です。
間違えました。
>は CDaoDatabase で DAOなのでは?(≒ADO)
は CDaoDatabase で DAOなのでは?(≠ADO)
> _variant_t vRecsAffected(0L);
> m_pRecordset = m_pConnect->Execute(bstrQuery, &vRecsAffected,
> adOptionUnspecified);
は
m_pRecordset = m_pConnect->Execute(bstrQuery, NULL, adCmdText);
ではどうでしょうか?
一応試してみた。
ちゃんと、田中 佐藤 井上 という結果が得られました。
#include <windows.h>
#include <comdef.h>
#include <iostream>
#import C:\Program Files\Common Files\System\ADO\msado15.dll rename
( EOF, adoEOF )
HRESULT Test()
{
HRESULT hr = S_OK;
ADODB::_ConnectionPtr pConn = NULL;
ADODB::_RecordsetPtr pRec = NULL;
try
{
hr = pConn.CreateInstance( __uuidof( ADODB::Connection ) );
if ( FAILED( hr ) ) _com_issue_error( hr );
pConn->Mode = ADODB::adModeReadWrite;
pConn->Open( LProvider=Microsoft.Jet.OLEDB.4.0;Data Source=db1.mdb,
L", L", ADODB::adConnectUnspecified );
pRec = pConn->Execute( LSELECT 氏名 FROM 社員マスタ,
NULL, ADODB::adCmdText );
ADODB::FieldsPtr pFields;
ADODB::FieldPtr pField;
while ( pRec->GetadoEOF() != VARIANT_TRUE )
{
pFields = pRec->Fields;
pField = pFields->Item[ 0L ];
_bstr_t value( pField->Value.bstrVal );
printf( %s\n, ( const char* )value );
pRec->MoveNext();
}
pRec->Close();
pConn->Close();
}
catch ( _com_error& e )
{
hr = e.Error();
}
if ( pConn ) pConn.Release();
if ( pRec ) pRec.Release();
return hr;
}
int main()
{
if ( SUCCEEDED( ::CoInitialize( NULL ) ) )
{
Test();
::CoUninitialize();
}
return 0;
}
連投ですが、
> if ( pRec ) pRec.Release();
はいらないでした。
それと、
> ADODB::_RecordsetPtr pRec = NULL;
もtryブロックの中に入れてしまうほうがよかったです。
> CDaoDatabase で DAOなのでは?(≒ADO)
そうですね、間違ってました。
>>こだわらないのなら「CRecordset」を薦めます。
>は ODBC です。
そうです、ODBCです。
「CRecordset」のほうが資料が多いし分りやすいと思いました。
アドバイスありがとうございます。
教えて頂いたプログラムで不明点がありましたので教えて下さい。
コンパイル時に 'GetadoEOF' : '_Recordset' のメンバではありません。
は Blueさんと同じのを import しましたら解決しました。
下記の3点が不明です。
1. FieldsPtr, FieldPtrはCOMの時に使うのでしょうか?
webで調べても詳しく載っていないので分かりませんでした。
みなさんはこのようなポインタの知識はどこで身に付けられるのでしょうか?
(_ConnectionPtr, _CommandPtr, m_pRecordset これらのメンバー関数などの知識も)
2. pFields->Item[ 0L ];ここで 田中 佐藤 井上のあるアドレス
をpFieldをセットしていると思ってるのですが0Lが分かりません。
(DBの場所もアドレスと表現していいのか分かりません)
3. データベースから値を取得しているのですが エディットボックス には反映
されないので調べて下記を参考にして SetWindowText を使用しました。
http://72.14.235.104/search?q=cache:El-6x1_LPnMJ:www.oct-
net.ne.jp/~monmon_d/win32api/setwindowtext.html+SetWindowText()
&hl=ja&gl=jp&ct=clnk&cd=9&lr=lang_ja
結果はエラーが3つ出ました。
1.SetWindowTextA' : 1 番目の引数を 'const int' から 'struct HWND__ *' に変換
できません。
2.文字 '0x81' は認識できません。
3.文字 '0x40' は認識できません。
1番目の引数は IDC_COMBO2 はコンボボックスのIDです。
ウィンドウまたはコントロールのハンドル・・・
恥ずかしい事にハンドルを理解できていません。
別のやり方でやるべきなのでしょうか。アドバイスよろしくお願い致します。
FieldsPtr pFields;
FieldPtr pField;
// データがなくなるまでループ
while ( m_pRecordset->GetadoEOF() != VARIANT_TRUE )
{
// データ取得
pFields = m_pRecordset->Fields;
pField = pFields->Item[ 0L ];
_bstr_t value( pField->Value.bstrVal );
SetWindowText(IDC_COMBO2, value);
printf( %s\n, ( const char* )value );
m_pRecordset->MoveNext(); //カーソルを次のレコードに移動
}
> SetWindowText(IDC_COMBO2, value);
コンボボックスに追加するんじゃないの?
というか、MFCにおいてダイアログコントロールを操作するのは基本中の基本だと思
うのですが。(COMとか云々とかいえるレベルじゃない)
SetDlgItemTextを使ってください。(ただし、ループで上書きされますが。)
コンボボックスのリストに追加したいならば、
GetDlgItemでコンボボックスを取得して、AddStringで追加してください。
> 2.文字 '0x81' は認識できません。
> 3.文字 '0x40' は認識できません。
全角空白はいっていますよね?(この程度のエラーは調べてもらいたいが。)
> 2. pFields->Item[ 0L ];ここで 田中 佐藤 井上のあるアドレス
> をpFieldをセットしていると思ってるのですが0Lが分かりません。
アドレスではありません。
0L は単なる 0 の long型です。(末尾に L をつけることでlong型になる)
SELECT文の結果の1カラム目の結果を取得しているだけです。
>コンボボックスに追加するんじゃないの?
その通りです間違えていました。申し訳ありません。
猫を参考にしてやったのですが
http://72.14.235.104/search?
q=cache:xNgyNHBZs5AJ:www.kumei.ne.jp/c_lang/mfc/mfc_14.htm+AddString&hl=ja&gl=j
p&ct=clnk&cd=1
GetDlgItem を調べた結果
1. HWND GetDlgItem( int nIDDlgItem )
ダイアログクラスのメンバ関数内でのみ使用可。
2. HWND GetDlgItem(HWND hDlg , int nIDDlgItem)
ダイアログクラスのメンバ関数外での場合使用。
とゆう事が分かったので、ダイアログクラスのメンバ関数内でコンボボックスの
ハンドルを取得して
hWnd = ( HWND* )GetDlgItem(IDC_COMBO2); hWnd を引数にしたのですが
ComboSet の中の pCombo = (CComboBox *)GetDlgItem(*hWnd, IDC_COMBO2);
で失敗してしまいます。
原因は GetDlgItem(*hWnd, IDC_COMBO2) の *hWnd で アドレスでなく
指し示す場所の値を渡してるからだと思うのですが・・・
回避方法が分かりません。よろしくお願い致します。
<プログラム (多少使用の変更しました)>
BOOL CAppointmentDlg::OnInitDialog()
{
HWND* hWnd;
AD.SetProvider(); // プロバイダー情報設定
AD.ConnectOpen(); // DBのコネクトを開く
CString TableName = SELECT 氏名 FROM 社員マスタ;
// IDC_COMBO2 のハンドルを取得
hWnd = ( HWND* )GetDlgItem(IDC_COMBO2);
AD.ComboSet(TableName, hWnd);
}
ComboSet関数では下記のように受け取りました。
bool CAdoOperation::ComboSet(const CString TableName, HWND* hWnd)
{
// 変数の宣言及び初期化
HRESULT hr = S_OK;
CComboBox *pCombo;
_bstr_t bstrQuery(TableName);
m_pRecordset = m_pConnect->Execute(bstrQuery, NULL, adCmdText);
try
{
FieldsPtr pFields;
FieldPtr pField;
// データがなくなるまでループ
while ( m_pRecordset->GetadoEOF() != VARIANT_TRUE )
{
// データ取得
pFields = m_pRecordset->Fields;
pField = pFields->Item[ 0L ];
_bstr_t value( pField->Value.bstrVal );
// この GetDlgItem で失敗する
pCombo = (CComboBox *)GetDlgItem(*hWnd, IDC_COMBO2);
pCombo->AddString(value);
m_pRecordset->MoveNext(); //カーソルを次のレコードに移動
}
m_pRecordset->Close();
m_pConnect->Close();
}
catch ( _com_error& e )
{
hr = e.Error();
return false;
}
if ( m_pConnect ) m_pConnect.Release();
return true;
}