ms-access: instead of rowsource, running from query - sql

i have a very complex query that is running from a listbox rowsource. i just do a listbox1.requery and it populates the listbox.
instead of doing it this way, i would like to:
i just want to save the query in the queries section
call it from there.
then i want to save the results of the query into a string
then i want to feed the string into the listbox
can you please help me with the code for these four questions.
thanks!

another solution is to open the query in a recordset and then set the recordset property of the listbox control to it. I have my own function for that (I use it mostly for comboboxes). If necessary, you can add an extra 'connection' parameter to the sub when you want to open a recordset from another database.
Public Sub addQueryToCombobox(x_query As String, x_control As Control)
Dim rs As ADODB.Recordset
On Error GoTo ERREUR
Set rs = New ADODB.Recordset
Set rs.ActiveConnection = CurrentProject.AccessConnection
rs.CursorType = adOpenStatic
rs.LockType = adLockReadOnly
rs.CursorLocation = adUseClient
rs.Open x_Query
Set rs.ActiveConnection = Nothing
Set x_control.Recordset = rs
Set rs = Nothing
On Error GoTo 0
Exit Sub
ERREUR:
'add here your own error manager'
End Sub

I think your first 3 items are addressed by this answer to your other question:
ms-access save query result in a string
As for the fourth item in this question, set your list box Row Source Type to "Value List" and write your string to its Row Source property.

you could just set the rowsource of the listbox to your query.

Related

Access Continuous form based on recordest made with VBA (fill the form fields)

I've prepared recordset and open form with this.
The form works with recordset - quantities of records in the form is the same like on the recordset.
Problem:
I have absolutely no idea how to display the recordset results in the form fields.
I know one way - create an assistant table but I would like to avoid it.
Any idea please ?
Dim rst As Object
Set rst = CreateObject("ADODB.Recordset")
....
With rst
.Fields.Append "date", 7
.Fields.Append "index", 3
End With
rst.Open
......
Set Forms!Form1.Recordset = rst
Thank you for your interesting,
I have to create recordset.
I need to make some calculation between two table and only way I find it is with vba (no way with sql).
Anyway it shoud be a way to open form with recordset.
You cane create a simple continuous form ("Form1") with one blank field.
The code below is for loading form.
As you can see you'll open the form with 4 blank field.
How to put code result (0,1,2,3) into form fields ?
Private Sub Form_Load()
Dim rst As Object
Dim i As Integer
Set rst = CreateObject("ADODB.Recordset")
rst.Fields.Append "Field_1", 3
rst.Open
For i = 0 To 3
With rst
.AddNew
![Field_1] = i
.Update
End With
Debug.Print i
Next
Set Forms!Form1.Recordset = rst
Set rst = Nothing
End Sub

Access 2016 - RecordsetClone Error on a form constructed with a virtual recordset opens "Select Data Source" dialog

