再現環境
- SQL Server 2014
- Excel 2013
問題発生
客先の社内システムの画面の一部をSQL Server Reporting Service(以下SSRS)で作成したレポートの形で提供していたところ、「画面をExcelで保存するとエラーが出る」というクレームがありました。
そもそもExcelで保存って何だ?と再確認してみると、SSRSの標準機能としてExcelファイルへのエクスポート機能があることに気付きました(先に把握しておくべきだったかとは思いますが)。
色々試してみたところ、特定のデータで特定のレポートをエクスポートしたときだけExcelファイルが破損していました。
再現方法
レポートビルダーで新規レポートを作成し、適当なデータソース・データセットを作成し、下記のクエリを設定します。
SELECT 0.00000000000000 AS data
作成したデータセットのdataフィールドをD&Dでレポートに放り込んで、テキストボックスを作成します。
そしておもむろに実行。
レポートが表示されたら、エクスポート->Excelを選択し、ファイルを適当な場所に保存してExcelで開きます。
すると、「'~.xlsx'の一部の内容に問題が見つかりました」のダイアログが表示されます。
内容の回復は可能で、回復すると一応ファイルを開くことができます。
勿論、レポートサーバに配置した後でも同様の問題が発生します。
原因は?
Excelの数値有効桁数が15桁なので、それにまつわる問題かと思われます。
値が完全な0ではない場合は、指数表現に変換されるためかセーフとなります。
そうは言っても、そうそう15桁を超えることなんか無いような、とも思えるのですが、SQL Serverの場合はDECIMAL÷INTとかやってしまうといきなり桁数が膨れ上がる(参考:NUMERIC/DECIMAL の演算結果の有効桁数と小数点以下桁数)ので、あっさり突破されます。
回避方法
該当の式にFormatプロパティを設定して、小数桁数が14桁以下になるようにすればOK。
・・・かと思いきや、SSRSからExcel形式でエクスポートした場合、値は値、FormatはExcelの書式指定として別々にエクスポートされるので回避できません。
他に考えられる回避策は
- Valueプロパティ内でFormat式を使用して桁数を削る
- SQLの段階で適当な桁数のDECIMALにキャストする
- SQLでDECIMAL÷INT系の演算をしないように気をつける
といったところでしょうか。
いずれにせよ、一括処理はできないので調査・対応は非常に面倒です。
うぐぐぐぐ。