Tham chiếu điều kiện của Query đến 1 biến trong Access?

Liên hệ QC

sealand

Thành viên gạo cội
Tham gia
16/5/08
Bài viết
4,884
Được thích
7,687
Giới tính
Nam
Nghề nghiệp
Kế Toán
Trên lưới tạo lập query trong Access ta có thể tham chiếu đến (Trong VD dưới đây Table DATA có field: nam để ghi năm của chứng từ):
1-Một điều khiển trên 1 Form
"SELECT * FROM DATA WHERE DATA.nam = Forms![DK_loc]!Nam" Tại ô tiêu chuẩn gõ: = Forms![DK_loc]!Nam
2-1 thông tin nhập vào
"SELECT * FROM DATA WHERE DATA.nam = ["Nhap nam:"]" Tại ô tiêu chuẩn gõ:= ["Nhap nam:"]

Mình muốn tham chiếu đến biến Global (Toàn cục) thì câu lệnh trên sửa thế nào và trên lưới thiết kế Query đưa vào đâu để được chấp nhận trong Access. Lưu ý là không dùng field phụ để lọc nhé.
Mong anh em giúp đỡ. Xin cảm ơn.
 
Lần chỉnh sửa cuối:
Anh phải tạo 1 function để lấy giá trị của biến Global đó, sau đó mới gán vào câu lệnh SQL. Và đối với những trường hợp này phải dùng Form để thao tác, ví dụ muốn gán giá trị cho biến toàn cục, ...

Đại khái như sau:
[highlight=VB]
Global myString as String
'--------------------------
Public Function myGlobal()
myGlobal = myString
End [/highlight]
PHP:
SELECT * FROM tbData WHERE tbData.Nam = myGlobal()

Tham khảo thêm tại đây
 
Lần chỉnh sửa cuối:
Cám ơn Ca_dafi, biến Global là biến toàn cục và nó tồn tại suốt quá trình chạy chương trình. Ta đã khai báo nó khi đăng nhập chương trình bằng câu lệnh Public rồi (Public nam as string). VD: Chọn năm làm việc: 2009 thì biến nam luôn tồn tại . Khi cần ta chỉ việc gọi nó không phải khai và set giá trị nữa.
Câu lệnh của Ca_dafi đúng là chạy theo lệnh VB thì OK, nhưng đưa vào Query được tạo sẵn của Access thì không được. Nhờ Ca_dafi xem lại giúp.
 
Lần chỉnh sửa cuối:
Vậy anh gửi file lên để mọi người cùng xem nhé! Em không biết không được là không được như thế nào!?
 
Theo thiển ý của tôi, khi tạo biến tòan cục, ta có thể gán biến nảy vào một trường của một table nào đó của CSDL được không? Và khi cần thì gọi nó ra phục vụ cho công tác tính tóan
 
Theo thiển ý của tôi, khi tạo biến tòan cục, ta có thể gán biến nảy vào một trường của một table nào đó của CSDL được không? Và khi cần thì gọi nó ra phục vụ cho công tác tính tóan
Ngay từ đầu tác giả đã nói là không dùng field phụ rồi mà.
To cadafi: Nếu dùng trực tiếp trên Form thì không cần phải dùng qua hàm mà có thể dùng trực tiếp biến luôn, ở đây tác giả hỏi là thao tác trong lưới tạo Query
Theo tôi thì không có cách nào, vì biến toàn cục thì phải khai báo trong Module, mà Module thì không có trạng thái running. Với ví dụ của Forms thì ta cũng chỉ thao tác được khi form đang trong chế độ running, còn nếu ta đóng form lại thì nó lại hiểu thành Tham số như thường
 
Rất cám ơn anh em và xin khất đến buổi tối mình sẽ chuẩn bị 1 ví dụ thật cụ thể, tầm giờ xếp triệu liên tục . Mong anh em thông cảm.
 
Dear all,
-------

Em đồng ý với rollover79, nếu để tham chiếu đến 1 biến thì chắc chắn phải đặt trong môi trường VBA rồi. Và dù trong môi trường nào thì khi truy vấn đến giá trị của một điều khiển trên Form thì Form đó cũng phải đang mở, khái niệm biến toàn cục hầu như không liên quan đến loại truy vấn này.

