@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

ASP.NET(VB)でEXCELプロセスが消えない

1
投稿者投稿内容
egmain
会議室デビュー日: 2008/08/19
投稿数: 3
投稿日時: 2008-08-19 15:09
環境 VS2005(VB)
   EXCEL2000〜2003
   WindowsXP Pro

EXCELプロセスが消えない問題に関してはよく話題になっているのでいろいろ参考にして
コーディングしましたが、どうしても消えない現象に詰まってしまったので書き込ませてもらいました。
機能としては指定したEXCELファイルのシート上にある指定した文字を検索し、その値と行、列を配列に格納して返すと
いうものです。

http://jeanne.wankuma.com/tips/vb.net/programming/releasecom.html
このページを参考に下記コーディングを行いましたがプロセスが消えずに残ってしまいます。
xlCells.Findを使っているTryブロックをコメント化するとプロセスは消えるのでこのブロックに問題があると思うのですが、
原因が分かりません。どなたかご教授お願いします。

----------------------------------------------------
' 必要な変数は Try の外で宣言する
Dim xlApplication As Excel.Application
Dim blnchk As Boolean = False
Dim blnendchk As Boolean = False
Dim irow As Integer = 1
Dim icol As Integer = 1

' COM オブジェクトの解放を保証するために Try 〜 Finally を使用する
Try
xlApplication = New Excel.Application()

' 警告メッセージなどを表示しないようにする
xlApplication.DisplayAlerts = False

Dim xlBooks As Excel.Workbooks = xlApplication.Workbooks

Try
Dim xlBook As Excel.Workbook

Try
xlBook = xlBooks.Open(strFilePath)

Dim xlSheets As Excel.Sheets = xlBook.Worksheets

Try
For iCnt As Integer = 1 To xlSheets.Count

Do

Dim xlSheet As Excel.Worksheet = DirectCast(xlSheets(iCnt), Excel.Worksheet)

Try
If strSheetName = xlSheet.Name Then

Dim xlCells As Excel.Range = xlSheet.Cells

Try

Dim rg As Excel.Range = DirectCast(xlCells(irow, icol), Excel.Range)

Try
If blnchk = False Then
'シートを検索する
rg = xlCells.Find(strFieldName, , , XlLookAt.xlPart)
If rg Is Nothing Then
blnendchk = True
Else
ReDim strFindCell(0)
strFindCell(UBound(strFindCell)) = rg.Value & "," & rg.Row & "," & rg.Column
blnchk = True
irow = rg.Row
icol = rg.Column
End If

Else
'シートを次検索する
rg = xlCells.FindNext(rg)
If rg Is Nothing Then
blnendchk = True
Else
If strFindCell(0) = rg.Value & "," & rg.Row & "," & rg.Column Then
'検索が最初に戻ったら抜ける
blnendchk = True
Else
ReDim Preserve strFindCell(UBound(strFindCell) + 1)
strFindCell(UBound(strFindCell)) = rg.Value & "," & rg.Row & "," & rg.Column
irow = rg.Row
icol = rg.Column
End If

End If
End If

Finally
If Not rg Is Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(rg)
End If
End Try

Finally
If Not xlCells Is Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlCells)
End If

End Try
Else
Exit Do
End If

Finally
If Not xlSheet Is Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheet)
End If

End Try

If blnendchk = True Then
Exit Do
End If
Loop
Next

Finally
If Not xlSheets Is Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets)
End If

End Try
Finally
If Not xlBook Is Nothing Then
Try
xlBook.Close()
Finally
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook)
End Try

