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

Grid - Keep left column visible as you horiz. scroll 1

Status
Not open for further replies.

JRB-Bldr

Programmer
Joined
May 17, 2001
Messages
3,281
Location
US
I have a Grid which uses a data table as its source.
Each Column's ControlSource is individually defined.

There are more columns than can be displayed on-screen at a given time so there is a Horizontal Scroll Bar in addition to the Horizontal Scroll Bar.

My user wants something like they can get in Excel where they keep a left-most column constantly visible as they horizontally scroll through the rest of the columns.

In my VFP7 Form I have tried setting the Grid's Partition parameter, but, upon first opening the form, it ends up with the left-most column showing twice in the Grid.
Once in the Left Partition
Once (again) in the Right Partition

And it ends up with a separate Vertical Scroll Bar between the Left & Right Partitions.

That is confusing to the user.

What I am looking for is how to get something similar to the visual appearance of Excel but within VFP.

And I would like not not have to see the Vertical scroll bar between the Left & Right partitions. The Right one by itself is sufficient.

Can this be accomplished without having to resort to 2 separate grids?

Your suggestions would be most appreciated.

Thanks,
JRB-Bldr
 

Hi JRB-Bldr,

I would have thought that, between the Panel, PanelLink and Parition properties, you would be able to achieve the desired result (but not with just one vertical scrollbar, as far as I know).

If you can't, you might have to resort to two grids, but then there would be no way to keep them in sync.

Interesting problem ....

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
Mike,

Thanks for the prompt reply.

The Panel property being set to 1 puts the user's cursor into the appropriate Right-most panel.
And the Panel Link property being set TRUE connects the record pointer from the Right & Left panels.
And the Partition property allows me to display a separate Left "Panel" which will remain fixed. And this property does not select Grid Columns, instead it sets panel width.

But, while the over-all result is functionally OK, it ends up appearing "messy".

With multiple (duplicate) vertical scroll bars and initially duplicated left-most columns, the user is not as happy as they would be with how Excel operates for them.

What I would ideally like is to:
1. Only show Left panel columns in Left panel and not show them in Right panel at all.
2. Only show a single Vertical scroll bar on right panel, none in left panel.

If anyone has any ideas how to visually "clean this up", I would welcome their input.

Thanks,
JRB-Bldr
 

What if you made it into two grids, as Mike suggested, created two cursors from the original table, one for each of them, and set a relation between them? Then they should be in sync. Would that work?
 
JRB-Bldr if you are member of Universalthread.com check FAQ #8151 - How to freeze (lock) a column in the grid without use of split bar. if you are not here the full text of it:
The approach is based on a simple principle. LeftColumn property of the grid represents a column that is currently the leftmost visible column in the grid with current horizontal scrolling. As we scroll the grid horizontally, this property changes. We can assign this number to the ColumnOrder property of the column we want to hold and that’s all:
Code:
this.Columns(1).ColumnOrder = this.LeftColumn
You can use this in the Scrolled and AfterRowColChange events of the grid. However, there is a little problem with this: order of columns spoiled after few scrolling forward and back. This is because column order changes using principle "replace older column by newer on that place", so older column is placed on place of newer column. Column orders of all other columns are not changed. This causes the problem. This FAQ describes an approach that allows to organize freezing of the column and workaround most issues.

The code is a very basic and simple to give the basics of the approach. Code samples could be improved to work correctly in case user change order of columns, as well as improve the logic related to the focus change.

Description
Following is a code that updates columns in grid to make first column always leftmost. Use it in the Scrolled event when grid is scrolled horizontally and in the AfterRowColChange event when active column is changed in the grid.
Code:
	local i
	if this.columns(1).ColumnOrder < this.LeftColumn
		&& we scroll forward
		for i=this.columns(1).ColumnOrder to this.LeftColumn-1
			this.columns(1).ColumnOrder = this.columns(1).ColumnOrder + 1
		endfor
	else
		&& we scroll backward
		for i=this.LeftColumn+1 to this.columns(1).ColumnOrder
			this.columns(1).ColumnOrder = this.columns(1).ColumnOrder - 1
		endfor
	endif