I've seen a number of posts trying to describe this bug but they haven't framed the problem correctly to be reproduced... or not set the scenario in the way that I've experienced the bug using a common technique.
The bug occurs when a form's recordset is set to a virtual recordset and then referred to by a DAO recordsetclone statement. Instead of the recordset being set to the form's recordset (via cloning), a "Select Data Source" dialog is presented.
We most commonly use this to add a checkbox control to a detail form for a user to select one or more records for further processing. I've used this technique many times in many applications but now it fails.
Note: I have confirmed that this code works correctly in Access 2010.
I'm using Windows 10 Pro with a 32 bit Office installation
To set this up and reproduce the bug:
Create a new ACCDB database
Add the following references to the default references:
Microsoft ActiveX Data Objects 6.1 Library
Microsoft ADO Ext. 2.8 for DDL and Security
Create a testing table:
TestId, AutoNumber, PK
TestText, Short Text
Append about 10 rows to the table.
Create an unbound form with 3 controls:
Checkbox, Name: Selected, Control Source: Selected
Textbox, Name: TestId, Control Source: TestId
Textbox, Name: TestText, Control Source: TextText
In the form's header add a command button: Name: cmdTest, Caption: Test
Set the form Default View: Continuous
In the Form_Open call a sub SetRecordsource which creates a recordset and adds a column "Selected" for the user to check the records they want.
The command button cmdTest will attempt to reference the form's recordsource. It's while attempting to reference the form's recordsouce that the error occurs. Instead of the reference being made, the "Select Data Source" dialog pops up.
The complete form's VBA code:
Option Compare Database
Option Explicit
Private Sub cmdTest_Click()
On Error GoTo errHandler
Dim rs As DAO.Recordset
Set rs = Me.RecordsetClone
' Using an ADODB recordset works but is an ugly solution
' To test comment out the Dim DAO and Set rs statements above and uncomment the next 2 lines.
' Dim rs As ADODB.Recordset
' Set rs = Me.Recordset
rs.MoveFirst
With rs
Do While Not .EOF
Debug.Print .Fields("Selected"), .Fields("TestId"), .Fields("TestText")
.MoveNext
Loop
End With
Set rs = Nothing
ExitSub:
Exit Sub
errHandler:
MsgBox "Error in " & Me.Name & ".SetRecordsource " & Err.Number & " - " & Err.Description
Resume ExitSub
End Sub
Private Sub SetRecordsource()
Dim rs As ADODB.Recordset 'the virtual recordset to hold the source data plus the boolean Selected field
Dim rsSource As DAO.Recordset 'dim the source recordset
Set rs = New ADODB.Recordset
With rs
.Fields.Append "Selected", adboolean
.Fields.Append "TestId", adInteger, , adFldKeyColumn
.Fields.Append "TestText", adVarChar, 80
.CursorLocation = adUseClient
.LockType = adLockOptimistic
.CursorType = adOpenKeyset
.Open
Set rsSource = CurrentDb.OpenRecordset("Select TestId, TestText from Test", dbOpenDynaset)
rsSource.MoveFirst
Do Until rsSource.EOF
.AddNew
.Fields("Selected") = 0 'set the checkboxes to unchecked
.Fields("TestId") = rsSource.Fields(0)
.Fields("TestText") = rsSource.Fields(1)
.Update
rsSource.MoveNext
Loop
End With
Set Me.Recordset = rs 'Set the form's recordset = to our virtual recordset
Set rsSource = Nothing
Set rs = Nothing
ExitSub:
Exit Sub
err_handler:
MsgBox "Error in " & Me.Name & ".SetRecordsource " & Err.Number & " - " & Err.Description
Resume ExitSub
End Sub 'SetRecordsource
Open the form and click the Test command button to reproduce the error.
One solution proposed is to use an ADODB recordset and set it to Me.Recordset instead of Me.Recordsetclone. While this does work, it's an ugly solution since you are now operating on the form's recordsource and when looping through the records to find the rows where Selected = True moves the current record on the form. Not only does the current record pointer move but if there's more rows then the can show, the user sees the form's records scrolling.
Any help, confirmation or recommendations would be greatly appreciated.
Thanks in advance!
From another forum the solution to this is to use an ADODB recordset and then clone the form to it via Recordset.Clone. In the code above, it references an "ugly" solution:
' Using an ADODB recordset works but is an ugly solution
' To test comment out the Dim DAO and Set rs statements above and uncomment the next 2 lines.
' Dim rs As ADODB.Recordset
' Set rs = Me.Recordset
Setting rs = Me.Recordset will operate on the form (not desired).
But using an ADODB recordset and then
setting rs = Me.Recordset.Clone works, does not operate on the form and doesn't pop up the Data Source Dialog.
Something has changed in 2016 but this does work and may help someone else.
You may also want to read: Create In-Memory ADO Recordsets at Database Journal
Your code can't work, as you try to assign an ADODB.Recordset (the one in Form.Recordset) to a DAO.Recordset,`as it is declared.
If the Recordset-Type can vary, you can dimrs as Objectthen it gets the type of Form.Recordset(by Form Property RecordsetClone, that surprisingly works for ADODB:Recordsets too). You can query the type with:
If TypeOf Me.RecordSet Is ADODB.Recordset Then
'ADODB
Else
'DAO
End If
If you need an unboundCheckBox, you can useclsCCRecordSelect-Class from SelectRecordsV2.
TheclsCCRecordSelectis used by me for years and I don't want to live without!

MS Access: How to load data from query into form