Theo em, việc lưu trữ SQL trong Query không phải là một cách hay, không thuận tiện và khó bảo trì. Em luôn tạo các truy vấn trong Query sau đó chuyển nó sang một thủ tục hoặc hàm để có cơ hội sử dụng lại và xử lý linh hoạt hơn.
 
Mình xin gửi file ví dụ và mong muốn của mình là đưa biến thang vào Q01_loc_thang (Phần Criteria ... or.... ấy) thay vì Forms!Form1!th
Trong file ví dụ bất cứ lúc nào mở form2 không liên quan tới set biến tháng kiểm tra vẫn thấy giá trị của biến thang (Tức là biến này luôn tồn tại nếu ta không cố tình xóa nó đi)

Nói chung các bạn đã hiểu ý mình rồi, mình tạo biến bằng VBA và dùng biến lưu giữ các thông tin thay vì vẫn phải chay nền 1 form . Sau khi xem trên datasheet ta muốn in report thì còn phải lấy lại thông tin để lập query của Report chạy(View dữ liệu và tạo Report là 2 query riêng vì cấu trúc và kết xuất dữ liệu khác nhau). Tất nhiên, có lý do mình không muốn sử dụng lệnh trong VBA khi mở QR trong trường hợp này. Mong các bạn xem giúp.

To Đào Việt Cường: Trong ví dụ mình muốn chứng minh cái biến đó nó vẫn tồn tại khi không có code VBA nào hoạt động nữa và mình muốn lấy chúng làm nơi lưu giữ các thông tin chung của 1 phiên làm việc.
To XuanThanh: Đúng là thực tế làm như vậy, ví dụ 1 file kế toán có thể quản lý n đơn vị. Lưu các thông tin chung vào 1 table T01_INFO. Khi chọn đơn vị nào thì sẽ load các thông tin đó lên các biến chung dạng này: như tên Đ/vị, mã số thuế, địa chỉ ...Biến của mình thuộc dạng trên sau khi đã load
 

File đính kèm

  • Hoi GPE.rar
    70 KB · Đọc: 351
Lần chỉnh sửa cuối:
Mình xin gửi file ví dụ và mong muốn của mình là đưa biến thang vào Q01_loc_thang (Phần Criteria ... or.... ấy) thay vì Forms!Form1!th
Trong file ví dụ bất cứ lúc nào mở form2 không liên quan tới set biến tháng kiểm tra vẫn thấy giá trị của biến thang (Tức là biến này luôn tồn tại nếu ta không cố tình xóa nó đi)

Sau khi xem trên datasheet ta muốn in report thì còn phải lấy lại thông tin để lập query của Report chạy(View dữ liệu và tạo Report là 2 query riêng vì cấu trúc và kết xuất dữ liệu khác nhau). Tất nhiên, có lý do mình không muốn sử dụng lệnh trong VBA khi mở QR trong trường hợp này. Mong các bạn xem giúp.

Dear sealand,
-------------
Nếu vậy chắc phải khai báo một Parameter trong SQL và sử dụng biến này để điền giá trị cần truy vấn, ví dụ:

PHP:
PARAMETERS prmThang Byte;
SELECT Data.loai, Data.ngay, Data.thang, Data.so, Data.noidung, Data.tkno, Data.tkco, Data.tien, Data.makh
FROM Data
WHERE (((Data.[thang])=[prmThang]));

Nhưng theo cách này khi cần xử lý truy vấn bằng mã lệnh VBA sẽ phức tạp hơn nếu muốn truyền tham số cho prmThang. Theo em cách làm linh hoạt nhất vẫn là truyền tham số vào SQL string bằng value nhận được từ textbox, ví dụ:

Private Sub Command4_Click()
Dim myQuery As QueryDef
Set myQuery = CurrentDb.QueryDefs("Q01_loc_thang")
DoCmd.Close acQuery, myQuery.Name
myQuery.SQL = Q01_loc_thang
DoCmd.OpenQuery myQuery.Name, acPreview
End Sub


