2

フォーム コントロールの値に基づいて vba で作成した SQL を使用して、クエリまたはレコードセットなど (データシート ビュー) を開く必要があります。私のデータには「多対多」の関係があります(一種の)。Person テーブル、Pet テーブル、および ID Pet_Person テーブルがあるとします。返されたデータの 1 行にすべてのペットを連結した文字列を含む People のリストを作成したいと考えています。そう....

Row    Person       Pets
1      Kim          Lucius, Frodo, Cricket, Nemo
2      Bob          Taco

そして、グーグルで調べたところ、VBAで関数を記述してSQLから呼び出すことができることがわかりました。そう。これが問題です。多くのレコードがあり、一度開くと、行をクリックするたびにその連結関数が呼び出されないと、データシートビュー/クエリ/その他を移動できません。SQLが最初に実行されたときに一度だけ呼び出す必要があります...スナップショットなどのように。

私は Access とその可能性にあまり精通していません。オンラインで見つけたいくつかのことを試してみましたが、すべて同じ結果になりました...その結果のデータセットにまったく触れたときに連結関数が呼び出されました。

最後に試したのは次のようなものです。

With db
        Set qdf = .CreateQueryDef("Search Results", q)
        DoCmd.OpenQuery "Search Results", , acReadOnly
        .QueryDefs.Delete "Search Results"
End With

StackOverflow は、私のものを正しくフォーマットすることは決してありません。おそらくユーザーエラー....ああ、まあ。

編集:

ああ、バート S. ありがとうございます。でも、あなたはすぐに去ってしまい、そこに答えがあるかどうかを理解できませんでした。ありがとうございました。

あ、レム。 はい、あなたの投稿を見ました。私はあなたの投稿を使用しました。このプロジェクトに取り組んでいる間、私はあなたの投稿の多くを使用しました。Access がすべての SQL 関数をサポートしていない理由は、MySQL に慣れているためわかりません。あなたはこのサイトのすばらしい仲間です。質問にリンクするべきでしたが、コーヒーはまだ入っていませんでした。

連結関数があり、SQL 内で呼び出しています。そのrecorsetやクエリなどを開くためにdocmdで開いていました。しかし、これが私の問題です(一度にあまりにも多くのソリューションを試して自分でこれを作成している可能性があります。または、何かを見落としている可能性があります)...結果のデータセット/クエリ/ものに触れるたびに、その関数を呼び出し続けますそして、それが起こるにはデータが多すぎます。砂時計を見すぎているだけです。これは、私がそれを開く方法が原因であると確信しています。これは、検索フォーム画面の結果であることを意図しています。私は文字通りアクセスで別のフォームを作成し、結果のレコードセットを入力する必要があると考えています。皆さんのおっしゃる通りだと思います。わからない。これは奇妙な例です。しかし... Excelでは、各行の値を取得するためにある種のインライン関数を作成するとわかります...そして、値だけに特別なコピーアンドペーストを行います(関数ではありません)...私はそれが必要です。この関数(明らかにExcelではありません)はクエリを実行する必要があり、行がクリックされるたびに再適用するのに時間がかかるためです(単一の行がクリックされた場合、実際には各行を再クエリしていると思います. SQLまたは何かを再実行します)。NIN/Depeche Mode の曲のように Dead Souls... それは私/それを呼び続けます。

4

2 に答える 2

2

私はいつも次のようにしています。

Dim strSql As String

strSql = "SELECT * FROM table WHERE field=something;"
Set rs = CurrentDb.OpenRecordSet(strSql)

次に、RS を使用してアクションを実行します。もっと良い方法があるかもしれません。たとえば、Access で直接クエリを作成し、VBA から呼び出すことができます。

レコードセットをループしている間に、文字列を連結できます。

Dim strResult As String
While (Not rs.EOF)
  strResult = strResult & rs!yourfield
WEnd
于 2012-05-15T13:52:37.227 に答える
2