I have a form that helps the user add some data into a Database, however I noticed that a few of the fields on each product added are very similar. So I'm adding a second database of commonly used fields that can be pre-filled by selecting from a combo-box.
For example if the user is adding Product XX-X but product XX-X is of the same family of YY-Y and I already have YY-Y's data in Database2, I want to just load those parameters. I made a query that returns the parameters as I want however I dont know how to add this to the FORM.
Basically I have a blank VBA code slot for "ComboBox_Change".
I want the ComboBox_Change function to load field X from query and paste it into field X1 on the current form.
Hope I'm explaining myself correctly.
Thanks!
THANKS for the suggestion this is the code so far that has an error
Private Sub LoadMatCB_Change()
Dim rs As Recordset
Dim db As Database
Set db = CurrentDb
Set rs = CurrentDb.OpenRecordset("VendorDeetsQuery")
If Nz(Me.Input_Vendor.Value, "") = "" Then Me.Input_Vendor.Value = rs![Origin]
Set rs = Nothing
Set db = Nothing
End Sub
You will need to use the table's ID field to grab the related record from your query into a recordset object. You can then use the fields of the recordset to set the value in each of the other fields you want to populate; you can add the if statements to check if the controls are blank if that is a condition you need.
Dim rs As Recordset
Dim db as Database
Dim qry as QueryDef
Set db = CurrentDb
Set qry = db.QueryDefs("YourQueryName")
qry.Parameters("ParamName") = comboBox.Value '<pass your parameter here>
'repeat the above for any other parameters you need to pass
Set rs = qry.OpenRecordset
'for each of these, use your control names and whatever you named the fields from your query'
If Nz(Me.txtBox1.Value, "") = "" Then Me.txtBox1 = rs![fieldName1]
If Nz(Me.txtBox2.Value, "") = "" Then Me.txtBox2 = rs![fieldName2]
...
...
If Nz(Me.txtBoxN.Value, "") = "" Then Me.txtBoxN = rs![fieldNameN]
Set rs = Nothing
Set qry = Nothing
Set db = Nothing

Creating a Button in Excel, that calls upon a created Access query

