Find distinct set of values using Access VBA - ms-access

I want to find the distinct list of values from a collection of certain fields across a number of tables in MS Access. However, my VBA code only returns the first value from every field (and not the full collection of distinct values in each field). Please see below:
Sub GetDistinctValues()
Dim tbl As DAO.TableDef
Dim fld As DAO.Field
Dim rs As DAO.Recordset
Dim rs1 As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("Fields_To_Examine")
Do While Not rs.EOF
For Each tbl In CurrentDb.TableDefs
If tbl.Name = rs("Table_Name") Then
Debug.Print tbl.Name
For Each fld In tbl.Fields
If fld.Name = rs("Field_Name") Then
Debug.Print fld.Name
Set rs1 = CurrentDb.OpenRecordset("SELECT DISTINCT " & tbl.Name & ".Source_System, " & tbl.Name & "." & fld.Name & " FROM " & tbl.Name)
Debug.Print rs1(0), rs1(1)
rs.MoveNext
End If
Next
End If
Next
Loop
rs.Close
rs1.Close
Set rs = Nothing
Set rs1 = Nothing
End Sub
Any suggestions on where I am going wrong?

MoveNext is inside the field loop, so:
For Each tbl In CurrentDb.TableDefs
If tbl.Name = rs("Table_Name") Then
Debug.Print tbl.Name
For Each fld In tbl.Fields
If fld.Name = rs("Field_Name") Then
Debug.Print fld.Name
Set rs1 = CurrentDb.OpenRecordset("SELECT DISTINCT " & tbl.Name & ".Source_System, " & tbl.Name & "." & fld.Name & " FROM " & tbl.Name)
Debug.Print rs1(0), rs1(1)
End If
Next
End If
Next
rs.MoveNext

Related

Access object 424

I am running an expression to loop through a recordset and with a string from each record run an update query on second table. Based on a LIKE match it updates a field to create a relation. I am having problem with Runtime Error '424' Object Required at CurrentDb.Execute.
Tables:
Transactions (main table to update)
TransactionType (relation table of types or categories)
TransSet (List of strings and transactiontype to set to)
Private Sub Toggle1_Click()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Set db = CurrentDb Set rst = db.OpenRecordset("TransSet")
Do Until rst.EOF
CurrentDb.Execute ("UPDATE Transactions SET Transactions.TransactionType =" & (TransSet.TransTypeSet) & " WHERE ((Transactions.TransactionText1) Like * " & (TransSet.TransIdent) & "*))")
rst.MoveNext Loop
rst.Close Set rst = Nothing
End Sub
Reference the recordset object, not the table or query the recordset is based on.
Need apostrophe delimiters for text type fields paramaters.
CurrentDb.Execute ("UPDATE Transactions SET TransactionType ='" & rst!TransTypeSet & "'" & _
" WHERE TransactionText1 Like '*" & rst!TransIdent & "*'")
Thank you - I also had realised my error and fixed the code. I also changed the table name to not confuse with reserved words.
Private Sub Toggle1_Click()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Set db = CurrentDb
Set rst = db.OpenRecordset("Select * FROM TransSet")
Do Until rst.EOF
CurrentDb.Execute ("UPDATE Trans SET trans.TransactionType =" & (rst!TransTypeSet) & " WHERE ((Trans.TransactionText1) Like '*" & (rst!TransIdent) & "*');")
' MsgBox ("UPDATE Trans SET trans.TransactionType =" & (rst!TransTypeSet) & " WHERE ((Trans.TransactionText1) Like '*" & (rst!TransIdent) & "*');")
rst.MoveNext
Loop
rst.Close
Set rst = Nothing
End Sub

Find unmatched records code

