Relasing Excel from memory

Hi

I am having trouble releasing Excel from memory.

The following works just fine; Excel is loaded and released from memory correctly:

CREATE "Excel.Application" chExcel.
chBook = chExcel:Workbooks:Add.
chSheet = chBook:Sheets:Item("Sheet1").
chSheet:Activate.
RELEASE OBJECT chSheet.

RELEASE OBJECT chBook.
chExcel:QUIT().
RELEASE OBJECT chExcel.

But then if I add in the additional code (in blue):

CREATE "Excel.Application" chExcel.
chBook = chExcel:Workbooks:Add.
chSheet = chBook:Sheets:Item("Sheet1").
chSheet:Activate.
chSheet:Range("A1:B2"):Select().
chSelection = chExcel:Selection.
RELEASE OBJECT chSelection.
RELEASE OBJECT chSheet.

RELEASE OBJECT chBook.
chExcel:QUIT().
RELEASE OBJECT chExcel.

The selection statement works and Excel appears to exit but in trak manager the Excel.exe is still resident in memory.

I have tried swapping the RELEASE statements around without success.

Any help would be greatly appreciated.

Cheers
 
Re: Releasing Excel from memory

I have resolved this issue :)

It seems the above example does not cause the problem.

The problem only occurs where I use the chSelection handle multiple times.

It has just dawned on me that you need to always use "RELEASE OBJECT <com-handle>" before re-using the handle.

This alleviates memory leakage which in turn causes Excel.exe to remain in memory after quitting Excel.

I always knew this was the case with the chBook and chSheet handles but it didn't occur to me to apply the same logic to a chSelection handle which I use dozens of times during the course of formatting a document. Sometimes the obvious is hard to see... :blush:

My problem is solved. I hope this tip helps someone else from the frustration and trial and error I have had with this issue.
 

sphipp

Member
To tell the truth, I've stopped using :Select() wherever possible.

For many things, you can access things directly.

Also, I tend to use a procedure that automatically adds things to a temp-table then releaases them when the program has finished.

So, for example I have a temp-table t_object:
def temp-table t_object no-undo
field hobject as com-handle
index idx1 hobject.

procedure p_add_object:
def input param inp_handle as com-handle.
find t_object where t_object.hobject = inp_handle no-lock no-error.
if not available t_object then do:
create t_object.
t_object.hobject = inp_handle.
end.
end procedure.
procedure p_delete_objects:
for each t_object:
release com-handle t_object.hobject no-error.
delete t_object.
end.
end.

procedure p_handle_action:
def input param inp_handle as com-handle no-undo.
def input param inp_action as char no-undo.
def input param inp_value as char no-undo.
run p_add_object (inp_handle).
case inp_action:
when "font_bold" then inp_handle:font:bold = (inp_value = "yes").
/* etc */
end case.
end procedure.

run p_handle_action (chWorkSheet:Range("B1") :Font,"bold","yes").

run p_delete_objects.
 
To tell the truth, I've stopped using :Select() wherever possible.

For many things, you can access things directly.

Also, I tend to use a procedure that automatically adds things to a temp-table then releaases them when the program has finished.

So, for example I have a temp-table t_object:
def temp-table t_object no-undo
field hobject as com-handle
index idx1 hobject.

procedure p_add_object:
def input param inp_handle as com-handle.
find t_object where t_object.hobject = inp_handle no-lock no-error.
if not available t_object then do:
create t_object.
t_object.hobject = inp_handle.
end.
end procedure.
procedure p_delete_objects:
for each t_object:
release com-handle t_object.hobject no-error.
delete t_object.
end.
end.

procedure p_handle_action:
def input param inp_handle as com-handle no-undo.
def input param inp_action as char no-undo.
def input param inp_value as char no-undo.
run p_add_object (inp_handle).
case inp_action:
when "font_bold" then inp_handle:font:bold = (inp_value = "yes").
/* etc */
end case.
end procedure.

run p_handle_action (chWorkSheet:Range("B1") :Font,"bold","yes").

run p_delete_objects.

Thanks for the suggestions, I like the temp-table idea a lot! Might just have to implement this at some stage.

I use Select because com objects is an upgrade in functionality from DDE where of course you need to select first before doing pretty much anything else. As I need to keep the existing procedures for program stability I had no choice but to go down the Select path. I agree it would be easier to go down the direct access route but it's just no possible in my setup.
 
Top