How do I declare my active Excel workbook and active Excel worksheet as a variable? - vb.net

I am trying to figure how to set the active workbook and active sheet as a variable I can reference later. I have my script set up, and I placed ????'s in the areas where I assume I would put the reference.
Any suggetsions?
Dim oXL As Application
Dim oWB As Microsoft.Office.Interop.Excel.Workbook
Dim oSheet As Microsoft.Office.Interop.Excel.Worksheet
Dim oRng As Microsoft.Office.Interop.Excel.Range
oWB = ????
oSheet = ?????
Added info from comment to Karen Payne's answer:
I am trying to reference an existing one I already have open, that is
the active window at the time of using my application.
i.e.: How can I attach to an open Excel instance and retrieve a reference to the ActiveWorkbook?

Perhaps the following will help. It is a demo that sets the active sheet in xlWorkSheet that can be used as you see fit.
Option Strict On
Imports Excel = Microsoft.Office.Interop.Excel
Imports Microsoft.Office
Imports System.Runtime.InteropServices
Module SetDefaultWorkSheetCode
Public Sub SetDefaultSheet(ByVal FileName As String, ByVal SheetName As String)
Dim xlApp As Excel.Application = Nothing
Dim xlWorkBooks As Excel.Workbooks = Nothing
Dim xlWorkBook As Excel.Workbook = Nothing
Dim xlWorkSheet As Excel.Worksheet = Nothing
Dim xlWorkSheets As Excel.Sheets = Nothing
xlApp = New Excel.Application
xlApp.DisplayAlerts = False
xlWorkBooks = xlApp.Workbooks
xlWorkBook = xlWorkBooks.Open(FileName)
xlApp.Visible = False
xlWorkSheets = xlWorkBook.Sheets
For x As Integer = 1 To xlWorkSheets.Count
xlWorkSheet = CType(xlWorkSheets(x), Excel.Worksheet)
If xlWorkSheet.Name = SheetName Then
xlWorkSheet.Activate()
xlWorkSheet.SaveAs(FileName)
Runtime.InteropServices.Marshal.FinalReleaseComObject(xlWorkSheet)
xlWorkSheet = Nothing
Exit For
End If
Runtime.InteropServices.Marshal.FinalReleaseComObject(xlWorkSheet)
xlWorkSheet = Nothing
Next
xlWorkBook.Close()
xlApp.UserControl = True
xlApp.Quit()
ReleaseComObject(xlWorkSheets)
ReleaseComObject(xlWorkSheet)
ReleaseComObject(xlWorkBook)
ReleaseComObject(xlWorkBooks)
ReleaseComObject(xlApp)
End Sub
Private Sub ReleaseComObject(ByVal obj As Object)
Try
If obj IsNot Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
End If
Catch ex As Exception
obj = Nothing
End Try
End Sub
End Module

With those Excel objects, you have to assign values to them using the "Set" keyword. For example:
Set oWB = ActiveWorkbook

