- 題名: vb.netで2つのエクセルファイルを処理する場合の挙動について(その2)
- 日時: 2012/09/13 17:32:37
- ID: 30927
- この記事の返信元:
- (なし)
- この記事への返信:
- [30929] Re[1]: vb.netで2つのエクセルファイルを処理する場合の挙動について(その2)2012/09/13 22:14:57
- ツリーを表示
■No30927に返信(やむさんの記事) > 同じような問題が再発しました。 同じコードを試してみましたが、当方では再現しませんでした。 使用したファイルは、 "あいうえお.xlsx" (tmpPath) → 新規ブックでSheet1に「あいうえお」と書いただけ。 "かきくけこ.xlsx" (shipGuide) → 新規ブックでSheet1に「かきくけこ」と書いただけ。 "さしすせそ.xlsx" (filePath/saveFile) → 存在しないファイル名。 という単純なものです。他のシート/他のブックへの参照や数式などは含まれていません。 ただし、上記ファイル群の保存先は マイ ドキュメント に変更しています。 これは権限周りの問題で、「読み込みはできるが保存はできない」とか、 あるいは「ファイルを生成できるが、既存ファイルの編集は出来ない」などの 別の問題が発生する可能性を除外しておくためです。 なお、実験環境は下記のとおり。 コードの実行前後で、Excel.exe が起動されていない事を確認しています。 Windows 7 Enterprise (64bit) Service Pack 1 Excel 2010 (32bit) バージョン 14.0.6123.5001 Visual Studio 2008 バージョン 9.0.30729.4462 QFE .NET Framework 3.5 Service Pack 1 + Office 14 PIA Debug 構成 x86 ビルド 追加で用意したフィールド変数は下記の通り。 いずれも、WithEvents や AddHandler は利用していません。 Private xlApp As Excel.Application Private xlBooks As Excel.Workbooks Private xlTmpBook As Excel.Workbook Private xlTmpSheets As Excel.Sheets Private xlTmpSheet As Excel.Worksheet Private xlBook As Excel.Workbook Private xlSheets As Excel.Sheets Private xlSheet As Excel.Worksheet > 同じような質問で恐縮ですが、問題点と解決法をアドバイス頂けると幸いです。 原因にはまったく思い当らないのですが、とりあえず、 気になる点を列挙してみます。 > OSがWindowsXP から Windows7 64bitに > Officeが2007 から 2010に変更になりました。 Office 2010 は、64bit 版をインストールしましたか? それとも、32bit 版の 2010 をインストールしましたか? それと一応念のために聞いておきますが、複数バージョンの Office を 共存インストールさせていたりはしますか? > 開発環境は以前のまま、VB2008です。 ビルドは AnyCPU でしょうか、x86 でしょうか。それとも x64? また、参照設定しているのは Excel 14 の PIA でしょうか? (Microsoft.Office.Interop.Excel.dll) > テンプレートファイルを解放すると テンプレートという事は、*.xls/*.xlsx ではなく、*.xlt/*.xltx ファイルでしょうか。 (動作上の差異は無いでしょうけれども) > 今回の問題もBookの保存時にエラーが出るというものです。 MRComObject を呼び出した時に、ReleaseComObject の戻り値が 0 になっているかを 確認してみてください。COM オブジェクトを引数に渡すメソッドを呼び出した場合、 参照カウントが増加してしまい、正しく解放されない場合があるためです。 恐らく、今回はすべて 0 が返されるであろうと予想しますが、万一、 1 以上が返されるオブジェクトが見つかった場合には、強制破棄のために MRComObject の force 引数に True を渡して呼び出す事ができます。 > Public Sub closeTmpExcel() > If IsNothing(xlTmpSheet) = False Then > MRComObject(xlTmpSheet) > End If > MRComObject(xlTmpSheets) xlTmpSheet は事前に Nothing 判定をかけているのに対し、 xlTmpSheets はその判定を行っていないのは何故でしょうか? そもそも、Nothing 判定は MRComObject 内でも実施されていますので、 一連の処理コードに対称性が無いように見えます。動きとしては問題ないですが。 > Message="'xxx.xlsx' にアクセスできません。" エラーメッセージ中のファイル名は、テンプレートファイル(tmpPath)の名前でしょうか。 shipGuide でしょうか、あるいは filePath(saveFile)のパスでしょうか。 また、xlBook の方を、Workbooks.Open → Workbook.SaveAs の流れでは無く、 Workbooks.Add → Workbook.SaveAs にした場合はどうでしょうか。
分類:[.NET]
2012/09/13(Thu) 17:33:13 編集(投稿者)
先日No30892を投稿したものです。
No30892の問題は、魔界の仮面弁士さんのアドバイスにより解決したのですが、
今週に入って社内端末の総入れ替えがありまして、同じような問題が再発しました。
OSがWindowsXP から Windows7 64bitに
Officeが2007 から 2010に変更になりました。
開発環境は以前のまま、VB2008です。
今回の問題もBookの保存時にエラーが出るというものです。
テンプレートファイルを解放すると、処理を行う方のBookを保存する際にエラーとなります。
同じような質問で恐縮ですが、問題点と解決法をアドバイス頂けると幸いです。
以下ソースと問題箇所
Public Sub openExcel(ByVal tmpPath As String, ByVal filePath As String, ByVal sheetName As String)
'テンプレートファイルのオープン
xlApp = New Excel.Application
xlApp.Visible = False
xlApp.DisplayAlerts = False
xlBooks = xlApp.Workbooks
xlTmpBook = xlBooks.Open(tmpPath)
xlTmpSheets = xlTmpBook.Worksheets
xlTmpSheet = DirectCast(xlTmpSheets.Item(1), Excel.Worksheet)
Dim shipGuide As String = IO.Path.Combine(My.Application.Info.DirectoryPath, FILE_NAME)
xlBook = xlBooks.Open(shipGuide)
xlSheets = xlBook.Worksheets
xlSheet = DirectCast(xlSheets.Item(1), Excel.Worksheet)
'テンプレートのシートをコピー
xlTmpSheet.Copy(After:=xlSheet)
'既に存在するSheet1を削除
xlSheet.Delete()
MRComObject(xlSheet)
'コピーしたシートの名称変更
xlSheet = DirectCast(xlSheets.Item(1), Excel.Worksheet)
xlSheet.Name = sheetName
xlBook.SaveAs(filePath) '※1この保存は問題なし。※2でエラーとなるので一旦保存ができるか確認用
closeTmpExcel()
closeExcel(filePath)
End Sub
Public Sub closeTmpExcel()
If IsNothing(xlTmpSheet) = False Then
MRComObject(xlTmpSheet)
End If
MRComObject(xlTmpSheets)
xlTmpBook.Close()
MRComObject(xlTmpBook)
End Sub
Public Sub closeExcel(ByVal saveFile As String)
Try
xlBook.SaveAs(saveFile) ※2この部分でエラー。エラーメッセージは後述
Catch ex As Exception
MsgBox(ex.Message)
End Try
MRComObject(xlSheet)
MRComObject(xlSheets)
xlBook.Close()
MRComObject(xlBook)
xlBooks.Close()
MRComObject(xlBooks)
xlApp.Visible = True
xlApp.DisplayAlerts = True
xlApp.Quit()
MRComObject(xlApp)
End Sub
Private Shared Sub MRComObject(Of T As Class)(ByRef objCom As T, Optional ByVal force As Boolean = False)
If objCom Is Nothing Then
Return
End If
Try
If System.Runtime.InteropServices.Marshal.IsComObject(objCom) Then
If force Then
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objCom)
Else
System.Runtime.InteropServices.Marshal.ReleaseComObject(objCom)
End If
End If
Finally
objCom = Nothing
End Try
End Sub
※エラーメッセージ
System.Runtime.InteropServices.COMException がキャッチされました
ErrorCode=-2146827284
HelpLink="xlmain11.chm"
Message="'xxx.xlsx' にアクセスできません。"
Source="Microsoft Excel"