coding help - please

S

sue gray

I am working on a project (again). I have a multi page report that has
employee information on separate pages. I want to email the individual
report to employee. I have been given help before, but I always get in way
over my head. I really could use some more help. This is the code I have
copied/tweeked so far. The problem is right now I can't get passed "Set rst
= CurrentDb.OpenRecordset("All Emp Time To Date")" I step thru the code and
soon as I hit that line it goes to the error message. I haven't worked too
much on the rest of the code yet. Any help is greatly, greatly appreciated.
I have this code in a new module. THanks in advance.


Option Compare Database

Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim strBody As String, lngCount As Long, lngRSCount As Long
Dim db As Database
Dim rst As Recordset

Set rst = CurrentDb.OpenRecordset("All Emp Time To Date")

lngRSCount = rs.RecordCount
If lngRSCount = 0 Then
MsgBox "No promo email messages to send.", vbInformation
Else
rs.MoveLast
rs.MoveFirst
Do Until rs.EOF
lngCount = lngCount + 1
strTo = rs!cEmailAddress
intMessageID = Year(Now) & Month(Now) & Day(Now) & Fix(Timer) &
"_MabryMail"
' Send the email using some technique or other
rs.Edit
rs("cpeDateTimeEmailed") = Now()
rs.Update
rs.MoveNext
Loop

End If
rs.Close
MyDB.Close
Set rs = Nothing
Set MyDB = Nothing
Close


MsgBox "Done sending Promo email. ", vbInformation, "Done"

Exit Sub

Some_Err:
'MousePointer = 0
MsgBox "Error (" & CStr(Err.Number) & ") " & Err.Description, _
vbExclamation, "Error!"


End Sub
 
J

Jack Leach

Dim rst As Recordset

dim this line as a DAO.Recrdset:

Dim rst As DAO.Recordset


Set rst = CurrentDb.OpenRecordset("All Emp Time To Date")

Enclose your query name in brackets (or even better don't use spaces in your
naming scheme)

Set rst = CurrentDb.OpenRecordset("[All Emp Time To Date"])



and...
Dim db As Database

you have db dimmed as a database, but never use it (you are using CurrentDb
as the database object instead). Get rid of that line.


and...
MyDB.Close
Set rs = Nothing
Set MyDB = Nothing

Here you are close MyDB (which appears to be a database object variable,
though it is not dimensioned). You probably don't want to close your db, so
get rid of the MyDB.Close line. And, being that MyDB is not dimmed, you
don't need to set it to nothing, so you can get rid of the Set MyDB = Nothing
line (remember, you are using CurrentDb as the database object to open the
recordset, and therefore don't need a variable to hold it)



This statement is used to close an open file (ex: Close #FileNum). I see no
reason for this to be here, so I guess you can get rid of that as well.



The variable lngRSCount you are using to check the count of the recordset,
but it is not necessary, you can check the count directly from the property.
And, lngCount you are making a count of the records you are looping, but
aren't doing anything with it after, so you can get rid of that. All in all,
to clean up your code a litte, here's what you would wind up with:


Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim strBody As String
Dim rst As DAO.Recordset

Set rst = CurrentDb.OpenRecordset("[AllEmpTimeToDate]")

If rst.RecordCount = 0 Then
MsgBox "No promo email messages to send.", vbInformation
Else
rst.MoveFirst
Do Until rs.EOF
strTo = rst!cEmailAddress
intMessageID = Year(Now) & Month(Now) & Day(Now) & Fix(Timer) &
"_MabryMail"
' Send the email using some technique or other
With rst
.Edit
.Fields("cpeDateTimeEmailed") = Now()
.Update
.MoveNext
End With
Loop

End If
rst.Close
Set rst = Nothing

MsgBox "Done sending Promo email. ", vbInformation, "Done"

Exit Sub

Some_Err:
'MousePointer = 0
MsgBox "Error (" & CStr(Err.Number) & ") " & Err.Description, _
vbExclamation, "Error!"
End Sub



hth!

--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that don''t work."
-Thomas Edison (1847-1931)
 
D

Dorian

You got the brackets in the wrong place...

Enclose your query name in brackets (or even better don't use spaces in your
naming scheme)

Set rst = CurrentDb.OpenRecordset("[All Emp Time To Date"])
should be
Set rst = CurrentDb.OpenRecordset("[All Emp Time To Date]")

--
"Give someone a fish and they eat for a day; teach someone to fish and they
eat for a lifetime".


Jack Leach said:
Dim rst As Recordset

dim this line as a DAO.Recrdset:

Dim rst As DAO.Recordset


Set rst = CurrentDb.OpenRecordset("All Emp Time To Date")

Enclose your query name in brackets (or even better don't use spaces in your
naming scheme)

Set rst = CurrentDb.OpenRecordset("[All Emp Time To Date"])



and...
Dim db As Database

you have db dimmed as a database, but never use it (you are using CurrentDb
as the database object instead). Get rid of that line.


and...
MyDB.Close
Set rs = Nothing
Set MyDB = Nothing

