variables and parameters

S

SillySally

Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , , acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is FindGroup. I'm
trying to find the group of people to send an email to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for the group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"
 
R

Rob Oldfield

You're close. What do you mean by the parameter field on GroupParamEmail...
a parameter you have to enter when the form opens? I don't quite get how
you're choosing to specify the people you want to mail... could you go into
a bit more detail please.
 
S

SillySally

Thanks for taking an interest in my question- it's driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box field,
FindGroup, that allows an end-user to choose a group. I
use a similar form to run mailing labels. For example,
the end-user selects "Board of Directors" and the report
creates mail labels for all People who are in the "Board
of Directors" group.

So what I'm hoping to do with the email list is loop
through all People with email addresses that also belong
to the user specified group. Hope that explanation
helps. I had found an article from ATTAC Consulting Group
titled "How to create your won input box forms and pause
code for user input" which seems exactly what I need.
It's long but I'll paste it in (see after ***) -skip it if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get information or a
selection from a user that an a standard Input Box isn't
designed to handle.
As an example, you may want to offer the user only a
selection of one of two choices. Since there's no way to
restrict what the user can enter into an input box, an
input box won't work well.

To get around this limitation you can design a form that
acts as psudo input box, opening the form to get input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which the
running function is in, and for which you need to get the
input from the user, dimension new variables which will to
hold the return values which the user selects or enters
into your input form.The value of these variables will
be "visible" to your running function after the user
enters their selections. There's no need to make these
variables global variables.

Add a new sub procedure to the same module as your running
function. Your custom input box form will call this sub
procedure. The purpose of this sub procedure is solely to
accept the values from your input form as parameters and
to set the new module level variables equal to the value
of the parameters.

Design your own "input box" form as a dialog box form.
When a dialog box is opened, it will cause your running
code to "pause" until the dialog is closed. (You have to
specifically specify opening it in your running function
as "acDialog".)

In the OnClose event of your input box form, now add a
call to the sub procedure you just wrote. Specifying as
parameter values, the values of the text boxes or option
groups etc. from your form. This will send the data back
to your module when the dialog is closed.

