Jump to random records

T

Teddy

I have a form named frmForm1 which is linked to two tables called tblTable1
and tblTable2; tblTable2 is linked to the subform while tblTable1 is linked
to the main form. I have a command button on the form, when I click it I
would like for it to jump to and/or select one random record from tblTable1
and display it in the main form field in frmForm1 while simultaneously
jumping to and/or selecting 3 random records from tblTable2 and displaying
them in the subform field in frmForm1. The tables are not linked. Do you
know what code would enable me to do this?
 
G

GeoffG

Teddy said:
I have a form named frmForm1 which is linked to two tables
called tblTable1
and tblTable2; tblTable2 is linked to the subform while
tblTable1 is linked
to the main form. I have a command button on the form,
when I click it I
would like for it to jump to and/or select one random
record from tblTable1
and display it in the main form field in frmForm1 while
simultaneously
jumping to and/or selecting 3 random records from
tblTable2 and displaying
them in the subform field in frmForm1. The tables are not
linked. Do you
know what code would enable me to do this?

This is possible.
I had to do it using the following.

Put two subform controls on one unbound form.
The first subform control should contain the form for
tblTable1 and the second subform control should contain the
form for tblTable2.
The name of the subform control is not necessarily the same
as the name of the form in the subform control. Select the
subform control, open its properties sheet, and examine the
Name property. Ensure you get the names of the subform
controls in the constants at the top of the code.

You need a primary key field in each table. I used
Autonumber fields with the field names ID1 and ID2.

I used SQL statements as the recordsources of the forms for
tables 1 and 2. Its easy to adjust SQL statements to select
just one record in subform control 1 and three records in
subform control 2.

Below is the code I used in the module behind the unbound
form.
Copy and paste the code into an unbound form.
Adjust the constants at the top to reflect your solution.

Option Compare Database
Option Explicit

' Requires reference to Microsoft DAO
' (In VBA editor, Tools > References > Microsoft DAO.)

' Assumes:
' Main form is unbound.
' Main form contains 2 subform controls.


' CONSTANTS

' Store names of subform controls
' containing 1st and 2nd subforms:
Private Const mstrcSFrm1 As String = "SubFrmCtrlTable1"
Private Const mstrcSFrm2 As String = "SubFrmCtrlTable2"

' Store RecordSource SQL statements
' for 1st and 2nd subforms:
Private Const mstrcSQL1 As String = "SELECT tblTable1.* " _
& "FROM tblTable1;"
Private Const mstrcSQL2 As String = "SELECT tblTable2.* " _
& "FROM tblTable2;"

' Store names of primary key fields
' for 1st and 2nd tables:
Private Const mstrcPKFieldName1 As String = "ID1"
Private Const mstrcPKFieldName2 As String = "ID2"


Private Sub cmdSelect_Click()

Dim objSF1 As Access.SubForm
Dim objRS1 As DAO.Recordset

Dim objSF2 As Access.SubForm
Dim objRS2 As DAO.Recordset

Dim strFirstBookMark1 As String
Dim strFirstBookMark2 As String

' To store primary keys:
Dim lngPK1 As Long
Dim lngPK2a As Long
Dim lngPK2b As Long
Dim lngPK2c As Long

Dim lngRecordCount1 As Long
Dim lngRecordCount2 As Long

Dim lngRecord1 As Long
Dim lngRecord2a As Long
Dim lngRecord2b As Long
Dim lngRecord2c As Long

Dim strSQL As String

On Error GoTo Error_cmdSelect_Click

' PROCESS SUBFORM 1:

Set objSF1 = Me.Controls(mstrcSFrm1)
objSF1.Form.RecordSource = mstrcSQL1
Set objRS1 = objSF1.Form.Recordset
With objRS1
If .RecordCount > 0 Then

' After the form is opened, the first
' record may not be the current record,
' therefore:
.MoveFirst
strFirstBookMark1 = .Bookmark

' Get accurate record count:
.MoveLast
lngRecordCount1 = .RecordCount
.MoveFirst

' Calculate and move to random
' record number:
lngRecord1 = Int(lngRecordCount1 * Rnd)
.Move lngRecord1, strFirstBookMark1

' Get primary key of current record:
lngPK1 = .Fields(mstrcPKFieldName1).Value

' Show only the current record:
strSQL = Left(mstrcSQL1, Len(mstrcSQL1) - 1)
strSQL = strSQL _
& " WHERE " & mstrcPKFieldName1 _
& "=" & lngPK1 & ";"
objSF1.Form.RecordSource = strSQL

Else
MsgBox "Cannot move in main table. " _
& "No Records."
End If
End With

' PROCESS SUBFORM 2:

