次の方法で共有

複数のサブフォームのRecordsetを低負荷で設定したい

Anonymous
2015-09-10T00:56:18+00:00

複数のサブフォームのRecordsetを低負荷で設定する方法を探しています。

■やりたい事。

1つメインフォームに複数のサブフォームがあります。

メインフォームはサブフォームを表示するためだけの器です。

例えば注文情報を蓄積した注文テーブルが1つあるとして、

サブフォーム毎に異なる条件でフィルタした注文レコードを表示させる、というようなものです。

下記の様なイメージのフォームを作成しています。

+メインフォーム

++サブフォーム1 (必要なレコード = Recordset_A * Filter_1)

++サブフォーム2 (必要なレコード = Recordset_A * Filter_2)

++サブフォーム3 (必要なレコード = Recordset_A * Filter_3)

++ (以下同様)

■課題、理由

しかし、単純に各サブフォームに

 ・レコードソース=Query_Recordset_A

 ・フィルタ=Filter_1

と設定すると、メインフォームの起動時に非常に重くなってしまいました。

サブフォームの数だけ新規にテーブルを読み込みに行ってると思いますので

当然かもしれません。

そこで、大元のRecordsetは共通していますので、1回読み込んだRecordsetを使い回す、

つまりVBAでフィルタ操作などして各サブフォームにセットしてやれば軽くなると考え、今回の方法を検討しています。

■試行

メインフォーム、各サブフォームのレコードソース、フィルターは空欄

下記コードをメインフォームのOpenイベントで実行。

(Open後にコマンドボタンのClickイベントでフィルタ条件を変更する事もある)

//コード

Dim rs As New ADODB.Recordset       '共通のRecordset

Dim rsC As New ADODB.Recordset      '作業用のRecordsetClone

' 共通Recordsetの取得

rs.CursorLocation = adUseClient

rs.Open "Query_Recordset_A", CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly, adCmdTable

’ 必要なレコードを抽出

Set rsC = rs.Clone

rsC.Filter = "注文日=#" & Date & "#"

' サブフォームにRecordsetを設定

Set Me.subfサブフォーム1.Form.Recordset = rsC    ' ← ここでエラー

'Set Me.subfサブフォーム1.Form.Recordset = rs.Clone    ' ← これでもエラー

//結果

上記最後のRecordsetプロパティへrsCを設定しようとすると次のエラーが発生します。

「実行時エラー '-2147467259(80004005)':

'Recordset' メソッドは失敗しました: '_Form_サブフォーム1' オブジェクト」

なぜか「Recordset『メソッド』」になってますし、何が失敗したのか不明です。

また、別パターンとして、rs.Cloneを設定しようとすると、今度は別のエラーが発生します。

「実行時エラー '3001':

引数が間違った型、許容範囲外、または競合しています。」

ここで詰まってしまいました。

■質問

上記の回避策はありますでしょうか。

あるいは今回の目的では別の望ましい方法がありますでしょうか。

どうぞ宜しくお願いします。

Microsoft 365 と Office | アクセス | 家庭向け | Windows

ロックされた質問。 この質問は、Microsoft サポート コミュニティから移行されました。 役に立つかどうかに投票することはできますが、コメントの追加、質問への返信やフォローはできません。

0 件のコメント コメントはありません

質問作成者が受け入れた回答

Anonymous
2015-09-10T08:21:58+00:00

最初にボタンやタブによるフィルター切替も試してみたのですが、実際には利用上煩わしかったため、

ユーザーの積極的に利用する意欲を削ぎかねないと判断し、これらの手法は不採用になってしまいました。

3つのフォームは常時表示しているということですね。

レコードセットを使い回すということですが、

まず、抽出条件を設定しないレコードセットを読み込む。

Cloneを作成して、Filterを設定する。

ということのようですが、

ヘルプには、

Filterで抽出するより、レコードセットを開くときに、SQLのWHERE句で抽出条件を設定したほうが高速だという記載があります。

これを考えたら、Filterを使うことでそれほど高速化されるとは思えません。

すなおに、サブフォームのレコードソースに抽出条件付きのクエリを設定すればいいのかなと、思います。

ReadOnlyで開いているようなので、フォームの「レコードセット」プロパティを「スナップショット」に設定しておけば、負荷も軽減できます。

あと、フォームを開くのを高速化する目的でしたら、私なら下記のような設計を採用するかな。

サブフォーム1のみソースオブジェクトを設定しておいて、

