How can i call the below function to populate my access form list control - sql

I need to populate the access form list box from a access table.
Below is the code which I copy-pasted on button click event:
Public Sub PopulateLBWithData(DBPath As String, _
TableName As String, FieldName As String, _
oListControl As Object,Optional Distinct As Boolean = False, _
Optional OrderBy As String)
''#PURPOSE: Populate a list box, combo box
''#or control with similar interface with data
''#from one field in a Access Database table
''#Parameters: DBPath: FullPath to Database
''#TableName: The Name of the Table
''#FieldName: Name of the Field
''#Distinct: Optional -- True if you want distinct value
''#Order By: Optional -- Field to Order Results by
''#Must have reference to DAO in your project
Dim sSQL As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim td As DAO.TableDef
Dim f As DAO.Field
Dim sTest As String
Dim bIsNumeric As Boolean
Dim i As Integer
On Error Resume Next
''#validate all parameters
oListControl.AddItem "a"
oListControl.Clear
If Err.Number > 0 Then Exit Sub
sTest = Dir(DBPath)
If sTest = "" Then Exit Sub
Set db = Workspaces(0).OpenDatabase(DBPath)
If Err.Number > 0 Then Exit Sub
Set td = db.TableDefs(TableName)
If Err.Number > 0 Then
db.Close
Exit Sub
End If
Set f = td.Fields(FieldName)
If Err.Number > 0 Then
db.Close
Exit Sub
End If
If Len(OrderBy) Then
Set f = td.Fields(OrderBy)
If Err.Number > 0 Then
db.Close
Exit Sub
End If
End If
sSQL = "SELECT "
If Distinct Then sSQL = sSQL & "DISTINCT "
sSQL = sSQL & "[" & FieldName & "] FROM [" & TableName & "]"
If OrderBy <> "" Then sSQL = sSQL & " ORDER BY " & OrderBy
Set rs = db.OpenRecordSet(sSQL, dbOpenForwardOnly)
With rs
Do While Not .EOF
oListControl.AddItem rs(FieldName)
.MoveNext
Loop
.Close
End With
db.Close
End Sub
But this function need arguments according to the VBA conventions.
Please help me how i can call this function to populate my vba form list box from the same access table?

That code is overly complex for what you're probably trying to do.
Why not try to just set the control's row source and then requery.
If you want to retain the parameterization, then pass in the SQL.
Dim strSQL As String
strSQL = "SELECT MyField FROM MyTable;"
Me.lstMyListBox.RowSource = strSQL
Me.lstMyListBox.Requery

Related

ListBox Multiselect in MS Access

