Exporting Recordset to Spreadsheet - ms-access

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.

Related

Error 3131 when trying to query on multiselect list box

I have a MultiSelect List Box that I'm trying to use as criteria in a query. I'm fine until the line of code "qdf.SQL = strSQL" at which point I receive the error code 3131. If I place a message box just after the "strSQL =" command, it appears to populate with the correct data.
I am pulling from a list of Categories on a form (Forms("frmMain").listCat1).
What am I doing wrong? Thank you in advance.
Private Sub CAT1_Criteria()
Dim varItem As Variant
Dim strCAT1 As String
Dim ctl As Control
Dim strSQL As String
Dim db As Database
Dim qdf As QueryDef
Set ctl = Forms("frmMain").listCat1
For Each varItem In ctl.ItemsSelected
strCAT1 = strCAT1 & ",'" & ctl.ItemData(varItem) _
& "'"
Next varItem
If Len(strCAT1) = 0 Then
strCAT1 = "Like '*'"
Else
strCAT1 = Right(strCAT1, Len(strCAT1) - 1)
strCAT1 = "IN(" & strCAT1 & ")"
End If
strSQL = "SELECT dbo_CATEGORY1.* FROM dbo_CATEGORY1" & _
"WHERE dbo_CATEGORY1.[LEVEL1] " & strCAT1 & ";"
Set db = CurrentDb
Set qdf = db.QueryDefs("qryCAT1_Sel")
qdf.SQL = strSQL
'Set qdf = Nothing
'Set db = Nothing
DoCmd.OpenQuery "qryCAT1_Sel"
End Sub

Add corresponding OLE object (image) in table through button on form in MS Access

