How do you code, adding a new record?

N

Nick Mirro

I was just given this kind advice on how I might add a new record to a
foreign key table (tblPayments).

"You can use the Form_AfterInsert Event of the Form you use to add Record
into tblVisits to add a related (dummy/nearly blank) Record into the
tblPayments by code if you wish to."


As tblPayments is 1:1 with ancestor tblVisits, tblPayments needs the
autonumber primary key (visitID) from tblVisits as a unique id for the new
record.


primary key type

tblVisits visitID autonumber
tblPayments visitID numer. (foreign key)


Having little to no vb training, here's how I guessed it might start. Could
I ask how this could be altered to actually work?


Private Sub Form_AfterInsert()

Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("tblPayments")
rst.AddNew
rst!VisitID = ""
rst.Update

End Sub


Nick

(Relationships)

http://home.comcast.net/~nickmirro/images/Temporary/Relationships.pdf
 
D

Dirk Goldgar

Nick Mirro said:
I was just given this kind advice on how I might add a new record to a
foreign key table (tblPayments).

"You can use the Form_AfterInsert Event of the Form you use to add
Record into tblVisits to add a related (dummy/nearly blank) Record
into the tblPayments by code if you wish to."


As tblPayments is 1:1 with ancestor tblVisits, tblPayments needs the
autonumber primary key (visitID) from tblVisits as a unique id for
the new record.


primary key type

tblVisits visitID autonumber
tblPayments visitID numer. (foreign key)


Having little to no vb training, here's how I guessed it might start.
Could I ask how this could be altered to actually work?


Private Sub Form_AfterInsert()

Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("tblPayments")
rst.AddNew
rst!VisitID = ""
rst.Update

End Sub


Nick

(Relationships)

http://home.comcast.net/~nickmirro/images/Temporary/Relationships.pdf

Nick -

The code you've proposed should work with only minor modifications. All
you'd need to do -- so far as I know at the moment -- is modify this
line:
rst!VisitID = ""

to this:

rst!VisitID = Me.VisitID

and add a couple of lines after the rst.Update line to close the
recordset and set rst to Nothing:
rst.Update
rst.Close
Set rst = Nothing

So try that and see if it works for you. I would probably do this
slightly differently, just executing an inline append query to insert
the record in tblPayments, but this should work fine.
 
N

Nick Mirro

Thank you Dirk. Here's what I ended up with:


Private Sub Form_AfterInsert()

Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("tblPayments")
rst.AddNew
rst!VisitID = Me.VisitID
rst.Update
rst.Update
rst.Close
Set rst = Nothing

End Sub


I open the form to a record that doesn't exist in tblPayments yet. I add
data to fields from tblPayments and close the form. On close I get the
error again:

"You cannot add a record (to tblPayments) because a related record is
required in table 'tblVisits.'"

Nick
 
D

Dirk Goldgar

Nick Mirro said:
Thank you Dirk. Here's what I ended up with:


Private Sub Form_AfterInsert()

Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("tblPayments")
rst.AddNew
rst!VisitID = Me.VisitID
rst.Update
rst.Update
rst.Close
Set rst = Nothing

End Sub


I open the form to a record that doesn't exist in tblPayments yet. I
add data to fields from tblPayments and close the form. On close I
get the error again:

"You cannot add a record (to tblPayments) because a related record is
required in table 'tblVisits.'"

First let me observe that you don't want the rst.Update line in there
twice. That's true no matter what else is going on. But now I'm
confused by this problem you're describing. I thought this form was
bound to tblVisits. That's what your question implied to me: that when
you add a record to tblVisits via the form, you want to automatically
add a record to tblPayments. If this is so, how can you be using the
form to "add data to fields from tblPayments"? Something is not right
here.

What is the RecordSource of the form?
 
N

Nick Mirro

Well the form is bound to a query which calls data from tblVisits,
tblPayments and tblBillingInfo. Both tblPayments and tblBillingInfo are
linked to tblVisits by a 1:1 relationship (strangely).

