How to return information from a form?

L

Laurel

I have a little form that is opened by a couple of other forms, which allows
the user to mark the students in a class present or absent and the data is
saved in the database. This info is then used by the main form to retrieve
students. So in the main forms I have this sort of code.

DoCmd.OpenForm "frmStudentsPresent", acNormal, , , , acDialog,
is_classcode

ls_sql = "Select * from tblStudents Where class_code = '" &
[cboClass_Code] _
& "' AND Absent = False Order by First_Name, Last_Name"

Set irst_Students = CurrentDb.OpenRecordset(ls_sql)
ETC.

And when control returns to the main form, it proceeds with its work. I
would like to be able to put a CANCEL button on the little form, so that the
user can decide, after getting into the little window, that they don't want
the main window to proceed with its work (which is to create rows for each
of the present students). How can the main form know that the user clicked
CANCEL in the little window instead of OK? In other languages, there would
be the ablility to Close with Return, which would set a variable that the
main form could read. But I can't find such a thing in VB. Any
suggestions?

tia
las
 
A

Albert D. Kallal

I explain in good detail here two things:

1) how you can use a dialog form to RETURN VALUES

2) Note in the same code how a "cancel" is assumed.

So, in your case, if the user hits cancel, you can consider *leaving* the
form open..and assume that is a cancel.

Or, even perhaps set a public variable in that form, and then check this
value in the retuning code

http://www.members.shaw.ca/AlbertKallal/Dialog/Index.html
 
K

Ken Sheridan

First paste the following module into your database. It was originally
developed by Stuart McCall and myself and allows you to pass multiple
arguments via the OpenArgs mechanism, either as a literal tokenised list or
named arguments. In this case the last method is used.

''''module starts''''
Private Const OFFSET As Long = 127
Private Const ASSIGNOP As String = "=="

Function Arg(buffer, idx) As Variant

If IsNumeric(idx) Then
i& = InStr(1, buffer, Chr(idx + OFFSET - 1))
token$ = Chr(idx + OFFSET)
i& = InStr(i&, buffer, ASSIGNOP) + 2
Else
i& = InStr(1, buffer, idx) + Len(idx) + 2
token$ = Chr(Asc(Mid(buffer, InStr(1, buffer, idx) - 1, 1)) + 1)
End If
Arg = Mid(buffer, i&, InStr(i&, buffer, token$) - i&)

End Function

Function Argname(buffer, idx) As String

i& = InStr(1, buffer, Chr(idx + OFFSET - 1))
token$ = Chr(idx + OFFSET)
Argname = Mid(buffer, i& + 1, InStr(i&, buffer, ASSIGNOP) - (i& + 1))

End Function

Function ArgCount(buffer) As Long

ArgCount = Asc(Right(Chr(OFFSET) & buffer, 1)) - OFFSET

End Function

Sub AddArg(buffer, Argname, argval)

If Len(buffer & "") = 0 Then buffer = Chr(OFFSET)
If IsNumeric(Argname) Then Argname = ArgCount(buffer) + 1
buffer = buffer & Argname & ASSIGNOP & argval & Chr(Asc(Right(buffer,
1)) + 1)

End Sub

Sub AddArgList(buffer, ParamArray Tokens())

For i& = 0 To UBound(Tokens)
AddArg buffer, i& + 1, Tokens(i&)
Next

End Sub
''''module ends''''

In your calling forms modules move the code which creates the rows for each
of the students into a separate procedure in the form's module:

Public Sub DoStuff()

' your code goes here

End Sub

By declaring the procedure as Public this exposes it as a method of the
form, which can be called from outside the form while its open.

To open the frmStudentsPresent form you'll use this code which passes two
named arguments to the dialogue form:

Dim args As String

AddArg args, "ClassCode", is_classcode
AddArg args, "CallingForm", Me.Name

DoCmd.OpenForm "frmStudentsPresent", _
WindowMode:=acDialog, _
OpenArgs:=args

The frmStudentsPresent form's module will contain the following code along
with any other code you already have there. CmdCancel is the name of the
Cancel button.

''''module begins''''
Option Compare Database
Option Explicit

Dim blnCancelled As Boolean

Private Sub cmdCancel_Click()

blnCancelled = True
DoCmd.Close acForm, Me.Name

End Sub

Private Sub Form_Close()

Dim args As String

args = Me.OpenArgs

Me.Visible = False