I have a table Students with the following fields: Voornaam, Achternaam and Foto. The fields Voornaam and Achternaam are filled in with the students firstname and lastname. The field Foto (Picture) is empty. Because I don't want to manually add every picture of the students I wanted to do it with some code.
I have a form where I put the records and I have a button to load the photos in the empty fields. I also have a textbox where I could say where he has to look for the photos.
This is my code:
Sub cmdLoad_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim query As String
Dim MyFolder As String
Dim MyPath As String
Dim MyFile As String
'On Error GoTo ErrorHandler
Set db = CurrentDb
query = "Select * FROM tblStudents"
Set rs = db.OpenRecordset(query, dbOpenDynaset)
MyFolder = Me!txtFolder
'Wanneer er geen items zijn. Sluiten
If rs.EOF Then Exit Sub
With rs
Do Until rs.EOF
MyPath = MyFolder & "\" & [Voornaam] & " " & [Achternaam] & ".jpg"
MyFile = Dir(MyPath, vbNormal)
rs.Edit
[Foto].Class = "Paint.Picture"
[Foto].OLETypeAllowed = acOLEEmbedded
[Foto].SourceDoc = MyPath
[Foto].Action = acOLECreateEmbed
rs.Update
rs.MoveNext
Loop
End With
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
Exit Sub
ErrorHandler: MsgBox "Test Error #: " & Err.Number & vbCrLf &
vbCrLf & Err.Description End Sub
I iterate on the results of the table. At every record I edit it and I want to add the picture to the foto field, but here's the problem.
When I click the button to load in, I get the following error:
a error occurred while microsoft access was communicating with the ole
server or activex control
.
When I debug it's on this line where it goes wrong:
[Foto].Action = acOLECreateEmbed
I've tried to find a solution, but so far I couldn't find it. I hope the problem is a bit clear. Or is there a better solution?
I store my user photos, documents etc as BLOB.
Avoids the overhead of OLE embed or link;
http://www.ammara.com/articles/imagesaccess.html
To load;
Private Sub cmdLoadImageClient_Click()
Dim strFile As String
Dim strname As String
strname = Form_subfrmClientDetailsAAClient.FirstName & Form_subfrmClientDetailsAAClient.Surname
strFile = fGetFile("Image", "*.gif; *.jpg; *.jpeg; *.png")
If Len(strFile) > 0 Then
If InsertBLOB("tblzBLOBClientPics", CStr(TempVars!frmClientOpenID), strname, "ClientPic", strFile) Then Call ShowImageClient
End If
End Sub
To delete;
Private Sub cmdDeleteImageClient_Click()
Dim strname As String
Dim i As Integer
strname = Form_subfrmClientDetailsAAClient.FirstName & Form_subfrmClientDetailsAAClient.Surname
i = MsgBox("Do you want to Delete the Image for; " & strname & "?", vbOKCancel, "Beresford Financial.")
Select Case i
Case vbOK
dbLocal.Execute "DELETE FROM tblzBLOBClientPics WHERE ClientID = '" & CStr(TempVars!frmClientOpenID) & "' AND ClientName = '" & strname & "' AND BLOBDesc = 'ClientPic'"
Me.ProfilePicClient.Picture = ""
Case vbCancel
End Select
End Sub
To view;
Public Sub ShowImageClient()
Dim strTemp As String
Dim strname As String
On Error GoTo errHere
Me.ProfilePicClient.Picture = ""
strTemp = CurrentProject.Path & "\Temp.jpg"
strname = Nz(Form_subfrmClientDetailsAAClient.FirstName) & Nz(Form_subfrmClientDetailsAAClient.Surname)
If ExtractBLOB("tblzBLOBClientPics", CStr(TempVars!frmClientOpenID), strname, "ClientPic", strTemp) Then
If Len(Dir(strTemp)) > 0 Then
Me.ProfilePicClient.Picture = strTemp
Kill strTemp
End If
End If
Exit Sub
errHere:
MsgBox "Error " & Err & vbCrLf & Err.Description
End Sub
BLOB Functions;
Option Compare Database
Option Explicit
Function InsertBLOB(tblBLOB As String, ClientID As String, ClientName As String, strDesc As String, strFileName As String) As Boolean
'Inserts BLOB into table tblzBLOBDocuments
On Error GoTo CloseUp
Dim objStream As Object 'ADODB.Stream
Dim objCmd As Object 'ADODB.Command
Dim varFileBinary
'Empty any matching record
CurrentDb.Execute "DELETE FROM " & tblBLOB & " WHERE ClientID = '" & ClientID & "' AND ClientName = '" & ClientName & "' AND BLOBDesc = '" & strDesc & "'"
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = 1 'adTypeBinary
objStream.Open
objStream.LoadFromFile strFileName
varFileBinary = objStream.Read
objStream.Close
Set objStream = Nothing
Set objCmd = CreateObject("ADODB.Command")
With objCmd
.CommandText = "PARAMETERS paramID Text(255), paramTable Text(255), paramDesc Text(255), paramExtn Text(5), paramFile LongBinary;" & _
"INSERT INTO " & tblBLOB & " (ClientID, ClientName, BLOBDesc, FileExtn, BLOB) " & _
"SELECT paramID, paramTable, paramDesc, paramExtn, paramFile"
.CommandType = 1 'adCmdText
.Parameters.Append .CreateParameter("paramID", 200, 1, 255, ClientID)
.Parameters.Append .CreateParameter("paramTable", 200, 1, 255, ClientName)
.Parameters.Append .CreateParameter("paramDesc", 200, 1, 255, strDesc)
.Parameters.Append .CreateParameter("paramExtn", 200, 1, 5, right(strFileName, Len(strFileName) - InStrRev(strFileName, ".")))
.Parameters.Append .CreateParameter("paramFile", 205, 1, 2147483647, varFileBinary)
Set .ActiveConnection = CurrentProject.Connection
.Execute , , 128
End With
InsertBLOB = True
CloseUp:
On Error Resume Next
Set objStream = Nothing
Set objCmd = Nothing
End Function
Function ExtractBLOB(tblBLOB As String, ClientID As String, ClientName As String, strDesc As String, ByRef strFileName As String) As Boolean
'Extracts specified BLOB to file from table tblzBLOBDocuments
Dim strSql As String
Dim rst As Object 'ADODB.Recordset
Dim objStream As Object 'ADODB.Stream
Set rst = CreateObject("ADODB.Recordset")
strSql = "SELECT FileExtn, BLOB FROM " & tblBLOB & " WHERE ClientID = '" & ClientID & "' AND ClientName = '" & ClientName & "' AND BLOBDesc = '" & strDesc & "'"
rst.Open strSql, CurrentProject.Connection, 1, 3
If rst.RecordCount = 0 Then
GoTo CloseUp
End If
Set objStream = CreateObject("ADODB.Stream")
With objStream
.Type = 1 'adTypeBinary
.Open
.Write rst.Fields("BLOB").Value
If Not IsNull(rst!FileExtn) Then
strFileName = Left(strFileName, InStrRev(strFileName, ".")) & rst!FileExtn
End If
.SaveToFile strFileName, 2 'adSaveCreateOverWrite
End With
ExtractBLOB = True
CloseUp:
On Error Resume Next
rst.Close
Set rst = Nothing
Set objStream = Nothing
End Function
Filepicker;
Function fGetFile(strType As String, strExt As String, Optional strPath As String)
With Application.FileDialog(3) ' 3=msoFileDialogFilePicker 4=msoFileDialogFolderPicker
' .Filters.Add "Excel Files", "*.xls, *.xlsx, *.xlsm", 1
.Filters.Add strType, strExt, 1
If strPath <> "" Then
.InitialFileName = strPath ' start in this folder
End If
.AllowMultiSelect = False
.Show
If .SelectedItems.Count > 0 Then
' MsgBox .SelectedItems(1)
fGetFile = .SelectedItems(1)
End If
End With
End Function
tblzBLOBClientPics;
ClientID Short Text
ClientName Short Text
BLOBDesc Short Text
FileExtn Short Text
BLOB OLE Object