When I open the form in which billing (not payment) info is first entered, a
new record is automatically generated in tblBillingInfo. Unfortunately this
is not happening in the form that I use to enter payment info. This
"frmPayments" calls up Billing Info just for user input reference.

frmPayments qryPayments tblPayments
frmBillingInfo qryBillingInfo tblBillingInfo

Both queries link to fields in all 3 tables.


The 1:1 relationships include all records in tblVisits and matching in the 2
other tables. (cascade update and delete)

http://home.comcast.net/~nickmirro/images/Temporary/Relationships.pdf

form screenshots available : )

Nick
 
D

Dirk Goldgar

Nick Mirro said:
Well the form is bound to a query which calls data from tblVisits,
tblPayments and tblBillingInfo. Both tblPayments and tblBillingInfo
are linked to tblVisits by a 1:1 relationship (strangely).

When I open the form in which billing (not payment) info is first
entered, a new record is automatically generated in tblBillingInfo.
Unfortunately this is not happening in the form that I use to enter
payment info. This "frmPayments" calls up Billing Info just for user
input reference.

frmPayments qryPayments tblPayments
frmBillingInfo qryBillingInfo tblBillingInfo

Both queries link to fields in all 3 tables.


The 1:1 relationships include all records in tblVisits and matching
in the 2 other tables. (cascade update and delete)

http://home.comcast.net/~nickmirro/images/Temporary/Relationships.pdf

form screenshots available : )

I wish all newsgroup querents were so obliging.

Since you've been asking questions in the newsgroups for a while, I
suppose others have already mentioned that your table design is not
normalized -- there are lots of repeating field groups like CPT1, CPT2,
CPT3, DxCode1, DxCode2, DxCode3, DateOfPayment1, DateOfPayment2,
DateOfPayment3, and so on -- and that this will probably cause trouble
for you down the road. I'm not intending to harp on that now, but I
thought I should mention it.

