0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【.NET】簡易ExcelファイルをHTMLに変換して表示する

Last updated at Posted at 2022-02-20

はじめに

同僚がデータ修正ツールを作成する上で、修正前のデータと修正後のデータをExcelファイルに出力して表示していた。
社内で使用するだけなら、Office 365がインストールされているPCで行うのでいいのですが、実際に使用してもらうユーザーの環境には場所(工場内など)によってはOfficeがインストールされてないPCがあるため、レビューでExcelファイルをHTMLに変換して表示してもらえるように依頼した。

ExcelファイルからHTML変換

Excelの編集はEPPlusというExcel操作ライブラリーを使用している。
※EPPlus Ver 5系から商用利用は有償となっているため、Ver 4.5系(LGPL ライセンス)を使う。

EPPlusにはHTML変換する機能は備わっていないので、以前ExcelファイルからPDF変換に使用したSpireライブラリーを使用することにした。

Spire.Office

中国のE-iceblue社が提供するofficeの.NETコンポーネントのSpire.Office があり、印刷およびPDF出力やHTML出力をサポートしている。さらに機能制限がある無償版FreeSpire.Officeも提供している。

Spire.officeには、下記コンポーネントが含まれている。個別にダウンロードすることも出来る。

コンポーネント 内容 無償版制限
Spire.Doc Word ファイルの作成・読み・書き・変換・印刷・エクスポート Wordファイルの編集は、500段落と25テーブルに制限されています。 \ PDFファイルの変換は最初の3ページのみ。
Spire.DocViewer Word ファイルの表示・変換
Spire.XLS Excel ファイルの新規作成・編集・変換 Excelファイルの編集は、ブックごとに5シート、1シートあたり200行に制限されています。
Spire.Presentation PowerPont ファイルの新規作成・編集・変換 プレゼンテーションスライドが10枚に制限されています。
Spire.PDF PDFドキュメントの作成・読み・書き・編集 PDFファイルの編集は、10ページに制限されています。
Spire.PDFViewer PDFドキュメントをストリーム、ファイル、バイト配列から読み込み
Spire.DataExport Word/Excel/Access、html、PDF、DBF、SQLスクリプト、csv等の形式にデータをエクスポート
Spire.Barcode バーコードの生成

制限の確認

NuGetで「FreeSpire.XLS ver 12.2.0」をインストールする。
FreeSpire.XLSでは、Excelファイルの編集はブックごとに5シート、1シートあたり200行に制限されているのですが、Excelの編集自体はEPPlusを使用するので心配ない。問題はExcelファイルからHTML変換で1シートあたり200行に制限があるかを確認する。

ソースコード

EPPlusで300行のExcelファイルを作成して、FreeSpire.XLSでHTML変換する。

using OfficeOpenXml;
using OfficeOpenXml.Style;
using Spire.Xls;
using System.IO;
using ExcelHorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment;


const int START_ROW = 2;
const int COL_ID = 2;
const int COL_NAME = 3;
const int COL_BIRTHDAY = 4;

private void button1_Click(object sender, EventArgs e)
{
    string filePath = @"sample.xlsx";
    FileInfo excelFile = new FileInfo(filePath);
    if (excelFile.Exists)
    {
        excelFile.Delete();
        excelFile = new FileInfo(filePath);
    }

    using (var package = new ExcelPackage(excelFile))
    {
        ExcelWorksheet sheet = package.Workbook.Worksheets.Add("sheet");

        // ヘッダーにあたる行を作成
        CreateHeaderRow(sheet);

        // 300行のデータを作成
        Random rnd = new Random();
        foreach (var index in Enumerable.Range(1, 300))
            CreateRow(sheet, index, rnd);

        // 名前と誕生日の幅を広げる
        sheet.Column(COL_NAME).Width = 14;
        sheet.Column(COL_BIRTHDAY).Width = 16;

        //Excelのファイルをセーブする。
        package.Save();
    }

    // HTMLに変換
    SaveToHtml(filePath);

    MessageBox.Show("完了");
}

// ExcelからHTMLに変換する
private void SaveToHtml(string path)
{
    // Spire.XlsでExcelファイルを読み込む
    Workbook workbook = new Workbook();
    workbook.LoadFromFile(path);

    // ExcelからHTMLに変換
    Worksheet sheet = workbook.Worksheets[0];
    sheet.SaveToHtml("sample.html");
}

// ヘッダー行を作成する
private void CreateHeaderRow(ExcelWorksheet sheet)
{
    sheet.Cells[START_ROW, COL_ID].Value = "ID";
    sheet.Cells[START_ROW, COL_NAME].Value = "名前";
    sheet.Cells[START_ROW, COL_BIRTHDAY].Value = "誕生日";

    // ヘッダーセルにスタイルを適用する
    var headerCells = sheet.Cells[START_ROW, COL_ID, START_ROW, COL_BIRTHDAY];

    // 4方に罫線
    headerCells.Style.Border.Top.Style = ExcelBorderStyle.Thin;
    headerCells.Style.Border.Left.Style = ExcelBorderStyle.Thin;
    headerCells.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
    headerCells.Style.Border.Right.Style = ExcelBorderStyle.Thin;
    // 薄いグリーンの背景色で塗りつぶす
    headerCells.Style.Fill.PatternType = ExcelFillStyle.Solid;
    headerCells.Style.Fill.BackgroundColor.SetColor(Color.LightGreen);
    // テキストはセンタリング
    headerCells.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
    // 太字
    headerCells.Style.Font.Bold = true;
}