If Not blnCancelled Then
Forms(Arg(args, "CallingForm")).DoStuff
End If

End Sub
''''module ends''''

The way it works is that if the Cancel button is clicked the module level
Boolean variable is set to True. The form's Close event procedure then
conditionally calls the DoStuff procdure in the calling form's module. It
identifies which form's module is the right one from the CallingForm named
argument passed to it.

Note that when you refer to the value of is_classcode in the
frmStudentsPresent form you now refer to it as the named ClassCode argument
by means of the Arg function like so:

Dim strClassCode As String

strClassCode = Arg(args, "ClassCode")

In case you are interested in using the module to pass arguments as a
literal list (you can't use a list to pass variables) rather than as named
arguments here's the opening blurb from a little application which
demonstrates its use:

"This application demonstrates how lists of values can be passed to a form
by means of the OpenArgs mechanism. Values can be passed individually as
named arguments:

Dim args As String

' add some named arguments
AddArg args, "First", "Apples"
AddArg args, "Second", "Pears"
AddArg args, "Third", "Bananas"

Or as an arguments list:

AddArgList args, "Oranges", "Peaches", "Grapefruit"

The list is then passed to the form with:

DoCmd.OpenForm "frmMyForm", OpenArgs:=args

In the form's module the values can be extracted like so:

Dim args As String, i As Integer

args = Me.OpenArgs

' get some named named arguments
Debug.Print Arg(args, "First")
Debug.Print Arg(args, "Second")
Debug.Print Arg(args, "Third")
' get some arguments by ordinal position
Debug.Print Arg(args, 4)
Debug.Print Arg(args, 5)
Debug.Print Arg(args, 6)
' list all arguments
For i = 1 To ArgCount(args)
Debug.Print Argname(args, i), Arg(args, i)
Next i
' get count of arguments
Debug.Print ArgCount(args)"

Ken Sheridan
Stafford, England

Laurel said:
I have a little form that is opened by a couple of other forms, which allows
the user to mark the students in a class present or absent and the data is
saved in the database. This info is then used by the main form to retrieve
students. So in the main forms I have this sort of code.

DoCmd.OpenForm "frmStudentsPresent", acNormal, , , , acDialog,
is_classcode

ls_sql = "Select * from tblStudents Where class_code = '" &
[cboClass_Code] _
& "' AND Absent = False Order by First_Name, Last_Name"

Set irst_Students = CurrentDb.OpenRecordset(ls_sql)
ETC.

And when control returns to the main form, it proceeds with its work. I
would like to be able to put a CANCEL button on the little form, so that the
user can decide, after getting into the little window, that they don't want
the main window to proceed with its work (which is to create rows for each
of the present students). How can the main form know that the user clicked
CANCEL in the little window instead of OK? In other languages, there would
be the ablility to Close with Return, which would set a variable that the
main form could read. But I can't find such a thing in VB. Any
suggestions?

tia
las
 
L

Laurel

Wow, thanks. Not just a solution, but a ton of technical info.

Ken Sheridan said:
First paste the following module into your database. It was originally
developed by Stuart McCall and myself and allows you to pass multiple
arguments via the OpenArgs mechanism, either as a literal tokenised list
or
named arguments. In this case the last method is used.

''''module starts''''
Private Const OFFSET As Long = 127
Private Const ASSIGNOP As String = "=="

Function Arg(buffer, idx) As Variant

If IsNumeric(idx) Then
i& = InStr(1, buffer, Chr(idx + OFFSET - 1))
token$ = Chr(idx + OFFSET)
i& = InStr(i&, buffer, ASSIGNOP) + 2
Else
i& = InStr(1, buffer, idx) + Len(idx) + 2
token$ = Chr(Asc(Mid(buffer, InStr(1, buffer, idx) - 1, 1)) + 1)
End If
Arg = Mid(buffer, i&, InStr(i&, buffer, token$) - i&)

End Function

Function Argname(buffer, idx) As String

i& = InStr(1, buffer, Chr(idx + OFFSET - 1))
token$ = Chr(idx + OFFSET)
Argname = Mid(buffer, i& + 1, InStr(i&, buffer, ASSIGNOP) - (i& + 1))

End Function

Function ArgCount(buffer) As Long

ArgCount = Asc(Right(Chr(OFFSET) & buffer, 1)) - OFFSET

End Function

Sub AddArg(buffer, Argname, argval)

If Len(buffer & "") = 0 Then buffer = Chr(OFFSET)
If IsNumeric(Argname) Then Argname = ArgCount(buffer) + 1
buffer = buffer & Argname & ASSIGNOP & argval & Chr(Asc(Right(buffer,
1)) + 1)

End Sub

Sub AddArgList(buffer, ParamArray Tokens())

For i& = 0 To UBound(Tokens)
AddArg buffer, i& + 1, Tokens(i&)
Next

End Sub
''''module ends''''

In your calling forms modules move the code which creates the rows for
each
of the students into a separate procedure in the form's module:

Public Sub DoStuff()

' your code goes here

End Sub

By declaring the procedure as Public this exposes it as a method of the
form, which can be called from outside the form while its open.

To open the frmStudentsPresent form you'll use this code which passes two
named arguments to the dialogue form:

Dim args As String

AddArg args, "ClassCode", is_classcode
AddArg args, "CallingForm", Me.Name

DoCmd.OpenForm "frmStudentsPresent", _
WindowMode:=acDialog, _
OpenArgs:=args

The frmStudentsPresent form's module will contain the following code along
with any other code you already have there. CmdCancel is the name of the
Cancel button.

''''module begins''''
Option Compare Database
Option Explicit

Dim blnCancelled As Boolean

Private Sub cmdCancel_Click()

blnCancelled = True
DoCmd.Close acForm, Me.Name

End Sub

Private Sub Form_Close()

Dim args As String

args = Me.OpenArgs

Me.Visible = False

If Not blnCancelled Then
Forms(Arg(args, "CallingForm")).DoStuff
End If

End Sub
''''module ends''''

The way it works is that if the Cancel button is clicked the module level
Boolean variable is set to True. The form's Close event procedure then
conditionally calls the DoStuff procdure in the calling form's module. It
identifies which form's module is the right one from the CallingForm named
argument passed to it.

Note that when you refer to the value of is_classcode in the
frmStudentsPresent form you now refer to it as the named ClassCode
argument
by means of the Arg function like so:

Dim strClassCode As String

strClassCode = Arg(args, "ClassCode")

In case you are interested in using the module to pass arguments as a
literal list (you can't use a list to pass variables) rather than as named
arguments here's the opening blurb from a little application which
demonstrates its use:

"This application demonstrates how lists of values can be passed to a form
by means of the OpenArgs mechanism. Values can be passed individually as
named arguments:

Dim args As String

' add some named arguments
AddArg args, "First", "Apples"
AddArg args, "Second", "Pears"
AddArg args, "Third", "Bananas"

Or as an arguments list:

AddArgList args, "Oranges", "Peaches", "Grapefruit"

The list is then passed to the form with:

DoCmd.OpenForm "frmMyForm", OpenArgs:=args

In the form's module the values can be extracted like so:

Dim args As String, i As Integer

args = Me.OpenArgs

' get some named named arguments
Debug.Print Arg(args, "First")
Debug.Print Arg(args, "Second")
Debug.Print Arg(args, "Third")
' get some arguments by ordinal position
Debug.Print Arg(args, 4)
Debug.Print Arg(args, 5)
Debug.Print Arg(args, 6)
' list all arguments
For i = 1 To ArgCount(args)
Debug.Print Argname(args, i), Arg(args, i)
Next i
' get count of arguments
Debug.Print ArgCount(args)"

Ken Sheridan
Stafford, England

Laurel said:
I have a little form that is opened by a couple of other forms, which
allows
the user to mark the students in a class present or absent and the data
is
saved in the database. This info is then used by the main form to
retrieve
students. So in the main forms I have this sort of code.

DoCmd.OpenForm "frmStudentsPresent", acNormal, , , , acDialog,
is_classcode

ls_sql = "Select * from tblStudents Where class_code = '" &
[cboClass_Code] _
& "' AND Absent = False Order by First_Name, Last_Name"

Set irst_Students = CurrentDb.OpenRecordset(ls_sql)
ETC.

And when control returns to the main form, it proceeds with its work. I
would like to be able to put a CANCEL button on the little form, so that
the
user can decide, after getting into the little window, that they don't
want
the main window to proceed with its work (which is to create rows for
each
of the present students). How can the main form know that the user
clicked
CANCEL in the little window instead of OK? In other languages, there
would
be the ablility to Close with Return, which would set a variable that the
main form could read. But I can't find such a thing in VB. Any
suggestions?

tia
las
 

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

Top