784.TXT ===================================================================== Using Scrolling Cursors ===================================================================== PRODUCT: R:BASE VERSION: 4.5+ or Higher ===================================================================== CATALOG: Programmin in R:BASE AREA : Logic & Data Manipulation R:BASE 4.5 Plus! introduced the concept of scrolling cursors. When a cursor is defined as a scrolling cursor, you gain the capability of moving both forwards and backwards through the rows of data and can also jump past rows. A regular cursor only moves forward through rows, one row at a time. To define a cursor as a scrolling cursor, include the word SCROLL in the DECLARE CURSOR command. For example, DECLARE c1 SCROLL CURSOR FOR SELECT ... The word SCROLL comes right after the cursor name. If SCROLL is not included in the cursor definition, the cursor can only move forward through the rows one at a time. Once a cursor is defined as a scrolling cursor, a number of additional options on the FETCH command become available. These options are as follows; note that the directions and positions are based on the order of the rows as specified by the DECLARE CURSOR command, not on the order of the rows in the actual table: NEXT - The default option if none is specified on the FETCH command. NEXT moves the cursor forward through the rows, it gets the next available row based on the current cursor position. NEXT steps through the rows one-by-one going forward. PRIOR - Moves the cursor backwards through the rows. The PRIOR option gets the previous row based on the current cursor position, and steps through the rows one-by-one going backwards. FIRST - Moves the cursor from its current position to the first row. This option jumps immediately to the first row as determined by the DECLARE CURSOR command. A FETCH NEXT then finds the second row. The cursor is repositioned at the beginning of the set of rows. LAST - Moves the cursor from its current position immediately to the last row as specified by the DECLARE CURSOR command. A FETCH PRIOR then finds the next to last row; a FETCH NEXT returns "end of data encountered". LAST jumps over the rows between the current cursor position and the last row. ABSOLUTE n - Moves the cursor the specified number of rows from the first row of data as determined by the DECLARE CURSOR and OPEN commands. A positive number must be specified; you can't use this option to move backwards. The intervening rows are jumped over. You can't jump past the last row; if the number given is greater than the number of rows retrieved, an "end of data" error is returned. RELATIVE n - Moves the cursor the specified number of rows from the current cursor position. This option moves the cursor either forwards or backwards - forwards if a positive number is specified, backwards if a negative number is specified. The intervening rows are jumped over. You can't jump past the last row or the first row; an "end of data" error is returned if the specified number would take you past the beginning or end of the selected rows. An example To see how a scrolling cursor can be used in an application, imagine you have a group of customers to contact each day. The scrolling cursor retrieves the list of customers for today. They are ordered by company name. The first row is brought up in a menuless form. The form remains on the screen when you are done with the record, and a menu pops up giving the user choices as to which record to select next. You can: move through the list of customers one-by-one both forwards and backwards jump to the last record and back to the first record jump past a group of records search for a particular record by last name or by company name Each time you select a record, the cursor is repositioned ready for the next selection. The ASCII menu file: walklist POPUP |Next Customer| |Previous Customer| |Jump Forward "n"| |Jump Backward "n"| |Last Customer| |First Customer| |Search by Lastname| |Search by Company| ENDC *(WALKLIST.CMD scroll through a list of customers ) SET MESSAGE OFF SET ERROR MESSAGE OFF DROP CURSOR C1 CLS DECLARE C1 scroll CURSOR FOR + SELECT CustId, LastName, Company FROM Customer + WHERE calldate = .#DATE ORDER BY Company OPEN C1 FETCH FIRST FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany WHILE SQLCODE <> 100 THEN EDIT USING cust WHERE CustId = .VCustId CHOOSE VAction FROM WALKLIST.MNU AT 10 51 FOOT IF VAction = '[ESC]' THEN RETURN ENDIF SWITCH (.VAction) CASE 'Next Customer' FETCH NEXT FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany IF SQLCODE = 100 THEN FETCH LAST FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany ENDIF BREAK CASE 'Previous Customer' FETCH PRIOR FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany IF SQLCODE = 100 THEN FETCH FIRST FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany ENDIF BREAK CASE 'Jump Forward "n"' DIALOG 'How many to jump forward' VNum=4 VEndKey 1 SET VAR VPlus = (INT(.VNum)) FETCH RELATIVE .vplus FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany IF SQLCODE = 100 THEN FETCH LAST FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany ENDIF BREAK CASE 'Jump Backward "n"' DIALOG 'How many to jump backward' VNum=4 VEndKey 1 SET VAR VMinus = (INT(.VNum) * -1) FETCH RELATIVE .vminus FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany IF SQLCODE = 100 THEN FETCH FIRST FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany ENDIF BREAK CASE 'Last Customer' FETCH LAST FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany BREAK CASE 'First Customer' FETCH FIRST FROM C1 INTO + VCustId ICustId, VLastname ILastname, + VCompany ICompany BREAK CASE 'Search by Lastname' SET VAR vsearch = NULL DIALOG 'Enter the last name to find' + VSearch VEndKey 1 at 12 IF VEndKey = '[Esc]' THEN BREAK ENDIF WHILE #PI <> 0.0 THEN FETCH NEXT FROM c1 INTO + VCustID ICustId, VLastname ILastname, + VCompany ICompany IF VLastname CONT .VSearch THEN BREAK ENDIF IF SQLCODE = 100 THEN DIALOG + 'No match found. Continue search from beginning?' + VResp VEndKey YES IF VEndKey = '[Esc]' THEN BREAK ENDIF IF VResp = 'YES' THEN FETCH FIRST FROM c1 INTO + VCustID ICustId, VLastname ILastname, + VCompany ICompany IF VLastname CONT .VSearch THEN BREAK ENDIF ELSE FETCH LAST FROM c1 INTO + VCustID ICustId, VLastname ILastname, + VCompany ICompany BREAK ENDIF ENDIF ENDWHILE BREAK CASE 'Search by Company' SET VAR VSearch = NULL DIALOG 'Enter the company to find' + VSearch VEndKey 1 at 12 IF VEndKey = '[Esc]' THEN BREAK ENDIF WHILE #PI <> 0.0 THEN FETCH NEXT FROM c1 INTO + VCustID ICustId, VLastname ILastname, + VCompany ICompany IF VCompany CONT .VSearch THEN BREAK ENDIF IF SQLCODE = 100 THEN DIALOG + 'No match found. Continue search from beginning?' + VResp VEndKey YES IF VEndKey = '[Esc]' THEN BREAK ENDIF IF VResp = 'YES' THEN FETCH FIRST FROM c1 INTO + VCustID ICustId, VLastname ILastname, + VCompany ICompany IF VCompany CONT .VSearch THEN BREAK ENDIF ELSE FETCH LAST FROM c1 INTO + VCustID ICustId, VLastname ILastname, + VCompany ICompany BREAK ENDIF ENDIF ENDWHILE BREAK ENDSW ENDWHILE DROP CURSOR C1 RETURN Define the scrolling cursor Open the cursor and get the first row Bring up the form with the data from the first row. After the form is exited, choose from the menu which record to retrieve next The switch/case block determines which record to retrieve Move forward one row at a time If already on the last row, stay there Move backward one row at a time If already on the first row, stay there Move forward the specified number of records R:BASE counts from the current cursor position If the number of records to jump past takes you beyond the last record, the last record is retrieved Move backward the specified number of records R:BASE counts from the current cursor position If the number of records to jump past takes you beyond the first record, the first record is retrieved Jump to the last record Next customer from the last record returns end-of-data Jump to the first record Prior customer from the first record returns end-of-data Prompt for the last name to find Search forward for a matching record If a match is found, the row is displayed and the cursor repositioned at that row If no match was found, the search can be continued from the first row. If the search is not continued, the last row is retrieved Prompt for the company name to find Search forward for a matching company record If a match is found, the row is displayed and the cursor repositioned at that row If no match was found, the search can be continued from the first row. If the search is not continued, the last row is retrieved.