あきちゃんの飽き飽き備忘録

ほぼ死んでるブログ

Blazor ServerでExcelに電子印鑑(後編:Excel画像貼り付け)

初めまして、アキちゃんです。

備忘録をかねてブログを書くことにしました。

今回はBlazor ServerでExcelに電子印鑑(後編:Excel画像貼り付け)について書きます。

それでは早速・・・Blazor ServerでExcelに電子印鑑(後編:Excel画像貼り付け)!

Lesson.1 前回まで

前回までで印鑑っぽい画像のBitmapを返すControllerを作成しました。

*2022/12/26に誤りが確認でき、記事のLesson.4の修正を行いました。

akr9915.hatenablog.com

今回はHttpRequestMessageでBitmapを取得しExcelの任意のセルに張り付けるところまでしようと思います。

Lesson.2 NPOI

C#Excelを操作することのできるライブラリは結構たくさんあります。

画像やグラフの操作に関してはNPOIが一番簡潔だと思うので使わせてもらいましょう。

Nugetパッケージの管理からNPOIをインストールします。

Lesson.3 Excel画像貼り付け

前回までに、Stamp画像のStreamを取得できるControllerを作成しました。

なので今回はStreamを渡してExcelに張り付けるControllerを作ろうと思います。

Controllerフォルダに 追加→コントローラー→MVCコントローラー - 空 を選択し、SealStampController.csを作成します。

できたSealStampController.csをざっくり以下のように修正します。

SealController.cs(クリックで展開) SealController.cs(クリックで圧縮)
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
namespace ExcelStamp.Controllers
{
    public class SealStampController : Controller
    {
        private readonly IWebHostEnvironment environment;
        public SealStampController(IWebHostEnvironment environment)
        {
            this.environment = environment;
        }
        [HttpPost]
        [Route("api/sealstamp")]
        public async Task<IActionResult> SealStamp(IFormFile[] file)
        {
            var guid = Guid.NewGuid();
            try
            {
                var orgFileName = Path.Combine(environment.WebRootPath + @"\excel", "test.xlsx");
                var newFileName = Path.Combine(environment.WebRootPath + @"\delete", $"{guid}.xlsx"); ;
                System.IO.File.Copy(orgFileName, newFileName);
                using (var stampMs = new MemoryStream())
                {
                    await file[0].CopyToAsync(stampMs);
                    var stamp = stampMs.ToArray();
                    var anchor = new XSSFClientAnchor()
                    {
                        AnchorType = AnchorType.DontMoveAndResize,
                        Row1 = 0,
                        Row2 = 4,
                        Col1 = 0,
                        Col2 = 2,
                        Dx1 = XSSFShape.EMU_PER_PIXEL * 5,
                        Dx2 = XSSFShape.EMU_PER_PIXEL * -5,
                        Dy1 = XSSFShape.EMU_PER_PIXEL * 5,
                        Dy2 = XSSFShape.EMU_PER_PIXEL * -5,
                    };
                    SealStamp(newFileName, newFileName, "Sheet1", anchor, stamp);
                }
                return StatusCode(200);
            }
            catch (Exception ex)
            {
                return StatusCode(500, ex.Message);
            }
        }
        protected void SealStamp(string inpath, string outpath, string sheetName, XSSFClientAnchor anchor, byte[] data)
        {
            var book = WorkbookFactory.Create(inpath);
          var sheet = book.GetSheet(sheetName);
            var pictureidx = book.AddPicture(data, (PictureType)XSSFWorkbook.PICTURE_TYPE_PNG);
            var patriarch = sheet.CreateDrawingPatriarch();
            patriarch.CreatePicture(anchor, pictureidx);
         
            using (var fs = new FileStream(outpath, FileMode.OpenOrCreate))
            {
                book.Write(fs, true);
            }
          book.Close();
        }
    }
}

動作としてはwwwroot/excel/text.xlsxを発行したGUID.xlsxでwwwroot/delete/{GUID}.xlsxでコピーを取りそのファイルに画像を貼り付けてStatusCode(200)を返しています。

Excelのシートへの画像貼り付けはRow1,Row2,Col1,Col2で位置調整します。

Lesson.4 HttpRequestMessage

あとは、それぞれ作ったControllerを使用するためHttpRequestMessageを使う準備をします。

Program.csに以下コードを追記します。

builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddHttpClient();

var app = builder.Build();

社名・日付・名前・権限を入力できるようにIndex.razorを以下のように修正します。

Index.razor(クリックで展開) Index.razpr(クリックで圧縮)
@page "/"
@inject IHttpClientFactory ClientFactory
<PageTitle>Index</PageTitle>
<div class="form-group">
    <label>
        会社名:
        <input @bind="compInput" size="50" />
    </label>
</div>
<div class="form-group">
    <label>
        ユーザー名:
        <input @bind="userInput" size="50" />
    </label>
</div>
<div class="form-group">
    <label>
        日付文字列:
        <input @bind="datestrInput" size="50" />
    </label>
</div>
<div class="form-group">
    <label>
        権限文字列:
        <input @bind="powerInput" size="50" />
    </label>
</div>
<button @onclick="Send">作成</button>
@code {
    private string? compInput;
    private string? userInput;
    private string? datestrInput;
    private string? powerInput;
    private async Task Send()
    {
        byte[] stampBinary;
        {
            var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:7009" + "/api/stamp/getstamp/" + compInput + "/" + userInput + "/" + powerInput + "/" + datestrInput);
            var client = ClientFactory.CreateClient();
            var response = await client.SendAsync(request);
            stampBinary = await response.Content.ReadAsByteArrayAsync();
        }
        {
            var request = new HttpRequestMessage(HttpMethod.Post, "https://localhost:7009" + "/api/sealstamp");
            var content = new MultipartFormDataContent();
            content.Add(new ByteArrayContent(stampBinary), "file", "stamp.bin");
            var client = ClientFactory.CreateClient();
            {
                request.Content = content;
                await client.SendAsync(request);
            }
        }
    }
}

赤字のポート番号はお手前のプロジェクトに合わせてください。

ここまで来たら実行してみて以下のように入力して作成を押下します。

するとプロジェクトのwwwroot/deleteにExcelファイルができるのでこれをダブルクリックで開きます。

すると黒印鑑でA1~B4のセルに黒い印鑑画像が貼り付けられていたらここまで完了です。

また権限を1にすることで赤い印鑑画像が貼り付けられます。

Lesson.5 あとがき

前回記事ではソースがないのにミスコードを上げてしまい申し訳なかったです。: (_;´꒳`;) :_

以上・・・

github.com