Set objSF2 = Me.Controls(mstrcSFrm2)
objSF2.Form.RecordSource = mstrcSQL2
Set objRS2 = objSF2.Form.Recordset
With objRS2
If .RecordCount > 0 Then

' After the form is opened, the first
' record may not be the current record,
' therefore:
.MoveFirst
strFirstBookMark2 = .Bookmark

' Get accurate record count:
.MoveLast
lngRecordCount2 = .RecordCount
.MoveFirst


' Calculate and move to 1st random
' record number:
lngRecord2a = Int(lngRecordCount2 * Rnd)
.Move lngRecord2a, strFirstBookMark2

' Get primary key of current record:
lngPK2a = .Fields(mstrcPKFieldName2).Value


' Calculate and move to 2nd random
' record number:
lngRecord2b = Int(lngRecordCount2 * Rnd)
.Move lngRecord2b, strFirstBookMark2

' Get primary key of current record:
lngPK2b = .Fields(mstrcPKFieldName2).Value


' Calculate and move to 3rd random
' record number:
lngRecord2c = Int(lngRecordCount2 * Rnd)
.Move lngRecord2c, strFirstBookMark2

' Get primary key of current record:
lngPK2c = .Fields(mstrcPKFieldName2).Value


' Show only the current record:
strSQL = Left(mstrcSQL2, Len(mstrcSQL2) - 1)
strSQL = strSQL _
& " WHERE " & mstrcPKFieldName2 _
& " IN (" & lngPK2a _
& ", " & lngPK2b _
& ", " & lngPK2c & ");"
objSF2.Form.RecordSource = strSQL

Else
MsgBox "Cannot move in sub-table. " _
& "No Records."
End If
End With

Exit_cmdSelect_Click:

Set objRS2 = Nothing
Set objSF2 = Nothing

Set objRS1 = Nothing
Set objSF1 = Nothing
Exit Sub

Error_cmdSelect_Click:

MsgBox "Error No: " & Err.Number _
& vbNewLine _
& Err.Description, _
vbOKOnly + vbExclamation, _
"Error Information"

Resume Exit_cmdSelect_Click

End Sub

Private Sub cmdShowAll_Click()

Dim objSF1 As Access.SubForm
Dim objSF2 As Access.SubForm

Set objSF1 = Me.Controls(mstrcSFrm1)
Set objSF2 = Me.Controls(mstrcSFrm2)

objSF1.Form.RecordSource = mstrcSQL1
objSF2.Form.RecordSource = mstrcSQL2

Exit_cmdShowAll_Click:

Set objSF1 = Nothing
Set objSF2 = Nothing
Exit Sub

Error_cmdShowAll_Click:

MsgBox "Error No: " & Err.Number _
& vbNewLine _
& Err.Description, _
vbOKOnly + vbExclamation, _
"Error Information"
Resume Exit_cmdShowAll_Click:

End Sub

Private Sub Form_Load()

Dim objSF1 As Access.SubForm
Dim objSF2 As Access.SubForm

' Put SQL statements into RecordSource
' property of forms in SubForm controls.

Set objSF1 = Me.Controls(mstrcSFrm1)
objSF1.Form.RecordSource = mstrcSQL1

Set objSF2 = Me.Controls(mstrcSFrm2)
objSF2.Form.RecordSource = mstrcSQL2

Exit_Form_Load:

Set objSF2 = Nothing
Set objSF1 = Nothing
Exit Sub

Error_Form_Load:

MsgBox "Error No: " & Err.Number _
& vbNewLine _
& "Error Description:" & vbNewLine _
& Err.Description, vbOKOnly + vbExclamation, _
"Error Information"
Resume Exit_Form_Load

End Sub

Private Sub Form_Open(Cancel As Integer)

Randomize

End Sub


Geoff
 
T

Teddy

Holy Moley Geoff, this is absolutely amazing! Thank you I am very excited.
I am going to work with the instructions you gave me and then let you know
how it turns out. Thank you so so so much!
 
G

GeoffG

It's occurred to me that, if there are fewer than 4 records
in Table 2, then there is no point in randomly selecting 3
records.

See the 3 marked code revisions below
(which apply to SubForm2):


' PROCESS SUBFORM 2:

Set objSF2 = Me.Controls(mstrcSFrm2)
objSF2.Form.RecordSource = mstrcSQL2
Set objRS2 = objSF2.Form.Recordset
With objRS2

'CHANGE STARTS:
' Check for more than 3 records:
If .RecordCount > 3 Then
'CHANGE ENDS.

' After the form is opened, the first
' record may not be the current record,
' therefore:
.MoveFirst
strFirstBookMark2 = .Bookmark

' Get accurate record count:
.MoveLast
lngRecordCount2 = .RecordCount
.MoveFirst