Now, as for the relationships: even in a one-to-one relationship, one
table is primary and the other is secondary (that may not be the
technical term, but it's how I think of it). Generally, if one table
the linking key field in one table is an autonumber, then that table is
primary. If the key is not autonumber in any of the tables, I think
Access decides which is primary based on which table's key field is
dragged to the other to create the relationship in the relationship
window, but I don't remember exactly how that works. At any rate, you
can create a record in the primary table without a matching record in
the secondary table, but not vice versa. After looking at your
relationship diagram, I'm going to assume that tblVisits is primary in
these one-to-one relationships. That means that you can't add a record
to tblPayments or tblBillingInfo without a matching record in tblVisits.
That makes sense, though as I said, I wouldn't have structured my tables
this way.

Now, you can build an updatable query that joins all three tables on
VisitID, and if you set it up right you will be able to update fields
from all three tables. I believe that query must include the VisitID
field from tblVisits, along with whatever other fields you want from the
three tables. The way it will work, in the absence of any special code,
is that

1. You can't add new payment or billing data for a new visit unless
you *first* enter something in one of the fields from tblVisits, so that
a VisitID is created.

2. If you don't "dirty" any of the fields that come from
tblPayments, no record will be created in that table.

3. Similarly, if you don't "dirty" any of the fields that come from
tblBillingInfo, no record will be created in that table.

On the other hand, I don't see any reason to add a dummy record to those
tables. If your form is based on a query that left-joins tblVisits to
each of the other tables, your forms for payments and billing info will
still show a record for every visit, with fields for you to fill in the
info that will go in the other tables.

If you really do feel a need to have a record in tblPayments and
tblBillingInfo to match every record in tblVisits, all you really have
to do is programmatically "dirty" one field from each table in the
form's BeforeUpdate event. For example, you might have code like this:

Private Sub Form_BeforeUpdate(Cancel As Integer)

' Force save of BillingInfo record
Me.CPT1 = Me.CPT1

' Force save of payment record
Me.DateOfPayment1 = Me.DateOfPayment1

End Sub

If you do that, you don't need to use DAO to add records to these
tables. The act of setting these fields to their existing values (even
if those values are Null) is enough to force Access to create matching
records in those tables.
 
D

Dirk Goldgar

Nick Mirro said:
Thanks for your patience here. I tried this code in the payments
form...


Private Sub Form_BeforeUpdate(Cancel As Integer)

' Force save of payment record
Me.DateOfPayment1 = Me.DateOfPayment1

End Sub


with the same result. The date fields have the same name as the
underlying data fields. Strangely, this missing record is not an
issue for the BillingInfo form.

Does the recordsource query for the form include the VisitID from
tblVisits (not just tblPayments)? Did you first enter data in a field
that came from tblVisits?

I think you'd better post the SQL of the form's recordsource query, and
list the bound controls on the form and what fields they are bound to.
 
N

Nick Mirro

Hello again. Refering to the three steps you outline, I've already been
doing this. The query for frmBillingInfo has VisitID from tblVisits, as
well as fields from tblPayments and tblBillingInfo. I get the error after
trying to update one of the fields from tblBillingInfo, and then changing
records.

http://home.comcast.net/~nickmirro/images/Temporary/frmPayments.gif

http://home.comcast.net/~nickmirro/images/Temporary/qryPayments.gif



Here is the existing code behind the form:


Private Sub Form_BeforeUpdate(Cancel As Integer)

' Force save of BillingInfo record
' Me.CPT1 = Me.CPT1

' Force save of payment record
Me.DateOfPayment1 = Me.DateOfPayment1

End Sub


Private Sub cboSelector_AfterUpdate()
' Find the record that matches the control.
Dim rs As Object

DoCmd.RunCommand acCmdSaveRecord
DoCmd.ShowAllRecords
Me.cboSelector.Requery
Set rs = Me.Recordset.Clone
rs.FindFirst "[VisitID] = " & Str(Me![cboSelector])
Me.Bookmark = rs.Bookmark

End Sub


Private Sub cboSelector_Enter()

Dim lngCount As Long
DoCmd.RunCommand acCmdSaveRecord
Me.cboSelector.Requery

lngCount = Me.cboSelector.ListCount

End Sub


Private Sub CommLog_Click()
On Error GoTo Err_CommLog_Click

Dim stDocName As String
Dim stLinkCriteria As String

stDocName = "Communication log"

DoCmd.RunCommand acCmdSaveRecord
stLinkCriteria = "[VisitID]=" & Me![VisitID]
DoCmd.OpenForm stDocName, , , stLinkCriteria

Exit_CommLog_Click:
Exit Sub

Err_CommLog_Click:
MsgBox Err.Description
Resume Exit_CommLog_Click

End Sub



Private Sub MDR_Click()
On Error GoTo Err_MDR_Click

Dim stDocName As String
Dim stLinkCriteria As String

stDocName = "MDR form"

DoCmd.RunCommand acCmdSaveRecord
stLinkCriteria = "[VisitID]=" & Me![VisitID]
DoCmd.OpenForm stDocName, , , stLinkCriteria

Exit_MDR_Click:
Exit Sub

Err_MDR_Click:
MsgBox Err.Description
Resume Exit_MDR_Click

End Sub



Private Sub Reports_button_Click()
On Error GoTo Err_Reports_button_Click

Dim stDocName As String
Dim stLinkCriteria As String

DoCmd.RunCommand acCmdSaveRecord
stDocName = "Print Billing Reports Dialog"
DoCmd.OpenForm stDocName, , , stLinkCriteria

Exit_Reports_button_Click:
Exit Sub

Err_Reports_button_Click:
MsgBox Err.Description
Resume Exit_Reports_button_Click

End Sub



Private Sub btnOpenCodes_Click()
On Error GoTo Err_btnOpenCodes_Click

Dim stDocName As String
Dim stLinkCriteria As String

stDocName = "frmProcMusSkel"

stLinkCriteria = "[VisitID]=" & Me![VisitID]
DoCmd.OpenForm stDocName, , , stLinkCriteria

Exit_btnOpenCodes_Click:
Exit Sub

Err_btnOpenCodes_Click:
MsgBox Err.Description
Resume Exit_btnOpenCodes_Click

End Sub
 
D

Dirk Goldgar

Nick Mirro said:
Hello again. Refering to the three steps you outline, I've already
been doing this. The query for frmBillingInfo has VisitID from
tblVisits, as well as fields from tblPayments and tblBillingInfo. I
get the error after trying to update one of the fields from
tblBillingInfo, and then changing records.

http://home.comcast.net/~nickmirro/images/Temporary/frmPayments.gif

http://home.comcast.net/~nickmirro/images/Temporary/qryPayments.gif

[code snipped]

I notice your query includes both tblVisits.VisitID and
tblBillingInfo.VisitID. I can't see whether it also contains
tblPayments.VisitID. In my tests of a similar setup, I included only
the key from the primary table -- tblVisits.VisitID in your case -- and
I had a control on the form bound to this field. Does your form have a
control bound to tblVisits.VisitID?
 
D

Dirk Goldgar

Nick Mirro said:
Dirk,

In qryPayments, VisitID is from tblPayments. Regarding adding a
record to tblVisits, the only field in frmPayments from tblVisits is
DateOfVisit, which is already completed. There are no other fields
that would be related to the visit (treatment date) that need
completing. If this is essential, I could take a random field from
tblPayments and move it to tblVisits.

Here's the sql: (sorry about the number of fields)

SELECT [Patient information].Patient_first_name, [Patient
information].Patient_last_name, tblVisits.DateOfVisit,
tblVisits.VisitID, [Insurance information].[Carrier name],
tblPayments.DateOfPayment1, tblPayments.DateOfPayment2,
tblPayments.DateOfPayment3, tblPayments.TotalPayed,
tblPayments.CPT1PaymentTotal, tblPayments.CPT1UnitsPaid1,
tblPayments.CPT1UnitsPaid2, tblPayments.CPT1UnitsPaid3,
tblPayments.CPT1UnitPayment1, tblPayments.CPT1UnitPayment2,
tblPayments.CPT1UnitPayment3, tblPayments.CPT1Balance,
tblPayments.CPT2PaymentTotal, tblPayments.CPT2UnitsPaid1,
tblPayments.CPT2UnitsPaid2, tblPayments.CPT2UnitsPaid3,
tblPayments.CPT2UnitPayment1, tblPayments.CPT2UnitPayment2,
tblPayments.CPT2UnitPayment3, tblPayments.CPT2Balance,
tblPayments.CPT3PaymentTotal, tblPayments.CPT3UnitsPaid1,
tblPayments.CPT3UnitsPaid2, tblPayments.CPT3UnitsPaid3,
tblPayments.CPT3UnitPayment1, tblPayments.CPT3UnitPayment2,
tblPayments.CPT3UnitPayment3, tblPayments.CPT3Balance,
tblPayments.CPT4PaymentTotal, tblPayments.CPT4UnitsPaid1,
tblPayments.CPT4UnitsPaid2, tblPayments.CPT4UnitsPaid3,
tblPayments.CPT4UnitPayment1, tblPayments.CPT4UnitPayment2,
tblPayments.CPT4UnitPayment3, tblPayments.CPT4Balance,
tblPayments.CPT5PaymentTotal, tblPayments.CPT5UnitsPaid1,
tblPayments.CPT5UnitsPaid2, tblPayments.CPT5UnitsPaid3,
tblPayments.CPT5UnitPayment1, tblPayments.CPT5UnitPayment2,
tblPayments.CPT5UnitPayment3, tblPayments.CPT5Balance,
tblPayments.CPT6PaymentTotal, tblPayments.CPT6UnitsPaid1,
tblPayments.CPT6UnitsPaid2, tblPayments.CPT6UnitsPaid3,
tblPayments.CPT6UnitPayment1, tblPayments.CPT6UnitPayment2,
tblPayments.CPT6UnitPayment3, tblPayments.CPT6Balance,
tblBillingInfo.CPT1, tblBillingInfo.CPT1Units,
tblBillingInfo.CPT1UnitCharge, tblBillingInfo.CPT2,
tblBillingInfo.CPT2Units, tblBillingInfo.CPT2UnitCharge,
tblBillingInfo.CPT3, tblBillingInfo.CPT3Units,
tblBillingInfo.CPT3UnitCharge, tblBillingInfo.CPT4,
tblBillingInfo.CPT4Units, tblBillingInfo.CPT4UnitCharge,
tblBillingInfo.CPT5, tblBillingInfo.CPT5Units,
tblBillingInfo.CPT5UnitCharge, tblBillingInfo.CPT6,
tblBillingInfo.CPT6Units, tblBillingInfo.CPT6UnitCharge

FROM (((([Patient information] LEFT JOIN [Injury information] ON
[Patient information].PatientID = [Injury information].PatientID)
LEFT JOIN tblVisits ON [Injury information].InjuryID =
tblVisits.InjuryID) LEFT JOIN [Insurance information] ON [Injury
information].InjuryID = [Insurance information].InjuryID) LEFT JOIN
tblBillingInfo ON tblVisits.VisitID = tblBillingInfo.VisitID) LEFT
JOIN tblPayments ON tblVisits.VisitID = tblPayments.VisitID

ORDER BY tblVisits.DateOfVisit DESC;


I'm working on the fields and controls list. Thank you for helping me
through this. This database is really important to me : )