The above code is very simple because it is written only for the column 1 and only one column frozen. The approach change ColumnOrder of the column by 1. This cause correct moving of column to required place like if you move the column by dragging it by header. This save the original order of columns and solve any problems with confusing order change after scrolling. Use this code in the AfterRowColChange event (when column changed) or in the Scrolled event (when grid is scrolled horizontally, in other words, when nDirection parameter of the Scrolled event is greater or equal 4).

For more complex case (more than one column) you will require to do similar things. For example, following is for 2 columns:
Code:
	local i, lnCurrOrder
	m.lnCurrOrder = this.columns(1).ColumnOrder
	if this.columns(1).ColumnOrder < this.LeftColumn
		&& we scroll forward
		for i=m.lnCurrOrder to this.LeftColumn-1
			this.columns(2).ColumnOrder = this.columns(2).ColumnOrder + 1
		endfor
		for i=m.lnCurrOrder to this.LeftColumn-1
			this.columns(1).ColumnOrder = this.columns(1).ColumnOrder + 1
		endfor
	else
		&& we scroll backward
		for i=this.LeftColumn+1 to m.lnCurrOrder
			this.columns(1).ColumnOrder = this.columns(1).ColumnOrder - 1
		endfor
		for i=this.LeftColumn+1 to m.lnCurrOrder
			this.columns(2).ColumnOrder = this.columns(2).ColumnOrder - 1
		endfor
	endif
Finally, when doing manipulations with column objects on the form, the current focused column might be lost. The workaround for this is to remember current focused column and set the focus back after moving "locked" columns. So, wrap the column(s) moving code (above sample code) into the following code:
Code:
	lnCol = this.ActiveColumn
	lnColToFocus = 0
	if lnCol > 0
		for i=1 to this.ColumnCount
			if this.columns(m.i).ColumnOrder = m.lnCol
				lnColToFocus = m.i
				exit
			endif
		endfor
	endif

        * Check if we do not need to set focus to the last column in grid
        * This will happen when we did not focused column explicitly by 
        * mouse and pressed either Shift+TAB, left arrow key or Ctrl+left 
        * arrow key. In the last condition we check if column focused is 
        * the locked column. When you have 2 columns, you should check for 
        * both (for example, 
        * "AND (m.lnColToFocus = 1 OR m.lnColToFocus = 2)")
	if not MDOWN() AND inlist(lastkey(),15,19,26) AND (m.lnColToFocus = 1)
			this.Columns(this.ColumnCount).SetFocus
			m.lnColToFocus = this.ColumnCount
	endif

* ....... Put here code from previous samples

	if lnColToFocus > 0
		if this.Columns(m.lnColToFocus).ColumnOrder > this.LeftColumn
			this.Columns(m.lnColToFocus).SetFocus
		else
			* Determine the next column after locked and focus it
			for i=1 to this.ColumnCount
				if this.columns(m.i).ColumnOrder = this.Columns(1).ColumnOrder + 2
					lnColToFocus = m.i
					exit
				endif
			endfor
			this.Columns(m.lnColToFocus).SetFocus
		endif
	endif
The side effect of the above code is that "TAB" key pressing in last column when it is active will cause moving to the first column that is not locked. This is a good thing also, because usually locked column is used as information column when others are for data entry. To do opposite (SHIFT+TAB in the first not locked column will focus the last column), we should add some code in the AfterRowColChange event to fix the active column - appropriate section of the code in above sample is marked by comment "Check if we do not need to set focus to the last column in grid".

There is also a problem - when scrolling horizontally and focused column goes out of scrolled area, we just cannot restore active column because this will scroll the grid back. In such case it is good idea to set the focus to the column just after locked column(s) in current scrolling. This column will have next ColumnOrder value after the locked column. This workaround is after the comment "Determine the next column after locked and focus it".

Vlad Grynchyshyn

Borislav Borissov
VFP9 SP1, SQL Server 2000/2005.
 
Boris,

Even though the info is someone else's work, you deserve a star for finding it.

Thanks,
JRB-Bldr
 
HA!
I am the big boss now :-) earn bonuses from somebody else work :-)

Borislav Borissov
VFP9 SP1, SQL Server 2000/2005.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top