' Calculate and move to 1st random
' record number:
lngRecord2a = Int(lngRecordCount2 * Rnd)
.Move lngRecord2a, strFirstBookMark2

' Get primary key of 1st record:
lngPK2a = .Fields(mstrcPKFieldName2).Value



' Calculate 2nd random record number:
lngRecord2b = Int(lngRecordCount2 * Rnd)

' Move to 2nd record:
.Move lngRecord2b, strFirstBookMark2

' Get primary key of 2nd record:
lngPK2b = .Fields(mstrcPKFieldName2).Value



' Calculate 3rd random record number:
lngRecord2c = Int(lngRecordCount2 * Rnd)

' Move to 3rd record:
.Move lngRecord2c, strFirstBookMark2

' Get primary key of 3rd record:
lngPK2c = .Fields(mstrcPKFieldName2).Value


'CHANGE STARTS:
' Show only the 3 randomly-selected
' records:
'CHANGE ENDS.
strSQL = Left(mstrcSQL2, Len(mstrcSQL2) - 1)
strSQL = strSQL _
& " WHERE " & mstrcPKFieldName2 _
& " IN (" & lngPK2a _
& ", " & lngPK2b _
& ", " & lngPK2c & ");"
objSF2.Form.RecordSource = strSQL

Else
'CHANGE STARTS:
MsgBox "There are fewer than 4 records " _
& "in Table 2."
'CHANGE ENDS.
End If
End With


Geoff
 
T

Teddy

Hi Geoff,

Thanks for the tip. I have multiple records in both tables but if that
changes your modifications will definitely come in handy. I am writing
because I need help implementing your instructions from the first post.

Below are the steps I took to implement them; however I seem to have made an
error /done something wrong as it is not working properly. I am getting
these error messages

Error1: Occurs when I open the form
------------------------------------------------------------------------------
Microsoft Visual Basic: Compile error: Variable not defined

'mstrcSQL1' is highlighted in this line of code

objSF1.Form.RecordSource = mstrcSQL1

Error2: Occurs after I click OK to 1st error message, close visual basic and
then click the command button on the for
-------------------------------------------------------------------------------
Compile Error: Invalid attribute in Sub or Function and 'Private Const' is
highlighted from this line of code

Private Const mstrcSFrm1 As String = "SubFrmCtrlTable1"

--------------------------------------------------------------------------------
These are the steps I took to implement the instructions.
(Assume I already have tblTable1 and tblTable2, both of which have
Autonumber fields ID1 and ID2)

1. Forms / Form Wizard / tblTable1 / OK / Tablefield1 / > / Next / Columnar
/ Next / Standard / Next / what title do you want for your form?
SubFrmCtrlTable1 / Finish

2. Forms / Form Wizard / tblTable2 / OK / Tablefield2 / > / Next / Columnar
/ Next / Standard / Next / what title do you want for your form?
SubFrmCtrlTable2 / Finish

3. Forms / New / Design view / OK / toolbox / subform subreport / subform
wizard / SubFrmCtrlTable1 / next / what name would you like for your subform?
mstrcSFrm1 / Finish

4. Forms / New / Design view / OK / toolbox / subform subreport / subform
wizard / SubFrmCtrlTable2 / next / what name would you like for your subform?
mstrcSFrm2 / Finish

5. mstrcSFrm1 / properties / record source / mstrcSQL1 / close properties

6. mstrcSFrm2 / properties / record source / mstrcSQL2 / close properties

7. command button / command button wizard / cancel / command button
properties / Event / on click / code builder / paste in the code below.

Option Compare Database
Option Explicit

' Requires reference to Microsoft DAO
' (In VBA editor, Tools > References > Microsoft DAO.)

' Assumes:
' Main form is unbound.
' Main form contains 2 subform controls.


' CONSTANTS

' Store names of subform controls
' containing 1st and 2nd subforms:
Private Const mstrcSFrm1 As String = "SubFrmCtrlTable1"
Private Const mstrcSFrm2 As String = "SubFrmCtrlTable2"

' Store RecordSource SQL statements
' for 1st and 2nd subforms:
Private Const mstrcSQL1 As String = "SELECT tblTable1.* " _
& "FROM tblTable1;"
Private Const mstrcSQL2 As String = "SELECT tblTable2.* " _
& "FROM tblTable2;"

' Store names of primary key fields
' for 1st and 2nd tables:
Private Const mstrcPKFieldName1 As String = "ID1"
Private Const mstrcPKFieldName2 As String = "ID2"


Private Sub cmdSelect_Click()

Dim objSF1 As Access.SubForm
Dim objRS1 As DAO.Recordset

Dim objSF2 As Access.SubForm
Dim objRS2 As DAO.Recordset

Dim strFirstBookMark1 As String
Dim strFirstBookMark2 As String

