Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Grid go recno()+1/-1 with index set order to

Status
Not open for further replies.
Sep 17, 2001
672
US
So I have a grid with a table that has an index and set order to. Since the order changes the recno() order when I try to do go recno()+1 or recno()-1 it causes the the grid row to jump around rather than go 1 up or down. Is there another way to be able to move 1 up or down when the recno() is not in order?

Regards,

Rob
 
Sure. Just use skip. You can also say skip -1, skip 2, 3, whatever. easy peasey. Skip uses the current index order. By the way, the recno() never changes unless you do a sort (NEVER bother with a sort) or if you do a pack and there are deleted records or if you copy to another table with an index order in place. Then the new table has the new recno order.
 
To move forward in the table one record at a time:

Code:
SKIP
IF EOF()
  SKIP - 1
ENDIF

To move back one record at a time:

Code:
IF NOT BOF()
  SKIP -1
ENDIF

The tests for eof (end of file) and bof (beginnning of file) are essential, otherwise you risk getting an error.

After executing the above commands, you might need to set focus (THIS.SetFocus) on the grid to make the change visible (you do NOT need to refresh the grid).

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
+Doug (I agree fully with Doug), the SORT command is actually not in my active vocabulary. As we have SKIP SET ORDER is completely sufficient to sort and display and, well, SKIP in any sort order.

Rob, I wonder how you could live without knowing SKIP, it's essential in the legacy way to do a WHILE !EOF() loop not using SCAN...ENDSCAN. At the end of such a WHILE !OEF() loop you have to SKIP 1, as otherwise, the loop will never get to EOF(), SCAN..ENDSCAN does that automatically.

+Mike (I agree fully with Mike), it's also important to think of the corner cases - here begin/end of file cases. Notice, Rob, no matter how an Index changes order from recno order, skipping past the last record in sort order always positions the record pointer at an EOF byte, that also means you can only check that after the SKIP. What's slightly off the point with Mikes code is that BOF also only turns .T. after SKIP -1 from the first record, see here:

Code:
CREATE CURSOR crsTest (sortorder int)
INSERT INTO crsTest VALUES (2)
INSERT INTO crsTest VALUES (1)
INSERT INTO crsTest VALUES (4)
INSERT INTO crsTest VALUES (3)
INDEX on sortorder TAG xSort
GO 2
? RECNO(),BOF()
SKIP -1
? RECNO(),BOF()
GO 3
? RECNO(),EOF()
SKIP +1
? RECNO(),EOF()
I intentionally put the lowest and highest values 1 and 4 into the middle of the data at record 2 and 3.

First I explicitly GO 2 and at that moment BOF() is not yet .T., SKIP -1 activates BOF() and automatically stays at RECNO()=2. Mikes code is correctly NOT doing a SKIP +1 in that case, as VFP stays at recno 2 already. But BOF() only became .T. after you are at recno=2, SKIP -1 and still are on recno=2.

The difference with EOF() becomes clear with the code starting with GO 3 to manually go to the last record with value 4. The Skip +1 actually finds a RECNO() 5, even though we only have 4 records. The EOF is an extra byte after the last record. When you add a record this byte becomes the deleted flag of that new record and a new EOF byte is added after that. That byte position within the DBF actually is where a recno 5 starts (or will start). This is also the reason EOF is a special place in the data and REPLACE "misbehaves" at this position and doesn't replace nor error. That's the unpopular "It's by design". It's a reason Mike does SKIP -1 in that case, to get back to really point to the last record of the data. So, Mike, I see you know this subtle difference.

By the way: FOUND() also simply is NOT EOF().

The easy way out of any error of a SKIP +/-N is using TRY CATCH to do the SKIP command. The only thing to care about, if you care about it is, that when you SKIP forward EOF really means the record pointer is positioned after the last record, whereas when BOF() becomes .T. you know you're positioned on the first record and not any byte before it. So in case you SKIP within TRY CATCH you FINALLY only need to SKIP -1 in case of EOF().

Also notice, you can't explicitly GO 5, that's causing a "Record is out of range" error. That's also what happens even to experienced developers storing RECNO() as current position and trying to go back with GO, it fails in such corner cases and there are more, when you use buffering and new records have negative recnos before they are committed with TABLEUPDATE or by locating another record while buffering is only record buffering instead of table buffering. You then can't go back to -1, for example, it turned to recno being the new RECCOUNT().

So this whole construction leads to many problems and caused many curses, for sure. I can't think of a better concept, it might be slightly better, if BOF also was an extra byte, simply the last byte of the header part of a DBF, that would make behavior fully symmetrical, you could be at RENCO=0 but never be able to GO 0, for example, BOF would also be a place outside of the range of records, etc. The asymmetry then would only be, that extra BOF byte would not be at RECSIZE() distance to the first byte of recno 1, it would always be only 1 byte before it.

The sorting an index causes, must have begin and end somehow, and so the record pointer positioning is special about this and an asymmetry about BOF() EOF() boolean states is that RECNO() being a valid or "virtual" record number. GO Recno, therefore, is a bit flawed.

Knowing SKIP is essential anyway.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top