2

I managed to Create a DLL with the help of Reza Aghaei

Here is the C# code (that I get from Print RDLC Report without showing ReportViewer Control):

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)
    {
        var pageSettings = new PageSettings();
        pageSettings.PaperSize = report.GetDefaultPageSettings().PaperSize;
        pageSettings.Landscape = report.GetDefaultPageSettings().IsLandscape;
        pageSettings.Margins = report.GetDefaultPageSettings().Margins;
        Print(report, pageSettings);
    }

    public static void Print(this LocalReport report, PageSettings pageSettings)
    {
        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.Print();
        }
    }
}

In C# as mentioned by Reza Aghaei the function is called with

this.reportViewer1.LocalReport.Print();

I Reference and tried to call this in vb.net

if I try

this.reportViewer1.LocalReport.Print()

or

LocalReport.Print()

it gives error.

What am I missing Kindly Help or if an Expert can convert it in Vb.net that would be really appreciated.

My Receipt I made look like this.

enter image description here

I would appreciate if any expert help me solve this as I mainly work in VB.net.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
425618
  • 55
  • 5
  • What is the error? Which version of C# is this? – Charlieface Feb 14 '21 at 14:00
  • VB.NET or C#? Which language are you using for your project? – Reza Aghaei Feb 14 '21 at 14:04
  • Sir, I'm using Vb.net for my project. it would be really great if I could get a Dll or vb.net converted code of it to use. – 425618 Feb 14 '21 at 14:27
  • In C# it turned out the error was because of "$" before "@" so I removed it. I have edited the question would be of great help if its resolved. – 425618 Feb 14 '21 at 15:39
  • I think you should import namespace of LocalReportExtensions. [This is](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods) how extension methods work in c# – Serhii Feb 14 '21 at 16:16

1 Answers1

2

Note: All the converters that I tried were unable to convert the C# code of the linked post to a correct VB.NET version. You can find the original C# version in the linked post: Print RDLC Report without showing ReportViewer Control.

VB.NET - Print RDLC Report without showing ReportViewer control

Here is the VB version of the Print extension method of LocalReport:

Imports Microsoft.Reporting.WinForms
Imports System.Drawing.Imaging
Imports System.Drawing.Printing
Imports System.IO
Imports System.Runtime.CompilerServices

Public Module LocalReportExtensions
    <Extension()>
    Sub Print(ByVal report As LocalReport)
        Dim pageSettings = New PageSettings()
        pageSettings.PaperSize = report.GetDefaultPageSettings().PaperSize
        pageSettings.Landscape = report.GetDefaultPageSettings().IsLandscape
        pageSettings.Margins = report.GetDefaultPageSettings().Margins
        Print(report, pageSettings)
    End Sub

    <Extension()>
    Sub Print(ByVal report As LocalReport, ByVal pageSettings As PageSettings)
        Dim deviceInfo As String = $"<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>"
        Dim warnings() As Warning
        Dim streams = New List(Of Stream)()
        Dim currentPageIndex = 0
        report.Render("Image", deviceInfo,
                      Function(name, fileNameExtension, encoding, mimeType, willSeek)
                          Dim stream = New MemoryStream()
                          streams.Add(stream)
                          Return stream
                      End Function, warnings)

        For Each stream As Stream In streams
            stream.Position = 0
        Next

        If streams Is Nothing OrElse streams.Count = 0 Then
            Throw New Exception("Error: no stream to print.")
        End If

        Dim printDocument = New PrintDocument()
        printDocument.DefaultPageSettings = pageSettings

        If Not printDocument.PrinterSettings.IsValid Then
            Throw New Exception("Error: cannot find the default printer.")
        Else
            AddHandler printDocument.PrintPage,
                Sub(sender, e)
                    Dim pageImage As Metafile = New Metafile(streams(currentPageIndex))
                    Dim adjustedRect As Rectangle = New Rectangle(
                        e.PageBounds.Left - CInt(e.PageSettings.HardMarginX),
                        e.PageBounds.Top - CInt(e.PageSettings.HardMarginY),
                        e.PageBounds.Width,
                        e.PageBounds.Height)
                    e.Graphics.FillRectangle(Brushes.White, adjustedRect)
                    e.Graphics.DrawImage(pageImage, adjustedRect)
                    currentPageIndex += 1
                    e.HasMorePages = (currentPageIndex < streams.Count)
                    e.Graphics.DrawRectangle(Pens.Red, adjustedRect)
                End Sub

            AddHandler printDocument.EndPrint,
                Sub(Sender, e)
                    If streams IsNot Nothing Then
                        For Each stream As Stream In streams
                            stream.Close()
                        Next
                        streams = Nothing
                    End If
                End Sub

            printDocument.Print()
        End If
    End Sub
End Module

To use above code, it's enough to call Print extension method on a LocalReport. For example if you have a (visible or invisible ReportViewer):

Me.ReportViewer1.LocalReport.Print()

Of if you want to pass printer settings:

Me.ReportViewer1.LocalReport.Print(ReportViewer1.GetPageSettings())
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Firstly I really thank you for your help, I have updated the Question again kindly check. – 425618 Feb 14 '21 at 17:04
  • I've seen your update and since you are new to C#, I decided to share the VB.NET version with you. Use the VB.NET version code, just copy the module into a file in your project and use it as explained in the answer. – Reza Aghaei Feb 14 '21 at 17:06
  • The dll approach (that you tried also works), just make sure that you Import the namespace of the class. Extension methods will be visible to your code just after you imported their namespace. – Reza Aghaei Feb 14 '21 at 17:07
  • 1
    thank to all who helped if finally solved it. turned out making Dll was not a good option. just make a class and call me.reportviewer1.localreport.print(). – 425618 Feb 14 '21 at 17:34