*--------------------------------------------------------------------------------------------------------------------------------------------------------
* (EN) AUTOGENERATED - ATTENTION!! - NOT INTENDED FOR EXECUTION!! USE ONLY FOR MERGING CHANGES AND STORING WITH SCM TOOLS!!
*--------------------------------------------------------------------------------------------------------------------------------------------------------
*< FOXBIN2PRG: Version="1.21" SourceFile="_table.vcx" CPID="1252" /> (Solo para binarios VFP 9 / Only for VFP 9 binaries)
*
*
DEFINE CLASS _filterdialog AS _form OF "_base.vcx"
*< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" />
*-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder
*< OBJECTDATA: ObjPath="shpExpressionFrame" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="shpFilterFrame" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="lblOrder" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="lblTables" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="lblCriteria" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cboOperator" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="edtSought" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdAdd" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="lstQueryParts" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cboOrder" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cboTables" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdOK" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdReset" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdCancel" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdDelete" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdUp" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdDown" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdOr" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cboFieldname" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cusTable" UniqueID="" Timestamp="" />
#INCLUDE "_table.h"
*
*m: brackets
*m: cleanparens
*m: editquery
*m: fset
*m: nobrack
*m: notag
*m: ontag
*m: qreset
*m: qset
*m: setaction
*m: setinitialqueryparts
*m: setrowsources
*m: settags
*m: setupfilter && This takes the conditions listed in the dialog and rationalizes them into a filter expression (it also applies the NORMALIZE() function to the expression).
*p: cfilter && This is the filter expression.
*p: coldexact
*p: ibact
*p: iqptr
*p: iquerymax
*p: iselect
*p: ocaller
*a: adbfs[1,0]
*a: aflds[1,0]
*a: aquery[1,0]
*a: atags[1,0]
*
*
AutoCenter = .T.
BorderStyle = 0
Caption = ("Filter Conditions ")
cfilter = ("")
ClipControls = .F.
Closable = .T.
coldexact = ("OFF")
DoCreate = .T.
FontName = "MS Sans Serif"
FontSize = 8
HalfHeightCaption = .F.
Height = 326
ibact = 0
iqptr = 0
iquerymax = 50
iselect = 0
MaxButton = .F.
MinButton = .T.
Movable = .T.
Name = "_filterdialog"
ocaller = .NULL.
Width = 389
ZoomBox = .F.
*
ADD OBJECT 'cboFieldname' AS _combobox WITH ;
BorderStyle = 1, ;
Enabled = .T., ;
FontBold = .F., ;
FontName = "MS Sans Serif", ;
FontSize = 9, ;
Height = 20, ;
Left = 12, ;
Name = "cboFieldname", ;
ReleaseErase = .F., ;
RowSource = "", ;
RowSourceType = 5, ;
Sorted = .F., ;
SpecialEffect = 0, ;
Style = 2, ;
TabIndex = 5, ;
Top = 46, ;
Value = 1, ;
Width = 108
*< END OBJECT: ClassLib="_base.vcx" BaseClass="combobox" />
ADD OBJECT 'cboOperator' AS _combobox WITH ;
Enabled = .T., ;
FirstElement = 1, ;
FontBold = .F., ;
FontName = "MS Sans Serif", ;
FontSize = 9, ;
Height = 20, ;
Left = 127, ;
Name = "cboOperator", ;
ReleaseErase = .F., ;
RowSource = "=,<>,<,>,<=,>=,==,IN", ;
RowSourceType = 1, ;
Sorted = .T., ;
SpecialEffect = 0, ;
Style = 2, ;
TabIndex = 6, ;
Top = 46, ;
Value = ("="), ;
Width = 32
*< END OBJECT: ClassLib="_base.vcx" BaseClass="combobox" />
ADD OBJECT 'cboOrder' AS _combobox WITH ;
BorderStyle = 1, ;
Enabled = .T., ;
FontBold = .F., ;
FontName = "MS Sans Serif", ;
FontSize = 9, ;
Height = 20, ;
Left = 271, ;
Name = "cboOrder", ;
ReleaseErase = .F., ;
RowSourceType = 5, ;
Sorted = .F., ;
SpecialEffect = 0, ;
Style = 2, ;
TabIndex = 4, ;
Top = 5, ;
Value = 1, ;
Width = 112
*< END OBJECT: ClassLib="_base.vcx" BaseClass="combobox" />
ADD OBJECT 'cboTables' AS _combobox WITH ;
BorderStyle = 1, ;
Enabled = .T., ;
FontBold = .F., ;
FontName = "MS Sans Serif", ;
FontSize = 9, ;
Height = 20, ;
Left = 50, ;
Name = "cboTables", ;
ReleaseErase = .F., ;
RowSourceType = 5, ;
Sorted = .F., ;
SpecialEffect = 0, ;
Style = 2, ;
TabIndex = 2, ;
Top = 5, ;
Value = 1, ;
Width = 155
*< END OBJECT: ClassLib="_base.vcx" BaseClass="combobox" />
ADD OBJECT 'cmdAdd' AS _commandbutton WITH ;
AutoSize = .F., ;
Caption = "\
ADD OBJECT 'cmdCancel' AS _commandbutton WITH ;
AutoSize = .F., ;
Cancel = .T., ;
Caption = "Cancel", ;
FontName = "MS Sans Serif", ;
FontSize = 9, ;
Height = 25, ;
Left = 204, ;
Name = "cmdCancel", ;
ReleaseErase = .F., ;
TabIndex = 17, ;
Top = 288, ;
Width = 51
*< END OBJECT: ClassLib="_base.vcx" BaseClass="commandbutton" />
ADD OBJECT 'cmdDelete' AS _commandbutton WITH ;
AutoSize = .F., ;
Caption = "\
ADD OBJECT 'cmdDown' AS _commandbutton WITH ;
AutoSize = .F., ;
Caption = "Do\
ADD OBJECT 'cmdOK' AS _commandbutton WITH ;
AutoSize = .F., ;
Caption = "OK", ;
FontName = "MS Sans Serif", ;
FontSize = 9, ;
Height = 25, ;
Left = 128, ;
Name = "cmdOK", ;
ReleaseErase = .F., ;
TabIndex = 16, ;
Top = 288, ;
Width = 51
*< END OBJECT: ClassLib="_base.vcx" BaseClass="commandbutton" />
ADD OBJECT 'cmdOr' AS _commandbutton WITH ;
AutoSize = .F., ;
Caption = "\
ADD OBJECT 'cmdReset' AS _commandbutton WITH ;
AutoSize = .F., ;
Caption = "\
ADD OBJECT 'cmdUp' AS _commandbutton WITH ;
AutoSize = .F., ;
Caption = "\
ADD OBJECT 'cusTable' AS _table WITH ;
Left = 211, ;
Name = "cusTable", ;
Top = 4
*< END OBJECT: ClassLib="_table.vcx" BaseClass="custom" />
ADD OBJECT 'edtSought' AS _editbox WITH ;
AllowTabs = .F., ;
BorderStyle = 1, ;
DisabledBackColor = 223,223,223, ;
Enabled = .T., ;
FontName = "MS Sans Serif", ;
FontSize = 9, ;
Format = "3K", ;
Height = 20, ;
Left = 164, ;
Margin = 0, ;
Name = "edtSought", ;
ReleaseErase = .F., ;
ScrollBars = 0, ;
SpecialEffect = 0, ;
TabIndex = 7, ;
Top = 46, ;
Width = 212
*< END OBJECT: ClassLib="_base.vcx" BaseClass="editbox" />
ADD OBJECT 'lblCriteria' AS _label WITH ;
AutoSize = .T., ;
Caption = (" Criteria "), ;
DisabledBackColor = 225,225,225, ;
FontName = "MS Sans Serif", ;
FontSize = 9, ;
Height = 15, ;
Left = 13, ;
Name = "lblCriteria", ;
ReleaseErase = .F., ;
TabIndex = 8, ;
Top = 90, ;
Width = 40
*< END OBJECT: ClassLib="_base.vcx" BaseClass="label" />
ADD OBJECT 'lblOrder' AS _label WITH ;
AutoSize = .T., ;
BackStyle = 0, ;
Caption = ("Ord\
ADD OBJECT 'lblTables' AS _label WITH ;
AutoSize = .T., ;
BackStyle = 0, ;
Caption = ("\
ADD OBJECT 'lstQueryParts' AS _listbox WITH ;
Enabled = .F., ;
FontName = "MS Sans Serif", ;
FontSize = 9, ;
Height = 126, ;
IntegralHeight = .T., ;
Left = 14, ;
Name = "lstQueryParts", ;
ReleaseErase = .F., ;
RowSourceType = 5, ;
SpecialEffect = 0, ;
TabIndex = 9, ;
Top = 107, ;
Value = 1, ;
Width = 359
*< END OBJECT: ClassLib="_base.vcx" BaseClass="listbox" />
ADD OBJECT 'shpExpressionFrame' AS _shape WITH ;
BackStyle = 0, ;
FillStyle = 1, ;
Height = 46, ;
Left = 5, ;
Name = "shpExpressionFrame", ;
ReleaseErase = .F., ;
SpecialEffect = 0, ;
Top = 34, ;
Width = 379
*< END OBJECT: ClassLib="_base.vcx" BaseClass="shape" />
ADD OBJECT 'shpFilterFrame' AS _shape WITH ;
BackStyle = 0, ;
FillStyle = 1, ;
Height = 179, ;
Left = 4, ;
Name = "shpFilterFrame", ;
ReleaseErase = .F., ;
SpecialEffect = 0, ;
Top = 98, ;
Width = 379
*< END OBJECT: ClassLib="_base.vcx" BaseClass="shape" />
PROCEDURE Activate
LOCAL lidbc, liIndex
LOCAL ARRAY laTemp[1,2]
lidbc=AUSED(laTemp)
THIS.iSelect = SELECT()
THIS.cOldExact = SET("EXACT")
SET EXACT OFF
IF lidbc # ALEN(THIS.aDbfs) OR ;
EMPTY(THIS.aDbfs[1]) && empty array will happen only the first time
WAIT WINDOW NOWAIT LEFT(FILTER_CHECKING_OPEN_TABLES_LOC,254)
IF lidbc = 0
USE ?
IF EMPTY(ALIAS())
WAIT WINDOW LEFT(FILTER_CANCELLED_LOC,254) NOWAIT
NODEFAULT
RETURN .F.
ELSE
lidbc = 1
THIS.aDbfs[1] = PROPER(ALIAS())
THIS.cboTables.Requery()
THIS.cboTables.Value = 1
ENDIF
ELSE
DIME THIS.aDbfs[lidbc]
FOR liIndex = 1 TO lidbc
THIS.aDbfs[liIndex] = PROPER(laTemp[liIndex,1])
ENDFOR
THIS.cboTables.Requery()
ENDIF
WAIT CLEAR
ENDIF
IF EMPTY(ALIAS())
SELECT (THIS.aDbfs[1])
THIS.cboTables.Value = 1
ELSE
THIS.cboTables.Value = ASCAN(THIS.aDbfs,PROPER(ALIAS()))
ENDIF
LOCAL lcFilter
lcFilter = SET("FILTER")
DO CASE
CASE TYPE("THIS.oCaller.Name") = "C"
THIS.SetInitialQueryParts(THIS.oCaller.cFilter)
CASE THIS.SetupFilter() AND ;
(THIS.cFilter == lcFilter)
* don't touch
CASE EMPTY(lcFilter)
THIS.SetInitialQueryParts("")
OTHERWISE
THIS.SetInitialQueryParts(lcFilter)
ENDCASE
THIS.SetAction()
ENDPROC
PROCEDURE brackets
LPARAMETERS tcx, tcb1, tcb2
LOCAL lcout, lii, lcv, lcx
IF SUBSTR(tcx,1,1)=tcb1 AND SUBSTR(tcx,LEN(tcx),1)=tcb2
RETURN tcx
ENDIF
IF THIS.cboOperator.Value = "IN"
RETURN tcb1 + tcx + tcb2
ENDIF
lcout = ""
lcx = tcx
DO WHILE LEN(lcx) > 0
lii = AT(",", lcx)
IF lii = 0
lcv = lcx
lcx = ""
ELSE
lcv = SUBSTR(lcx,1,lii-1)
lcx = IIF(lii=LEN(lcx),"",SUBSTR(lcx,lii+1))
ENDIF
IF LEN(lcout) > 0
lcout = lcout + ","
ENDIF
lcout = lcout + tcb1 + lcv + tcb2
ENDDO
RETURN lcout
ENDPROC
PROCEDURE cleanparens
LPARAMETERS piItem
*-
*- remove parens from filter
*- Called from cmdDelete:Click and THISFORM:Init
*-
LOCAL i, lcItem
lcItem = THISFORM.aQuery[piItem]
DO WHILE .T.
*- there may be multiple sets of parentheses, so loop through
*- till we get rid of all of them
DO CASE
CASE OCCURS("(", lcItem) == OCCURS(")",lcItem)
*- ignore, since same number of left and right parens are on this item
EXIT
CASE LEFT(lcItem,1) == "("
*- scan forward, looking for matching ")"
FOR i = piItem TO ALEN(THISFORM.aquery,1)
IF RIGHT(THISFORM.aQuery[i],1) == ")"
THISFORM.aQuery[i] = LEFT(THISFORM.aquery[i],LEN(THISFORM.aquery[i]) - 1)
lcItem = IIF(i == piItem, THISFORM.aQuery[i], lcItem)
EXIT
ENDIF
NEXT
lcItem = SUBSTR(lcItem,2) && strip left paren
CASE RIGHT(lcItem,1) == ")"
*- scan backward, looking for matching "("
FOR i = piItem TO 1 STEP -1
IF LEFT(THISFORM.aQuery[i],1) == "("
THISFORM.aQuery[i] = SUBSTR(THISFORM.aquery[i],2)
lcItem = IIF(i == piItem, THISFORM.aQuery[i], lcItem)
EXIT
ENDIF
NEXT
lcItem = LEFT(lcItem, LEN(lcItem) - 1) && strip right paren
OTHERWISE
*- nothing to do
EXIT
ENDCASE
ENDDO
RETURN
ENDPROC
PROCEDURE Deactivate
LOCAL lcExact
lcExact = THIS.cOldExact
SET EXACT &lcExact
SELECT (THIS.iSelect)
ENDPROC
PROCEDURE editquery
LPARAMETERS tcx
LOCAL lcvar, lii, lcorig, lcout, lcv, lcx
lcorig = tcx
lii = AT(" ", tcx)
IF lii = 0
RETURN lcorig
ENDIF
lcvar = SUBSTR(tcx,1,lii-1)
lcx = SUBSTR(tcx,lii+1)
lii = AT(" ", lcx)
THIS.cboOperator.Value = SUBSTR(lcx,1,lii-1)
lcx = SUBSTR(lcx,lii+1)
IF THIS.cboOperator.Value # "IN"
RETURN lcorig
ENDIF
lcout = "("
DO WHILE LEN(lcx) > 0
lii = AT(",", lcx)
IF lii = 0
lcv = lcx
lcx = ""
ELSE
lcv = SUBSTR(lcx,1,lii-1)
lcx = IIF(lii=LEN(lcx),"",SUBSTR(lcx,lii+1))
ENDIF
IF RIGHT(lcout,1) # "("
lcout = lcout + " OR "
ENDIF
lcout = lcout + lcvar + "=" + lcv
ENDDO
lcout = lcout + ")"
RETURN lcout
ENDPROC
PROCEDURE fset
LOCAL lcx, lctyp
IF THIS.aQuery(THIS.lstQueryParts.Value) = "*OR*"
STORE .F. TO THIS.cboFieldName.Enabled, ;
THIS.edtSought.Enabled, ;
THIS.cboOperator.Enabled
ELSE
THIS.cbofieldname.Enabled = .T.
IF THIS.cboFieldname.Value = 0
THIS.cboFieldname.Value = 1
THIS.cboOperator.Value = "="
THIS.edtSought.Value = ""
ENDIF
lcx = THIS.NoTag(THIS.aFlds[THIS.cbofieldname.Value])
lctyp = TYPE(lcx)
STORE (lcTyp # "L") TO ;
THIS.cboOperator.Enabled, ;
THIS.edtSought.Enabled
ENDIF
ENDPROC
PROCEDURE Init
LPARAMETERS toCaller
IF NOT DODEFAULT()
RETURN .F.
ENDIF
IF TYPE("toCaller.Name") = "C" AND ;
PEMSTATUS(toCaller,"SetFilter",5) && this dialog is really only supposed
&& to be called by a parent dialog, but
&& what the heck, if you don't call it this way
&& we will set the filter directly...
THIS.oCaller = toCaller
ENDIF
DIME THIS.aQuery[THIS.iQueryMax]
THIS.aQuery = " "
THIS.iqptr = 0
THIS.edtSought.Value = ""
THIS.cboOperator.Value = "="
THIS.SetRowSources()
IF SYSTEM_LARGEFONTS
THIS.SetAll("FontName",DIALOG_LARGEFONT_NAME)
ENDIF
RETURN
ENDPROC
PROCEDURE nobrack
LPARAMETERS tcx
LOCAL lii,lcy,lcC
lcy = ""
FOR lii = 1 TO LEN(tcx)
lcC = SUBSTR(tcx,lii,1)
IF NOT lcC$"'{}"
lcy = lcy + lcC
ENDIF
ENDFOR
RETURN lcy
ENDPROC
PROCEDURE notag
LPARAMETERS tcX
LOCAL lcX
lcX = SUBSTR(tcx,2)
RETURN lcX
ENDPROC
PROCEDURE ontag
LPARAMETERS tcx
LOCAL lcX
lcx = IIF(ASCAN(THIS.aTags,tcx)#0,"*"," ") + tcx
RETURN lcx
ENDPROC
PROCEDURE qreset
THIS.aQuery = " "
THIS.iQptr = 0
THIS.lstQueryParts.Value = 1
THIS.cboOperator.Value = "="
THIS.edtSought.Value = ""
THIS.edtSought.Refresh()
THIS.SetAction()
ENDPROC
PROCEDURE qset
LOCAL lcx, lii, lcFieldname, liDot
IF BETWEEN(1,THIS.lstQueryParts.Value,THIS.iQptr)
lcx = THIS.aQuery(THIS.lstQueryParts.Value)
IF lcx = CHR(205) && "Í" -- should it be "=" ??
RETURN
ENDIF
lii = AT(" ",lcx)
liDot = AT(".",lcx)
IF lii <= 1
THIS.cboOperator.Value = "="
THIS.edtSought.Value = ""
IF TYPE(lcx) = "U" OR liDot = 0 OR ;
UPPER(SUBSTR(lcx,1,liDot)) # UPPER(ALIAS())+"."
THIS.cboFieldname.Value = 1
ELSE
THIS.cboFieldname.Value = ASCAN(THIS.aFlds,THIS.OnTag(SUBSTR(lcx,liDot+1)))
ENDIF
ELSE
lcFieldName = SUBSTR(lcx,1,lii-1)
IF TYPE(lcFieldName) = "U" OR liDot = 0 OR ;
UPPER(SUBSTR(lcFieldName,1,liDot)) # UPPER(ALIAS())+"."
THIS.cboFieldName.Value = 1
ELSE
THIS.cboFieldName.Value = ASCAN(THIS.aFlds,THIS.OnTag(SUBSTR(lcFieldName,liDot+1)))
ENDIF
lcx = SUBSTR(lcx,lii+1)
lii = AT(" ",lcx)
THIS.cboOperator.Value = SUBSTR(lcx,1,lii-1)
THIS.edtSought.Value = THIS.Nobrack(SUBSTR(lcx,lii+1))
ENDIF
THIS.cboFieldName.Refresh
THIS.cboOperator.Refresh
THIS.edtSought.Refresh
ENDIF
ENDPROC
PROCEDURE setaction
DO CASE
CASE THIS.iQptr = 0
STORE .F. TO THIS.cmdReset.Enabled, ;
THIS.cmdOr.Enabled, ;
THIS.cmdOK.Enabled, ;
THIS.lstQueryParts.Enabled, ;
THIS.cmdDelete.Enabled, ;
THIS.cmdUp.Enabled, ;
THIS.cmdDown.Enabled
CASE THIS.lstQueryParts.Value > THIS.iQptr
THIS.cmdOr.Enabled = ;
(THIS.lstQueryParts.Value = THIS.iQptr + 1)
STORE .F. TO THIS.cmdDelete.Enabled, ;
THIS.cmdUp.Enabled, ;
THIS.cmdDown.Enabled
STORE .T. TO THIS.cmdReset.Enabled, ;
THIS.cmdOK.Enabled, ;
THIS.lstQueryParts.Enabled
OTHERWISE
STORE .T. TO THIS.cmdReset.Enabled, ;
THIS.cmdOK.Enabled, ;
THIS.cmdOr.Enabled, ;
THIS.lstQueryParts.Enabled, ;
THIS.cmdDelete.Enabled
THIS.cmdUp.Enabled = ;
(THIS.iQptr # 1 AND THIS.lstQueryParts.Value # 1)
THIS.cmdDown.Enabled = ;
(THIS.iQptr # 1 AND THIS.iQptr # THIS.lstQueryParts.Value)
ENDCASE
ENDPROC
PROCEDURE setinitialqueryparts
LPARAMETERS tcQueryString
ASSERT EMPTY(tcQueryString) OR VARTYPE(tcQueryString) = "C"
DIME THIS.aQuery[THIS.iQueryMax]
THIS.cFilter = ""
THIS.aQuery = " "
THIS.iqptr = 0
IF EMPTY(tcQueryString)
THIS.lstQueryParts.Value = 1
THIS.lstQueryParts.Enabled = .F.
RETURN
ENDIF
LOCAL lcQueryString, lcThisPart, liThisChar, ;
lcStringLength, lcThisChar, lcDelimiters
lcQueryString = NORMALIZE(tcQueryString)
liThisChar = 0
liStringLength = LEN(lcQueryString)
STORE "" TO lcThisPart, lcThisChar, lcDelimiters
DO WHILE .T.
liThisChar = liThisChar + 1
lcThisChar = SUBSTR(lcQueryString,liThisChar,1)
lcThisPart = lcThisPart + lcThisChar
IF INLIST(lcThisChar,["], ['],"[", "]" )
IF (INLIST(lcThisChar,["],[']) AND ;
RIGHT(lcDelimiters,1) = lcThisChar) OR ;
(lcThisChar = "]" AND ;
RIGHT(lcDelimiters,1) = "[")
* finishing an expression
lcDelimiters = LEFT(lcDelimiters, LEN(lcDelimiters)-1)
ELSE
IF lcThisChar # "]"
lcDelimiters = lcDelimiters + lcThisChar
ENDIF
ENDIF
ENDIF
DO CASE
CASE LEN(lcDelimiters) > 0
* we're in an expression
CASE RIGHT(lcThisPart,4) = ".OR."
lcThisPart = LEFT(lcThisPart,LEN(lcThisPart)-4)
THIS.iQptr = THIS.iQptr + 1
THIS.aQuery(THIS.iQptr) = lcThisPart
THIS.iQptr = THIS.iQptr + 1
THIS.aQuery(THIS.iQptr) = "*OR*"
lcThisPart = ""
CASE RIGHT(lcThisPart,5) = ".AND."
lcThisPart = LEFT(lcThisPart,LEN(lcThisPart)-5)
THIS.iQptr = THIS.iQptr + 1
THIS.aQuery(THIS.iQptr) = lcThisPart
lcThisPart = ""
OTHERWISE
* continue
ENDCASE
IF liThisChar = liStringLength OR ;
THIS.iQptr = THIS.iQueryMax
EXIT
ENDIF
ENDDO
* final "part"
THIS.iQptr = THIS.iQptr + 1
THIS.aQuery(THIS.iQptr) = lcThisPart
THIS.lstQueryParts.Value = THIS.iQptr+1
THIS.lstQueryParts.Enabled = .T.
ENDPROC
PROCEDURE setrowsources
THIS.cboFieldName.RowSource = "THISFORM.aFlds"
THIS.cboOrder.RowSource = "THISFORM.aTags"
THIS.cboTables.RowSource = "THISFORM.aDbfs"
THIS.lstQueryParts.RowSource = "THISFORM.aQuery"
ENDPROC
PROCEDURE settags
THIS.aTags[1] = "Record#"
LOCAL iFl
DIME THIS.aTags[TAGCOUNT()+1]
FOR iFl = 2 TO (ALEN(THIS.aTags))
THIS.aTags(iFl) = TAG(iFl-1)
ENDFOR
DIME THIS.aFlds[FCOUNT()]
FOR ifl = 1 TO ALEN(THIS.aFlds)
IF TYPE(FIELD(ifl)) = "G"
THIS.aFlds[ifl] = "\"+FIELD(ifl)
ELSE
THIS.aFlds[ifl] = ;
THIS.OnTag(FIELD(ifl))
ENDIF
ENDFOR
ENDPROC
PROCEDURE setupfilter && This takes the conditions listed in the dialog and rationalizes them into a filter expression (it also applies the NORMALIZE() function to the expression).
LOCAL lcx, lii, lnstime, lnetime, lcy, lik, liempty, liSelect, lcAlias
lcx = ""
IF THISFORM.iQptr # 0
FOR lik = 1 TO THISFORM.iQptr
IF THISFORM.aQuery(lik)#"*OR*"
lcx = "("+THISFORM.EditQuery(TRIM(THISFORM.aQuery(lik)))
EXIT
ENDIF
ENDFOR
FOR lii = lik+1 TO THISFORM.iQptr
IF THISFORM.aQuery(lii) = "*OR*"
IF THISFORM.aQuery(lii-1) = "*OR*"
LOOP
ENDIF
lcx = lcx + ") OR ("
ELSE
IF THISFORM.aQuery(lii-1) # "*OR*"
lcx = lcx + " AND "
ENDIF
lcx = lcx + THISFORM.EditQuery(TRIM(THISFORM.aQuery(lii)))
ENDIF
ENDFOR
lcx = lcx + ")"
liempty = RAT(' OR ()',lcx)
IF liempty#0
lcx = SUBSTR(lcx,1,liempty-1)
ENDIF
IF LEN(lcx) > FILTER_MAX_FILTER
WAIT WINDOW LEFT(FILTER_TOO_LONG_LOC,254) NOWAIT
RETURN 0
ENDIF
liSelect = SELECT()
lcAlias = "C"+SYS(2015)
lnstime = SECONDS()
SELECT COUNT(*) AS myTally, .T. ;
FROM (ALIAS()) WHERE &lcx ;
INTO CURSOR (lcAlias)
lnetime = SECONDS()
lcy = ALLTRIM(TRANS(myTally,"9,999,999"))+" "+ FILTER_RECORDS_LOC+", "
lcy = lcy + ALLTRIM(TRANS(lnetime-lnstime,"999.99")) + " "+FILTER_SECONDS_LOC+"."
USE IN (lcAlias)
SELECT (liSelect)
WAIT WINDOW LEFT(lcy,254) NOWAIT TIMEOUT 2
ENDIF
IF EMPTY(lcx)
STORE "" TO THISFORM.cfilter
ELSE
STORE NORMALIZE(lcx) TO THISFORM.cFilter
ENDIF
ENDPROC
PROCEDURE cboOrder.Valid
LOCAL lcx
lcx = ALLTRIM(THISFORM.aTags[THISFORM.cboOrder.Value])
IF UPPER(lcx) = "RECORD#"
SET ORDER TO
ELSE
SET ORDER TO (lcx)
ENDIF
GO TOP
ENDPROC
PROCEDURE cboTables.InteractiveChange
SELECT (THISFORM.aDbfs[THIS.Value])
THISFORM.SetTags()
THISFORM.cboOrder.Requery()
THISFORM.cboFieldname.Requery()
THISFORM.cboOrder.Value = IIF(LEN(ORDER())=0,1,ASCAN(THISFORM.aTags,ORDER()))
THISFORM.cboFieldname.Value = 1
THISFORM.FSet()
ENDPROC
PROCEDURE cboTables.ProgrammaticChange
THIS.InteractiveChange()
ENDPROC
PROCEDURE cmdAdd.Click
LOCAL lcx, lcy, lcz, lctyp, lctyp2
IF THISFORM.iQptr = THISFORM.iQueryMax
?? CHR(7)
WAIT WINDOW LEFT(FILTER_QUERY_LIST_FULL_LOC,254) NOWAIT
RETURN 0
ENDIF
lcx = ALIAS()+"."+THISFORM.NoTag(TRIM(THISFORM.aFlds[THISFORM.cboFieldname.Value]))
lcy = ALLTRIM(THISFORM.edtSought.Value)
lctyp = TYPE(lcx)
IF EMPTY(lcy) AND NOT lctyp = "L"
?? CHR(7)
WAIT WINDOW LEFT(FILTER_MISSING_VALUE_LOC,254) NOWAIT
THISFORM.edtSought.SetFocus()
* this shouldn't happen anymore
* because of the programmatic/interactive change stuff
* on edtSought, but JIC.
RETURN 0
ENDIF
DO CASE
CASE INLIST(lctyp,"C","M")
lcy = THISFORM.Brackets(lcy,"'","'")
CASE INLIST(lctyp,"D","T")
lcy = THISFORM.Brackets(lcy,"{","}")
CASE INLIST(lctyp,"N","Y","I")
IF AT('"',lcy)#0
WAIT WINDOW LEFT(FILTER_NUMERIC_NO_QUOTES_LOC,254) NOWAIT
RETURN 0
ENDIF
lctyp2 = TYPE(lcy)
IF NOT INLIST(lctyp2,"N","Y","I")
WAIT WINDOW LEFT(FILTER_NUMERIC_REQUIRED_LOC,254) NOWAIT
RETURN 0
ENDIF
ENDCASE
IF lctyp = "L"
lcz = lcx
ELSE
lcz = lcx + " " + THISFORM.cboOperator.Value + " " + lcy
ENDIF
IF BETWEEN(1,THISFORM.lstQueryParts.Value,THISFORM.iQptr)
THISFORM.aQuery(THISFORM.lstQueryParts.Value) = lcz
ELSE
THISFORM.iQptr = THISFORM.iQptr + 1
THISFORM.aQuery(THISFORM.iQptr) = lcz
ENDIF
THISFORM.lstQueryParts.Value = THISFORM.iQptr+1
THISFORM.lstQueryParts.Enabled = .T.
THISFORM.SetAction()
ENDPROC
PROCEDURE cmdCancel.Click
THISFORM.Release()
ENDPROC
PROCEDURE cmdDelete.Click
THISFORM.ibact = 1
*- clean up parens
THISFORM.cleanparens(THISFORM.lstQueryParts.Value)
= ADEL(THISFORM.aQuery,THISFORM.lstQueryParts.Value)
THISFORM.aQuery(THISFORM.iQueryMax) = " "
THISFORM.iQptr = THISFORM.iQptr - 1
THISFORM.lstQueryParts.Value = ;
MIN(THISFORM.lstQueryParts.Value,THISFORM.iQptr+1)
THISFORM.Qset()
THISFORM.SetAction()
THISFORM.lstQueryParts.Refresh
ENDPROC
PROCEDURE cmdDown.Click
LOCAL lcx
THISFORM.ibact = 3
IF THISFORM.lstQueryParts.Value < THISFORM.iQptr
lcx = THISFORM.aQuery(THISFORM.lstQueryParts.Value+1)
THISFORM.aQuery(THISFORM.lstQueryParts.Value+1) = ;
THISFORM.aQuery(THISFORM.lstQueryParts.Value)
THISFORM.aQuery(THISFORM.lstQueryParts.Value) = lcx
THISFORM.lstQueryParts.Value = THISFORM.lstQueryParts.Value + 1
ENDIF
THISFORM.Setaction()
THISFORM.lstQueryParts.Refresh
ENDPROC
PROCEDURE cmdOK.Click
THISFORM.SetUpFilter()
IF TYPE("THISFORM.oCaller.Name") = "C" AND ;
PEMSTATUS(THISFORM.oCaller,"setfilter",5)
THISFORM.oCaller.SetFilter(THISFORM.cFilter)
ELSE
* set it directly after deciding that it is okay to do it
* using the _table object
IF THISFORM.cusTable.CurrentTableAllowsNavigation(ALIAS())
LOCAL lcFilter
lcFilter = THISFORM.cFilter
SET FILTER TO &lcFilter
LOCATE
THISFORM.cusTable.RefreshLastWindowAfterChange()
ENDIF
ENDIF
THISFORM.Release()
ENDPROC
PROCEDURE cmdOr.Click
LOCAL lii
THISFORM.ibact = 4
IF THISFORM.lstQueryParts.Value < THISFORM.iQptr
FOR lii = THISFORM.iQptr TO THISFORM.lstQueryParts.Value+1 STEP -1
THISFORM.aQuery(lii+1) = THISFORM.aQuery(lii)
ENDFOR
THISFORM.aQuery(THISFORM.lstQueryParts.Value + 1) = "*OR*"
THISFORM.lstQueryParts.Value = THISFORM.lstQueryParts.Value + 2
ELSE
THISFORM.aQuery(THISFORM.iQptr+1) = "*OR*"
THISFORM.lstQueryParts.Value = THISFORM.iQptr + 2
ENDIF
THISFORM.iQptr = THISFORM.iQptr + 1
THISFORM.SetAction()
THISFORM.lstQueryParts.Refresh
ENDPROC
PROCEDURE cmdReset.Click
THISFORM.aQuery = " "
THISFORM.iQptr = 0
THISFORM.lstQueryParts.Value = 1
THISFORM.cboOperator.Value = "="
THISFORM.edtSought.Value = ""
THISFORM.SetAction()
*THISFORM.edtSought.Refresh
ENDPROC
PROCEDURE cmdUp.Click
LOCAL lcx
THISFORM.iBact= 2
IF THISFORM.lstQueryParts.Value > 1 AND ;
THISFORM.lstQueryParts.Value <= THISFORM.iQptr
lcx = THISFORM.aQuery(THISFORM.lstQueryParts.Value-1)
THISFORM.aQuery(THISFORM.lstQueryParts.Value-1) = ;
THISFORM.aQuery(THISFORM.lstQueryParts.Value)
THISFORM.aQuery(THISFORM.lstQueryParts.Value) = lcx
THISFORM.lstQueryParts.Value = THISFORM.lstQueryParts.Value - 1
ENDIF
THISFORM.SetAction()
THISFORM.lstQueryParts.Enabled = .T.
ENDPROC
PROCEDURE edtSought.InteractiveChange
THISFORM.cmdAdd.Enabled = (NOT EMPTY(THIS.Value))
ENDPROC
PROCEDURE edtSought.ProgrammaticChange
THIS.InteractiveChange()
ENDPROC
PROCEDURE edtSought.Valid
IF "'"$THIS.Value
WAIT WINDOW LEFT(FILTER_NO_SINGLE_QUOTES_LOC,254) NOWAIT
RETURN 0
ENDIF
THIS.InteractiveChange()
ENDPROC
PROCEDURE lstQueryParts.InteractiveChange
THIS.Valid()
ENDPROC
PROCEDURE lstQueryParts.ProgrammaticChange
THIS.Valid()
ENDPROC
PROCEDURE lstQueryParts.Valid
THISFORM.SetAction()
THISFORM.QSet()
THISFORM.FSet()
ENDPROC
ENDDEFINE
DEFINE CLASS _filterexpr AS _form OF "_base.vcx"
*< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" />
*-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder
*< OBJECTDATA: ObjPath="cusTable" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="edtFilterExpression" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdBuild" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdApply" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdCancel" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="lblEdit" UniqueID="" Timestamp="" />
#INCLUDE "_table.h"
*
*m: cfilter_access
*m: setfilter && Sets the value of the cFilter property. This method is primarily useful when _FilterDialog is called modally to do further work on the expression to be built.
*m: setfilterontable && If the current table allows navigation according to the dialog's _table member, this method applies the current filter to the current alias, issues a LOCATE to refresh the filter.
*p: cfilter && The filter expression.
*p: ioldselect && Old work area.
*p: ioldsession && Old data session.
*p: ladvanced && This is used to toggle _FilterExpr between two modes (_FilterDialog and GETEXPR).
*
*
AutoCenter = .T.
BorderStyle = 0
Caption = "Set Filter"
cfilter = (SPACE(254))
DoCreate = .T.
Height = 155
ioldselect = 0
ioldsession = 0
Name = "_filterexpr"
Width = 328
WindowType = 1
*
ADD OBJECT 'cmdApply' AS _commandbutton WITH ;
Caption = "\
ADD OBJECT 'cmdBuild' AS _commandbutton WITH ;
AutoSize = .F., ;
Caption = "\
ADD OBJECT 'cmdCancel' AS _commandbutton WITH ;
Cancel = .T., ;
Caption = "\
ADD OBJECT 'cusTable' AS _table WITH ;
Height = 15, ;
Left = 298, ;
Name = "cusTable", ;
Top = 5, ;
Width = 24
*< END OBJECT: ClassLib="_table.vcx" BaseClass="custom" />
ADD OBJECT 'edtFilterExpression' AS _editbox WITH ;
ControlSource = "THISFORM.cFilter", ;
FontName = "MS Sans Serif", ;
Height = 99, ;
IntegralHeight = .T., ;
Left = 8, ;
MaxLength = 254, ;
Name = "edtFilterExpression", ;
TabIndex = 2, ;
Top = 19, ;
Value = (""), ;
Width = 312, ;
ZOrderSet = 2
*< END OBJECT: ClassLib="_base.vcx" BaseClass="editbox" />
ADD OBJECT 'lblEdit' AS _label WITH ;
AutoSize = .T., ;
Caption = "\
PROCEDURE cfilter_access
LOCAL lcValue
IF EMPTY(THIS.cFilter)
lcValue = SPACE(254)
ELSE
lcValue = STRTRAN(ALLTRIM(THIS.cFilter),CHR(13),SPACE(1))
lcValue = STRTRAN(lcValue,CHR(9),SPACE(1))
lcValue = STRTRAN(lcValue,CHR(10),SPACE(1))
ENDIF
RETURN lcValue
ENDPROC
PROCEDURE Init
LOCAL loControl
IF NOT DODEFAULT()
RETURN .F.
ENDIF
LOCAL ARRAY laCheck[1]
IF EMPTY(ALIAS())
THIS.iOldSession = SET("DATASESSION")
IF EMPTY(AUSED(laCheck))
DO CASE
CASE TYPE("_SCREEN.ActiveForm.Parent") = "O"
SET DATASESSION TO _SCREEN.ActiveForm.Parent.DataSessionID
CASE TYPE("_SCREEN.ActiveForm") = "O"
SET DATASESSION TO _SCREEN.ActiveForm.DataSessionID
OTHERWISE
* no other real choices
ENDCASE
IF NOT EMPTY(AUSED(laCheck))
THIS.iOldSelect = SELECT()
SELECT (laCheck[1,1])
ELSE
SET DATASESSION TO THIS.iOldSession
RETURN .F.
ENDIF
ELSE
THIS.iOldSelect = SELECT()
SELECT (laCheck[1,1])
ENDIF
ENDIF
THIS.Caption = STRTRAN(SETFILTER_CAPTION_LOC,"\<","")
THIS.cmdBuild.Caption = SETFILTER_BUILDEXPR_LOC
THIS.cmdApply.Caption = SETFILTER_APPLY_LOC
THIS.cmdCancel.Caption = SETFILTER_CANCEL_LOC
THIS.lblEdit.Caption = SETFILTER_EDIT_LOC
IF SYSTEM_LARGEFONTS
LOCAL lcStandardFont
lcStandardFont = UPPER(DIALOG_SMALLFONT_NAME)
FOR EACH loControl IN THIS.Controls
IF PEMSTATUS(loControl,"FontName",5) AND ;
UPPER(loControl.FontName) == lcStandardFont
loControl.FontName = DIALOG_LARGEFONT_NAME
ENDIF
ENDFOR
* Note: no recursion here.
ENDIF
THIS.SetFilter(SET("FILTER"))
ENDPROC
PROCEDURE setfilter && Sets the value of the cFilter property. This method is primarily useful when _FilterDialog is called modally to do further work on the expression to be built.
LPARAMETERS tcValue
LOCAL lcFilter
IF VARTYPE(tcValue) = "C" AND TYPE(tcValue) = "L"
lcFilter = tcValue
ELSE
lcFilter = SPACE(THIS.edtFilterExpression.MaxLength)
ENDIF
STORE lcFilter TO THIS.cFilter, ;
THIS.edtFilterExpression.Value
ENDPROC
PROCEDURE setfilterontable && If the current table allows navigation according to the dialog's _table member, this method applies the current filter to the current alias, issues a LOCATE to refresh the filter.
IF THIS.cusTable.CurrentTableAllowsNavigation(ALIAS())
LOCAL lcFilter
lcFilter = THISFORM.cFilter
SET FILTER TO &lcFilter
LOCATE
THIS.cusTable.RefreshLastWindowAfterChange()
ENDIF
ENDPROC
PROCEDURE Unload
IF NOT EMPTY(THIS.iOldSession)
SET DATASESSION TO THIS.iOldSession
ENDIF
IF NOT EMPTY(THIS.iOldSelect)
SELECT (THIS.iOldSelect)
ENDIF
ENDPROC
PROCEDURE cmdApply.Click
THISFORM.SetFilterOnTable()
THISFORM.Release()
ENDPROC
PROCEDURE cmdBuild.Click
IF THISFORM.lAdvanced
LOCAL lcFilter
GETEXPR THISFORM.Caption ;
TO lcFilter ;
TYPE [L; SETFILTER_INVALID_LOC] ;
DEFAULT THISFORM.cFilter
IF TYPE(lcFilter) = "L"
THISFORM.cFilter = lcFilter
THISFORM.edtFilterExpression.Refresh
ENDIF
ELSE
LOCAL lcfile, loForm
lcfile = FULLPATH(THISFORM.ClassLibrary)
loForm = NEWOBJECT("_FilterDialog",lcFile,"",THISFORM)
IF TYPE("loForm.Name") = "C"
loForm.Show(1)
THISFORM.edtFilterExpression.Refresh()
ENDIF
ENDIF
ENDPROC
PROCEDURE cmdCancel.Click
THISFORM.Release()
ENDPROC
PROCEDURE edtFilterExpression.Valid
LOCAL llReturn, lcValue
lcValue = STRTRAN(ALLTRIM(THIS.Value),CHR(13),SPACE(1))
lcValue = STRTRAN(lcValue,CHR(9),SPACE(1))
lcValue = STRTRAN(lcValue,CHR(10),SPACE(1))
DO CASE
CASE EMPTY(lcValue)
llReturn = .T.
CASE LEN(lcValue) > THIS.MaxLength
WAIT WINDOW LEFT(SETFILTER_MAXLENGTH_LOC,254) NOWAIT
CASE TYPE(lcValue) # "L"
WAIT WINDOW LEFT(SETFILTER_INVALID_LOC,254) NOWAIT
OTHERWISE
llReturn = .T.
THISFORM.cFilter = lcValue
ENDCASE
RETURN IIF(llReturn,.T.,0)
ENDPROC
ENDDEFINE
DEFINE CLASS _findbutton AS _container OF "_base.vcx"
*< CLASSDATA: Baseclass="container" Timestamp="" Scale="Pixels" Uniqueid="" />
*-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder
*< OBJECTDATA: ObjPath="cmdTableFind" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cusTableFind" UniqueID="" Timestamp="" />
#INCLUDE "_table.h"
*
*m: calias_access
*m: calias_assign
*m: cfindstring_access
*m: cfindstring_assign
*m: dofind && This is ordinarily the only method you need to call to do search.
*m: lfindagain_access
*m: lfindagain_assign
*m: lmatchcase_access
*m: lmatchcase_assign
*m: lskipmemos_access
*m: lskipmemos_assign
*m: lwraparound_access
*m: lwraparound_assign
*m: setbuttonui
*m: skipfield && This method allows you to eliminate any particular field or fields from the search.
*p: calias && The data source to search in.
*p: cfindstring && The string to search for. Defaults to a null string.
*p: lfindagain && This determines whether the class will perform a SKIP before its next check, allowing you to move through a file finding successive instances of a string.
*p: lmatchcase && Case-sensitivity.
*p: lskipmemos && Whether to skip searching in memo fields.
*p: lwraparound && Whether to continue searching from beginning if end of file reached.
*
*
BackStyle = 0
BorderWidth = 0
calias = ("")
cfindstring = ("")
Height = 28
Name = "_findbutton"
Width = 69
*
ADD OBJECT 'cmdTableFind' AS _commandbutton WITH ;
AutoSize = .T., ;
Caption = "\
ADD OBJECT 'cusTableFind' AS _tablefind WITH ;
Left = 48, ;
Name = "cusTableFind", ;
Top = 0
*< END OBJECT: ClassLib="_table.vcx" BaseClass="custom" />
PROCEDURE calias_access
RETURN THIS.cusTableFind.calias
ENDPROC
PROCEDURE calias_assign
LPARAMETERS tcNewVal
STORE tcNewVal TO THIS.cusTableFind.cAlias, THIS.cAlias
THIS.SetButtonUI()
ENDPROC
PROCEDURE cfindstring_access
RETURN THIS.cusTableFind.cfindstring
ENDPROC
PROCEDURE cfindstring_assign
LPARAMETERS tcNewVal
STORE tcNewVal TO THIS.cusTableFind.cFindString, THIS.cFindString
THIS.SetButtonUI()
ENDPROC
PROCEDURE dofind && This is ordinarily the only method you need to call to do search.
LPARAMETERS tcString, tcAlias
THIS.cusTableFind.DoFind(tcString,tcAlias)
THIS.SetButtonUI()
ENDPROC
PROCEDURE Init
IF NOT DODEFAULT()
RETURN .F.
ENDIF
* autosize the button for the larger caption,
* then turn off the autosize
THIS.cmdTableFind.AutoSize = .T.
THIS.cmdTableFind.Caption = FIND_FINDNEXT_LOC
THIS.cmdTableFind.AutoSize = .F.
THIS.SetButtonUI()
ENDPROC
PROCEDURE lfindagain_access
RETURN THIS.cusTableFind.lfindagain
ENDPROC
PROCEDURE lfindagain_assign
LPARAMETERS tlNewVal
STORE tlNewVal TO THIS.cusTableFind.lFindAgain, THIS.lFindAgain
THIS.SetButtonUI()
ENDPROC
PROCEDURE lmatchcase_access
RETURN THIS.cusTableFind.lmatchcase
ENDPROC
PROCEDURE lmatchcase_assign
LPARAMETERS tlNewVal
STORE tlNewVal TO THIS.cusTableFind.lMatchCase, THIS.lMatchCase
THIS.SetButtonUI()
ENDPROC
PROCEDURE lskipmemos_access
RETURN THIS.cusTableFind.lskipmemos
ENDPROC
PROCEDURE lskipmemos_assign
LPARAMETERS tlNewVal
STORE tlNewVal TO THIS.cusTableFind.lSkipMemos, THIS.lSkipMemos
THIS.SetButtonUI()
ENDPROC
PROCEDURE lwraparound_access
RETURN THIS.cusTableFind.lwraparound
ENDPROC
PROCEDURE lwraparound_assign
LPARAMETERS tlNewVal
STORE tlNewVal TO THIS.cusTableFind.lWrapAround, THIS.lWrapAround
THIS.SetButtonUI()
ENDPROC
PROCEDURE setbuttonui
THIS.cmdTableFind.Enabled = (NOT EMPTY(THIS.cAlias)) AND ;
(NOT EMPTY(THIS.cFindString))
IF THIS.lFindAgain
THIS.cmdTableFind.Caption = FIND_FINDNEXT_LOC
ELSE
THIS.cmdTableFind.Caption = FIND_FIND_LOC
ENDIF
ENDPROC
PROCEDURE skipfield && This method allows you to eliminate any particular field or fields from the search.
LPARAMETERS tcField
THIS.cusTableFind.SkipField(tcField)
THIS.SetButtonUI()
ENDPROC
PROCEDURE cmdTableFind.Click
THIS.Parent.DoFind()
ENDPROC
ENDDEFINE
DEFINE CLASS _finddialog AS _form OF "_base.vcx"
*< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" />
*-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder
*< OBJECTDATA: ObjPath="lblFind" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="shpOptionFrame" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="lblOptions" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="chkMatchCase" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="chkWrapAround" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdFind" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdCancel" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cboFindString" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="chkSkipMemos" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="lblLookIn" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cboTables" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cusTableFind" UniqueID="" Timestamp="" />
#INCLUDE "_table.h"
*
*m: calias_access
*m: calias_assign
*m: cfindstring_access
*m: cfindstring_assign
*m: clearfindstrings
*m: dofind
*m: ladvanced_assign
*m: lfindagain_access
*m: lfindagain_assign
*m: lmatchcase_access
*m: lmatchcase_assign
*m: lskipmemos_access
*m: lskipmemos_assign
*m: lwraparound_access
*m: lwraparound_assign
*m: refreshtablechoices
*m: setfindbuttoncaption
*m: setfindbuttonenable
*m: skipfield
*p: calias && The data source to search in.
*p: cfindstring && The search string.
*p: ladvanced && Whether to display advanced options in dialog.
*p: lfindagain && This determines whether the class will perform a SKIP before its next check, allowing you to move through a file finding successive instances of a string.
*p: lmatchcase && Case-sensitivity.
*p: lskipmemos && Whether to skip searching in memo fields.
*p: lwraparound && Whether to continue searching from beginning if end of file reached.
*
*
AlwaysOnTop = .T.
AutoCenter = .T.
BorderStyle = 0
calias = ("")
Caption = "Find"
cfindstring = ("")
DoCreate = .T.
Height = 131
MaxButton = .F.
MinButton = .F.
Name = "_finddialog"
ShowWindow = 1
Visible = .F.
Width = 378
*
ADD OBJECT 'cboFindString' AS _combobox WITH ;
FontName = "MS Sans Serif", ;
FontSize = 8, ;
Height = 24, ;
Left = 78, ;
Name = "cboFindString", ;
TabIndex = 2, ;
Top = 11, ;
Width = 216
*< END OBJECT: ClassLib="_base.vcx" BaseClass="combobox" />
ADD OBJECT 'cboTables' AS _combobox WITH ;
FontName = "MS Sans Serif", ;
FontSize = 8, ;
Height = 24, ;
Left = 78, ;
Name = "cboTables", ;
Style = 2, ;
TabIndex = 4, ;
Top = 48, ;
Value = (THISFORM.cAlias), ;
Width = 216
*< END OBJECT: ClassLib="_base.vcx" BaseClass="combobox" />
ADD OBJECT 'chkMatchCase' AS _checkbox WITH ;
AutoSize = .T., ;
BackStyle = 0, ;
Caption = "\
ADD OBJECT 'chkSkipMemos' AS _checkbox WITH ;
AutoSize = .T., ;
Caption = "\
ADD OBJECT 'chkWrapAround' AS _checkbox WITH ;
AutoSize = .T., ;
BackStyle = 0, ;
Caption = "\
ADD OBJECT 'cmdCancel' AS _commandbutton WITH ;
Cancel = .T., ;
Caption = "\
ADD OBJECT 'cmdFind' AS _commandbutton WITH ;
Caption = "\
ADD OBJECT 'cusTableFind' AS _tablefind WITH ;
Left = 324, ;
Name = "cusTableFind", ;
Top = 84
*< END OBJECT: ClassLib="_table.vcx" BaseClass="custom" />
ADD OBJECT 'lblFind' AS _label WITH ;
AutoSize = .T., ;
BackStyle = 0, ;
BorderStyle = 0, ;
Caption = "\
ADD OBJECT 'lblLookIn' AS _label WITH ;
AutoSize = .T., ;
BackStyle = 0, ;
BorderStyle = 0, ;
Caption = "Look \
ADD OBJECT 'lblOptions' AS _label WITH ;
AutoSize = .T., ;
BorderStyle = 0, ;
Caption = "Options", ;
FontName = "MS Sans Serif", ;
FontSize = 8, ;
Height = 15, ;
Left = 15, ;
Name = "lblOptions", ;
TabIndex = 5, ;
Top = 79, ;
Width = 38
*< END OBJECT: ClassLib="_base.vcx" BaseClass="label" />
ADD OBJECT 'shpOptionFrame' AS _shape WITH ;
BackStyle = 0, ;
BorderStyle = 1, ;
BorderWidth = 1, ;
Height = 36, ;
Left = 10, ;
Name = "shpOptionFrame", ;
SpecialEffect = 0, ;
Top = 85, ;
Width = 284
*< END OBJECT: ClassLib="_base.vcx" BaseClass="shape" />
PROCEDURE Activate
IF NOT EMPTY(ALIAS())
THIS.RefreshTableChoices()
STORE PROPER(ALIAS()) TO THIS.cboTables.Value, THIS.cboTables.DisplayValue
ENDIF
ENDPROC
PROCEDURE calias_access
RETURN THIS.cusTableFind.cAlias
ENDPROC
PROCEDURE calias_assign
LPARAMETERS m.vNewVal
THIS.cusTableFind.cAlias = m.vNewVal
ENDPROC
PROCEDURE cfindstring_access
RETURN THIS.cusTableFind.cFindString
ENDPROC
PROCEDURE cfindstring_assign
LPARAMETERS m.vNewVal
STORE m.vNewVal TO THIS.cusTableFind.cFindString
ENDPROC
PROCEDURE clearfindstrings
THIS.cboFindString.Clear()
STORE "" TO THIS.cboFindString.Value, ;
THIS.cboFindString.DisplayValue, ;
THIS.cusTableFind.cFindString
THIS.SetFindButtonCaption()
THIS.SetFindButtonEnable()
ENDPROC
PROCEDURE dofind
ENDPROC
PROCEDURE Init
LPARAMETERS tlAdvanced
IF NOT DODEFAULT()
RETURN .F.
ENDIF
IF PCOUNT() > 0
THIS.lAdvanced = tlAdvanced
ELSE
THIS.lAdvanced = THIS.lAdvanced
* default to the value of the property,
* but still synch up the positioning
* of the objects on the form to the current state
ENDIF
* localize strings
THIS.Caption = FIND_CAPTION_LOC
THIS.lblFind.Caption = FIND_LOOKFOR_LOC
THIS.lblOptions.Caption = FIND_OPTIONS_LOC
THIS.chkWrapAround.Caption = FIND_WRAPAROUND_LOC
THIS.chkMatchCase.Caption = FIND_MATCHCASE_LOC
THIS.chkSkipMemos.Caption = FIND_SKIPMEMOS_LOC
THIS.cmdFind.Caption = FIND_FIND_LOC
THIS.cmdCancel.Caption = FIND_CANCEL_LOC
THIS.lblLookIn.Caption = FIND_LOOKIN_LOC
* bindings to member properties occurs
* here rather than properties window
* because of possible order conflicts (the
* custom object may be created after some
* of the members we wish to bind to its properties):
THIS.cboFindString.ControlSource = "THISFORM.cusTableFind.cFindString"
THIS.cboTables.ControlSource = "THISFORM.cusTableFind.cAlias"
THIS.chkWrapAround.ControlSource = "THISFORM.cusTableFind.lWrapAround"
THIS.chkSkipMemos.ControlSource = "THISFORM.cusTableFind.lSkipMemos"
THIS.chkMatchCase.ControlSource = "THISFORM.cusTableFind.lMatchCase"
IF SYSTEM_LARGEFONTS
THIS.SetAll("FontName",DIALOG_LARGEFONT_NAME)
ENDIF
ENDPROC
PROCEDURE ladvanced_assign
LPARAMETERS m.vNewVal
LOCAL lnMargin
lnMargin = THIS.cmdFind.Top
THIS.lAdvanced = m.vNewVal
STORE THIS.lAdvanced TO ;
THIS.cboTables.Visible, THIS.cboTables.Enabled, ;
THIS.lblLookIn.Visible, THIS.lblLookIn.Enabled
IF THIS.lAdvanced
THIS.lblOptions.Top = THIS.cboTables.Top + THIS.cboTables.Height + lnMargin
ELSE
THIS.lblOptions.Top = THIS.cboTables.Top
ENDIF
THIS.shpOptionFrame.Top = THIS.lblOptions.Top + THIS.lblOptions.Height/2
THIS.SetAll("Top", ;
THIS.shpOptionFrame.Top + ;
((THIS.shpOptionFrame.Height/2)-(THIS.chkMatchCase.Height/2)), ;
"_checkbox")
THIS.Height=THIS.shpOptionFrame.Top+THIS.shpOptionFrame.Height+lnMargin
ENDPROC
PROCEDURE lfindagain_access
RETURN THIS.cusTableFind.lFindAgain
ENDPROC
PROCEDURE lfindagain_assign
LPARAMETERS m.vNewVal
THIS.cusTableFind.lFindAgain = m.vNewVal
ENDPROC
PROCEDURE lmatchcase_access
RETURN THIS.cusTableFind.lMatchCase
ENDPROC
PROCEDURE lmatchcase_assign
LPARAMETERS m.vNewVal
THIS.cusTableFind.lMatchCase = m.vNewVal
ENDPROC
PROCEDURE lskipmemos_access
RETURN THIS.cusTableFind.lSkipMemos
ENDPROC
PROCEDURE lskipmemos_assign
LPARAMETERS m.vNewVal
THIS.cusTableFind.lSkipMemos = m.vNewVal
ENDPROC
PROCEDURE lwraparound_access
RETURN THIS.cusTableFind.lWrapAround
ENDPROC
PROCEDURE lwraparound_assign
LPARAMETERS m.vNewVal
THIS.cusTableFind.lWrapAround = m.vNewVal
ENDPROC
PROCEDURE refreshtablechoices
IF THIS.lAdvanced
THIS.cboTables.Refresh(.T.)
ENDIF
ENDPROC
PROCEDURE setfindbuttoncaption
IF THIS.cusTableFind.lFindAgain
THIS.cmdFind.Caption = FIND_FINDNEXT_LOC
ELSE
THIS.cmdFind.Caption = FIND_FIND_LOC
ENDIF
ENDPROC
PROCEDURE setfindbuttonenable
THIS.cmdFind.Enabled = (NOT EMPTY(THIS.cusTableFind.cAlias)) AND ;
(NOT EMPTY(THIS.cboFindString.DisplayValue))
ENDPROC
PROCEDURE Show
LPARAMETERS nStyle
THIS.RefreshTableChoices()
DO CASE
CASE EMPTY(THIS.cusTableFind.cAlias)
THIS.cusTableFind.cAlias = THIS.cusTableFind.GetCurrentAlias()
CASE NOT USED(THIS.cusTableFind.cAlias)
THIS.cusTableFind.cAlias = ""
OTHERWISE
* leave it alone
ENDCASE
THIS.SetFindButtonCaption()
THIS.SetFindButtonEnable()
IF NOT THIS.cmdFind.Enabled
IF EMPTY(THIS.cFindString)
KEYBOARD SPACE(1)+"{HOME}"
ELSE
KEYBOARD THIS.cFindString
ENDIF
ENDIF
ENDPROC
PROCEDURE skipfield
LPARAMETERS tcField
THIS.cusTableFind.SkipField(tcField)
ENDPROC
PROCEDURE cboFindString.InteractiveChange
THISFORM.SetFindButtonEnable()
ENDPROC
PROCEDURE cboFindString.Valid
WITH THIS
IF NOT EMPTY(.DisplayValue)
LOCAL liItem, llFound
FOR liItem = 1 TO .ListCount
IF .List(liItem) == .DisplayValue
llFound = .T.
EXIT
ENDIF
ENDFOR
IF NOT llFound
.AddItem(.DisplayValue,1)
ENDIF
ENDIF
.Value = .DisplayValue
ENDWITH
ENDPROC
PROCEDURE cboTables.Refresh
LPARAMETERS tlForceRefresh
IF THISFORM.lAdvanced
IF tlForceRefresh
THIS.Clear
LOCAL aAliases[1,2], liAlias, liAliasCount
liAliasCount = AUSED(aAliases)
FOR liAlias = 1 TO liAliasCount
THIS.AddItem(PROPER(aAliases[liAlias,1]))
ENDFOR
THIS.AddItem(SPACE(8))
ENDIF
ENDIF
ENDPROC
PROCEDURE cmdCancel.Click
THISFORM.Release()
ENDPROC
PROCEDURE cmdFind.Click
THISFORM.cusTableFind.DoFind()
ENDPROC
PROCEDURE cusTableFind.calias_assign
LPARAMETERS tcAlias
DODEFAULT(tcAlias)
LOCAL liAlias, llFound, llEmpty
IF EMPTY(THIS.cAlias)
THISFORM.Caption = FIND_CAPTION_LOC
llEmpty = .T.
ELSE
THISFORM.Caption = FIND_FINDIN_LOC+" "+ PROPER(THIS.cAlias)
ENDIF
THISFORM.SetFindButtonEnable()
THISFORM.SetFindButtonCaption()
IF THISFORM.lAdvanced
IF NOT llEmpty
FOR liAlias = 1 TO THISFORM.cboTables.ListCount
llFound = (THIS.cAlias == THISFORM.cboTables.List(liAlias))
IF llFound
EXIT
ENDIF
ENDFOR
ENDIF
IF NOT (llFound OR llEmpty)
THISFORM.cboTables.AddItem(THIS.cAlias)
ENDIF
STORE THIS.cAlias TO THISFORM.cboTables.Value, ;
THISFORM.cboTables.DisplayValue
THISFORM.cboTables.Refresh()
ENDIF
ENDPROC
PROCEDURE cusTableFind.cfindstring_assign
LPARAMETERS tcString
DODEFAULT(tcString)
THISFORM.SetFindButtonCaption()
THISFORM.SetFindButtonEnable()
ENDPROC
PROCEDURE cusTableFind.dofind
LPARAMETERS tcString, tcAlias
IF DODEFAULT(tcString, tcAlias)
THISFORM.cusTableFind.RefreshLastWindowAfterChange()
ENDIF
THISFORM.SetFindButtonEnable()
THISFORM.SetFindButtonCaption()
RETURN
*!* * the commented version below can
*!* * replace the above if "multiple find"
*!* * is inadvisable on a modal dialog,
*!* * for any reason,
*!* * but it seems to be okay
*!* IF DODEFAULT(tcString, tcAlias)
*!* THISFORM.cusTableFind.RefreshLastWindowAfterChange()
*!* IF THISFORM.WindowType = 1
*!* THISFORM.Release()
*!* ENDIF
*!* ELSE
*!* IF THISFORM.WindowType = 1
*!* THISFORM.Release()
*!* ELSE
*!* THISFORM.SetFindButtonEnable()
*!* THISFORM.SetFindButtonCaption()
*!* ENDIF
*!* ENDIF
ENDPROC
PROCEDURE cusTableFind.lfindagain_assign
LPARAMETERS tlVal
DODEFAULT(tlVal)
THISFORM.SetFindButtonCaption()
THISFORM.SetFindButtonEnable()
ENDPROC
PROCEDURE cusTableFind.lmatchcase_assign
LPARAMETERS tlVal
DODEFAULT(tlVal)
THISFORM.SetFindButtonCaption()
THISFORM.SetFindButtonEnable()
ENDPROC
PROCEDURE cusTableFind.lskipmemos_assign
LPARAMETERS tlVal
DODEFAULT(tlVal)
THISFORM.SetFindButtonCaption()
THISFORM.SetFindButtonEnable()
ENDPROC
PROCEDURE cusTableFind.lwraparound_assign
LPARAMETERS tlVal
DODEFAULT(tlVal)
THISFORM.SetFindButtonCaption()
THISFORM.SetFindButtonEnable()
ENDPROC
PROCEDURE cusTableFind.setfields
DODEFAULT()
THISFORM.SetFindButtonCaption()
THISFORM.SetFindButtonEnable()
ENDPROC
PROCEDURE cusTableFind.skipfield
LPARAMETERS tcField
DODEFAULT(tcField)
THISFORM.SetFindButtonCaption()
THISFORM.SetFindButtonEnable()
ENDPROC
ENDDEFINE
DEFINE CLASS _findnextbuttons AS _findbutton OF "_table.vcx"
*< CLASSDATA: Baseclass="container" Timestamp="" Scale="Pixels" Uniqueid="" />
*-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder
*< OBJECTDATA: ObjPath="cmdTableFindNext" UniqueID="" Timestamp="" />
#INCLUDE "_table.h"
*
calias = ("")
Height = 30
Name = "_findnextbuttons"
Width = 134
cmdTableFind.AutoSize = .F.
cmdTableFind.Name = "cmdTableFind"
cusTableFind.Left = 48
cusTableFind.Name = "cusTableFind"
cusTableFind.Top = 0
*
ADD OBJECT 'cmdTableFindNext' AS _commandbutton WITH ;
AutoSize = .T., ;
Caption = "Find \
PROCEDURE Init
IF NOT DODEFAULT()
RETURN .F.
ENDIF
THIS.cmdTableFind.Caption = FIND_FIND_LOC
THIS.cmdTableFindNext.Caption = FIND_FINDNEXT_LOC
THIS.cmdTableFind.Width = THIS.cmdTableFindNext.Width
THIS.cmdTableFindNext.Left = THIS.cmdTableFind.Width+2
THIS.Width = THIS.cmdTableFind.Width*2+2
ENDPROC
PROCEDURE setbuttonui
* override, so that the captions won't be re-set
THIS.cmdTableFind.Enabled = (NOT EMPTY(THIS.cAlias)) AND ;
(NOT EMPTY(THIS.cFindString))
THIS.cmdTableFindNext.Enabled = THIS.cmdTableFind.Enabled AND ;
THIS.lFindAgain
ENDPROC
PROCEDURE cmdTableFind.Click
THIS.Parent.lFindAgain = .F.
DODEFAULT()
ENDPROC
PROCEDURE cmdTableFindNext.Click
THIS.Parent.DoFind()
ENDPROC
ENDDEFINE
DEFINE CLASS _gotodialog AS _form OF "_base.vcx"
*< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" />
*-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder
*< OBJECTDATA: ObjPath="cusTableNav" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="spnGoTo" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdOK" UniqueID="" Timestamp="" />
#INCLUDE "_table.h"
*
*m: refreshuiafterchange
*
*
AutoCenter = .T.
BorderStyle = 0
Caption = "Go To Record"
DoCreate = .T.
Height = 81
KeyPreview = .T.
MaxButton = .F.
MinButton = .F.
Name = "_gotodialog"
ShowWindow = 1
Width = 164
WindowType = 1
*
ADD OBJECT 'cmdOK' AS _commandbutton WITH ;
AutoSize = .T., ;
Caption = "\
ADD OBJECT 'cusTableNav' AS _tablenav WITH ;
Left = 12, ;
Name = "cusTableNav", ;
Top = 0
*< END OBJECT: ClassLib="_table.vcx" BaseClass="custom" />
ADD OBJECT 'spnGoTo' AS _spinner WITH ;
FontName = "MS Sans Serif", ;
Format = "", ;
Increment = 1.00, ;
InputMask = "9999999999999999999", ;
Left = 22, ;
Name = "spnGoTo", ;
Top = 12
*< END OBJECT: ClassLib="_base.vcx" BaseClass="spinner" />
PROCEDURE Init
LOCAL llReturn, loControl
llReturn = DODEFAULT()
IF llReturn
IF EMPTY(THIS.cusTableNav.cAlias) OR RECCOUNT(THIS.cusTableNav.cAlias) < 2
llReturn = .F.
ELSE
WITH THIS.spnGoTo
STORE 1 TO .SpinnerLowValue, .KeyBoardLowValue
STORE RECCOUNT(THIS.cusTableNav.cAlias) TO ;
.SpinnerHighValue, .KeyBoardHighValue
.Value = RECNO(THIS.cusTableNav.cAlias)
.Value = MIN(.Value,.SpinnerHighValue) && EOF()
ENDWITH
ENDIF
IF SYSTEM_LARGEFONTS
LOCAL lcStandardFont
lcStandardFont = UPPER(DIALOG_SMALLFONT_NAME)
FOR EACH loControl IN THIS.Controls
IF PEMSTATUS(loControl,"FontName",5) AND ;
UPPER(loControl.FontName) == lcStandardFont
loControl.FontName = DIALOG_LARGEFONT_NAME
ENDIF
ENDFOR
* Note: no recursion here.
ENDIF
ENDIF
RETURN llReturn
ENDPROC
PROCEDURE KeyPress
LPARAMETERS nKeyCode, nShiftAltCtrl
IF nKeyCode = 27
THIS.Release()
ENDIF
ENDPROC
PROCEDURE refreshuiafterchange
ENDPROC
PROCEDURE cmdOK.Click
THISFORM.cusTableNav.GoToRecord(THISFORM.spnGoTo.Value)
* we may not have moved but we may have reverted data
* so we have to refresh whether the pointer has
* moved or not
THISFORM.cusTableNav.RefreshLastWindowAfterChange()
THISFORM.Release()
ENDPROC
PROCEDURE cusTableNav.Init
LOCAL llReturn
llReturn = DODEFAULT()
IF llReturn
THIS.cAlias = THIS.GetCurrentAlias()
ENDIF
RETURN llReturn
ENDPROC
ENDDEFINE
DEFINE CLASS _nav2buttons AS _container OF "_base.vcx"
*< CLASSDATA: Baseclass="container" Timestamp="" Scale="Pixels" Uniqueid="" />
*-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder
*< OBJECTDATA: ObjPath="cmgNav" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cusTableNav" UniqueID="" Timestamp="" />
#INCLUDE "_table.h"
*
*m: lcycle_access
*m: lcycle_assign
*m: tablenav && Handles record navigation.
*p: lcycle && Controls movement when record pointer hits end or beginning of file.
*
*
BackStyle = 0
BorderWidth = 0
Height = 38
Name = "_nav2buttons"
Width = 78
*
ADD OBJECT 'cmgNav' AS _commandgroup WITH ;
BorderStyle = 1, ;
Height = 37, ;
Left = 8, ;
Name = "cmgNav", ;
Top = 1, ;
Width = 64, ;
ZOrderSet = 0, ;
Command1.AutoSize = .T., ;
Command1.Caption = "<", ;
Command1.FontBold = .T., ;
Command1.Left = 5, ;
Command1.Name = "Command1", ;
Command1.Top = 5, ;
Command2.AutoSize = .T., ;
Command2.Caption = ">", ;
Command2.FontBold = .T., ;
Command2.Height = 27, ;
Command2.Left = 32, ;
Command2.Name = "Command2", ;
Command2.Top = 5, ;
Command2.Width = 27
*< END OBJECT: ClassLib="_base.vcx" BaseClass="commandgroup" />
ADD OBJECT 'cusTableNav' AS _tablenav WITH ;
Left = 0, ;
Name = "cusTableNav", ;
Top = 0
*< END OBJECT: ClassLib="_table.vcx" BaseClass="custom" />
PROCEDURE lcycle_access
RETURN THIS.cusTableNav.lCycle
ENDPROC
PROCEDURE lcycle_assign
LPARAMETERS m.vNewVal
THIS.cusTableNav.lCycle= m.vNewVal
ENDPROC
PROCEDURE tablenav && Handles record navigation.
LPARAMETERS tcAction
IF EMPTY(tcAction) OR VARTYPE(tcAction) # "C"
RETURN
ENDIF
DO CASE
CASE UPPER(tcAction) = "NEXT"
THIS.cusTableNav.GoNext()
CASE UPPER(tcAction) = "PREVIOUS"
THIS.cusTableNav.GoPrevious()
OTHERWISE
*whoops!
ENDCASE
ENDPROC
PROCEDURE cmgNav.Command1.Click
THIS.Parent.Parent.TableNav("PREVIOUS")
ENDPROC
PROCEDURE cmgNav.Command2.Click
THIS.Parent.Parent.TableNav("NEXT")
ENDPROC
ENDDEFINE
DEFINE CLASS _nav4buttons AS _nav2buttons OF "_table.vcx"
*< CLASSDATA: Baseclass="container" Timestamp="" Scale="Pixels" Uniqueid="" />
*-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder
*< OBJECTDATA: ObjPath="cmdTop" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="cmdBottom" UniqueID="" Timestamp="" />
#INCLUDE "_table.h"
*
Height = 37
Name = "_nav4buttons"
Width = 133
cmgNav.Command1.Left = 33
cmgNav.Command1.Name = "Command1"
cmgNav.Command1.TabIndex = 1
cmgNav.Command1.Top = 5
cmgNav.Command2.Left = 60
cmgNav.Command2.Name = "Command2"
cmgNav.Command2.TabIndex = 2
cmgNav.Command2.Top = 5
cmgNav.Height = 36
cmgNav.Left = 8
cmgNav.Name = "cmgNav"
cmgNav.TabIndex = 2
cmgNav.Width = 122
cusTableNav.Name = "cusTableNav"
*
ADD OBJECT 'cmdBottom' AS _commandbutton WITH ;
AutoSize = .T., ;
Caption = ">|", ;
FontBold = .T., ;
Height = 27, ;
Left = 96, ;
Name = "cmdBottom", ;
TabIndex = 3, ;
Top = 6, ;
Width = 30
*< END OBJECT: ClassLib="_base.vcx" BaseClass="commandbutton" />
ADD OBJECT 'cmdTop' AS _commandbutton WITH ;
AutoSize = .T., ;
Caption = "|<", ;
FontBold = .T., ;
Height = 27, ;
Left = 11, ;
Name = "cmdTop", ;
TabIndex = 1, ;
Top = 6, ;
Width = 30
*< END OBJECT: ClassLib="_base.vcx" BaseClass="commandbutton" />
PROCEDURE tablenav && Handles record navigation.
LPARAMETERS tcAction
IF EMPTY(tcAction) OR VARTYPE(tcAction) # "C"
RETURN
ENDIF
DODEFAULT(tcAction)
DO CASE
CASE UPPER(tcAction) = "TOP"
THIS.cusTableNav.GoTop()
CASE UPPER(tcAction) = "BOTTOM"
THIS.cusTableNav.GoBottom()
OTHERWISE
* ??
ENDCASE
ENDPROC
PROCEDURE cmdBottom.Click
THIS.Parent.TableNav("BOTTOM")
ENDPROC
PROCEDURE cmdTop.Click
THIS.Parent.TableNav("TOP")
ENDPROC
ENDDEFINE
DEFINE CLASS _table AS _custom OF "_base.vcx"
*< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" />
#INCLUDE "_table.h"
*
*m: currentrowbufferedandchanged && Determines whether there is a change in the current control without actually doing a flush.
*m: currenttableallowsnavigation && Evaluates whether the user needs to be presented with choices before leaving the current row.
*m: currenttableallowsordering && Returns .F. if the current alias is a child of a relationship or if the current control is a grid that uses the Linkmaster/ChildOrder/RelationalExpr properties.
*m: dotargetofrelationmessage && Abstract method.
*m: flushcurrentcontrol && Flushes data when the user confirms a desire to do an update.
*m: getcurrentalias && If the current value of the cAlias property is a currently-USED() table, this method RETURNs THIS.cAlias.
*m: getcurrentboundfield && Returns an aliased field in an existing table or, if there is no current bound field, it returns an empty string.
*m: getcurrentcontrol && Returns current control or NULL if there is no ActiveControl at the moment.
*m: refreshlastwindowafterchange && This is similar to RefreshUIAfterChange method, but it is designed especially for use by modal dialogs that may be affecting tables bound to them.
*m: refreshuiafterchange && Looks for an _SCREEN.ActiveForm.Parent (formset) or, failing that, simply a _SCREEN.ActiveForm to refresh.
*m: settoactivesession && Looks for a _SCREEN.ActiveForm or _SCREEN.ActiveForm.Parent (formset) from which to derive an active DataSessionID, and SETs DATASESSION TO that session.
*p: calias && Alias of data source.
*
*
calias = ("")
Name = "_table"
*
PROCEDURE currentrowbufferedandchanged && Determines whether there is a change in the current control without actually doing a flush.
LPARAMETERS tcAlias
ASSERT EMPTY(tcAlias) OR VARTYPE(tcAlias) = "C" AND USED(tcAlias)
LOCAL lcAlias, llReturn, loCurrentControl, lcCurrentField
IF EMPTY(tcAlias)
lcAlias = THIS.GetCurrentAlias()
ELSE
lcAlias = tcAlias
ENDIF
IF (NOT EMPTY(lcAlias)) AND ;
(EMPTY(RECCOUNT(lcAlias)))
lcAlias = ""
ENDIF
IF (NOT EMPTY(lcAlias)) AND ;
INLIST(CURSORGETPROP("BUFFERING",lcAlias), ;
DB_BUFLOCKRECORD, ;
DB_BUFOPTRECORD)
lcCurrentField = THIS.GetCurrentBoundField()
* return of GetCurrentBoundField() will always be aliased
IF NOT EMPTY(lcCurrentField)
IF UPPER(LEFT(lcCurrentField,LEN(lcAlias)+1)) == ;
UPPER(lcAlias)+"."
* check to see if we would need to flush the current control
* to actually see a change:
loCurrentControl = THIS.GetCurrentControl()
IF (NOT ISNULL(loCurrentControl)) AND ;
PEMSTATUS(loCurrentControl,"Value",5) AND ;
(NOT EVAL(lcCurrentField) == loCurrentControl.Value)
* we definitely have a change
llReturn = .T.
ENDIF
ENDIF
ENDIF
IF NOT llReturn && yet
llReturn = (GETFLDSTATE(-1,lcAlias) # ;
REPL("1",FCOUNT(lcAlias)+1))
ENDIF
ENDIF
RETURN llReturn
ENDPROC
PROCEDURE currenttableallowsnavigation && Evaluates whether the user needs to be presented with choices before leaving the current row.
LPARAMETERS tcAlias
ASSERT EMPTY(tcAlias) OR VARTYPE(tcAlias) = "C" AND USED(tcAlias)
LOCAL lcAlias, liReturn
IF (NOT EMPTY(tcAlias)) AND USED(tcAlias)
lcAlias = tcAlias
ELSE
lcAlias = THIS.GetCurrentAlias()
ENDIF
IF (NOT EMPTY(lcAlias)) AND ;
(EMPTY(RECCOUNT(lcAlias)))
lcAlias = ""
ENDIF
IF (NOT EMPTY(lcAlias)) AND ;
THIS.CurrentRowBufferedAndChanged(lcAlias)
IF INLIST(_VFP.Startmode,0,4)
liReturn = MESSAGEBOX(TABLE_MESSAGE_ROW_CHANGED_LOC,;
MB_ICONEXCLAMATION+MB_YESNOCANCEL, ;
TABLE_MESSAGE_TITLE_ROW_CHANGED_LOC)
ELSE
lcAlias = ""
ENDIF
DO CASE
CASE EMPTY(lcAlias)
* we're in a server
* and we shouldn't be moving
* the record pointer here;
* should make the determination
* to revert or update somewhere else!
CASE liReturn = IDYES
THIS.FlushCurrentControl()
IF NOT TABLEUPDATE(0,.T.,lcAlias)
lcAlias = ""
ENDIF
CASE liReturn = IDNO
=TABLEREVERT(.F.,lcAlias)
OTHERWISE && cancel
lcAlias = ""
ENDCASE
ENDIF
RETURN (NOT EMPTY(lcAlias))
ENDPROC
PROCEDURE currenttableallowsordering && Returns .F. if the current alias is a child of a relationship or if the current control is a grid that uses the Linkmaster/ChildOrder/RelationalExpr properties.
LPARAMETERS tcAlias
ASSERT EMPTY(tcAlias) OR VARTYPE(tcAlias) = "C" AND USED(tcAlias)
LOCAL lcAlias, llReturn, loCurrentControl, ;
loCurrentGrid, liIndex, liTables, liTarget, lcTarget
LOCAL ARRAY laTables[1,2]
IF (NOT EMPTY(tcAlias)) AND USED(tcAlias)
lcAlias = tcAlias
ELSE
lcAlias = THIS.GetCurrentAlias()
ENDIF
IF (NOT EMPTY(lcAlias))
lcAlias = UPPER(lcAlias)
llReturn = .T.
* check for grid in a child relation
loCurrentControl = THIS.GetCurrentControl()
DO WHILE TYPE("loCurrentControl.Parent.Baseclass") = "C"
loCurrentControl = loCurrentControl.Parent
IF UPPER(loCurrentControl.Baseclass) == "GRID"
loCurrentGrid = loCurrentControl
EXIT
ENDIF
ENDDO
IF TYPE("loCurrentGrid.Name") = "C" AND ;
(NOT EMPTY(loCurrentGrid.LinkMaster+;
loCurrentGrid.ChildOrder+;
loCurrentGrid.RelationalExpr))
llReturn = .F.
ENDIF
ENDIF
IF llReturn
* check for a relational expression even though
* this isn't a grid
liTables = AUSED(laTables)
FOR liIndex = 1 TO liTables
liTarget = 1
lcTarget = UPPER(TARGET(1,laTables[liIndex,1]))
DO WHILE NOT EMPTY(lcTarget)
IF lcAlias == lcTarget
llReturn = .F.
EXIT
ELSE
liTarget = liTarget + 1
lcTarget = UPPER(TARGET(liTarget,laTables[liIndex,1]))
ENDIF
ENDDO
IF NOT llReturn
EXIT
ENDIF
ENDFOR
ENDIF
IF NOT llReturn
THIS.DoTargetOfRelationMessage(lcAlias)
ENDIF
RETURN llReturn
ENDPROC
PROCEDURE dotargetofrelationmessage && Abstract method.
LPARAMETERS tcAlias
IF EMPTY(tcAlias)
RETURN
ENDIF
ENDPROC
PROCEDURE flushcurrentcontrol && Flushes data when the user confirms a desire to do an update.
LPARAMETERS tcAlias
ASSERT EMPTY(tcAlias) OR VARTYPE(tcAlias) = "C" AND USED(tcAlias)
LOCAL lcAlias, llReturn, loCurrentControl, lcCurrentField
IF EMPTY(tcAlias)
lcAlias = THIS.GetCurrentAlias()
ELSE
lcAlias = tcAlias
ENDIF
IF (NOT EMPTY(lcAlias)) AND ;
(EMPTY(RECCOUNT(lcAlias)))
lcAlias = ""
ENDIF
IF (NOT EMPTY(lcAlias)) AND ;
INLIST(CURSORGETPROP("BUFFERING",lcAlias), ;
DB_BUFLOCKRECORD, ;
DB_BUFOPTRECORD)
lcCurrentField = THIS.GetCurrentBoundField()
* return of GetCurrentBoundField() will always be aliased
IF NOT EMPTY(lcCurrentField)
IF UPPER(LEFT(lcCurrentField,LEN(lcAlias)+1)) == ;
UPPER(lcAlias)+"."
loCurrentControl = THIS.GetCurrentControl()
IF (NOT ISNULL(loCurrentControl)) AND ;
PEMSTATUS(loCurrentControl,"Value",5)
loCurrentControl.Value = loCurrentControl.Value
llReturn = .T.
ENDIF
ENDIF
ENDIF
ENDIF
RETURN llReturn
ENDPROC
PROCEDURE getcurrentalias && If the current value of the cAlias property is a currently-USED() table, this method RETURNs THIS.cAlias.
LOCAL lcAlias
IF EMPTY(THIS.cAlias) OR NOT USED(THIS.cAlias)
THIS.SetToActiveSession()
lcAlias = ALIAS()
ELSE
lcAlias = THIS.cAlias
ENDIF
RETURN lcAlias
ENDPROC
PROCEDURE getcurrentboundfield && Returns an aliased field in an existing table or, if there is no current bound field, it returns an empty string.
* this will always return an aliased field in an existing
* table or it will return an empty string.
LOCAL lcFieldName, loCurrentControl, iPos, lcAlias
loCurrentControl = THIS.GetCurrentControl()
IF ISNULL(loCurrentControl) OR (TYPE("loCurrentControl.ControlSource") # "C")
IF NOT EMPTY(VARREAD())
* could be a browse...
RETURN UPPER(ALIAS()+"."+VARREAD())
ELSE
RETURN ""
ENDIF
ELSE
lcFieldName = UPPER(loCurrentControl.ControlSource)
ENDIF
* is this a bound field we can find in the current list of tables?
THIS.SetToActiveSession()
iPos = AT(".",lcFieldName)
lcAlias = ALIAS()
DO CASE
CASE OCCURS(".",lcFieldName) > 1 AND ;
VARTYPE(lcFieldName) = "O"
* we can't use a member object,
* we're looking for a table attribute/column
lcFieldName = ""
CASE iPos <= 1 AND EMPTY(lcAlias)
lcFieldName = ""
CASE iPos = 0
iPos = LEN(lcAlias)+ 1
lcFieldName = lcAlias+"."+lcFieldName
CASE iPos = 1
iPos = LEN(lcAlias)+ 1
lcFieldName = lcAlias+lcFieldName
CASE iPos = 2 AND LEFT(lcFieldName,1) = "M"
* we can't use a memvar
lcFieldName = ""
OTHERWISE
* we may have an aliased field
* or we may have a property --
* which is it??
IF NOT USED(SUBSTR(lcAlias,1,iPos-1))
lcFieldName = ""
ENDIF
ENDCASE
* okay, now do we have something usable?
IF NOT EMPTY(lcFieldName)
IF TYPE(lcFieldName) = "U"
lcFieldName = ""
ENDIF
ENDIF
RETURN lcFieldName
ENDPROC
PROCEDURE getcurrentcontrol && Returns current control or NULL if there is no ActiveControl at the moment.
LOCAL loRealActiveControl, liThisColumn, loActiveControl, loColumn
loRealActiveControl = NULL
IF TYPE("_SCREEN.ActiveForm.ActiveControl.BaseClass")= "C"
loActiveControl = _SCREEN.ActiveForm.ActiveControl
IF UPPER(loActiveControl.BaseClass) == "GRID"
liThisColumn = loActivecontrol.ActiveColumn
FOR EACH loColumn IN loActiveControl.Columns
IF loColumn.ColumnOrder = liThisColumn
IF TYPE("loColumn.CurrentControl") = "C"
loRealActiveControl = ;
EVAL("loColumn."+loColumn.CurrentControl)
ELSE
loRealActiveControl = loColumn
ENDIF
EXIT
ENDIF
ENDFOR
ELSE
loRealActiveControl = loActiveControl
ENDIF
ENDIF
RETURN loRealActiveControl
ENDPROC
PROCEDURE refreshlastwindowafterchange && This is similar to RefreshUIAfterChange method, but it is designed especially for use by modal dialogs that may be affecting tables bound to them.
LOCAL loForm, liForms, liThisForm, loThisForm
liForms = _SCREEN.FormCount
IF TYPE("THISFORM") = "O"
loThisForm = THISFORM
ELSE
loThisForm = .NULL.
ENDIF
DO CASE
CASE liForms > 1
* find the next one down in the stack, not counting toobars
FOR liThisForm = 2 TO liForms
loForm = _SCREEN.Forms(liThisForm)
IF (NOT ISNULL(loThisForm)) AND loForm = loThisForm
LOOP
ENDIF
IF UPPER(loForm.BaseClass) == "FORM"
IF TYPE("loForm.Parent") = "O"
loForm.Parent.Refresh()
ELSE
loForm.Refresh()
ENDIF
EXIT
ENDIF
ENDFOR
CASE _SCREEN.Visible
_SCREEN.Refresh()
OTHERWISE
* Not much we can do...
ENDCASE
ENDPROC
PROCEDURE refreshuiafterchange && Looks for an _SCREEN.ActiveForm.Parent (formset) or, failing that, simply a _SCREEN.ActiveForm to refresh.
DO CASE
CASE TYPE("_SCREEN.ActiveForm.Parent") = "O"
_SCREEN.ActiveForm.Parent.Refresh()
CASE TYPE("_SCREEN.ActiveForm") = "O"
_SCREEN.ActiveForm.Refresh()
OTHERWISE
IF NOT EMPTY(WONTOP())
SHOW WINDOW (WONTOP()) REFRESH
ENDIF
ENDCASE
ENDPROC
PROCEDURE settoactivesession && Looks for a _SCREEN.ActiveForm or _SCREEN.ActiveForm.Parent (formset) from which to derive an active DataSessionID, and SETs DATASESSION TO that session.
LOCAL liSession
liSession = SET("DATASESSION")
* we may be calling from the menu or a toolbar:
DO CASE
CASE TYPE("_SCREEN.ActiveForm.DatasessionID") = "N" AND ;
liSession # _SCREEN.ActiveForm.DatasessionID
SET DATASESSION TO (_SCREEN.ActiveForm.DatasessionID)
CASE TYPE("_SCREEN.ActiveForm.Parent.DatasessionID") = "N" AND ;
liSession # _SCREEN.ActiveForm.Parent.DatasessionID
SET DATASESSION TO (_SCREEN.ActiveForm.Parent.DatasessionID)
OTHERWISE
* we're in the right datasession already
ENDCASE
ENDPROC
ENDDEFINE
DEFINE CLASS _tablefind AS _table OF "_table.vcx"
*< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" />
#INCLUDE "_table.h"
*
*m: calias_assign
*m: ccontrolcharacter_assign
*m: cfindstring_assign
*m: dofind && This is ordinarily the only method you need to call to do search.
*m: lfindagain_assign
*m: lmatchcase_assign
*m: lskipmemos_assign
*m: lwraparound_assign
*m: setfields
*m: showmessagenotfound
*m: skipfield && This method allows you to eliminate any particular field or fields from the search.
*p: ccontrolcharacter
*p: cfields && List of fields to search.
*p: cfindstring && The string to search for. Defaults to a null string.
*p: imemos
*p: lfindagain && This determines whether the class will perform a SKIP before its next check, allowing you to move through a file finding successive instances of a string.
*p: lmatchcase && Case-sensitivity.
*p: lskipmemos && Whether to skip searching of memos.
*p: lwraparound && Whether to continue searching from beginning if end of file reached.
*a: amemos[1,0]
*
*
calias = ("")
ccontrolcharacter = ("~")
cfields = ("")
cfindstring = ("")
imemos = 0
Name = "_tablefind"
*
PROCEDURE calias_assign
LPARAMETERS tcNewVal
DO CASE
CASE VARTYPE(tcNewVal) # "C" OR NOT USED(tcNewVal)
THIS.cAlias = ""
THIS.cFields = ""
THIS.lFindAgain = .F.
CASE THIS.cAlias == PROPER(tcNewVal)
* do nothing
OTHERWISE
THIS.cAlias = PROPER(tcNewVal)
THIS.SetFields()
THIS.lFindAgain = .F.
ENDCASE
ENDPROC
PROCEDURE ccontrolcharacter_assign
LPARAMETERS tcNewVal
IF VARTYPE(tcNewVal) # "C" OR EMPTY(tcNewVal)
THIS.cControlCharacter = "~"
ELSE
IF LEFTC(tcNewVal,1) == THIS.cControlCharacter
* do nothing
ELSE
* one character only
THIS.cControlCharacter = LEFTC(tcNewVal,1)
THIS.SetFields()
ENDIF
ENDIF
ENDPROC
PROCEDURE cfindstring_assign
LPARAMETERS tcNewVal
IF VARTYPE(tcNewVal) # "C"
RETURN .F.
ENDIF
IF RTRIM(tcNewVal) == THIS.cFindString
* do nothing
ELSE
STORE RTRIM(tcNewVal) TO THIS.cFindString
THIS.lFindAgain = .F.
ENDIF
ENDPROC
PROCEDURE dofind && This is ordinarily the only method you need to call to do search.
LPARAMETERS tcFindString, tcAlias
ASSERT EMPTY(tcFindString) OR VARTYPE(tcFindString) = "C"
ASSERT EMPTY(tcAlias) OR VARTYPE(tcAlias) = "C"
LOCAL llSuccess
llSuccess = .T.
IF NOT EMPTY(tcFindString)
THIS.cFindString = tcFindString
ENDIF
IF EMPTY(THIS.cFindString)
llSuccess = .F.
ENDIF
IF NOT EMPTY(tcAlias)
THIS.cAlias = tcAlias
ENDIF
IF EMPTY(THIS.cAlias)
THIS.cAlias = THIS.GetCurrentAlias()
ENDIF
IF NOT USED(THIS.cAlias)
THIS.cAlias = ""
ENDIF
IF EMPTY(THIS.cAlias)
llSuccess = .F.
ENDIF
IF llSuccess
llSuccess = THIS.CurrentTableAllowsNavigation(THIS.cAlias)
ENDIF
IF llSuccess
* now do the real work
LOCAL liRecno, liSelect
liSelect = SELECT()
SELECT (THIS.cAlias)
liRecno = RECNO()
IF THIS.lFindAgain
IF NOT EOF()
SKIP
ELSE
LOCATE
ENDIF
ENDIF
IF THIS.lMatchCase
LOCATE REST FOR AT_C(THIS.cFindString,EVAL(THIS.cFields)) > 0
ELSE
LOCATE REST FOR ATCC(THIS.cFindString,EVAL(THIS.cfields)) > 0
ENDIF
IF EOF() AND THIS.lWrapAround
IF THIS.lMatchCase
LOCATE FOR AT_C(THIS.cFindString,EVAL(THIS.cFields)) > 0
ELSE
LOCATE FOR ATCC(THIS.cFindString,EVAL(THIS.cFields)) > 0
ENDIF
ENDIF
IF EOF()
THIS.ShowMessageNotFound()
GO liRecno
llSuccess = .F.
ENDIF
SELECT (liSelect)
ENDIF
THIS.lFindAgain = llSuccess
RETURN llSuccess
ENDPROC
PROCEDURE lfindagain_assign
LPARAMETERS tlNewVal
THIS.lFindAgain = tlNewVal
ENDPROC
PROCEDURE lmatchcase_assign
LPARAMETERS tlNewVal
IF THIS.lMatchCase = tlNewVal
* do nothing
ELSE
THIS.lMatchCase = tlNewVal
THIS.lFindAgain = .F.
ENDIF
ENDPROC
PROCEDURE lskipmemos_assign
LPARAMETERS tlNewVal
IF tlNewVal = THIS.lSkipMemos
* do nothing
ELSE
THIS.lFindAgain = .F.
THIS.lSkipMemos = tlNewVal
THIS.SetFields()
ENDIF
ENDPROC
PROCEDURE lwraparound_assign
LPARAMETERS m.vNewVal
THIS.lWrapAround = m.vNewVal
ENDPROC
PROCEDURE setfields
IF VARTYPE(THIS.cAlias) # "C" OR NOT USED(THIS.cAlias)
THIS.cFields = ""
RETURN
ENDIF
LOCAL liIndex, lcThisField, lcThisFieldType
THIS.iMemos = 0
THIS.cFields = "["+THIS.cControlCharacter+"]"
DIME THIS.aMemos[1]
THIS.aMemos[1] = .F.
FOR liIndex = 1 TO FCOUNT(THIS.cAlias)
lcThisField = FIELD(liIndex,THIS.cAlias)
lcThisFieldType = TYPE(THIS.cAlias+"."+lcThisField)
DO CASE
CASE lcThisFieldType = "M" AND NOT THIS.lSkipMemos
THIS.iMemos = THIS.iMemos + 1
DIME THIS.aMemos(THIS.iMemos)
THIS.aMemos(THIS.iMemos) = lcThisField
THIS.cFields = THIS.cFields+"+"+lcThisField+"+["+THIS.cControlCharacter+"]"
CASE lcThisFieldType = "C"
THIS.cFields = THIS.cFields+"+"+lcThisField+"+["+THIS.cControlCharacter+"]"
CASE INLIST(lcThisFieldType,"N","I","Y")
THIS.cfields = ;
THIS.cfields+"+ ALLTRIM(STR("+lcThisField+",12,4))+["+THIS.cControlCharacter+"]"
CASE lcThisFieldType = "D"
THIS.cfields = ;
THIS.cfields+"+ DTOC("+lcThisField+")+["+THIS.cControlCharacter+"]"
CASE lcThisFieldType = "T"
THIS.cfields = ;
THIS.cfields+"+ TTOC("+lcThisField+")+["+THIS.cControlCharacter+"]"
CASE lcThisFieldType = "L"
THIS.cfields = ;
THIS.cfields+"+ IIF("+lcThisField+",'.T.','.F.')+["+THIS.cControlCharacter+"]"
OTHERWISE
* a type we can't yet handle
ENDCASE
ENDFOR
THIS.cFields = UPPER(STRTRAN(THIS.cFields,SPACE(1),""))
IF THIS.cFields == "["+THIS.cControlCharacter+"]"
THIS.cAlias = ""
ENDIF
ENDPROC
PROCEDURE showmessagenotfound
IF INLIST(_VFP.StartMode,0,4)
?? CHR(7)
WAIT WINDOW NOWAIT LEFT(FIND_NOFIND_LOC,254)
ENDIF
ENDPROC
PROCEDURE skipfield && This method allows you to eliminate any particular field or fields from the search.
LPARAMETERS tcField
LOCAL llSkipped, lcThisField, lcThisFieldType
lcThisField = ""
IF VARTYPE(tcField) = "C" AND NOT(EMPTY(tcField))
lcThisFieldType = TYPE(THIS.cAlias+"."+tcField)
DO CASE
CASE INLIST(lcThisFieldType,"N","Y","I")
lcThisField = "["+THIS.cControlCharacter+"]" + ;
"+ ALLTRIM(STR("+ ;
tcField + ;
",12,4))+["+THIS.cControlCharacter+"]"
CASE INLIST(lcThisFieldType,"C","M")
lcThisField = "["+THIS.cControlCharacter+"]+" + ;
tcField + ;
"+["+THIS.cControlCharacter+"]"
CASE lcThisFieldType = "D"
lcThisField = "["+THIS.cControlCharacter+"]" + ;
"+DTOC("+tcField+")" + ;
"+["+THIS.cControlCharacter+"]"
CASE lcThisFieldType = "T"
lcThisField = "["+THIS.cControlCharacter+"]" + ;
"+TTOC("+tcField+")" + ;
"+["+THIS.cControlCharacter+"]"
CASE lcThisFieldType = "L"
lcThisField = "["+THIS.cControlCharacter+"]" + ;
"+ IIF("+tcField+",'.T.','.F.')"+ ;
"+["+THIS.cControlCharacter+"]"
ENDCASE
lcThisField = UPPER(STRTRAN(lcThisField,SPACE(1),""))
IF NOT EMPTY(lcThisField)
IF ATCC(lcThisField, THIS.cFields) > 0
THIS.cFields = STRTRAN(THIS.cFields,lcThisField,"["+THIS.cControlCharacter+"]")
llSkipped = .T.
IF LEFTC(THIS.cFields,1) = "+"
THIS.cFields = SUBSTRC(THIS.cFields,2)
ENDIF
IF RIGHTC(THIS.cFields,1) = "+"
THIS.cFields = SUBSTRC(THIS.cFields,1,LENC(THIS.cFields)-1)
ENDIF
IF EMPTY(THIS.cFields) OR ;
THIS.cFields == "["+THIS.cControlCharacter+"]"
THIS.cAlias = ""
ENDIF
THIS.lFindAgain = .F.
ENDIF
ENDIF
ENDIF
RETURN llSkipped
ENDPROC
ENDDEFINE
DEFINE CLASS _tablenav AS _table OF "_table.vcx"
*< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" />
#INCLUDE "_table.h"
*
*m: dobottommessage
*m: docyclebottommessage
*m: docycletopmessage
*m: dotopmessage
*m: gobottom && Moves record pointer to last record.
*m: gonext && Moves record pointer to next record.
*m: goprevious && Moves record pointer to previous record.
*m: gotop && Moves record pointer to first record.
*m: gotorecord && Moves record pointer to a specified record.
*p: lcycle && Controls movement when record pointer hits end or beginning of file.
*
*
Name = "_tablenav"
*
PROCEDURE dobottommessage
ENDPROC
PROCEDURE docyclebottommessage
ENDPROC
PROCEDURE docycletopmessage
ENDPROC
PROCEDURE dotopmessage
ENDPROC
PROCEDURE gobottom && Moves record pointer to last record.
LOCAL lcAlias
lcAlias = THIS.GetCurrentAlias()
IF THIS.CurrentTableAllowsNavigation(lcAlias)
GO BOTTOM IN (lcAlias)
THIS.RefreshUIAfterChange()
ENDIF
ENDPROC
PROCEDURE gonext && Moves record pointer to next record.
LOCAL lcAlias
lcAlias = THIS.GetCurrentAlias()
IF THIS.CurrentTableAllowsNavigation(lcAlias)
SKIP IN (lcAlias)
IF EOF(lcAlias)
SKIP -1 IN (lcAlias)
IF THIS.lCycle
THIS.DoCycleTopMessage()
THIS.GoTop()
THIS.RefreshUIAfterChange()
ELSE
THIS.DoBottomMessage()
ENDIF
ELSE
THIS.RefreshUIAfterChange()
ENDIF
ENDIF
ENDPROC
PROCEDURE goprevious && Moves record pointer to previous record.
LOCAL lcAlias
lcAlias = THIS.GetCurrentAlias()
IF EMPTY(lcAlias) OR ;
NOT THIS.CurrentTableAllowsNavigation(lcAlias)
RETURN
ENDIF
DO CASE
CASE (NOT BOF(lcAlias))
SKIP -1 IN (lcAlias)
IF BOF(lcAlias)
IF THIS.lCycle
THIS.DoCycleBottomMessage()
THIS.GoBottom()
ELSE
THIS.DoTopMessage()
ENDIF
ENDIF
THIS.RefreshUIAfterChange()
CASE BOF(lcAlias)
IF THIS.lCycle
THIS.DoCycleBottomMessage()
THIS.GoBottom()
THIS.RefreshUIAfterChange()
ELSE
THIS.DoTopMessage()
ENDIF
OTHERWISE
ENDCASE
ENDPROC
PROCEDURE gotop && Moves record pointer to first record.
LOCAL lcAlias
lcAlias = THIS.GetCurrentAlias()
IF THIS.CurrentTableAllowsNavigation(lcAlias)
GO TOP IN (lcAlias)
THIS.RefreshUIAfterChange()
ENDIF
ENDPROC
PROCEDURE gotorecord && Moves record pointer to a specified record.
LPARAMETERS tiRecord
ASSERT PCOUNT() = 1 AND VARTYPE(tiRecord) = "N"
LOCAL lcAlias
lcAlias = THIS.GetCurrentAlias()
IF THIS.CurrentTableAllowsNavigation(lcAlias) AND ;
(RECCOUNT(lcAlias) >= tiRecord)
GO tiRecord IN (lcAlias)
THIS.RefreshUIAfterChange()
ENDIF
ENDPROC
ENDDEFINE
DEFINE CLASS _tablesort AS _table OF "_table.vcx"
*< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" />
*
*m: dosort && DoSort([tcField] [,tcAlias] [,tcTag] [,tlDescending]) allows you to specify exactly what order in what table you would like to set -- or, if you prefer, which field in a given alias you would like to set order to.
*m: getsorttag && Looks for an appropriate tagname by looking at key expressions in this table relevant to this fieldname.
*m: removesort && Removes the current order (index tag).
*p: ldescending && Whether order is ascending or descending.
*
*
Name = "_tablesort"
*
PROCEDURE dosort && DoSort([tcField] [,tcAlias] [,tcTag] [,tlDescending]) allows you to specify exactly what order in what table you would like to set -- or, if you prefer, which field in a given alias you would like to set order to.
LPARAMETERS tcField, tcAlias, tcTag, tlDescending
THIS.SetToActiveSession()
ASSERT EMPTY(tcField) OR ;
(VARTYPE(tcField) = "C" AND ;
TYPE(IIF(EMPTY(tcAlias),"",tcAlias+".")+tcField) # "U")
ASSERT EMPTY(tcAlias) OR (VARTYPE(tcAlias) = "C" AND USED(tcAlias))
ASSERT EMPTY(tcAlias) OR (NOT EMPTY(tcField))
ASSERT EMPTY(tcTag) OR VARTYPE(tcTag) = "C"
ASSERT VARTYPE(tlDescending) = "L"
LOCAL lcField, lcAlias, liPos, lcTag, liSelect, llDescending
IF PCOUNT() > 3
llDescending = tlDescending
ELSE
llDescending = THIS.lDescending
ENDIF
DO CASE
CASE EMPTY(tcAlias) AND EMPTY(tcField)
lcField = THIS.GetCurrentBoundField()
* will be properly aliased if one can be found
IF NOT EMPTY(lcField)
liPos = AT(".",lcField)
lcAlias = LEFT(lcField,liPos-1)
lcField = SUBSTR(lcField,liPos+1)
ELSE
lcField = ""
lcAlias = THIS.GetCurrentAlias()
ENDIF
CASE (NOT EMPTY(tcAlias)) AND USED(tcAlias)
lcField = tcField
lcAlias = tcAlias
OTHERWISE
lcField = tcField
lcAlias = THIS.GetCurrentAlias()
ENDCASE
IF NOT THIS.CurrentTableAllowsOrdering(lcAlias)
RETURN .F.
ENDIF
IF VARTYPE(tcTag) = "C"
* the SELECTs are necessary
* because TAGNO() doesn't work
* on the non-selected area properly,
* although it is doc'd to work...
IF NOT EMPTY(lcAlias)
liSelect = SELECT()
SELECT (lcAlias)
ENDIF
IF NOT EMPTY(TAGNO(tcTag))
lcTag = tcTag
ENDIF
IF NOT EMPTY(lcAlias)
SELECT (liSelect)
ENDIF
ENDIF
IF EMPTY(lcTag) AND (TYPE(lcAlias+"."+lcField) = "U")
RETURN .F.
ENDIF
IF EMPTY(lcTag)
lcTag = THIS.GetSortTag(lcField,lcAlias)
ENDIF
IF NOT EMPTY(lcTag)
IF EMPTY(lcAlias)
lcAlias = ""
ELSE
lcAlias = "IN "+lcAlias
ENDIF
IF llDescending
SET ORDER TO (lcTag) &lcAlias DESCENDING
ELSE
SET ORDER TO (lcTag) &lcAlias ASCENDING
ENDIF
THIS.RefreshUIAfterChange()
ENDIF
RETURN (NOT EMPTY(lcTag))
ENDPROC
PROCEDURE getsorttag && Looks for an appropriate tagname by looking at key expressions in this table relevant to this fieldname.
LPARAMETERS tcField, tcAlias
ASSERT VARTYPE(tcAlias) = "C" AND USED(tcAlias)
ASSERT TYPE(tcAlias+"."+tcField) # "U"
LOCAL lcAlias, lcField, liTags, liSelect, lcKey, lcExact, lcTag, lcAliasedField, ;
lnIndex
lcAlias = UPPER(tcAlias) && must be passed!
lcField = UPPER(tcField) && ditto!
lcTag = ""
liSelect = SELECT()
lcExact = SET("EXACT")
SELECT (lcAlias)
SET EXACT OFF
liTags = TAGCOUNT()
lcAliasedField = UPPER(lcAlias)+"."+lcField
IF liTags > 0
FOR lnIndex = 1 to liTags
lcKey = UPPER(KEY(lnIndex))
IF TYPE(lcKey) # "U"
* this test makes sure that the index expression
* can be evaluated in the current environment
* now test to see if we can use it for
* the current purpose, with an inexact
* comparison since that's all we need
* for an adequate sort
lcKey = NORMALIZE(lcKey)
IF lcKey = lcField OR ;
lcKey = lcAliasedField OR ;
lcKey = "UPPER("+lcField+")" OR ;
lcKey = "UPPER("+lcAliasedField+")" OR ;
lcKey = "UPPER("+lcField+"+" OR ;
lcKey = "UPPER("+lcAliasedField+"+" OR ;
lcKey = "LOWER("+lcField+")" OR ;
lcKey = "LOWER("+lcAliasedField+")" OR ;
lcKey = "LOWER("+lcField+"+" OR ;
lcKey = "LOWER("+lcAliasedField+"+" OR ;
lcKey = "PROPER("+lcField+")" OR ;
lcKey = "PROPER("+lcAliasedField+")" OR ;
lcKey = "PROPER("+lcField+"+" OR ;
lcKey = "PROPER("+lcAliasedField+"+" OR ;
lcKey = "SUBSTR("+lcField+"," OR ;
lcKey = "SUBSTR("+lcAliasedField+"," OR ;
lcKey = "LEFT("+lcField+"," OR ;
lcKey = "LEFT("+lcAliasedField+"," OR ;
lcKey = "SUBSTRC("+lcField+"," OR ;
lcKey = "SUBSTRC("+lcAliasedField+"," OR ;
lcKey = "LEFTC("+lcField+"," OR ;
lcKey = "LEFTC("+lcAliasedField+","
lcTag = UPPER(TAG(lnIndex))
EXIT
ENDIF
ENDIF
ENDFOR
ENDIF
SET EXACT &lcExact
SELECT (liSelect)
RETURN lcTag
ENDPROC
PROCEDURE removesort && Removes the current order (index tag).
LPARAMETERS tcAlias
THIS.SetToActiveSession()
ASSERT EMPTY(tcAlias) OR (VARTYPE(tcAlias) = "C" AND USED(tcAlias))
LOCAL lcAlias
IF EMPTY(tcAlias)
lcAlias = THIS.GetCurrentAlias()
ELSE
lcAlias = tcAlias
ENDIF
IF NOT USED(lcAlias)
RETURN .F.
ENDIF
SET ORDER TO 0 IN (lcAlias)
THIS.RefreshUIAfterChange()
ENDPROC
ENDDEFINE