' To store primary keys:
Dim lngPK1 As Long
Dim lngPK2a As Long
Dim lngPK2b As Long
Dim lngPK2c As Long

Dim lngRecordCount1 As Long
Dim lngRecordCount2 As Long

Dim lngRecord1 As Long
Dim lngRecord2a As Long
Dim lngRecord2b As Long
Dim lngRecord2c As Long

Dim strSQL As String

On Error GoTo Error_cmdSelect_Click

' PROCESS SUBFORM 1:

Set objSF1 = Me.Controls(mstrcSFrm1)
objSF1.Form.RecordSource = mstrcSQL1
Set objRS1 = objSF1.Form.Recordset
With objRS1
If .RecordCount > 0 Then

' After the form is opened, the first
' record may not be the current record,
' therefore:
..MoveFirst
strFirstBookMark1 = .Bookmark

' Get accurate record count:
..MoveLast
lngRecordCount1 = .RecordCount
..MoveFirst

' Calculate and move to random
' record number:
lngRecord1 = Int(lngRecordCount1 * Rnd)
..Move lngRecord1, strFirstBookMark1

' Get primary key of current record:
lngPK1 = .Fields(mstrcPKFieldName1).Value

' Show only the current record:
strSQL = Left(mstrcSQL1, Len(mstrcSQL1) - 1)
strSQL = strSQL _
& " WHERE " & mstrcPKFieldName1 _
& "=" & lngPK1 & ";"
objSF1.Form.RecordSource = strSQL

Else
MsgBox "Cannot move in main table. " _
& "No Records."
End If
End With

' PROCESS SUBFORM 2:

Set objSF2 = Me.Controls(mstrcSFrm2)
objSF2.Form.RecordSource = mstrcSQL2
Set objRS2 = objSF2.Form.Recordset
With objRS2
If .RecordCount > 0 Then

'CHANGE STARTS:
' Check for more than 3 records:
If .RecordCount > 3 Then
'CHANGE ENDS.

' After the form is opened, the first
' record may not be the current record,
' therefore:
..MoveFirst
strFirstBookMark2 = .Bookmark

' Get accurate record count:
..MoveLast
lngRecordCount2 = .RecordCount
..MoveFirst


' Calculate and move to 1st random
' record number:
lngRecord2a = Int(lngRecordCount2 * Rnd)
..Move lngRecord2a, strFirstBookMark2

' Get primary key of 1st record:
lngPK2a = .Fields(mstrcPKFieldName2).Value

' Calculate and move to 2nd random
' record number:
lngRecord2b = Int(lngRecordCount2 * Rnd)

' Move to 2nd record:
..Move lngRecord2b, strFirstBookMark2

' Get primary key of current record:
lngPK2b = .Fields(mstrcPKFieldName2).Value

' Calculate 3rd random record number:
lngRecord2c = Int(lngRecordCount2 * Rnd)

' Move to 3rd record:
..Move lngRecord2c, strFirstBookMark2


' Get primary key of 3rd record:
lngPK2c = .Fields(mstrcPKFieldName2).Value

'CHANGE STARTS:
' Show only the 3 randomly-selected
' records:
'CHANGE ENDS.
strSQL = Left(mstrcSQL2, Len(mstrcSQL2) - 1)
strSQL = strSQL _
& " WHERE " & mstrcPKFieldName2 _
& " IN (" & lngPK2a _
& ", " & lngPK2b _
& ", " & lngPK2c & ");"
objSF2.Form.RecordSource = strSQL

Else
'CHANGE STARTS:
MsgBox "There are fewer than 4 records " _
& "in Table 2."
'CHANGE ENDS.
End If
End With

' Show only the current record:
strSQL = Left(mstrcSQL2, Len(mstrcSQL2) - 1)
strSQL = strSQL _
& " WHERE " & mstrcPKFieldName2 _
& " IN (" & lngPK2a _
& ", " & lngPK2b _
& ", " & lngPK2c & ");"
objSF2.Form.RecordSource = strSQL

Else
MsgBox "Cannot move in sub-table. " _
& "No Records."
End If
End With

Exit_cmdSelect_Click:

Set objRS2 = Nothing
Set objSF2 = Nothing

Set objRS1 = Nothing
Set objSF1 = Nothing
Exit Sub

Error_cmdSelect_Click:

MsgBox "Error No: " & Err.Number _
& vbNewLine _
& Err.Description, _
vbOKOnly + vbExclamation, _
"Error Information"

Resume Exit_cmdSelect_Click

End Sub

Private Sub cmdShowAll_Click()

Dim objSF1 As Access.SubForm
Dim objSF2 As Access.SubForm

Set objSF1 = Me.Controls(mstrcSFrm1)
Set objSF2 = Me.Controls(mstrcSFrm2)