Here are two techniques for attaching to a running Excel instance. I think the method shown in 'Button1_Click' is one you are seeking, but I also showed second method that looks in the Running Object Table (ROT) for a matching Workbook name.
Imports System.Runtime.InteropServices
Imports Microsoft.Office.Interop
Public Class Form1
Private WithEvents ExcelCleanUpTimer As New Timer With {.Interval = 100}
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim app As Excel.Application
Try ' to attach to any Excel instance
app = CType(Marshal.GetActiveObject("Excel.Application"), Excel.Application)
Catch ex As Exception
MessageBox.Show("No Excel instances found")
Exit Sub
End Try
' take over responsibility for closing Excel
app.UserControl = False
app.Visible = False
Dim activeWB As Excel.Workbook = app.ActiveWorkbook
Dim activeSheet As Object = app.ActiveSheet
' determine if ActiveSheet is a Worksheet or Chart
' if it is a Worksheet, activeChart is Nothing
' if it is a Chart, activeWorksheet is Nothing
Dim activeWorksheet As Excel.Worksheet = TryCast(activeSheet, Excel.Worksheet)
Dim activeChart As Excel.Chart = TryCast(activeSheet, Excel.Chart)
If activeWorksheet IsNot Nothing Then
For Each cell As Excel.Range In activeWorksheet.Range("A1:A20")
cell.Value2 = "hello"
Next
End If
'shut Excel down, don't save anything
app.DisplayAlerts = False
app.Workbooks.Close()
app.Quit()
' using a timer lets any ComObj variables in this method go out of context and
' become eligible for finalization. GC's call to RCW wrapper finalizer will
' release its reference counts on Excel
ExcelCleanUpTimer.Start()
End Sub
Private Sub ExcelCleanUpTimer_Tick(sender As Object, e As EventArgs) Handles ExcelCleanUpTimer.Tick
ExcelCleanUpTimer.Stop()
GC.Collect()
GC.WaitForPendingFinalizers()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
' if this is a saved Workbook, the path will be the full file path
Dim path As String = "Book1" ' or the full file path to a workbook including the extension
Dim activeWorkbook As Excel.Workbook = Nothing
Try
' this technique differs for Marshal.GetActiveObject in that if the path
' is a valid file path to an Excel file and Excel is not running, it will
' launch Excel to open the file.
activeWorkbook = CType(Marshal.BindToMoniker(path), Excel.Workbook)
Catch ex As Exception
' an exception will be throw if 'path' is not found in the Runinng Object Table (ROT)
MessageBox.Show(path & " not found")
Exit Sub
End Try
Dim app As Excel.Application = activeWorkbook.Application
app.Visible = True
app.UserControl = True
' the wb window will be hidden if opening a file
activeWorkbook.Windows(1).Visible = True
ExcelCleanUpTimer.Start()
End Sub
End Class

Sorry about my last answer.. I didn't see that you were trying to do it in .NET. Anyway, just like in the context of Excel, you have to first open or create all of the workbooks that you want to work with. If you already have it open, then you can use the file name of the workbook you want to assign it to a workbook variable..
xlWorkbook = xlApp.Workbooks.Item("filename of the workbook already open")

Here is the same code, partly commented out as to the activate part and I added in code to show how to get the current active sheet.
Option Strict On
Imports Excel = Microsoft.Office.Interop.Excel
Imports Microsoft.Office
Imports System.Runtime.InteropServices
Module SheetCode
Public Sub SetDefaultSheet(ByVal FileName As String, ByVal SheetName As String)
Dim xlApp As Excel.Application = Nothing
Dim xlWorkBooks As Excel.Workbooks = Nothing
Dim xlWorkBook As Excel.Workbook = Nothing
Dim xlWorkSheet As Excel.Worksheet = Nothing
Dim xlWorkSheets As Excel.Sheets = Nothing
xlApp = New Excel.Application
xlApp.DisplayAlerts = False
xlWorkBooks = xlApp.Workbooks
xlWorkBook = xlWorkBooks.Open(FileName)
xlApp.Visible = False
xlWorkSheets = xlWorkBook.Sheets
'
' Here I added how to get the current active worksheet
'
Dim ActiveSheetInWorkBook As Excel.Worksheet = CType(xlWorkBook.ActiveSheet, Excel.Worksheet)
Console.WriteLine(ActiveSheetInWorkBook.Name)
Runtime.InteropServices.Marshal.FinalReleaseComObject(ActiveSheetInWorkBook)
ActiveSheetInWorkBook = Nothing
'For x As Integer = 1 To xlWorkSheets.Count
' xlWorkSheet = CType(xlWorkSheets(x), Excel.Worksheet)
' If xlWorkSheet.Name = SheetName Then
' xlWorkSheet.Activate()
' xlWorkSheet.SaveAs(FileName)
' Runtime.InteropServices.Marshal.FinalReleaseComObject(xlWorkSheet)
' xlWorkSheet = Nothing
' Exit For
' End If
' Runtime.InteropServices.Marshal.FinalReleaseComObject(xlWorkSheet)
' xlWorkSheet = Nothing
'Next
xlWorkBook.Close()
xlApp.UserControl = True
xlApp.Quit()
ReleaseComObject(xlWorkSheets)
ReleaseComObject(xlWorkSheet)
ReleaseComObject(xlWorkBook)
ReleaseComObject(xlWorkBooks)
ReleaseComObject(xlApp)
End Sub
Private Sub ReleaseComObject(ByVal obj As Object)
Try
If obj IsNot Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
End If
Catch ex As Exception
obj = Nothing
End Try
End Sub
End Module

Related

Copying Datagridview to excel - leaves excel process open

