2.6x
WINDOWS
kbtool kbcode kbfixlist kbbuglist
The information in this article applies to:
- Microsoft FoxPro for Windows, versions 2.6x
SYMPTOMS
When the SCREEN WIZARD has been used to create a screen for two or more
related tables, clicking the LOCATE button can produce this error message:
Invalid function argument value, type, or count.
CAUSE
In the LOC_DLOG procedure for the LOCATE button, OBJVAR is used to provide
the name of the memory variable, array element, or field associated with an
object. However, OBJVAR is returning a NULL value rather than a CHARACTER
value during a READ, which causes the error message.
RESOLUTION
NOTE: In Visual FoxPro, the One-To-Many Form Wizard is used for related
tables. The One-To-Many Wizard does not have this problem.
To avoid this message, perform one of the following resolutions.
Resolution 1
Change the following line of code in the .SPR from
DO WHILE !EMPTY(OBJVAR(m.i))
to the following:
DO WHILE TYPE("OBJVAR(m.i)") = "C"
By checking the return type of the function, the error will not occur, and
the loop will not continue, which is the purpose of checking EMPTY().
Resolution 2
Change the LOC_DLOG procedure in the .SPR file.
You can have the BROWSE window that is executed in the LOCATE button
display all fields from the parent table or display only the fields
included in the screen. For example, a screen may have been created that
holds only the CNO and COMPANY fields from the CUSTOMER table; in this
case, the BROWSE should display only the fields CNO and COMPANY, not all
fields from CUSTOMER.
How to Display all Fields from a Table in the BROWSE:
- Add the following to the SETUP code prior to #REGION 0:
PUBLIC myprog
myprog=PROGRAM() && Store name of the screen currently running.
mypath=FULLPATH(myprog) && Store the full path of the screen.
- Replace the existing LOC_DLOG PROCEDURE in the CLEANUP code of the .SCX
file with this code:
PROCEDURE loc_dlog
PRIVATE gfields,i
DEFINE WINDOW wzlocate FROM 1,1 TO 20,40;
SYSTEM GROW CLOSE ZOOM FLOAT FONT "MS Sans Serif",8
MOVE WINDOW wzlocate CENTER
** Save the name of the currently used table:
cur_tbl=ALIAS()
** Get the full path of where the .SCX table for this screen is:
myscx= ;
SUBSTR(FULLPATH(myprog+'.spr'),1,ATC('.',FULLPATH(myprog+'.spr'))-1)
** If the screen table isn't open, open it:
IF !USED(myscx+'.scx')
SELECT 0
USE (myscx)+'.scx' AGAIN
ELSE
SELECT (myscx)+'.scx'
ENDIF
** Get all name fields where objtype=15 and objcode=1
** objtype = 15 and objcode = 1 are the field names used
** in the screen
COUNT FOR objtype=15 AND objcode=1 TO mnum
** Create an array to hold the field names used in the screen:
DIMENSION test[mnum]
j = 1
** Select the main, original table:
SELECT (cur_tbl)
m.gfields=SET('FIELDS',2)
IF !EMPTY(RELATION(1))
SET FIELDS ON
IF m.gfields # 'GLOBAL'
SET FIELDS GLOBAL
ENDIF
IF EMPTY(FLDLIST())
m.i=1
** Select the screen's database:
SELECT (myprog)
SET FIELDS TO
SET FILTER TO objtype=15 AND objcode=1
GO TOP
** Grab the field names and place into array:
* NOTE: If all the field objects are changed to memory
* variables, this DO WHILE loop will go into an infinite loop.
* SKIP only occurs when the entry is NOT a memory variable.
* Also, if m.memvar is used, the "M." will not match it.
DO WHILE !EOF()
FOR j = 1 TO mnum
IF ATC('M.',MLINE(name,1))=0
test[j]=MLINE(name,1)
SKIP
ENDIF
NEXT
ENDDO
SET FILTER TO
SELECT (cur_tbl)
SET FIELDS ON
SET FIELDS GLOBAL
j = 1
FOR j = 1 TO mnum
SET FIELDS TO (test[j])
NEXT
ENDIF
ENDIF
** Close the screen file that was used:
IF USED(myprog)
SELECT (myprog)
USE
SELECT (cur_tbl)
ENDIF
BROWSE WINDOW wzlocate NOEDIT NODELETE ;
NOMENU TITLE C_BRTITLE
SET FIELDS &gfields
SET FIELDS OFF
RELEASE WINDOW wzlocate
RELEASE test && Release the array from memory.
RETURN
How to Display Only the Fields Included in the Screen in the BROWSE:
- Add the following code to the SETUP code prior to #REGION 0:
PUBLIC myprog
myprog=PROGRAM() && Store name of the screen currently running.
mypath=FULLPATH(myprog) && Store the full path of the screen.
- Replace the existing LOC_DLOG PROCEDURE in the CLEANUP code of the .SCX
file with this code:
PROCEDURE loc_dlog
PRIVATE gfields,i
DEFINE WINDOW wzlocate FROM 1,1 TO 20,40;
SYSTEM GROW CLOSE ZOOM FLOAT FONT "MS Sans Serif",8
MOVE WINDOW wzlocate CENTER
cur_tbl=ALIAS()
myscx ;
=SUBSTR(FULLPATH(myprog+'.spr'),1,ATC('.',FULLPATH(myprog+'.spr'))-1)
IF !USED(myscx+'.scx')
SELECT 0
USE (myscx)+'.scx' AGAIN
ELSE
SELECT (myscx)+'.scx'
ENDIF
SET FILTER TO objtype=2
GO TOP
** Get all expr fields where objtype=2:
COUNT FOR objtype=2 TO mnum
GO TOP
curr_dbf = LEFT(MLINE(name,1),ATC('.dbf',MLINE(name,1))-1)
SELECT (curr_dbf)
num_flds1=FCOUNT()
SELECT (cur_tbl)
m.gfields=SET('FIELDS',2)
IF !EMPTY(RELATION(1))
SET FIELDS ON
IF m.gfields # 'GLOBAL'
SET FIELDS GLOBAL
ENDIF
IF EMPTY(FLDLIST())
m.i=1
FOR k = 1 TO fcount()
SET FIELDS TO (FIELD(k))
NEXT
ENDIF
ENDIF
** Close the screen file that was used:
IF USED(myprog)
SELECT (myprog)
USE
SELECT (cur_tbl)
ENDIF
BROWSE WINDOW wzlocate NOEDIT NODELETE ;
NOMENU TITLE C_BRTITLE
SET FIELDS &gfields
SET FIELDS OFF
RELEASE WINDOW wzlocate
RETURN
STATUS
Microsoft has confirmed this to be a problem in the Microsoft products
listed at the beginning of this article. This problem was corrected in
Visual FoxPro 3.0 for Windows.
MORE INFORMATION
Steps to Reproduce Problem
- Enter these commands:
SELECT 0
USE tutorial\customer
SELECT 0
USE tutorial\invoices
INDEX ON cno TAG cno
SET ORDER TO TAG cno
SELECT customer
SET RELATION TO cno INTO invoices
SET SKIP TO invoices
- Choose Wizard from the Run menu, and select Screen.
- Add all fields from both tables. Select all the remaining defaults. Save
as OBJVAR.
- Enter this command:
DO objvar.spr
- As soon as the screen appears, click the LOCATE button. At this point,
you'll see the error message:
Invalid function argument value, type, or count.
|