End If
End Try
Finally
If Not xlBooks Is Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)
End If
End Try
Finally
If Not xlApplication Is Nothing Then
Try
xlApplication.Quit()
Finally
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication)
End Try
End If
End Try
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2008-08-19 15:35
エラー: 変数 'rg' は参照カウントをデクリメントする前に、別の参照で上書きされています。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
egmain
会議室デビュー日: 2008/08/19
投稿数: 3
投稿日時: 2008-08-19 15:59
早速の返答ありがとうございます。
dim rg1 as Excel.Range
rg1 = xlCells.Find(〜
のようにxlCells.Findの結果を別のExcelRangeオブジェクトに格納することによって
プロセスが消えるようになりました。
的確なご指摘ありがとうございました。
次にサーバ上にあるEXCELテンプレートに値をマッピングしてクライアントにダウンロードする
機能を実装予定です。
なるべく自力でがんばりたいと思いますが、もしまた行き詰ったら宜しくお願いします。

egmain
会議室デビュー日: 2008/08/19
投稿数: 3
投稿日時: 2008-08-19 18:16
さきほどのEXCELテンプレートに値をマッピングしてクライアントにダウンロードする機能をコーディングしてみたのですがやはりプロセスが残ってしまいました。
大体の仕様としてはサーバ上に保存されているEXCELファイルをOPENしてテンプレート用のシートをコピーしてそのシートにデータをセットしていきます。単式とは1シートに1レコードのデータをセットし複数レコードの場合はシートコピーしてセットを繰り返します。複式とは指定したレコード分のデータをセットしたらシートコピーしてセットを繰り返すというものです。全てのデータをセットしたら元のテンプレートシートを削除し、Tempフォルダに保存し、クライアントにダンロードさせます。
非常に見にくいコードになってしまい申し訳ありませんが、ご教授願います。

-------------------------------------------
''' <summary>
''' EXCEL出力処理
''' </summary>
''' <param name="strFilePath">EXCELファイルパス</param>
''' <param name="strSheetName">EXCELシート名称</param>
''' <param name="strType">出力種別(単式or複式)</param>
''' <param name="ds">出力データセット</param>
''' <param name="strField">出力対象フィールド名称</param>
''' <param name="iRow">出力行</param>
''' <param name="iCol">出力列</param>
''' <param name="strTempFilePath">Tempファイルパス</param>
''' <param name="iMaxRow">複式の場合の最大出力行数</param>
''' <remarks></remarks>
Public Sub ExcelOut(ByVal strFilePath As String, ByVal strSheetName As String, ByVal strType As String, _
ByVal ds As DataSet, ByVal strField() As String, ByVal iRow() As Integer, ByVal iCol() As Integer, _
ByRef strTempFilePath As String, Optional ByVal iMaxRow As Integer = 0)

Dim iworkrow As Integer
Dim iSheetMaxCnt As Integer
Dim iSheetCnt As Integer
Dim strFileName As String

' 必要な変数は Try の外で宣言する
Dim xlApplication As Excel.Application

' COM オブジェクトの解放を保証するために Try 〜 Finally を使用する
Try
xlApplication = New Excel.Application()

' 警告メッセージなどを表示しないようにする
xlApplication.DisplayAlerts = False

Dim xlBooks As Excel.Workbooks = xlApplication.Workbooks

Try
Dim xlBook As Excel.Workbook

Try
xlBook = xlBooks.Open(strFilePath)

For iCount As Integer = 0 To ds.Tables(0).Rows.Count - 1

Dim xlSheets As Excel.Sheets = xlBook.Worksheets

Try

If iCount = 0 Then
'Excelブックの初期シート数を格納
iSheetMaxCnt = xlSheets.Count
End If

'シート原紙をコピーする。
If strType = "単式" Then
xlSheets(strSheetName).Copy(After:=xlSheets(iSheetMaxCnt + iCount))
ElseIf strType = "複式" And iCount = 0 Then
xlSheets(strSheetName).Copy(After:=xlSheets(iSheetMaxCnt + iSheetCnt))
ElseIf strType = "複式" And iMaxRow <> 0 AndAlso iworkrow = iMaxRow Then
'指定行数になるとシート原紙をコピーする。
iSheetCnt += 1
xlSheets(strSheetName).Copy(After:=xlSheets(iSheetMaxCnt + iSheetCnt))
End If

Dim xlSheet As Excel.Worksheet

Try

If strType = "単式" Then
xlSheet = xlSheets(iSheetMaxCnt + iCount + 1)
xlSheet.Name = CStr("Rev" & iCount + 1)
ElseIf strType = "複式" And iCount = 0 Then
xlSheet = xlSheets(iSheetMaxCnt + iSheetCnt + 1)
xlSheet.Name = CStr("Rev" & iSheetCnt + 1)
ElseIf strType = "複式" And iMaxRow <> 0 AndAlso iworkrow = iMaxRow Then
xlSheet = xlSheets(iSheetMaxCnt + iSheetCnt + 1)
xlSheet.Name = CStr("Rev" & iSheetCnt + 1)
iworkrow = 0
Else
xlSheet = xlSheets(xlSheets.Count)
End If

If strType = "単式" Then

For icount1 As Integer = 0 To ds.Tables(0).Columns.Count - 1

For icount2 As Integer = 0 To UBound(strField)
If ds.Tables(0).Columns(icount1).ColumnName = strField(icount2) Then

Dim xlCells1 As Excel.Range = xlSheet.Cells(iRow(icount2), iCol(icount2))

Try
'値をセット
xlCells1.Value = ds.Tables(0).Rows(iCount).Item(icount1).ToString

Finally
If Not xlCells1 Is Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlCells1)
End If

End Try

End If
Next
Next

ElseIf strType = "複式" Then

For icount1 As Integer = 0 To ds.Tables(0).Columns.Count - 1

For icount2 As Integer = 0 To UBound(strField)

If ds.Tables(0).Columns(icount1).ColumnName = strField(icount2) Then

Dim xlCells1 As Excel.Range = xlSheet.Cells(iRow(icount2) + iworkrow, iCol(icount2))

Try
'値をセット
xlCells1.Value = ds.Tables(0).Rows(iCount).Item(icount1).ToString

Finally
If Not xlCells1 Is Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlCells1)
End If

End Try

End If

Next icount2

Next icount1

iworkrow += 1

End If

Finally
If Not xlSheet Is Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheet)
End If

End Try

'最終レコードまで処理したらTempに保存する
If iCount = ds.Tables(0).Rows.Count - 1 Then
'印刷テンプレートシートを削除
For iCount3 As Integer = 1 To iSheetMaxCnt
xlSheets(1).Delete()
Next

'シート全選択状態で保存
xlSheets.Select(1)
xlSheets.Select()

'TEMPファイルにコピー
strFileName = Format(DateTime.Now, "yyyyMMddHHmmss") & "_Temp.xls"
strTempFilePath = HttpContext.Current.Server.MapPath("~\\Temp\\" & strFileName)
xlBook.SaveCopyAs(strTempFilePath)

'クライアントにダウンロード
HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=" & strFileName)
HttpContext.Current.Response.WriteFile(strTempFilePath)

End If

Finally
If Not xlSheets Is Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets)
End If

End Try

Next iCount

Finally
If Not xlBook Is Nothing Then
Try
xlBook.Close()
Finally
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook)
End Try

End If
End Try
Finally
If Not xlBooks Is Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)
End If
End Try
Finally
If Not xlApplication Is Nothing Then
Try
xlApplication.Quit()
Finally
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication)
End Try
End If
End Try

End Sub
1

スキルアップ/キャリアアップ(JOB@IT)