SQL with no matches found causes MsgBox

My form takes the data the user entered, constructs a SQL statement and returns the results. I would like to have a message box pop up when there are no matches found.
My current code/idea:
If qdf.sql = 0 Then
MsgBox "No clients matching your information." & _
vbCrLf & "have been found. Please try again." & _
, vbCritical, "No Matches"
Else
DoCmd.OpenForm "frmSearchResults"
Me.Visible = False
End If
I'm having trouble figuring out the correct syntax for if qdf.sql = 0 .
UPDATE: Full query
Private Sub cmdSearch_Click()
'On Error GoTo cmdSearch_Click_err
Dim db As Database
Dim strSQL As String
Dim rs As DAO.Recordset
Dim qdf As QueryDef
Dim strClientID As String
Dim strLastName As String
Dim strFirstName As String
Dim strDOB As String
Set db = CurrentDb
Set rs = db.OpenRecordset(qdf.sql)
' call QueryCheck module to determine if query exists
If Not QueryExists("qrySearch") Then
Set qdf = db.CreateQueryDef("qrySearch")
Else
Set qdf = db.QueryDefs("qrySearch")
End If
' handle nulls in the user's entries
If IsNull(Me.txtClientID.Value) Then
strClientID = " Like '*' "
Else
strClientID = "='" & Me.txtClientID.Value & "' "
End If
If IsNull(Me.txtLastName.Value) Then
strLastName = " Like '*' "
Else
strLastName = " Like '" & Me.txtLastName.Value & "*' "
End If
If IsNull(Me.txtFirstName.Value) Then
strFirstName = " Like '*' "
Else
strFirstName = " Like '*" & Me.txtFirstName.Value & "*' "
End If
If IsNull(Me.txtDOB.Value) Then
strDOB = " Like '*' "
Else
strDOB = "='" & Me.txtDOB.Value & "' "
End If
strSQL = "SELECT Clients.* " & _
"FROM Clients " & _
"WHERE Clients.clientid" & strClientID & _
"AND Clients.namelast" & strLastName & _
"AND Clients.namefirst" & strFirstName & _
"AND Clients.birthdate" & strDOB & _
"ORDER BY Clients.namelast,Clients.namefirst;"
Debug.Print strSQL
' check to see if the results form is open and close if it is
DoCmd.Echo False
If Application.SysCmd(acSysCmdGetObjectState, acForm, "frmSearchResults") = acObjStateOpen Then
DoCmd.Close acForm, "frmSearchResults"
End If
' run SQL statment
qdf.sql = strSQL
' check for no matches found
If rs.RecordCount = 0 Then
MsgBox "No clients matching your information were found." & _
vbCrLf & "Please search again.", vbInformation, "No Matches"
Else
DoCmd.OpenForm "frmSearchResults"
Me.Visible = False
End If
'cmdSearch_Click_exit:
' DoCmd.Echo True
' Set qdf = Nothing
' Set db = Nothing
'Exit Sub
'cmdSearch_Click_err:
' MsgBox "An unexpected error has occurred." & _
' vbCrLf & "Please note of the following details and contact the EIIS support desk:" & _
' vbCrLf & "Error Number: " & Err.Number & _
' vbCrLf & "Description: " & Err.Description _
' , vbCritical, "Error"
' Resume cmdSearch_Click_exit
End Sub
The reason that If qdf.sql = 0 then won't perform a proper check is that qdf contains the information about your query such as the SQL text that you are checking in that statement but not the results.
To get the results of the query you need to assign it to a Recordset after you have build your query. So first build your query and then assign it to the record set.
Dim db as DAO.Database
Set db = CurrentDb
Dim qdf as DAO.Querydef
Set qdf = db.CreateQueryDef("qrySearch")
Dim rs as DAO.Recordset
Set rs = CurrentDb.OpenRecordset(qdf.sql)
You can then check what your record set has returned.
If rs.RecordCount = 0 then
So where you have your line ' run SQL statment you would want to place the Set rs line.
If you have any ADO experience you can use something like
dim strSQL as String
dim conn as Connection
dim cmd as Command
dim rs as Recordset
(set up connection/command here)
cmd.commandtext = (your select query)
set rs = Command.execute
if rs.eof then
(or if rs.recordcount = 0 however returning a recordcount requires the correct cursortype - usually adOpenStatic - to be used)
'msgbox no match
else
'do stuff
If any of this is alien, then post your actual query and I'll try and give you the code in full. Good luck!

