4
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.

DioDocs for Excel のテンプレート機能が少し不満があったので自作した

Last updated at Posted at 2021-09-07

概要

・Visual Stadio 2019 Blazor Server で DioDocs for Excel を使用してみたが
 DioDocsのテンプレート機能が少し使いにくかったので、オリジナルで作成してみた。
 ※明細の表が複数でも出力可能になる。

手順

1.Visual Stadio 2019 で新しいプロジェクトで Blazor Server を選択し
 「DioDocs2」と言う名称でプロジェクトを作成する。

2.プロジェクトの追加で、コンソールアプリケーションを選択し、「Reports」という名称
 で追加する。

3.プロジェクトのプロパティ設定で、出力の種類を「クラスライブラリ」に変更する。

4.以下のファイルを追加

DioDocsReports.cs
using System.Collections.Generic;
using GrapeCity.Documents.Excel;
using Reports.Model;

namespace Reports
{
    /// <summary>
    /// DioDocs帳票作成クラス
    /// </summary>
    public static class DioDocsReports
    {
        /// <summary>ワークブック</summary>
        private static Workbook _Workbook;

        /// <summary>ヘッダー定義記号(左)長さ</summary>
        private static int _HederKigoLeftLen = 4;

        /// <summary>明細定義記号(左)長さ</summary>
        private static int _DetailKigoLeftLen = 3;

        /// <summary>
        /// テンプレートOPEN
        /// </summary>
        /// <param name="fileName">ファイル名</param>
        /// <returns>ワークブック</returns>
        public static Workbook OpenTemplate(string fileName)
        {
            _Workbook = new Workbook();
            _Workbook.Open(fileName, OpenFileFormat.Xlsx);
            return _Workbook;
        }

        /// <summary>
        /// シート削除
        /// </summary>
        /// <param name="fileName">ファイル名</param>
        public static void DeleteSheet(string sheetName)
        {
            _Workbook.Worksheets[sheetName].Delete();
        }

        /// <summary>
        /// PDF出力(シート)
        /// </summary>
        /// <param name="fileName">ファイル名</param>
        public static void OutputPdfSheet(string fileName)
        {
            _Workbook.ActiveSheet.Save(fileName);
        }

        /// <summary>
        /// PDF出力(ブック)
        /// </summary>
        /// <param name="fileName">ファイル名</param>
        /// <returns>ステータス</returns>
        public static void OutputPdf(string fileName)
        {
            _Workbook.ActiveSheet.Save(fileName);
        }

        /// <summary>
        /// Excel Save
        /// </summary>
        /// <param name="fileName">ファイル名</param>
        public static void Save(string fileName)
        {
            _Workbook.Save(fileName);
        }

        /// <summary>
        /// マージン設定
        /// </summary>
        /// <param name="top">上</param>
        /// <param name="bottom">下</param>
        /// <param name="left">左</param>
        /// <param name="right">右</param>
        public static void SetMargin(double top, double bottom, double left, double right)
        {
            var sheet = _Workbook.ActiveSheet;
            sheet.PageSetup.TopMargin = top;
            sheet.PageSetup.BottomMargin = bottom;
            sheet.PageSetup.LeftMargin = left;
            sheet.PageSetup.RightMargin = right;
        }

        /// <summary>
        /// ヘッダーエリア設定
        /// </summary>
        /// <param name="row1">行1</param>
        /// <param name="col1">列1</param>
        /// <param name="rowcnt">行数</param>
        /// <param name="colcnt">列数</param>
        public static List<AreaModel> SetHeaderArea(int row1, int col1, int rowcnt, int colcnt)
        {
            List<AreaModel> areaList = new List<AreaModel>();
            var range = _Workbook.ActiveSheet.Range[row1, col1, rowcnt, colcnt];

            for (int r = 0; r < range.RowCount; r++)
            {
                for (int c = 0; c < range.ColumnCount; c++)
                {
                    var tmp = range[0 + r, c].Value == null ? null : range[0 + r, c].Value.ToString();
                    if (!string.IsNullOrEmpty(tmp))
                    {
                        if ((tmp.Length > 5) && (tmp.Substring(0, _HederKigoLeftLen) == "{***") && tmp.Substring(tmp.Length - 1, 1) == "}")
                        {
                            var addData = new AreaModel()
                            {
                                AreaName = tmp.Substring(_HederKigoLeftLen, tmp.Length - _HederKigoLeftLen).Replace("}", ""),
                                Row = row1 + r,
                                Col = col1 + c
                            };
                            areaList.Add(addData);
                            range[0 + r, c].Value = "";
                        }
                    }
                }
            }
            return areaList;
        }

