2013-12-16 21 views
3

所以我已經研究了好幾天,現在如何在一個方式,是舒適的控制篩選行來源的結果,希望你明白我的意思是說作爲我解釋。我找到了解決方案,一堆解決方案。我更關心評估他們的好處和否定。查詢篩選,找出執行的靈活性和易用性之間的平衡

我有一個具體的例子,但我的關注更真實。對我而言,這似乎是我的應用程序的支柱,所以我想確保它是正確完成的,最好的方式,而不僅僅是「有效」的方式。

基本上,我有漸進的組合框過濾器。第一個框過濾第二個框,然後在「單一窗體」視圖中選擇一條記錄。這兩個組合框位於表單的標題中。

可以說我有一張表CanadianCities。這兩個組合框可能是cboProvinceFilter「按省篩選」,cboCitySelect「選擇城市」

當我加載表格時,省過濾器關閉,所以城市列表中填充了一個選擇所有城市的行源SELECT ID,CityName FROM CanadianCities)。但這是一個很大的列表,所以我有第二個組合框來縮小列表的範圍(SELECT ID,ProvinceName FROM CanadianProvinces)。

所以我們的目標是在cboProvinceFilter.AfterUpdate重新查詢cboCitySelect並更改where子句(「[...] WHERE ProvinceID = [cboProvinceFilter]」)。

問題在於如何修改where子句。理想情況下,上述方法可以在設計器中正常工作,但SQL設計似乎超出了表單的範圍,所以cboProvinceFilter在那裏不存在。我同意這種觀點,即直接參照形式不好。我不想嫁給我的SQL到這樣的形式。另外,我想使用一個導航窗體,但也有一個移動選項,因此在導航中單獨運行窗體並且在導航中運行將是理想的,絕對參考無法做到這一點。

有埋在我的代碼重複的SQL語句,感覺像設計很差,稍有不同的過濾重複同樣的疑問是可怕的,當參數正是出於這個原因。

有些人會對此嗤之以鼻,但是在VBA中重寫Access設計器的功能也不好。如果我構建自己的SQL,執行自己的查詢並填充自己的列表,那麼爲什麼Microsoft將所有努力都放在構建這種生產力協助工具上?過濾並不完全是數據庫管理的晦澀難懂的功能......我覺得必須有合理的方法來做這種事情。另外,彈出式窗體很討厭,所以我不會製作具體的窗體只是爲了擁有可靠的絕對引用。這絕對感覺像一個警察。

的解決方案,這樣做感覺很好,但我沒有做工作......

SQL參數 這樣做的最明智的方式,我覺得應該是使用SQL參數,因爲這是他們打算什麼對嗎? QueryDef將存儲它的參數值,我可以根據需要進行更改。但是,我會讓查詢自然執行查詢。

因此,而不是寫行執行查詢並填充控制的少數,我只是設置的參數值,並呼籲我的控制,這所有的功能內置到它重新查詢。

因此,在SQL語句中定義了一些參數,然後在執行查詢之前嘗試在VBA中設置這些參數的值,但是如果參數沒有引用實際對象,JET似乎總是彈出來,它沒有檢查我的代碼集querydefs。

爲了這個工作,似乎我必須手動執行SQL,並解析我自己的記錄集,並填充控件。對於我想要提供的每個過濾器選項,這感覺就像是過多的重複。

相對引用 我不介意引用表單,只要它是相對路徑即可。不幸的是[屏幕] [ActiveForm]指的是導航形式,而不是實際的,活動的形式......因此,似乎已經出來。

現在我想我唯一的選擇是手動設置rowsource然後調用控件的查詢。這是較不令人反感的選擇。可能最好採取當前查詢和字符串替換where部分,所以如果查詢結構發生變化,我不必更新每個事件。

最後的想法 無論如何,這是越來越簡陋,所以讓我知道你的想法。我並不是真的在尋找代碼解決方案,這就是爲什麼我沒有提供很好的例子。我正在尋找一種管理這種過濾的範例,這種過濾不是太嚴格(絕對參考),也不是太重複/重新發明(硬編碼sql,執行,控制填充)。

回答

1

如果您的Access版本> = 2007,則可以使用TempVars Collection。這是一個即時窗口會話。

' add a TempVar with value 
TempVars.which_id = 12 
' or do it explicitly with Add method 
TempVars.Add "which_id", 12 
? TempVars!which_id 
12 
' asking for the value of non-existent TempVar returns Null 
? TempVars!bogus 
Null 

查詢可以引用TempVar來過濾結果集。

SELECT f.* 
FROM tblFoo AS f 
WHERE f.id=[TempVars]![which_id] OR [TempVars]![which_id] Is Null; 

所以,你可以使用這種方法在該行源查詢的cboCitySelect組合框。然後在cboProvinceFilter和接下來的RequerycboCitySelect之後分配After更新事件中的TempVar值。

對於Access版本< 2007,TempVars Collection不可用。在這種情況下,您可以使用自定義VBA函數來保存可以在查詢中引用的靜態值。

SELECT f.* 
FROM tblFoo AS f 
WHERE f.id=TargetId() OR TargetId() Is Null; 
Public Function TargetId(Optional ByVal pValue As Variant) As Variant 
    Static varReturn As Variant 
    If IsMissing(pValue) Then 
     If VarType(varReturn) = vbEmpty Then 
      varReturn = Null 
     End If 
    Else 
     varReturn = pValue 
    End If 
    TargetId = varReturn 
End Function 
+0

這一評論可能打破規則,但輝煌。 – user3108399

+1

我考慮使用一個變量進行過濾,並傾向於此,但TempVars更加優雅(即使它本質上相同)。 SetTempVars是一個宏函數,所以設置過濾器值然後重新查詢AfterUpdate宏中的其他控件是非常容易的。因爲一個不存在的TempVar返回null,所以我只是做舊的「... WHERE(ProvinceID = [TempVars]![ProvinceID_Filter])OR([TempVars]![ProvinceID_Filter Is Null)如果TempVar是Null,而不是沒有行,則會獲得所有行。 – user3108399