I have created a form to get all the field header names, but I'm unable to select multiple fields. Attached is for your reference.
Following is the code used to get the Headers from the Master Table:
Private Sub Form_Load()
'Call GetColumnNameFromIndex
'Call List4_Click
Dim rst As New ADODB.Recordset
rst.Open "SELECT * FROM Master_DataBase", CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
' Note: adOpenForwardOnly and adLockReadOnly are the default values '
' for the CursorType and LockType arguments, so they are optional here '
' and are shown only for completeness '
Dim ii As Integer
Dim ss As String
For ii = 0 To rst.Fields.Count - 1
ss = ss & "," & rst.Fields(ii).Name
Next ii
Me.List4.RowSource = ss
Debug.Print ss
Me.Requery
End Sub
Set your properties to Simple or Extended.
Sample VBA code may look like this.
Option Compare Database
Private Sub cmdOpenQuery_Click()
On Error GoTo Err_cmdOpenQuery_Click
Dim MyDB As DAO.Database
Dim qdef As DAO.QueryDef
Dim i As Integer
Dim strSQL As String
Dim strWhere As String
Dim strIN As String
Dim flgSelectAll As Boolean
Dim varItem As Variant
Set MyDB = CurrentDb()
strSQL = "SELECT * FROM tblCompanies"
'Build the IN string by looping through the listbox
For i = 0 To lstCounties.ListCount - 1
If lstCounties.Selected(i) Then
If lstCounties.Column(0, i) = "All" Then
flgSelectAll = True
End If
strIN = strIN & "'" & lstCounties.Column(0, i) & "',"
End If
Next i
'Create the WHERE string, and strip off the last comma of the IN string
strWhere = " WHERE [strCompanyCountries] in (" & Left(strIN, Len(strIN) - 1) & ")"
'If "All" was selected in the listbox, don't add the WHERE condition
If Not flgSelectAll Then
strSQL = strSQL & strWhere
End If
MyDB.QueryDefs.Delete "qryCompanyCounties"
Set qdef = MyDB.CreateQueryDef("qryCompanyCounties", strSQL)
'Open the query, built using the IN clause to set the criteria
DoCmd.OpenQuery "qryCompanyCounties", acViewNormal
'Clear listbox selection after running query
For Each varItem In Me.lstCounties.ItemsSelected
Me.lstCounties.Selected(varItem) = False
Next varItem
Exit_cmdOpenQuery_Click:
Exit Sub
Err_cmdOpenQuery_Click:
If Err.Number = 5 Then
MsgBox "You must make a selection(s) from the list", , "Selection Required !"
Resume Exit_cmdOpenQuery_Click
Else
'Write out the error and exit the sub
MsgBox Err.Description
Resume Exit_cmdOpenQuery_Click
End If
End Sub
Please customize to your specific needs.

Access Export Subform to excel

