Assigning field values to VBA variables and vice-versa

L

Ltexeira

Greetings,

Old to programming, new to ACCESS. Have project dumped on me
with old database. Need to do it quick and dirty, for now.

Sorry these are basic questions, but I couldn't find and real
answers to them in the threads.

Questions :

1. VBA code to 'open' a database. Once open, you can read/write
to any table in the database without reopening it?

2. VBA code to 'read' a 'record' from a table and assign the field
values to VBA variables.

3. VBA code to assign VBA variables to fields in a record and write
to table.

4. Error code to determine if all went well, for example if the read from
question 2 failed.

So, I just need to be able to read and write to tables from VBA and
utilize field values as needed. That's what I'm used to, and it's the
fastest way to get this out of my hair. ( Okay, out of my remaining
hair ).

I apologize in advance for probably using poor terminology. I also
realize that properly done the system should be rewritten with bound
forms etc, but I don't have that kind of time, and I have to accept the
learning curve over a longer period of time as well.

Thank you.
 
K

Klatuu

See Answers below in line.
--
Dave Hargis, Microsoft Access MVP


Ltexeira said:
Greetings,

Old to programming, new to ACCESS. Have project dumped on me
with old database. Need to do it quick and dirty, for now.

Sorry these are basic questions, but I couldn't find and real
answers to them in the threads.

Questions :

1. VBA code to 'open' a database. Once open, you can read/write
to any table in the database without reopening it?

See VBA Help for the OpenRecordset method. Whether you can continue to read
and write to it depends on the object's scope. The scope is determined by
where the object is Dimmed. If it is dimmed within a procedure, it will only
be seen in the procedure. If it is dimmed within a module, it can be seen in
an procedure in the module. I don't know your background, but in Access, it
is usually limited to one of the levels described above. Using Global dims
is not a good idea.
2. VBA code to 'read' a 'record' from a table and assign the field
values to VBA variables.

You don't read a record. When you open a recordset, it will be positioned
on the first record in the recordset (assuming there are records in the
recordset). When you move to a different record, the recordset's fields are
available to you. To populate variables, it is just assigning the value of
the field to a variable:

Dim rst As DAO.Recordset
Dim strSomeVariable As String

Set rst = Currentdb.OpenRecordset("SomeTableOrQueryName")
If rst.Recordcount = 0 Then
MsgBox "No Data Available"
Exit Sub
End If

'Fully popluate recordset
rst.MoveLast
rst.MoveFirst
strSomeVariable = rst![ATextField]

'Go to the next record
rst.MoveNext