Can anyone point out what is causing the excel process to remain open after my code finishes?
I've researched everything on this topic and the main point seems to be to avoid 3 dots with excel interop, but I believe I have done that and I still can't see where I'm going wrong.
my process is to copy the datagridview to the clipboard and then paste it in a newly created excel file, save it, close excel, and then give the user an option to open the file.
Two scenarios. First, when I run through the code and DON'T open the excel file it leaves the process open. Second, if I open the workbook and then close the workbook it doesn't leave a process running. I don't understand the difference because the opening of the workbook happens after I try to close and release all references to excel.
Private Sub CopyDGVtoClipBoard()
Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
Me.DataGridView1.RowHeadersVisible = False
Me.DataGridView1.SelectAll()
Dim dataObj As DataObject = Me.DataGridView1.GetClipboardContent
If dataObj IsNot Nothing Then
Clipboard.SetDataObject(dataObj)
End If
Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithAutoHeaderText
Me.DataGridView1.RowHeadersVisible = True
Me.DataGridView1.ClearSelection()
End Sub
Private Sub ExportToExcel()
If Me.DataGridView1.Rows.Count < 1 Then Exit Sub
CopyDGVtoClipBoard()
SaveFileDialog1.Filter = "Excel File|*.xlsx"
SaveFileDialog1.Title = "Save In"
SaveFileDialog1.FileName = "Generic name"
If SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
If SaveFileDialog1.FileName <> "" Then
Dim xlExcel As excel.Application
Dim xlWorkBooks As excel.Workbooks
Dim xlWorkBook As excel.Workbook
Dim xlWorkSheet As excel.Worksheet
Dim CR As excel.Range
Dim misValue As Object = System.Reflection.Missing.Value
xlExcel = New excel.Application
xlExcel.Visible = True
xlWorkBooks = xlExcel.Workbooks
xlWorkBook = xlWorkBooks.Add(misValue)
xlWorkBook.Application.DisplayAlerts = False
xlWorkSheet = xlWorkBook.ActiveSheet
CR = xlWorkSheet.Cells(1, 1)
CR.Select()
xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, True)
xlWorkBook.SaveAs(SaveFileDialog1.FileName())
xlWorkBook.Close(False)
misValue = Nothing
ReleaseExcel(CR)
ReleaseExcel(xlWorkSheet)
ReleaseExcel(xlWorkBook)
ReleaseExcel(xlWorkBooks)
xlExcel.Quit()
ReleaseExcel(xlExcel)
Dim OpenCheck As MsgBoxResult = MsgBox("Would you like to open the file?", MsgBoxStyle.YesNo, "Open File")
Dim fPath As String = SaveFileDialog1.FileName
If OpenCheck = MsgBoxResult.Yes Then
Process.Start(fPath)
End If
End If
End If
Private Sub ReleaseExcel(ByVal O As Object)
Do While System.Runtime.InteropServices.Marshal.ReleaseComObject(O) >= 0
System.Runtime.InteropServices.Marshal.ReleaseComObject(O)
Loop
O = Nothing
End Sub
I've narrowed the issue down to the below code. If I do everything except specifying a range and adding data it'll close and end the process but as soon as I reference CR = xlWorkSheet.Cells(1,1) it hangs a process
CR = xlWorkSheet.Cells(1, 1)
CR.Select()
xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, True)
Edit
So I compared my code vs. what Karen posted and made some slight adjustments to my code (full code plus changes listed below), but for some reason it works and doesn't leave a process open! Not sure how, but I'll take it.
Private Sub CopyDGVtoClipBoard()
Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
Me.DataGridView1.RowHeadersVisible = False
Me.DataGridView1.SelectAll()
Dim dataObj As DataObject = Me.DataGridView1.GetClipboardContent
If dataObj IsNot Nothing Then
Clipboard.SetDataObject(dataObj)
End If
Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithAutoHeaderText
Me.DataGridView1.RowHeadersVisible = True
Me.DataGridView1.ClearSelection()
End Sub
Private Sub ExportToExcel()
If Me.DataGridView1.Rows.Count < 1 Then Exit Sub
CopyDGVtoClipBoard()
Dim DateCon As DateTime = DateTime.ParseExact(Today.ToShortDateString, "M/d/yyyy", Nothing)
SaveFileDialog1.Filter = "Excel File|*.xlsx"
SaveFileDialog1.Title = "Save In"
SaveFileDialog1.FileName = "Generic Name"
If SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
If SaveFileDialog1.FileName <> "" Then
Dim xlExcel As excel.Application = Nothing
Dim xlWorkBooks As excel.Workbooks = Nothing
Dim xlWorkBook As excel.Workbook = Nothing
Dim xlWorkSheet As excel.Worksheet = Nothing
Dim CR As excel.Range = Nothing
Dim misValue As Object = System.Reflection.Missing.Value
xlExcel = New excel.Application
xlExcel.Visible = False
xlExcel.DisplayAlerts = False
xlWorkBooks = xlExcel.Workbooks
xlWorkBook = xlWorkBooks.Add(misValue)
xlWorkSheet = xlWorkBook.ActiveSheet
CR = xlWorkSheet.Range("A1")
CR.PasteSpecial(excel.XlPasteType.xlPasteAll)
CR.Select()
xlWorkBook.SaveAs(SaveFileDialog1.FileName)
Clipboard.Clear()
ReleaseExcel(CR)
CR = Nothing
ReleaseExcel(xlWorkSheet)
xlWorkSheet = Nothing
xlWorkBook.Close(False)
ReleaseExcel(xlWorkBook)
xlWorkBook = Nothing
ReleaseExcel(xlWorkBooks)
xlWorkBooks = Nothing
xlExcel.Quit()
ReleaseExcel(xlExcel)
xlExcel = Nothing
Dim OpenCheck As MsgBoxResult = MsgBox("Would you like to open the file?", MsgBoxStyle.YesNo, "Open File")
Dim fPath As String = SaveFileDialog1.FileName
If OpenCheck = MsgBoxResult.Yes Then
Process.Start(fPath)
End If
End If
End If
End Sub
Private Sub ReleaseExcel(ByVal O As Object)
Try
Do Until System.Runtime.InteropServices.Marshal.FinalReleaseComObject(O) = 0
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(O)
Loop
Catch ex As Exception
Finally
GC.Collect()
GC.WaitForPendingFinalizers()
End Try
End Sub
The following goes along with using only two dots. After the work is done excel is properly disposed of.
Option Strict On
Option Infer Off
Imports Excel = Microsoft.Office.Interop.Excel
Imports Microsoft.Office
Imports System.Runtime.InteropServices
Module Demo1
Public Sub DoPaste()
Dim FileName As String = IO.Path.Combine(Application.StartupPath, "SomeFile.xlsx")
Dim SheetName As String = "Sheet1"
Dim Proceed As Boolean = False
Dim xlApp As Excel.Application = Nothing
Dim xlWorkBooks As Excel.Workbooks = Nothing
Dim xlWorkBook As Excel.Workbook = Nothing
Dim xlWorkSheet As Excel.Worksheet = Nothing
Dim xlWorkSheets As Excel.Sheets = Nothing
Dim xlCells As Excel.Range = Nothing
xlApp = New Excel.Application
xlApp.DisplayAlerts = False
xlWorkBooks = xlApp.Workbooks
xlWorkBook = xlWorkBooks.Open(FileName)
xlApp.Visible = False
xlWorkSheets = xlWorkBook.Sheets
For x As Integer = 1 To xlWorkSheets.Count
xlWorkSheet = CType(xlWorkSheets(x), Excel.Worksheet)
If xlWorkSheet.Name = SheetName Then
Dim xlRange1 As Excel.Range = Nothing
xlRange1 = xlWorkSheet.Range("A1:B6")
xlRange1.Select()
xlRange1.Copy()
Dim xlDestination As Excel.Range = Nothing
xlDestination = xlWorkSheet.Range("C1:D6")
xlDestination.PasteSpecial(Excel.XlPasteType.xlPasteAll, Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone)
Marshal.FinalReleaseComObject(xlDestination)
xlDestination = Nothing
Marshal.FinalReleaseComObject(xlRange1)
xlRange1 = Nothing
xlWorkSheet.SaveAs(FileName)
Marshal.FinalReleaseComObject(xlWorkSheet)
xlWorkSheet = Nothing
Exit For
End If
Next
xlWorkBook.Close()
xlApp.UserControl = True
xlApp.Quit()
ReleaseComObject(xlCells)
ReleaseComObject(xlWorkSheets)
ReleaseComObject(xlWorkSheet)
ReleaseComObject(xlWorkBook)
ReleaseComObject(xlWorkBooks)
ReleaseComObject(xlApp)
End Sub
Private Sub ReleaseComObject(ByVal obj As Object)
Try
If obj IsNot Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
End If
Catch ex As Exception
obj = Nothing
End Try
End Sub
End Module

