Namazu-win32-users-ja(旧)


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

返信:Excel97アベンドの件



  池浦@福岡県水産海洋技術センター豊前海研究所です。


>(Excel95では開くファイルがExcel97ではアベンドする)があった場合、
>当該ファイルのみを無効にしたいのですが、実際には、それ以降
>のExcelファイルが全て無効になってしまいます。
>(ちなみに、Namazu側をExcel2000に置換しても同じでした)
>このような上位互換でないファイルが5千本中、数十本あると思われ、
>苦慮しております。何か良い方策はないでしょうか?
>
>[結果]
>1/8 - /E|/bk_1/try/Book1.xls [application/excel]
>2/8 - /E|/bk_1/try/Book2.xls ファイルが巨大なので無視します
>3/8 - /E|/bk_1/try/Book3.xls C:\namazu\var\namazu\index\NMZ.xls0.tmp
>                                           : No such file or directory
>       (この先、全て「No such file or directory」でエラー)
>

 当方ではWin2000+Excel2000を使用していますが、確かにExcel95等で作ったファイルの
中にはExcel2000で開こうとすると異常動作をするものがあります。

パターンとしては、
 1.ファイルを開けずにExcelが終了してしまう。
 2.ファイルは開けるが、保存や終了操作をするとDrWatsonが作動して強制終了される。

 このうち、1についてはまあ勝手にExcelが終了するので良いのですが、2については
OLEでExcelを起動して保存等の操作を行うとExcelのインスタンスが無応答状態になった
まま残ってしまうようです(DrWatsonは出てきてくれない)。

 竹迫さんのoleexcel.plはインデックスの作成を高速化するため、一度起動したExcelの
インスタンスを終了せずに繰り返し使用する仕様になっています。
 しかし一度Excelが異常になると、ブックへの変数($Book)はOpenメソッドの成否に関係なく
一時ファイル(NMZ.xls0.tmp)を指したままの状態になっているようです。
(一応変数$Bookは未定義状態ではないため、oleexcel.pl166行目のOpen失敗時のエラー処理が
効いていない)。

 更にこの状態(->ExcelがNMZ.xls0.tmpをロックしている)で一時ファイル(NMZ.xls0.tmp)を
作成orアクセスしようとするので"No such file or directory"のエラーが出ているのでは
ないかと思われます(はずれだったらごめんなさい)。


とりあえずの対応としては、

 1.Excelのインスタンスをファイルごとに毎回作成(当方はこうしています)
 2.一時ファイルのロックへの対応
 3.SaveAsメソッドに失敗した場合に、一時ファイルにアクセスさせない

といったところでしょうか。

 oleexcel.pl Ver3.06を書き換えることになります。当方と環境が違うのでうまくいくか
どうかわかりませんが、こんなものでどうでしょうか?(Perlがよく分かっていないので
めちゃくちゃなコードかもしれません)。

  --- oleexcel.pl ver3.06の変更 ---

130:	my $fseed=sprintf("%d",time);	<-追加、一時ファイル名を時刻で設定

132:	my $tmpfile0 = util::tmpnam('NMZ.xls0' . $fseed);    <-変更
133:	my $tmpfile1 = util::tmpnam('NMZ.xls1' . $fseed);    <- 〃
134:	my $tmpfile2 = util::tmpnam('NMZ.xls2' . $fseed);    <- 〃

144:	#eval {$excel = Win32::OLE->GetActiveObject('Excel.Application')};          <-コメントアウト
145:	#die "MSExcel not installed" if $@;                                         <-    〃
146:	#unless (defined $excel) {                                                  <-    〃
147:		$excel = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;});  <-行末にセミコロンを追加
148:	#		or die "Oops, cannot start Excel";                          <-コメントアウト
149:	#}                                                                          <-コメントアウト

196:		if ($ret) {    <-definedを削除:SaveAsメソッド失敗で$ret=0のケースがあるため
                                               (defined $ret)で保存失敗がトラップできない場合あり

226:	$excel->quit;           <-追加
227:	undef $excel;		<-元の226行のコメントを解除

 ただ、この方法だと異常なExcelのインスタンスは残ったままになります(一時ファイルも)。
これでごまかしながら問題のあるファイルを潰していくしかないのかな?
本当は異常なExcelのプロセスを殺すようなコードが書けるといいんですが、
どなたか書いてもらえないでしょうか?