現在VB.NETで開発をしています。
エクセルにスプレッドのデータを出力するときに、既存のファイルが開かれている状態で、既存のファイルに上書きしようとすると
HRESULT からの例外です : 0x800A03EC。というエラーになってしまいます。
上書きしようとしているファイルが開かれていることを知る方法はあるのか
教えていただけませんでしょうか?
現在のソースは
'------------------------------
' Excel保存
'------------------------------
If Len(PrmSaveFile) > 0 Then
SysExcel.DisplayAlerts = False
SysWorkBook.SaveAs(PrmSaveFile)★
End If
現状は★の処理の直後に落ちてしまう状態です。
他にメソッドがあるのか、もしくは事前にファイルが開かれていること
情報を取得してSaveAsを回避する必要があるのか、そのあたりを
教えていただくと大変助かります。
以上ですがよろしくお願いします。
訂正です。
上の書き込みでエラーが
HRESULT からの例外です : 0x800A03EC。
と書きましたが、
1004 'XXX.xls'にアクセスできません。
の間違いでした。
再度よろしくお願いいたします。
FileIOpermissionクラスでなんかできませんか?
ファイル入出力処理の際には、Try Catch のエラー処理を組み込みましょう。
もし、事前にファイルの状態を取得するメソッドがあったとしても、
その状態を取得してから、実際にそれを保存するまでのわずかな間に、
ファイルの状態が変化する可能性もあるわけですから。
返事がおそくなり大変申し訳ありませんでした。
魔界の仮面弁士様
現在はTryCatchではなくOnErrorで処理しているのですが、
それによってなにが違ってくるのか教えていただけませんでしょうか?
SaveAsしようとしているファイルが既に存在するかをチェックし、
一旦削除するかリネームしてみて、例外が発生すれば、「開いている」
と判断できるかと。
ただ、微妙なタイミングで、その判断後にファイルを開かれてしまうケースも
無いとは言い切れないので、
SaveAsでの例外をCatchしたほうが安全です。
Goto有害論とか構造化プログラミングとかという言葉を聞いたことはありますか?
On Error GoTo で処理すると、
処理の流れを無視してエラーハンドラへ飛ばされ、その中で処理して、
必要があればResumeとか、その場でExit...
ということになります。
その際、「どこの行でエラーになったか?」を知るのすら結構困難だったり、
OnErrorを書かなくて上位関数のハンドラに飛ばされて戻って来れなかったり
しますよね。
まあ、VB6.0以前もそうだったから、それでもいいのですが、
Try〜Catchであれば、処理の流れを壊さずにその場で、
実行〜エラー検知〜エラー種類による処理分岐〜上位へのエラー通知
が行えます。
一応、参考URLを。
http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard12.htm
http://www.atmarkit.co.jp/fdotnet/vb6tonet2/vbnet2_09/vbnet2_09_01.html
もげ様
教えていただいたURLを参考にTry〜Catchは大まかにですが
理解することができました。
また、今回の質問とは少しずれてしまいますが、、現在vb.netから
エクセルに出力するときに、新規でブックを開き、保存前にDELETE
して、ファイルが存在するか判断しています。
そこで、問題となるのが最初の質問の内容と重複しますが、既存のファイル
が開かれている時に、DELETEやSAVEを行うとエラーになるというところまでは
いいのですが、エクセル接続時にAddメソッドで新規にブックを作成している
ために、エラーで落ちても"Book1"といったように新規でファイルが作られて
しまいます。
どうしたいかといいますと、エラーで落ちたときにaddメソッドで作成したブックを
削除したいのですが、なにか方法はないでしょうか?
以下が現在のソースになります。
'------------------------------
' Excel接続
'------------------------------
SysExcel = CreateObject("Excel.Application")
'------------------------------
' Book接続
'------------------------------
If Len(PrmOpenFile) > 0 Then
SysWorkBook = SysExcel.Workbooks.Open(PrmOpenFile)
Else
SysWorkBook = SysExcel.Workbooks.Add
End If
SysWorkSheet = SysWorkBook.Worksheets(1)
'中略(出力処理)
If Len(PrmSaveFile) > 0 Then
If Dir$(PrmSaveFile).IndexOf(".xls") = -1 Then
PrmSaveFile = PrmSaveFile.Insert(PrmSaveFile.Length, ".xls")
End If
If System.IO.File.Exists(PrmSaveFile) Then
If MsgBox("ファイル'" & PrmSaveFile & "'は既に存在していま す。 上書きしてよろしいですか?", MsgBoxStyle.Question + MsgBoxStyle.OKCancel, "問合せ") = MsgBoxResult.OK Then
System.IO.File.Delete(PrmSaveFile)
SysWorkBook.SaveAs(PrmSaveFile)
End If
Else
SysWorkBook.SaveAs(PrmSaveFile)
End If
End If
説明不足がございましたら、ご指摘のほうよろしくお願いします。
>エラーで落ちたときに
というのが、例外としてCatchできるものであれば、
Try〜Catchを確実に実施して、例外をCatchしてください。
そうでないもの(Excelの強制終了?で貴殿のExeも道ずれ)を想定している
のであれば、新規ブックを作成したらそのままの名前(Book1)で使わずに、
直ちにリネームして、%TEMP%フォルダのような一時ファイル領域
に置いて作業を続行するような方法が考えられます。
(まあ、ディスクのクリーンアップ時まではファイルが残りますが...)
それから、
COMの開放を忘れずに実施しましょう。
Excelのプロセスが残ったり、その後の処理が不安定になりがちです。
http://hanatyan.sakura.ne.jp/dotnet/index.html のExcel関係トピック
http://jeanne.wankuma.com/tips/programing/releasecom.html
http://madia.world.coocan.jp/vb/vb_bbs2/200409_04090051.html
ツイート | ![]() |