「タイマー時」のイベントで、サブフォーム2、サブフォーム3 のソースオブジェクトを設定する。

これなら、サブフォーム1 のレコードを読み込み終了と同時にメインフォームが表示されて、

その後、サブフォーム2、サブフォーム3のレコードが読み込まれる。

形になります。

ユーザーは無反応のまま長時間待たされるということは回避できます。

なお、Me.subfサブフォーム1.Form.Recordset に Recordsetオブジェクト(ADO) を Set するという構文は

問題無いでしょうか。Me.subfサブフォーム1.Form.Recordset はメソッドと認識されるのでしょうか。

私自身は、ADOレコードセットをフォームに連結することにメリットがあるとは思っていないので、実運用で採用したことはなく、この件に関しては、アドバイスできるものは持っていません。

他の方の回答をお待ち下さい。

この回答は役に立ちましたか?

0 件のコメント コメントはありません

質問作成者が受け入れた回答

Anonymous
2015-09-10T08:18:58+00:00

> rs.Open "Query_Recordset_A", CurrentProject.Connection,

> adOpenForwardOnly, adLockReadOnly, adCmdTable

ADODB.Recordset オブジェクトを

フォームにバインドさせるのであれば

Connection プロパティではなく

AccessConnection プロパティが返す

ADODB.Connection オブジェクトを渡すようにされた方がよいでしょう。

(2015/09/10 18:47追記)

バインドされたフォームのレコードを編集したい場合は、

Access のバージョンによってはむしろ

Connection プロパティの方がよい場合もあります。

Connection プロパティで問題がなければ

上記のコメントは無視して下さい。

この回答は役に立ちましたか?

0 件のコメント コメントはありません

5 件の追加の回答

並べ替え方法: 最も役に立つ
  1. Anonymous
    2015-09-14T00:49:43+00:00

    結果報告です。

    今回はサブフォームのRecordSourceプロパティにSQL文を設定することに落ち着きました。

    このSQL文は、条件に応じて組み立てています。

    ただ、(これはお伝えしていませんでしたが)オープン後にもコマンドボタンによってこの条件を再評価→SQL再組み立てを行っています。

    つまりフォームオープン時とボタンクリック時にレコードを読み込んでいます。

    その為、最初に読み込んだ基礎的なRecordsetを保持しておきその後フィルタを掛けるという事を

    検討してみたのですが、上手くいかないばかりか余計遅くなるという事が分かったため

    単純にRecordSourceプロパティを制御することにしました。

    この方法だとレコード取得までに多少のタイムラグはありますが、費用対効果の落とし所としました。

    sk.exeさん、hatena19さん、今回もありがとうございました。

    この回答は役に立ちましたか?

    0 件のコメント コメントはありません
  2. Anonymous
    2015-09-11T00:58:54+00:00

    3つのフォームは常時表示しているということですね。

    その通りです。(現状では6つ程、今後の増減もあり得ます。)

    ヘルプには、

    Filterで抽出するより、レコードセットを開くときに、SQLのWHERE句で抽出条件を設定したほうが高速だという記載があります。

    これを考えたら、Filterを使うことでそれほど高速化されるとは思えません。

    確かに、.Filterの設定をやめたら重さが結構軽減されました。

    すなおに、サブフォームのレコードソースに抽出条件付きのクエリを設定すればいいのかなと、思います。

    SQLを組み立てる方で検討します。

    あと、フォームを開くのを高速化する目的でしたら、私なら下記のような設計を採用するかな。

    サブフォーム1のみソースオブジェクトを設定しておいて、

    「タイマー時」のイベントで、サブフォーム2、サブフォーム3 のソースオブジェクトを設定する。

    これなら、サブフォーム1 のレコードを読み込み終了と同時にメインフォームが表示されて、

    その後、サブフォーム2、サブフォーム3のレコードが読み込まれる。

    形になります。

    ユーザーは無反応のまま長時間待たされるということは回避できます。

    なるほど、WEBサイトの設計と同じような考え方ですね。

    体感速度までは考えてませんでした。検討してみます。

    私自身は、ADOレコードセットをフォームに連結することにメリットがあるとは思っていないので、実運用で採用したことはなく、この件に関しては、アドバイスできるものは持っていません。

    一晩調べてみましたが、確かにあまり一般的な手法ではないようです。

    私のレベルで手法の是非をアレコレ考えるより、ここは素直に先達に倣おうかと思っています。

    今一度検討し直してみます。

    この回答は役に立ちましたか?

    0 件のコメント コメントはありません