Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

サーバーサイドでExcelファイルを読み書きするWebアプリケーションを作る

ASP.NET MVCやMicrosoft Azure Functions上でExcel処理を記述しよう

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2017/05/26 14:00
目次

機能(2) データの一覧が出力されたExcelファイルを生成する

 次は、Excelファイルをダウンロードできる機能を実装します。このExcelファイルには、登録されているデータの一覧が記載されているものとします。Excelコンポーネントではゼロからファイルを作成することもできますが、ここでは、あらかじめ用意されたExcelファイルをテンプレートとして利用します。

手順

 下の図のようなExcelファイルを用意し、プロジェクトの「App_Data」フォルダ配下に「フィットネスtemplate.xlsx」として配置します。このExcelファイルの「H3」のセルには、「Name」という値で名前を定義します。後に、このセルに名前を書き込みます。Excelの名前定義については、「数式で名前を定義し使用する - Excel」を参照してください。

用意したExcelファイル。H3のセルに「Name」の値で名前定義を設定済み。7行目から値を書き込みます。
用意したExcelファイル。H3のセルに「Name」の値で名前定義を設定済み。7行目から値を書き込みます。
プロジェクトにExcelファイルを追加したときのソリューションエクスプローラー。
プロジェクトにExcelファイルを追加したときのソリューションエクスプローラー。

 「TrainingLogsController.cs」に、次のように「Download」メソッドを追記します。

/// <summary>
/// 一覧をExcelファイルとして取得します
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult> Download()
{
  string templateFilePath = @"~\App_Data\フィットネスtemplate.xlsx";
  var excelBook = new C1XLBook();
  excelBook.Load(Server.MapPath(templateFilePath));
  var sheet = excelBook.Sheets[0];

  var list = await db.TrainingLogs.OrderBy(log => log.Date).ToListAsync();

  //名前を出力する
  string name = list.FirstOrDefault()?.Name;
  foreach(XLNamedRange range in excelBook.NamedRanges)
  {
    //名前の定義がNameのみ後述の処理を行う
    if (range.Name != "Name") continue;
    //名前が定義されているセルの位置を特定します
    int colIndex = range.CellRange.ColumnFrom;
    int rowIndex = range.CellRange.RowFrom;
    //セルに名前を出力します
    sheet[rowIndex, colIndex].Value = name;
  }

  //セルのスタイルを参照する行インデックスを定義
  int styleRowIndex = 6;
  //データの1行目の各セルのスタイルを取得します。あとでこのスタイルをデータ行に適用します。
  //key: 列インデックス、value: XLStyleクラス
  Dictionary<int, XLStyle> styleDictionary = Enumerable.Range(1, 5)
  .ToDictionary(col => col, col => sheet[styleRowIndex, colIndex: col].Style);

  int dataRowIndex = 6;
  foreach (var log in list)
  {
//列インデックス1には、日付、列インデックス2には、体重…といったように各値を書き込みます
    sheet[dataRowIndex, colIndex: 1].SetValue(log.Date, styleDictionary[1]);
    sheet[dataRowIndex, colIndex: 2].SetValue(log.BodyWeight, styleDictionary[2]);
    sheet[dataRowIndex, colIndex: 3].SetValue(log.SquatCount, styleDictionary[3]);
    sheet[dataRowIndex, colIndex: 4].SetValue(log.PushupCount, styleDictionary[4]);
    sheet[dataRowIndex, colIndex: 5].SetValue(log.SitupCount, styleDictionary[5]);
    dataRowIndex += 1;
  }

  var stream = new MemoryStream();
  excelBook.Save(stream, FileFormat.OpenXml);
  stream.Position = 0;
  return File(stream, contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileDownloadName: "list.xlsx");
}

実行例

 ここで、デバッグ実行をし、URL「TrainingLogs/Download」にアクセスすると、Excelファイルがブラウザによってダウンロードされることを確認します。作成されたExcelファイルは次の図のようになります。

解説

 こちらも、Downloadメソッドの内容について説明します。まず、次のように、あらかじめ用意されたExcelファイルを読み込みます。

string templateFilePath = @"~\App_Data\フィットネスtemplate.xlsx";
var excelBook = new C1XLBook();
excelBook.Load(Server.MapPath(templateFilePath));

 次に、「Name」名前で定義されたセルを特定し、名前を書き込みます。行・列インデックスではなく名前の定義によりセルを特定することで、デザインの変更に柔軟に対応できます。

foreach(XLNamedRange range in excelBook.NamedRanges)
{
	//名前の定義がNameのみ後述の処理を行う
	if (range.Name != "Name") continue;
	//名前が定義されているセルの位置を特定します
	int colIndex = range.CellRange.ColumnFrom;
	int rowIndex = range.CellRange.RowFrom;
	//セルに名前を出力します
	sheet[rowIndex, colIndex].Value = name;
}

 データの行には、文字色や書式設定などのスタイルが設定されています。次の処理では、データの個数が可変であってもすべての行にスタイルを適用するために、データ1行目に設定されたスタイルを保存しておき、行を書き込むときに適用しています。SetValueメソッド(C1.C1Excel名前空間のXLCellクラス)で、セルに値を書き込むと同時にスタイルの設定を行います。

  //セルのスタイルを参照する行インデックスを定義
  int styleRowIndex = 6;
  //データの1行目の各セルのスタイルを取得します。あとでこのスタイルをデータ行に適用します。
  //key: 列インデックス、value: XLStyleクラス
  Dictionary<int, XLStyle> styleDictionary = Enumerable.Range(1, 5)
  .ToDictionary(col => col, col => sheet[styleRowIndex, colIndex: col].Style);

  int dataRowIndex = 6;
  foreach (var log in list)
  {
    //列インデックス1には、日付、列インデックス2には、体重…といったように各値を書き込みます
    sheet[dataRowIndex, colIndex: 1].SetValue(log.Date, styleDictionary[1]);
    sheet[dataRowIndex, colIndex: 2].SetValue(log.BodyWeight, styleDictionary[2]);
    sheet[dataRowIndex, colIndex: 3].SetValue(log.SquatCount, styleDictionary[3]);
    sheet[dataRowIndex, colIndex: 4].SetValue(log.PushupCount, styleDictionary[4]);
    sheet[dataRowIndex, colIndex: 5].SetValue(log.SitupCount, styleDictionary[5]);
    dataRowIndex += 1;
  }

 また、本筋から離れますが、「ComponentOne Studio for ASP.NET MVC」の他のコンポーネントを使用すると、次のような表やグラフの描画を行うことができます。


  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 矢後 比呂加(ヤゴ ヒロカ)

     Microsoft MVP for Visual Studio and Development Technologies(https://mvp.microsoft.com/ja-jp/PublicProfile/5000246)  シグマコンサルティング株式会社にて、Microsoft Azu...

バックナンバー

連載:ComponentZine(ComponentOne Studio)

もっと読む

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5