Here you are close MyDB (which appears to be a database object variable,
though it is not dimensioned). You probably don't want to close your db, so
get rid of the MyDB.Close line. And, being that MyDB is not dimmed, you
don't need to set it to nothing, so you can get rid of the Set MyDB = Nothing
line (remember, you are using CurrentDb as the database object to open the
recordset, and therefore don't need a variable to hold it)



This statement is used to close an open file (ex: Close #FileNum). I see no
reason for this to be here, so I guess you can get rid of that as well.



The variable lngRSCount you are using to check the count of the recordset,
but it is not necessary, you can check the count directly from the property.
And, lngCount you are making a count of the records you are looping, but
aren't doing anything with it after, so you can get rid of that. All in all,
to clean up your code a litte, here's what you would wind up with:


Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim strBody As String
Dim rst As DAO.Recordset

Set rst = CurrentDb.OpenRecordset("[AllEmpTimeToDate]")

If rst.RecordCount = 0 Then
MsgBox "No promo email messages to send.", vbInformation
Else
rst.MoveFirst
Do Until rs.EOF
strTo = rst!cEmailAddress
intMessageID = Year(Now) & Month(Now) & Day(Now) & Fix(Timer) &
"_MabryMail"
' Send the email using some technique or other
With rst
.Edit
.Fields("cpeDateTimeEmailed") = Now()
.Update
.MoveNext
End With
Loop

End If
rst.Close
Set rst = Nothing

MsgBox "Done sending Promo email. ", vbInformation, "Done"

Exit Sub

Some_Err:
'MousePointer = 0
MsgBox "Error (" & CStr(Err.Number) & ") " & Err.Description, _
vbExclamation, "Error!"
End Sub



hth!

--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that don''t work."
-Thomas Edison (1847-1931)



sue gray said:
I am working on a project (again). I have a multi page report that has
employee information on separate pages. I want to email the individual
report to employee. I have been given help before, but I always get in way
over my head. I really could use some more help. This is the code I have
copied/tweeked so far. The problem is right now I can't get passed "Set rst
= CurrentDb.OpenRecordset("All Emp Time To Date")" I step thru the code and
soon as I hit that line it goes to the error message. I haven't worked too
much on the rest of the code yet. Any help is greatly, greatly appreciated.
I have this code in a new module. THanks in advance.


Option Compare Database

Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim strBody As String, lngCount As Long, lngRSCount As Long
Dim db As Database
Dim rst As Recordset

Set rst = CurrentDb.OpenRecordset("All Emp Time To Date")

lngRSCount = rs.RecordCount
If lngRSCount = 0 Then
MsgBox "No promo email messages to send.", vbInformation
Else
rs.MoveLast
rs.MoveFirst
Do Until rs.EOF
lngCount = lngCount + 1
strTo = rs!cEmailAddress
intMessageID = Year(Now) & Month(Now) & Day(Now) & Fix(Timer) &
"_MabryMail"
' Send the email using some technique or other
rs.Edit
rs("cpeDateTimeEmailed") = Now()
rs.Update
rs.MoveNext
Loop

End If
rs.Close
MyDB.Close
Set rs = Nothing
Set MyDB = Nothing
Close


MsgBox "Done sending Promo email. ", vbInformation, "Done"

Exit Sub

Some_Err:
'MousePointer = 0
MsgBox "Error (" & CStr(Err.Number) & ") " & Err.Description, _
vbExclamation, "Error!"


End Sub
 
J

Jack Leach

oops... sorry that last one was supposed to be inside the quote

--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that don''t work."
-Thomas Edison (1847-1931)



Dorian said:
You got the brackets in the wrong place...

Enclose your query name in brackets (or even better don't use spaces in your
naming scheme)

Set rst = CurrentDb.OpenRecordset("[All Emp Time To Date"])
should be
Set rst = CurrentDb.OpenRecordset("[All Emp Time To Date]")

--
"Give someone a fish and they eat for a day; teach someone to fish and they
eat for a lifetime".


Jack Leach said:
Dim rst As Recordset

dim this line as a DAO.Recrdset:

Dim rst As DAO.Recordset


Set rst = CurrentDb.OpenRecordset("All Emp Time To Date")

Enclose your query name in brackets (or even better don't use spaces in your
naming scheme)

Set rst = CurrentDb.OpenRecordset("[All Emp Time To Date"])



and...
Dim db As Database

you have db dimmed as a database, but never use it (you are using CurrentDb
as the database object instead). Get rid of that line.


and...
MyDB.Close
Set rs = Nothing
Set MyDB = Nothing