objSF1.Form.RecordSource = mstrcSQL1
objSF2.Form.RecordSource = mstrcSQL2

Exit_cmdShowAll_Click:

Set objSF1 = Nothing
Set objSF2 = Nothing
Exit Sub

Error_cmdShowAll_Click:

MsgBox "Error No: " & Err.Number _
& vbNewLine _
& Err.Description, _
vbOKOnly + vbExclamation, _
"Error Information"
Resume Exit_cmdShowAll_Click:

End Sub

Private Sub Form_Load()

Dim objSF1 As Access.SubForm
Dim objSF2 As Access.SubForm

' Put SQL statements into RecordSource
' property of forms in SubForm controls.

Set objSF1 = Me.Controls(mstrcSFrm1)
objSF1.Form.RecordSource = mstrcSQL1

Set objSF2 = Me.Controls(mstrcSFrm2)
objSF2.Form.RecordSource = mstrcSQL2

Exit_Form_Load:

Set objSF2 = Nothing
Set objSF1 = Nothing
Exit Sub

Error_Form_Load:

MsgBox "Error No: " & Err.Number _
& vbNewLine _
& "Error Description:" & vbNewLine _
& Err.Description, vbOKOnly + vbExclamation, _
"Error Information"
Resume Exit_Form_Load

End Sub

Private Sub Form_Open(Cancel As Integer)

Randomize

End Sub

Any input is greatly appreciated. Thank you.
 
G

GeoffG

Hi Teddy,

Comments below.


COMMENT 1
Error1: Occurs when I open the form
------------------------------------------------------------------------------
Microsoft Visual Basic: Compile error: Variable not
defined

'mstrcSQL1' is highlighted in this line of code

objSF1.Form.RecordSource = mstrcSQL1

mstrcSQL1 is a constant (despite the error message telling
you that it is a variable). The constant is defined at the
top of the module in the line:

Private Const mstrcSQL1 As String = "SELECT tblTable1.* " _
& "FROM tblTable1;"

The leading "m" (in mstrcSQL1) means that the constant has
module-wide scope. It will be declared in the module's
general declarations section (at the top of the module).
This give you the clue as to where to look for it.

In fact, if you click on mstrcSQL1 in the above line and
press Shift-F2, it should take you to where the declaration
has been made. (See "Code Window Navigation Keys" in Help
for more keyboard shortcuts.)

The fact that you're getting the error message suggests that
you've either omitted the above line or not entered the
constant name "mstrcSQL1" correctly.

FYI, other clues are:
1. The "str" (in mstrcSQL1) means it's a string constant.
2. The "c" after "str" means it's a constant (as opposed to
a variable). (A variable would not have the "c".)


COMMENT 2
Error2: Occurs after I click OK to 1st error message,
close visual basic and
then click the command button on the form
-------------------------------------------------------------------------------
Compile Error: Invalid attribute in Sub or Function and
'Private Const' is
highlighted from this line of code

Private Const mstrcSFrm1 As String = "SubFrmCtrlTable1"

I declared the above constant in the general declarations
section at the top of the module.

In the general declarations section it is acceptable to use
the word "Private" to declare constants and variables with
module-wide scope. They are then private to the module and
can be seen by all subprocedures in the module.

However, it is not acceptable to use the word "Private"
inside a subprocedure or function procedure. If you want to
declare a constant in a subprocedure, omit the word
"Private" altogether. The constant will then only be seen
inside that subprocedure.


COMMENT 3
--------------------------------------------------------------------------------
These are the steps I took to implement the instructions.
(Assume I already have tblTable1 and tblTable2, both of
which have
Autonumber fields ID1 and ID2)

1. Forms / Form Wizard / tblTable1 / OK / Tablefield1 / >
/ Next / Columnar
/ Next / Standard / Next / what title do you want for your
form?
SubFrmCtrlTable1 / Finish

Do the above steps give the form the name
"SubFrmCtrlTable1"? If so, that was not my intention. The
above form should have been named "frmTable1". The database
window or Navigation Pane should show the name of the form
as "frmTable1".

I used the name "SubFrmCtrlTable1" for the subform control
on Form1 that contained "frmTable1". See COMMENT 4 below
for how I did this.


COMMENT 4
2. Forms / Form Wizard / tblTable2 / OK / Tablefield2 / >
/ Next / Columnar
/ Next / Standard / Next / what title do you want for your
form?
SubFrmCtrlTable2 / Finish

3. Forms / New / Design view / OK / toolbox / subform
subreport / subform
wizard / SubFrmCtrlTable1 / next / what name would you
like for your subform?
mstrcSFrm1 / Finish

4. Forms / New / Design view / OK / toolbox / subform
subreport / subform
wizard / SubFrmCtrlTable2 / next / what name would you
like for your subform?
mstrcSFrm2 / Finish