Hmm, I don't see immediately why it doesn't work, then, when my
similarly constructed (but much simpler) query and test form do. I
can't work on it any more tonight, but I hope to have another look
tomorrow. Perhaps you could take the time to create a cut-down copy of
your database with only a few dummy records in it. I may ask you to
send me something like that tomorrow, if nothing becomes clear from the
list of fields and controls.

Understand, I do believe that you wouldn't be having these problems if
you were using properly normalized tables and presenting them in
subforms. But I'm curious as to whether this structure can be made to
work. We may have to at least use a main form based on tblVisits and a
subform based on tblPayments.

Keep the faith until tomorrow.
 
N

Nick Mirro

Meanwhile I'll take a look at the subform approach and see if I can squeeze
all the fields into one. Thank you for the time.

Nick


Dirk Goldgar said:
Nick Mirro said:
Dirk,

In qryPayments, VisitID is from tblPayments. Regarding adding a
record to tblVisits, the only field in frmPayments from tblVisits is
DateOfVisit, which is already completed. There are no other fields
that would be related to the visit (treatment date) that need
completing. If this is essential, I could take a random field from
tblPayments and move it to tblVisits.

Here's the sql: (sorry about the number of fields)

SELECT [Patient information].Patient_first_name, [Patient
information].Patient_last_name, tblVisits.DateOfVisit,
tblVisits.VisitID, [Insurance information].[Carrier name],
tblPayments.DateOfPayment1, tblPayments.DateOfPayment2,
tblPayments.DateOfPayment3, tblPayments.TotalPayed,
tblPayments.CPT1PaymentTotal, tblPayments.CPT1UnitsPaid1,
tblPayments.CPT1UnitsPaid2, tblPayments.CPT1UnitsPaid3,
tblPayments.CPT1UnitPayment1, tblPayments.CPT1UnitPayment2,
tblPayments.CPT1UnitPayment3, tblPayments.CPT1Balance,
tblPayments.CPT2PaymentTotal, tblPayments.CPT2UnitsPaid1,
tblPayments.CPT2UnitsPaid2, tblPayments.CPT2UnitsPaid3,
tblPayments.CPT2UnitPayment1, tblPayments.CPT2UnitPayment2,
tblPayments.CPT2UnitPayment3, tblPayments.CPT2Balance,
tblPayments.CPT3PaymentTotal, tblPayments.CPT3UnitsPaid1,
tblPayments.CPT3UnitsPaid2, tblPayments.CPT3UnitsPaid3,
tblPayments.CPT3UnitPayment1, tblPayments.CPT3UnitPayment2,
tblPayments.CPT3UnitPayment3, tblPayments.CPT3Balance,
tblPayments.CPT4PaymentTotal, tblPayments.CPT4UnitsPaid1,
tblPayments.CPT4UnitsPaid2, tblPayments.CPT4UnitsPaid3,
tblPayments.CPT4UnitPayment1, tblPayments.CPT4UnitPayment2,
tblPayments.CPT4UnitPayment3, tblPayments.CPT4Balance,
tblPayments.CPT5PaymentTotal, tblPayments.CPT5UnitsPaid1,
tblPayments.CPT5UnitsPaid2, tblPayments.CPT5UnitsPaid3,
tblPayments.CPT5UnitPayment1, tblPayments.CPT5UnitPayment2,
tblPayments.CPT5UnitPayment3, tblPayments.CPT5Balance,
tblPayments.CPT6PaymentTotal, tblPayments.CPT6UnitsPaid1,
tblPayments.CPT6UnitsPaid2, tblPayments.CPT6UnitsPaid3,
tblPayments.CPT6UnitPayment1, tblPayments.CPT6UnitPayment2,
tblPayments.CPT6UnitPayment3, tblPayments.CPT6Balance,
tblBillingInfo.CPT1, tblBillingInfo.CPT1Units,
tblBillingInfo.CPT1UnitCharge, tblBillingInfo.CPT2,
tblBillingInfo.CPT2Units, tblBillingInfo.CPT2UnitCharge,
tblBillingInfo.CPT3, tblBillingInfo.CPT3Units,
tblBillingInfo.CPT3UnitCharge, tblBillingInfo.CPT4,
tblBillingInfo.CPT4Units, tblBillingInfo.CPT4UnitCharge,
tblBillingInfo.CPT5, tblBillingInfo.CPT5Units,
tblBillingInfo.CPT5UnitCharge, tblBillingInfo.CPT6,
tblBillingInfo.CPT6Units, tblBillingInfo.CPT6UnitCharge

