SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

ComponentZine(ComponentOne)(AD)

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

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

  • X ポスト
  • このエントリーをはてなブックマークに追加

機能(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」の他のコンポーネントを使用すると、次のような表やグラフの描画を行うことができます。

次のページ
Azure FunctionsでExcelファイルを読み書きする

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
ComponentZine(ComponentOne)連載記事一覧

もっと読む

この記事の著者

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

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

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/10168 2017/05/26 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング