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 Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

sorting grid

Status
Not open for further replies.

Bertiethedog

Programmer
Feb 8, 2007
118
GB
I have been writing a form that opens any table and presents it in a grid.

I have the facility to sort the grid by clicking on the header of that column.

At the mo the table I am experimenting with has 7 fields. If I click on Field 3 then then it resort fine but the method that I use to reset the headers (header name & width) will not work on the column that has just been sorted

The resort code is here
Code:
private laEvents[ 1 ], loHeader, lcField, loColumn, lcFrom, lnBuffering, lcSortOrder, loControl
private llFoundColumn, llAllowCellSelection


*** First of all, see which column fired off this event
Aevents( laEvents, 0 )

loHeader = laEvents[ 1 ]

If Vartype( loHeader ) = 'O'
*** First See if a ControlsSource was set for the column
	With loHeader.Parent
		lcField = ''
		If Not Empty( .ControlSource )
*** Cool. Use it to decide how to sort the grid
			If Not Empty( .ControlSource ) And ( '.' $ .ControlSource ) And Not( '(' $ .ControlSource )
				lcField = Justext( .ControlSource )
				WAIT WINDOW lcField
			Endif
		Endif
	ENDWITH
	
	*** if we have a field - let's sort
	RETURN lcField
	
	
ENDIF

RETURN


*-* This bit is not used





*** we	 have a field - let's see if it already has a sort order set
*** if it does, it will have the appropriate picture in the header
	lcSortOrder = ''
	If Not Empty( loHeader.Picture )
		lcSortOrder = Iif( Lower( Justfname( loHeader.Picture ) ) == 'down.bmp', '', 'DESC' )
	Else
*** See if there is a visual cue on any of the other grid
*** column headers and remove it if there is
*-*FOR EACH loColumn IN This.Columns
		For Each loColumn In Thisform.grid2.Columns
			For Each loControl In loColumn.Controls
				If Lower( loControl.BaseClass ) == [header]
					If Not Empty( loControl.Picture )
						llFoundColumn = .T.
						loControl.Picture = []
						loControl.FontBold = .F.
						Exit
					Endif
				Endif
			Endfor
			If llFoundColumn
				Exit
			Endif
		Endfor
	Endif


This bit of code was placed on here and I lifted it, it is not my own work

The customer wants the prog to remember the row & order so that is what is stored in the table

The select code is dead simple

Code:
lcTable = ALLTRIM(menuoptions.table)

lcOrder = thisform.getOrder()


PRIVATE lcStr, ;
	lcField, ;
	lnVar, ;
	lnPos

IF !USED('GenTable')
	USE (lcTable) IN 0 ALIAS Gentable
ENDIF

IF USED('dispdata')
	USE IN dispdata
endif

SELECT GenTable

lcStr = 'RECNO() AS "Record"'
FOR i = 1 TO FCOUNT()
	lcField = RTRIM(FIELD(i))

	COUNT FOR !EMPTY(&lcField) TO lnVar
	IF lnVar > 0
		lcStr =  (lcfield) + ',' + lcStr
	ENDIF
NEXT

lcResultFile = SYS(2023) + '\dispdata'

SELECT &lcStr ;
	FROM GenTable ;
	ORDER BY &lcOrder ;
	INTO  CURSOR dispdata
	
	*-*TABLE  (lcResultFile)
lnArea = ALIAS()

lnPos = thisform.GetPos()	

SELECT (lnArea)
*-* trap the fact that some records might have been deleted
lnPos = IIF(lnPos <= RECCOUNT(), lnPos,RECCOUNT())
GOTO lnPos

so just one problem but has anyone got any ideas


Richard

 
I have the facility to sort the grid by clicking on the header of that column

Hmmm. That code looks very familiar to me. I think I may be the one who wrote it initially. Here is the complete code - and I know that it works correctly - I am using it in several production apps:

Code:
Define Class grdbase As grid
  DeleteMark = .F.
  Height = 200
  HighlightRow = .F.
  ScrollBars = 2
  Width = 371
  HighlightStyle = 2
  AllowCellSelection = .F.
  Optimize = .T.
  *-- Name of the field that is controlling the sort
  csortfield = ""
  *-- Ascending or descending
  csortorder = ""
  Name = "grdbase"

  *-- Do anything special that must be done to setup the grid (like hightlight the active row)
  Procedure setgrid
    Local lnFgColor, lnBgColor, loColumn, loControl, lnCol, lnAlignment
    *** Set up for highlighting current row
    Declare Integer GetSysColor In "user32" Integer nIndex
    lnBgColor = GetSysColor( 13 )
    lnFgColor = GetSysColor( 14 )

    *** Setup grid highlighing. We do not want a 50% gradient
    With This
      .HighlightBackColor = lnBgColor
      .HighlightForeColor = lnFgColor
    Endwith

    *** now make sure that the dblclick method of all the contained text boxes
    *** delegate to the grid's dblclick()
    For lnCol = 1 To This.ColumnCount
      loColumn = This.Columns[ lnCol ]
      For Each loControl In loColumn.Controls
        If Lower( loControl.BaseClass ) = 'header'
          Bindevent( loControl, 'Click', This, 'SortGrid' )
        Else
          If Pemstatus( loControl, [dblClick], 5 )
            Bindevent( loControl, 'dblClick', This, 'dblClick' )
          Endif
          If Pemstatus( loControl, [RightClick], 5 )
            Bindevent( loControl, 'RightClick', This, 'RightClick' )
          Endif
        Endif
      Endfor
    Endfor
  Endproc

  *-- Sets the order for the grid based on the column whose header was double clicked
  Procedure sortgrid
    Local laEvents[ 1 ], loHeader, lcField, loColumn, lcSortOrder, loControl
    Local llFoundColumn, llAllowCellSelection, lnRecNo

    llAllowCellSelection = This.AllowCellSelection

    *** First of all, see which column fired off this event
    Aevents( laEvents, 0 )
    loHeader = laEvents[ 1 ]
    If Vartype( loHeader ) = 'O'
      *** First See if a ControlsSource was set for the column
      With loHeader.Parent
        lcField = ''
        If Not Empty( .ControlSource )
          *** Cool. Use it to decide how to sort the grid
          If Not Empty( .ControlSource ) And ( '.' $ .ControlSource ) And Not( '(' $ .ControlSource )
            lcField = Justext( .ControlSource )
          Endif
        Endif
      Endwith
      If Empty( lcField )
        *** Try to find the field in the underlying data
        *** This code assumes that the
        *** The underlying cursor will be in natural order
        For lnCol = 1 To This.ColumnCount
          If This.Columns[ lnCol ].Name = loHeader.Parent.Name
            lcField = Field( lnCol, This.RecordSource )
            Exit
          Endif
        Endfor
      Endif
      If Not Empty( lcField )
        *** Save the field that controls the sort to a grid property
        *** Check to see if the tag exists assume
        *** that if there is a tag on this field, it has the same name as the field
        If IsTag( lcField, This.RecordSource )
          *** we have a field - let's see if it already has a sort order set
          *** if it does, it will have the appropriate picture in the header
          lcSortOrder = ''
          If Not Empty( loHeader.Picture )
            lcSortOrder = Iif( Lower( Justfname( loHeader.Picture ) ) == 'down.bmp', '', 'DESC' )
          Else
            *** See if there is a visual cue on any of the other grid
            *** column headers and remove it if there is
            For Each loColumn In This.Columns
              For Each loControl In loColumn.Controls
                If Lower( loControl.BaseClass ) == [header]
                  If Not Empty( loControl.Picture )
                    llFoundColumn = .T.
                    loControl.Picture = []
                    loControl.FontBold = .F.
                    Exit
                  Endif
                Endif
              Endfor
              If llFoundColumn
                Exit
              Endif
            Endfor
          Endif

          This.csortfield = lcField
          This.csortorder = lcSortOrder
          This.csortcaption = loHeader.Caption

          This.DoSort()

          *** And set the visual cues on the header
          loHeader.Picture = Iif( Empty( lcSortOrder ), [..\graphics\up.bmp], [..\graphics\down.bmp] )
          loHeader.FontBold = .T.
        Endif
      Endif
    Endif
    This.AllowCellSelection = llAllowCellSelection
  Endproc

  *-- Called by SortGrid to do the actual sorting - removed to a separate method so that it could be called from elsewhere in the form
  Procedure DoSort
    Local lnRecNo
    *** if we have a field - let's sort
    If Not Empty( This.csortfield  )
      *** There seems to be a refresh issue here
      *** because even though the data is in the cursor
      *** it is not showing up in the grid after the sort
      *** and it looks like it is related to AllowCellSelection being .F.
      This.AllowCellSelection = .F.
      This.Refresh()
      Keyboard '{CTRL+TAB}'

      lnRecNo = Recno( This.RecordSource )
      *** Go ahead and set the order for the table
      Select ( This.RecordSource )
      If Not Empty( This.csortorder )
        Set Order To ( This.csortfield ) Descending
      Else
        Set Order To ( This.csortfield )
      Endif
      This.SetFocus()
      If lnRecNo # 0
        Go lnRecNo In ( This.RecordSource )
      Endif
    Endif
  Endproc

  Procedure Init
    This.setgrid()
  Endproc
Enddefine

And here is the IsTag() function:

Code:
*-- Passed the name of an index tag returns true if it is a tag for the specified table. Uses table in the current work area if no table name is passed.
FUNCTION IsTag( tcTagName, tcTable )
  LOCAL ARRAY laTags[1]
  LOCAL llRetVal
  *** Did we get a tag name?
  IF TYPE( 'tcTagName' ) # 'C'
    *** Error - must pass a Tag Name
    ERROR '9000: Must Pass a Tag Name when calling ISTAG()'
    RETURN .F.
  ENDIF
  *** How about a table alias?
  IF TYPE( 'tcTable' ) = 'C' AND ! EMPTY( tcTable )
      *** Get all open indexes for the specified table
      ATagInfo( laTags, "", tcTable )
  ELSE
      *** Get all open indexes for the current table
      ATagInfo( laTags, "" )
  ENDIF

  *** Do a Case Insensitive, Exact=ON, Scan of the first column of array
  *** Return Whether the Tag is Found or not
  RETURN ( ASCAN( laTags, tcTagName, -1, -1, 1, 15 ) > 0 )
ENDFUNC

Marcia G. Akins
 
Hi Marcia

I think the version I started with was a bit older, this is definatly different.


Hope you didn't mind me reusing your code

Richard
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top