        /// <summary>
        /// 明細エリア設定
        /// </summary>
        /// <param name="row1">行1</param>
        /// <param name="col1">列1</param>
        /// <param name="rowcnt">行数</param>
        /// <param name="colcnt">列数</param>
        public static List<AreaModel> SetDetailArea(int row1, int col1, int rowcnt, int colcnt)
        {
            List<AreaModel> areaList = new List<AreaModel>();
            var range = _Workbook.ActiveSheet.Range[row1, col1, rowcnt, colcnt];
            for (int r = 0; r < range.RowCount; r++)
            {
                for (int c = 0; c < range.ColumnCount; c++)
                {
                    var tmp = range[r, c].Value == null ? null : range[r, c].Value.ToString();
                    if (!string.IsNullOrEmpty(tmp))
                    {
                        if ((tmp.Length > (_DetailKigoLeftLen + 1)) && (tmp.Substring(0, _DetailKigoLeftLen) == "{**") && (tmp.Substring(tmp.Length - 1, 1) == "}"))
                        {
                            if ((tmp.Substring((_DetailKigoLeftLen + 1), 1) != "*"))
                            {
                                var addData = new AreaModel()
                                {
                                    AreaName = tmp.Substring(_DetailKigoLeftLen, tmp.Length - _DetailKigoLeftLen).Replace("}", ""),
                                    Row = row1 + r,
                                    Col = col1 + c
                                };
                                areaList.Add(addData);
                                range[0 + r, c].Value = "";
                            }
                        }
                    }
                }
            }
            return areaList;
        }

        /// <summary>
        /// ヘッダーデータ設定
        /// </summary>
        /// <typeparam name="T">テーブル</typeparam>
        /// <param name="list">データリスト</param>
        /// <param name="areaList">エリアリスト</param>
        public static void SetHedar<T>(List<T> list, List<AreaModel> areaList)
        {
            foreach (var a in list)
            {
                foreach (var property in a.GetType().GetProperties())
                {
                    foreach (var dat in areaList)
                    {
                        if (dat.AreaName == property.Name)
                        {
                            _Workbook.ActiveSheet.Cells[dat.Row, dat.Col].Value = a.GetType().GetProperty(property.Name).GetValue(a);
                        }
                    }
                }
                break;
            }
        }

