初日 最新 目次 MAIL HOME


*-- To Tell The Truth --*
Cruz
MAIL
HOME

My追加

2001年12月25日(火)
独自レコードセット作成

今日は仕事。

半日かけてあれこれ悩んだ挙句、やはりMFCは断念。
とてもじゃないが、今日明日でできると思えなかったので。
うまく使えると簡単そうなんだけどなぁ。

・・で、SDK+ADOで作っていたプロトタイプにメスを入れる。
例のvariant型対策だ。

◆本に出ている方法
(LPCTSTR)_bstr_t(m_Rec->GetCollect(L"カラム名")));

GetCollectで取ってきた値をダイレクト(?)にBSTRにして、LPCTSTRにキャストしているんだけど、なんか上手く変換できていないんだよねぇ。

◆ネット&MSDNで発見した方法
_variant_t vStr;
vStr = m_Rec->GetCollect(L"カラム名");
vStr.ChangeType(VT_BSTR);
vStr.bstrVal ← に変換済み(?)文字列が入る

1つ1つデバックで値確認はできるんだけど、なぜかvStr.bstrValを(char *)でキャストして使用しようとすると、1文字目しかないんだよね。
vStr.bstrValそのものを覗いても、1文字分しかないし・・・。
ビミョーに使用方法を間違っているだけのような気もするんだけど??

◆独自レコードセット作成
詳しくはこちらMSDNのADO VC++エクステンションの使用を参考にするとわかる。

SDKで書いているものの・・・レコードセットクラスとして、GenericクラスCADORecordBindingを作成した。
connectしたりselectするクラスにしっかりインクルードさせて。

#define INITGUID
// ADO使用
#import "C:\program files\common files\system\ado\msado15.dll" \
    no_namespace \
    rename( "EOF", "adoEOF")
#include

class CRecordSet : public CADORecordBinding
{
// レコードセット設定マクロ
BEGIN_ADO_BINDING(CRecordSet)
 ADO_FIXED_LENGTH_ENTRY(1,
            adChar,
            stFdsData.cpCardNo,
            lau_lCardNoStatus,
            FALSE)
 ADO_FIXED_LENGTH_ENTRY(2,
            adChar,
            stFdsData.cpRiyouYMD,
            lau_lRiyouYMDStatus,
            FALSE)
 ADO_FIXED_LENGTH_ENTRY(3,
            adInteger,
            stFdsData.iRiyouAmt,
            lau_lRiyouAmtStatus,
            FALSE)
END_ADO_BINDING()
public:
   USERDATA stData;
   ULONG lau_lCardNoStatus;
   ULONG lau_lRiyouYMDStatus;
   ULONG lau_lRiyouAmtStatus;
};

ここまでが、独自レコードセットクラス
次は、使用しているconnectやらselectをするクラス


#include "RecordSet.h" // 独自レコードセット
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CADODataAccess
{
public:
 CADODataAccess();
 virtual ~CADODataAccess();

 BOOL SelectListADO(HWND hList);
private:
 _ConnectionPtr m_pConnect;  // Connectionオブジェクト
 _CommandPtr  m_pCommand;   // Commandオブジェクト
 _RecordsetPtr m_pRecordset; // Recordsetオブジェクト

 CRecordSet  m_rsRecSet;   // FDS RecSetオブジェクト

 void SetSelect();       // Select文生成
 void DisplayList(HWND hList); // 検索結果リスト表示
};

これで準備完了。次に使用しているところ。

BOOL CADODataAccess::SelectListADO(HWND hList)
{
 HRESULT hr;
 IADORecordBinding *picRs = NULL;

 // COMの初期化処理
 ::CoInitialize(NULL);

 // ADOオブジェクトの生成
 m_pConnect.CreateInstance(__uuidof(Connection));
 m_pCommand.CreateInstance(__uuidof(Command));
 m_pRecordset.CreateInstance(__uuidof(Recordset));

 // データベースへの接続
 hr = m_pConnect->Open(
   _bstr_t(DB2_NAME),
   _bstr_t(DB2_USERID),
   _bstr_t(DB2_PASSWD),
   adConnectUnspecified);

 if(SUCCEEDED(hr)){
   // SQLの設定
   m_pCommand->ActiveConnection = m_pConnect;
   SetSelect();
   m_pRecordset->PutRefSource(m_pCommand);

   // レコードセットの取得
   _variant_t vNull; // VARIANT型のNULLとして使う
   vNull.vt = VT_ERROR;
   vNull.scode = DISP_E_PARAMNOTFOUND;
   m_pRecordset->Open(vNull,
            vNull,
            adOpenStatic,
            adLockReadOnly,
            adCmdText);

   // レコードのバインドを行うインターフェイスポインタ取得
   if(FAILED(m_pRecordset->QueryInterface(__uuidof(IADORecordBinding),
    (LPVOID*)&picRs))){
     _com_issue_error(E_NOINTERFACE);
   }
   picRs->BindToRecordset(&m_rsRecSet);

   // 検索結果件数
   if(m_pRecordset->GetRecordCount() <= 0){
    return FALSE;
   }

   // 先頭レコードへ移動し、フィールドの値を取得
   m_pRecordset->MoveFirst();
   DisplayList(hList);

  }else{
   return FALSE;
  }
  return TRUE;
}

void CADODataAccess::DisplayList(HWND hList)
{
  LV_ITEM lvitem;
  int i = 0;
  int iSubItemCount = 0;
  long lRecCount = 0;

  lRecCount = m_pRecordset->GetRecordCount();

  // リストビュー画面のクリア
  ListView_DeleteAllItems(hList);


  // List Data
  lvitem.mask = LVIF_TEXT | LVIF_IMAGE;

  for(i = 0; i < lRecCount; i++){

   // CardNo
   lvitem.pszText = m_rsRecSet.stData.cpCardNo;
   lvitem.iItem = i;
   lvitem.iSubItem = iSubItemCount;
   ListView_InsertItem(hList, &lvitem);

   iSubItemCount++;

   // 利用日時
   lvitem.pszText = m_rsRecSet.stData.cpRiyouYMD;
   lvitem.iItem = i;
   lvitem.iSubItem = iSubItemCount;
   ListView_SetItem(hList, &lvitem);

   iSubItemCount++;

   // 利用金額
   sprintf(lvitem.pszText, "%d", m_rsRecSet.stData.iRiyouAmt);
   lvitem.iItem = i;
   lvitem.iSubItem = iSubItemCount;
   ListView_SetItem(hList, &lvitem);

   iSubItemCount = 0;
   m_pRecordset->MoveNext();
 }

}

以上

これでもまだ、文字化けしているんだよなぁ。
ただ、int型はバッチリできれてるので、もしやテーブルの方の問題か?

ちなみに、connectなんかをする場合は、きちんとするならtryを使用しましょう。
これはプロトタイプです。