一定のデータ再読み込みの問題に対処するためのいくつかの考えと戦略を次に示します。

  1. クエリが に設定されていることを確認してくださいsnapshot。フォームも同じ。
    もちろん、これによりデータは読み取り専用になりますが、少し役立つ場合があります。

  2. クエリの結果をローカル テーブルにキャッシュし、クエリ自体の代わりにそのテーブルを表示/バインドします。
    これにより、クエリが実行されてローカル テーブルに保存されるまで、ユーザーは最初は少し長く待たされますが、すべてのデータがローカルであり、再計算する必要がないため、その後のインターフェイスがはるかにスムーズになります。

    • localPetResultクエリのフィールドと一致するすべてのフィールドを持つローカル テーブルを (クライアント側で) 作成します。

    • クエリ自体をデータシート フォームにバインドする代わりに、をバインドしてlocalPetResultから、フォームの VBA モジュールで OnLoad イベントを処理します。

      Private Sub Form_Load()
          ' Remove all previous data from the local cache table '
          CurrentDb().Execute "DELETE FROM localPetResult"
      
          ' Define the original query '
          Dim q as String
          q = q & "SELECT Row, "
          q = q & "       Person, "
          q = q & "       Coalesce(""SELECT PetName FROM Pets WHERE Person='"" & [Person] & ""',"","") AS PetNames "
          q = q & "FROM MyData"
      
          ' Wrap the query to insert its results into the local table '
          q = "INSERT INTO localPetResult " & q
      
          ' Execute the query to cache the data '
          CurrentDb().Execute q
      End Sub
      

      機能するようになったら、さまざまな方法でこれを改善して、より良くすることができます (画面をフリーズして砂時計を表示する、データが計算された後に ersult テーブルをフォームに動的にバインドするなど)。

  3. 合体関数への各呼び出しの結果をキャッシュします。
    これを使用して、レコードごとに 1 回連結を計算し、その結果をキーがレコードの ID である Dictionary に格納します。同じ ID の後続の計算は、再計算されるのではなく、辞書から取得されます。

    たとえば、VBA モジュールに次を追加します。RemouのCoalesce機能も使っていると思います。

        Option Compare Database
        Option Explicit
    
        ' A Scripting.Dictionary object we'll use for caching '
        Private dicCache As Object
    
        ' Call to initialise/reset the cache before/after using it '
        Public Sub ResetCoalesceCache()
            If Not (dicCache Is Nothing) Then
                dicCache.RemoveAll
            End If
        End Sub
    
        ' Does the Same as Coalesce() from Remou, but attempts to '
        ' cache the result for faster retrieval later '
        Public Function Coalesce2(key As Variant, _
                                  sql As String, _
                                  sep As String, _
                                  ParamArray NameList() As Variant) As Variant
    
            ' Create the cache if it hasn't been initialised before '
            If dicCache Is Nothing Then
                Set dicCache = CreateObject("Scripting.Dictionary")
            End If
    
            If IsNull(key) Then
                 ' The key is invalid, just run the normal coalesce '                                       
                 Coalesce2 = Coalesce(sql, sep, NameList)
            ElseIf dicCache.Exists(key) Then
                ' Hurray, the key exists in the cache! '
                Coalesce2 = dicCache(key)
            Else
                ' We need to calculate and then cache the data '
                Coalesce2 = Coalesce(sql, sep, NameList)
                dicCache.Add(key, Coalesce2)
            End If
    
        End Function
    

    次に、クエリで使用するには:

        ' first clear the cache to make sure it doesn't contain old '
        ' data that could be returned by mistake '
        ResetCoalesceCache
    
        ' Define the original query '
        Dim q as String
        q = q & "SELECT Row, "
        q = q & "       Person, "
        q = q & "       Coalesce2([Row], ""SELECT PetName FROM Pets WHERE Person='"" & [Person] & ""',"","") AS PetNames "
        q = q & "FROM MyData"
    
        ' Bind to your form or whatever '
        ...
    
于 2012-05-16T03:34:35.770 に答える