Releasing Excel after using Interop - excel

I've read many post looking for my answer, but all are similar to this:
Reading excel files in vb.net leaves excel process hanging
My problem is that I don't quit the app...
The idea is this:
If a User has Excel Open, if he has the file I'm interested in open... get that Excel instance and do whatever I want to do...
But I don't to close his File after I'm done... I want him to keep working on it, the problem is that when he closes Excel... The process keeps running... and running... and running after the user closes Excel with the X button...
this is how I try to do it
This piece is used to know if he has Excel open, and in the For I check for the file name I'm interested in.
Try
oApp = GetObject(, "Excel.Application")
libroAbierto = True
For Each libro As Microsoft.Office.Interop.Excel.Workbook In oApp.Workbooks
If libro.Name = EquipoASeccionIdSeccion.Text & ".xlsm" Then
Exit Try
End If
Next
libroAbierto = False
Catch ex As Exception
oApp = New Microsoft.Office.Interop.Excel.Application
End Try
here would be my code... if he hasn't Excel open, I create a new instance, open the file and everything else.
My code ends with this:
If Not libroAbierto Then
libroSeccion.Close(SaveChanges:=True)
oApp.Quit()
Else
oApp.UserControl = True
libroSeccion.Save()
End If
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(libroOriginal)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(libroSeccion)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(origen)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(copiada)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oApp)
libroOriginal = Nothing
libroSeccion = Nothing
oApp = Nothing
origen = Nothing
copiada = Nothing
nuevosGuardados = True
So you can see that, if I opened the file, I call oApp.Quit() and everything else and the Excel Process ends after a few seconds (maybe 5 aprox.)
BUT if I mean the user to keep the file open (not calling Quit()), Excel process keeps running after the user closes Excel with the X button.
Is there any way to do what I try to do?? Control a open instance of excel and releasing everything so when the user closes it with the X button, the Excel Process dies normally???
Thanks!!!