Function Q01_loc_thang() As String
Q01_loc_thang = "SELECT loai, ngay, thang, so, noidung, tkno, tkco, tien, makh " & _
"FROM Data " & _
"WHERE thang= " & thang
End Function

sealand đã viết:
có lý do mình không muốn sử dụng lệnh trong VBA khi mở QR trong trường hợp này.
Không biết "lý do" đó có to hơn "mục đích" không, nhưng em thấy sử dụng lệnh trong VBA vẫn là một lợi thế!%#^#$
 
Dùng Parameter thì không được rồi vì khi mở nó không nhận biến thang mà nó bắt mình nhap thang.
Hướng thứ 2 của Cường cũng rất khả quan nhưng mình lại không chủ động định dạng để view trên Datasheet. Mình thích dátahheett hơn Form vì tốc độ và các chế độ lọc tìm sẵn có của Access. Để mình test cụ thể rồi thỉnh ý thêm.
Xin cám ơn nhé.
 
Mình thích datasheet hơn Form vì tốc độ và các chế độ lọc tìm sẵn có của Access.

Form có chế độ Datasheet View mà Sealand?
Hướng là như vầy:
- Trên form dùng combobox hoặc text box, chọn [thang]
- Nhấn nút hoặc dùng sự kiện AfterUpdate gì đó, mở datasheet form khác, hoặc mở query, hoặc chuyển chính form này thành Datasheet view. Hoặc làm như cũ của Sealand.

Sau khi xem trên datasheet ta muốn in report thì còn phải lấy lại thông tin để lập query của Report chạy(View dữ liệu và tạo Report là 2 query riêng vì cấu trúc và kết xuất dữ liệu khác nhau).

Thì vẫn gán giá trị cho biến thang như bình thường.
DataSource của Report thì bình thường theo SQL hoặc tạo trên lưới lưu lại Query tùy ý, thí dụ lưu là Q01, không cần điều kiện lọc (Criteria). Thậm chí cấu trúc và field trích xuất khác hoàn toàn với Q01_loc_thang.

Code của Report thì thêm câu này vào:

PHP:
Private Sub Report_Open(Cancel As Integer)
Me.FilterOn = True
Me.Filter = "thang = " & thg
End Sub

Đề xuất: biến đặt khác với field name, thí dụ thg thay vì thang.
 

File đính kèm

  • Hoi GPE.rar
    79.7 KB · Đọc: 106
Mở rộng thêm thủ thuật gán Filter:

1. Query không cần lọc sẵn theo criteria
2. Form cũng có Property Filter, và cũng có Datasheet view (method view acFormDS)
3. Khi Open form hoặc open report, gán Filter vào bằng 1 chuỗi kèm theo biến, hoặc kèm theo giá trị của 1 combobox trên form gọi.
4. Chuỗi Filter này có thể là điều kiện phức hợp với And và Or, và cả IIf(). Thí dụ dùng 2 option buttons để chọn hoặc in báo cáo hết, hoặc chỉ in báo cáo 1 khách hàng. Căn cứ vào Option nào được chọn, ta có 1 chuỗi Filter tương ứng để open report.

Sealand xem file thí dụ, nếu xài được, khen lão chết tiệt 2 chữ “tuyệt chiêu”, nha.
 

File đính kèm

  • Hoi GPE.rar
    86.4 KB · Đọc: 120
Mình thích datasheet hơn Form vì tốc độ và các chế độ lọc tìm sẵn có của Access. Để mình test cụ thể rồi thỉnh ý thêm.

ptm0412 đã viết:
Form có chế độ Datasheet View mà Sealand?

Dear all,
---------
Bởi vậy em mới nói, "lý do" to hơn hay "mục đích" to hơn! Nếu mục đích sử dụng truy vấn để lập báo cáo, chỉ việc "Click to Preview/Print" thì nên đưa SQL vào thủ tục VBA để xử lý. Còn nếu để lọc, tìm kiếm... thì sử dụng ngay Data table là tiện quá rồi, cần gì phải thiết kế thêm form DataSheet cho... tốn bộ nhớ! :-=(có chăng thì nên thiết kế Main/Sub để nhập liệu cho thuận tiện)
 
