I am opening an excel file from my winform using:
Dim xlsApp3 As Excel.Application
Dim xlsWB3 As Excel.Workbook
xlsApp3 = CreateObject("Excel.Application")
xlsApp3.Visible = True
xlsWB3 = xlsApp3.Workbooks.Open("C:\myfile.xlsm")
Try
Marshal.ReleaseComObject(xlsWB3)
Marshal.ReleaseComObject(xlsApp3)
xlsWB3 = Nothing
xlsApp3 = Nothing
Catch ex As Exception
xlsWB3 = Nothing
xlsApp3 = Nothing
Finally
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()
End Try
When I look at my task manager, it closes the process, but as soon as I close the excel application window that I open, the process comes back? If I close my whole winform application, thats when the excel process closes. Is the application holding on to the process in memory?
Add the following lines:
xlsWB3.Close(True, Type.Missing, Type.Missing)
xlsApp3.Quit
Don't access anything unmanaged with two dots like you did in
xlsApp3.Workbooks.Open
The Workbooks object is opened behind the scenes but .NET doesn't know about it and it can't clean it up properly.
Instead, you need to make a .NET reference to Workbooks, and the GC will clean everything up for you. Your entire code snippet can be reduced to this
Dim xlApp = New Excel.Application()
Dim xlBooks = xlApp.Workbooks
Dim xlBook = xlBooks.Open("C:\myfile.xlsm")
xlApp.Visible = True
Related
I have an error while trying to open two excel files with giving only their names and not the full path (error: file not exist), the files are both in the same folder as the project (Debug).
I am trying to not use a static path so when i change the laptop the project will always work.
This is the code that i am using.
Thanks for your help
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
xlApp = New Excel.Application
xlBook = xlApp.Workbooks.Open(Filename:="c:\EMP_.xlsx", IgnoreReadOnlyRecommended:=True, ReadOnly:=False, Editable:=True)
xlSheet = xlBook.Worksheets(1)
If DataGridView1.DataSource IsNot Nothing Then
Dim i, j As Integer
For i = 1 To DataGridView1.RowCount - 1
For j = 1 To DataGridView1.ColumnCount
xlSheet.Cells(i + 1, j) = DataGridView1.Rows(i - 1).Cells(j - 1).Value
Next
Next
xlApp.Visible = True
xlApp.UserControl = True
xlApp.Quit()
xlApp = Nothing
Else
MsgBox("Le tableau est vide")
End If
Per Jimi's comment, something like this will read an xlsx that is alongside the exe:
Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "emp_.xlsx")
Path.Combine(Application.StartupPath, "emp_.xlsx")
Always use Path.Combine to combine paths, not string concatenation
You asked about moving the app to another PC:
THe new pc does NOT need Vsual Studio installed - visual studio creates a standalone EXE that will run without needing VS
The new PC WILL need to have an appropriate version of the .Net Framework installed. Most Windows 10 PCs will meet this requirement, but users will see a message that tells them to install it if not
The new PC WILL need to have Excel installed. Per my comment, if you dont want this or cannot guarantee it (paying for an office licence just to read an excel file is expensive and unnecessary) you should use the ACE driver or EPPlus to read your excel; neither needs Excel and both are free
Use an OpenFileDialog to show a user interface that you can choose which excel file you want to open. They're easy to use:
Dim ofd as New OpenFileDialog
Dim result = ofd.ShowDialog
If result <> DialogResult.OK Then Return 'if the user cancels
xlApp.Workbooks.Open(Filename:= ofd.Filename ...
I'm having some problems closing Excel files. I am doing a program that opens some Excel files, uses the information and then close them.
I tried some different codes, but they didn't work because the EXCEL process is still running.
My first code:
Dim aplicacaoexcel As New Excel.Application
Dim livroexcel As Object
Dim folhaexcel As Excel.Worksheet
livroexcel = aplicacaoexcel.Workbooks.Open("C:\Users\LPO1BRG\Desktop\Software Fiabilidade\Tecnicos.xlsx", UpdateLinks:=False, ReadOnly:=False, Password:="qmm7", WriteResPassword:="qmm7")
folhaexcel = livroexcel.sheets("Folha1")
aplicacaoexcel.DisplayAlerts = False
aplicacaoexcel.Visible = False
folhaexcel = Nothing
livroexcel.Close()
livroexcel = Nothing
aplicacaoexcel.Quit()
aplicacaoexcel = Nothing
Then I added this: System.GC.Collect() but it still not closing the Excel process.
Now I am trying this:
Dim process() As Process = system.Diagnostics.Process.GetProcessesByName("EXCEL")
For Each p As Process In process
p.Kill()
Next
Actually, this one is working, but it closes all the Excel files (even those that are not opened by my program).
What can I do to close just the Excel files opened by my program? :)
Releasing the Excel.Application Interop COM object is a little bit trickier than other Office Interop objects, because some objects are created without your knowledge, and they all must be released before the main Application can be actually closed.
These objects include:
The Excel.Application
The Excel.Application.WorkBooks collection
The WorkBooks collection opened WorkBook
The WorkBook Sheets collection
The Sheets collection referenced Worksheet
These objects must all be released in order to terminate the EXCEL process.
A simple solution is to use explicit declarations/assignment for all the COM objects:
Dim ExcelApplication As New Microsoft.Office.Interop.Excel.Application()
Dim ExcelWorkbooks As Workbooks = ExcelApplication.Workbooks
Dim MyWorkbook As Workbook = ExcelWorkbooks.Open("[WorkBookPath]", False)
Dim worksheets As Sheets = MyWorkbook.Worksheets
Dim MyWorksheet As Worksheet = CType(worksheets("Sheet1"), Worksheet)
When you're done, release them all:
Imports System.Runtime.InteropServices
Marshal.ReleaseComObject(MyWorksheet)
Marshal.ReleaseComObject(worksheets)
MyWorkbook.Close(False) '<= False if you don't want to save it!
Marshal.ReleaseComObject(MyWorkbook)
ExcelWorkbooks.Close()
Marshal.ReleaseComObject(ExcelWorkbooks)
ExcelApplication.Quit()
Marshal.FinalReleaseComObject(ExcelApplication)
Marshal.CleanupUnusedObjectsInCurrentContext()
Try something like workbook.Save, workbook.close
I'm a little rusty on my VB and don't have access to Visual Studio right now to test this, but I will try writing the code from memory.
The problem you are running into is that setting an object equal to Nothing still leaves the object allocated in memory and doesn't dispose of the object entirely. Even the Close() and Quit() methods of the object still leave it allocated in memory in case the program needs to access them again later. The Kill() method works because it simply kills the Excel application that is running in memory, which closes any open Excel documents as well as the ones used by COM objects. What you want to do is dispose of the specific COM objects that your application is using.
Try this change in your code though.
Dim aplicacaoexcel As New Excel.Application
Dim livroexcel As Object
Dim folhaexcel As Excel.Worksheet
livroexcel = aplicacaoexcel.Workbooks.Open("C:\Users\LPO1BRG\Desktop\Software Fiabilidade\Tecnicos.xlsx", UpdateLinks:=False, ReadOnly:=False, Password:="qmm7", WriteResPassword:="qmm7")
folhaexcel = livroexcel.sheets("Folha1")
aplicacaoexcel.DisplayAlerts = False
aplicacaoexcel.Visible = False
DisposeComObj(folhaexcel)
DisposeComObj(livroexcel)
DisposeComObj(aplicacaoexcel)
Then add the following to your application as well.
Private Sub DisposeComObj(ByRef Reference As Object)
Try
Do Until _
System.Runtime.InteropServices.Marshal.ReleaseComObject(Reference)<=0
Loop
Catch
Finally
Reference = Nothing
End Try
End Sub
Hopefully my memory is serving me well. I haven't written any code in VB or C# in more than a year and feel very out of practice. I only saw your question because I clicked on the wrong link and remembered how I used to struggle with garbage collection when I started programming.
A Visual Management Board at my workplace uses an excel spreadsheet, with many sheets in it, to populate a VMB on a TV. These sheets have many charts in them. I don't work a whole lot in VB so please bear with me.
I'm convinced my problem is because the chart the program is trying to access, literally isn't visible in the excel sheet that pops up. I may just not know what I'm talking about but this seems like a terrible way to get and display data. But I'm supposed to fix it. Here's the sheet that pops up on the screen (I've erased some information for privacy reasons):
Here is an example of the bmp being created when it tries to export a chart that is not visible in the excel window:
From my research, I've found many have resolved this issue by Activating the chart object before exporting it. I tried to do that here, but an exception gets thrown. Here's the entire section of code dealing with the charts and exports to make BMPs that are supposed to reside in the Documents folder:
Dim xlApp As Excel.Application
Dim xlWorkBooks As Excel.Workbooks
Dim xlWorkBook As Excel.Workbook
Dim xlWorkSheets As Excel.Sheets
Dim xlWorkSheet As Excel.Worksheet
xlApp = New Excel.Application
xlApp.Visible = True
xlWorkBooks = xlApp.Workbooks
xlWorkBook = xlWorkBooks.Open(ScoreCard)
xlWorkSheets = xlWorkBook.Sheets
For x As Integer = 1 To xlWorkSheets.Count
xlWorkSheet = CType(xlWorkSheets(x), Excel.Worksheet)
If xlWorkSheet.Name = My.Settings.Org Then
xlWorkSheet.ChartObjects(2).chart.Export(Filename:=path + "\Documents\OnTimeDelivery.bmp", FilterName:="BMP")
picOnTimeDelivery.Image = New System.Drawing.Bitmap(path + "\Documents\OnTimeDelivery.bmp")
xlWorkSheet.ChartObjects(3).chart.Export(Filename:=path + "\Documents\Quality.bmp", FilterName:="BMP")
picQuality.Image = New System.Drawing.Bitmap(path + "\Documents\Quality.bmp")
xlWorkSheet.ChartObjects(1).chart.Export(Filename:=path + "\Documents\NoDemandInventory.bmp", FilterName:="BMP")
picNoDemandInventory.Image = New System.Drawing.Bitmap(path + "\Documents\NoDemandInventory.bmp")
xlWorkSheet.ChartObjects(7).chart.Export(Filename:=path + "\Documents\ExcessInventory.bmp", FilterName:="BMP")
picExcessInventory.Image = New System.Drawing.Bitmap(path + "\Documents\ExcessInventory.bmp")
xlWorkSheet.ChartObjects(4).chart.Export(Filename:=path + "\Documents\Freight.bmp", FilterName:="BMP")
picFreight.Image = New System.Drawing.Bitmap(path + "\Documents\Freight.bmp")
xlWorkSheet.ChartObjects(5).chart.Export(Filename:=path + "\Documents\ShortagesByStart.bmp", FilterName:="BMP")
picShortagesByStart.Image = New System.Drawing.Bitmap(path + "\Documents\ShortagesByStart.bmp")
xlWorkSheet.ChartObjects(6).chart.Export(Filename:=path + "\Documents\ShortagesRootCause.bmp", FilterName:="BMP")
picShortagesRootCause.Image = New System.Drawing.Bitmap(path + "\Documents\ShortagesRootCause.bmp")
End If
Runtime.InteropServices.Marshal.FinalReleaseComObject(xlWorkSheet)
Next
xlWorkBook.Close()
xlApp.UserControl = True
xlApp.Quit()
'Close connection to excel sheet
MyConnection.Close()
The program crashes, throwing an Invalid Parameter exception when trying to set
picFreight.Image = New System.Drawing.Bitmap(path + "\Documents\Freight.bmp")
because the Freight.bmp in my documents folder is a 0kb file. If I change what image it's loading next (comment that line out and let it try to load ShortagesByStart.bmp) it crashes for the same reason. All of the charts past this point have one thing in common, they aren't visible on screen. Still this seems like a stupid reason to me; surely something like that wouldn't cause an issue!
First I tried to Activate the xlWorkSheet
xlWorkSheet.Activate()
but this changed nothing.
So I tried to activate the individual ChartObjects by adding
xlWorkSheet.ChartObjects(2).chart.Activate()
xlWorkSheet.ChartObjects(3).chart.Activate()
xlWorkSheet.ChartObjects(1).chart.Activate()
xlWorkSheet.ChartObjects(7).chart.Activate()
xlWorkSheet.ChartObjects(4).chart.Activate()
before the export statements. This actually threw an exception:
So, at this point I'm stuck. How can I activate the chart objects in the worksheet properly? Perhaps there's another problem that's causing this.
So the solution was to update Microsoft Office on whichever PC we wanted to run the VMB from. Corporate creates this Excel spreadsheet with the data on it that this program was trying to display. Eventually, whoever creates this excel sheet got a newer version of Excel, which creates an .xlxs file.
I honestly don't know why the spreadsheet successfully opened in ReadOnly mode, but I suppose there wasn't full support there for Office 2007 and 2010. After upgrading the copy of office on the PC the program created all of the bmps. Weird and I'm sorry if this isn't much of an answer for others but this resolved my issue!
This VBScript errs as "unknown runtime error", on the VBScript line that calls the application object's RUN method, which I'm quite sure I'm using correctly, syntactically.
With only one workbook open under the application object, I probably don't even need to prefix it with the Workbookname.
It appears the previous line (which sets the wb variable to the application object's Workbooks.Open method, does not open. Nor does it err, nor does it "eventually" open. The path is correct, the filename is correct, there is no On Error Resume Next in my VBScript.
How can the workbook not open and not error?
I hope I am wrong in thinking there is a "wait/pause" issue. Acting directly on the Excel object model, it seems like the VBScript code waiting until the excelapp object has opened the workbook should be a given?
dim excelapp, wb
set excelapp = createobject("excel.application")
excelapp.enableevents=true
excelapp.visible=true
set wb = excelapp.workbooks.open("C:\Users\John\Desktop\Scheduled Jobs from Isaac\Availability.xlsb")
'MSGBOX "SHOULD BE OPEN"
excelapp.windowstate = -4137 'value for constant xlMaximized acccording to msdn
excelapp.caption = "Running AVAILABILITY - Please WAIT..."
excelapp.run "Availability.xlsb!ChangeAndCopyFile"
final vbscript code i used, for better or worse:
dim excelapp, wb
'set excelapp = createobject("excel.application")
'excelapp.enableevents=true
'excelapp.visible=true
'set wb = excelapp.workbooks.open("C:\Users\John\Desktop\ScheduledJobsfromIsaac\Availability.xlsb")
'although I don't know why the above line is silently failing, i'm going to use an alternate method I read on S.O.:
set wb = GetObject("C:\Users\John\Desktop\ScheduledJobsfromIsaac\Availability.xlsb")
set excelapp = getobject(,"excel.application")
excelapp.enableevents=true
excelapp.visible=true
excelapp.windowstate = -4137 'value for constant xlMaximized acccording to msdn
excelapp.caption = "Running AVAILABILITY - Please WAIT..."
excelapp.run "Availability.xlsb!ChangeAndCopyFile"
wb.close(true)
excelapp.caption = "10 seconds to close - please WAIT..."
wscript.sleep 10000
excelapp.displayalerts=false
excelapp.quit
probably, it helps if you can describe where and how you execute your vbscript above? is this coded in a .vbs file and execute with wscript.exe or cscript.exe, or embedded in a HTML or HTA?
If this is scripted in HTML, what browser are you using to view that? Please take note that almost all modern browsers will just ignore the vbscript silently.
I am calling Excel objects from MS Access and I do not manage to close the instance!
One would believe that the workbooks are closed because we cannot see them anymore but in task Manager --> Processes I still have EXCEL.EXE*32 running...
This is what I have:
Dim xlApp as Excel.Application
Dim wbks as Workbooks
Set xlApp = GetObject("", "Excel.Application")
Set wbks = xlApp.Workbooks
wbks.Open "C:\blp\api\Office Tools\BloombergUI.xla"
wbks("BloombergUI.xla").RunAutoMacros (xlAutoOpen)
wbks.Add
xlApp.Visible = True
...performs actions...
xlApp.Workbooks(1).SaveAs FileName:=strFullPath, FileFormat:=xlCSV
xlApp.Application.DisplayAlerts = False
xlApp.Workbooks("BbgDivData.csv").Close SaveChanges:=True
wbks("BloombergUI.xla").Close
xlApp.Quit
Set xlApp = Nothing
Any idea why it is still there? I suspect the Add-in to mess things up!
You never explicitly set the collection of workbooks to nothing, you just call close from one member. I would try adding:
Set wbks = Nothing
after the Close and before the Quit.