I'm trying to write some VBA to export filtered records from a subform. I've found a number of post related to this issue and I've cobbled the code below from those post.
When I run it I get a run-time error saying:
the Object '__temp' already exist.
When I click debug it highlights the line
Set qrydef = db.CreateQueryDef(strTempQryDef, strSQL)
Thank you for you help.
Private Sub ExportSubform()
Dim db As dao.Database
Dim qrydef As dao.QueryDef
Dim strSQL As String
Dim bolWithFilterOn As Boolean
Dim strTempQryDef As String
Dim strRecordSource As String
strTempQryDef = "__temp"
bolWithFilterOn = me.subsearch_frm.Form.FilterOn
strRecordSource = me.subsearch_frm.Form.RecordSource
If InStr(strRecordSource, "SELECT ") <> 0 Then
strSQL = strRecordSource
Else
strSQL = "SELECT * FROM [" & strRecordSource & "]"
End If
' just in case our sql string ends with ";"
strSQL = Replace(strSQL, ";", "")
If bolWithFilterOn Then
strSQL = strSQL & _
IIf(InStr(strSQL, "WHERE ") <> 0, " And ", " Where ") & _
me.subsearch_frm.Form.Filter
End If
Set db = CurrentDb
'create temporary query
Set qrydef = db.CreateQueryDef(strTempQryDef, strSQL)
db.QueryDefs.Append qrydef
Set qrydef = Nothing
DoCmd.TransferSpreadsheet TransferType:=acExport, _
SpreadsheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:=strTempQryDef, _
FileName:=Replace(CurrentProject.Path & "\", "\\", "\") & strTempQryDef & ".xlsx"
' Delete the temporary query
db.QueryDefs.Delete strTempQryDef
Set db = Nothing
End Sub
Per the documentation:
If the object specified by name is already a member of the QueryDefs collection, a run-time error occurs.
As such, you should delete the temporary query before attempting to create it. To do this, you could use code along the lines of the following:
On Error Resume Next
DoCmd.DeleteObject acQuery, strTempQryDef
On Error GoTo 0
Also, per the documentation:
In a Microsoft Access workspace, if you provide anything other than a zero-length string for the name when you create a QueryDef, the resulting QueryDef object is automatically appended to the QueryDefs collection.
As such, you don't need this line:
db.QueryDefs.Append qrydef

multi-combo box search with VBA

I am currently having this issue of my search not working correctly. The idea is to have the user click on different fields and have them assigned to textboxes and then be searched against. Above is what the UI currently looks like in the form and the code is attached below. For example, when I pick firstName as the field 1 and Title as field 2, enter the text "joe" into field 1 into
and "student" into the respective text boxes and then hit search, it shows all of the student results instead of that single row of data in the table. I am thinking this is could be an issue of the combo boxes not being synchronized, where let's say if cbo1 and cbo2 declare fields, then those repsective text fields become filtered. cboField, cboField2 and cboField3 are all combo boxes and command_21 is a search button and command_28 is a show all records. I am very new to this still and am not entirely sure. Any help is appreciated. Thanks in advance
Option Compare Database
Private Sub cboField_Enter()
Dim oRS As DAO.Recordset, i As Integer
If Me.Form.FilterOn = True Then DoCmd.ShowAllRecords
Set oRS = Me.RecordsetClone
cboField.RowSourceType = "Value List"
cboField.RowSource = ""
For i = 0 To oRS.Fields.Count - 1
If oRS.Fields(i).Type = dbText Then cboField.AddItem oRS.Fields(i).Name
Next i
End Sub
Private Sub cboField2_Enter()
Dim rs As DAO.Recordset, i As Integer
If Me.Form.FilterOn = True Then DoCmd.ShowAllRecords
Set rs = Me.RecordsetClone
cboField2.RowSourceType = "Value List"
cboField2.RowSource = ""
For i = 0 To rs.Fields.Count - 1
If rs.Fields(i).Type = dbText Then cboField2.AddItem rs.Fields(i).Name
Next i
End Sub
Private Sub cboField3_Enter()
Dim rs As DAO.Recordset, i As Integer
If Me.Form.FilterOn = True Then DoCmd.ShowAllRecords
Set rs = Me.RecordsetClone
cboField2.RowSourceType = "Value List"
cboField2.RowSource = ""
For i = 0 To rs.Fields.Count - 1
If rs.Fields(i).Type = dbText Then cboField2.AddItem rs.Fields(i).Name
Next i
End Sub
Private Sub Command21_Click()
Dim sfilter As String, oRS As DAO.Recordset
Dim sfilter2 As String, rs As DAO.Recordset
If IsNull(cboField) And IsNull(cboField2) And IsNull(cboField3) Then
DoCmd.ShowAllRecords
MsgBox "select a field"
Exit Sub
End If
If Not IsNull(cboField) Then
sfilter = cboField & " LIKE '" & txtBox & "*'"
DoCmd.ApplyFilter , sfilter
End If
If Not IsNull(cboField2) Then
sfilter2 = cboField2 & " LIKE '" & txtBox2 & "*'"
DoCmd.ApplyFilter , sfilter2
End If
If Not IsNull(cboField3) Then
sfilter3 = cboField3 & " LIKE '" & txtBox3 & "*'"
DoCmd.ApplyFilter , sfilter3
End If
Set oRS = Me.RecordsetClone
Set rs = Me.RecordsetClone
If oRS.RecordCount And rs.RecordCount = 0 Then
MsgBox " no record matches"
DoCmd.ShowAllRecords
End If
End Sub
Private Sub Command28_Click()
DoCmd.ShowAllRecords
End Sub

Select only certain data type in Microsoft SQL query

In Access 2007 I need to select all the short-text fields in a table.
VBA code should look like this:
Dim strClient As String
Set dbs = CurrentDb()
Debug.Print Me.ID
strClient = "Select * from ANG_CLIENTS where DATA_TYPE='TEXT' AND ID=" & Me.ID
Set rs = dbs.OpenRecordset(strClient)
I get "Runtime error 3061. Too few parameters. Expected 1" on the last assignment.
You need to define a custom function to loop through the recordset fields and extract the names of text fields only.
The names can then be added to your SQL script.
Public Function TextDataFileds(rs As DAO.Recordset) As String
Dim fld As DAO.Field, item As String
For Each fld In rs.Fields
If fld.Type = 10 Then 'dbText
item = IIf(Len(item) = 0, fld.Name, item & ", " & fld.Name)
End If
Next fld
TextDataFileds = item
End Function
You can then call it like this:
Sub Test()
On Error GoTo ErrProc
Dim rs As DAO.Recordset
Set rs = CurrentDb().OpenRecordset("SELECT TOP 1 * FROM ANG_CLIENTS;")
Dim sql_ As String
sql_ = "SELECT " & TextDataFileds(rs) & " FROM ANG_CLIENTS WHERE ID=" & Me!ID
rs.Close
Set rs = Nothing
Set rs = CurrentDb().OpenRecordset(sql_)
'....
Leave:
rs.Close
Set rs = Nothing
On Error GoTo 0
Exit Sub
ErrProc:
MsgBox Err.Description, vbCritical
Resume Leave
End Sub

Check if access table exists

I want to log web site visits' IP, datetime, client and refferer data to access database but I'm planning to log every days log data in separate tables in example logs for 06.06.2010 will be logged in 2010_06_06 named table. When date is changed I'll create a table named 2010_06_07. But the problem is if this table is already created.
Any suggestions how to check if table exists in Access?
You can use the hidden system table MSysObjects to check if a table exists:
If Not IsNull(DlookUp("Name","MSysObjects","Name='TableName'")) Then
'Table Exists
However, I agree that it is a very bad idea to create a new table every day.
EDIT: I should add that tables have a type 1, 4 or 6 and it is possible for other objects of a different type to have the same name as a table, so it would be better to say:
If Not IsNull(DlookUp("Name","MSysObjects","Name='TableName' And Type In (1,4,6)")) Then
'Table Exists
However, it is not possible to create a table with the same name as a query, so if you need a look up to test for a name, it may be best to add 5, that is query, to the Type list.
Here's another solution, will be a bit faster than looping over all of the tables.
Public Function doesTableExist(strTableName As String) As Boolean
Dim db As DAO.Database
Dim td As DAO.TableDef
Set db = CurrentDb
On Error Resume Next
Set td = db.TableDefs(strTableName)
doesTableExist = (Err.Number = 0)
Err.Clear
End Function
I tested various methods for finding out if a table exists several years ago. Here is the code for all of them as I implemented, including my simple test routine.
Public Function TableExists(strTableName As String, Optional ysnRefresh As Boolean, Optional db As DAO.Database) As Boolean
' Originally Based on Tony Toews function in TempTables.MDB, http://www.granite.ab.ca/access/temptables.htm
' Based on testing, when passed an existing database variable, this is the fastest
On Error GoTo errHandler
Dim tdf As DAO.TableDef
If db Is Nothing Then Set db = CurrentDb()
If ysnRefresh Then db.TableDefs.Refresh
Set tdf = db(strTableName)
TableExists = True
exitRoutine:
Set tdf = Nothing
Exit Function
errHandler:
Select Case Err.Number
Case 3265
TableExists = False
Case Else
MsgBox Err.Number & ": " & Err.Description, vbCritical, "Error in mdlBackup.TableExists()"
End Select
Resume exitRoutine
End Function
Public Function TableExists2(strTableName As String, Optional ysnRefresh As Boolean, Optional db As DAO.Database) As Boolean
On Error GoTo errHandler
Dim bolCleanupDB As Boolean
Dim tdf As DAO.TableDef
If db Is Nothing Then
Set db = CurrentDb()
bolCleanupDB = True
End If
If ysnRefresh Then db.TableDefs.Refresh
For Each tdf In db.TableDefs
If tdf.name = strTableName Then
TableExists2 = True
Exit For
End If
Next tdf
exitRoutine:
Set tdf = Nothing
If bolCleanupDB Then
Set db = Nothing
End If
Exit Function
errHandler:
MsgBox Err.Number & ": " & Err.Description, vbCritical, "Error in mdlBackup.TableExists1()"
Resume exitRoutine
End Function
Public Function TableExists3(strTableName As String, _
Optional db As DAO.Database) As Boolean
' Based on testing, when NOT passed an existing database variable, this is the fastest
On Error GoTo errHandler
Dim strSQL As String
Dim rs As DAO.Recordset
If db Is Nothing Then Set db = CurrentDb()
strSQL = "SELECT MSysObjects.Name FROM MSysObjects "
strSQL = strSQL & "WHERE MSysObjects.Name=" & Chr(34) & strTableName & Chr(34)
strSQL = strSQL & " AND MSysObjects.Type=6;"
Set rs = db.OpenRecordset(strSQL)
TableExists3 = (rs.RecordCount <> 0)
exitRoutine:
If Not (rs Is Nothing) Then
rs.Close
Set rs = Nothing
End If
Exit Function
errHandler:
MsgBox Err.Number & ": " & Err.Description, vbCritical, _
"Error in TableExists1()"
Resume exitRoutine
End Function
Public Sub TestTableExists(strTableName As String, intLoopCount As Integer)
Dim dteStart As Date
Dim i As Integer
Dim bolResults As Boolean
dteStart = Now()
For i = 0 To intLoopCount
bolResults = TableExists(strTableName, , CurrentDB())
Next i
Debug.Print "TableExists (" & intLoopCount & "): " & Format(Now() - dteStart, "nn:ss")
dteStart = Now()
For i = 0 To intLoopCount
bolResults = TableExists2(strTableName, , CurrentDB())
Next i
Debug.Print "TableExists2 (" & intLoopCount & "): " & Format(Now() - dteStart, "nn:ss")
dteStart = Now()
For i = 0 To intLoopCount
bolResults = TableExists3(strTableName, CurrentDB())
Next i
Debug.Print "TableExists3 (" & intLoopCount & "): " & Format(Now() - dteStart, "nn:ss")
End Sub
I have found querying system tables or tabledefs to be unreliable and introduce unpredictable behaviour in scripts where tables get regularly created and dropped.
Based on my results, my hypothesis is that these tables aren't necessarily updated at the exact instant a CREATE or DROP is executed, or that concurrency issues are preventing me from getting an accurate result.
I've found the following method to be more reliable:
Public Function TableExists(theDatabase As Access.Application, _
tableName As String) As Boolean
' Presume that table does not exist.
TableExists = False
' Define iterator to query the object model.
Dim iTable As Integer
' Loop through object catalogue and compare with search term.
For iTable = 0 To theDatabase.CurrentData.AllTables.Count - 1
If theDatabase.CurrentData.AllTables(iTable).Name = tableName Then
TableExists = True
Exit Function
End If
Next iTable
End Function
There should be no runtime issue iterating unless there is an staggeringly enormous collection of tables.
This question is quite old but I found that no answer is satisfying, because:
they do not handle the case of "bad" linked tables, where the linked table points to a non existing db or table.
since linked tables are potentially huge, we must be able to check them with a fast query.
So here is my simple but more complete solution:
Function isTableOk(tblName As String) As Boolean
'works with local or linked tables
Dim db As DAO.Database, rs As DAO.Recordset
Dim sSql As String
sSql = "SELECT TOP 1 ""xxx"" AS Expr1 FROM [" & tblName & "]"
On Error Resume Next
Err.Clear
Set db = CurrentDb
Set rs = db.OpenRecordset(sSql)
isTableOk = (Err.Number = 0)
rs.Close
End Function
You can even check table in an external Access db with this version:
Function isTableOk(tblName As String, Optional dbName As String) As Boolean
'works with local or linked tables, or even tables in external db (if dbName is provided)
Dim db As DAO.Database, rs As DAO.Recordset
Dim sSql As String
Set db = CurrentDb
sSql = "SELECT TOP 1 'xxx' AS Expr1 FROM [" & tblName & "]"
If Len(dbName) > 0 Then 'external db
sSql = sSql & " IN '" & dbName & "'"
End If
Err.Clear
On Error Resume Next
Set rs = db.OpenRecordset(sSql)
isTableOk = (Err.Number = 0)
rs.Close
End Function