Please verify the below code which was build to find unmatched values between two table in MS access ( as there is run-time error 3075 in query expression Count(table1.Inv_No])'
Public Sub subCreateRowDiff()
Dim strSQL As String
Dim rs1 As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim db As DAO.Database
Dim lngCount As Long
Const TEMP_TABLE As String = "tblNoMatch"
strSQL = "SELECT table1.[Inv_No], table1.[Amt], Count(table1.Inv_No]) As Expr1 GROUP BY table1.[Inv_No], table1.[Amt];"
Set db = CurrentDb
'remove all records
db.Execute "DELETE " & TEMP_TABLE & ".* FROM " & TEMP_TABLE & ";"
'open table1
Set rs1 = db.OpenRecordset(strSQL)
strSQL = Replace(strSQL, "table1", "table2")
'open table2
Set rs2 = db.OpenRecordset(strSQL)
'check for difference
With rs1
If Not (.BOF And .EOF) Then .MoveFirst
While Not .EOF
lngCount = .Fields(2).Value 'the count field
'find matching record in table2
rs2.FindFirst "[Inv_No] = " & .Fields(0) & " AND [Amt] = " & .Fields(1).Value
If rs2.NoMatch Then
'save this record as many times (lngCount)
While lngCount <> 0
db.Execute "Insert Into " & TEMP_TABLE & "(Inv_No, Amt) " & _
"Values(" & .Fields(0).Value & ", " & .Fields(1) & ");"
lngCount = lngCount - 1
Wend
Else
' there is a match
' check the difference
If .Fields(2).Value > rs2.Fields(2).Value Then
lngCount = .Fields(2).Value - rs2.Fields(2).Value
Else
lngCount = rs2.Fields(2).Value - .Fields(2).Value
End If
While lngCount <> 0
db.Execute "Insert Into " & TEMP_TABLE & "(Inv_No, Amt) " & _
"Values(" & .Fields(0).Value & ", " & .Fields(1) & ");"
lngCount = lngCount - 1
Wend
End If
.MoveNext
Wend
End With
' now use table2 as reference
With rs2
If Not (.BOF And .EOF) Then .MoveFirst
While Not .EOF
lngCount = .Fields(2).Value 'the count field
'find matching record in table1
rs1.FindFirst "[Inv_No] = " & .Fields(0) & " AND [Amt] = " & .Fields(1).Value
If rs1.NoMatch Then
'save this record as many times (lngCount)
While lngCount <> 0
db.Execute "Insert Into " & TEMP_TABLE & "(Inv_No, Amt) " & _
"Values(" & .Fields(0).Value & ", " & .Fields(1) & ");"
lngCount = lngCount - 1
Wend
Else
' we already did this before
' so no need
End If
.MoveNext
Wend
End With
rs1.Close: Set rs1 = Nothing
rs2.Close: Set rs2 = Nothing
Set db = Nothing
End Sub
Missing a left bracket [. No brackets are needed in this SQL statement because table and field names do not have spaces.

Use Query As DAO.Recordset

I am attempting to iterate a query as a DAO.Recordset, my issue is that my recordset never prints anything. If I look at my table, and my query both of them have the data that I am after, but the VBA is not producing the data that I expect. Below is synatx - why will this not write my data?
Option Compare Database
Sub Test()
Dim query1 As String, rs1 As DAO.Recordset
Dim qryDef As QueryDef, strSQL As String
query1 = "qryPullData"
strSQL = "SELECT fl1 As [Field With Spaces One],fl2 As [Field With Spaces Two], " & _
"fl3 As [Field WIth Spaces Three], fl4 As [Field With Spaces Four] " & _
"FROM smallsubset ORDER BY fl1 ASC;"
Set qryDef = CurrentDb.CreateQueryDef(query1, strSQL)
Set rs1 = CurrentDb.OpenRecordset(query1)
If Not rs1.EOF Then
While Not rs1.EOF
Debug.Print rs1("Field With Spaces One")
Debug.Print rs1("Field With Spaces Two")
Debug.Print rs1("Field With Spaces Three")
Debug.Print rs1("Field With Spaces Four")
Debug.Print rs1("[Field With Spaces One]")
Debug.Print rs1("[Field With Spaces Two]")
Debug.Print rs1("[Field With Spaces Three]")
Debug.Print rs1("[Field With Spaces Four]")
Wend
rs1.Close
End If
End Sub
Here is the code using several of the suggestions from the above comments:
Sub Test()
Dim query1 As String, rs1 As DAO.Recordset
Dim qryDef As QueryDef, strSQL As String
If CheckQuery("qryPullData") = "Yes" Then
DoCmd.DeleteObject acQuery, "qryPullData"
End If
query1 = "qryPullData"
strSQL = "SELECT fl1 As [Field With Spaces One],fl2 As [Field With Spaces Two], " & _
"fl3 As [Field WIth Spaces Three], fl4 As [Field With Spaces Four] " & _
"FROM smallsubset ORDER BY fl1 ASC;"
Set qryDef = CurrentDb.CreateQueryDef(query1, strSQL)
Set rs1 = CurrentDb.OpenRecordset(query1)
rs1.MoveFirst
While Not rs1.EOF
Debug.Print rs1("Field With Spaces One")
Debug.Print rs1("Field With Spaces Two")
Debug.Print rs1("Field With Spaces Three")
Debug.Print rs1("Field With Spaces Four")
rs1.MoveNext
Wend
rs1.Close
End Sub
Here is the CheckQuery sub stolen from here: http://www.access-programmers.co.uk/forums/showthread.php?t=206298
Function CheckQuery(queryName As String)
Dim qryLoop As QueryDef
Dim dbs As Database
Dim exists As String
exists = "No"
For Each qryLoop In CurrentDb.QueryDefs
If qryLoop.Name = queryName Then
exists = "Yes"
Exit For
End If
Next
CheckQuery = exists
End Function
Make sure that you are looking in the immediate window for the Debug.Print results.
Slightly tidier version of code from #tlemaster. This will format your output a little better rather than just running all the fields and records together one after the other, removes unnecessary variables from the CheckQuery function and properly releases all the object variables.
Public Sub Test()
Dim rs1 As DAO.Recordset
Dim qryDef As QueryDef
Dim query1 As String
Dim strSQL As String
Dim lngRecordNum As Long '(how many records are you expecting?)
query1 = "qryPullData"
If QueryExists(query1) Then
DoCmd.DeleteObject acQuery, query1
End If
strSQL = "SELECT fl1 As [Field With Spaces One], fl2 As [Field With Spaces Two], " & _
"fl3 As [Field WIth Spaces Three], fl4 As [Field With Spaces Four] " & _
"FROM smallsubset ORDER BY fl1 ASC;"
Set qryDef = CurrentDb.CreateQueryDef(query1, strSQL)
Set rs1 = CurrentDb.OpenRecordset(query1)
lngRecordNum = 1
Do While Not rs1.EOF
Debug.Print "Record " & lngRecordNum & ":"
Debug.Print " " & rs1("Field With Spaces One")
Debug.Print " " & rs1("Field With Spaces Two")
Debug.Print " " & rs1("Field With Spaces Three")
Debug.Print " " & rs1("Field With Spaces Four")
rs1.MoveNext
Loop
Set rs1 = Nothing
Set qryDef = Nothing
End Sub
Public Function QueryExists(queryName As String) As Boolean
Dim qryLoop As QueryDef
For Each qryLoop In CurrentDb.QueryDefs
If qryLoop.Name = queryName Then
QueryExists = True
Exit For
End If
Next
Set qryLoop = Nothing
End Function

How to add selected Items from a listbox into a table?

I am still new to VBA and would appreciate some help.
I need to add the selected items from the listbox into a table, but every time I try the displayed table has no values in it.
Here is the code:
Private Sub BefehlX_Click()
Dim db As Database
Dim rs As Recordset
Dim qdf As QueryDef
Dim varItem As Variant
Dim strCriteria As String
Dim strSQL As String
Dim lstBox As ListBox`
DoCmd.SetWarnings (False)
Set db = CurrentDb()
Set rs = db.OpenRecordset("T_Auswertung", dbOpenDynaset)
Set qdf = db.QueryDefs("Abfrage4")
Set lstBox = Me!ListField1
For Each varItem In lstBox.ItemsSelected
strCriteria = strCriteria & ",'" & lstBox.ItemData(varItem) & "'"
rs.AddNew
'what should be placed here?`
rs.Update
Next varItem
Set rs = Nothing
If Len(strCriteria) = 0 Then
MsgBox "Sie haben keine Queues gewählt!" _
, vbExclamation, "Nichts zu finden!"
Exit Sub
End If
strCriteria = Right(strCriteria, Len(strCriteria) - 1)
DoCmd.SetWarnings (True)
End Sub
If you want to store all values in a single string split by ",", then move the rs.AddNew to outside the For cycle:
For Each varItem In lstBox.ItemsSelected
strCriteria = strCriteria & ",'" & lstBox.ItemData(varItem) & "'"
Next varItem
'removes first ","
strCriteria = Right(strCriteria , Len(strCriteria ) - 1)
rs.AddNew
rs!NAME_OF_FIELD = strCriteria
rs.Update
If you want to store all values in separate registries (so ID = 1 has one itemselected, and ID = 2 has the next one, and so on) keep the add inside the For cycle:
For Each varItem In lstBox.ItemsSelected
strCriteria = lstBox.ItemData(varItem)
rs.AddNew
rs!NAME_OF_FIELD = strCriteria
rs.Update
Next varItem

Exporting Recordset to Spreadsheet

Just getting to grips some VBA (this stuff's new to me so bear with us!)
From query ContactDetails_SurveySoftOutcomes, I'm trying to first find a list of all the unique values in the DeptName field in that query, hence the rsGroup Dim storing a Grouped query on the DeptName field.
I'm then going to use this grouped list as way of cycling through the same query again, but passing through each unique entry as a filter on the whole recordset and export each filtered recordset to its own Excel spreadsheet... see the Do While Not loop.
My code's tripping up on the DoCmd.TransferSpreadsheet ... rsExport part. I'm a bit new to this, but I guess my Dim name rsExport for the recordset isn't accepted in this method..?
Is there an easy fix to the code I've already started or should I be using a completely different approach to achieve all this?
Code:
Public Sub ExportSoftOutcomes()
Dim rsGroup As DAO.Recordset
Dim Dept As String
Dim myPath As String
myPath = "C:\MyFolder\"
Set rsGroup = CurrentDb.OpenRecordset("SELECT ContactDetails_SurveySoftOutcomes.DeptName " _
& "FROM ContactDetails_SurveySoftOutcomes GROUP BY ContactDetails_SurveySoftOutcomes.DeptName", dbOpenDynaset)
Do While Not rsGroup.EOF
Dept = rsGroup!DeptName
Dim rsExport As DAO.Recordset
Set rsExport = CurrentDb.OpenRecordset("SELECT * FROM ContactDetails_SurveySoftOutcomes " _
& "WHERE (((ContactDetails_SurveySoftOutcomes.DeptName)='" & Dept & "'))", dbOpenDynaset)
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, rsExport, myPath & Dept & "\" & Dept & " - Soft Outcomes Survey.xls", True
rsGroup.MoveNext
Loop
End Sub
Fixed Code:
Public Sub ExportSoftOutcomes()
Dim rsGroup As DAO.Recordset
Dim Dept As String
Dim myPath As String
myPath = "C:\MyFolder\"
Set rsGroup = CurrentDb.OpenRecordset("SELECT ContactDetails_SurveySoftOutcomes.DeptName " _
& "FROM ContactDetails_SurveySoftOutcomes GROUP BY ContactDetails_SurveySoftOutcomes.DeptName", dbOpenDynaset)
Do While Not rsGroup.EOF
Dept = rsGroup!DeptName
Dim rsExportSQL As String
rsExportSQL = "SELECT * FROM ContactDetails_SurveySoftOutcomes " _
& "WHERE (((ContactDetails_SurveySoftOutcomes.DeptName)='" & Dept & "'))"
Dim rsExport As DAO.QueryDef
Set rsExport = CurrentDb.CreateQueryDef("myExportQueryDef", rsExportSQL)
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, "myExportQueryDef", myPath & Dept & "\" & Dept & " - Soft Outcomes Survey.xls", True
CurrentDb.QueryDefs.Delete rsExport.Name
rsGroup.MoveNext
Loop
End Sub
You're right that your rsGroup parameter is wrong, Access expects a table name or select query.
Try this code:
strExport = "SELECT * FROM ContactDetails_SurveySoftOutcomes " _
& "WHERE (((ContactDetails_SurveySoftOutcomes.DeptName)='" & Dept & "'))"
Set qdfNew = CurrentDb.CreateQueryDef("myExportQueryDef", strExport)
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, "myExportQueryDef", myPath & Dept & "\" & Dept & " - Soft Outcomes Survey.xls", True
CurrentDb.QueryDefs.Delete qdfNew.Name 'cleanup
Hope that works
try this hope this will help you
Function Export2XLS(sQuery As String)
Dim oExcel As Object
Dim oExcelWrkBk As Object
Dim oExcelWrSht As Object
Dim bExcelOpened As Boolean
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim iCols As Integer
Const xlCenter = -4108
'Start Excel
On Error Resume Next
Set oExcel = GetObject(, "Excel.Application") 'Bind to existing instance of Excel
If Err.Number <> 0 Then 'Could not get instance of Excel, so create a new one
Err.Clear
On Error GoTo Error_Handler
Set oExcel = CreateObject("excel.application")
bExcelOpened = False
Else 'Excel was already running
bExcelOpened = True
End If
On Error GoTo Error_Handler
oExcel.ScreenUpdating = False
oExcel.Visible = False 'Keep Excel hidden until we are done with our manipulation
Set oExcelWrkBk = oExcel.Workbooks.Add() 'Start a new workbook
Set oExcelWrSht = oExcelWrkBk.Sheets(1)
'Open our SQL Statement, Table, Query
Set db = CurrentDb
Set rs = db.OpenRecordset(sQuery, dbOpenSnapshot)
With rs
If .RecordCount <> 0 Then
'Build our Header
For iCols = 0 To rs.Fields.Count - 1
oExcelWrSht.Cells(1, iCols + 1).Value = rs.Fields(iCols).Name
Next
With oExcelWrSht.Range(oExcelWrSht.Cells(1, 1), _
oExcelWrSht.Cells(1, rs.Fields.Count))
.Font.Bold = True
.Font.ColorIndex = 2
.Interior.ColorIndex = 1
.HorizontalAlignment = xlCenter
End With
oExcelWrSht.Range(oExcelWrSht.Cells(1, 1), _
oExcelWrSht.Cells(1, rs.Fields.Count)).Columns.AutoFit 'Resize our Columns based on the headings
'Copy the data from our query into Excel
oExcelWrSht.Range("A2").CopyFromRecordset rs
oExcelWrSht.Range("A1").Select 'Return to the top of the page
Else
MsgBox "There are no records returned by the specified queries/SQL statement.", vbCritical + vbOKOnly, "No data to generate an Excel spreadsheet with"
GoTo Error_Handler_Exit
End If
End With
' oExcelWrkBk.Close True, sFileName 'Save and close the generated workbook
' 'Close excel if is wasn't originally running
' If bExcelOpened = False Then
' oExcel.Quit
' End If
Error_Handler_Exit:
On Error Resume Next
oExcel.Visible = True 'Make excel visible to the user
rs.Close
Set rs = Nothing
Set db = Nothing
Set oExcelWrSht = Nothing
Set oExcelWrkBk = Nothing
oExcel.ScreenUpdating = True
Set oExcel = Nothing
Exit Function
Error_Handler:
MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: Export2XLS" & vbCrLf & _
"Error Description: " & Err.Description _
, vbOKOnly + vbCritical, "An Error has Occured!"
Resume Error_Handler_Exit
End Function
DoCmd.TransferSpreadsheet expects its third parameter to be a String (variable or literal) specifying the name of a table or query. So, instead of opening a DAO.Recordset you could create a DAO.QueryDef named something like "forExportToExcel" with the same SQL code, then use that name in the TransferSpreadsheet call.