0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C#でMicrosoft RDLC reportを非同期で直接印刷する

Posted at

1. はじめに

  • C#でMicrosoft RDLC reportをプレビューなしに直接印刷したい
  • 印刷処理に時間がかかることを想定して、非同期で印刷したい

2. 開発環境

  • C#
  • .NET 6
  • Visual Studio 2022
  • Microsoft RDLC Report Desinger 2022
  • ReportViewerCore.WinForms (NuGet)

3. 事前準備

4. LocalReportExtensionsクラスの作成

  • 参考文献のソースコードをそのまま活用させてもらった
LocalReportExtensions.cs
using Microsoft.Reporting.WinForms;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.IO;

public static class LocalReportExtensions
{
    public static void Print(this LocalReport report, string printerName)
    {
        var pageSettings = new PageSettings();
        pageSettings.PaperSize = report.GetDefaultPageSettings().PaperSize;
        pageSettings.Landscape = report.GetDefaultPageSettings().IsLandscape;
        pageSettings.Margins = report.GetDefaultPageSettings().Margins;
        Print(report, pageSettings, printerName);
    }

    public static void Print(this LocalReport report, PageSettings pageSettings, string printerName)
    {
        string deviceInfo =
            $@"<DeviceInfo>
                <OutputFormat>EMF</OutputFormat>
                <PageWidth>{pageSettings.PaperSize.Width * 100}in</PageWidth>
                <PageHeight>{pageSettings.PaperSize.Height * 100}in</PageHeight>
                <MarginTop>{pageSettings.Margins.Top * 100}in</MarginTop>
                <MarginLeft>{pageSettings.Margins.Left * 100}in</MarginLeft>
                <MarginRight>{pageSettings.Margins.Right * 100}in</MarginRight>
                <MarginBottom>{pageSettings.Margins.Bottom * 100}in</MarginBottom>
            </DeviceInfo>";

        Warning[] warnings;
        var streams = new List<Stream>();
        var currentPageIndex = 0;

        report.Render("Image", deviceInfo,
            (name, fileNameExtension, encoding, mimeType, willSeek) =>
            {
                var stream = new MemoryStream();
                streams.Add(stream);
                return stream;
            }, out warnings);

        foreach (Stream stream in streams)
            stream.Position = 0;

        if (streams == null || streams.Count == 0)
            throw new Exception("Error: no stream to print.");

        var printDocument = new PrintDocument();
        printDocument.DefaultPageSettings = pageSettings;
        if (!printDocument.PrinterSettings.IsValid)
            throw new Exception("Error: cannot find the default printer.");
        else
        {
            printDocument.PrintPage += (sender, e) =>
            {
                Metafile pageImage = new Metafile(streams[currentPageIndex]);
                Rectangle adjustedRect = new Rectangle(
                    e.PageBounds.Left - (int)e.PageSettings.HardMarginX,
                    e.PageBounds.Top - (int)e.PageSettings.HardMarginY,
                    e.PageBounds.Width,
                    e.PageBounds.Height);
                e.Graphics.FillRectangle(Brushes.White, adjustedRect);
                e.Graphics.DrawImage(pageImage, adjustedRect);
                currentPageIndex++;
                e.HasMorePages = (currentPageIndex < streams.Count);
                e.Graphics.DrawRectangle(Pens.Red, adjustedRect);
            };
            printDocument.EndPrint += (Sender, e) =>
            {
                if (streams != null)
                {
                    foreach (Stream stream in streams)
                        stream.Close();
                    streams = null;
                }
            };
            printDocument.PrinterSettings.PrinterName = printerName;
            printDocument.Print();
        }
    }
}

5. WinFormクライアントの作成

Form1.cs
using Microsoft.Reporting.WinForms;
using System.Diagnostics;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        private async void ButtonStart_Click(object sender, EventArgs e)
        {
            // 非同期で印刷処理を実行する
            await ReportPrintAsync();
        }

        private async Task ReportPrintAsync()
        {

            Debug.Print("非同期処理開始");

            // 確認用にSleepする
            await Task.Delay(10000);

            // ReportViewerコントロールを追加する
            this.Controls.Add(this.reportViewer1);

            // ReportViewerコントロールを非表示にする
            reportViewer1.Visible = false;

            // ReportViewerコントロールにレポートを設定する
            reportViewer1.LocalReport.ReportPath = @"C:\XXXX\Report.rdlc";

            // レポートをプリンタを指定して直接印刷する
            reportViewer1.LocalReport.Print("Microsoft Print to PDF");


            Debug.Print("非同期処理終了");

        }

    }
}

6. 参考文献

0
3
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
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?