        /// <summary>
        /// 明細データ設定
        /// </summary>
        /// <typeparam name="T">テーブル</typeparam>
        /// <param name="list">データリスト</param>
        /// <param name="areaList">エリアリスト</param>
        public static void SetDetail<T>(IEnumerable<T> list, List<AreaModel> areaList)
        {
            foreach (var a in list)
            {
                foreach (var property in a.GetType().GetProperties())
                {
                    foreach (var dat in areaList)
                    {
                        if (dat.AreaName == property.Name)
                        {
                            _Workbook.ActiveSheet.Cells[dat.Row++, dat.Col].Value = a.GetType().GetProperty(property.Name).GetValue(a);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Cellデータ設定
        /// </summary>
        /// <typeparam name="data">値</typeparam>
        /// <param name="list">データリスト</param>
        /// <param name="areaList">エリアリスト</param>
        public static void SetCell(object obj, int row, int col)
        {
            _Workbook.ActiveSheet.Cells[row, col].Value = obj;
        }

        /// <summary>
        /// コピーテンプレート(シート)
        /// </summary>
        public static void CopyTemplete()
        {
            // テンプレートのシートをアクティブ
            _Workbook.Worksheets["temp"].Activate();

            // テンプレートのシートをコピー
            var copy_worksheet = _Workbook.ActiveSheet.Copy();

            // コピーしたシートに名前を設定
            copy_worksheet.Name = _Workbook.Worksheets.Count.ToString();

            // コピーしたシートをアクティブ
            copy_worksheet.Activate();
        }

        /// <summary>
        /// ページコピー
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="page"></param>
        public static void PageCopy(int row, int col, int page)
        {
            for (int c = 1; c < page; c++)
            {
                _Workbook.ActiveSheet.Range[0, 0, row - 1, col - 1].Copy(_Workbook.ActiveSheet.Range[c * row, 0, row - 1, col - 1]);
                _Workbook.ActiveSheet.HPageBreaks.Add(_Workbook.ActiveSheet.Range[c * row, 0]);
            }
        }

        /// <summary>
        /// 明細行コピー
        /// </summary>
        /// <param name="list"></param>
        /// <param name="areaList"></param>
        public static void SetDetailCopy(int lineNo, int gyoCnt)
        {
            for (int c = 1; c < gyoCnt; c++)
            {
                _Workbook.ActiveSheet.Range[lineNo, 0, 1, 999].Insert(InsertShiftDirection.Down);
                _Workbook.ActiveSheet.Range[lineNo, 0, 1, 999].Copy(_Workbook.ActiveSheet.Range[lineNo + 1, 0, 1, 999]);
            }
        }
    }
}
CreateReports.cs
using System.Collections.Generic;
using GrapeCity.Documents.Excel;

namespace Reports
{
    public class CreateReports
    {
        private Workbook _Workbook;


        public void PdfOutput()
        {
            List<HeaderModel> hederList = new List<HeaderModel>();
            List<UserModel> DataList = new List<UserModel>();

            var dat0 = new HeaderModel()
            {
                 Shozoku = "0001:大阪府"
            };
            hederList.Add(dat0);
            var dat1 = new UserModel()
            {
                Id = "0001",
                Name = "テスト01",
                Gender = "M",
                Age = 20,
            };
            DataList.Add(dat1);
            var dat2 = new UserModel()
            {
                Id = "0002",
                Name = "テスト02",
                Gender = "F",
                Age = 21,
            };
            DataList.Add(dat2);

            for(var c = 3; c < 60; c++)
            {
                var dat3 = new UserModel()
                {
                    Id = c.ToString("0000"),
                    Name = "テスト" + c.ToString(),
                    Gender = "M",
                    Age = c + 21,
                };
                DataList.Add(dat3);
            }

            // テンプレートOPEN
            var _Workbook = DioDocsReports.OpenTemplate(@"C:\Test\DioDocs2\DioDocs2\Template\ユーザー一覧表.xlsx");

            // テンプレートシートをコピー
            DioDocsReports.CopyTemplete();

            // ヘッダー領域を設定
            var listHeader = DioDocsReports.SetHeaderArea(0, 0, 5, 8);
            // 明細領域を設定
            var listDetail = DioDocsReports.SetDetailArea(6, 0, 1, 8);
            // データ件数に合わせて明細行をコピー
            DioDocsReports.SetDetailCopy(6, DataList.Count);
            // ヘッダー領域にデータを設定
            DioDocsReports.SetHedar<HeaderModel>(hederList, listHeader);
            // 明細領域にデータを設定
            DioDocsReports.SetDetail<UserModel>(DataList, listDetail);
            // テンプレートのシートを削除
            DioDocsReports.DeleteSheet("temp");
            // PDF出力
            DioDocsReports.OutputPdf(@"C:\Test\DioDocs2\DioDocs2\wwwroot\DownLoad\ユーザー一覧表.pdf");
            DioDocsReports.Save(@"C:\Output\ユーザー一覧表.xlsx");
        }
    }
    /// <summary>
    /// 詳細モデル
    /// </summary>
    public class UserModel
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public int Age { get; set; }
    }
    /// <summary>
    /// ヘッダーモデル
    /// </summary>
    public class HeaderModel
    {
           public string Shozoku { get; set; }
    }
}

5.NavMenu.razor を以下のように修正

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="fetchdata">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
            </NavLink>
        </li>
        /// -->追加
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="PdfOutput">
                <span class="oi oi-print" aria-hidden="true"></span>PdfOutput
            </NavLink>
        </li>
        /// <--追加
    </ul>
</div>

6.Page フォルダに以下のファイルを追加

PdfOutput.razor
@page "/PdfOutput"
@using Reports
@inject IJSRuntime jsRuntime

<h3>PdfOutput</h3>

<button class="btn btn-primary" @onclick="CreatePdf">Pdf</button>
PdfOutput.razor.cs

using System;
using System.Threading.Tasks;
using System.Text.Json;
using System.Security.Cryptography;
using Microsoft.JSInterop;
using Microsoft.AspNetCore.Components;
using Reports;

namespace DioDocs2.Pages
{
    public partial class PdfOutput
    {

        public async Task CreatePdf()
        {
            try
            {

                var rep = new CreateReports();
                rep.PdfOutput();
                rep = null;
                await Task.Delay(10);
                await jsRuntime.InvokeVoidAsync("DownLoad", @"ユーザー一覧表.pdf");
            }
            catch (Exception ex){

                var a = ex.Message;
            }
        }
    }
}

7.テンプレートファイル用のフォルダを追加 ...DioDocs2\Template

8.PDF出力用のフォルダを追加 ...DioDocs2\DioDocs2\wwwroot\DownLoad\

9.テンプレートファイルの追加 ユーザー一覧表.xlsx
no000.jpg

10._Host.cshtml を以下のように修正

@page "/"
@namespace DioDocs2.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
    Layout = null;
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>DioDocs2</title>
    <base href="~/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />
    <link href="DioDocs2.styles.css" rel="stylesheet" />
</head>
<body>
    <component type="typeof(App)" render-mode="ServerPrerendered" />

    <div id="blazor-error-ui">
        <environment include="Staging,Production">
            An error has occurred. This application may no longer respond until reloaded.
        </environment>
        <environment include="Development">
            An unhandled exception has occurred. See browser dev tools for details.
        </environment>
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>

    <script src="_framework/blazor.server.js"></script>
</body>
</html>

<script>
    // ファイルダウンロード
    function DownLoad(fileName) {
        const link = document.createElement('a');
        link.setAttribute("type", "hidden");
        link.href = './DownLoad/' + fileName;
        link.target = '_blank';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        link.remove();
    }
</script>

11.実行結果
no002.jpg

no003.jpg

no005.jpg

4
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
4
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?