LOOP WITHIN A LOOP

G

Guest

Good morning,

I am using Access 2000 and just about to write my first database. I have
some code for looping through the records in a certain field but is it
possible to have an inner loop which will lop through the reords for the
first field then go to the next field and lop again and so on.......
 
A

Allen Browne

Yes, you can loop through the Fields of the Recordset, as well as looping
through the records:
For i = 0 To rs.Fields.Count -1
Do While Not rs.EOF
rs.MoveNext
Loop
Next

Realistically Sean, I can't think of a practical reason to do that. You
rarely need to loop all records in Access. If you are trying to alter
values, an UPDATE query will usually be more efficient.

If you did want to alter the fields, it would be much more efficient to loop
the fields in the record (a single Edit and Update) instead of performing an
Edit and Update on every field again through every record.
 
A

Amy Blankenship

What's the end goal of what you want to accomplish?

You probably don't want to loop through the fields as the outer loop,
because depending on the cursor type you've chosen for your recordset, you
may not be able to get back to the first record to loop again.

You're probably better off looping through field in rs.fields as the inner
loop rather than the outer loop.

HTH;

Amy
 
C

Chris2

SEAN DI''''ANNO said:
Good morning,

I am using Access 2000 and just about to write my first database. I have
some code for looping through the records in a certain field but is it
possible to have an inner loop which will lop through the reords for the
first field then go to the next field and lop again and so
on.......

Sean,

If you loop through all rows for one column, and then do it again,
then you'll be going through the table once per column. This will
be extraordinarly costly.

If you're going to take the costly step of looping through a table
in the first place, operate on every column at once. That way, you
only need to loop through the table once.

The earlier comments about using standard SQL statements if at all
possible should be taken seriously.


Sincerely,

Chris O.

PS Although meant for an sqlserver newsgroup, the
following link is still applicable for MS Access:
http://www.aspfaq.com/etiquette.asp?id=5006, and
is excellent when it comes to detailing how to
provide the information that will best enable
others to answer your questions.
 
G

Guest

Thanks guys, I think I understand what you mean

Outer loop - Loop through record 1 to end of records
Inner loop - Loop through each field within the record

I will explain why I want to do this.

I am writing a database to monitor the accuracy of new data entered. (It is
exported into access and not input) I have to give each record a data score
depending on accurate the data is. The only way I can think to do this is to
loop the fields and then using the value of the field name and the value
entered for the field, look up any SHOULD NOT USE VALUES stored in another
table using a DLOOKUP function (I think...ha ha)

How do I know the name of the field that the loop is on. Is it
rs.fields.value?
 
J

John Vinson

Thanks guys, I think I understand what you mean

Outer loop - Loop through record 1 to end of records
Inner loop - Loop through each field within the record

I will explain why I want to do this.

I am writing a database to monitor the accuracy of new data entered. (It is
exported into access and not input) I have to give each record a data score
depending on accurate the data is. The only way I can think to do this is to
loop the fields and then using the value of the field name and the value
entered for the field, look up any SHOULD NOT USE VALUES stored in another
table using a DLOOKUP function (I think...ha ha)

I VERY much doubt that either VBA or looping through records and
fields is necessary in order to do this.

Access (or any SQL-language RDBMS) is very good at flexible Queries
which can retrieve all your data in one swell foop, without doing it
"procedurally". If you have a table of forbidden field values, I
strongly suspect an Unmatched query joining your table to the
forbidden-values table will validate your data MUCH more quickly than
any loop such as you suggest. DLookUp is powerful - but it can't lay
much claim to being fast or efficient!

John W. Vinson[MVP]
 
C

Chris2

SEAN DI''''ANNO said:
Thanks guys, I think I understand what you mean

Outer loop - Loop through record 1 to end of records
Inner loop - Loop through each field within the record

I will explain why I want to do this.

I am writing a database to monitor the accuracy of new data entered. (It is
exported into access and not input) I have to give each record a data score
depending on accurate the data is. The only way I can think to do this is to
loop the fields and then using the value of the field name and the value
entered for the field, look up any SHOULD NOT USE VALUES stored in another
table using a DLOOKUP function (I think...ha ha)

How do I know the name of the field that the loop is on. Is it
rs.fields.value?

"Chris2" wrote:

Sean,

I am not sure why this operation cannot be accomplished with one
UPDATE statement.

The narratives given so far present no compelling reason to use VBA
that I can see.

It is difficult to tell, though, as I am not sure what your schema
is, or what your source data and desired results are.


Although meant for an sqlserver newsgroup, the
following link is still applicable for MS Access:
http://www.aspfaq.com/etiquette.asp?id=5006, and
is excellent when it comes to detailing how to
provide the information that will best enable
others to answer your questions.


Pure Guesswork:

UPDATE DataEntryScores AS DS1
INNER JOIN
DataEntry DE1
ON DS1.pk = DE1.pk
SET DS1.col1 = <your accuracy check on DE1.col1>
,DS1.col2 = <your accuracy check on DE1.col2>
,DS1.col3 = <your accuracy check on DE1.col3>
,etc.
,etc.
,etc.

Or possibly the SET will look like:

SET DS1.col1 = <your accuracy check on all DE1 columns>


Sincerely,

Chris O.
 
G

Guest

Good morning ladies and gentleman. First Of all, a big thank you to everyone
who has kindly given me advice and support in regards to my question. I did
previously pose the question as (BASIC CODE TO USE IN MY FIRST DATABASE but I
think the question implied that I was being lazy and wanted some one to do
all the work for me. Not the case, I have just found it hard knowing what
syntax to use for code. I have looked for a good book to guide me through
writing VB in accedss for beginners but can not find one. If anyone knows
of a good book which I can order on the internet to teach me properly I would
really appreciate it. Ps I live in the UK. In reagrds to my question which
I think is the engine to the whole database I need to write;

Chris2 - I really don ot know how I can achieve this with a single update
statement. In essense my database will work by;

Comparing a list of records containing contact addresses against a new file
of contact addresses with the "new" records being the ones to validate.

The fields will be along the lines of;

Contact Name, Address 1, Address 2, Address 3 Tel No, Post Code, Fax No

The reason I asked the loop within a loop question was so that I can loop
through all of the fields for each record anh have a running score. Eg

Outer Loop From 1 to end of new records
No Of New Records Counter=0
If outerloop record is not duplicate add 1 to New Records Counter

Inner Loop From Field 1 to End Of fields
DataScore=20 (20 Fields To Validate in total so 20 is potential best
score)

VALIDATION CHECKS
Compare Value for Outerloop, innerloop in forbidden values

John Vinson, looking at your reply - it has got me thinking, a simple query
links one table to another e.g. Customer No to Customer No, I guess I could
link the forbidden values table to the values of inner loop
(rs.fields(i).name and outer loop by just using as the criteria??

If the value matches up to a value in forbidden values then
DATASCORE=DATASCORE-1
NEXT INNER LOOP

RECORD SCORE IN TABLE (so that reporting can be done)

NEXT OUTERLOOP

And thats it...easy in theory...ha ah. Thanks again, I have slowly but
surely gaining confidence from all of the input and I hope in time might be
able to offer the same help to others.
 
G

Guest

Morning again guys.......Sorry shoudl have pointed out that IFONLYIKNEWCODE
AND Sean Di'Anno are one in the same...Sean is the user name I use at home.
 
V

Vincent Johns

Assuming you can define a set of forbidden values, a Query (or set
thereof) is probably the easiest way to go. But your criteria could be
trickier than just an easily listed set. I'll show an example using two
ways to calculate your scores. Suppose you have a Table looking like
this (I've omitted some fields for brevity):

[ContactList] Table Datasheet View:

ContactList_ID Contact Name Address 1 Post Code
-------------- --------------- ---------- ---------
2085843127 Murgatroyd 23-B Baker 2V5-L8N
2014364093 Rumpelstiltskin 85 Palace 0H1-B0Y
-1397802452 Smith 9 Downing 2V5-X2Z
-1488856006 xxx None 0X0-X0X

There are some things you might not like about some of these records, as
you indicate in the following Query. For example, you are critical of
anyone whose name begins with "X". (Incidentally, please remember that
in all of this, no amount of consistency checking will ever ensure that
the data that you enter are correct. What it will do is catch obvious
mistakes. If you COULD somehow identify correct records, you wouldn't
need to input them, you could just calculate them.)

In your case, you'd likely have lots of other criteria to list here.

[Q_FindFaults] SQL:

SELECT ContactList.ContactList_ID,
(IIf((Right$([ContactList]![Contact Name],5)="troyd")
Or (UCase$(Left$([ContactList]![Contact Name],1))="X"),-1,0)) AS Bad1,
IIf(InStr([ContactList]![Address 1],"Baker")>0,-1,0) AS Bad2,
IIf(Left$([ContactList]![Post Code],3)="2V5",-1,0) AS Bad3
FROM ContactList;

Hmmmm... it seems we have some apparent mistakes here.

[Q_FindFaults] Query Datasheet View:

ContactList_ID Bad1 Bad2 Bad3
-------------- ---- ---- ----
-1488856006 -1 0 0
-1397802452 0 0 -1
2014364093 0 0 0
2085843127 -1 -1 -1

What I do next is to tabulate these into two columns so that I can add
them up easily.

[Q_FindFaults2] SQL:

SELECT Q_FindFaults.ContactList_ID, Q_FindFaults.Bad1 as Bad
FROM Q_FindFaults WHERE Bad1<>0
UNION ALL
SELECT Q_FindFaults.ContactList_ID, Q_FindFaults.Bad2
FROM Q_FindFaults WHERE Bad2<>0
UNION ALL
SELECT Q_FindFaults.ContactList_ID, Q_FindFaults.Bad3
FROM Q_FindFaults WHERE Bad3<>0;

Notice that a record might have multiple mistakes.

[Q_FindFaults2] Query Datasheet View:

ContactList_ID Bad
-------------- ---
2085843127 -1
-1488856006 -1
2085843127 -1
2085843127 -1
-1397802452 -1

Now I add up the mistakes and subtract from the total number of fields
(4 in this case, but you'd probably use something more like 20).

[Q_FindFaults3] SQL:

SELECT Q_FindFaults2.ContactList_ID,
4+[SumOfBad] AS ScoreFromQuery,
Sum(Q_FindFaults2.Bad) AS SumOfBad
FROM Q_FindFaults2
GROUP BY Q_FindFaults2.ContactList_ID;

and the results give you a score (in the [ScoreFromQuery] field) similar
to what you described.

[Q_FindFaults3] Query Datasheet View:

ContactList_ID ScoreFromQuery SumOfBad
-------------- -------------- --------
-1488856006 3 -1
-1397802452 3 -1
2085843127 1 -3

HOWEVER... depending on how tricky your criteria are, you might prefer
to write a VBA function to do the same calculations. The following code
is faulty, however, as it omits all the error-checking statements that I
would normally include. (Some people object to including error-checking
stuff on the basis that errors shouldn't occur in the first place, and I
suppose I agree if the software is operating a traffic signal or
surgical equipment.)

Once you have written the basic function (BTW, you need to set a
reference to DAOs for this to work), adding or changing criteria is
pretty easy.

'DataScore() returns the number of valid fields in
' the selected record in the [ContactList] Table
'
Public Function DataScore( _
ByVal RecordID As Long) _
As Integer

'ByVal RecordID As Long 'Primary key of record

Dim CurrentRecord As Recordset 'Record identified _
by RecordID key value
Dim fldField As Field 'One of the data fields

'Grab the selected record
Set CurrentRecord = CurrentDb.OpenRecordset _
("SELECT * FROM [ContactList] " _
& "WHERE [ContactList_ID] = " _
& RecordID & ";", _
dbOpenSnapshot)

'Start by assuming all fields to be valid
DataScore = CurrentRecord.Fields.Count

For Each fldField In CurrentRecord.Fields

'Look for whatever might be wrong in the field
Select Case fldField.Name

Case "Contact Name"
If Right$(fldField.Value, 5) = "troyd" _
Then DataScore = DataScore - 1
If UCase$(Left$(fldField.Value, 1)) = "X" _
Then DataScore = DataScore - 1

Case "Address 1"
If InStr(fldField.Value, "Baker") > 0 _
Then DataScore = DataScore - 1

Case "Post Code"
If Left$(fldField.Value, 3) = "2V5" _
Then DataScore = DataScore - 1

End Select 'Case fldField.Name

Next fldField

End Function 'DataScore()

You can refer to your DataScore() function in SQL similarly to this:

[Q_Scores] SQL:

SELECT ContactList.*,
DataScore([ContactList]![ContactList_ID]) AS Score,
Q_FindFaults3.ScoreFromQuery AS QScore
FROM ContactList LEFT JOIN Q_FindFaults3
ON ContactList.ContactList_ID = Q_FindFaults3.ContactList_ID
ORDER BY DataScore([ContactList]![ContactList_ID]) DESC;

and the results show both sets of scores. You'll notice that one of the
[QScore] values is missing (no faults found on that record), but if you
need it you can take care of it by modifying the Query.

[Q_Scores] Query Datasheet View:

ContactList_ID Contact Name Address 1 Post Code Score QScore
-------------- --------------- ---------- --------- ----- ------
2014364093 Rumpelstiltskin 85 Palace 0H1-B0Y 4
-1488856006 xxx None 0X0-X0X 3 3
-1397802452 Smith 9 Downing 2V5-X2Z 3 3
2085843127 Murgatroyd 23-B Baker 2V5-L8N 1 1

-- Vincent Johns <[email protected]>
Please feel free to quote anything I say here.
 
G

Guest

Thank Vincent for your time and understanding. Your help is really
appreciated and you are a credit to this site.

Thanks again, I will disect your code and plan my database
accordingly...Very nervous I have to say ha ha
 

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