Here you are close MyDB (which appears to be a database object variable,
though it is not dimensioned). You probably don't want to close your db, so
get rid of the MyDB.Close line. And, being that MyDB is not dimmed, you
don't need to set it to nothing, so you can get rid of the Set MyDB = Nothing
line (remember, you are using CurrentDb as the database object to open the
recordset, and therefore don't need a variable to hold it)



This statement is used to close an open file (ex: Close #FileNum). I see no
reason for this to be here, so I guess you can get rid of that as well.



The variable lngRSCount you are using to check the count of the recordset,
but it is not necessary, you can check the count directly from the property.
And, lngCount you are making a count of the records you are looping, but
aren't doing anything with it after, so you can get rid of that. All in all,
to clean up your code a litte, here's what you would wind up with:


Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim strBody As String
Dim rst As DAO.Recordset

Set rst = CurrentDb.OpenRecordset("[AllEmpTimeToDate]")

If rst.RecordCount = 0 Then
MsgBox "No promo email messages to send.", vbInformation
Else
rst.MoveFirst
Do Until rs.EOF
strTo = rst!cEmailAddress
intMessageID = Year(Now) & Month(Now) & Day(Now) & Fix(Timer) &
"_MabryMail"
' Send the email using some technique or other
With rst
.Edit
.Fields("cpeDateTimeEmailed") = Now()
.Update
.MoveNext
End With
Loop

End If
rst.Close
Set rst = Nothing

MsgBox "Done sending Promo email. ", vbInformation, "Done"

Exit Sub

Some_Err:
'MousePointer = 0
MsgBox "Error (" & CStr(Err.Number) & ") " & Err.Description, _
vbExclamation, "Error!"
End Sub



hth!

--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that don''t work."
-Thomas Edison (1847-1931)



sue gray said:
I am working on a project (again). I have a multi page report that has
employee information on separate pages. I want to email the individual
report to employee. I have been given help before, but I always get in way
over my head. I really could use some more help. This is the code I have
copied/tweeked so far. The problem is right now I can't get passed "Set rst
= CurrentDb.OpenRecordset("All Emp Time To Date")" I step thru the code and
soon as I hit that line it goes to the error message. I haven't worked too
much on the rest of the code yet. Any help is greatly, greatly appreciated.
I have this code in a new module. THanks in advance.


Option Compare Database

Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim strBody As String, lngCount As Long, lngRSCount As Long
Dim db As Database
Dim rst As Recordset

Set rst = CurrentDb.OpenRecordset("All Emp Time To Date")

lngRSCount = rs.RecordCount
If lngRSCount = 0 Then
MsgBox "No promo email messages to send.", vbInformation
Else
rs.MoveLast
rs.MoveFirst
Do Until rs.EOF
lngCount = lngCount + 1
strTo = rs!cEmailAddress
intMessageID = Year(Now) & Month(Now) & Day(Now) & Fix(Timer) &
"_MabryMail"
' Send the email using some technique or other
rs.Edit
rs("cpeDateTimeEmailed") = Now()
rs.Update
rs.MoveNext
Loop

End If
rs.Close
MyDB.Close
Set rs = Nothing
Set MyDB = Nothing
Close


MsgBox "Done sending Promo email. ", vbInformation, "Done"

Exit Sub

Some_Err:
'MousePointer = 0
MsgBox "Error (" & CStr(Err.Number) & ") " & Err.Description, _
vbExclamation, "Error!"


End Sub
 
C

ChrisO

Sue.

"All Emp Time To Date" is fine the way it is, it is probably a reference
problem.
(You could think about removing the spaces, but that’s not essential.)

Let’s also look at a few other things while we’re at it.

You don’t have Option Explicit and that’s a bit of a ‘no no’ for this type
of stuff.
We should also try to clean the code, meaning removing all that we can and
only add that which is needed.

With your code as posted…
On of the things we can remove are all references.
Apart from the passed arguments we can also remove all declared variables.
The other thing we can do is break it up into smaller manageable chunks.
Smaller chunks are easier to late bind.
We can also standardize our error handling which also works better on
smaller chunks.
I’ll use your error handler but would suggest including the Procedure Name,
at the very least.

So let’s have a look at it: -


Option Explicit ' This should be used.
' Option Compare Database ' This is debatable.
Option Compare Text


Public Sub Email_RPT_to_All_Emp_Click()

On Error GoTo ErrorHandler

With CurrentDb.OpenRecordset("All Emp Time To Date")
If .RecordCount Then
Do Until .EOF
If Len(!cEmailAddress) Then
If SendEMail(!cEmailAddress, , "Some Text") Then
.Edit
!cpeDateTimeEmailed = Now()
.Update
End If
End If
.MoveNext
Loop
.Close
MsgBox "Done sending Promo email. ", vbInformation, "Done"
Else
MsgBox "No promo email messages to send.", vbInformation
End If
End With

ExitProcedure:
Exit Sub

ErrorHandler:
MsgBox "Error (" & CStr(err.Number) & ") " & err.Description,
vbExclamation, "Error!"

Resume ExitProcedure

End Sub


Public Function SendEMail(ByVal strTo As String, _
Optional strSubject As String = "No subject
transmitted.", _
Optional strBody As String = "No body transmitted.")
As Integer

On Error GoTo ErrorHandler

With CreateObject("Outlook.Application").CreateItem(0)
.To = strTo
.Subject = strSubject
.Body = strBody
.Send
End With

SendEMail = True

ExitProcedure:
Exit Function

ErrorHandler:
MsgBox "Error (" & CStr(err.Number) & ") " & err.Description,
vbExclamation, "Error!"

Resume ExitProcedure

End Function

Regards,
Chris.
 
S

sue gray

Thanks for all the help. I am trying really hard to learn how to code, but
still need a ton of help. I have changed alot of he code using suggestions
from here. I've come a long way, but I still can't get the results I want.
The problem I have now is the report will attach to the email, but it will
either be blank or wil include everyone. Any help is greatly appreciated.

Option Explicit
Option Compare Database

Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim rst As DAO.Recordset
Dim strempid As Long
Dim strTo As String

Set rst = CurrentDb.OpenRecordset("All EmpTimeToDate_Crosstab")

If rst.RecordCount = 0 Then
MsgBox "No Reports to email.", vbInformation
Else
rst.MoveFirst
Do Until rst.EOF
strempid = rst!EmployeeID
strTo = rst!EmailAddress

DoCmd.OpenReport "All Emp Time", acViewPreview, , "[EmployeeID] =
strempid"

DoCmd.SendObject acSendReport, "All Emp Time", acFormatSNP, strTo, ,
, "Monthly Time", "Attached is your monthly time"

rst.MoveNext

Loop

End If
rst.Close
Set rst = Nothing

MsgBox "Done sending Employee Time email. ", vbInformation, "Done"

Exit Sub

Some_Err:
MsgBox "Error (" & CStr(Err.Number) & ") " & Err.Description, _
vbExclamation, "Error!"

End Sub





Jack Leach said:
oops... sorry that last one was supposed to be inside the quote

--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that don''t work."
-Thomas Edison (1847-1931)



Dorian said:
You got the brackets in the wrong place...

Enclose your query name in brackets (or even better don't use spaces in your
naming scheme)

Set rst = CurrentDb.OpenRecordset("[All Emp Time To Date"])
should be
Set rst = CurrentDb.OpenRecordset("[All Emp Time To Date]")

--
"Give someone a fish and they eat for a day; teach someone to fish and they
eat for a lifetime".


Jack Leach said:
Dim rst As Recordset

dim this line as a DAO.Recrdset:

Dim rst As DAO.Recordset



Set rst = CurrentDb.OpenRecordset("All Emp Time To Date")

Enclose your query name in brackets (or even better don't use spaces in your
naming scheme)

Set rst = CurrentDb.OpenRecordset("[All Emp Time To Date"])