// index行目のデータを作る
private void CreateRow(ExcelWorksheet sheet, int index, Random rnd)
{
    int row = START_ROW + index;

    // id列を作る
    sheet.Cells[row, COL_ID].Value = index;
    // 名前も適当
    sheet.Cells[row, COL_NAME].Value = "鈴木 太郎" + index;
    // 誕生日も適当
    int year = DateTime.Now.AddYears(-rnd.Next(50)).Year;
    int month = rnd.Next(12) + 1;
    int day = rnd.Next(28) + 1;
    sheet.Cells[row, COL_BIRTHDAY].Value = new DateTime(year, month, day);
    // yyyy年mm月dd日形式で誕生日を表示
    sheet.Cells[row, COL_BIRTHDAY].Style.Numberformat.Format = "yyyy年mm月dd日";

    // 全ての列に4方に罫線のあるスタイルを作って適用する
    var cells = sheet.Cells[row, COL_ID, row, COL_BIRTHDAY];
    cells.Style.Border.Top.Style = ExcelBorderStyle.Thin;
    cells.Style.Border.Left.Style = ExcelBorderStyle.Thin;
    cells.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
    cells.Style.Border.Right.Style = ExcelBorderStyle.Thin;
}

出力結果

ExcelファイルからHTML変換で300行表示出来たので、200行の制限については問題なさそうだ。
image.png

下記サイトを参考に小計を計算するためにFormulaプロパティに式を使用したものをHTML変換すると例外エラーが発生したので、あくまで簡易なExcelファイルの変換で使用すると割り切った方がいいのかも。

【2022/02/21追記】
例外エラーは「System.NullReferenceException: 'オブジェクト参照がオブジェクト インスタンスに設定されていません。'」で、Formulaを設定しているところをコメントアウトすると例外エラーにならなくなる。
下記のSpire.XLSフォーラムを参考に変換時に数式を計算しないように「workbook.ConverterSetting.IsReCalculateOnConvert = false;」を追加したけど結果は変わらずれ例外エラーのまま。
Export to Pdf Value of =SUM Field is wrong - Forum / Spire.XLS

PDF変換「sheet.SaveToPdf("sample.pdf");」に切り替えるとFormulaを設定した状態でも例外エラーなく、小計も計算されてPDF変換される。

BoostrapのModalで別ページを表示する

BoostrapのModalにて、iframeを使用して別ページを表示する。

Test.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
    <style type="text/css">
      .modal-dialog-fluid {
         max-width: inherit;
         width: 98%;
         margin-left: 15px;
      }
    </style>
    <script type="text/javascript">
        window.addEventListener("load", () => {
            let elem = document.getElementById("content");
            let wh = window.innerHeight - 250;
            elem.style.height = wh + "px";
        }, false);
    </script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<button class="btn btn-primary" data-toggle="modal" data-target="#myModal">Trigger Modal in iFrame</button>
 
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-dialog-fluid" role="document">
        <div class="modal-content">
            <div class="modal-header bg-info text-white">
                <h4 class="modal-title" id="myModalLabel">動作デモ</h4>
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true" aria-label="Close">
                    <span aria-hidden="true">×</span>
                </button>
            </div>
            <div class="modal-body">
                <iframe src="sample.html" width="100%" id="content" frameborder="0" allowtransparency="true"></iframe>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">閉じる</button>
            </div>
        </div>
    </div>
</div>
</body>
</html>

表示結果

テストでは「Trigger Modal in iFrame」ボタンをクリックすると直ぐにModal画面で別ページを表示している。
実際にはクリックしたら抽出条件などをPostAJaxを用いて送信して、ASP.NETのサーバー上でExcelファイルの生成およびHTML変換が完了した段階でModal画面を表示する。
image.png
クリック後にModal画面で別ページのsample.htmlが表示される。
image.png

iFrameのソースを変更したい

Boostrapでモーダルを開く場合、Clickイベントの記述がなくてもクリックするとdata-toggledata-targetの属性指定によりモーダル表示されるようになっています。
iFrameのソースを条件よって変更したい場合、モーダルを開く前に処理を行う必要があります。Boostrapに則った方法を調べるとshow.bs.modalを使用する方法がありました。

下記の方法でモーダルが開く前にiFrameのソースを変更することが出来ます。
条件によってモーダルを開きたくない場合、return falseでキャンセルすることができます。

$(document).on('show.bs.modal','.modal', function () {
     // キャンセルしたい場合、return false;
     $("#myModal iframe").attr("src", "sample.html");
})

本当は「$('#myModal').on('show.bs.modal', function ()」のように記載したかったんですが、何故か動かなくて下記参照サイトのようにしたら動きました。
bootstrap jquery show.bs.modal event won't fire

最後に

これでOfficeがインストールされていないPCでも、見た目がExcelのような表示を実現できた。
Officeがインストールされている環境があれば、Excelファイルを開けるボタンを用意するなどすればいいでしょう。

式などあるならHTML変換よりPDF変換の方がいいかも知れない、PDFビューアーすらインストールされていない場合はPDF.jsを使用して表示させる。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?