Ptm0412 ốm khỏi chưa? Thấy trở lại là tốt rồi.
Mình muốn lọc trên Datasheet chứ không phải trên report. Lý do là không phải chỉ có xem thôi mà khi duyệt các Record thì đồng thời phải lấy được mã số của chứng từ của dòng kết quả. Khi phát hiện sai sót không phải thoát ra mà nhấn phím chức năng (F1-12) hay nhấp đúp vào dòng đó phải mở lại chứng từ đó để sửa chữa. Nếu nhấn Enter mở chi tiết cấp 2. Đây là cơ chế quản trị dữ liệu Drill-Down rất được ưa thích.
Hơn nữa, trong các phần mềm kế toán hiện nay đều có 2 chức năng xem và in sổ sách (Thêm cả chuyển đỏi dữ liệu sang Excel chẳng hạn). Nhưng nếu xem bằng Printview thì hiện nay ít dùng và người sd không chấp nhận được. Nó không hoạt như không có dòng Current, không lọc , tìm hay xắp xếp được...
Nếu có thể, các bạn hướng dẫn mình cách view 1 Recordset trong Access với. Như vậy thì ta có thể bỏ qua cái QueryDefs này đi mà sử dụng ADO cho gọn
Chúc Pmt mau khỏe hỗ trợ anh em với nhé. Cám ơn các anh em giúp đỡ.
 
Lần chỉnh sửa cuối:
Lý do là không phải chỉ có xem thôi mà khi duyệt các Record thì đồng thời phải lấy được mã số của chứng từ của dòng kết quả. Khi phát hiện sai sót không phải thoát ra mà nhấn phím chức năng (F1-12) hay nhấp đúp vào dòng đó phải mở lại chứng từ đó để sửa chữa. Nếu nhấn Enter mở chi tiết cấp 2. Đây là cơ chế quản trị dữ liệu Drill-Down rất được ưa thích.

Dear sealand,
-------------
Thì ra đây là lý do để anh "yêu thích" Query hơn là Report!