Unable to kill excel processes

I am using the followiwing code to do some copying and pasting with excel files:
Imports Excel = Microsoft.Office.Interop.Excel
Imports System.IO
Imports System.Runtime.InteropServices
Private Sub btnCombine_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCombine.Click
Dim xlAppSource As New Excel.Application
Dim xlAppTarget As New Excel.Application
Dim xlWbSource As Excel.Workbook
Dim xlWbTarget As Excel.Workbook
Dim xlsheetSource As Excel.Worksheet
Dim xlsheetTarget As Excel.Worksheet
Dim xlRangeSource As Excel.Range
Dim xlRangeTarget As Excel.Range
Dim Progress As Integer = 0
pbrProgress.Minimum = 0
pbrProgress.Maximum = amountOfFiles
btnCombine.Enabled = False
btnSelect.Enabled = False
pbrProgress.Visible = True
getSaveLocation()
MakeExcelFile()
'loop through all excel files to get the required data
For i = 0 To amountOfFiles - 1
Dim CurrentFile As String = strFileNames(i)
Dim IntAmountOfRows As Integer = amountOfRows(CurrentFile)
Dim intStartOfEmptyRow As Integer = amountOfRows(SummaryLocation)
xlAppSource.DisplayAlerts = False
xlAppTarget.DisplayAlerts = False
'Set current workbook
xlWbSource = xlAppSource.Workbooks.Open(CurrentFile)
xlWbTarget = xlAppTarget.Workbooks.Open(SummaryLocation)
'set current worksheet
xlsheetSource = xlWbSource.ActiveSheet
xlsheetTarget = xlWbTarget.ActiveSheet
'copy range of data from source to target file
xlRangeSource = xlsheetSource.Range("A2:k" & IntAmountOfRows)
xlRangeSource.Copy()
xlRangeTarget = xlsheetTarget.Range("A" & intStartOfEmptyRow)
xlRangeTarget.PasteSpecial(Excel.XlPasteType.xlPasteValues)
'save summary file before closing
xlsheetTarget.SaveAs(SummaryLocation)
'updating progress bar
Progress = Progress + 1
pbrProgress.Value = Progress
Next
'close excel
xlWbSource.Close(True)
xlWbTarget.Close(True)
xlAppSource.Quit()
xlAppTarget.Quit()
xlAppSource.DisplayAlerts = True
xlAppTarget.DisplayAlerts = True
'Cleanup
Marshal.ReleaseComObject(xlAppSource)
Marshal.ReleaseComObject(xlAppTarget)
Marshal.ReleaseComObject(xlWbSource)
Marshal.ReleaseComObject(xlWbTarget)
Marshal.ReleaseComObject(xlsheetSource)
Marshal.ReleaseComObject(xlsheettarget)
Marshal.ReleaseComObject(xlRangeSource)
Marshal.ReleaseComObject(xlRangeTarget)
xlAppSource = Nothing
xlAppTarget = Nothing
xlWbSource = Nothing
xlWbTarget = Nothing
xlsheetSource = Nothing
xlsheetTarget = Nothing
xlRangeSource = Nothing
xlRangeTarget = Nothing
MsgBox("Samenvoegen compleet")
init()
End Sub
I have tried every solution given on SO:
Never use 2 points on a line
I have tried using marshall.ReleaseComObject
I have tried setting the objects to "Nothing"
However, everytime I run the application, there will be 10-20 excel processes still running.
Option Explicit
Sub Main()
Dim xlApp As Excel.Application
Set xlApp = New Excel.Application
xlApp.Visible = False
xlApp.DisplayAlerts = False
Dim xlWb As Workbook
Set xlWb = xlApp.Workbooks.Open("C:\...\path")
Dim xlSht As Worksheet
Set xlSht = xlWb.Sheets(1)
xlSht.Range("A1") = "message from " & ThisWorkbook.FullName
xlWb.Saved = True
xlWb.Save
xlWb.Close
xlApp.Quit
End Sub
Works for me every single time and does not leave any Excel processes hanging in the task manager.
Note: if your code breaks at some point and you do not handle the already opened objects properly then they will just hang in the processes tab in the Task Manager. If you haven't implemented error handling in your code then start here.
just consider this as alternative
Option Explicit
Sub Main()
On Error GoTo ErrHandler
Dim xlApp As Excel.Application
Set xlApp = New Excel.Application
xlApp.Visible = False
xlApp.DisplayAlerts = False
Dim xlWb As Workbook
Set xlWb = xlApp.Workbooks.Open("C:\...\path")
Dim xlSht As Worksheet
Set xlSht = xlWb.Sheets(1)
xlSht.Range("A1") = "message from " & ThisWorkbook.FullName
xlWb.Saved = True
xlWb.Save
xlWb.Close
xlApp.Quit
Exit Sub
ErrHandler:
xlWb.Saved = True
xlWb.Save
xlWb.Close
xlApp.Quit
End Sub
The Interop Marshal release doesn't always work because Excel XP and lower suck at releasing. I had to use your loop, but replace the Process.Close() and Process.Quit() with Process.Kill(). Works like a charm. Just be careful that you want ALL versions of excel.exe to be killed, because they will.
I use this:
Workbook.Save()
Workbook.Close()
Application.Quit()
System.Runtime.InteropServices.Marshal.ReleaseComObject(Application)
Worksheet = Nothing
Workbook = Nothing
Application = Nothing
Dim proc As System.Diagnostics.Process
For Each proc In System.Diagnostics.Process.GetProcessesByName("EXCEL")
proc.Kill()
Next
When you do anything with the Excel Interop, it creates a new process.
The problem with killing all Excel processes is that you may kill a process that you are working with. You can kill all processes which have been running for a certain length of time (i.e. from a certain timestamp) with:
Dim proc As System.Diagnostics.Process
Dim info As ManagementObject
Dim search As New ManagementObjectSearcher("SELECT ProcessId FROM Win32_process WHERE caption = 'Excel'")
For Each info In search.Get()
'The string will give you the time that the process started
'You can then subtract that from the current time to see if you want to kill the process
Dim TheString As String = info.GetText(TextFormat.Mof).ToString
'Kill the process according to its ID
proc = System.Diagnostics.Process.GetProcessById(Mid$(TheString, _
(Len(TheString) - 8), 4))
proc.CloseMainWindow()
proc.Refresh()
If proc.HasExited Then GoTo NoKill
proc.Kill()
NoKill:
Next
You'll need to add:
Imports System.Management
and add the reference for the 'System.Management' to your project.
You can obtain the process ID from the Excel.Application hwnd and use that to kill the process safely.

