Corey:
Firstly names don't make good keys as they can be duplicated, even within a
small set of people; I once worked with two Maggie Taylors! Its best when
dealing with people to use a unique numeric primary key, and this can be an
autonumber field so whenever a new record is added a value will be entered
automatically. The actual values are immaterial, it’s the uniqueness that
matters. Call it something like PersonnelID. When dealing with values which
are unique, e.g. US states then as the names of the states are unique you can
use the name as the key. City names can be duplicated, though, so always use
a CityID numeric key for them, or you could end up confusing Paris, France
with Paris, Texas!
Any table which the Personnel table references in a many-to-one relationship
would also have a unique primary key. Lets say you want to record which
Company each soldier is in, then a Companies table would have a CompanyID
primary key field, and the Personnel table would have a CompanyID foreign key
field. The foreign key field must be a straightforward long integer number,
not an autonumber, however. The primary key of Companies can be an
autonumber though. So long as you only want to record which company a
soldier is currently in then you don't need a subform for this; on the main
Personnel form you'd have a combo box bound to the CompanyID field with a
RowSource property like this:
SELECT CompanyID, Company FROM Companies ORDER BY Company;
The BoundColumn property of the combo box would be 1, its ColumnCount
property 2 and its ColumnWidths property 0cm;8cm (or rough equivalent in
inches, but the first dimension must be zero as this hides the CompanyID so
you just see the text Company names in the combo box).
If, on the other hand there is a one-to-many relationship from Personnel to
another table then you would use a subform. Lets stick with the example of
Companies but assume that, rather than merely recording a soldier's current
company, you want to record all the companies they've served in. For this
you don't have a Companies foreign key in the Personnel table. The Companies
table remains the same as before. What you have here is a many-to-many
relationship between Personnel and Companies, i.e. each soldier can have
served in one or more companies, and each company will obviously have been
made up of more than one soldier. The way this is modelled is by creating a
third table, CompanyPersonnel say, which has two foreign keys, PersonnelID
and CompanyID. The many-to-many relationship has been resolved into two
one-to-many relationships, one from Personnel to CompanyPersonnel, the other
from Companies to CompanyPersonnel.
The CompanyPersonnel table would also have other fields such as the dates a
soldier joined and left a company, along with any others you might need to
record data relevant to a soldiers service in the company in question.
To incorporate this in your form, as the relationship from Personnel to
CompanyPersonnel is one-to-many, you'd use a subform based on the
CompanyPersonnel table (or better still a query on the table sorted by the
DateJoined field so the records are shown in date order). The
LinkMasterFields and LinkChildFields properties of the subform control would
be PersonnelID.
In this subform you'd have a combo box bound to the CompanyID field exactly
as in the example above in the main form where you are only recording a
soldier's current company. In addition you'd have text boxes bound to the
DateJoined and DateLeft fields etc. For each company a soldier has served in
a new record is entered in the subform.
I hope the above illustrates the general principles involved and will help
you with your own tables and forms, but if you need any clarification, or
there's any other aspect I can help with then don't hesitate to post back.
Ken Sheridan
Stafford, England
Corey Hite said:
Thanks, Ken-
I did the subforms on the main form and set the Link child and Link master
fields, but I still can't input new records, even after setting all data
entry properties to yes. I have the primary key of the soldiers name on the
main form, and have it set as a foreign key to all of the other forms, and
then I use that to look up and input data into all of the other records. Do
I have it all backwards? Do I need to have the primary key as the soldiers
name in all of the other tables, and have it as the foreign key to the main
one and then allow updates? Or do I have it set up right and have to have
the name block in each of the subforms? I can do edits through a query, so I
just want to be able to input new records and then edit them through a query.
Thanks in advance for the help.
--
SSG Corey Hite
2/34th BSTB
IA ARNG
:
Corey:
You should certainly not create a single table, as this would introduce a
lot of redundancy, and the consequent risk of update anomalies. I don’t
really see a lot of point in adding rows into each table in one operation as
all you can insert into the referenced tables (those on the may side of the
relationships) would be the foreign key values corresponding to the primary
key of the referenced table. Also what happens when you want to add another
row to one of the referencing tables after the initial row has been inserted?
You can add a record to the main referenced table then as many or as few to
each of the referencing tables very simply with bound forms, either by using
subforms bound to each of the referencing tables in a parent form bound to
the main referenced table, or by opening linked forms from a form bound to
the referenced table.
If you use subforms then you don’t need any code at all. Just add a subform
to the main form for each referenced table and set the LinkMasterFields and
LinkChildFields properties of each subform control in the main form to the
name of the primary key of the main table and corresponding foreign key of
the referenced table. To keep the size of the form down you can put each
subform on a separate page of a tab control in the main form. If you want
the form and subforms only to be used for adding new records, not for viewing
or editing existing ones, set their DataEntry properties to True (Yes).
To use linked forms, each based on one of the referencing tables, you can
have on the main form a button to open each linked form with code like this,
assuming the primary key of the main form’s table and the corresponding
foreign key of the linked form’s table is called MyID and is a numeric data
type:
DoCmd.OpenForm "LinkedFormName", _
WhereCondition:="[MyID] = " & Me.[MyID], _
DataMode:=acFormAdd, _
WindowMode:=acDialog, _
OpenArgs:=Me.[MyID]
In each linked form's Open event procedure put code to set the DefaultValue
property of the MyID control in the linked form:
If Not IsNull(Me.OpenArgs) Then
Me.[MyID].DefaultValue = """" & Me.OpenArgs & """"
End If
This sets the default value of the MyID control in the linked form, so a new
record is only begun to be added once you start inserting other data. As
many new records as required for the current main record can be added in the
subform, and each will have the same MyID value.
If you wished you could open each linked form in turn with a single button
just by tacking together the code which calls the OpenForm method:
DoCmd.OpenForm "FirstLinkedFormName", _
WhereCondition:="[MyID] = " & Me.[MyID], _
DataMode:=acFormAdd, _
WindowMode:=acDialog, _
OpenArgs:=Me.[MyID]
DoCmd.OpenForm "SecondLinkedLinkedFormName", _
WhereCondition:="[MyID] = " & Me.[MyID], _
DataMode:=acFormAdd, _
WindowMode:=acDialog, _
OpenArgs:=Me.[MyID]
DoCmd.OpenForm "ThirdLinkedLinkedFormName", _
<and so on>
Because each form is opened in dialogue mode by means of the acDialog
setting for the WindowMode argument, the next form won't open until the first
one has been closed. One or more records can be added in each as required,
or any of the linked forms can simply be closed without doing anything more
to move onto the next form without adding a record in the previous one.
Ken Sheridan
Stafford, England
:
I'm trying to create a master form and use append queries to allow me to
enter new records into all the tables at once. All of the tables use the
same primary field and are connected to a main table that has a one to many
relationship with all of them. I'm trying to create a field in the form that
will allow me to insert a new record into all the tables at once with the use
of a command button. I've tried to do this through creating a series of
append queries and then putting those queries together on a macro using their
SQL statements. When I try to run the macro, I keep getting the message
'duplicate output destination (field name)'. Would it be better to try this
using visual basic and creating an SQL string? Or will I have to start
everything over from scratch and create one huge table to input the data on?
Thanks in advance for your help.