'Find a specific record
rst.FindFirst "[SomeTextField] = """ & Me.SomeControlName & """""
If Not .NoMatch Then
strSomeVariable = rst![ATextField]
3. VBA code to assign VBA variables to fields in a record and write
to table.

See # 2
4. Error code to determine if all went well, for example if the read from
question 2 failed.

You use error handling code in a sub or function. You can trap for specific
error codes, but this is pretty generic. The On Error line tells VBA what to
do when an error is encountered. In this case, you go to a tag name which
processes the error:

Private Sub DoSomething()

On Error GoTo DoSomething_Err

.......
......

Exit Sub ' So the error code doesn't execute
DoSomething_Err:

MsgBox Err.Number & " - " & Err.Description

End Sub
So, I just need to be able to read and write to tables from VBA and
utilize field values as needed. That's what I'm used to, and it's the
fastest way to get this out of my hair. ( Okay, out of my remaining
hair ).

I apologize in advance for probably using poor terminology. I also
realize that properly done the system should be rewritten with bound
forms etc, but I don't have that kind of time, and I have to accept the
learning curve over a longer period of time as well.

It is actually faster to write bound forms. You don't need that much code.
The basics are, each form has a Record Source property. In this property you
define the table or query to use as the form's data.

Each control (text box, combo box, check box, etc.) that can contain data
has a Control Source property. You identify the field from the Record Source
the control will be bound to. Then each time you move to a record, the value
in the bound field will show in the control. You can then add or edit data.
When you move to a different record (including a new record) or close the
form, the underlying table(s) will be updated.

With unbound forms, you have to establish a recordset, provide your own
navigation controls, move through the recordset, populate the controls from
the fields, then populate the fields from the controls. And, you have to
know whether you are at EOF or BOF, and have to add a new record.

All that has to be done in VBA where with bound forms, it all happens for you.
 
L

Ltexeira

It doesn't make as much sense as I'd like, but it is slowly coming together.

If the VBA is running from a form that is part of an opened database in
ACCESS, do I still need to create a workspace and a connection?

From my quick looking over the samples, it appears that I can get the table
as a
recordset, then filter it to another recordset to get the 1 record I want.
Is this correct? And without a sample I am presuming that I do not need to
enumerate through the records in the recordset if there is only 1. Is this
also correct?

The samples are pretty basic (which is good) but don't have error
information (which is bad). How can I programatically determine if the
result of a filter on the recordset produced zero records?

Thank you for your assistance, every step helps!
 
L

Ltexeira

That is excellent information, thank you! The 'errors' I was referring to
involved no records being returned. I apologize for the confusion between
that and the VBA error handler.

A little more information so you can see what I'm up against. I'm an old VB
programmer, used to writing code for jBase and PICK. New to ACCESS.

The form starts with a Vehicle number and a Date. If there is a record in
table "A" that matches the vehicle number and date, then that record should
be used to populate the rest of the fields on the form, and allow for editing
and saving.

Now the tricky part. If there is no matching record, then there are some
starting values in table "B" using the vehicle number as the key. Go get
that record, whatever fields are filled in from that record can be
programatically transposed to the new form (they don't match one to one), and
then again allow for editing and writing to table "A" using vehicle number
and date.

Some other people that have used ACCESS before had no idea how to do that
with a bound form, and since I'm new to ACCESS I had no idea either. So to
get this done with I'm going with what I know. Read record from "A", if no
record, read record from "B" and populate controls. When magic 'SAVE' button
clicked, populate record from controls and write to "A".

I know it's a bunch of coding to handle it all, but it's got to happen
fairly quickly, and no one seems to know how to do it 'properly'. ( By that,
I mean no one I can physically speak with. )

So again, thanks for your assistance, every little bit helps. I hope the
explanation clears up the question of 'why are you doing it like that'!

Klatuu said:
See Answers below in line.
--
Dave Hargis, Microsoft Access MVP


Ltexeira said:
Greetings,

Old to programming, new to ACCESS. Have project dumped on me
with old database. Need to do it quick and dirty, for now.

Sorry these are basic questions, but I couldn't find and real
answers to them in the threads.

Questions :

1. VBA code to 'open' a database. Once open, you can read/write
to any table in the database without reopening it?

See VBA Help for the OpenRecordset method. Whether you can continue to read
and write to it depends on the object's scope. The scope is determined by
where the object is Dimmed. If it is dimmed within a procedure, it will only
be seen in the procedure. If it is dimmed within a module, it can be seen in
an procedure in the module. I don't know your background, but in Access, it
is usually limited to one of the levels described above. Using Global dims
is not a good idea.
2. VBA code to 'read' a 'record' from a table and assign the field
values to VBA variables.

You don't read a record. When you open a recordset, it will be positioned
on the first record in the recordset (assuming there are records in the
recordset). When you move to a different record, the recordset's fields are
available to you. To populate variables, it is just assigning the value of
the field to a variable:

Dim rst As DAO.Recordset
Dim strSomeVariable As String

Set rst = Currentdb.OpenRecordset("SomeTableOrQueryName")
If rst.Recordcount = 0 Then
MsgBox "No Data Available"
Exit Sub
End If

'Fully popluate recordset
rst.MoveLast
rst.MoveFirst
strSomeVariable = rst![ATextField]

'Go to the next record
rst.MoveNext

'Find a specific record
rst.FindFirst "[SomeTextField] = """ & Me.SomeControlName & """""
If Not .NoMatch Then
strSomeVariable = rst![ATextField]
3. VBA code to assign VBA variables to fields in a record and write
to table.

See # 2
4. Error code to determine if all went well, for example if the read from
question 2 failed.

You use error handling code in a sub or function. You can trap for specific
error codes, but this is pretty generic. The On Error line tells VBA what to
do when an error is encountered. In this case, you go to a tag name which
processes the error:

Private Sub DoSomething()

On Error GoTo DoSomething_Err

.......
......

Exit Sub ' So the error code doesn't execute
DoSomething_Err:

MsgBox Err.Number & " - " & Err.Description

End Sub
So, I just need to be able to read and write to tables from VBA and
utilize field values as needed. That's what I'm used to, and it's the
fastest way to get this out of my hair. ( Okay, out of my remaining
hair ).

I apologize in advance for probably using poor terminology. I also
realize that properly done the system should be rewritten with bound
forms etc, but I don't have that kind of time, and I have to accept the
learning curve over a longer period of time as well.

It is actually faster to write bound forms. You don't need that much code.
The basics are, each form has a Record Source property. In this property you
define the table or query to use as the form's data.

Each control (text box, combo box, check box, etc.) that can contain data
has a Control Source property. You identify the field from the Record Source
the control will be bound to. Then each time you move to a record, the value
in the bound field will show in the control. You can then add or edit data.
When you move to a different record (including a new record) or close the
form, the underlying table(s) will be updated.

With unbound forms, you have to establish a recordset, provide your own
navigation controls, move through the recordset, populate the controls from
the fields, then populate the fields from the controls. And, you have to
know whether you are at EOF or BOF, and have to add a new record.

All that has to be done in VBA where with bound forms, it all happens for you.
Thank you.
 
A

Albert D. Kallal

Now the tricky part. If there is no matching record, then there are some
starting values in table "B" using the vehicle number as the key. Go get
that record, whatever fields are filled in from that record can be
programatically transposed to the new form (they don't match one to one),
and
then again allow for editing and writing to table "A" using vehicle number
and date.

The first problem is does one need to copy this data over from table B
anyway? Are these really defaults that you need for from values in this
record, or is in fact information that you want to display from table B? If
you're just needing to display some of that information, then you don't want
a copy the information over, you want to use the relational ability of
ms-access to display this informaton (and, it will not take any code to
display that information from table B if you do this right.
Some other people that have used ACCESS before had no idea how to do that
with a bound form

Its rather easy to do this with a bound form, but the problem is your design
approach is somewhat wrong for ms-access, and therefore you having trouble
finding people to explain how to do this. It's not that you can not do this
in MS access, the problem is your approach is the wrong way to go about
doing this.

..>, and since I'm new to ACCESS I had no idea either. So to
get this done with I'm going with what I know. Read record from "A", if
no
record, read record from "B" and populate controls. When magic 'SAVE'
button
clicked, populate record from controls and write to "A".

dBase, dbaseIII, dbaseIV, Knowledge man, FoxPro, and *most* of the pc based
databases don't have a save button, it is implied.

Anyway:

I'm going to make the assumption that this form is based on one table. The
fact that you want to display values from the other table, or copy values
from the other table is a different issue (however it is critical you
clarify this issue).

The form you going to build is going to be bound on the first table. Can I
assume then once you've copied all the values from table B., we're adding
one record from table a, and we are editing the one reocrd in table A?
Correct?

So the first thing I would do is build your form to edit data from table A.
I suggest using the wizard to do it. This form will be built and designed on
table A (it is a few mouse clicks to do this, and takes very little time to
do this). You now have a form that will let you browse and move through the
records in table a. (the fact that you don't need to browse and edit
previous records is really moot here, we NEED to build a form that lets you
edit data from table a, and we must do that before the next step).

When we eventually get this working, will we will disable things like the
forms navigation keys, and a number of the other features that will stop the
user from editing data in this form.

We will now add two text boxes to prompt for the date, and the vehicle at
the top of this form. These will be what we call un-bound forms. You will be
able to type in your values, and this is also where we will write that code
to "read" the existing record, and, if not found, add a new record.

Do you plan to put a search button at the top of the form for the person to
press, or do you simply wanted to "search" after the second text box data is
entered? (the coding for in their case is much the same, it's just a
question do you want to put a button up their research, or simply have
things go and display after the second text box data is entered?).

I going to assume we search after the 2nd txt box data is entered.

so, we have two text boxes at the top

txtDate and txtVehicle

The code we will write thus goes in the after update event of the text box
called txtVehicle.

The code will look like:

dim strSql as string
dim rstVehicle as dao.ReocrdSet

if isnull(me.txtDate) = true then
msgbox "You must enter a date to seach for"
exit sub
end if

if isnull(me.txtVechicle) = true then
msgbox "you must enter a vehicle to search for"
exit sub
end if

' lets check if the vehicle number actually exists
' this is like a READ command in pick, we going to
' pull "one" record into a variable. This is the munch
' and crunch way of doing things
'
strSql = "select * from TableB where VehicleNum = " & me.txtVehicle
set rstVehicle = currentdb.OpenreocrdSet(strSql)
if rstVehicle.ReocrdCount = 0 then
msgbox "vehicle does not exist, try again"
exit sub
end if


' ok, loaded the vehicle, now lets search for the record. We going to use
the equivalent of much what it is like to do a TCL select command in pick)
' we're going to send the select command right into the form, and this is
legal in MS access. In ms-access, a sql select
can be sent to a reocrdset (like above, the rstVehcile code, or send that
select right into the form).

strSql = "select * from tableA where " & _
" ServiceDate = # & "format(me.txtDate,"mm/dd/yyy") & "#" & _
" and VehicleNum = " & me.txtVehicle

' in the above it's important to note that if the vehicle numbers actually
add text data type field, then you'll have to surround it and put quotes as
follows

" and VehicleNum = '" & me.txtVehicle & "'"

Ok, execute this select into the form:

me.RecordSource = strSql

' if we did not match,then reocrdCount is zero, and we add a new record
then.


if me.ReocrdSource.RecordCount = 0 then
' send form to a new reocrd
docmd.GoToRecord acDataForm,,acNewRec
' now copy values from rstVehcild into the form
me.Make = rstVehicle!Make
me.Model = rstVehcile!Model
.etc.
end if

There, that is about it. Do note that all the code I kept above was
completely what I call "air" code.

We probably should also add a save button at the bottom of form. That button
will write out the record and then clear the form for the next record.


if me.dirty = true then
me.dirty = false ' force disk write
end if

' now, clear the form

me.recordSource = "select * from tableA where id = 0"

The above will write out all the data, and the select command will return a
blank record because we've assigned a blank record to the form.

And, at this point, we like should set the focus back up at the top of the
form, and clear out the txtDate + txtVehicle controls

me.txtDate = Null
me.txtVehcile = null
me.txtDate.SetFocus

There's a number of other settings in the form's property tab that you also
should set to make this work a little bit more clean, such as removing the
navigation buttons on the form, and furthermore setting the forms record
cycle property to current reocrd.
 
L

Ltexeira

Great information. With this, I should be able to get this ship floating.

I am going to do the following :

1. Write this out in crunch and munch mode. Just get it working.

2. Write another form as suggested to see if I can get it working like that.

To answer your questions, I did not have any choice in the design. It's an
existing project that I got dumped on me.

Yes, the values from the vehicles file are actually just starting (default)
values that need to be copied over and can be modified in the new form. I
know, it's not my fault. If it were up to me, it would all be in jBase, or
some other MV product. I can whip out VB code under jBase pretty quickly and
have it do exactly what I need it to do and look exactly like I want it to
look. Maybe I'll be able to do that in ACCESS sometime, but not now!

Thank you for the information, I'm off to the races.
 

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