and...

Dim db As Database

you have db dimmed as a database, but never use it (you are using CurrentDb
as the database object instead). Get rid of that line.


and...

MyDB.Close
Set rs = Nothing
Set MyDB = Nothing

Here you are close MyDB (which appears to be a database object variable,
though it is not dimensioned). You probably don't want to close your db, so
get rid of the MyDB.Close line. And, being that MyDB is not dimmed, you
don't need to set it to nothing, so you can get rid of the Set MyDB = Nothing
line (remember, you are using CurrentDb as the database object to open the
recordset, and therefore don't need a variable to hold it)



Close

This statement is used to close an open file (ex: Close #FileNum). I see no
reason for this to be here, so I guess you can get rid of that as well.



The variable lngRSCount you are using to check the count of the recordset,
but it is not necessary, you can check the count directly from the property.
And, lngCount you are making a count of the records you are looping, but
aren't doing anything with it after, so you can get rid of that. All in all,
to clean up your code a litte, here's what you would wind up with:


Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim strBody As String
Dim rst As DAO.Recordset

Set rst = CurrentDb.OpenRecordset("[AllEmpTimeToDate]")

If rst.RecordCount = 0 Then
MsgBox "No promo email messages to send.", vbInformation
Else
rst.MoveFirst
Do Until rs.EOF
strTo = rst!cEmailAddress
intMessageID = Year(Now) & Month(Now) & Day(Now) & Fix(Timer) &
"_MabryMail"
' Send the email using some technique or other
With rst
.Edit
.Fields("cpeDateTimeEmailed") = Now()
.Update
.MoveNext
End With
Loop

End If
rst.Close
Set rst = Nothing

MsgBox "Done sending Promo email. ", vbInformation, "Done"

Exit Sub

Some_Err:
'MousePointer = 0
MsgBox "Error (" & CStr(Err.Number) & ") " & Err.Description, _
vbExclamation, "Error!"
End Sub



hth!

--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that don''t work."
-Thomas Edison (1847-1931)



:

I am working on a project (again). I have a multi page report that has
employee information on separate pages. I want to email the individual
report to employee. I have been given help before, but I always get in way
over my head. I really could use some more help. This is the code I have
copied/tweeked so far. The problem is right now I can't get passed "Set rst
= CurrentDb.OpenRecordset("All Emp Time To Date")" I step thru the code and
soon as I hit that line it goes to the error message. I haven't worked too
much on the rest of the code yet. Any help is greatly, greatly appreciated.
I have this code in a new module. THanks in advance.


Option Compare Database

Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim strBody As String, lngCount As Long, lngRSCount As Long
Dim db As Database
Dim rst As Recordset

Set rst = CurrentDb.OpenRecordset("All Emp Time To Date")

lngRSCount = rs.RecordCount
If lngRSCount = 0 Then
MsgBox "No promo email messages to send.", vbInformation
Else
rs.MoveLast
rs.MoveFirst
Do Until rs.EOF
lngCount = lngCount + 1
strTo = rs!cEmailAddress
intMessageID = Year(Now) & Month(Now) & Day(Now) & Fix(Timer) &
"_MabryMail"
' Send the email using some technique or other
rs.Edit
rs("cpeDateTimeEmailed") = Now()
rs.Update
rs.MoveNext
Loop

End If
rs.Close
MyDB.Close
Set rs = Nothing
Set MyDB = Nothing
Close


MsgBox "Done sending Promo email. ", vbInformation, "Done"

Exit Sub

Some_Err:
'MousePointer = 0
MsgBox "Error (" & CStr(Err.Number) & ") " & Err.Description, _
vbExclamation, "Error!"


End Sub
 
G

GeoffG

Sue,

Personally, I'd replace:

If rst.RecordCount = 0 Then

with:

If rst.BOF And rst.EOF then

If the BOF (beginning of file) and EOF (end of file)
properties are both true, the DAO recordset is empty. This
is the standard way of testing whether a DAO recordset
contains records. Your method uses the RecordCount
property, which may not be accurate unless you first use the
MoveLast, MoveFirst methods. I seem to recall the initial
accuracy of the RecordCount property depends on the type of
recordset you open; whereas, the BOF/EOF test always
provides the right answer.


Your following code line opens a report using an EmployeeID
criterion:

DoCmd.OpenReport "All Emp Time", acViewPreview, ,
"[EmployeeID] = strempid"

In contrast, your following code line sends the report
without using an EmployeeID criterion (which explains why it
contains all records):

DoCmd.SendObject acSendReport, "All Emp Time", acFormatSNP,
strTo, , , "Monthly Time", "Attached is your monthly time"

Do you need to open the report and send it?
Why not just send it?
I've not checked if the SendObject method allows you to
specify a criterion.
Check it out in help.

Regards,
Geoff





message
Thanks for all the help. I am trying really hard to learn
how to code, but
still need a ton of help. I have changed alot of he code
using suggestions
from here. I've come a long way, but I still can't get
the results I want.
The problem I have now is the report will attach to the
email, but it will
either be blank or wil include everyone. Any help is
greatly appreciated.

Option Explicit
Option Compare Database

Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim rst As DAO.Recordset
Dim strempid As Long
Dim strTo As String

Set rst = CurrentDb.OpenRecordset("All
EmpTimeToDate_Crosstab")

If rst.RecordCount = 0 Then
MsgBox "No Reports to email.", vbInformation
Else
rst.MoveFirst
Do Until rst.EOF
strempid = rst!EmployeeID
strTo = rst!EmailAddress

DoCmd.OpenReport "All Emp Time", acViewPreview, ,
"[EmployeeID] =
strempid"

DoCmd.SendObject acSendReport, "All Emp Time",
acFormatSNP, strTo, ,
, "Monthly Time", "Attached is your monthly time"

rst.MoveNext

Loop

End If
rst.Close
Set rst = Nothing

MsgBox "Done sending Employee Time email. ",
vbInformation, "Done"

Exit Sub

Some_Err:
MsgBox "Error (" & CStr(Err.Number) & ") " &
Err.Description, _
vbExclamation, "Error!"

End Sub





Jack Leach said:
oops... sorry that last one was supposed to be inside the
quote

--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that
don''t work."
-Thomas Edison (1847-1931)



Dorian said:
You got the brackets in the wrong place...

Enclose your query name in brackets (or even better
don't use spaces in your
naming scheme)

Set rst = CurrentDb.OpenRecordset("[All Emp Time To
Date"])
should be
Set rst = CurrentDb.OpenRecordset("[All Emp Time To
Date]")

--
"Give someone a fish and they eat for a day; teach
someone to fish and they
eat for a lifetime".


:

Dim rst As Recordset

dim this line as a DAO.Recrdset:

Dim rst As DAO.Recordset



Set rst = CurrentDb.OpenRecordset("All Emp Time
To Date")

Enclose your query name in brackets (or even better
don't use spaces in your
naming scheme)

Set rst = CurrentDb.OpenRecordset("[All Emp Time To
Date"])



and...

Dim db As Database

you have db dimmed as a database, but never use it
(you are using CurrentDb
as the database object instead). Get rid of that
line.


and...

MyDB.Close
Set rs = Nothing
Set MyDB = Nothing

Here you are close MyDB (which appears to be a
database object variable,
though it is not dimensioned). You probably don't
want to close your db, so
get rid of the MyDB.Close line. And, being that MyDB
is not dimmed, you
don't need to set it to nothing, so you can get rid
of the Set MyDB = Nothing
line (remember, you are using CurrentDb as the
database object to open the
recordset, and therefore don't need a variable to
hold it)



Close

This statement is used to close an open file (ex:
Close #FileNum). I see no
reason for this to be here, so I guess you can get
rid of that as well.



The variable lngRSCount you are using to check the
count of the recordset,
but it is not necessary, you can check the count
directly from the property.
And, lngCount you are making a count of the records
you are looping, but
aren't doing anything with it after, so you can get
rid of that. All in all,
to clean up your code a litte, here's what you would
wind up with:


Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim strBody As String
Dim rst As DAO.Recordset

Set rst =
CurrentDb.OpenRecordset("[AllEmpTimeToDate]")

If rst.RecordCount = 0 Then
MsgBox "No promo email messages to send.",
vbInformation
Else
rst.MoveFirst
Do Until rs.EOF
strTo = rst!cEmailAddress
intMessageID = Year(Now) & Month(Now) &
Day(Now) & Fix(Timer) &
"_MabryMail"
' Send the email using some technique or
other
With rst
.Edit
.Fields("cpeDateTimeEmailed") = Now()
.Update
.MoveNext
End With
Loop

End If
rst.Close
Set rst = Nothing

MsgBox "Done sending Promo email. ",
vbInformation, "Done"

Exit Sub

Some_Err:
'MousePointer = 0
MsgBox "Error (" & CStr(Err.Number) & ") " &
Err.Description, _
vbExclamation, "Error!"
End Sub



hth!

--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways
that don''t work."
-Thomas Edison (1847-1931)



:

I am working on a project (again). I have a multi
page report that has
employee information on separate pages. I want to
email the individual
report to employee. I have been given help before,
but I always get in way
over my head. I really could use some more help.
This is the code I have
copied/tweeked so far. The problem is right now I
can't get passed "Set rst
= CurrentDb.OpenRecordset("All Emp Time To Date")"
I step thru the code and
soon as I hit that line it goes to the error
message. I haven't worked too
much on the rest of the code yet. Any help is
greatly, greatly appreciated.
I have this code in a new module. THanks in
advance.


Option Compare Database

Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim strBody As String, lngCount As Long,
lngRSCount As Long
Dim db As Database
Dim rst As Recordset

Set rst = CurrentDb.OpenRecordset("All Emp Time
To Date")

lngRSCount = rs.RecordCount
If lngRSCount = 0 Then
MsgBox "No promo email messages to send.",
vbInformation
Else
rs.MoveLast
rs.MoveFirst
Do Until rs.EOF
lngCount = lngCount + 1
strTo = rs!cEmailAddress
intMessageID = Year(Now) & Month(Now) &
Day(Now) & Fix(Timer) &
"_MabryMail"
' Send the email using some technique or
other
rs.Edit
rs("cpeDateTimeEmailed") = Now()
rs.Update
rs.MoveNext
Loop

End If
rs.Close
MyDB.Close
Set rs = Nothing
Set MyDB = Nothing
Close


MsgBox "Done sending Promo email. ",
vbInformation, "Done"

Exit Sub

Some_Err:
'MousePointer = 0
MsgBox "Error (" & CStr(Err.Number) & ") " &
Err.Description, _
vbExclamation, "Error!"


End Sub
 
M

Marshall Barton

sue said:
Thanks for all the help. I am trying really hard to learn how to code, but
still need a ton of help. I have changed alot of he code using suggestions
from here. I've come a long way, but I still can't get the results I want.
The problem I have now is the report will attach to the email, but it will
either be blank or wil include everyone. Any help is greatly appreciated.

Option Explicit
Option Compare Database

Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim rst As DAO.Recordset
Dim strempid As Long
Dim strTo As String

Set rst = CurrentDb.OpenRecordset("All EmpTimeToDate_Crosstab")

If rst.RecordCount = 0 Then
MsgBox "No Reports to email.", vbInformation
Else
rst.MoveFirst
Do Until rst.EOF
strempid = rst!EmployeeID
strTo = rst!EmailAddress

DoCmd.OpenReport "All Emp Time", acViewPreview, , "[EmployeeID] =
strempid"

DoCmd.SendObject acSendReport, "All Emp Time", acFormatSNP, strTo, ,
, "Monthly Time", "Attached is your monthly time"

rst.MoveNext

Loop

End If
rst.Close
Set rst = Nothing

MsgBox "Done sending Employee Time email. ", vbInformation, "Done"

Exit Sub

Some_Err:
MsgBox "Error (" & CStr(Err.Number) & ") " & Err.Description, _
vbExclamation, "Error!"

End Sub


First, you do not need to use the MoveLast and MoveFirst,
because a freshly opened record set will always be
positioned at the first record. The record count will
either be a 0 if there are no records or >0 if there is one
or more records.

I think you should test the query separately to make sure it
works before getting involved in all the code. Once the
query runs successfully, then it should open in your code,

BUT your whole idea may not be valid even after you fix the
OpenReport line to be:
DoCmd.OpenReport "All Emp Time", acViewPreview, ,
"EmployeeID = " & strempid

The problem is that the report and your VBA code run
asynchronously with the VBA code having a higher priority.
That means that your code goes around the loop and tries to
run the next report before the current report has been
processed. A second attempt to open an already open report
will produce unpredictable results so you must code the loop
to wait for one report to finish before trying to open the
next one.

I have no experience using SendObject, but, if SendObject is
synchronous (i.e. completes its job before returning to your
code), then you would not need to use some yucky code to
wait, but you definitely would need to close the report
after the SendObject line.

Before doing it that way, I think(?) I would first try
moving the OpenReport outside the loop and just set the
report's Filter property inside the loop. This would
restart the report with the new filter but avoid closing and
re-opening the report.

DoCmd.OpenReport "All Emp Time", acViewPreview
Set rst = CurrentDb.OpenRecordset("All
EmpTimeToDate_Crosstab")

If rst.RecordCount = 0 Then
MsgBox "No Reports to email.", vbInformation
Else
Do Until rst.EOF
strempid = rst!EmployeeID
strTo = rst!EmailAddress

Reports("All Emp Time").Filter = "[mployeeID=" &
strempid
Reports("All Emp Time").FilterOn = True
DoCmd.SendObject ......

rst.MoveNext
Loop
DoCmd.Close acReport, "All Emp Time", acSaveNo
End If

All this is pretty advanced stuff dealling with some subtle
and complex issues, but I believe it is necessitated by your
need to send the same report multiple times with different
data.
 
G

GeoffG

Hi Marsh/Sue,

Nice to know that RecordCount = 0 is reliable.

I thought that, if Sue is using a Crosstab query, it might
not produce usable records and would be worth checking.

Apologies for not knowing that SendObject does not permit a
criterion argument.

I ran some tests, with two interesting results.

1. SendObject appears not to work as stated in help.

In Access Help, the "SendObject Action" topic states that,
if the "Edit Message" argument is set to Yes, you can edit
the email; whereas, if the argument is set to No, the email
is sent automatically. Help says the default is No. As Sue
does not use this argument, the default of No should apply,
thereby sending the email immediately. However, I found
that, by not using the "Edit Message" argument, Microsoft
Outlook pauses, allowing the user to edit the email. This
seems to imply that the default for this argument is Yes.
Also, I found that if the "Edit Message" argument is set to
No (so the message is sent immediately), Microsoft Outlook
security intervenes with a warning to the effect that a
program is attempting to send a message. As a result,
security enforces a 15 second pause, which might be
inconvenient; it might be better to allow editing and click
the Send button.

2. Marsh, your method of using a filter appears not to work
for the reasons you cite. I found that there appears to be
insufficient time for Access to apply the filter before
SendObject sends the report. As a result, when your method
is run at full speed, all emails have an attached report
that contains all records, not just the filtered record.
The good news is that it appears that SendObject finishes
its work before returning control to VBA. Therefore, it is
possible (as you suggested) to enhance Sue's method by
closing the report at the end of the loop to produce a
workable solution.

Here are the two tests I ran:


Private Sub Email_RPT_to_All_Emp_Click_1()

' Marsh's filter method.
'
' This method works when the code is
' stepped through, but does not work
' at full speed.

Const strcReportName As String = _
"All Emp Time"

Dim rst As DAO.Recordset
Dim lngEmpID As Long
Dim strTo As String
Dim objRPT As Access.Report

On Error GoTo Error_Email_RPT_to_All_Emp_Click_1

DoCmd.OpenReport strcReportName, acViewPreview

Set rst = CurrentDb.OpenRecordset( _
"All EmpTimeToDate_Crosstab")

If rst.RecordCount = 0 Then
MsgBox "No Reports to email.", vbInformation
Else
Do Until rst.EOF
lngEmpID = rst!EmployeeID
strTo = rst!EmailAddress
Reports(strcReportName).Filter = _
"EmployeeID=" & lngEmpID
Reports(strcReportName).FilterOn = True
DoCmd.SendObject acSendReport, strcReportName, _
acFormatSNP, strTo, , , "Monthly Time", _
"Attached is your monthly time"
rst.MoveNext
Loop
End If

MsgBox "Done sending Employee Time email. ", _
vbInformation, "Done"

Exit_Email_RPT_to_All_Emp_Click_1:

For Each objRPT In Access.Reports
If objRPT.Name = strcReportName Then
DoCmd.Close acReport, strcReportName, _
acSaveNo
Exit For
End If
Next

If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
Exit Sub

Error_Email_RPT_to_All_Emp_Click_1:

Select Case Err.Number
Case 2501
MsgBox "User cancelled sending email " _
& "for EmployeeID = " & lngEmpID
Resume Next
Case Else
MsgBox "Error (" & CStr(Err.Number) & ") " _
& Err.Description, vbExclamation, "Error!"
Resume Exit_Email_RPT_to_All_Emp_Click_1
End Select

End Sub



Private Sub Email_RPT_to_All_Emp_Click_2()

' Sue's method, enhanced with Close Report
' at end of loop.
' This method works a full speed.

Const strcReportName As String = _
"All Emp Time"

Dim rst As DAO.Recordset
Dim lngEmpID As Long
Dim strTo As String
Dim objRPT As Access.Report

On Error GoTo Error_Email_RPT_to_All_Emp_Click_2

Set rst = CurrentDb.OpenRecordset( _
"All EmpTimeToDate_Crosstab")

If rst.RecordCount = 0 Then
MsgBox "No Reports to email.", vbInformation
Else
Do Until rst.EOF
lngEmpID = rst!EmployeeID
strTo = rst!EmailAddress
DoCmd.OpenReport strcReportName, acViewPreview, _
, "[EmployeeID] = " & lngEmpID
DoCmd.SendObject acSendReport, strcReportName, _
acFormatSNP, strTo, , , "Monthly Time", _
"Attached is your monthly time"
DoCmd.Close acReport, strcReportName, acSaveNo
rst.MoveNext
Loop
End If

MsgBox "Done sending Employee Time email. ", _
vbInformation, "Done"

Exit_Email_RPT_to_All_Emp_Click_2:

For Each objRPT In Access.Reports
If objRPT.Name = strcReportName Then
DoCmd.Close acReport, strcReportName, _
acSaveNo
Exit For
End If
Next

If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
Exit Sub

Error_Email_RPT_to_All_Emp_Click_2:

Select Case Err.Number
Case 2501
MsgBox "User cancelled sending email " _
& "for EmployeeID = " & lngEmpID
Resume
Case Else
MsgBox "Error (" & CStr(Err.Number) & ") " _
& Err.Description, vbExclamation, "Error!"
Resume Exit_Email_RPT_to_All_Emp_Click_2
End Select

End Sub


Regards
Geoff.








Marshall Barton said:
sue said:
Thanks for all the help. I am trying really hard to learn
how to code, but
still need a ton of help. I have changed alot of he code
using suggestions
from here. I've come a long way, but I still can't get
the results I want.
The problem I have now is the report will attach to the
email, but it will
either be blank or wil include everyone. Any help is
greatly appreciated.

Option Explicit
Option Compare Database

Private Sub Email_RPT_to_All_Emp_Click()
On Error GoTo Some_Err

Dim rst As DAO.Recordset
Dim strempid As Long
Dim strTo As String

Set rst = CurrentDb.OpenRecordset("All
EmpTimeToDate_Crosstab")

If rst.RecordCount = 0 Then
MsgBox "No Reports to email.", vbInformation
Else
rst.MoveFirst
Do Until rst.EOF
strempid = rst!EmployeeID
strTo = rst!EmailAddress

DoCmd.OpenReport "All Emp Time", acViewPreview, ,
"[EmployeeID] =
strempid"

DoCmd.SendObject acSendReport, "All Emp Time",
acFormatSNP, strTo, ,
, "Monthly Time", "Attached is your monthly time"

rst.MoveNext

Loop

End If
rst.Close
Set rst = Nothing

MsgBox "Done sending Employee Time email. ",
vbInformation, "Done"

Exit Sub

Some_Err:
MsgBox "Error (" & CStr(Err.Number) & ") " &
Err.Description, _
vbExclamation, "Error!"

End Sub


First, you do not need to use the MoveLast and MoveFirst,
because a freshly opened record set will always be
positioned at the first record. The record count will
either be a 0 if there are no records or >0 if there is
one
or more records.

I think you should test the query separately to make sure
it
works before getting involved in all the code. Once the
query runs successfully, then it should open in your code,

BUT your whole idea may not be valid even after you fix
the
OpenReport line to be:
DoCmd.OpenReport "All Emp Time", acViewPreview, ,
"EmployeeID = " & strempid

The problem is that the report and your VBA code run
asynchronously with the VBA code having a higher priority.
That means that your code goes around the loop and tries
to
run the next report before the current report has been
processed. A second attempt to open an already open
report
will produce unpredictable results so you must code the
loop
to wait for one report to finish before trying to open the
next one.

I have no experience using SendObject, but, if SendObject
is
synchronous (i.e. completes its job before returning to
your
code), then you would not need to use some yucky code to
wait, but you definitely would need to close the report
after the SendObject line.

Before doing it that way, I think(?) I would first try
moving the OpenReport outside the loop and just set the
report's Filter property inside the loop. This would
restart the report with the new filter but avoid closing
and
re-opening the report.

DoCmd.OpenReport "All Emp Time", acViewPreview
Set rst = CurrentDb.OpenRecordset("All
EmpTimeToDate_Crosstab")

If rst.RecordCount = 0 Then
MsgBox "No Reports to email.", vbInformation
Else
Do Until rst.EOF
strempid = rst!EmployeeID
strTo = rst!EmailAddress

Reports("All Emp Time").Filter = "[mployeeID=" &
strempid
Reports("All Emp Time").FilterOn = True
DoCmd.SendObject ......

rst.MoveNext
Loop
DoCmd.Close acReport, "All Emp Time", acSaveNo
End If

All this is pretty advanced stuff dealling with some
subtle
and complex issues, but I believe it is necessitated by
your
need to send the same report multiple times with different
data.
 
M

Marshall Barton

GeoffG said:
Nice to know that RecordCount = 0 is reliable.

I thought that, if Sue is using a Crosstab query, it might
not produce usable records and would be worth checking.

Apologies for not knowing that SendObject does not permit a
criterion argument.

I ran some tests, with two interesting results.

1. SendObject appears not to work as stated in help.

In Access Help, the "SendObject Action" topic states that,
if the "Edit Message" argument is set to Yes, you can edit
the email; whereas, if the argument is set to No, the email
is sent automatically. Help says the default is No. As Sue
does not use this argument, the default of No should apply,
thereby sending the email immediately. However, I found
that, by not using the "Edit Message" argument, Microsoft
Outlook pauses, allowing the user to edit the email. This
seems to imply that the default for this argument is Yes.
Also, I found that if the "Edit Message" argument is set to
No (so the message is sent immediately), Microsoft Outlook
security intervenes with a warning to the effect that a
program is attempting to send a message. As a result,
security enforces a 15 second pause, which might be
inconvenient; it might be better to allow editing and click
the Send button.

2. Marsh, your method of using a filter appears not to work
for the reasons you cite. I found that there appears to be
insufficient time for Access to apply the filter before
SendObject sends the report. As a result, when your method
is run at full speed, all emails have an attached report
that contains all records, not just the filtered record.
The good news is that it appears that SendObject finishes
its work before returning control to VBA. Therefore, it is
possible (as you suggested) to enhance Sue's method by
closing the report at the end of the loop to produce a
workable solution.

Here are the two tests I ran:


Private Sub Email_RPT_to_All_Emp_Click_1()

' Marsh's filter method.
'
' This method works when the code is
' stepped through, but does not work
' at full speed.

Const strcReportName As String = _
"All Emp Time"

Dim rst As DAO.Recordset
Dim lngEmpID As Long
Dim strTo As String
Dim objRPT As Access.Report

On Error GoTo Error_Email_RPT_to_All_Emp_Click_1

DoCmd.OpenReport strcReportName, acViewPreview

Set rst = CurrentDb.OpenRecordset( _
"All EmpTimeToDate_Crosstab")

If rst.RecordCount = 0 Then
MsgBox "No Reports to email.", vbInformation
Else
Do Until rst.EOF
lngEmpID = rst!EmployeeID
strTo = rst!EmailAddress
Reports(strcReportName).Filter = _
"EmployeeID=" & lngEmpID
Reports(strcReportName).FilterOn = True
DoCmd.SendObject acSendReport, strcReportName, _
acFormatSNP, strTo, , , "Monthly Time", _
"Attached is your monthly time"
rst.MoveNext
Loop
End If

MsgBox "Done sending Employee Time email. ", _
vbInformation, "Done"

Exit_Email_RPT_to_All_Emp_Click_1:

For Each objRPT In Access.Reports
If objRPT.Name = strcReportName Then
DoCmd.Close acReport, strcReportName, _
acSaveNo
Exit For
End If
Next

If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
Exit Sub

Error_Email_RPT_to_All_Emp_Click_1:

Select Case Err.Number
Case 2501
MsgBox "User cancelled sending email " _
& "for EmployeeID = " & lngEmpID
Resume Next
Case Else
MsgBox "Error (" & CStr(Err.Number) & ") " _
& Err.Description, vbExclamation, "Error!"
Resume Exit_Email_RPT_to_All_Emp_Click_1
End Select

End Sub



Private Sub Email_RPT_to_All_Emp_Click_2()

' Sue's method, enhanced with Close Report
' at end of loop.
' This method works a full speed.

Const strcReportName As String = _
"All Emp Time"

Dim rst As DAO.Recordset
Dim lngEmpID As Long
Dim strTo As String
Dim objRPT As Access.Report

On Error GoTo Error_Email_RPT_to_All_Emp_Click_2

Set rst = CurrentDb.OpenRecordset( _
"All EmpTimeToDate_Crosstab")

If rst.RecordCount = 0 Then
MsgBox "No Reports to email.", vbInformation
Else
Do Until rst.EOF
lngEmpID = rst!EmployeeID
strTo = rst!EmailAddress
DoCmd.OpenReport strcReportName, acViewPreview, _
, "[EmployeeID] = " & lngEmpID
DoCmd.SendObject acSendReport, strcReportName, _
acFormatSNP, strTo, , , "Monthly Time", _
"Attached is your monthly time"
DoCmd.Close acReport, strcReportName, acSaveNo
rst.MoveNext
Loop
End If

MsgBox "Done sending Employee Time email. ", _
vbInformation, "Done"

Exit_Email_RPT_to_All_Emp_Click_2:

For Each objRPT In Access.Reports
If objRPT.Name = strcReportName Then
DoCmd.Close acReport, strcReportName, _
acSaveNo
Exit For
End If
Next

If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
Exit Sub

Error_Email_RPT_to_All_Emp_Click_2:

Select Case Err.Number
Case 2501
MsgBox "User cancelled sending email " _
& "for EmployeeID = " & lngEmpID
Resume
Case Else
MsgBox "Error (" & CStr(Err.Number) & ") " _
& Err.Description, vbExclamation, "Error!"
Resume Exit_Email_RPT_to_All_Emp_Click_2
End Select

End Sub


Nice analysis and the results are good to know. I guess it
makes sense that something should prevent sending a
gazillion emails per second.

Your button 2 code looks good although I think I would not
loop throught the Reports collection in the exit sequence.
Probably not important, but my inclination would be to use:

If CurrentProject.AllReports(strcReportName).IsLoaded Then
DoCmd.Close acReport, strcReportName, acSaveNo
End If
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top