- - PR -
ASP.NET(VB)でEXCELプロセスが消えない
1
投稿者 | 投稿内容 |
---|---|
|
投稿日時: 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 |
|
投稿日時: 2008-08-19 15:35
エラー: 変数 'rg' は参照カウントをデクリメントする前に、別の参照で上書きされています。
_________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 |
|
投稿日時: 2008-08-19 15:59
早速の返答ありがとうございます。
dim rg1 as Excel.Range rg1 = xlCells.Find(〜 のようにxlCells.Findの結果を別のExcelRangeオブジェクトに格納することによって プロセスが消えるようになりました。 的確なご指摘ありがとうございました。 次にサーバ上にあるEXCELテンプレートに値をマッピングしてクライアントにダウンロードする 機能を実装予定です。 なるべく自力でがんばりたいと思いますが、もしまた行き詰ったら宜しくお願いします。 |
|
投稿日時: 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