You can also make your main code pause and wait for the
user's input and for non-dialog style forms by using code
like the following in you main procedure ( an " _ " means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub procedure to
notify your running function if the user clicked a cancel
button rather than an OK button to end your process.


-----Original Message-----
You're close. What do you mean by the parameter field on GroupParamEmail...
a parameter you have to enter when the form opens? I don't quite get how
you're choosing to specify the people you want to mail... could you go into
a bit more detail please.


Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , , acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is FindGroup. I'm
trying to find the group of people to send an email to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for the group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"


.
 
R

Rob Oldfield

I still don't get exactly what process you're trying to use. Is this right?

You click a button on a form which pops up the GroupParamEmail form... on
that you choose the group you want to mail (in a combo that is also called
GroupParamEmail?)... and then, when you hit OK, you want the mail to be
sent?

If I have that wrong, then please let me know what it is that you want to
happen in terms of picking options from forms etc (feel free to be
demanding, it can all be done)

Last thing... I don't see where you are using the choice you make from the
combo to specify the people you want to mail... is 'People' a query that
includes a criteria reference to that control? If not... then how does that
work? How does 'Board of Directors' produce a list of addresses? (i.e.
what's the table structure that includes those addresses?)


SillySally said:
Thanks for taking an interest in my question- it's driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box field,
FindGroup, that allows an end-user to choose a group. I
use a similar form to run mailing labels. For example,
the end-user selects "Board of Directors" and the report
creates mail labels for all People who are in the "Board
of Directors" group.

So what I'm hoping to do with the email list is loop
through all People with email addresses that also belong
to the user specified group. Hope that explanation
helps. I had found an article from ATTAC Consulting Group
titled "How to create your won input box forms and pause
code for user input" which seems exactly what I need.
It's long but I'll paste it in (see after ***) -skip it if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get information or a
selection from a user that an a standard Input Box isn't
designed to handle.
As an example, you may want to offer the user only a
selection of one of two choices. Since there's no way to
restrict what the user can enter into an input box, an
input box won't work well.

To get around this limitation you can design a form that
acts as psudo input box, opening the form to get input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which the
running function is in, and for which you need to get the
input from the user, dimension new variables which will to
hold the return values which the user selects or enters
into your input form.The value of these variables will
be "visible" to your running function after the user
enters their selections. There's no need to make these
variables global variables.

Add a new sub procedure to the same module as your running
function. Your custom input box form will call this sub
procedure. The purpose of this sub procedure is solely to
accept the values from your input form as parameters and
to set the new module level variables equal to the value
of the parameters.

Design your own "input box" form as a dialog box form.
When a dialog box is opened, it will cause your running
code to "pause" until the dialog is closed. (You have to
specifically specify opening it in your running function
as "acDialog".)

In the OnClose event of your input box form, now add a
call to the sub procedure you just wrote. Specifying as
parameter values, the values of the text boxes or option
groups etc. from your form. This will send the data back
to your module when the dialog is closed.

You can also make your main code pause and wait for the
user's input and for non-dialog style forms by using code
like the following in you main procedure ( an " _ " means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub procedure to
notify your running function if the user clicked a cancel
button rather than an OK button to end your process.


-----Original Message-----
You're close. What do you mean by the parameter field on GroupParamEmail...
a parameter you have to enter when the form opens? I don't quite get how
you're choosing to specify the people you want to mail... could you go into
a bit more detail please.


Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , , acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is FindGroup. I'm
trying to find the group of people to send an email to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for the group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"


.
 
S

SillySally

Demanding I can be ;-)
So, I suppose what you're saying is "code doesn't just
happen". Rats!
I do appreciate your efforts to help me get this working.
It's the "biggie" that will get my non-profit off their
old system (Address Book- yikes!) and on to Access. They
love their "groups" to segment the population.

Here's the process: I have a form (LabelsAndLists) that
has a command button (EmailGroup) that kicks off the
emailing code. The code calls form GroupParamEmail that
has an unbound combo box called FindGroup. Here's the sql
for FindGroup: SELECT Groups.GroupID, Groups.GroupName
FROM Groups
WHERE (((Groups.GroupEnd) Is Null));

Then magic happens! Somehow the code knows which Group the
user wants to email and which Contacts are in that Group
and sends the email to them. I do see the problem. It's
where "magic happens".

Here's the table structure
Contacts (my "main table", contains ContactID, EmailName)
Groups (contains GroupID, GroupName, GroupStart, GroupEnd)
GroupMember (contains GroupMember, ContactID, GroupID,
GMemberStart, GMemberEnd)

I created qryGroups:
SELECT Contacts.ContactID, Contacts.EmailName,
Groups.GroupName
FROM Groups INNER JOIN (Contacts INNER JOIN GroupMembers
ON Contacts.ContactID = GroupMembers.ContactID) ON
Groups.GroupID = GroupMembers.GroupID
WHERE (((GroupMembers.GMemberEnd) Is Null) AND
((Groups.GroupEnd) Is Null) AND ((Contacts.EmailName) Is
Not Null));
This gives me all Contacts in a Group (where both the
group itself and the Contact's involement in the Group
are "active") that have an Email address.

Now here's the pitiful attempt. I thought maybe I could
use (see below) strWhere and strGroup. But I still don't
know what Set rst = CurrentDb.OpenRecordset (X) would be.
Or how the user input from FindGroup interacts with
qryGroups- perhaps I would need FindGroup to equal
GroupName in strGroup. Here's the rest of the code:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String

strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)

Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM Contacts WHERE [EmailName] Is Not Null AND something
about group members...")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Group
Email Link"
End Sub
-----Original Message-----
I still don't get exactly what process you're trying to use. Is this right?

You click a button on a form which pops up the GroupParamEmail form... on
that you choose the group you want to mail (in a combo that is also called
GroupParamEmail?)... and then, when you hit OK, you want the mail to be
sent?

If I have that wrong, then please let me know what it is that you want to
happen in terms of picking options from forms etc (feel free to be
demanding, it can all be done)

Last thing... I don't see where you are using the choice you make from the
combo to specify the people you want to mail... is 'People' a query that
includes a criteria reference to that control? If not... then how does that
work? How does 'Board of Directors' produce a list of addresses? (i.e.
what's the table structure that includes those addresses?)


Thanks for taking an interest in my question- it's driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box field,
FindGroup, that allows an end-user to choose a group. I
use a similar form to run mailing labels. For example,
the end-user selects "Board of Directors" and the report
creates mail labels for all People who are in the "Board
of Directors" group.

So what I'm hoping to do with the email list is loop
through all People with email addresses that also belong
to the user specified group. Hope that explanation
helps. I had found an article from ATTAC Consulting Group
titled "How to create your won input box forms and pause
code for user input" which seems exactly what I need.
It's long but I'll paste it in (see after ***) -skip it if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get information or a
selection from a user that an a standard Input Box isn't
designed to handle.
As an example, you may want to offer the user only a
selection of one of two choices. Since there's no way to
restrict what the user can enter into an input box, an
input box won't work well.

To get around this limitation you can design a form that
acts as psudo input box, opening the form to get input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which the
running function is in, and for which you need to get the
input from the user, dimension new variables which will to
hold the return values which the user selects or enters
into your input form.The value of these variables will
be "visible" to your running function after the user
enters their selections. There's no need to make these
variables global variables.

Add a new sub procedure to the same module as your running
function. Your custom input box form will call this sub
procedure. The purpose of this sub procedure is solely to
accept the values from your input form as parameters and
to set the new module level variables equal to the value
of the parameters.

Design your own "input box" form as a dialog box form.
When a dialog box is opened, it will cause your running
code to "pause" until the dialog is closed. (You have to
specifically specify opening it in your running function
as "acDialog".)

In the OnClose event of your input box form, now add a
call to the sub procedure you just wrote. Specifying as
parameter values, the values of the text boxes or option
groups etc. from your form. This will send the data back
to your module when the dialog is closed.

You can also make your main code pause and wait for the
user's input and for non-dialog style forms by using code
like the following in you main procedure ( an " _ " means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub procedure to
notify your running function if the user clicked a cancel
button rather than an OK button to end your process.


-----Original Message-----
You're close. What do you mean by the parameter field
on
GroupParamEmail...
a parameter you have to enter when the form opens? I don't quite get how
you're choosing to specify the people you want to
mail...
could you go into
a bit more detail please.


"SillySally" <[email protected]> wrote
in
message
Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , , acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is FindGroup. I'm
trying to find the group of people to send an email to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for the group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"


.


.
 
R

Rob Oldfield

OK. That looks good. It's certainly correct to have a many-to-many
relationship from Contacts to Groups (although... what's going into the
GroupMember, GMemberStart and GMemberEnd fields in GroupMember? Could you
just give me some sample data from that table. Did you set the tables up by
the way?)


SillySally said:
Demanding I can be ;-)
So, I suppose what you're saying is "code doesn't just
happen". Rats!
I do appreciate your efforts to help me get this working.
It's the "biggie" that will get my non-profit off their
old system (Address Book- yikes!) and on to Access. They
love their "groups" to segment the population.

Here's the process: I have a form (LabelsAndLists) that
has a command button (EmailGroup) that kicks off the
emailing code. The code calls form GroupParamEmail that
has an unbound combo box called FindGroup. Here's the sql
for FindGroup: SELECT Groups.GroupID, Groups.GroupName
FROM Groups
WHERE (((Groups.GroupEnd) Is Null));

Then magic happens! Somehow the code knows which Group the
user wants to email and which Contacts are in that Group
and sends the email to them. I do see the problem. It's
where "magic happens".

Here's the table structure
Contacts (my "main table", contains ContactID, EmailName)
Groups (contains GroupID, GroupName, GroupStart, GroupEnd)
GroupMember (contains GroupMember, ContactID, GroupID,
GMemberStart, GMemberEnd)

I created qryGroups:
SELECT Contacts.ContactID, Contacts.EmailName,
Groups.GroupName
FROM Groups INNER JOIN (Contacts INNER JOIN GroupMembers
ON Contacts.ContactID = GroupMembers.ContactID) ON
Groups.GroupID = GroupMembers.GroupID
WHERE (((GroupMembers.GMemberEnd) Is Null) AND
((Groups.GroupEnd) Is Null) AND ((Contacts.EmailName) Is
Not Null));
This gives me all Contacts in a Group (where both the
group itself and the Contact's involement in the Group
are "active") that have an Email address.

Now here's the pitiful attempt. I thought maybe I could
use (see below) strWhere and strGroup. But I still don't
know what Set rst = CurrentDb.OpenRecordset (X) would be.
Or how the user input from FindGroup interacts with
qryGroups- perhaps I would need FindGroup to equal
GroupName in strGroup. Here's the rest of the code:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String

strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)

Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM Contacts WHERE [EmailName] Is Not Null AND something
about group members...")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Group
Email Link"
End Sub
-----Original Message-----
I still don't get exactly what process you're trying to use. Is this right?

You click a button on a form which pops up the GroupParamEmail form... on
that you choose the group you want to mail (in a combo that is also called
GroupParamEmail?)... and then, when you hit OK, you want the mail to be
sent?

If I have that wrong, then please let me know what it is that you want to
happen in terms of picking options from forms etc (feel free to be
demanding, it can all be done)

Last thing... I don't see where you are using the choice you make from the
combo to specify the people you want to mail... is 'People' a query that
includes a criteria reference to that control? If not... then how does that
work? How does 'Board of Directors' produce a list of addresses? (i.e.
what's the table structure that includes those addresses?)


Thanks for taking an interest in my question- it's driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box field,
FindGroup, that allows an end-user to choose a group. I
use a similar form to run mailing labels. For example,
the end-user selects "Board of Directors" and the report
creates mail labels for all People who are in the "Board
of Directors" group.

So what I'm hoping to do with the email list is loop
through all People with email addresses that also belong
to the user specified group. Hope that explanation
helps. I had found an article from ATTAC Consulting Group
titled "How to create your won input box forms and pause
code for user input" which seems exactly what I need.
It's long but I'll paste it in (see after ***) -skip it if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get information or a
selection from a user that an a standard Input Box isn't
designed to handle.
As an example, you may want to offer the user only a
selection of one of two choices. Since there's no way to
restrict what the user can enter into an input box, an
input box won't work well.

To get around this limitation you can design a form that
acts as psudo input box, opening the form to get input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which the
running function is in, and for which you need to get the
input from the user, dimension new variables which will to
hold the return values which the user selects or enters
into your input form.The value of these variables will
be "visible" to your running function after the user
enters their selections. There's no need to make these
variables global variables.

Add a new sub procedure to the same module as your running
function. Your custom input box form will call this sub
procedure. The purpose of this sub procedure is solely to
accept the values from your input form as parameters and
to set the new module level variables equal to the value
of the parameters.

Design your own "input box" form as a dialog box form.
When a dialog box is opened, it will cause your running
code to "pause" until the dialog is closed. (You have to
specifically specify opening it in your running function
as "acDialog".)

In the OnClose event of your input box form, now add a
call to the sub procedure you just wrote. Specifying as
parameter values, the values of the text boxes or option
groups etc. from your form. This will send the data back
to your module when the dialog is closed.

You can also make your main code pause and wait for the
user's input and for non-dialog style forms by using code
like the following in you main procedure ( an " _ " means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub procedure to
notify your running function if the user clicked a cancel
button rather than an OK button to end your process.



-----Original Message-----
You're close. What do you mean by the parameter field on
GroupParamEmail...
a parameter you have to enter when the form opens? I
don't quite get how
you're choosing to specify the people you want to mail...
could you go into
a bit more detail please.


message
Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is FindGroup.
I'm
trying to find the group of people to send an email to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for the
group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"


.


.
 
S

SillySally

Hi. I set up GMemberStart and GMemberEnd (both date
fields) to specify the start and end dates in the Group
for the Contact. For example, a Group could have started
01/05/05 but this particular Contact didn't start being
associated with the Group until 02/13/05. A real example:
Board of Directors is an on-going group. Contacts serve 2
years and then stop being on the Board. Rather than
setting up a new Group, we can just set the Contact's
GMemberEnd date and leave Group going. That way when I
want to send email to the Board, I tell the email code
(someday!) not to send email to the Contacts with a value
in GMemberEnd.

GroupMemberID is the key of GroupMember table.
GroupMember is the "intermediary" table between Groups and
Contacts.
Sample data: GroupMemberID, ContactID, GroupID,
GMemberStart and GMemberEnd

9, 95, 5, 01/01/02
10, 95, 6, 05/01/02

This means that ContactID = 95 is a memeber of 2 Groups
(Board of Directors, starting 01/01/02) and (Reading
piolot, starting 05/01/02). That also means that
ContactID = 95 has two GroupMemberIDs.

Did I put this together? Perhaps. The database has evolved
(sort of) over a couple of years and is stuck together
with logic and spit. I do have a database designing
friend that helped in the beginning, but I give away
almost all credit for the good, and take ALL "credit" for
the bad. Thanks, Sal
-----Original Message-----
OK. That looks good. It's certainly correct to have a many-to-many
relationship from Contacts to Groups (although... what's going into the
GroupMember, GMemberStart and GMemberEnd fields in GroupMember? Could you
just give me some sample data from that table. Did you set the tables up by
the way?)


Demanding I can be ;-)
So, I suppose what you're saying is "code doesn't just
happen". Rats!
I do appreciate your efforts to help me get this working.
It's the "biggie" that will get my non-profit off their
old system (Address Book- yikes!) and on to Access. They
love their "groups" to segment the population.

Here's the process: I have a form (LabelsAndLists) that
has a command button (EmailGroup) that kicks off the
emailing code. The code calls form GroupParamEmail that
has an unbound combo box called FindGroup. Here's the sql
for FindGroup: SELECT Groups.GroupID, Groups.GroupName
FROM Groups
WHERE (((Groups.GroupEnd) Is Null));

Then magic happens! Somehow the code knows which Group the
user wants to email and which Contacts are in that Group
and sends the email to them. I do see the problem. It's
where "magic happens".

Here's the table structure
Contacts (my "main table", contains ContactID, EmailName)
Groups (contains GroupID, GroupName, GroupStart, GroupEnd)
GroupMember (contains GroupMember, ContactID, GroupID,
GMemberStart, GMemberEnd)

I created qryGroups:
SELECT Contacts.ContactID, Contacts.EmailName,
Groups.GroupName
FROM Groups INNER JOIN (Contacts INNER JOIN GroupMembers
ON Contacts.ContactID = GroupMembers.ContactID) ON
Groups.GroupID = GroupMembers.GroupID
WHERE (((GroupMembers.GMemberEnd) Is Null) AND
((Groups.GroupEnd) Is Null) AND ((Contacts.EmailName) Is
Not Null));
This gives me all Contacts in a Group (where both the
group itself and the Contact's involement in the Group
are "active") that have an Email address.

Now here's the pitiful attempt. I thought maybe I could
use (see below) strWhere and strGroup. But I still don't
know what Set rst = CurrentDb.OpenRecordset (X) would be.
Or how the user input from FindGroup interacts with
qryGroups- perhaps I would need FindGroup to equal
GroupName in strGroup. Here's the rest of the code:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String

strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)

Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM Contacts WHERE [EmailName] Is Not Null AND something
about group members...")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Group
Email Link"
End Sub
-----Original Message-----
I still don't get exactly what process you're trying to use. Is this right?

You click a button on a form which pops up the GroupParamEmail form... on
that you choose the group you want to mail (in a combo that is also called
GroupParamEmail?)... and then, when you hit OK, you
want
the mail to be
sent?

If I have that wrong, then please let me know what it
is
that you want to
happen in terms of picking options from forms etc (feel free to be
demanding, it can all be done)

Last thing... I don't see where you are using the
choice
you make from the
combo to specify the people you want to mail... is 'People' a query that
includes a criteria reference to that control? If
not...
then how does that
work? How does 'Board of Directors' produce a list of addresses? (i.e.
what's the table structure that includes those addresses?)


"SillySally" <[email protected]> wrote
in
message
Thanks for taking an interest in my question- it's driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box field,
FindGroup, that allows an end-user to choose a group. I
use a similar form to run mailing labels. For example,
the end-user selects "Board of Directors" and the report
creates mail labels for all People who are in the "Board
of Directors" group.

So what I'm hoping to do with the email list is loop
through all People with email addresses that also belong
to the user specified group. Hope that explanation
helps. I had found an article from ATTAC Consulting Group
titled "How to create your won input box forms and pause
code for user input" which seems exactly what I need.
It's long but I'll paste it in (see after ***) -skip
it
if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get information or a
selection from a user that an a standard Input Box isn't
designed to handle.
As an example, you may want to offer the user only a
selection of one of two choices. Since there's no way to
restrict what the user can enter into an input box, an
input box won't work well.

To get around this limitation you can design a form that
acts as psudo input box, opening the form to get input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which the
running function is in, and for which you need to get the
input from the user, dimension new variables which
will
to
hold the return values which the user selects or enters
into your input form.The value of these variables will
be "visible" to your running function after the user
enters their selections. There's no need to make these
variables global variables.

Add a new sub procedure to the same module as your running
function. Your custom input box form will call this sub
procedure. The purpose of this sub procedure is
solely
to
accept the values from your input form as parameters and
to set the new module level variables equal to the value
of the parameters.

Design your own "input box" form as a dialog box form.
When a dialog box is opened, it will cause your running
code to "pause" until the dialog is closed. (You have to
specifically specify opening it in your running function
as "acDialog".)

In the OnClose event of your input box form, now add a
call to the sub procedure you just wrote. Specifying as
parameter values, the values of the text boxes or option
groups etc. from your form. This will send the data back
to your module when the dialog is closed.

You can also make your main code pause and wait for the
user's input and for non-dialog style forms by using code
like the following in you main procedure ( an " _ " means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub
procedure
to
notify your running function if the user clicked a cancel
button rather than an OK button to end your process.



-----Original Message-----
You're close. What do you mean by the parameter
field
on
GroupParamEmail...
a parameter you have to enter when the form opens? I
don't quite get how
you're choosing to specify the people you want to mail...
could you go into
a bit more detail please.


"SillySally" <[email protected]>
wrote
in
message
Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is FindGroup.
I'm
trying to find the group of people to send an
email
to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for the
group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"


.



.


.
 
R

Rob Oldfield

In which case you just need to change your original code to...

Dim rst As DAO.Recordset
Dim strTo As String
Dim sql As String
sql = "SELECT Contacts.EMailName FROM GroupMember INNER JOIN " + _
"Contacts ON GroupMember.ContactID = Contacts.ContactID " + _
"WHERE (((GroupMember.GroupID)=" + CStr(Me.YourComboName) + _
") AND ((GroupMember.GMemberEnd) Is Null));"
Set rst = CurrentDb.OpenRecordset(sql)

Note... rather than using CurrentDB you're generally better off doing... dim
db as database... set db=currentdb and then set rst=db.openrecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email Group "

....and that's providing that GroupID is the bound column on your combo
(which it should be).

It's really just a case of building an SQL string that gives you *any* list
of addresses.... and then replacing the key value in that with a reference
to the control that you're using. You can drop a breakpoint into the code
and copy the SQL variable out into a query window to see what it is doing.


SillySally said:
Hi. I set up GMemberStart and GMemberEnd (both date
fields) to specify the start and end dates in the Group
for the Contact. For example, a Group could have started
01/05/05 but this particular Contact didn't start being
associated with the Group until 02/13/05. A real example:
Board of Directors is an on-going group. Contacts serve 2
years and then stop being on the Board. Rather than
setting up a new Group, we can just set the Contact's
GMemberEnd date and leave Group going. That way when I
want to send email to the Board, I tell the email code
(someday!) not to send email to the Contacts with a value
in GMemberEnd.

GroupMemberID is the key of GroupMember table.
GroupMember is the "intermediary" table between Groups and
Contacts.
Sample data: GroupMemberID, ContactID, GroupID,
GMemberStart and GMemberEnd

9, 95, 5, 01/01/02
10, 95, 6, 05/01/02

This means that ContactID = 95 is a memeber of 2 Groups
(Board of Directors, starting 01/01/02) and (Reading
piolot, starting 05/01/02). That also means that
ContactID = 95 has two GroupMemberIDs.

Did I put this together? Perhaps. The database has evolved
(sort of) over a couple of years and is stuck together
with logic and spit. I do have a database designing
friend that helped in the beginning, but I give away
almost all credit for the good, and take ALL "credit" for
the bad. Thanks, Sal
-----Original Message-----
OK. That looks good. It's certainly correct to have a many-to-many
relationship from Contacts to Groups (although... what's going into the
GroupMember, GMemberStart and GMemberEnd fields in GroupMember? Could you
just give me some sample data from that table. Did you set the tables up by
the way?)


Demanding I can be ;-)
So, I suppose what you're saying is "code doesn't just
happen". Rats!
I do appreciate your efforts to help me get this working.
It's the "biggie" that will get my non-profit off their
old system (Address Book- yikes!) and on to Access. They
love their "groups" to segment the population.

Here's the process: I have a form (LabelsAndLists) that
has a command button (EmailGroup) that kicks off the
emailing code. The code calls form GroupParamEmail that
has an unbound combo box called FindGroup. Here's the sql
for FindGroup: SELECT Groups.GroupID, Groups.GroupName
FROM Groups
WHERE (((Groups.GroupEnd) Is Null));

Then magic happens! Somehow the code knows which Group the
user wants to email and which Contacts are in that Group
and sends the email to them. I do see the problem. It's
where "magic happens".

Here's the table structure
Contacts (my "main table", contains ContactID, EmailName)
Groups (contains GroupID, GroupName, GroupStart, GroupEnd)
GroupMember (contains GroupMember, ContactID, GroupID,
GMemberStart, GMemberEnd)

I created qryGroups:
SELECT Contacts.ContactID, Contacts.EmailName,
Groups.GroupName
FROM Groups INNER JOIN (Contacts INNER JOIN GroupMembers
ON Contacts.ContactID = GroupMembers.ContactID) ON
Groups.GroupID = GroupMembers.GroupID
WHERE (((GroupMembers.GMemberEnd) Is Null) AND
((Groups.GroupEnd) Is Null) AND ((Contacts.EmailName) Is
Not Null));
This gives me all Contacts in a Group (where both the
group itself and the Contact's involement in the Group
are "active") that have an Email address.

Now here's the pitiful attempt. I thought maybe I could
use (see below) strWhere and strGroup. But I still don't
know what Set rst = CurrentDb.OpenRecordset (X) would be.
Or how the user input from FindGroup interacts with
qryGroups- perhaps I would need FindGroup to equal
GroupName in strGroup. Here's the rest of the code:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String

strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)

Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM Contacts WHERE [EmailName] Is Not Null AND something
about group members...")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Group
Email Link"
End Sub

-----Original Message-----
I still don't get exactly what process you're trying to
use. Is this right?

You click a button on a form which pops up the
GroupParamEmail form... on
that you choose the group you want to mail (in a combo
that is also called
GroupParamEmail?)... and then, when you hit OK, you want
the mail to be
sent?

If I have that wrong, then please let me know what it is
that you want to
happen in terms of picking options from forms etc (feel
free to be
demanding, it can all be done)

Last thing... I don't see where you are using the choice
you make from the
combo to specify the people you want to mail...
is 'People' a query that
includes a criteria reference to that control? If not...
then how does that
work? How does 'Board of Directors' produce a list of
addresses? (i.e.
what's the table structure that includes those addresses?)


message
Thanks for taking an interest in my question- it's
driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box field,
FindGroup, that allows an end-user to choose a group. I
use a similar form to run mailing labels. For example,
the end-user selects "Board of Directors" and the report
creates mail labels for all People who are in the "Board
of Directors" group.

So what I'm hoping to do with the email list is loop
through all People with email addresses that also belong
to the user specified group. Hope that explanation
helps. I had found an article from ATTAC Consulting
Group
titled "How to create your won input box forms and pause
code for user input" which seems exactly what I need.
It's long but I'll paste it in (see after ***) -skip it
if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get information or a
selection from a user that an a standard Input Box isn't
designed to handle.
As an example, you may want to offer the user only a
selection of one of two choices. Since there's no way to
restrict what the user can enter into an input box, an
input box won't work well.

To get around this limitation you can design a form that
acts as psudo input box, opening the form to get input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which the
running function is in, and for which you need to get
the
input from the user, dimension new variables which will
to
hold the return values which the user selects or enters
into your input form.The value of these variables will
be "visible" to your running function after the user
enters their selections. There's no need to make these
variables global variables.

Add a new sub procedure to the same module as your
running
function. Your custom input box form will call this sub
procedure. The purpose of this sub procedure is solely
to
accept the values from your input form as parameters and
to set the new module level variables equal to the value
of the parameters.

Design your own "input box" form as a dialog box form.
When a dialog box is opened, it will cause your running
code to "pause" until the dialog is closed. (You have to
specifically specify opening it in your running function
as "acDialog".)

In the OnClose event of your input box form, now add a
call to the sub procedure you just wrote. Specifying as
parameter values, the values of the text boxes or option
groups etc. from your form. This will send the data back
to your module when the dialog is closed.

You can also make your main code pause and wait for the
user's input and for non-dialog style forms by using
code
like the following in you main procedure ( an " _ "
means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub procedure
to
notify your running function if the user clicked a
cancel
button rather than an OK button to end your process.



-----Original Message-----
You're close. What do you mean by the parameter field
on
GroupParamEmail...
a parameter you have to enter when the form opens? I
don't quite get how
you're choosing to specify the people you want to
mail...
could you go into
a bit more detail please.


in
message
Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter
value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is FindGroup.
I'm
trying to find the group of people to send an email
to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for the
group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset("SELECT
[EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Email
Group"


.



.


.
 
S

SillySally

I have no idea you could do that with sql in vb code!

I put in CStr(Me.FindGroup) + ")
FindGroup is the combo box on GroupParam form. But I'm
getting an error message- Compile error: method or data
member not found. I'm not even sure what CStr is being
used for. Help says to use CStr to convert a number to a
string. Do I need to define it in the "Dim" section?

Here's what I have so far. I think I did the db section as
you suggested:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String
Dim strWhere As String
Dim sql As String
Dim db As Database
'Dim CStr As ?
'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog


strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)
sql = "SELECT Contacts.EmailName FROM GroupMember
INNER JOIN " + "Contacts ON GroupMember.ContactID =
Contacts.ContactID " + "WHERE (((GroupMember.GroupID)=" +
CStr(Me.FindGroup) + ") AND ((GroupMember.GMemberEnd) Is
Null));"
Set db = CurrentDb
Set rst = db.OpenRecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"
End Sub

Thanks, Sal
-----Original Message-----
In which case you just need to change your original code to...

Dim rst As DAO.Recordset
Dim strTo As String
Dim sql As String
sql = "SELECT Contacts.EMailName FROM GroupMember INNER JOIN " + _
"Contacts ON GroupMember.ContactID = Contacts.ContactID " + _
"WHERE (((GroupMember.GroupID)=" + CStr(Me.YourComboName) + _
") AND ((GroupMember.GMemberEnd) Is Null));"
Set rst = CurrentDb.OpenRecordset(sql)

Note... rather than using CurrentDB you're generally better off doing... dim
db as database... set db=currentdb and then set rst=db.openrecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email Group "

....and that's providing that GroupID is the bound column on your combo
(which it should be).

It's really just a case of building an SQL string that gives you *any* list
of addresses.... and then replacing the key value in that with a reference
to the control that you're using. You can drop a breakpoint into the code
and copy the SQL variable out into a query window to see what it is doing.


Hi. I set up GMemberStart and GMemberEnd (both date
fields) to specify the start and end dates in the Group
for the Contact. For example, a Group could have started
01/05/05 but this particular Contact didn't start being
associated with the Group until 02/13/05. A real example:
Board of Directors is an on-going group. Contacts serve 2
years and then stop being on the Board. Rather than
setting up a new Group, we can just set the Contact's
GMemberEnd date and leave Group going. That way when I
want to send email to the Board, I tell the email code
(someday!) not to send email to the Contacts with a value
in GMemberEnd.

GroupMemberID is the key of GroupMember table.
GroupMember is the "intermediary" table between Groups and
Contacts.
Sample data: GroupMemberID, ContactID, GroupID,
GMemberStart and GMemberEnd

9, 95, 5, 01/01/02
10, 95, 6, 05/01/02

This means that ContactID = 95 is a memeber of 2 Groups
(Board of Directors, starting 01/01/02) and (Reading
piolot, starting 05/01/02). That also means that
ContactID = 95 has two GroupMemberIDs.

Did I put this together? Perhaps. The database has evolved
(sort of) over a couple of years and is stuck together
with logic and spit. I do have a database designing
friend that helped in the beginning, but I give away
almost all credit for the good, and take ALL "credit" for
the bad. Thanks, Sal
-----Original Message-----
OK. That looks good. It's certainly correct to have a many-to-many
relationship from Contacts to Groups (although...
what's
going into the
GroupMember, GMemberStart and GMemberEnd fields in GroupMember? Could you
just give me some sample data from that table. Did you set the tables up by
the way?)


"SillySally" <[email protected]> wrote
in
message
Demanding I can be ;-)
So, I suppose what you're saying is "code doesn't just
happen". Rats!
I do appreciate your efforts to help me get this working.
It's the "biggie" that will get my non-profit off their
old system (Address Book- yikes!) and on to Access. They
love their "groups" to segment the population.

Here's the process: I have a form (LabelsAndLists) that
has a command button (EmailGroup) that kicks off the
emailing code. The code calls form GroupParamEmail that
has an unbound combo box called FindGroup. Here's the sql
for FindGroup: SELECT Groups.GroupID, Groups.GroupName
FROM Groups
WHERE (((Groups.GroupEnd) Is Null));

Then magic happens! Somehow the code knows which
Group
the
user wants to email and which Contacts are in that Group
and sends the email to them. I do see the problem. It's
where "magic happens".

Here's the table structure
Contacts (my "main table", contains ContactID, EmailName)
Groups (contains GroupID, GroupName, GroupStart, GroupEnd)
GroupMember (contains GroupMember, ContactID, GroupID,
GMemberStart, GMemberEnd)

I created qryGroups:
SELECT Contacts.ContactID, Contacts.EmailName,
Groups.GroupName
FROM Groups INNER JOIN (Contacts INNER JOIN GroupMembers
ON Contacts.ContactID = GroupMembers.ContactID) ON
Groups.GroupID = GroupMembers.GroupID
WHERE (((GroupMembers.GMemberEnd) Is Null) AND
((Groups.GroupEnd) Is Null) AND ((Contacts.EmailName) Is
Not Null));
This gives me all Contacts in a Group (where both the
group itself and the Contact's involement in the Group
are "active") that have an Email address.

Now here's the pitiful attempt. I thought maybe I could
use (see below) strWhere and strGroup. But I still don't
know what Set rst = CurrentDb.OpenRecordset (X) would be.
Or how the user input from FindGroup interacts with
qryGroups- perhaps I would need FindGroup to equal
GroupName in strGroup. Here's the rest of the code:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String

strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)

Set rst = CurrentDb.OpenRecordset("SELECT [EmailName]
FROM Contacts WHERE [EmailName] Is Not Null AND something
about group members...")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Group
Email Link"
End Sub

-----Original Message-----
I still don't get exactly what process you're trying to
use. Is this right?

You click a button on a form which pops up the
GroupParamEmail form... on
that you choose the group you want to mail (in a combo
that is also called
GroupParamEmail?)... and then, when you hit OK, you want
the mail to be
sent?

If I have that wrong, then please let me know what
it
is
that you want to
happen in terms of picking options from forms etc (feel
free to be
demanding, it can all be done)

Last thing... I don't see where you are using the choice
you make from the
combo to specify the people you want to mail...
is 'People' a query that
includes a criteria reference to that control? If not...
then how does that
work? How does 'Board of Directors' produce a list of
addresses? (i.e.
what's the table structure that includes those addresses?)


"SillySally" <[email protected]>
wrote
in
message
Thanks for taking an interest in my question- it's
driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box field,
FindGroup, that allows an end-user to choose a group. I
use a similar form to run mailing labels. For example,
the end-user selects "Board of Directors" and the report
creates mail labels for all People who are in the "Board
of Directors" group.

So what I'm hoping to do with the email list is loop
through all People with email addresses that also belong
to the user specified group. Hope that explanation
helps. I had found an article from ATTAC Consulting
Group
titled "How to create your won input box forms and pause
code for user input" which seems exactly what I need.
It's long but I'll paste it in (see after ***) -
skip
it
if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get
information
or a
selection from a user that an a standard Input Box isn't
designed to handle.
As an example, you may want to offer the user only a
selection of one of two choices. Since there's no way to
restrict what the user can enter into an input
box,
an
input box won't work well.

To get around this limitation you can design a
form
that
acts as psudo input box, opening the form to get input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which the
running function is in, and for which you need to get
the
input from the user, dimension new variables which will
to
hold the return values which the user selects or enters
into your input form.The value of these variables will
be "visible" to your running function after the user
enters their selections. There's no need to make these
variables global variables.

Add a new sub procedure to the same module as your
running
function. Your custom input box form will call
this
sub
procedure. The purpose of this sub procedure is solely
to
accept the values from your input form as
parameters
and
to set the new module level variables equal to the value
of the parameters.

Design your own "input box" form as a dialog box form.
When a dialog box is opened, it will cause your running
code to "pause" until the dialog is closed. (You have to
specifically specify opening it in your running function
as "acDialog".)

In the OnClose event of your input box form, now
add
a
call to the sub procedure you just wrote.
Specifying
as
parameter values, the values of the text boxes or option
groups etc. from your form. This will send the
data
back
to your module when the dialog is closed.

You can also make your main code pause and wait
for
the
user's input and for non-dialog style forms by using
code
like the following in you main procedure ( an " _ "
means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub procedure
to
notify your running function if the user clicked a
cancel
button rather than an OK button to end your process.



-----Original Message-----
You're close. What do you mean by the parameter field
on
GroupParamEmail...
a parameter you have to enter when the form
opens?
I
don't quite get how
you're choosing to specify the people you want to
mail...
could you go into
a bit more detail please.


in
message
Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter
value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is FindGroup.
I'm
trying to find the group of people to send an email
to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for the
group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset("SELECT
[EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Email
Group"


.



.



.


.
 
R

Rob Oldfield

The CStr is just there to convert the (integer I think) value produced by
the combo into a string that can be written into the SQL statement. No Dims
necessary. Which form are you trying to run this from? It should be on the
same one as the choice of mail group.


SillySally said:
I have no idea you could do that with sql in vb code!

I put in CStr(Me.FindGroup) + ")
FindGroup is the combo box on GroupParam form. But I'm
getting an error message- Compile error: method or data
member not found. I'm not even sure what CStr is being
used for. Help says to use CStr to convert a number to a
string. Do I need to define it in the "Dim" section?

Here's what I have so far. I think I did the db section as
you suggested:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String
Dim strWhere As String
Dim sql As String
Dim db As Database
'Dim CStr As ?
'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog


strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)
sql = "SELECT Contacts.EmailName FROM GroupMember
INNER JOIN " + "Contacts ON GroupMember.ContactID =
Contacts.ContactID " + "WHERE (((GroupMember.GroupID)=" +
CStr(Me.FindGroup) + ") AND ((GroupMember.GMemberEnd) Is
Null));"
Set db = CurrentDb
Set rst = db.OpenRecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"
End Sub

Thanks, Sal
-----Original Message-----
In which case you just need to change your original code to...

Dim rst As DAO.Recordset
Dim strTo As String
Dim sql As String
sql = "SELECT Contacts.EMailName FROM GroupMember INNER JOIN " + _
"Contacts ON GroupMember.ContactID = Contacts.ContactID " + _
"WHERE (((GroupMember.GroupID)=" + CStr(Me.YourComboName) + _
") AND ((GroupMember.GMemberEnd) Is Null));"
Set rst = CurrentDb.OpenRecordset(sql)

Note... rather than using CurrentDB you're generally better off doing... dim
db as database... set db=currentdb and then set rst=db.openrecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email Group "

....and that's providing that GroupID is the bound column on your combo
(which it should be).

It's really just a case of building an SQL string that gives you *any* list
of addresses.... and then replacing the key value in that with a reference
to the control that you're using. You can drop a breakpoint into the code
and copy the SQL variable out into a query window to see what it is doing.


Hi. I set up GMemberStart and GMemberEnd (both date
fields) to specify the start and end dates in the Group
for the Contact. For example, a Group could have started
01/05/05 but this particular Contact didn't start being
associated with the Group until 02/13/05. A real example:
Board of Directors is an on-going group. Contacts serve 2
years and then stop being on the Board. Rather than
setting up a new Group, we can just set the Contact's
GMemberEnd date and leave Group going. That way when I
want to send email to the Board, I tell the email code
(someday!) not to send email to the Contacts with a value
in GMemberEnd.

GroupMemberID is the key of GroupMember table.
GroupMember is the "intermediary" table between Groups and
Contacts.
Sample data: GroupMemberID, ContactID, GroupID,
GMemberStart and GMemberEnd

9, 95, 5, 01/01/02
10, 95, 6, 05/01/02

This means that ContactID = 95 is a memeber of 2 Groups
(Board of Directors, starting 01/01/02) and (Reading
piolot, starting 05/01/02). That also means that
ContactID = 95 has two GroupMemberIDs.

Did I put this together? Perhaps. The database has evolved
(sort of) over a couple of years and is stuck together
with logic and spit. I do have a database designing
friend that helped in the beginning, but I give away
almost all credit for the good, and take ALL "credit" for
the bad. Thanks, Sal

-----Original Message-----
OK. That looks good. It's certainly correct to have a
many-to-many
relationship from Contacts to Groups (although... what's
going into the
GroupMember, GMemberStart and GMemberEnd fields in
GroupMember? Could you
just give me some sample data from that table. Did you
set the tables up by
the way?)


message
Demanding I can be ;-)
So, I suppose what you're saying is "code doesn't just
happen". Rats!
I do appreciate your efforts to help me get this
working.
It's the "biggie" that will get my non-profit off their
old system (Address Book- yikes!) and on to Access.
They
love their "groups" to segment the population.

Here's the process: I have a form (LabelsAndLists) that
has a command button (EmailGroup) that kicks off the
emailing code. The code calls form GroupParamEmail that
has an unbound combo box called FindGroup. Here's the
sql
for FindGroup: SELECT Groups.GroupID, Groups.GroupName
FROM Groups
WHERE (((Groups.GroupEnd) Is Null));

Then magic happens! Somehow the code knows which Group
the
user wants to email and which Contacts are in that Group
and sends the email to them. I do see the problem.
It's
where "magic happens".

Here's the table structure
Contacts (my "main table", contains ContactID,
EmailName)
Groups (contains GroupID, GroupName, GroupStart,
GroupEnd)
GroupMember (contains GroupMember, ContactID, GroupID,
GMemberStart, GMemberEnd)

I created qryGroups:
SELECT Contacts.ContactID, Contacts.EmailName,
Groups.GroupName
FROM Groups INNER JOIN (Contacts INNER JOIN GroupMembers
ON Contacts.ContactID = GroupMembers.ContactID) ON
Groups.GroupID = GroupMembers.GroupID
WHERE (((GroupMembers.GMemberEnd) Is Null) AND
((Groups.GroupEnd) Is Null) AND ((Contacts.EmailName) Is
Not Null));
This gives me all Contacts in a Group (where both the
group itself and the Contact's involement in the Group
are "active") that have an Email address.

Now here's the pitiful attempt. I thought maybe I could
use (see below) strWhere and strGroup. But I still
don't
know what Set rst = CurrentDb.OpenRecordset (X) would
be.
Or how the user input from FindGroup interacts with
qryGroups- perhaps I would need FindGroup to equal
GroupName in strGroup. Here's the rest of the code:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String

strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)

Set rst = CurrentDb.OpenRecordset("SELECT
[EmailName]
FROM Contacts WHERE [EmailName] Is Not Null AND
something
about group members...")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Group
Email Link"
End Sub

-----Original Message-----
I still don't get exactly what process you're trying to
use. Is this right?

You click a button on a form which pops up the
GroupParamEmail form... on
that you choose the group you want to mail (in a combo
that is also called
GroupParamEmail?)... and then, when you hit OK, you
want
the mail to be
sent?

If I have that wrong, then please let me know what it
is
that you want to
happen in terms of picking options from forms etc (feel
free to be
demanding, it can all be done)

Last thing... I don't see where you are using the
choice
you make from the
combo to specify the people you want to mail...
is 'People' a query that
includes a criteria reference to that control? If
not...
then how does that
work? How does 'Board of Directors' produce a list of
addresses? (i.e.
what's the table structure that includes those
addresses?)


in
message
Thanks for taking an interest in my question- it's
driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box field,
FindGroup, that allows an end-user to choose a
group. I
use a similar form to run mailing labels. For
example,
the end-user selects "Board of Directors" and the
report
creates mail labels for all People who are in
the "Board
of Directors" group.

So what I'm hoping to do with the email list is loop
through all People with email addresses that also
belong
to the user specified group. Hope that explanation
helps. I had found an article from ATTAC Consulting
Group
titled "How to create your won input box forms and
pause
code for user input" which seems exactly what I need.
It's long but I'll paste it in (see after ***) - skip
it
if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get information
or a
selection from a user that an a standard Input Box
isn't
designed to handle.
As an example, you may want to offer the user only a
selection of one of two choices. Since there's no
way to
restrict what the user can enter into an input box,
an
input box won't work well.

To get around this limitation you can design a form
that
acts as psudo input box, opening the form to get
input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which the
running function is in, and for which you need to get
the
input from the user, dimension new variables which
will
to
hold the return values which the user selects or
enters
into your input form.The value of these variables
will
be "visible" to your running function after the user
enters their selections. There's no need to make
these
variables global variables.

Add a new sub procedure to the same module as your
running
function. Your custom input box form will call this
sub
procedure. The purpose of this sub procedure is
solely
to
accept the values from your input form as parameters
and
to set the new module level variables equal to the
value
of the parameters.

Design your own "input box" form as a dialog box
form.
When a dialog box is opened, it will cause your
running
code to "pause" until the dialog is closed. (You
have to
specifically specify opening it in your running
function
as "acDialog".)

In the OnClose event of your input box form, now add
a
call to the sub procedure you just wrote. Specifying
as
parameter values, the values of the text boxes or
option
groups etc. from your form. This will send the data
back
to your module when the dialog is closed.

You can also make your main code pause and wait for
the
user's input and for non-dialog style forms by using
code
like the following in you main procedure ( an " _ "
means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub
procedure
to
notify your running function if the user clicked a
cancel
button rather than an OK button to end your process.



-----Original Message-----
You're close. What do you mean by the parameter
field
on
GroupParamEmail...
a parameter you have to enter when the form opens?
I
don't quite get how
you're choosing to specify the people you want to
mail...
could you go into
a bit more detail please.


"SillySally" <[email protected]>
wrote
in
message
Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter
value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is
FindGroup.
I'm
trying to find the group of people to send an
email
to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for
the
group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset("SELECT
[EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Email
Group"


.



.



.


.
 
S

SillySally

Thanks. I'm confused. "Which form are you trying to run
this from? It should be on the same one as the choice of
mail group."

My LabelsAndLists form has a command button that executes
this code OnClick. When the button is clicked, I want the
GroupParamEmail form to open so the user can select from
the combo box FindGroup. I want the code to use FindGroup
(GroupID) to compare against the Contact's GroupID. And
chose who to send an email to.

Are you saying that instead, I should have the user select
the GroupParamEmail form and have a command button on it
that runs the code? That's not really what I was
thinking. And that seems strange in that the code calls
to open GroupParamEmail, not be on it. Am I missing many
things? Thanks, Sal
-----Original Message-----
The CStr is just there to convert the (integer I think) value produced by
the combo into a string that can be written into the SQL statement. No Dims
necessary. Which form are you trying to run this from? It should be on the
same one as the choice of mail group.


I have no idea you could do that with sql in vb code!

I put in CStr(Me.FindGroup) + ")
FindGroup is the combo box on GroupParam form. But I'm
getting an error message- Compile error: method or data
member not found. I'm not even sure what CStr is being
used for. Help says to use CStr to convert a number to a
string. Do I need to define it in the "Dim" section?

Here's what I have so far. I think I did the db section as
you suggested:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String
Dim strWhere As String
Dim sql As String
Dim db As Database
'Dim CStr As ?
'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog


strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)
sql = "SELECT Contacts.EmailName FROM GroupMember
INNER JOIN " + "Contacts ON GroupMember.ContactID =
Contacts.ContactID " + "WHERE (((GroupMember.GroupID)=" +
CStr(Me.FindGroup) + ") AND ((GroupMember.GMemberEnd) Is
Null));"
Set db = CurrentDb
Set rst = db.OpenRecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"
End Sub

Thanks, Sal
-----Original Message-----
In which case you just need to change your original
code
to...
Dim rst As DAO.Recordset
Dim strTo As String
Dim sql As String
sql = "SELECT Contacts.EMailName FROM GroupMember INNER JOIN " + _
"Contacts ON GroupMember.ContactID =
Contacts.ContactID "
+ _
"WHERE (((GroupMember.GroupID)=" + CStr
(Me.YourComboName)
+ _
") AND ((GroupMember.GMemberEnd) Is Null));"
Set rst = CurrentDb.OpenRecordset(sql)

Note... rather than using CurrentDB you're generally better off doing... dim
db as database... set db=currentdb and then set rst=db.openrecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email Group "

....and that's providing that GroupID is the bound
column
on your combo
(which it should be).

It's really just a case of building an SQL string that gives you *any* list
of addresses.... and then replacing the key value in
that
with a reference
to the control that you're using. You can drop a breakpoint into the code
and copy the SQL variable out into a query window to
see
what it is doing.
"SillySally" <[email protected]> wrote
in
message
Hi. I set up GMemberStart and GMemberEnd (both date
fields) to specify the start and end dates in the Group
for the Contact. For example, a Group could have started
01/05/05 but this particular Contact didn't start being
associated with the Group until 02/13/05. A real example:
Board of Directors is an on-going group. Contacts serve 2
years and then stop being on the Board. Rather than
setting up a new Group, we can just set the Contact's
GMemberEnd date and leave Group going. That way when I
want to send email to the Board, I tell the email code
(someday!) not to send email to the Contacts with a value
in GMemberEnd.

GroupMemberID is the key of GroupMember table.
GroupMember is the "intermediary" table between
Groups
and
Contacts.
Sample data: GroupMemberID, ContactID, GroupID,
GMemberStart and GMemberEnd

9, 95, 5, 01/01/02
10, 95, 6, 05/01/02

This means that ContactID = 95 is a memeber of 2 Groups
(Board of Directors, starting 01/01/02) and (Reading
piolot, starting 05/01/02). That also means that
ContactID = 95 has two GroupMemberIDs.

Did I put this together? Perhaps. The database has evolved
(sort of) over a couple of years and is stuck together
with logic and spit. I do have a database designing
friend that helped in the beginning, but I give away
almost all credit for the good, and take ALL "credit" for
the bad. Thanks, Sal

-----Original Message-----
OK. That looks good. It's certainly correct to have a
many-to-many
relationship from Contacts to Groups (although... what's
going into the
GroupMember, GMemberStart and GMemberEnd fields in
GroupMember? Could you
just give me some sample data from that table. Did you
set the tables up by
the way?)


"SillySally" <[email protected]>
wrote
in
message
Demanding I can be ;-)
So, I suppose what you're saying is "code doesn't just
happen". Rats!
I do appreciate your efforts to help me get this
working.
It's the "biggie" that will get my non-profit off their
old system (Address Book- yikes!) and on to Access.
They
love their "groups" to segment the population.

Here's the process: I have a form (LabelsAndLists) that
has a command button (EmailGroup) that kicks off the
emailing code. The code calls form
GroupParamEmail
that
has an unbound combo box called FindGroup. Here's the
sql
for FindGroup: SELECT Groups.GroupID, Groups.GroupName
FROM Groups
WHERE (((Groups.GroupEnd) Is Null));

Then magic happens! Somehow the code knows which Group
the
user wants to email and which Contacts are in that Group
and sends the email to them. I do see the problem.
It's
where "magic happens".

Here's the table structure
Contacts (my "main table", contains ContactID,
EmailName)
Groups (contains GroupID, GroupName, GroupStart,
GroupEnd)
GroupMember (contains GroupMember, ContactID, GroupID,
GMemberStart, GMemberEnd)

I created qryGroups:
SELECT Contacts.ContactID, Contacts.EmailName,
Groups.GroupName
FROM Groups INNER JOIN (Contacts INNER JOIN GroupMembers
ON Contacts.ContactID = GroupMembers.ContactID) ON
Groups.GroupID = GroupMembers.GroupID
WHERE (((GroupMembers.GMemberEnd) Is Null) AND
((Groups.GroupEnd) Is Null) AND ((Contacts.EmailName) Is
Not Null));
This gives me all Contacts in a Group (where both the
group itself and the Contact's involement in the Group
are "active") that have an Email address.

Now here's the pitiful attempt. I thought maybe I could
use (see below) strWhere and strGroup. But I still
don't
know what Set rst = CurrentDb.OpenRecordset (X) would
be.
Or how the user input from FindGroup interacts with
qryGroups- perhaps I would need FindGroup to equal
GroupName in strGroup. Here's the rest of the code:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String

strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup ("qryGroups", "GroupName",
strWhere), 0)

Set rst = CurrentDb.OpenRecordset("SELECT
[EmailName]
FROM Contacts WHERE [EmailName] Is Not Null AND
something
about group members...")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Group
Email Link"
End Sub

-----Original Message-----
I still don't get exactly what process you're trying to
use. Is this right?

You click a button on a form which pops up the
GroupParamEmail form... on
that you choose the group you want to mail (in a combo
that is also called
GroupParamEmail?)... and then, when you hit OK, you
want
the mail to be
sent?

If I have that wrong, then please let me know
what
it
is
that you want to
happen in terms of picking options from forms etc (feel
free to be
demanding, it can all be done)

Last thing... I don't see where you are using the
choice
you make from the
combo to specify the people you want to mail...
is 'People' a query that
includes a criteria reference to that control? If
not...
then how does that
work? How does 'Board of Directors' produce a
list
of
addresses? (i.e.
what's the table structure that includes those
addresses?)


in
message
Thanks for taking an interest in my question- it's
driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box field,
FindGroup, that allows an end-user to choose a
group. I
use a similar form to run mailing labels. For
example,
the end-user selects "Board of Directors" and the
report
creates mail labels for all People who are in
the "Board
of Directors" group.

So what I'm hoping to do with the email list is loop
through all People with email addresses that also
belong
to the user specified group. Hope that explanation
helps. I had found an article from ATTAC Consulting
Group
titled "How to create your won input box forms and
pause
code for user input" which seems exactly what I need.
It's long but I'll paste it in (see after
***) -
skip
it
if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get information
or a
selection from a user that an a standard Input Box
isn't
designed to handle.
As an example, you may want to offer the user only a
selection of one of two choices. Since there's no
way to
restrict what the user can enter into an input box,
an
input box won't work well.

To get around this limitation you can design a form
that
acts as psudo input box, opening the form to get
input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which the
running function is in, and for which you need
to
get
the
input from the user, dimension new variables which
will
to
hold the return values which the user selects or
enters
into your input form.The value of these variables
will
be "visible" to your running function after the user
enters their selections. There's no need to make
these
variables global variables.

Add a new sub procedure to the same module as your
running
function. Your custom input box form will call this
sub
procedure. The purpose of this sub procedure is
solely
to
accept the values from your input form as parameters
and
to set the new module level variables equal to the
value
of the parameters.

Design your own "input box" form as a dialog box
form.
When a dialog box is opened, it will cause your
running
code to "pause" until the dialog is closed. (You
have to
specifically specify opening it in your running
function
as "acDialog".)

In the OnClose event of your input box form,
now
add
a
call to the sub procedure you just wrote. Specifying
as
parameter values, the values of the text boxes or
option
groups etc. from your form. This will send the data
back
to your module when the dialog is closed.

You can also make your main code pause and wait for
the
user's input and for non-dialog style forms by using
code
like the following in you main procedure ( an " _ "
means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub
procedure
to
notify your running function if the user clicked a
cancel
button rather than an OK button to end your process.



-----Original Message-----
You're close. What do you mean by the parameter
field
on
GroupParamEmail...
a parameter you have to enter when the form opens?
I
don't quite get how
you're choosing to specify the people you want to
mail...
could you go into
a bit more detail please.


"SillySally"
wrote
in
message
Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter
value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is
FindGroup.
I'm
trying to find the group of people to send an
email
to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for
the
group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset("SELECT
[EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Email
Group"


.



.



.



.


.
 
S

SillySally

Hi. I'm good with calling the code from a command button
on GroupParamEmail, if I can get it to work! I think I'm
having pretty good luck, but at work we use GroupWise so
I can't really test it out. I did get to the point where
the code was trying to send the email, so that's a good
sign. I'll post after I get home to let you know. I'm
loving the sql statement- I could never figure out how to
have sql in vb. Thanks, Sal. This is what I'm working
with now:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
'Dim strGroup As String
'Dim strWhere As String
Dim sql As String
Dim db As Database
'Open GroupParamEmail
'DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog

sql = "SELECT Contacts.EmailName FROM GroupMembers
INNER JOIN " + "Contacts ON GroupMembers.ContactID =
Contacts.ContactID " + "WHERE (((GroupMembers.GroupID)="
+ CStr(Me.FindGroup) + ") AND ((GroupMembers.GMemberEnd)
Is Null));"
'strWhere = "[ContactID] = " & Nz([ContactID], 0)
'strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)
Set db = CurrentDb
Set rst = db.OpenRecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Email Group"
End Sub
-----Original Message-----
The CStr is just there to convert the (integer I think) value produced by
the combo into a string that can be written into the SQL statement. No Dims
necessary. Which form are you trying to run this from? It should be on the
same one as the choice of mail group.


I have no idea you could do that with sql in vb code!

I put in CStr(Me.FindGroup) + ")
FindGroup is the combo box on GroupParam form. But I'm
getting an error message- Compile error: method or data
member not found. I'm not even sure what CStr is being
used for. Help says to use CStr to convert a number to a
string. Do I need to define it in the "Dim" section?

Here's what I have so far. I think I did the db section as
you suggested:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String
Dim strWhere As String
Dim sql As String
Dim db As Database
'Dim CStr As ?
'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog


strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)
sql = "SELECT Contacts.EmailName FROM GroupMember
INNER JOIN " + "Contacts ON GroupMember.ContactID =
Contacts.ContactID " + "WHERE (((GroupMember.GroupID) =" +
CStr(Me.FindGroup) + ") AND ((GroupMember.GMemberEnd) Is
Null));"
Set db = CurrentDb
Set rst = db.OpenRecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"
End Sub

Thanks, Sal
-----Original Message-----
In which case you just need to change your original
code
to...
Dim rst As DAO.Recordset
Dim strTo As String
Dim sql As String
sql = "SELECT Contacts.EMailName FROM GroupMember
INNER
JOIN " + _
"Contacts ON GroupMember.ContactID =
Contacts.ContactID "
+ _
"WHERE (((GroupMember.GroupID)=" + CStr
(Me.YourComboName)
+ _
") AND ((GroupMember.GMemberEnd) Is Null));"
Set rst = CurrentDb.OpenRecordset(sql)

Note... rather than using CurrentDB you're generally better off doing... dim
db as database... set db=currentdb and then set rst=db.openrecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email Group "

....and that's providing that GroupID is the bound
column
on your combo
(which it should be).

It's really just a case of building an SQL string that gives you *any* list
of addresses.... and then replacing the key value in
that
with a reference
to the control that you're using. You can drop a breakpoint into the code
and copy the SQL variable out into a query window to
see
what it is doing.
"SillySally" <[email protected]> wrote
in
message
Hi. I set up GMemberStart and GMemberEnd (both date
fields) to specify the start and end dates in the Group
for the Contact. For example, a Group could have started
01/05/05 but this particular Contact didn't start being
associated with the Group until 02/13/05. A real example:
Board of Directors is an on-going group. Contacts serve 2
years and then stop being on the Board. Rather than
setting up a new Group, we can just set the Contact's
GMemberEnd date and leave Group going. That way when I
want to send email to the Board, I tell the email code
(someday!) not to send email to the Contacts with a value
in GMemberEnd.

GroupMemberID is the key of GroupMember table.
GroupMember is the "intermediary" table between
Groups
and
Contacts.
Sample data: GroupMemberID, ContactID, GroupID,
GMemberStart and GMemberEnd

9, 95, 5, 01/01/02
10, 95, 6, 05/01/02

This means that ContactID = 95 is a memeber of 2 Groups
(Board of Directors, starting 01/01/02) and (Reading
piolot, starting 05/01/02). That also means that
ContactID = 95 has two GroupMemberIDs.

Did I put this together? Perhaps. The database has evolved
(sort of) over a couple of years and is stuck together
with logic and spit. I do have a database designing
friend that helped in the beginning, but I give away
almost all credit for the good, and take
ALL "credit"
for
the bad. Thanks, Sal

-----Original Message-----
OK. That looks good. It's certainly correct to have a
many-to-many
relationship from Contacts to Groups (although... what's
going into the
GroupMember, GMemberStart and GMemberEnd fields in
GroupMember? Could you
just give me some sample data from that table. Did you
set the tables up by
the way?)


"SillySally" <[email protected]>
wrote
in
message
Demanding I can be ;-)
So, I suppose what you're saying is "code doesn't just
happen". Rats!
I do appreciate your efforts to help me get this
working.
It's the "biggie" that will get my non-profit off their
old system (Address Book- yikes!) and on to Access.
They
love their "groups" to segment the population.

Here's the process: I have a form
(LabelsAndLists)
that
has a command button (EmailGroup) that kicks off the
emailing code. The code calls form
GroupParamEmail
that
has an unbound combo box called FindGroup. Here's the
sql
for FindGroup: SELECT Groups.GroupID, Groups.GroupName
FROM Groups
WHERE (((Groups.GroupEnd) Is Null));

Then magic happens! Somehow the code knows which Group
the
user wants to email and which Contacts are in
that
Group
and sends the email to them. I do see the problem.
It's
where "magic happens".

Here's the table structure
Contacts (my "main table", contains ContactID,
EmailName)
Groups (contains GroupID, GroupName, GroupStart,
GroupEnd)
GroupMember (contains GroupMember, ContactID, GroupID,
GMemberStart, GMemberEnd)

I created qryGroups:
SELECT Contacts.ContactID, Contacts.EmailName,
Groups.GroupName
FROM Groups INNER JOIN (Contacts INNER JOIN GroupMembers
ON Contacts.ContactID = GroupMembers.ContactID) ON
Groups.GroupID = GroupMembers.GroupID
WHERE (((GroupMembers.GMemberEnd) Is Null) AND
((Groups.GroupEnd) Is Null) AND ((Contacts.EmailName) Is
Not Null));
This gives me all Contacts in a Group (where both the
group itself and the Contact's involement in the Group
are "active") that have an Email address.

Now here's the pitiful attempt. I thought maybe
I
could
use (see below) strWhere and strGroup. But I still
don't
know what Set rst = CurrentDb.OpenRecordset (X) would
be.
Or how the user input from FindGroup interacts with
qryGroups- perhaps I would need FindGroup to equal
GroupName in strGroup. Here's the rest of the code:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String

strWhere = "[ContactID] = " & Nz ([ContactID], 0)
strGroup = Nz(DLookup ("qryGroups", "GroupName",
strWhere), 0)

Set rst = CurrentDb.OpenRecordset("SELECT
[EmailName]
FROM Contacts WHERE [EmailName] Is Not Null AND
something
about group members...")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Group
Email Link"
End Sub

-----Original Message-----
I still don't get exactly what process you're trying to
use. Is this right?

You click a button on a form which pops up the
GroupParamEmail form... on
that you choose the group you want to mail (in a combo
that is also called
GroupParamEmail?)... and then, when you hit OK, you
want
the mail to be
sent?

If I have that wrong, then please let me know
what
it
is
that you want to
happen in terms of picking options from forms
etc
(feel
free to be
demanding, it can all be done)

Last thing... I don't see where you are using the
choice
you make from the
combo to specify the people you want to mail...
is 'People' a query that
includes a criteria reference to that control? If
not...
then how does that
work? How does 'Board of Directors' produce a
list
of
addresses? (i.e.
what's the table structure that includes those
addresses?)


in
message
Thanks for taking an interest in my question- it's
driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box field,
FindGroup, that allows an end-user to choose a
group. I
use a similar form to run mailing labels. For
example,
the end-user selects "Board of Directors" and the
report
creates mail labels for all People who are in
the "Board
of Directors" group.

So what I'm hoping to do with the email list
is
loop
through all People with email addresses that also
belong
to the user specified group. Hope that explanation
helps. I had found an article from ATTAC Consulting
Group
titled "How to create your won input box forms and
pause
code for user input" which seems exactly what
I
need.
It's long but I'll paste it in (see after
***) -
skip
it
if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get information
or a
selection from a user that an a standard Input Box
isn't
designed to handle.
As an example, you may want to offer the user only a
selection of one of two choices. Since there's no
way to
restrict what the user can enter into an input box,
an
input box won't work well.

To get around this limitation you can design a form
that
acts as psudo input box, opening the form to get
input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module
which
the
running function is in, and for which you
need to
get
the
input from the user, dimension new variables which
will
to
hold the return values which the user selects or
enters
into your input form.The value of these variables
will
be "visible" to your running function after
the
user
enters their selections. There's no need to make
these
variables global variables.

Add a new sub procedure to the same module as your
running
function. Your custom input box form will call this
sub
procedure. The purpose of this sub procedure is
solely
to
accept the values from your input form as parameters
and
to set the new module level variables equal to the
value
of the parameters.

Design your own "input box" form as a dialog box
form.
When a dialog box is opened, it will cause your
running
code to "pause" until the dialog is closed. (You
have to
specifically specify opening it in your running
function
as "acDialog".)

In the OnClose event of your input box form,
now
add
a
call to the sub procedure you just wrote. Specifying
as
parameter values, the values of the text boxes or
option
groups etc. from your form. This will send the data
back
to your module when the dialog is closed.

You can also make your main code pause and
wait
for
the
user's input and for non-dialog style forms by using
code
like the following in you main procedure (
an "
_ "
means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub
procedure
to
notify your running function if the user clicked a
cancel
button rather than an OK button to end your process.



-----Original Message-----
You're close. What do you mean by the parameter
field
on
GroupParamEmail...
a parameter you have to enter when the form opens?
I
don't quite get how
you're choosing to specify the people you want to
mail...
could you go into
a bit more detail please.


"SillySally"
wrote
in
message
[email protected]...
Greetings-
I am trying to write a subprocess that will set a
variable equal to an end-user selected parameter
value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is
FindGroup.
I'm
trying to find the group of people to send an
email
to.
I have the emailing code, but I'm having problems
figuring out how to integrate this group selection
parameter as the variable.

I believe I will need to add the subprocess for
the
group
selection to the OnClose event of GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset ("SELECT
[EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Email
Group"


.



.



.



.


.
 
R

Rob Oldfield

So which line is the compile error highlighting? And what's the text of the
error?


SillySally said:
Hi. I'm good with calling the code from a command button
on GroupParamEmail, if I can get it to work! I think I'm
having pretty good luck, but at work we use GroupWise so
I can't really test it out. I did get to the point where
the code was trying to send the email, so that's a good
sign. I'll post after I get home to let you know. I'm
loving the sql statement- I could never figure out how to
have sql in vb. Thanks, Sal. This is what I'm working
with now:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
'Dim strGroup As String
'Dim strWhere As String
Dim sql As String
Dim db As Database
'Open GroupParamEmail
'DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog

sql = "SELECT Contacts.EmailName FROM GroupMembers
INNER JOIN " + "Contacts ON GroupMembers.ContactID =
Contacts.ContactID " + "WHERE (((GroupMembers.GroupID)="
+ CStr(Me.FindGroup) + ") AND ((GroupMembers.GMemberEnd)
Is Null));"
'strWhere = "[ContactID] = " & Nz([ContactID], 0)
'strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)
Set db = CurrentDb
Set rst = db.OpenRecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Email Group"
End Sub
-----Original Message-----
The CStr is just there to convert the (integer I think) value produced by
the combo into a string that can be written into the SQL statement. No Dims
necessary. Which form are you trying to run this from? It should be on the
same one as the choice of mail group.


I have no idea you could do that with sql in vb code!

I put in CStr(Me.FindGroup) + ")
FindGroup is the combo box on GroupParam form. But I'm
getting an error message- Compile error: method or data
member not found. I'm not even sure what CStr is being
used for. Help says to use CStr to convert a number to a
string. Do I need to define it in the "Dim" section?

Here's what I have so far. I think I did the db section as
you suggested:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String
Dim strWhere As String
Dim sql As String
Dim db As Database
'Dim CStr As ?
'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog


strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)
sql = "SELECT Contacts.EmailName FROM GroupMember
INNER JOIN " + "Contacts ON GroupMember.ContactID =
Contacts.ContactID " + "WHERE (((GroupMember.GroupID) =" +
CStr(Me.FindGroup) + ") AND ((GroupMember.GMemberEnd) Is
Null));"
Set db = CurrentDb
Set rst = db.OpenRecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"
End Sub

Thanks, Sal
-----Original Message-----
In which case you just need to change your original code
to...

Dim rst As DAO.Recordset
Dim strTo As String
Dim sql As String
sql = "SELECT Contacts.EMailName FROM GroupMember INNER
JOIN " + _
"Contacts ON GroupMember.ContactID = Contacts.ContactID "
+ _
"WHERE (((GroupMember.GroupID)=" + CStr (Me.YourComboName)
+ _
") AND ((GroupMember.GMemberEnd) Is Null));"
Set rst = CurrentDb.OpenRecordset(sql)

Note... rather than using CurrentDB you're generally
better off doing... dim
db as database... set db=currentdb and then set
rst=db.openrecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group "

....and that's providing that GroupID is the bound column
on your combo
(which it should be).

It's really just a case of building an SQL string that
gives you *any* list
of addresses.... and then replacing the key value in that
with a reference
to the control that you're using. You can drop a
breakpoint into the code
and copy the SQL variable out into a query window to see
what it is doing.


message
Hi. I set up GMemberStart and GMemberEnd (both date
fields) to specify the start and end dates in the Group
for the Contact. For example, a Group could have
started
01/05/05 but this particular Contact didn't start being
associated with the Group until 02/13/05. A real
example:
Board of Directors is an on-going group. Contacts
serve 2
years and then stop being on the Board. Rather than
setting up a new Group, we can just set the Contact's
GMemberEnd date and leave Group going. That way when I
want to send email to the Board, I tell the email code
(someday!) not to send email to the Contacts with a
value
in GMemberEnd.

GroupMemberID is the key of GroupMember table.
GroupMember is the "intermediary" table between Groups
and
Contacts.
Sample data: GroupMemberID, ContactID, GroupID,
GMemberStart and GMemberEnd

9, 95, 5, 01/01/02
10, 95, 6, 05/01/02

This means that ContactID = 95 is a memeber of 2 Groups
(Board of Directors, starting 01/01/02) and (Reading
piolot, starting 05/01/02). That also means that
ContactID = 95 has two GroupMemberIDs.

Did I put this together? Perhaps. The database has
evolved
(sort of) over a couple of years and is stuck together
with logic and spit. I do have a database designing
friend that helped in the beginning, but I give away
almost all credit for the good, and take ALL "credit"
for
the bad. Thanks, Sal

-----Original Message-----
OK. That looks good. It's certainly correct to have a
many-to-many
relationship from Contacts to Groups (although...
what's
going into the
GroupMember, GMemberStart and GMemberEnd fields in
GroupMember? Could you
just give me some sample data from that table. Did you
set the tables up by
the way?)


in
message
Demanding I can be ;-)
So, I suppose what you're saying is "code doesn't
just
happen". Rats!
I do appreciate your efforts to help me get this
working.
It's the "biggie" that will get my non-profit off
their
old system (Address Book- yikes!) and on to Access.
They
love their "groups" to segment the population.

Here's the process: I have a form (LabelsAndLists)
that
has a command button (EmailGroup) that kicks off the
emailing code. The code calls form GroupParamEmail
that
has an unbound combo box called FindGroup. Here's the
sql
for FindGroup: SELECT Groups.GroupID,
Groups.GroupName
FROM Groups
WHERE (((Groups.GroupEnd) Is Null));

Then magic happens! Somehow the code knows which
Group
the
user wants to email and which Contacts are in that
Group
and sends the email to them. I do see the problem.
It's
where "magic happens".

Here's the table structure
Contacts (my "main table", contains ContactID,
EmailName)
Groups (contains GroupID, GroupName, GroupStart,
GroupEnd)
GroupMember (contains GroupMember, ContactID,
GroupID,
GMemberStart, GMemberEnd)

I created qryGroups:
SELECT Contacts.ContactID, Contacts.EmailName,
Groups.GroupName
FROM Groups INNER JOIN (Contacts INNER JOIN
GroupMembers
ON Contacts.ContactID = GroupMembers.ContactID) ON
Groups.GroupID = GroupMembers.GroupID
WHERE (((GroupMembers.GMemberEnd) Is Null) AND
((Groups.GroupEnd) Is Null) AND
((Contacts.EmailName) Is
Not Null));
This gives me all Contacts in a Group (where both the
group itself and the Contact's involement in the
Group
are "active") that have an Email address.

Now here's the pitiful attempt. I thought maybe I
could
use (see below) strWhere and strGroup. But I still
don't
know what Set rst = CurrentDb.OpenRecordset (X) would
be.
Or how the user input from FindGroup interacts with
qryGroups- perhaps I would need FindGroup to equal
GroupName in strGroup. Here's the rest of the code:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String

strWhere = "[ContactID] = " & Nz ([ContactID], 0)
strGroup = Nz(DLookup ("qryGroups", "GroupName",
strWhere), 0)

Set rst = CurrentDb.OpenRecordset("SELECT
[EmailName]
FROM Contacts WHERE [EmailName] Is Not Null AND
something
about group members...")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Group
Email Link"
End Sub

-----Original Message-----
I still don't get exactly what process you're
trying to
use. Is this right?

You click a button on a form which pops up the
GroupParamEmail form... on
that you choose the group you want to mail (in a
combo
that is also called
GroupParamEmail?)... and then, when you hit OK, you
want
the mail to be
sent?

If I have that wrong, then please let me know what
it
is
that you want to
happen in terms of picking options from forms etc
(feel
free to be
demanding, it can all be done)

Last thing... I don't see where you are using the
choice
you make from the
combo to specify the people you want to mail...
is 'People' a query that
includes a criteria reference to that control? If
not...
then how does that
work? How does 'Board of Directors' produce a list
of
addresses? (i.e.
what's the table structure that includes those
addresses?)


"SillySally" <[email protected]>
wrote
in
message
Thanks for taking an interest in my question- it's
driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box
field,
FindGroup, that allows an end-user to choose a
group. I
use a similar form to run mailing labels. For
example,
the end-user selects "Board of Directors" and the
report
creates mail labels for all People who are in
the "Board
of Directors" group.

So what I'm hoping to do with the email list is
loop
through all People with email addresses that also
belong
to the user specified group. Hope that
explanation
helps. I had found an article from ATTAC
Consulting
Group
titled "How to create your won input box forms and
pause
code for user input" which seems exactly what I
need.
It's long but I'll paste it in (see after ***) -
skip
it
if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get
information
or a
selection from a user that an a standard Input Box
isn't
designed to handle.
As an example, you may want to offer the user
only a
selection of one of two choices. Since there's no
way to
restrict what the user can enter into an input
box,
an
input box won't work well.

To get around this limitation you can design a
form
that
acts as psudo input box, opening the form to get
input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which
the
running function is in, and for which you need to
get
the
input from the user, dimension new variables which
will
to
hold the return values which the user selects or
enters
into your input form.The value of these variables
will
be "visible" to your running function after the
user
enters their selections. There's no need to make
these
variables global variables.

Add a new sub procedure to the same module as your
running
function. Your custom input box form will call
this
sub
procedure. The purpose of this sub procedure is
solely
to
accept the values from your input form as
parameters
and
to set the new module level variables equal to the
value
of the parameters.

Design your own "input box" form as a dialog box
form.
When a dialog box is opened, it will cause your
running
code to "pause" until the dialog is closed. (You
have to
specifically specify opening it in your running
function
as "acDialog".)

In the OnClose event of your input box form, now
add
a
call to the sub procedure you just wrote.
Specifying
as
parameter values, the values of the text boxes or
option
groups etc. from your form. This will send the
data
back
to your module when the dialog is closed.

You can also make your main code pause and wait
for
the
user's input and for non-dialog style forms by
using
code
like the following in you main procedure ( an "
_ "
means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub
procedure
to
notify your running function if the user clicked a
cancel
button rather than an OK button to end your
process.



-----Original Message-----
You're close. What do you mean by the parameter
field
on
GroupParamEmail...
a parameter you have to enter when the form
opens?
I
don't quite get how
you're choosing to specify the people you want to
mail...
could you go into
a bit more detail please.


"SillySally"
wrote
in
message
[email protected]...
Greetings-
I am trying to write a subprocess that will
set a
variable equal to an end-user selected
parameter
value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail",
acNormal, , , ,
acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is
FindGroup.
I'm
trying to find the group of people to send an
email
to.
I have the emailing code, but I'm having
problems
figuring out how to integrate this group
selection
parameter as the variable.

I believe I will need to add the subprocess for
the
group
selection to the OnClose event of
GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset ("SELECT
[EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Email
Group"


.



.



.



.


.
 
S

SillySally

Sorry, I had to wait to run it on my home system with
Outlook rather than at work with GroupWise.

Run-time error '2295':Unknown message recipient(s); the
message was not sent.

Debug stops at
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"

I figured out the problem. I had some Contacts associated
with a Group but the Contacts did not have an email
address. So the strTo had extra ;s in it:
(e-mail address removed); (e-mail address removed);;; jane@doenet

I put a GMemberEnd date on those Contacts and it worked!
However, there may be Contacts without email that are in
Groups. So I added to sql:
sql = "SELECT Contacts.EmailName FROM GroupMembers
INNER JOIN " + "Contacts ON GroupMembers.ContactID =
Contacts.ContactID " + "WHERE (((GroupMembers.GroupID)=" +
CStr(Me.FindGroup) + ") AND ((GroupMembers.GMemberEnd) Is
Null) AND ((Contacts.EmailName) Is Not Null));"

AND IT WORKED!!!! You totally and completely ROCK!
Thanks for writing code for me, but at least know that I
learned a lot! Thanks, Sal
-----Original Message-----
So which line is the compile error highlighting? And what's the text of the
error?


Hi. I'm good with calling the code from a command button
on GroupParamEmail, if I can get it to work! I think I'm
having pretty good luck, but at work we use GroupWise so
I can't really test it out. I did get to the point where
the code was trying to send the email, so that's a good
sign. I'll post after I get home to let you know. I'm
loving the sql statement- I could never figure out how to
have sql in vb. Thanks, Sal. This is what I'm working
with now:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
'Dim strGroup As String
'Dim strWhere As String
Dim sql As String
Dim db As Database
'Open GroupParamEmail
'DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog

sql = "SELECT Contacts.EmailName FROM GroupMembers
INNER JOIN " + "Contacts ON GroupMembers.ContactID =
Contacts.ContactID " + "WHERE (((GroupMembers.GroupID)="
+ CStr(Me.FindGroup) + ") AND ((GroupMembers.GMemberEnd)
Is Null));"
'strWhere = "[ContactID] = " & Nz([ContactID], 0)
'strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)
Set db = CurrentDb
Set rst = db.OpenRecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Email Group"
End Sub
-----Original Message-----
The CStr is just there to convert the (integer I think) value produced by
the combo into a string that can be written into the
SQL
statement. No Dims
necessary. Which form are you trying to run this from? It should be on the
same one as the choice of mail group.


"SillySally" <[email protected]> wrote
in
message
I have no idea you could do that with sql in vb code!

I put in CStr(Me.FindGroup) + ")
FindGroup is the combo box on GroupParam form. But I'm
getting an error message- Compile error: method or data
member not found. I'm not even sure what CStr is being
used for. Help says to use CStr to convert a number to a
string. Do I need to define it in the "Dim" section?

Here's what I have so far. I think I did the db section as
you suggested:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String
Dim strWhere As String
Dim sql As String
Dim db As Database
'Dim CStr As ?
'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail", acNormal, , , ,
acDialog


strWhere = "[ContactID] = " & Nz([ContactID], 0)
strGroup = Nz(DLookup("qryGroups", "GroupName",
strWhere), 0)
sql = "SELECT Contacts.EmailName FROM GroupMember
INNER JOIN " + "Contacts ON GroupMember.ContactID =
Contacts.ContactID " + "WHERE (((GroupMember.GroupID) =" +
CStr(Me.FindGroup) + ") AND ((GroupMember.GMemberEnd) Is
Null));"
Set db = CurrentDb
Set rst = db.OpenRecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group"
End Sub

Thanks, Sal
-----Original Message-----
In which case you just need to change your original code
to...

Dim rst As DAO.Recordset
Dim strTo As String
Dim sql As String
sql = "SELECT Contacts.EMailName FROM GroupMember INNER
JOIN " + _
"Contacts ON GroupMember.ContactID = Contacts.ContactID "
+ _
"WHERE (((GroupMember.GroupID)=" + CStr (Me.YourComboName)
+ _
") AND ((GroupMember.GMemberEnd) Is Null));"
Set rst = CurrentDb.OpenRecordset(sql)

Note... rather than using CurrentDB you're generally
better off doing... dim
db as database... set db=currentdb and then set
rst=db.openrecordset(sql)

With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , , strTo, "Email
Group "

....and that's providing that GroupID is the bound column
on your combo
(which it should be).

It's really just a case of building an SQL string that
gives you *any* list
of addresses.... and then replacing the key value in that
with a reference
to the control that you're using. You can drop a
breakpoint into the code
and copy the SQL variable out into a query window to see
what it is doing.


"SillySally" <[email protected]>
wrote
in
message
Hi. I set up GMemberStart and GMemberEnd (both date
fields) to specify the start and end dates in the Group
for the Contact. For example, a Group could have
started
01/05/05 but this particular Contact didn't start being
associated with the Group until 02/13/05. A real
example:
Board of Directors is an on-going group. Contacts
serve 2
years and then stop being on the Board. Rather than
setting up a new Group, we can just set the Contact's
GMemberEnd date and leave Group going. That way when I
want to send email to the Board, I tell the email code
(someday!) not to send email to the Contacts with a
value
in GMemberEnd.

GroupMemberID is the key of GroupMember table.
GroupMember is the "intermediary" table between Groups
and
Contacts.
Sample data: GroupMemberID, ContactID, GroupID,
GMemberStart and GMemberEnd

9, 95, 5, 01/01/02
10, 95, 6, 05/01/02

This means that ContactID = 95 is a memeber of 2 Groups
(Board of Directors, starting 01/01/02) and (Reading
piolot, starting 05/01/02). That also means that
ContactID = 95 has two GroupMemberIDs.

Did I put this together? Perhaps. The database has
evolved
(sort of) over a couple of years and is stuck together
with logic and spit. I do have a database designing
friend that helped in the beginning, but I give away
almost all credit for the good, and take ALL "credit"
for
the bad. Thanks, Sal

-----Original Message-----
OK. That looks good. It's certainly correct to have a
many-to-many
relationship from Contacts to Groups (although...
what's
going into the
GroupMember, GMemberStart and GMemberEnd fields in
GroupMember? Could you
just give me some sample data from that table. Did you
set the tables up by
the way?)


in
message
Demanding I can be ;-)
So, I suppose what you're saying is "code doesn't
just
happen". Rats!
I do appreciate your efforts to help me get this
working.
It's the "biggie" that will get my non-profit off
their
old system (Address Book- yikes!) and on to Access.
They
love their "groups" to segment the population.

Here's the process: I have a form (LabelsAndLists)
that
has a command button (EmailGroup) that kicks
off
the
emailing code. The code calls form GroupParamEmail
that
has an unbound combo box called FindGroup. Here's the
sql
for FindGroup: SELECT Groups.GroupID,
Groups.GroupName
FROM Groups
WHERE (((Groups.GroupEnd) Is Null));

Then magic happens! Somehow the code knows which
Group
the
user wants to email and which Contacts are in that
Group
and sends the email to them. I do see the problem.
It's
where "magic happens".

Here's the table structure
Contacts (my "main table", contains ContactID,
EmailName)
Groups (contains GroupID, GroupName, GroupStart,
GroupEnd)
GroupMember (contains GroupMember, ContactID,
GroupID,
GMemberStart, GMemberEnd)

I created qryGroups:
SELECT Contacts.ContactID, Contacts.EmailName,
Groups.GroupName
FROM Groups INNER JOIN (Contacts INNER JOIN
GroupMembers
ON Contacts.ContactID = GroupMembers.ContactID) ON
Groups.GroupID = GroupMembers.GroupID
WHERE (((GroupMembers.GMemberEnd) Is Null) AND
((Groups.GroupEnd) Is Null) AND
((Contacts.EmailName) Is
Not Null));
This gives me all Contacts in a Group (where both the
group itself and the Contact's involement in the
Group
are "active") that have an Email address.

Now here's the pitiful attempt. I thought
maybe
I
could
use (see below) strWhere and strGroup. But I still
don't
know what Set rst = CurrentDb.OpenRecordset (X) would
be.
Or how the user input from FindGroup interacts with
qryGroups- perhaps I would need FindGroup to equal
GroupName in strGroup. Here's the rest of the code:

Private Sub EmailGroup_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Dim strGroup As String

strWhere = "[ContactID] = " & Nz ([ContactID], 0)
strGroup = Nz(DLookup ("qryGroups", "GroupName",
strWhere), 0)

Set rst = CurrentDb.OpenRecordset("SELECT
[EmailName]
FROM Contacts WHERE [EmailName] Is Not Null AND
something
about group members...")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Group
Email Link"
End Sub

-----Original Message-----
I still don't get exactly what process you're
trying to
use. Is this right?

You click a button on a form which pops up the
GroupParamEmail form... on
that you choose the group you want to mail (in a
combo
that is also called
GroupParamEmail?)... and then, when you hit
OK,
you
want
the mail to be
sent?

If I have that wrong, then please let me know what
it
is
that you want to
happen in terms of picking options from forms etc
(feel
free to be
demanding, it can all be done)

Last thing... I don't see where you are using the
choice
you make from the
combo to specify the people you want to mail...
is 'People' a query that
includes a criteria reference to that control? If
not...
then how does that
work? How does 'Board of Directors' produce a list
of
addresses? (i.e.
what's the table structure that includes those
addresses?)


"SillySally"
wrote
in
message
Thanks for taking an interest in my
question-
it's
driving
me crazy.
I see that "parameter" is a bad description.

GroupParamEmail is simply an unbound combo box
field,
FindGroup, that allows an end-user to choose a
group. I
use a similar form to run mailing labels. For
example,
the end-user selects "Board of Directors"
and
the
report
creates mail labels for all People who are in
the "Board
of Directors" group.

So what I'm hoping to do with the email list is
loop
through all People with email addresses that also
belong
to the user specified group. Hope that
explanation
helps. I had found an article from ATTAC
Consulting
Group
titled "How to create your won input box forms and
pause
code for user input" which seems exactly
what
I
need.
It's long but I'll paste it in (see after ***) -
skip
it
if
too annoying ;-)
Thanks, Sal
***
In your application you may need to get
information
or a
selection from a user that an a standard Input Box
isn't
designed to handle.
As an example, you may want to offer the user
only a
selection of one of two choices. Since there's no
way to
restrict what the user can enter into an input
box,
an
input box won't work well.

To get around this limitation you can design a
form
that
acts as psudo input box, opening the form to get
input,
and then when closed, resuming your code.

Here's how:

In the declarations section of the module which
the
running function is in, and for which you need to
get
the
input from the user, dimension new variables which
will
to
hold the return values which the user
selects
or
enters
into your input form.The value of these variables
will
be "visible" to your running function after the
user
enters their selections. There's no need to make
these
variables global variables.

Add a new sub procedure to the same module
as
your
running
function. Your custom input box form will call
this
sub
procedure. The purpose of this sub procedure is
solely
to
accept the values from your input form as
parameters
and
to set the new module level variables equal to the
value
of the parameters.

Design your own "input box" form as a dialog box
form.
When a dialog box is opened, it will cause your
running
code to "pause" until the dialog is closed. (You
have to
specifically specify opening it in your running
function
as "acDialog".)

In the OnClose event of your input box form, now
add
a
call to the sub procedure you just wrote.
Specifying
as
parameter values, the values of the text boxes or
option
groups etc. from your form. This will send the
data
back
to your module when the dialog is closed.

You can also make your main code pause and wait
for
the
user's input and for non-dialog style forms by
using
code
like the following in you main procedure ( an "
_ "
means
the line continues on the next line show here):
DoCmd OpenForm "MyForm", acNormal

While SysCmd(acSysCmdGetObjectState, acForm, _
"My Form Name") = acObjStateOpen
DoEvents 'Do Nothing Wait for Closing
Wend

[Resume Code here]

You can also include a parameter in your sub
procedure
to
notify your running function if the user clicked a
cancel
button rather than an OK button to end your
process.



-----Original Message-----
You're close. What do you mean by the parameter
field
on
GroupParamEmail...
a parameter you have to enter when the form
opens?
I
don't quite get how
you're choosing to specify the people you want to
mail...
could you go into
a bit more detail please.


"SillySally"
wrote
in
message
news:180501c51083$59f6bdb0
[email protected]...
Greetings-
I am trying to write a subprocess that will
set a
variable equal to an end-user selected
parameter
value.

So far I have:
Dim strGroup As String

'Open GroupParamEmail
DoCmd.OpenForm "GroupParamEmail",
acNormal, , , ,
acDialog

That's it. Pitiful, I know.

The parameter field on GroupParamEmail is
FindGroup.
I'm
trying to find the group of people to
send
an
email
to.
I have the emailing code, but I'm having
problems
figuring out how to integrate this group
selection
parameter as the variable.

I believe I will need to add the subprocess for
the
group
selection to the OnClose event of
GroupParamEmail.

Any suggestions? Here's my emailing code:

Private Sub Email_Click()
Dim rst As DAO.Recordset
Dim strTo As String
Set rst = CurrentDb.OpenRecordset ("SELECT
[EmailName]
FROM People")
With rst
Do Until .EOF
strTo = strTo & ![EmailName] & ";"
.MoveNext
Loop
.Close
End With
strTo = Left(strTo, Len(strTo) - 1)
Set rst = Nothing
DoCmd.SendObject acSendNoObject, , , , ,
strTo, "Email
Group"


.



.



.



.



.


.
 

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