10秒目をつむったら…

Windows2000
IE6.0
Perl5.005_03
Spreadsheet-WriteExcel-0.33
Parse-RecDescent-1.80

質問ですが、CGIとして実行すると「サーバーが見つかりません」
になってしまいます。エクセルファイルは正常に作成はできているようです。
use Spreadsheet::WriteExcel;をコメントにして実行すると移動したいURLに
飛ぶことができるのですが、当然ながらEXCELファイルは作成されません。
どのようにしたらよいのでしょうか・・・

print "Location: 移動したいURL\n\n";
print '<html><body>';
print '<br><br>';
print'<table align = "center">';
print'<tr>';
print'<td><font size = 5 ; color = blue>';
print"EXCEL書き出し";
print'</font></td>';
print'</tr>';
print'</table>';
print '</body></html>';

use Spreadsheet::WriteExcel;
my $workbook = Spreadsheet::WriteExcel->new("perl.xls");
$worksheet = $workbook->addworksheet();
$format = $workbook->addformat();
$format->set_bold();
$format->set_color('red');
$format->set_align('center');
$col = 0;
$row = 0;
$worksheet->write($row, $col, "Hi Excel!");
$worksheet->write(1, $col, "Hi Excel!", $format);
$worksheet->write(2, $col, 1.2345);
$worksheet->write(3, $col, '=SIN(PI()/4)');

print 'Content-type: text/html' ."\n\n";
print <<EOF;
<html><head><title>test</title></head><body>Ah!</body></head></html>

A 回答 (2件)

んー。

手元で確認した限りは、問題なく動作しますね。
問題点を考えると、Spreadsheet::WriteExcel から、何らかの原因でエラーが Location ヘッダが出力される前にダンプ (標準エラー出力で) されていているのかも知れません。

ちなみに、use は上に書こうが下に書こうが、コードの実行前に対象モジュールを先に実行してオブジェクトを作ります。なのでどんなに先に Location ヘッダを出していても、エラーのダンプはトラップできません。

まずは原因の解明の為に、プログラムの先頭部分に

use CGI::Carp 'fatalsToBrowser';

を書いてエラー時のプラグマを宣言し、エラーをトラップしてみてください。そうすれば、エラーメッセージが出ていたらトラップできます。

CGI::Carp を使うのが野暮ったければ、Location ヘッダを出した後に use するように、

use Spreadsheet::WriteExcel;

の部分を、

eval q/use Spreadsheet::WriteExcel;/;

とし、use させたいステップに意図的に遅延させた上で SpreadSheet::WriteExcel を実行させるってのも手です。

その場合は、全ての出力のバッファを避けるために
$| = 1;
を明示的に書いてください (エラー出力する前に Location を出力させるため)

ちなみに、Location でフォーカスが移った後、httpd から STDOUT が開放されないので、ずっと (処理が全部終わるまで) 読み込みになってしまうかもしれません。特に出力させる Excel ファイルが膨大なほどこの問題は発生します。fork() システムコールを実装している処理系であったら、fork() させた小プロセスで Excel ファイルを生成させ、親プロセスでは close STDOUT; すれば、ブラウザは開放されます。一般的に重い処理が続く場合にそういう方法を使います。その際に wait するのを忘れると小プロセスは zombie になってしまうので注意が必要ですが。

あと指摘すべきは、Spreadsheet::WriteExcel のバージョンが古いですね。最新は 0.39 なので、今起きている問題はもしかしたら「既知のバグ」として fix されているかもしれません。
Microsoft の nmake ユーティリティで最新版をソースからインストールされたほうがいいと思います。
(と書きながら今自分の手元の version が 0.37 だという事に気付き慌てて入れなおしました。。。)

参考URL:http://search.cpan.org/author/JMCNAMARA/Spreadsh …

この回答への補足

早速の回答有難うございます。
eval q/use Spreadsheet::WriteExcel;/; に変えて実行したらできました。
ところで、
print "Location: 移動したいURL\n\n";
print '<html><body>';
print '<br><br>';
print '<table align = "center">';
print '<tr>';
print '<td><font size = 5 ; color = blue>';
print "EXCEL書き出し";
print '</font></td>';
print '</tr>';
print '</table>';
print '</body></html>';
これの"Location: 移動したいURL\n\n"; 部分を
'<meta http-equiv="Refresh" content="0;移動したいURL>';
に変えて上記のHTMLを表示させたいのですが、何かよい方法ございませんでしょうか?

補足日時:2002/10/15 15:16
    • good
    • 0

解決したなら出来れば別質問にして欲しかったのですが (ボソボソ...



> ところで、
> print "Location: 移動したいURL\n\n";
> print '<html><body>';
> print '<br><br>';
> print '<table align = "center">';
> print '<tr>';
> print '<td><font size = 5 ; color = blue>';
> print "EXCEL書き出し";
> print '</font></td>';
> print '</tr>';
> print '</table>';
> print '</body></html>';
> これの"Location: 移動したいURL\n\n"; 部分を
> '<meta http-equiv="Refresh" content="0;移動したいURL>';
> に変えて上記のHTMLを表示させたいのですが、何かよい方法ございませんでしょうか?

要するに、現状であれば処理が完結する前に、Location で指定したページに行ってしまっていて、要求としては、Location で飛ばさないで、処理中は「EXCEL 書き出し」と画面に表示し、書き出しが終了し次第、別の URL を表示させたい…って事ですよね?
(違ってたり、完全に的外れならごめんなさい)

一般的には…

a. "EXCEL 書き出し" を表示し、Refresh ヘッダ (あるいは <meta http-equiv="Refresh" ... ) を出力するだけのページを出力する CGI ("リダイレクト CGI" とする)
b. Spreadsheet::WriteExcel を用いて Excel ドキュメントを生成し、生成が終わったらしかるべき HTML を表示する CGI ("Excel CGI" とする)

の二つを作ります。そして…

1. まずリダイレクト CGI で必要なデータを受け取ったり受け取らなかったりして、Refresh ヘッダで Excel CGI を呼び出します。この時、データを受け渡したいなら、QUERY_STRING や PATH_INFO あるいは、セッション ID を格納した Cookie 等を利用してデータをブラウザに渡します。
例えば

print 'Refresh: 0; url="excel.cgi?session_id=1234567890"'."\n\n";
print '<html><body>';

みたいにするとか。。。(ここで 1234567890 って名前のテンポラリファイルを出力して、Excel CGI で読み取るって方法が考えられます。リダイレクト後の URL 枠に QUERY_STRING が入るので、それを含めたくなければ Set-Cookie ヘッダを出して Cookie を Excel CGI が受け取るとか)

2. リダイレクト CGI から呼び出された Excel CGI では、データを受け取るなりの処理を行うことで、リダイレクト CGI を呼び出したデータを特定できるので、上記のいずれかの方法でデータを受け取り、処理を行います。

これで、1. からリダイレクトされた Excel CGI は、処理に時間がかかるために、「しかるべき HTML」を出力するまでの時間がかかります。これによって、ブラウザは「必要な応答が無いので、応答があるまで待つ」状態に入ります。その間は「EXCEL書き出し」とだけ、画面に表示されます。2. で Excel ファイルの生成が完了し次第、HTML が出力されるので、ブラウザは応答反応を受け取り、すぐさま「しかるべき HTML」を表示し始めます。

この方法で、「処理待ち」→「処理完了」のページ遷移が出来上がります。
    • good
    • 0
この回答へのお礼

有難うございました。
完璧に私のほしい回答でした!
本当に助かりました。
一度締め切らずに質問して大変申し訳ありませんでした。

お礼日時:2002/10/15 16:57

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!