ウェブアプリケーションのサーバーサイドで Excel ブックを作成する必要があり、もともと IIS (Internet Information Services) と Ruby が動作する環境があったこともあり、rubyXL を試してみることにしました。
ひとまず、次のようなプログラムを作成してみました。
require "rubyXL"
workbook = RubyXL::Workbook.new
puts "Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
puts "Content-Disposition: attachment; filename=\"filename.xlsx\""
puts
print workbook.stream.string
しかし、ブラウザーで開くとファイルはダウンロードされるものの、そのファイルは Excel で開くことができません。
いろいろ調べてみると、次のように標準出力をバイナリモードに変更する必要があるようです。
require "rubyXL"
workbook = RubyXL::Workbook.new
puts "Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
puts "Content-Disposition: attachment; filename=\"filename.xlsx\""
puts
+ STDOUT.binmode
+
print workbook.stream.string
無事、空白の Excel ブックがダウンロードされるようになりました。
これは、rubyXL や Ruby であることは直接関係なく、CGI のプログラムは標準出力にデータを出力しますが、Windows の IO にはテキストモードとバイナリモードがあり、IO のひとつである標準出力にもそれらのモードがある。そして、標準はテキストモードになっているので、そのままでバイナリデータである Excel ブック(というべきか、ZIP ファイルというべきか)を出力すると壊れてしまう、と理解しています。1
いまどき CGI はあまり使われない上に、Windows 特有ということもあってか、なかなか情報がなく、たかだか 1 行ですが解決に時間が掛かりました。
環境
- Windows Server 2022 Datacenter
- IIS 10.0
- RubyInstaller Ruby+Devkit 3.3.4-1 (x64)
参考
-
テキストモードとは改行コード (
\n
,\r\n
) を自動的に変換するモードのこと。IIS というよりは Windows の機能なので、確認はしていませんが IIS 以外のウェブサーバーでも、Windows 環境の場合は同じなのではないかと思います ↩