Excel process does not close

I have this sub in my class that just opens excel to see if a range is present. The problem I am running into is that the process just does not close. I've been googling my tail off and I can't find a resolution. Please take a look at my code and see if it something simple stupid that I am missing. Thanks.
Private Function NamedRangeExists(ByVal ProductFileName As String, ByVal RangeName As String) As Boolean
Dim ExcelApp As Excel.Application
'Create an Excel Object
ExcelApp = CType(CreateObject("Excel.Application"), Excel.Application)
Dim TheRange As Microsoft.Office.Interop.Excel.Name
Dim TheRangeName As String = ""
Dim ObjWorkbook As Excel.Workbooks = ExcelApp.Workbooks
'Open the Product
Dim TheProduct As Excel.Workbook = ObjWorkbook.Open(ProductFileName)
For Each TheRange In TheProduct.Names 'ExcelApp.ActiveWorkbook.Names
TheRangeName = CStr(TheRange.Name)
If (InStr(TheRangeName, RangeName) <> 0) Then
TheProduct.Save()
TheProduct.Close()
ExcelApp.Quit()
ExcelApp = Nothing
Marshal.ReleaseComObject(ExcelApp)
Return True
End If
Next
TheProduct.Close()
ObjWorkbook.Close()
ExcelApp.Quit()
Marshal.ReleaseComObject(ObjWorkbook)
Marshal.ReleaseComObject(TheProduct)
Marshal.ReleaseComObject(ExcelApp)
TheProduct = Nothing
ObjWorkbook = Nothing
ExcelApp = Nothing
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
Return False
End Function
For any future viewers, this is the general method that I use:
Dim xlApp As New Excel.Application
Dim xlWB As Excel.Workbook = xlApp.Workbooks.Add
Dim xlWS As Excel.Worksheet = xlWB.Worksheets(1)
'do stuff
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()
FinalReleaseComObject(xlWS)
xlWB.Close(False)
FinalReleaseComObject(xlWB)
xlApp.Quit()
FinalReleaseComObject(xlApp)
You'll need Imports System.Runtime.InteropServices.Marshal.
Any other declared Excel objects (such as TheRange in the OP's case) will need to be set to Nothing before garbage collection.
The sequence of commands shown here is important. A detailed explanation can be found here.
This will do the job! Documentation
Marshal.FinalReleaseComObject(obj)

Modifying a template based excel in VB.NET

I am tyring to run code like this
xlWorkSheet.Cells(rownumber, 1) = "Some Value"
the problem is when I open the excel document the cell value is not updated.
any help will be appreciated
I use the following code to open the file
Dim pathtofile As String = Server.MapPath("~/UserControls/Upload/MyUpload.xlsx")
Dim xlApp As Excel.Application =New Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim xlworkbooks As Excel.Workbooks
Dim xlWorksheets As Excel.Worksheets
Dim misValue As Object = System.Reflection.Missing.Value
Dim xlWorkSheet As Excel.Worksheet = Nothing
xlWorkBook = xlApp.Workbooks.Add(misValue)
xlworkbooks = xlApp.Workbooks
xlWorkBook = xlworkbooks.Open(pathtofile )
xlWorkSheet = xlWorkBook.Sheets("Sheet1")
You need to save, close, and release the com objects to make sure excel doesn't remain running as a process.
Sub save(filename As String) ' Saves the sheet under a specfic name
xlWorkBook.SaveAs(filename)
End Sub
Sub closexl()
xlWorkBooks.Close()
xlApp.Quit()
End Sub
Sub cleanup() ' Releases all of the com objects to object not have excel running as a process after this method finishes
GC.Collect()
GC.WaitForPendingFinalizers()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkSheet)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkBook)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)
xlApp = Nothing
End Sub

