Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Articles
Search: 

How to remove the column in the grid?
Vladimir Shevchenko, January 1, 2001
One of my clients wants to have a smart grid class. Among other cool features this class should be able to remove the columns from the grid on the fly. Basically, the user will click the right button over the grid and choose from popup menu the Remove current column option. I said, "No problem, Sir"...
One of my clients wants to have a smart grid class. Among other cool features this class should be able to remove the columns from the grid on the fly. Basically, the user will click the right button over the grid and choose from popup menu the Remove current column option. I said, "No problem, Sir" and went to my computer to see what I have to do. The first thing that I saw was DeleteColumn method in grid class. This method has one parameter called nIndex that refers to Column's index inside the Grid. So, my first implementation of this method was like the following code:
Procedure  cf_RemoveCurrentColumn
* Method for removing the current column

Local inNextColumn, inCurrColumn, icName
inCurrColumn = this.ActiveColumn  && obtain a number of active column
* which column should be activated? if we stay on the last column then
* the focus will move to the first column
inNextColumn = iif(inCurrColumn < this.ColumnCount,inCurrColumn+1, 1)
icName = upper(this.Columns(this.ActiveColumn).Name)   && name of active column
* move focus to the next cell in a row
 this.ActivateCell(this.ActiveRow,inNextColumn)
if icName <> [MARKROW]  
* you can't delete the mark column, it's a special column for the sake of mark/unmarkin
* the row
  this.DeleteColumn(inCurrColumn)
endif

Endproc
I was happy until my first try of this method. It won't work, as it should be, even more, as soon as I choose this option from popup menu, VFP crashes completely with infamous "Performed illegal operation" error. I went to my lovely debugger (Isn't it the great tool?) and saw that VFP crashes right on DeleteColumn call. "Yikes", said I and change the DeleteColumn call to Removeobject method:
Procedure  cf_RemoveCurrentColumn
* method for removing the current column
............
icName = upper(this.Columns(this.ActiveColumn).Name)   && name of active column
.........
if icName <> [MARKROW]  
* you can't delete the mark column, it's a special column for the sake of mark/unmarkin
* the row
  this.RemoveObject(icName)
endif

Endproc
It won't work too and made the same result as well as the previous code. I thought that something wrong with my grid class definition and made a quick test on standard grid class. The results were the same: VFP crashes instantly with its lovely "Illegal operation" (What a good description of error! <g>) "Ok", say I and made the form with standard grid and the Command button. In the click event of this button I've placed the following code:
thisform.grid1.DeleteColumn(2)  && delete the second column in the grid
I was VERY happy when this code gave me the results what I looking for. The second column was removed instantly from the grid. So, the solution was to make the call of DeleteColumn method from outside of the grid. My first attempt to achieve this result was to made the invisible button on the form and simulates the Click event. But it failed for the same reason because DeleteColumn call, even when it was in Click event of button, was fired inside the grid: Grid method-->Click event of Command button-->Grid method. Fortunately, VFP has the Timer control that was the solution to this case. I ended up with the following Timer control which I call ColumnDestroyer:
**************************************************
*-- Class:        cls_columndestroyer (d:\projects\gsi\masken\class\mrrgrid.vcx)
*-- ParentClass:  timer
*-- BaseClass:    timer
*
DEFINE CLASS cls_columndestroyer AS timer

	Height = 23
	Width = 23
	Interval = 300
	*-- Holds the command that destroys the column
	PROTECTED cccommand
	cccommand = ""
	Name = "cls_columndestroyer"

	PROCEDURE Init
		lparameters tcCommand
		this.ccCommand = alltrim(tcCommand)
		this.Reset()
	ENDPROC

	PROCEDURE Timer
		local icCmd
		icCmd = this.ccCommand
		this.Interval = 0
		if !empty(this.ccCommand)
		  &icCmd
		endif
		release this    
	ENDPROC


ENDDEFINE
*
*-- EndDefine: cls_columndestroyer
**************************************************
As you may see from this code, this timer has the parameter in Init event. I pass the appropriate call through this parameter and store it in ccCommand property of timer. When the Timer event fires then passed command executes (if you didn't forgot to pass something useful ) and then the timer releases itself. Simple? I thought, yes.

I rewrote the cf_RemoveCurrentColumn method in order to use the ColumnDestroyer control:

Procedure  cf_RemoveCurrentColumn
* Method for removing the current column

local inNextColumn, inCurrColumn, icName, icGrid,icCmd
inCurrColumn = this.ActiveColumn  && obtain a number of active column
* Which column should be activated? if we stay on the last column then
* the focus will move to the first column
inNextColumn = iif(inCurrColumn < this.ColumnCount,inCurrColumn+1, 1)
icName = upper(this.Columns(this.ActiveColumn).Name)   && name of active column
* Move focus to the next cell in a row
 this.ActivateCell(this.ActiveRow,inNextColumn)
* Take the grid hierarchy
icGrid = sys(1272,this)
* Make the string with appropriate call
icCmd = alltrim(icGrid)+[.DeleteColumn(]+alltr(str(inCurrColumn))+[)]
* Instantiate the timer that will do the rest
if icName <> [MARKROW]  
* You can't delete the mark column
* Instantiate the Column destroyer that will do the rest
  =thisform.Addobject([tmr_DestroyColumn],[cls_ColumnDestroyer],icCmd)
endif

Endproc
In conclusion I would like to say that in any case you should avoid releasing container's or class members from inside of container because it could give you just dangerous results.

P.S. Excuse me for possible errors, after all, English isn't my mother tongue

Vladimir Shevchenko
Vladimir Shevchenko is an experienced independent software developer with 10 years of experience. Started to work with Foxpro since its DOS version thru all Windows version up to current release of VFP. Worked as employee at government institutions like Central bank of Russia and then started independent consulting for companies around the world in 1997. Developed many projects using various tools like frameworks, report generators, Active X components and have clear ability to translate user requirement specifications into software design and coding schedules. Talented in designing clear, concise and easy-to-understand user interfaces.
More articles from this author
Vladimir Shevchenko, January 1, 2001
Let assume that you live anywhere around the globe and want to develop an application with multilanguage support. It does not matter where do you live: Russia, USA, Canada, Switzerland etc, because you will always get the same problems with localization of user interfaces. Nowadays, you have differ...