Is there a way to create a button in Excel that runs a query, that is already created, in Access, and then updates the excel spreadsheet using the data from the query? I've searched the web for directions on how to do this, but have only found answers that create a button in Excel, that only runs a query in Excel, not Access. I am assuming this will be done by coding, upon click, in VBA, but have yet to find anything that does this. So... Is it possible? If so, how?
Okay, so I have kind of updated this with question, because I sort of used both options made. So I first created a Function in a Standard Module (Because we may use this later for another sheet in the workbook, and we didn't want to duplicate work):
Function GetSqlServerData(sQuery As String, sRange As Range)
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sConnString As String
' Create the connection string.
sConnString = "NMS"
' Create the Connection and Recordset objects.
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
' Open the connection and execute.
conn.Open sConnString
Set rs = conn.Execute(sQuery)
' Check we have data.
If Not rs.EOF Then
' Transfer result.
Sheets(3).Range("A2").CopyFromRecordset rs
' Close the recordset
rs.Close
Else
MsgBox "Error: No records returned.", vbCritical
End If
' Clean up
If CBool(conn.State And adStateOpen) Then conn.Close
Set conn = Nothing
Set rs = Nothing
End Function
Then I tried to use said function:
Sub GetPermits()
Dim sQuery As String
Dim sRange As Range
Set sQuery = "Select * From Customer;"
Set sRange = Sheets(3).Range("A2")
GetSqlServerData(sQuery, sRange)
End Sub
But it gives me an error right at the spot where is actually use the function. I don't need it to go to a MsgBox, and I don't need it to print it out, all I need is for it to put in the data into the sheet noted on the function call. BTW, the function needs some tweeking, I know. Right now, I just need it to call the darn thing, lol.
Here is a Screen Shot of the error message: If you cant see it, it says, "Compile Error: Expected:=" and it highlights the "GetSqlServerData(sQuery, sRange)" in red. So it must have something to do with that. I just can't figure out what it is.
Screenshot of the error message
Dependent on your requirements, you could have this without VBA in a quicker and more reliable way, to have a table that is pointed at your query, that updates when you click Refresh.
To do so, in Excel navigate to Data > From Access.
From here, navigate to your database with the saved query, and when asked to select a table, you can select the query instead.
You can also write your own SQL query for Excel to execute against the database instead.
You can edit the connection properties to refresh when the workbook is opened, or refresh when every 60 minutes for example, or you could turn it all off, and allow the user to hit 'Refresh' in Excel itself.
Alternatively, you could setup a button that runs the refresh table command against the linked table, and this would do the same
Private Sub CommandButton1_Click()
ActiveWorkbook.RefreshAll
End Sub
Good luck.
As an example for a solution with VBA using ADODB one could use the following function to connect to the database.
Function ConnectToDB(ByVal fileName As String)
Dim conn As New ADODB.Connection
If Dir(fileName) = "" Then
MsgBox "Could not find file " & fileName
Exit Function
End If
Dim connectionString As String
' https://www.connectionstrings.com/access/
connectionString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" _
& fileName & ";Persist Security Info=False;"
conn.Open connectionString
Set ConnectToDB = conn
End Function
And if you want to copy data from the database one could use the following code. You need to have a sheet with the codename shRepAllRecords
Option Explicit
Sub ReadFromDB()
' Get datbase name
Dim dbName As String
dbName = <fule filename of the database>
' Connect to the databse
Dim conn As ADODB.Connection
Set conn = ConnectToDB(dbName)
' read the data
Dim rs As New ADODB.Recordset
Dim query As String
' First example to use an SQL statement
' query = "SELECT * From CUSTOMER"
' Second example to use a query name defined in the database itself
query = "qryCustomer"
rs.Open query, conn
' shRepAllRecords is the codename of the sheet where the
' data is written to
' Write header
Dim i As Long
For i = 0 To rs.Fields.Count - 1
'shRepAllRecords.Cells(1, i + 1).Value = rs.Fields(i).Name
shRepAllRecords.Range("A1").Offset(0, i) = rs.Fields(i).Name
Next i
' Write Data
shRepAllRecords.Range("A2").CopyFromRecordset rs
shRepAllRecords.Activate
' clean up
conn.Close
End Sub
So I was finally able to figure out the issue. I was not putting "Call" in front of the function call. Once I did that, it accepted it. Thanks for all the assistance! The final answer was close to what Storax gave above. So I credited him with the answer. Thanks again!

DAO recordset filter function cannot filter with 2 properties

I am using VBA in MS Access 2010.
I am currently trying to filter from a recordset with 2 fields.
However i tired, it will not filter as per what i want.
But if i were to filter based on only one field, the recordset is able to filter accordingly.
This is what I have now.
Private Function getCheckedRecordsFromDB(ByVal cmNum As String) As Boolean
Dim rs As Recordset
Dim rsFiltered As Recordset
Dim iSeral As Integer
'Gets different fields from different tables and store them into rs
Set rs = CurrentDb.OpenRecordset("QueryMemoOutFrm")
' Its not working during the filtering, keeps returning nothing found
rs.Filter = "Doctype='Outgoing' AND DocumentRef='" & cmNum & "'"
Set rsFiltered = rs.OpenRecordset
Do While Not rsFiltered.EOF
' Do Something
Loop
rs.Close
Set rs = Nothing
rsFiltered.Close
Set rsFiltered = Nothing
End Function
I have read the documentation on MSDN, and does not see where did i go wrong. (Maybe i've missed out something)
I have changed the codes a little bit and it works. But not sure why though.
Private Function getCheckedRecordsFromDB(ByVal cmNum As String) As Boolean
Dim rs As Recordset
Dim rsFiltered As Recordset
Dim dSerial As Double
'Gets different fields from different tables and store them into rs
Set rs = CurrentDb.OpenRecordset("QueryMemoOutFrm")
rs.Filter = "Doctype='Outgoing' AND DocumentRef='" & cmNum & "'"
Set rsFiltered = rs.OpenRecordset
' newly added
rsFiltered.MoveFirst
Do While Not rsFiltered.EOF
dSerial = rsFiltered!SerialNo
rsFiltered.MoveNext
Loop
rs.Close
Set rs = Nothing
rsFiltered.Close
Set rsFiltered = Nothing
End Function
It's much easier to troubleshoot if your provide your actual code via copy/paste.
That being said, I'm just wondering why you're using two recordsets?
Do you get the proper answer if you actually do your loop on the real filtered recordset?
Eliminate the line
Set rsFiltered = rs.OpenRecordset
Use this block of code on rs instead of rsFiltered
Do While Not rs.EOF
' Do Something
Loop