This is what I did:

I created three forms with the following names:
Form1
frmTable1
frmTable2

As Form1 was an unbound form, I did not use the Forms wizard
to create it. In form design view, I simply created a new
form with a large area, ready to receive other controls.

I used the toolbox to create two command buttons on Form1,
named "cmdSelect" and "cmdShowAll".

Form1 also contained two subform controls.
However, I did not create the subform controls using the
toolbox.

I did this instead:

1. With Form1 open in design view, I dragged the form
"frmTable1" from the database window to the design area of
Form1. If you are using Access 2007, I imagine you drag
"frmTable1" from the Navigation pane.

2. This automatically created the subform control on Form1,
with "frmTable1" in it.

3. I selected the subform control. (This can be fiddly so
be sure you only select the subform control. I hold the
mouse down on the design grid just above the subform control
and move the mouse downwards just on to the subform control.
Four handles appear around the control and one handle
appears on its label, if it has one.)

4. I opened the subform control's property sheet by
clicking the Properties toolbar button. In the Properties
sheet, I clicked in the Name property and entered
"SubFrmCtrlTable1".

5. Similarly, I dragged "frmTable2" to the design area of
Form1. I gave the resulting subform control the name
"SubFrmCtrlTable2".


COMMENT 5
5. mstrcSFrm1 / properties / record source / mstrcSQL1 /
close properties

6. mstrcSFrm2 / properties / record source / mstrcSQL2 /
close properties

I'm not sure what you've done here.
The record source of "frmTable1" should be "Table1".
The record source of "frmTable2" should be "Table2".
To check this, open each form in turn in design view.
Open the property sheet for the form. (To do this in my
version of Access, I double-click the black-square tablet in
the top, left-hand corner of the design window.) In the
property sheet, click in the RecordSource property and use
the drop-down arrow on the right to select the appropriate
table for the form (as shown above).


COMMENT 6
7. command button / command button wizard / cancel /
command button
properties / Event / on click / code builder / paste in
the code below.

That seems right.
I imagine you ended up with the code I posted for the click
event procedure of the command buttons.


COMMENT 7

I've not looked through the code below to see if you have
changed it. Basically, all the code I posted before should
appear in the code module behind Form1. If you have used
the names I have for the tables, fields in the tables,
forms, and controls on the forms, then the code should run
without modification.

Geoff
 
T

Teddy

Hi Geoff,

You are incredible! I have studied your instructions closely and learned a
handful of Access skills that I did not already have. Thank you immensely.

I corrected my mistakes and got two additional errors. They are as follows.

When I open Form1 from the database window I get a Run-time error ‘13’: Type
mismatch error message text box with the option to Debug.

I click Debug

This line of code ‘Set objSF1 = Me.Controls(mstrcSFrm1)’ is highlighted.

I close Visual Basic and click ‘cmdSelect’ on Form1 (to see if it works) and
I get the following message in a text box.

‘Error Information: Error No: 13 Type mismatch’

Then I click OK and the error text box disappears

I return to the form and Click ‘cmdShowAll’

Visual basic opens up and this line of code ‘Set objSF1 =
Me.Controls(mstrcSFrm1)’ is highlighted again.

Below is the code I am using. If you want to help with the above issues
that’s fantastic; if not I understand. I know I have asked you a lot of
questions so please don’t feel obligated. But if you are interested in
answering the question I’d love to know. Thanks again for your help.



Option Compare Database
Option Explicit

' Requires reference to Microsoft DAO
' (In VBA editor, Tools > References > Microsoft DAO.)

' Assumes:
' Main form is unbound.
' Main form contains 2 subform controls.


' CONSTANTS

' Store names of subform controls
' containing 1st and 2nd subforms:
Private Const mstrcSFrm1 As String = "SubFrmCtrlTable1"
Private Const mstrcSFrm2 As String = "SubFrmCtrlTable2"

' Store RecordSource SQL statements
' for 1st and 2nd subforms:
Private Const mstrcSQL1 As String = "SELECT tblTable1.* " _
& "FROM tblTable1;"
Private Const mstrcSQL2 As String = "SELECT tblTable2.* " _
& "FROM tblTable2;"

' Store names of primary key fields
' for 1st and 2nd tables:
Private Const mstrcPKFieldName1 As String = "ID1"
Private Const mstrcPKFieldName2 As String = "ID2"


Private Sub cmdSelect_Click()

Dim objSF1 As Access.SubForm
Dim objRS1 As DAO.Recordset

Dim objSF2 As Access.SubForm
Dim objRS2 As DAO.Recordset

Dim strFirstBookMark1 As String
Dim strFirstBookMark2 As String

