M
Mike G
Background: I wrote a VB .NET class that can be passed a form. Any
datagrids on the passed in form are listed to the user and the user
can select which ones they want exported to Excel. Each grid is
exported to a different worksheet within the same workbook.
The Excel file is created successfully, but Excel remains open in Task
Manager until the application is closed entirely. To troubleshoot
this, I have commented out almost all the Excel references to range
objects and worksheet objects to isolate where the problem is
occurring. Basically, in the scaled down code, I have three lines of
test code that, when placed right after the declaration of the
Worksheet object, work fine and the Excel closes properly. When I
move these further down in the code into some nested if statements,
Excel does not close. In the code, I have the working version
uncommented out, and I also show the commented place where the same
three lines would cause this error. They are:
wrkSheet = wrkBook.Worksheets.Add()
wrkSheet.Name = "TEST"
wrkSheet.Range("A1").Value = "TEST"
Steps I've tried:
1.) As mentioned, I scaled everything down so there are no references
to any more Excel objects than there need to be. In the test version,
I no longer reference the range object. There shouldn't be any
implicit references to Excel objects in the version below.
2.) I've made sure all objects are first released using
ReleaseComObject and then set to nothing.
3.) I've confirmed that the objects are released and set to nothing in
proper order and I've checked the variable state after each release
and it appears to be working fine.
The twist is, the only thing different between a working version and a
version that fails to close Excel is the placement of some lines of
code.
Any help would be greatly appreciated. I apologize for the extraneous
code in the example below but it seemed silly to remove everything
just to give an example.
*****************************************************************************
Private Sub btnExport_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnExport.Click
' get the file name to save the list view information in from
the standard save dialog
Dim saveFileDialog1 As New SaveFileDialog
Dim xx As Integer = 0
Dim yy As Integer = 0
Dim rowCount As Integer = 0
Dim colCount As Integer = 0
Dim EndOfRows As Boolean = False
Dim NoRows As Boolean = False
Dim RowTest As String = ""
Dim vctl As Control
Dim vctl2 As Control
Dim app As New Excel.Application
Dim wrkBooks As Excel.Workbooks = app.Workbooks
Dim wrkBook As Excel.Workbook = wrkBooks.Add()
Dim wrkSheet As Excel.Worksheet
Dim wrkRange As Excel.Range
''test *****NOTE: When the next three lines of code are moved
to later
'' on in the module, Excel will not close. When left
here,
'' Excel closed fine. That is the only difference in
this
'' scaled down version of the code.
wrkSheet = wrkBook.Worksheets.Add()
wrkSheet.Name = "TEST"
wrkSheet.Range("A1").Value = "TEST"
''End Test **** NOTE
If chkBox1.Checked = True Or chkBox2.Checked = True Or
chkBox3.Checked = True _
Or chkBox4.Checked = True Or chkBox5.Checked = True Or
chkBox6.Checked = True _
Or chkBox7.Checked = True Or chkBox8.Checked = True Or
chkBox9.Checked = True Then
Try
saveFileDialog1.InitialDirectory = m_DefaultDirectory
saveFileDialog1.Filter = "Excel files (*.xls)|*.xls"
saveFileDialog1.FilterIndex = 1
saveFileDialog1.CheckFileExists = False
saveFileDialog1.CheckPathExists = True
saveFileDialog1.RestoreDirectory = True
saveFileDialog1.FileName = Date.Now.Year.ToString &
"-" & Date.Now.Month.ToString & "-" & Date.Now.Day.ToString _
& "_ExportGrids"
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
For Each vctl In m_Form.Controls
If TypeOf vctl Is DataGrid Then
For Each vctl2 In Me.Controls
If TypeOf vctl2 Is CheckBox Then
If CType(vctl2, CheckBox).Checked
= True Then
If CType(vctl2, CheckBox).Tag
= CType(vctl, DataGrid).Name Then
xx = 0
yy = 0
NoRows = False
EndOfRows = False
colCount =
CType(CType(vctl, DataGrid).DataSource, DataTable).Columns.Count()
rowCount =
CType(CType(vctl, DataGrid).DataSource, DataTable).Rows.Count
If rowCount = 0 Then
NoRows = True
End If
If Not NoRows Then
'****NOTE: If I uncomment these
' and Excel doesn't close
'wrkSheet =
wrkBook.Worksheets.Add()
'wrkSheet.Name = "TEST"
'wrkSheet.Range("A1").Value
= "TEST"
'****End NOTE
Dim
strColumnArray(colCount) As String
Dim
strRowArray(rowCount, colCount) As String
Dim strRange As String
Dim EndColumn As
String
'wrkSheet.Name =
FormatWrkSheetName(CType(vctl, DataGrid).CaptionText)
For yy = 0 To colCount
- 1
strColumnArray(yy)
= CType(CType(vctl, DataGrid).DataSource,
DataTable).Columns(yy).ColumnName.ToString
Next
Select Case colCount
Case Is > 26
EndColumn =
"A" & Chr((colCount - 26) + 64)
Case Is > 52
EndColumn =
"B" & Chr((colCount - 26) + 64)
Case Is > 78
EndColumn =
"C" & Chr((colCount - 26) + 64)
Case Is > 104
EndColumn =
"D" & Chr((colCount - 26) + 64)
Case Else
EndColumn =
Chr((colCount) + 64)
End Select
strRange = "A1:" &
EndColumn & "1"
'wrkSheet.Range(strRange).Value = strColumnArray
'wrkRange =
CType(wrkSheet.Range(strRange), Excel.Range)
'wrkRange.Value =
strColumnArray
'wrkRange.Font.Bold =
True
strRange = "A2:" &
EndColumn & (rowCount + 1).ToString
For xx = 0 To rowCount
- 1
For yy = 0 To
colCount - 1
strRowArray(xx, yy) = CType(vctl, DataGrid).Item(xx, yy).ToString
Next
Next
'wrkRange =
CType(wrkSheet.Range(strRange), Excel.Range)
'wrkRange.Value =
strRowArray
'NAR(wrkRange)
'NAR(wrkSheet)
strColumnArray =
Nothing
strRowArray = Nothing
strRange = Nothing
End If
End If
End If
End If
Next
End If
Next
If File.Exists(saveFileDialog1.FileName) Then
File.Delete(saveFileDialog1.FileName)
End If
wrkBook.SaveAs(saveFileDialog1.FileName)
MessageBox.Show(Text:="Exported Grids File Created
Successfully. " & _
"Please refer to file: " & vbCrLf & _
saveFileDialog1.FileName.ToString & vbCrLf & _
"to see created file.", caption:="Successful
Export", _
buttons:=MessageBoxButtons.OK,
Icon:=MessageBoxIcon.Information)
End If
Catch ex As Exception
MessageBox.Show(Text:="Failed to Export Data Grids. "
& vbCrLf & "Error: " & ex.Message.ToString, _
caption:="Failed Export.", _
buttons:=MessageBoxButtons.OK,
Icon:=MessageBoxIcon.Error)
Finally
'app.DisplayAlerts = False
NAR(wrkRange)
NAR(wrkSheet)
Call wrkBook.Close(SaveChanges:=False)
NAR(wrkBook)
Call wrkBooks.Close()
NAR(wrkBooks)
app.Quit()
NAR(app)
GC.Collect()
GC.WaitForPendingFinalizers()
Me.Close()
Me.Dispose()
End Try
Else
MessageBox.Show(Text:="No Grids selected for Export.", _
caption:="Failed Export", _
buttons:=MessageBoxButtons.OK,
Icon:=MessageBoxIcon.Error)
Me.Close()
Me.Dispose()
End If
End Sub
Private Sub NAR(ByRef o As Object)
If Not IsNothing(o) Then
Try
ReleaseComObject(o)
Catch
Finally
o = Nothing
End Try
End If
End Sub
datagrids on the passed in form are listed to the user and the user
can select which ones they want exported to Excel. Each grid is
exported to a different worksheet within the same workbook.
The Excel file is created successfully, but Excel remains open in Task
Manager until the application is closed entirely. To troubleshoot
this, I have commented out almost all the Excel references to range
objects and worksheet objects to isolate where the problem is
occurring. Basically, in the scaled down code, I have three lines of
test code that, when placed right after the declaration of the
Worksheet object, work fine and the Excel closes properly. When I
move these further down in the code into some nested if statements,
Excel does not close. In the code, I have the working version
uncommented out, and I also show the commented place where the same
three lines would cause this error. They are:
wrkSheet = wrkBook.Worksheets.Add()
wrkSheet.Name = "TEST"
wrkSheet.Range("A1").Value = "TEST"
Steps I've tried:
1.) As mentioned, I scaled everything down so there are no references
to any more Excel objects than there need to be. In the test version,
I no longer reference the range object. There shouldn't be any
implicit references to Excel objects in the version below.
2.) I've made sure all objects are first released using
ReleaseComObject and then set to nothing.
3.) I've confirmed that the objects are released and set to nothing in
proper order and I've checked the variable state after each release
and it appears to be working fine.
The twist is, the only thing different between a working version and a
version that fails to close Excel is the placement of some lines of
code.
Any help would be greatly appreciated. I apologize for the extraneous
code in the example below but it seemed silly to remove everything
just to give an example.
*****************************************************************************
Private Sub btnExport_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnExport.Click
' get the file name to save the list view information in from
the standard save dialog
Dim saveFileDialog1 As New SaveFileDialog
Dim xx As Integer = 0
Dim yy As Integer = 0
Dim rowCount As Integer = 0
Dim colCount As Integer = 0
Dim EndOfRows As Boolean = False
Dim NoRows As Boolean = False
Dim RowTest As String = ""
Dim vctl As Control
Dim vctl2 As Control
Dim app As New Excel.Application
Dim wrkBooks As Excel.Workbooks = app.Workbooks
Dim wrkBook As Excel.Workbook = wrkBooks.Add()
Dim wrkSheet As Excel.Worksheet
Dim wrkRange As Excel.Range
''test *****NOTE: When the next three lines of code are moved
to later
'' on in the module, Excel will not close. When left
here,
'' Excel closed fine. That is the only difference in
this
'' scaled down version of the code.
wrkSheet = wrkBook.Worksheets.Add()
wrkSheet.Name = "TEST"
wrkSheet.Range("A1").Value = "TEST"
''End Test **** NOTE
If chkBox1.Checked = True Or chkBox2.Checked = True Or
chkBox3.Checked = True _
Or chkBox4.Checked = True Or chkBox5.Checked = True Or
chkBox6.Checked = True _
Or chkBox7.Checked = True Or chkBox8.Checked = True Or
chkBox9.Checked = True Then
Try
saveFileDialog1.InitialDirectory = m_DefaultDirectory
saveFileDialog1.Filter = "Excel files (*.xls)|*.xls"
saveFileDialog1.FilterIndex = 1
saveFileDialog1.CheckFileExists = False
saveFileDialog1.CheckPathExists = True
saveFileDialog1.RestoreDirectory = True
saveFileDialog1.FileName = Date.Now.Year.ToString &
"-" & Date.Now.Month.ToString & "-" & Date.Now.Day.ToString _
& "_ExportGrids"
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
For Each vctl In m_Form.Controls
If TypeOf vctl Is DataGrid Then
For Each vctl2 In Me.Controls
If TypeOf vctl2 Is CheckBox Then
If CType(vctl2, CheckBox).Checked
= True Then
If CType(vctl2, CheckBox).Tag
= CType(vctl, DataGrid).Name Then
xx = 0
yy = 0
NoRows = False
EndOfRows = False
colCount =
CType(CType(vctl, DataGrid).DataSource, DataTable).Columns.Count()
rowCount =
CType(CType(vctl, DataGrid).DataSource, DataTable).Rows.Count
If rowCount = 0 Then
NoRows = True
End If
If Not NoRows Then
'****NOTE: If I uncomment these
' and Excel doesn't close
'wrkSheet =
wrkBook.Worksheets.Add()
'wrkSheet.Name = "TEST"
'wrkSheet.Range("A1").Value
= "TEST"
'****End NOTE
Dim
strColumnArray(colCount) As String
Dim
strRowArray(rowCount, colCount) As String
Dim strRange As String
Dim EndColumn As
String
'wrkSheet.Name =
FormatWrkSheetName(CType(vctl, DataGrid).CaptionText)
For yy = 0 To colCount
- 1
strColumnArray(yy)
= CType(CType(vctl, DataGrid).DataSource,
DataTable).Columns(yy).ColumnName.ToString
Next
Select Case colCount
Case Is > 26
EndColumn =
"A" & Chr((colCount - 26) + 64)
Case Is > 52
EndColumn =
"B" & Chr((colCount - 26) + 64)
Case Is > 78
EndColumn =
"C" & Chr((colCount - 26) + 64)
Case Is > 104
EndColumn =
"D" & Chr((colCount - 26) + 64)
Case Else
EndColumn =
Chr((colCount) + 64)
End Select
strRange = "A1:" &
EndColumn & "1"
'wrkSheet.Range(strRange).Value = strColumnArray
'wrkRange =
CType(wrkSheet.Range(strRange), Excel.Range)
'wrkRange.Value =
strColumnArray
'wrkRange.Font.Bold =
True
strRange = "A2:" &
EndColumn & (rowCount + 1).ToString
For xx = 0 To rowCount
- 1
For yy = 0 To
colCount - 1
strRowArray(xx, yy) = CType(vctl, DataGrid).Item(xx, yy).ToString
Next
Next
'wrkRange =
CType(wrkSheet.Range(strRange), Excel.Range)
'wrkRange.Value =
strRowArray
'NAR(wrkRange)
'NAR(wrkSheet)
strColumnArray =
Nothing
strRowArray = Nothing
strRange = Nothing
End If
End If
End If
End If
Next
End If
Next
If File.Exists(saveFileDialog1.FileName) Then
File.Delete(saveFileDialog1.FileName)
End If
wrkBook.SaveAs(saveFileDialog1.FileName)
MessageBox.Show(Text:="Exported Grids File Created
Successfully. " & _
"Please refer to file: " & vbCrLf & _
saveFileDialog1.FileName.ToString & vbCrLf & _
"to see created file.", caption:="Successful
Export", _
buttons:=MessageBoxButtons.OK,
Icon:=MessageBoxIcon.Information)
End If
Catch ex As Exception
MessageBox.Show(Text:="Failed to Export Data Grids. "
& vbCrLf & "Error: " & ex.Message.ToString, _
caption:="Failed Export.", _
buttons:=MessageBoxButtons.OK,
Icon:=MessageBoxIcon.Error)
Finally
'app.DisplayAlerts = False
NAR(wrkRange)
NAR(wrkSheet)
Call wrkBook.Close(SaveChanges:=False)
NAR(wrkBook)
Call wrkBooks.Close()
NAR(wrkBooks)
app.Quit()
NAR(app)
GC.Collect()
GC.WaitForPendingFinalizers()
Me.Close()
Me.Dispose()
End Try
Else
MessageBox.Show(Text:="No Grids selected for Export.", _
caption:="Failed Export", _
buttons:=MessageBoxButtons.OK,
Icon:=MessageBoxIcon.Error)
Me.Close()
Me.Dispose()
End If
End Sub
Private Sub NAR(ByRef o As Object)
If Not IsNothing(o) Then
Try
ReleaseComObject(o)
Catch
Finally
o = Nothing
End Try
End If
End Sub