Using iMacros with VBA to fill out a form on a site with a name then grab results for table of names

first off I am brand new to iMacros and not great with VBA (I know not a great start)
So my end game is to use iMacros to go to a site fill in a form on the site with a name from a table in access enter the name and grab some resulting text from that site grab the text and put it in a table. I will have to do this for each record in the table. So far this is what I have:
Dim Rs As DAO.Recordset 'recordset for list of names from VcWAuditUsers
Dim db As DAO.Database
Dim SQL As String
Dim Sql2 As String
Dim STRErr As String
Dim sTableName As String
Dim serverName As String
Dim dbName As String
Dim strUserCnt As Integer
Dim UserName As Variant
Dim StrSql As String
Dim iim1, iret
Set iim1 = CreateObject("imacros")
iret = iim1.iimInit
iret = iim1.iimPlayCode("URL GOTO=https://www.sam.gov/portal/public/SAM/)
sTableName = "vCPpAuditUsers"
serverName = GetLinkedServer(sTableName)
dbName = GetLinkedDatabase(sTableName)
SQL = "Select Distinct FName, LName from " & sTableName
Set db = CurrentDb
Set Rs = db.OpenRecordset(SQL)
If (Not Rs.EOF And Not Rs.BOF) Then
Rs.MoveLast
Rs.MoveFirst
With Rs
Do While (Rs.EOF = False)
UserName = Trim(![FName]) & " " & Trim(![LName])
MsgBox ("New Name: " & UserName)
strUserCnt = Rs.recordCount
MsgBox ("Number of rows: " & strUserCnt)
'set iMacros variables
iret = iim1.iimSet("CONTENT", UserName)
iret = iim1.iimPlay("Y:\Data\FS01-M\Healthcare\SAM_iMacro\SAMiMacro.iim")
If iret < 0 Then
MsgBox iim1.iimGetLastError()
End If
StrSql = "Insert Into ExceptionResults Values('" & UserName & "','" & iim1.iimGetExtract(1) & Now & "')"
MsgBox ("Test SqlInsert: " & StrSql)
.MoveNext
Loop
End With
Rs.Close
db.Close
End If
I know that I am missing some key stuff but I have been unable to find a good example to base what I am doing on.
Any help is greatly appreciated!
Thanks.
What I came up with:
Option Compare Database
Option Explicit
Private Sub cmdGetExceptions_Click()
Dim YNMess As String
YNMess = MsgBox("Do you wish to truncate results table ExceptionResults?", vbYesNo, "TRUNCATE?")
If YNMess = vbYes Then
Call ClearExceptionTable
Call RunExceptionTable
End If
If YNMess = vbNo Then
Call RunExceptionTable
End If
End Sub
Private Sub RunExceptionTable()
Dim Rs As DAO.Recordset 'recordset for list of names from VcWAuditUsers
Dim db As DAO.Database
Dim SQL As String
Dim sTableName As String
Dim serverName As String
Dim dbName As String
Dim strUserCnt As Integer
Dim UserName As Variant
Dim StrSql As String
Dim ExceptStat As String
On Error GoTo ErrHandler
Dim iim1, iret
' Creates iMacros object and gives the starting webpage
Set iim1 = CreateObject("imacros")
iret = iim1.iimInit
iret = iim1.iimPlayCode("URL GOTO=https://www.sam.gov/)
'Sets the source table name
sTableName = "[SourceTable]"
'Sets the SQL string to grab the names of people to be inserted into website input section
SQL = "Select Distinct FName, LName from " & sTableName
'Starts the recordset for the source table and recordset
Set db = CurrentDb
Set Rs = db.OpenRecordset(SQL)
'resets the RS to start at the begining
If (Not Rs.EOF And Not Rs.BOF) Then
Rs.MoveLast
Rs.MoveFirst
'Grabs the total record count to use for end user messaging.
strUserCnt = Rs.recordCount
'MsgBox ("Number of rows: " & strUserCnt)
'Opens RS and starts while loop to open first record of the source table
With Rs
Do While (Rs.EOF = False)
'Creates new UserName by combining first and last name
UserName = Trim(![FName]) & " " & Trim(![LName])
'MsgBox ("New Name: " & UserName)
'set iMacros variables This subs the spot in the iMacros code where you manually entered information (there should be {{USERNAME}} in the iMacros where you want to enter data.
iret = iim1.iimSet("USERNAME", UserName)
'Plays the iMacro you recorded and altered earlier.
iret = iim1.iimPlay("Location of your iMacros goes here.iim")
'Checks for errors in the iMacros(anything in the negative is considered an error)
If iret < 0 Then
MsgBox iim1.iimGetLastError()
End If
'grabs the extracted data from recorded iMacro. the extracted data is stored in an (1) based array. Makes substitutions for the text that it extracts to convert to 1 or 0
If Left(iim1.iimGetExtract(1), 2) = "No" Then
ExceptStat = 0
Else
ExceptStat = 1
End If
'For each record in the source the extracted data is entered into the insert statement below along with the employee name and date. then warnings are suppressed and each is inserted into a local access table, Loop and move to the next.
StrSql = "Insert Into ExceptionResults Values('" & UserName & "'," & ExceptStat & ",'" & Now & "')"
DoCmd.SetWarnings False
DoCmd.RunSQL (StrSql)
DoCmd.SetWarnings True
.MoveNext
Loop
End With
MsgBox ("ExceptionResults table is complete and has " & strUserCnt & " Records")
'Clean up
Rs.Close
db.Close
End If
'Clean up
Set db = CurrentDb
Set Rs = db.OpenRecordset(SQL)
Set iim1 = Nothing
strUserCnt = 0
ErrHandler:
MsgBox "ERROR" & vbCrLf & Err.Description, vbCritical, "CmdGetExceptions"
End Sub
Private Sub ClearExceptionTable()
Dim StrSql2 As String
StrSql2 = "Delete from ExceptionResults"
DoCmd.SetWarnings False
DoCmd.RunSQL (StrSql2)
DoCmd.SetWarnings True
MsgBox ("All records from ExceptionResults have been truncated")
End Sub

Access 2007 VBA Report email per company

I have a suppliers' report about 150 pages in access 2007. Each report has address, emails contact person, phone number, products and name of company per page. Once a month I have to send an email to the suppliers to confirm changes of contact person address, phone number and products.
I want to send that particular report to that particular email not the whole report.
I want this to be automated.
I have written code in VBA after research on the net and still not working. I am getting Too many parameters. Expected 1. Error.
Below is code for my form with a Send Report button.
Dim strSql As String
Dim strSubject As String
Dim strMsgBody As String
strSql = "SELECT DISTINCT Name, EMail FROM [Suppliers and Products]"
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset(strSql)
'loop through the recordset
Do While Not rst.EOF
' grab email string
strEmail = rst.Fields("EMail")
' grab name
strName = rst.Fields("Name")
Call fnUserID(rst.Fields("EMail"))
'send the pdf of the report to curent supplier
On Error Resume Next
strSubject = "September 2012 Supplier's Listing"
strMsgBody = "2008 Procedure Review Attached"
DoCmd.SendObject acSendReport, "Suppliers Confirmation forms", acFormatHTML, strEmail, , , strSubject, strMsgBody, False
If Err.Number <> 0 Then
MsgBox Err.Number & vbCrLf & Err.Description, vbOKOnly, "Delivery Failure to the following email address: " & strEmail
End If
On Error GoTo PROC_ERR
' move and loop
rst.MoveNext
Loop
' clean up
rst.Close
Set rst = Nothing
dbs.Close
Set dbs = Nothing
PROC_Exit:
Exit Sub
PROC_ERR:
MsgBox Err.Description
Resume PROC_Exit
I have a module with the following code
Option Compare Database
Public Function fnUserID(Optional Somevalue As Variant = Null, Optional reset As Boolean = False) As Variant
Static EMail As Variant
If reset Or IsEmpty(EMail) Then EMail = Null
If Not IsNull(Somevalue) Then EMail = Somevalue
fnUserID = EMail
End Function
Public Function SendReportByEmail(strReportName As String, strEmail As String)
On Error GoTo PROC_ERR
Dim strRecipient As String
Dim strSubject As String
Dim strMessageBody As String
'set the email variables
strRecipients = strEmail
strSubject = Reports(strReportName).Caption
strMessageBody = "May 2012 Suppliers' List "
' send report as HTML
DoCmd.SendObjectac acSendReport, strReportName, acFormatHTML, strRecipients, , , strSubject, strMessageBody, False
SendReportByEmail = True
PROC_Exit:
Exit Function
Proc Err:
SendReportByEmail = False
If Err.Number = 2501 Then
Call MsgBox("The email was not sent for " & strEmail & ".", vbOKOnly + vbExclamation + vbDefaultButton1, "User Cancelled Operation")
Else: MsgBox Err.Description
End If
Resume PROC_Exit
End Function
The query which is report is getting its data has the following SQL.
SELECT Names.Name, Names.Phys_Address,
Names.Telephones, Names.Fax, Names.EMail,
Names.Web, Names.Caption AS Expr1, [Products by Category].CatName,
[Products by Category].ProdName
FROM [Names]
INNER JOIN [Products by Category]
ON Names.SuppID=[Products by Category].SupID
WHERE ((Names.EMail = fnUserID()) or (fnUserID() Is Null));
Please help as I am stuck to where I am going wrong.
Some notes.
On Error GoTo PROC_ERR
Dim qdf As QueryDef
Dim strSQL As String
Dim strSubject As String
Dim strMsgBody As String
strSQL = "SELECT DISTINCT [Name], EMail, SuppID FROM Names " _
& "INNER JOIN [Products by Category] " _
& "ON Names.SuppID=[Products by Category].SupID "
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset(strSql)
qrySQL = "SELECT Names.Name, Names.Phys_Address, " _
& "Names.Telephones, Names.Fax, Names.EMail, " _
& "Names.Web, Names.Caption AS Expr1, " _
& "[Products by Category].CatName, " _
& "[Products by Category].ProdName " _
& "FROM [Names] " _
& "INNER JOIN [Products by Category] " _
& "ON Names.SuppID=[Products by Category].SupID "
'loop through the recordset
Do While Not rst.EOF
' grab email string
strEmail = rst.Fields("EMail")
' grab name
strName = rst.Fields("Name")
' You should check that the email is not null
Call fnUserID(rst.Fields("EMail"))
'send the pdf of the report to curent supplier
'On Error Resume Next
'The query that the report uses
Set qdf = CurrentDB.QueryDefs("Suppliers and Products")
qdf.SQL = qrySQL & " WHERE SuppID=" & rst!SuppID
strSubject = "September 2012 Supplier's Listing"
strMsgBody = "2008 Procedure Review Attached"
DoCmd.SendObject acSendReport, "Suppliers Confirmation forms", _
acFormatHTML, strEmail, , , strSubject, strMsgBody, False
' move and loop
rst.MoveNext
Loop
''Reset the query
qdf.SQL = qrySQL
rst.Close
Set rst = Nothing
dbs.Close
Set dbs = Nothing
PROC_Exit:
Exit Sub
PROC_ERR:
If Err.Number <> 0 Then
MsgBox Err.Number & vbCrLf & Err.Description, vbOKOnly, _
"Delivery Failure to the following email address: " & strEmail
End If
MsgBox Err.Description
Resume PROC_Exit