Theo em công dụng chính của Report là Print và Preview, đương nhiên nó không cho người dùng can thiệp vào Database nữa (đó là đối với Access, ngoại trừ một số phần mềm tạo báo cáo chuyên nghiệp vẫn cho phép "mở ngược lại" cơ sở dữ liệu ngay trên báo cáo (đờ-riu-đao hay búa gì gì đó!). Nhưng theo em vấn đề chỉnh sửa dữ liệu trên Access không phải chỉ là sửa trên Query (thực ra có những Qrery không được sửa) hay trên Datasheet (Table/Form) mà vấn đề là anh nhập dữ liệu ở đâu thì có thể sửa tại đó. Em lấy ví dụ:
Khi đang cập nhật một khoản thanh toán của một khách hàng thì phát hiện thông tin về khách hàng đó không đúng. Thông tin về khách được cập nhật trên màn hình Danh mục khách hàng thì dùng một command để mở màn hình cập nhật thông tin khách hàng đó. Sau khi sửa xong, các thông tin được sửa đổi sẽ tự động cập nhật vào màn hình làm việc.
Như vậy, vấn đề là anh phải thiết kế được đầy đủ giao diện nhập liệu, kể cả màn hình lọc, tìm kiếm theo nhiều tiêu thức khác nhau (trừ khi anh vẫn thích làm việc ở dạng lưới vì quá... yêu Excel).

Chúc anh có một phần mềm kế toán thật động (đậy)!
 
Nếu có thể, các bạn hướng dẫn mình cách view 1 Recordset trong Access với. Như vậy thì ta có thể bỏ qua cái QueryDefs này đi mà sử dụng ADO cho gọn

Dear
---------

Trong Help, MS Access có cả 1 đoạn nói về việc ứng dụng Parameter trong đó sử dụng Recordset này anh (ấn F1, tìm từ khóa "Parameter"):

PHP:
Sub ParameterX()

   Dim dbsNorthwind As Database
   Dim qdfReport As QueryDef
   Dim prmBegin As Parameter
   Dim prmEnd As Parameter

   Set dbsNorthwind = OpenDatabase("Northwind.mdb")

   ' Create temporary QueryDef object with two 
   ' parameters.
   Set qdfReport = dbsNorthwind.CreateQueryDef("", _
      "PARAMETERS dteBegin DateTime, dteEnd DateTime; " & _
      "SELECT EmployeeID, COUNT(OrderID) AS NumOrders " & _
      "FROM Orders WHERE ShippedDate BETWEEN " & _
      "[dteBegin] AND [dteEnd] GROUP BY EmployeeID " & _
      "ORDER BY EmployeeID")
   Set prmBegin = qdfReport.Parameters!dteBegin
   Set prmEnd = qdfReport.Parameters!dteEnd

   ' Print report using specified parameter values.
   ParametersChange qdfReport, prmBegin, #1/1/95#, _
      prmEnd, #6/30/95#
   ParametersChange qdfReport, prmBegin, #7/1/95#, _
      prmEnd, #12/31/95#

   dbsNorthwind.Close

End Sub

Sub ParametersChange(qdfTemp As QueryDef, _
   prmFirst As Parameter, dteFirst As Date, _
   prmLast As Parameter, dteLast As Date)
   ' Report function for ParameterX.

   Dim rstTemp As Recordset
   Dim fldLoop As Field

   ' Set parameter values and open recordset from 
   ' temporary QueryDef object.
   prmFirst = dteFirst
   prmLast = dteLast
   Set rstTemp = _ 
      qdfTemp.OpenRecordset(dbOpenForwardOnly)
   Debug.Print "Period " & dteFirst & " to " & dteLast

   ' Enumerate recordset.
   Do While Not rstTemp.EOF

      ' Enumerate Fields collection of recordset.
      For Each fldLoop In rstTemp.Fields
         Debug.Print " - " & fldLoop.Name & " = " & fldLoop;
      Next fldLoop

      Debug.Print
      rstTemp.MoveNext
   Loop

   rstTemp.Close

End Sub

Nhưng theo em, sử dụng Recordset trong Access giống như một sự thoát ly từ nông thôn ra thành phố vậy - không thích hợp!%#^#$
 
Không phải mình đang viết phần mềm, thi thoảng mình có viết 1 file phục vụ công việc thôi. Nhưng là người đã sử dụng phần mềm thì sao không tìm cách áp dụng các ngón hay của họ cho file của mình. Khổ nỗi kiến thức hạn hẹp nên mầy mò tìm hiểu thôi. Rất may là giờ có diễn đàn thêm người trợ giúp, mong được các bạn giúp đỡ thường xuyên nhé.
 
­Cường à, cái đoạn Help đó thực chất chính là gợi ý của Cường bài trước, tức là nó tạo lại query và thay thế ĐK mới vào QR . Để view được ta phải xóa cái cũ và append nó vào Container cơ. Sau đó mới dùng lệnh DoCmd.OpenQ..
 
Dear sealand,
-------------

Anh "ngâm cứu" đoạn cuối này này:

PHP:
   ' Set parameter values and open recordset from  
   ' temporary QueryDef object. 
   prmFirst = dteFirst 
   prmLast = dteLast 
   Set rstTemp = _  
      qdfTemp.OpenRecordset(dbOpenForwardOnly) 
   Debug.Print "Period " & dteFirst & " to " & dteLast 
   ' Enumerate recordset. 
   Do While Not rstTemp.EOF 
      ' Enumerate Fields collection of recordset. 
      For Each fldLoop In rstTemp.Fields 
         Debug.Print " - " & fldLoop.Name & " = " & fldLoop; 
      Next fldLoop 
      Debug.Print 
      rstTemp.MoveNext 
   Loop 
   rstTemp.Close

Để view được ta phải xóa cái cũ và append nó vào Container cơ

Nếu không muốn xóa "cái cũ" thì anh gán luôn cho nó vào Query đích danh như em đã làm là được mà:

Set myQuery = CurrentDb.QueryDefs("Q01_loc_thang")

Như vậy có đúng ý anh không? Hay anh định "chơi" ADODB, khổng liên quan gì đến Query nữa? :-= Nếu thế thì sử dụng ADODB.Recordset ở mọi môi trường lập trình đều giống nhau, anh đã sử dụng nhuần nhuyễn trên Excel thì có thể vận dụng trong Access...vvv.
 
Web KT
Back
Top Bottom