none
Print Directly to EMF using sql datatables C# RRS feed

  • Question

  •  

    I setup my report.rdlc file and have it embedded into my app,  now to just call the reportviewer is cake drop the control on a form,  and re-set the databindings on the popout.

     

    I need to be able to automatically output to EMF but the only code example for doing so just uses a xml dataset,  I have 7 different report datasources to make my report.  Are there any samples for doing a direct to EMF output using multiple datasources?

     

    I also was trying to just wrap the sample code into a class so I could call it (12 different reports when I'm done) and couldn't get that to work either (ended up making a huge mess)

     

    Are there any good samples for what I am looking to do?

    Thursday, January 10, 2008 5:08 AM

Answers

  • Warning massive code blocks ensure.  Here is my reporting class and how I'm calling the report with the datasources?

     

     

    Code Block

    using System;

    using System.IO;

    using System.Data;

    using System.Text;

    using System.Drawing.Imaging;

    using System.Drawing.Printing;

    using System.Collections.Generic;

    using System.Windows.Forms;

    using Microsoft.Reporting.WinForms;

    public class Reporting : IDisposable

    {

     

    public int m_currentPageIndex;

    public IList<Stream> m_streams;

    public Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)

    {

    string CurrentDrive;

    CurrentDrive = Application.StartupPath.ToString();

    Stream stream = new FileStream("C:\\" + name + "." + fileNameExtension, FileMode.Create);

    m_streams.Add(stream);

    return stream;

    }

    public void Export(LocalReport report)

    {

    string deviceInfo =

    "" +

    " EMF" +

    " 8.5in" +

    " 11in" +

    " 0.25in" +

    " 0.25in" +

    " 0.25in" +

    " 0.25in" +

    "";

    Warning[] warnings;

    m_streams = new List<Stream>();

    report.Render("Image", deviceInfo, CreateStream,

    out warnings);

    foreach (Stream stream in m_streams)

    stream.Position = 0;

    }

     

    public void PrintPage(object sender, PrintPageEventArgs ev)

    {

    Metafile pageImage = new

    Metafile(m_streams[m_currentPageIndex]);

    ev.Graphics.DrawImage(pageImage, ev.PageBounds);

    m_currentPageIndex++;

    ev.HasMorePages = (m_currentPageIndex < m_streams.Count);

    }

     

    public void Print()

    {

    const string printerName = "Microsoft Office Document Image Writer";

    if (m_streams == null || m_streams.Count == 0)

    {

    return;

    }

    PrintDocument printDoc = new PrintDocument();

    // printDoc.PrinterSettings..PrinterName = printerName

    if (!printDoc.PrinterSettings.IsValid)

    {

    string msg = string.Format("Can't find printer \"{0}\".", printerName);

    Console.WriteLine(msg);

    return;

    }

    printDoc.PrintPage += PrintPage;

    printDoc.PrinterSettings.Duplex = Duplex.Horizontal;

    printDoc.Print();

    }

    public void Dispose()

    {

    if (m_streams != null)

    {

    foreach (Stream stream in m_streams)

    stream.Close();

    m_streams = null;

    }

    }

     

    }

     

     

    Here is how I'm calling it,  changed the datesources for pasting.

     

    and at the top of the form calling the reporting I have a

    public Reporting myPRT;

    declared

    Code Block

    // This would be your rdlc report for your labels

    LocalReport report = new LocalReport();

    myPRT = new Reporting();

    // Set the physical path to your report rdlc file.

    report.ReportEmbeddedResource = "Personal.rdlc";

    // This next code binds my datasource to my report. I suspect you may be handling this differently.

    report.DataSources.Add(new ReportDataSource("TestDataSet_FOO", this.FOOBindingSource));

    report.DataSources.Add(new ReportDataSource("TestDataSet_FOO1", this.FOO1BindingSource));

    report.DataSources.Add(new ReportDataSource("TestDataSet1_FOOSource))", this.FOOSourceBindingSource1));

    report.DataSources.Add(new ReportDataSource("MainDataSet_FOO2", this.FOO2BindingSource));

    report.DataSources.Add(new ReportDataSource("MainDataSet_FOO3", this.FOO3BindingSource1));

    report.DataSources.Add(new ReportDataSource("MainDataSet_FOO4", this.FOO4BindingSource));

    report.DataSources.Add(new ReportDataSource("MainDataSet_FOO5", this.FOO5TableBindingSource));

     

    // This next code prepares the rdlc file for printing and calls the print function from the Reporting class file

    myPRT.Export(report);

    myPRT.m_currentPageIndex = 0;

    myPRT.Print();

     

     

    Any other info I can provied?
    Monday, January 14, 2008 6:55 PM
  • After banging my head against the wall,  I found the solution.

     

    report.ReportEmbeddedResource = "Personal.rdlc"; needed to be

     

    report.ReportEmbeddedResource = "ProjectName.Personal.rdlc";

     

     

    I hope other people can look at this page as a good C# sample to work off of for reporting directly to EMF without using the reportviewer.

     

    One last change since I just wanted to export the EMF files I commented out the following 2 lines.

     

    myPRT.m_currentPageIndex = 0;

    myPRT.Print();

     

    And called the dispose method at the end so I could finish the write of the EMF file

     

    myPRT.Dispose()

     

    Thanks for trying to help, I am not great with programming and still am not sure how to even ask some of the questions I come across.

    Monday, January 14, 2008 8:29 PM

