ADO Recordsetを使ったデータ取得


たやま  2010-11-05 23:48:21  No: 102674  IP: [192.*.*.*]

はじめまして

VBAを使用してDBの更新ツールを作成したいと考えております。
DBの取得には、ADODB Recordseの使用を考えております
現状、困っていることとして、ADODB Recordseで取得した値を
ローカル変数(構造体)に保持したいと考えております。
ローカル変数に保持する方法を教えて頂けないでしょうか

編集 削除
魔界の仮面弁士  2010-11-06 02:22:09  No: 102675  IP: [192.*.*.*]

> VBAを使用して
何の VBA をお使いなのでしょうか?


> DBの更新ツールを作成したいと考えております。
使用する DB によって接続文字列は異なりますが、そこは大丈夫でしょうか?


> 現状、困っていることとして、
やりたいことは分かりましたが、どこが分からないのかが
書かれていませんので、何を回答すればよいのか分かりません。
質問時には、どこまで分かっていて、どこで躓いているのかを
明確にしておかないと、回答がつきにくいですよ。


> ADODB Recordseで取得した値を
> ローカル変数(構造体)に保持したいと考えております。
・ADODB.Recordset を使用する方法までは調査できていますか?
  (MSDN ライブラリや MDAC SDK などのサンプルを参考にしてみてください)

・取得したデータを Recordset から取り出す方法が分からないのでしょうか?
  Recordset のカーソル行から、値を一つずつ取り出す方法もありますし、
  あるいは、データを一括で取り出すこともできます。
  (GetRows メソッドで、データを二次元配列としてまとめて取得したり、
   GetString メソッドで CSV などの文字列として取得したり、
   Save メソッドで XML 形式のデータに変換したり、あるいは Excel VBA なら
   CopyFromRecordset メソッドでシートにデータを転記させるなど)

・Recordset で取得することはできたけれども、それをユーザー定義型に
  代入する際に問題が生じているのでしょうか?
  (たとえば、『パブリックオブジェクトモジュールで定義された
  ユーザー定義型に限り…』などのコンパイルエラーが生じているとか)


> ローカル変数に保持する方法を教えて頂けないでしょうか
そもそも、その Recordset 自体もローカル変数なのでは。

編集 削除
たやま  2010-11-07 00:04:41  No: 102676  IP: [192.*.*.*]

大変申し訳ございません。
経験不足で説明が不足しておりました。

>何の VBA をお使いなのでしょうか?
Excelを使用してます。

下記サンプルプログラム上でDBから取得した場合、
DBから取得した値は、dbResの中に保持されていると思われますが、
dbResの値を別のレコードに保持(dbRes1)し、「dbRes.Update」
を実行した後でdbResとdbRes1の差分を比較したいと
考えております。
いろいろ試してみましたが、dbRes.Update実行した場合、同時に
dbRes1も更新されているようです。
dbRes1を更新しないようにできないでしょうか?


    Dim dbCon As New ADODB.Connection
    Dim dbRes As New ADODB.Recordset
    Dim dbRes1 As New ADODB.Recordset

    Do Until dbRes.EOF
        ' 行の変数を加算
        GYO = GYO + 1
        ' テーブルの登録全フールドをセルにセット
        COL = 0
        For Each dbCol In dbRes.Fields
            COL = COL + 1
            Cells(GYO, COL).Value = dbCol.Value
        Next dbCol
        ' 次のレコードに移る
        dbRes.MoveNext
    Loop
    '

編集 削除
魔界の仮面弁士  2010-11-07 09:59:48  No: 102677  IP: [192.*.*.*]

> dbRes1を更新しないようにできないでしょうか?

Recordset を Update しても、元となる DB にそれを反映させたく無いと
いう意味であれば、切断型(コネクションレス)の Recordset にすれば OK です。

手順は、ADO のヘルプ(MDAC SDK)に記載されている
[ADO プログラマーズ ガイド]
  [セクション I: ActiveX Data Objects (ADO)]
    [第 5 章: データの更新および永続化]
      [データの更新]
        [バッチ モード]
を参照してください。

------
ざっくり書くと、dbRes をクライアントバッチカーソルモード
(adLockBatchOptimistic)で開くようにし、さらに ActiveConnection に
Nothing を Set してから更新すれば OK ということです。
(dbRes は、いわゆる切断型 Recordset になります)

このようにすれば、dbRes に変更/削除/追加の処理を加えても、
DB 側には反映されないため、dbRes1 側には変更が伝わりません。


もうひとつの方法は、ADODB.Stream のインスタンスを生成しておき、
その Stream に ADTG 形式で dbRes.Save し、それを dbRes1.Open で
再 Open することでも、同じような結果を得る事ができます。


それ以外の手法としては Open 前の dbRes に対して、Fields.Append で
列定義を定め、Conenction を指定せずに、引数なしで dbRes.Open して
「空の Recordset を作っておく」という手もあります。この dbRes に、
dbRes1 側の内容を AddNew 等で転記して利用します。

編集 削除
たやま  2010-11-07 10:46:22  No: 102678  IP: [192.*.*.*]

>魔界の仮面弁士さん

いろいろな情報ありがとうございます。
教えて頂いた情報をもとにトライしてみます。

編集 削除