' To store primary keys:
Dim lngPK1 As Long
Dim lngPK2a As Long
Dim lngPK2b As Long
Dim lngPK2c As Long

Dim lngRecordCount1 As Long
Dim lngRecordCount2 As Long

Dim lngRecord1 As Long
Dim lngRecord2a As Long
Dim lngRecord2b As Long
Dim lngRecord2c As Long

Dim strSQL As String

On Error GoTo Error_cmdSelect_Click

' PROCESS SUBFORM 1:

Set objSF1 = Me.Controls(mstrcSFrm1)
objSF1.Form.RecordSource = mstrcSQL1
Set objRS1 = objSF1.Form.Recordset
With objRS1
If .RecordCount > 0 Then

' After the form is opened, the first
' record may not be the current record,
' therefore:
..MoveFirst
strFirstBookMark1 = .Bookmark

' Get accurate record count:
..MoveLast
lngRecordCount1 = .RecordCount
..MoveFirst

' Calculate and move to random
' record number:
lngRecord1 = Int(lngRecordCount1 * Rnd)
..Move lngRecord1, strFirstBookMark1

' Get primary key of current record:
lngPK1 = .Fields(mstrcPKFieldName1).Value

' Show only the current record:
strSQL = Left(mstrcSQL1, Len(mstrcSQL1) - 1)
strSQL = strSQL _
& " WHERE " & mstrcPKFieldName1 _
& "=" & lngPK1 & ";"
objSF1.Form.RecordSource = strSQL

Else
MsgBox "Cannot move in main table. " _
& "No Records."
End If
End With

' PROCESS SUBFORM 2:

Set objSF2 = Me.Controls(mstrcSFrm2)
objSF2.Form.RecordSource = mstrcSQL2
Set objRS2 = objSF2.Form.Recordset
With objRS2
If .RecordCount > 0 Then

'CHANGE STARTS:
' Check for more than 3 records:
If .RecordCount > 3 Then
'CHANGE ENDS.

' After the form is opened, the first
' record may not be the current record,
' therefore:
..MoveFirst
strFirstBookMark2 = .Bookmark

' Get accurate record count:
..MoveLast
lngRecordCount2 = .RecordCount
..MoveFirst


' Calculate and move to 1st random
' record number:
lngRecord2a = Int(lngRecordCount2 * Rnd)
..Move lngRecord2a, strFirstBookMark2

' Get primary key of 1st record:
lngPK2a = .Fields(mstrcPKFieldName2).Value

' Calculate and move to 2nd random
' record number:
lngRecord2b = Int(lngRecordCount2 * Rnd)

' Move to 2nd record:
..Move lngRecord2b, strFirstBookMark2

' Get primary key of current record:
lngPK2b = .Fields(mstrcPKFieldName2).Value

' Calculate 3rd random record number:
lngRecord2c = Int(lngRecordCount2 * Rnd)

' Move to 3rd record:
..Move lngRecord2c, strFirstBookMark2


' Get primary key of 3rd record:
lngPK2c = .Fields(mstrcPKFieldName2).Value

'CHANGE STARTS:
' Show only the 3 randomly-selected
' records:
'CHANGE ENDS.
strSQL = Left(mstrcSQL2, Len(mstrcSQL2) - 1)
strSQL = strSQL _
& " WHERE " & mstrcPKFieldName2 _
& " IN (" & lngPK2a _
& ", " & lngPK2b _
& ", " & lngPK2c & ");"
objSF2.Form.RecordSource = strSQL

Else
'CHANGE STARTS:
MsgBox "There are fewer than 4 records " _
& "in Table 2."
'CHANGE ENDS.
End If


' Show only the current record:
strSQL = Left(mstrcSQL2, Len(mstrcSQL2) - 1)
strSQL = strSQL _
& " WHERE " & mstrcPKFieldName2 _
& " IN (" & lngPK2a _
& ", " & lngPK2b _
& ", " & lngPK2c & ");"
objSF2.Form.RecordSource = strSQL

Else
MsgBox "Cannot move in sub-table. " _
& "No Records."
End If
End With

Exit_cmdSelect_Click:

Set objRS2 = Nothing
Set objSF2 = Nothing

Set objRS1 = Nothing
Set objSF1 = Nothing
Exit Sub

Error_cmdSelect_Click:

MsgBox "Error No: " & Err.Number _
& vbNewLine _
& Err.Description, _
vbOKOnly + vbExclamation, _
"Error Information"

Resume Exit_cmdSelect_Click

End Sub
 
T

Teddy

I just realized the code for the cmdShowAll button was not included in my
previous post. Thanks.

Private Sub cmdShowAll_Click()

Dim objSF1 As Access.SubForm
Dim objSF2 As Access.SubForm