Manipulating Excel files using VB8

My script is pulling some information (filename, date, &c) from a server that contains only (nearly) identical excel files generated by a separate application whenever it is used. The goal is to find out who is using the tool and how often.
I need help with two things: extracting info from within the excel file, and appending the results to the SAME excel file each time it's run instead of creating a new file each time.
Here is what I have...
Imports Excel = Microsoft.Office.Interop.Excel Imports System Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'declare excel objects
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim xlWorkSheet As Excel.Worksheet
Dim misValue As Object = System.Reflection.Missing.Value
Dim i As Integer = 2
'I know this is the problem area...
xlApp = New Excel.Application
xlWorkBook = xlApp.Workbooks.Add(misValue)
xlWorkSheet = xlWorkBook.Sheets("sheet1")
xlWorkSheet.Cells(1, 1) = " File Name "
xlWorkSheet.Cells(1, 2) = " Date Created "
'this should be cell B1
xlWorkSheet.Cells(1, 3) = " Requestor "
'this should be cell B21
xlWorkSheet.Cells(1, 4) = " Lead Type"
'get to directory
For Each strFolder As String In _
My.Computer.FileSystem.GetDirectories("Z:\\...")
'get file names
Dim infoReader As System.IO.FileInfo
infoReader = My.Computer.FileSystem.GetFileInfo(strFolder)
'write to excel worksheet
xlWorkSheet.Cells(i, 1) = strFolder
xlWorkSheet.Cells(i, 2) = infoReader.CreationTime
i += 1
Next
xlWorkSheet.SaveAs("C:\...")
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlApp)
releaseObject(xlWorkBook)
releaseObject(xlWorkSheet)
MsgBox("Excel file created , see file in c:\Documents")
End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
Instead of creating a new application and workbook, just use activeworkbook, e.g.
replace
'I know this is the problem area...
xlApp = New Excel.Application
xlWorkBook = xlApp.Workbooks.Add(misValue)
xlWorkSheet = xlWorkBook.Sheets("sheet1")
with
xlWorkBook = xlApp.ActiveWorkbook
xlWorkSheet = xlWorkBook.Sheets("sheetname")
where you replace sheetname with whatever the desired sheet name is.
Alternatively, you could just use ActiveSheet.