All replies

  • It should not matter what your data sources are, David.  It's irrelevant at the time you're rendering the report.  I think I know what sample you're referring to (on gotreportviewer.com, right?) but not at all sure how you've ended up in a mess <s>.

     

    So... we'll have to back up a little.  What sample code *are* you looking at and what did you do exactly <s>?  If it is the one I think it is, the only reason they show the xml dataset load is to have some data to report on.  The Export method, which would do the actuall export to EMF, should work for any report and any loaded data you happen to have.

     

    >L<

     

    Monday, January 14, 2008 2:03 AM
  • http://msdn2.microsoft.com/en-us/library/ms252091(VS.80).aspx

     

    This is the sample code I was referring to,  I Tried to make it a class so I could call it for the 12 reports I will need to process when all is said and done. 

     

    When I was trying to wrap it into a class this line was giving me trouble.

            report.Render("Image", deviceInfo, CreateStream,
               out warnings);

    Forgive me on lack of terminology as I am still quite new to programming,  but it looks like it was looking for the instance of it's class which would get called from the main form and not from the class file I was making.

     

    I found where they had done something very close on Experts-Exchange.

     

    http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_22770005.html

     

    but the code is all VB and I know little of C# and even less of VB to try to make the conversion.

     

    Also how do I declare the datasource when it's a datasource from within my project, the connection string is already there and the datasets already are set with the proper select functions.

     

    Lastly thanks for the reply I look forward to any help you can offer.

    Monday, January 14, 2008 2:41 PM
  • Hi David,

     

    That code (http://msdn2.microsoft.com/en-us/library/ms252091(VS.80).aspx )  is actually almost the same code as was on gotreportviewer.com <smile>.

     

    I don't know what sample is on experts-exchange but based on the initial question they also started with the same code (that is why they can't find the executable, in the original question in the thread).

     

    As far as dynamically defining the data source, I would point you to a walkthrough I wrote except that is in VB also and you probably won't like that <sigh>.

     

    Right now I don't understand your description of the error ("giving me trouble" = what error message?) or your description of  what you did ("trying to wrap it into a class" = what code?).

     

    I will try to help -- as will lots of people here ! but you need to show what you actually did.  As I explained, the code in the sample should allow you to save EMFs from *any* report.  It doesn't care what the report is.  You  should see this code in the sample version you used:

     

    Code Block

      // Create a local report for Report.rdlc, load the data,
        //    export the report to an .emf file, and print it.
        private void Run()
        {
            LocalReport report = new LocalReport();
            report.ReportPath = @"..\..\Report.rdlc";
            report.DataSources.Add(
               new ReportDataSource("Sales", LoadSalesData()));
            Export(report);
            m_currentPageIndex = 0;
            Print();
        }

     

     

     

    ... is this the code you are trying to adapt?  What exactly have you done so far?

     

    >L<

    Monday, January 14, 2008 5:11 PM
  • Warning massive code blocks ensure.  Here is my reporting class and how I'm calling the report with the datasources?

     

     

    Code Block

    using System;

    using System.IO;

    using System.Data;

    using System.Text;

    using System.Drawing.Imaging;

    using System.Drawing.Printing;

    using System.Collections.Generic;

    using System.Windows.Forms;

    using Microsoft.Reporting.WinForms;

    public class Reporting : IDisposable

    {

     

    public int m_currentPageIndex;

    public IList<Stream> m_streams;

    public Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)

    {

    string CurrentDrive;

    CurrentDrive = Application.StartupPath.ToString();

    Stream stream = new FileStream("C:\\" + name + "." + fileNameExtension, FileMode.Create);

    m_streams.Add(stream);

    return stream;

    }

    public void Export(LocalReport report)

    {

    string deviceInfo =

    "" +

    " EMF" +

    " 8.5in" +

    " 11in" +

    " 0.25in" +

    " 0.25in" +

    " 0.25in" +

    " 0.25in" +

    "";

    Warning[] warnings;

    m_streams = new List<Stream>();

    report.Render("Image", deviceInfo, CreateStream,

    out warnings);

    foreach (Stream stream in m_streams)

    stream.Position = 0;

    }

     

    public void PrintPage(object sender, PrintPageEventArgs ev)

    {

    Metafile pageImage = new

    Metafile(m_streams[m_currentPageIndex]);

    ev.Graphics.DrawImage(pageImage, ev.PageBounds);

    m_currentPageIndex++;

    ev.HasMorePages = (m_currentPageIndex < m_streams.Count);

    }

     

    public void Print()

    {

    const string printerName = "Microsoft Office Document Image Writer";

    if (m_streams == null || m_streams.Count == 0)

    {

    return;

    }

    PrintDocument printDoc = new PrintDocument();

    // printDoc.PrinterSettings..PrinterName = printerName

    if (!printDoc.PrinterSettings.IsValid)

    {

    string msg = string.Format("Can't find printer \"{0}\".", printerName);

    Console.WriteLine(msg);

    return;

    }

    printDoc.PrintPage += PrintPage;

    printDoc.PrinterSettings.Duplex = Duplex.Horizontal;

    printDoc.Print();

    }

    public void Dispose()

    {

    if (m_streams != null)

    {

    foreach (Stream stream in m_streams)

    stream.Close();

    m_streams = null;

    }

    }

     

    }

     

     

    Here is how I'm calling it,  changed the datesources for pasting.

     

    and at the top of the form calling the reporting I have a

    public Reporting myPRT;

    declared

    Code Block

    // This would be your rdlc report for your labels

    LocalReport report = new LocalReport();

    myPRT = new Reporting();

    // Set the physical path to your report rdlc file.

    report.ReportEmbeddedResource = "Personal.rdlc";

    // This next code binds my datasource to my report. I suspect you may be handling this differently.

    report.DataSources.Add(new ReportDataSource("TestDataSet_FOO", this.FOOBindingSource));

    report.DataSources.Add(new ReportDataSource("TestDataSet_FOO1", this.FOO1BindingSource));

    report.DataSources.Add(new ReportDataSource("TestDataSet1_FOOSource))", this.FOOSourceBindingSource1));

    report.DataSources.Add(new ReportDataSource("MainDataSet_FOO2", this.FOO2BindingSource));

    report.DataSources.Add(new ReportDataSource("MainDataSet_FOO3", this.FOO3BindingSource1));

    report.DataSources.Add(new ReportDataSource("MainDataSet_FOO4", this.FOO4BindingSource));

    report.DataSources.Add(new ReportDataSource("MainDataSet_FOO5", this.FOO5TableBindingSource));

     

    // This next code prepares the rdlc file for printing and calls the print function from the Reporting class file

    myPRT.Export(report);

    myPRT.m_currentPageIndex = 0;

    myPRT.Print();

     

     

    Any other info I can provied?
    Monday, January 14, 2008 6:55 PM
  • After banging my head against the wall,  I found the solution.

     

    report.ReportEmbeddedResource = "Personal.rdlc"; needed to be

     

    report.ReportEmbeddedResource = "ProjectName.Personal.rdlc";

     

     

    I hope other people can look at this page as a good C# sample to work off of for reporting directly to EMF without using the reportviewer.

     

    One last change since I just wanted to export the EMF files I commented out the following 2 lines.

     

    myPRT.m_currentPageIndex = 0;

    myPRT.Print();

     

    And called the dispose method at the end so I could finish the write of the EMF file

     

    myPRT.Dispose()

     

    Thanks for trying to help, I am not great with programming and still am not sure how to even ask some of the questions I come across.

    Monday, January 14, 2008 8:29 PM
  • Hi David,

     

    I'm glad you solved your own problem before I could get back here to see your code. <g>

     

     For what it's worth the "ReportEmbeddedResource" line is one of the typical issues that people have with this and also FWIW it is one of the items I "called out" in one of the walkthroughs I wrote about this (http://spacefold.com/lisa/post/Dynamically-loading-reports-in-ReportViewers.aspx) , as follows:

     

    Code Block

     

    Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
       Me.InitializeDefaultXSLT()
       ' the XSLT in use, like report resources, is editable by the user
       Me.exeLocation = System.Reflection.Assembly.GetExecutingAssembly().Location
       Me.InitializeViewer("TestHarness.Report1.rdlc")
    End Sub

     

    Notice the use of the executable name in the reference to the embedded resource above.  This was the source of confusion in the question I answered this morning, FWIW; if a resource is embedded you have to tell the ReportViewer where it is (in this case, inside an EXE named TestHarness).  This requirement has absolutely nothing to do with reports in particular; the call you see above to InitializeDefaultXSLT() has to do exactly the same thing when choosing to load the default XSLT embedded resource rather than an external transform selected by the user from XSLT files on disk.

     

     

    ... I wouldn't bother to show you this, considering that you really don't need my help , except for the point that this code happens to be VB.NET rather than C# and yet the line that actually assigns the resource is only different by a semi-colon from the C# version of the same code:

     

    Code Block

    Private Sub InitializeViewer(ByVal tsReport As String)

       Dim ReportDataSourceX = _
          New Microsoft.Reporting.WinForms.ReportDataSource() 
       Me.ReportViewer1.Reset() 
       Me.ReportViewer1.LocalReport.ReportEmbeddedResource = tsReport 

    [..]

     

     

    As you move forward doing more of this stuff... don't worry so much about what language the examples are in, okay?  You can read them, and apply the advice in them, no matter what.  You're going to do fine!

     

    Regards,

     

    >L<

    Tuesday, January 15, 2008 6:22 AM