It seems to me it would be better to use CreateObject instead of GetObject(, "Excel.Application") (see http://support.microsoft.com/kb/288902/en and http://technet.microsoft.com/en-us/library/ee176980.aspx). Then call of Quit method before calling of FinalReleaseComObject and assigninh Nothing will be have a clear sense.

Related

VBS Script not terminating the Excel Application in Task Manager

I have been struggling with what seems to be a common problem regarding opening, running Excel workbook macros, and closing the application from a visual basic script file (.vbs). I cannot terminate the Excel.exe.
I have found a number of recommendations about closing out the objects in the correct order, quitting before setting to nothing, being explicit about each object belonging to the parent object, but I still cannot seem to close of out EXCEL.EXE without manual intervention.
Some mention running a cmd script to kill Excel. I kick off a script like this manually when I have verified it is safe to do so but it is often not. I have dozens of individual batches kicked off each day, and some may be running halfway through during the kick off and completion of another. I would like the .vbs to close its created Excel instance so as to not overrun the memory.
Here is the skeleton of my script:
Set Params = Wscript.Arguments ' some arguments used in the run
Set eApp = CreateObject("Excel.Application")
eApp.Application.DisplayAlerts = False
' CreateObject("WScript.Shell").Run happens here for a log start
Set objWorkbook = eApp.Workbooks.Open("...")
eApp.Application.Visible = True
eApp.Windows(1).Visible = True
eApp.Worksheets(1).Activate
eApp.Application.Run "'...'!...", Cstr(Params(0)), Cstr(Params(1))
objWorkbook.Close False
eApp.Application.DisplayAlerts = True
Set objWorkbook = Nothing
' CreateObject("WScript.Shell").Run happens here for a log complete
eApp.Application.Quit
Set eApp = Nothing
Set Params = Nothing
Wscript.Quit
Is there anything that those more experienced can spot with the above code?

programming for excel with foxpro (or any suggestions)

I have a macro in excel that works.
Sub jim()
Range("$A$1").CurrentRegion.Select
Selection.RowHeight = 13
Selection.Font.Bold = True
…etc.
If I open a csv and run this macro it selects the seen data and then later does stuff to it.
So I made a foxpro program to do the same.
When I try to run in foxpro, I get a variable not found error.
local oExcel, oSheet
oExcel = CreateObject([Excel.Application])
oExcel.Visible = .T.
k:\wellcarestuff\All Data Files\"+ALLTRIM(xlfiles(1,1))
osheet = oexcel.workbooks.open("k:\wellcarestuff\all data files\20131210_CT_TransportationAddresses.csv") <<<=== it opens and shows the sheet here
Range("$A$1").CurrentRegion.Select <<<?=== get an error here?
Is the var it wants the current osheet?
On the line with the path, it looks like you are missing the beginning quote marks so it things that k:... is a variable. Should be:
"k:\wellcarestuff\All Data Files\"+ALLTRIM(xlfiles(1,1))
Try that and see if it works.

VBscript and Excel: Opening and closing Excel objects - Arraylist preventing closing of object

I've got a problem with a vbscript which creates Excel objects and reads from an Excel file.
The vbscript is executed from an Excel macro, and then creates and opens the Excel file and reads from it. The problem is that the Excel object isn't allways closed, even though I'm trying to to it.
Here's the code from the vbscript:
Set ExcelObject = createobject("Excel.Application")
ExcelObject.workbooks.open testWorkBookPath
Set testActionArray = CreateObject( "System.Collections.ArrayList" )
Function getTestsCaseActions (testsPath, esheet, row, col)
Set my_sheet = ExcelObject.sheets.item(esheet)
tempArray = array(my_sheet.cells(row, col-2), "")
testActionArray.Add tempArray
Do While my_sheet.cells(row, col).Value <> ""
tempArray = array(my_sheet.cells(row, col), my_sheet.cells(row+1, col))
testActionArray.Add tempArray
col = col+1
Loop
End Function
getTestsCaseActions testWorkBookPath, testCaseSheet, 3, 4
ExcelObject.Quit
Now, if I run the above code and watch the process explorer, a new Excel process is spawned when the script is started, and then closes, as expected.
However, if I insert this code after running the function, before the ExcelObject.Quit line:
For Each ArrayItem in testActionArray
IF ArrayItem(1) = "" Then
Wscript.Echo ArrayItem(0)
Else
Wscript.Echo ArrayItem(0) & " -> " & ArrayItem(1)
End If
Next
ExcelObject.Quit (STILL HERE)
then the spawned process does NOT quit, and the process list grows until Excel goes completely bananas.
I don't understand this; All the last bit of code does is loop through the ArrayList and print the contents. Why's not the process quitting?
EDIT: At seems that at least some of the Excel objects eventually disappear from the Process Explorer, but this takes about 20-30 minutes. And it's just a few of them - most are still there. At least my list at the moment has shrinked some, but there are still about 15 Excel processes running.
Also, suddenly this message appears:
File Now Available
'filename.xlsm ' is now available for editing. Choose Read-Write to open it for editing.
This line seems to help. It doesn't completely remove all extra processes, but the number grows to five, then goes back to two, and so on. So it works pretty well.
dim book: for each book in ExcelObject.Workbooks: book.saved = true: next

How do I make an Excel VBA Function that works when I reopen the document?

OK, I've just written a very simple VBA script that goes off and grabs the file size of a file found at a specified location (edit update code from dscarr):
Public Function FileSize(path As String) As Variant
On Error GoTo Err_FileSize:
Dim retVal As Variant
Dim filesys As Object
Dim file As Object
retVal = ""
Set filesys = CreateObject("Scripting.FileSystemObject")
Set file = filesys.GetFile(path)
retVal = file.Size
Exit_FileSize: On Error Resume Next
FileSize = retVal
Exit Function
Err_FileSize: retVal = "Error: " & Err.Description
Resume Exit_FileSize
End Function
If I import this into a new workbook, save the document as a "Excel Macro-Enabled Workbook" alongside an empty file called readme.txt and then put "./readme.txt" in A1 and "=FileSize(A1)" in A2, A2 evaluates properly to the file size of readme.txt, 0 bytes. Great. If I then save the document, close and reopen it, I'm warned that macros are disabled. If I enable them, the content of A2 has changed to #VALUE! and nothing I do will make the function work again. Has anyone seen this before, can anyone point out the mistake that I'm making here?
edit: the issue seems to be caused by me using relative paths. I can't explain why it works for a new workbook, but not once saved and reopened, but using absolute paths solves the problem, which as dscarr identified, was a "File Not Found" issue.
I duplicated your code in an Excel 2007 Macro Enabled workbook and found that it worked just fine with the following caveats
It does not automatically update the value (e.g. run the FileSize function) when you open the workbook. This can be compensated for by adding some code to the Worrkbook_Open event handler that calculates the workbook.
I get the #VALUE error when it cannot find the file that is specified. Indeed, when the file is missing or incorrectly named the line "Set file = filesys.GetFile(path)" throws the error number 53 "File Not Found". In this case the return value is never set because the line of code that sets it is never called. You could try setting a default value of "File Not Found" before actually attempting to retrieve the file size.
In Excel 2010, Go File->Options->Trust Center->Macro Settings and make sure the Enable option button has been selected.

HOW TO close Excel instance started by mail merge

HOW TO close Excel instance started by mail merge
this code running inside launcher does not have access to Excel running via DDE ??
'For i = 1 To Workbooks.Count
' MsgBox ("here" + Workbooks(i).Name)
'If (Workbooks(i).Name <> ActiveWorkbook.Name) Then
'Workbooks(i).Close
'End If
'Next i
You can kill the excel process like so: (from http://www.dreamincode.net/code/snippet1543.htm)
//Namespaces needed
using System.Diagnostics;
public bool FindAndKillProcess(string name)
{
//here we're going to get a list of all running processes on
//the computer
foreach (Process clsProcess in Process.GetProcesses()) {
//now we're going to see if any of the running processes
//match the currently running processes by using the StartsWith Method,
//this prevents us from incluing the .EXE for the process we're looking for.
//. Be sure to not
//add the .exe to the name you provide, i.e: NOTEPAD,
//not NOTEPAD.EXE or false is always returned even if
//notepad is running
if (clsProcess.ProcessName.StartsWith(name))
{
//since we found the proccess we now need to use the
//Kill Method to kill the process. Remember, if you have
//the process running more than once, say IE open 4
//times the loop thr way it is now will close all 4,
//if you want it to just close the first one it finds
//then add a return; after the Kill
clsProcess.Kill();
//process killed, return true
return true;
}
}
//process not found, return false
return false;
}
Excel can be closed via VBA, if called from within Excel
Application.Quit
If called from outside Excel, you will need to set a reference to Excel and then close it.
Set appExcel = GetObject(, "Excel.Application")
appExcel.Quit
You need to ensure that all Workbooks are closed or saved, otherwise Excel will prompt the user to save.

Resources