Set objSF1 = Me.Controls(mstrcSFrm1)
Set objSF2 = Me.Controls(mstrcSFrm2)

objSF1.Form.RecordSource = mstrcSQL1
objSF2.Form.RecordSource = mstrcSQL2

Exit_cmdShowAll_Click:

Set objSF1 = Nothing
Set objSF2 = Nothing
Exit Sub

Error_cmdShowAll_Click:

MsgBox "Error No: " & Err.Number _
& vbNewLine _
& Err.Description, _
vbOKOnly + vbExclamation, _
"Error Information"
Resume Exit_cmdShowAll_Click:

End Sub

Private Sub Form_Load()

Dim objSF1 As Access.SubForm
Dim objSF2 As Access.SubForm

' Put SQL statements into RecordSource
' property of forms in SubForm controls.

Set objSF1 = Me.Controls(mstrcSFrm1)
objSF1.Form.RecordSource = mstrcSQL1

Set objSF2 = Me.Controls(mstrcSFrm2)
objSF2.Form.RecordSource = mstrcSQL2

Exit_Form_Load:

Set objSF2 = Nothing
Set objSF1 = Nothing
Exit Sub

Error_Form_Load:

MsgBox "Error No: " & Err.Number _
& vbNewLine _
& "Error Description:" & vbNewLine _
& Err.Description, vbOKOnly + vbExclamation, _
"Error Information"
Resume Exit_Form_Load

End Sub

Private Sub Form_Open(Cancel As Integer)

Randomize

End Sub
 
G

GeoffG

Hi Teddy,

Now that my previous post and its attachments are in the
newsgroup, I have been able to test whether the text files
will work in loading the copies of my forms. As they stand,
the text files didn't work on my system. When I opened the
text files in Notepad, some of the very long lines of
numbers had wrapped to the next line.

The good news is you can correct this.

If you see wrapped lines, follow these steps:

1. Load the text files in turn into Notepad.
2. Put the cursor at the end of the very long lines of
numbers that have wrapped.
3. Press the delete key to bring the wrapped text up to
where it should be.
4. Save the text file.
5. Run the code:
Private Sub LoadFormsFromText()


FORM1.TXT

In Form1.txt, you need to unwrap these four lines:

0x0acc0e5500000000522de1c3b009e646bc5292e94765171d01
000000f2f4fc1c ,
0x7fa0e340e001917cfd040130660072006d005400610062006c
00650031000000 ,
0x00000000be9d668a9b0de74cb2b0e8e58f1096900100000040
9aff1c7fa0e340 ,
0x00000000fd040130660072006d005400610062006c00650032
000000

And this line:

0x2158b00023df3d448a5cb8bc31
0a1796

And this line:

0xc667a1429c7e5e47b05e5f5e48
0009f9


FRMTABLE1.TXT

In frmTable1.txt, you need to unwrap these five lines:

0x0acc0e5500000000db8ecf71110a8248a557e6c73c65532800
0000004fe2d516 ,
0x7fa0e3400000000000000000740062006c005400610062006c
00650031000000 ,
0x00000000b9b032cc3d57a94ea558175c06a9d20a07000000db
8ecf71110a8248 ,
0xa557e6c73c655328490044003100000000000000d01302fbb2
315b4682b40746 ,
0x18c04b5d07000000db8ecf71110a8248a557e6c73c6553284d
00610069006e00 ,

And this line:

0xf9246480ead2884b944ae314d7
d21d85

And this line:

0x37b1597b4814384bb2bf0a0cf6
2e3da7


FRMTABLE2.TXT

In frmTable2.txt, you need to unwrap these five lines:

0x0acc0e55000000002065322f6da0ec4babaee9ea34806f2500
0000009a8ed817 ,
0x7fa0e3400000000000000000740062006c005400610062006c
00650032000000 ,
0x00000000a56885585b10294291055af7125dfa540700000020
65322f6da0ec4b ,
0xabaee9ea34806f2549004400320000000000000010c041a6a7
eb494e8043308d ,
0xe2dfe718070000002065322f6da0ec4babaee9ea34806f2553
00750062004600 ,

And this line:

0x8e1c44ec87c9e54e9f04c0fb68
ac0a89

And this line:

0x76a7a16c79f37f4e84d43c63c3
b7135a


After you've unwrapped all the relevant lines and saved the
text files, you're all set to import my forms into your
database.


As you know, the code you need to run is:

Private Sub LoadFormsFromText()

' Change the path "C:\" to the path where
' you saved the text files:

LoadFromText acForm, "Form1", "C:\Form1.txt"
LoadFromText acForm, "frmTable1", "C:\frmTable1.txt"
LoadFromText acForm, "frmTable2", "C:\frmTable2.txt"
MsgBox "Finished Loading Forms"

End Sub


Geoff
 

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