FROM (((([Patient information] LEFT JOIN [Injury information] ON
[Patient information].PatientID = [Injury information].PatientID)
LEFT JOIN tblVisits ON [Injury information].InjuryID =
tblVisits.InjuryID) LEFT JOIN [Insurance information] ON [Injury
information].InjuryID = [Insurance information].InjuryID) LEFT JOIN
tblBillingInfo ON tblVisits.VisitID = tblBillingInfo.VisitID) LEFT
JOIN tblPayments ON tblVisits.VisitID = tblPayments.VisitID

ORDER BY tblVisits.DateOfVisit DESC;


I'm working on the fields and controls list. Thank you for helping me
through this. This database is really important to me : )

Hmm, I don't see immediately why it doesn't work, then, when my
similarly constructed (but much simpler) query and test form do. I
can't work on it any more tonight, but I hope to have another look
tomorrow. Perhaps you could take the time to create a cut-down copy of
your database with only a few dummy records in it. I may ask you to
send me something like that tomorrow, if nothing becomes clear from the
list of fields and controls.

Understand, I do believe that you wouldn't be having these problems if
you were using properly normalized tables and presenting them in
subforms. But I'm curious as to whether this structure can be made to
work. We may have to at least use a main form based on tblVisits and a
subform based on tblPayments.

Keep the faith until tomorrow.

--
Dirk Goldgar, MS Access MVP
www.datagnostics.com

(please reply to the newsgroup)
 

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