Giter VIP home page Giter VIP logo

my-fyireporting's Introduction

Majorsilence Reporting (formerly My-FyiReporting)

If you have any question about Majorsilence Reporting or do you want to contribute a discussion group for Majorsilence Reporting is available here:

https://groups.google.com/d/forum/myfyireporting

Linux Win(Deploy)
Release NA Build status appveyor

Documentation

See the projects wiki.

Download

See the downloads page.

Alternatively if you want keep up with the latest version you can always use Git

git clone https://github.com/majorsilence/My-FyiReporting.git

Introduction

"FYIReporting Designer is a report and charting system based on Microsoft's Report Definition Language (RDL). Tabular, free form, matrix, charts are fully supported. HTML, PDF, XML, .Net Control, and printing supported. A WYSIWYG designer allows you to create reports without knowledge of RDL. Wizards are available for creating new reports and for inserting new tables, matrixes, and charts into existing reports." (http://www.fyireporting.com/)

Use the report viewer .NET controls from ASP.NET, WPF, or Winforms using C#, F#, VB.NET, IronPython, or any other .NET language. The winform viewer also works in linux using mono. An experimental Gtk/WPF/Cocoa viewer also exists.

Majorsilence Reporting started as My-FyiReporting which was a fork of fyiReporting after it died. It has been rebranded as Majorsilence Reporting to make it clearer that it is a separate forked project. Majorsilence Reporting is a fork of fyiReporting. I cannot stress this enough. This is a FORK. The main purpose is to make sure that I have a copy of fyiReporting since that project seems to be dead. I am leaving the github project named My-FyiReporting so links are not broken. All branding will eventually be replaced with Majorsilence Reporting.

Also check this projects wiki as information will be slowly added.

Majorsilence Reporting is currently built with visual studio 2022 and rider 2024.1 and targets .net 4.8, net6.0 and 8.0. You can also run the build script.

Development

Majorsilence Reporting is developed with the following workflow:

  • Nothing happens for weeks or months
  • Someone needs it to do something it doesn't already do
  • That person implements that something and submits a pull request
  • Repeat If it doesn't have a feature that you want it to have, add it. If it has a bug you need fixed, fix it.

Contribute:

All contributions welcome. I'll try to respond the same day to any emails or pull requests. Or within a few days at the most. Small pull requests are best as they are easier to review.

See the wiki page https://github.com/majorsilence/My-FyiReporting/wiki/Contribute

Core Team

Contributors

A big thanks to all of Majorsilence Reporting contributors:

Layout:

  • DataProviders\DataProviders.sln
  • Images\
  • OracleSp\OracleSp.sln
    • Requires Oracle Data Provider for .NET
  • RdlAsp\RdlAsp.sln
    • Asp controls to display reports in asp.net and silverlight pages.
    • References RdlEngine
  • RdlCMD\RdlCmd.sln
    • Command line tools
    • References RdlEngine
  • RdlCri\RdlCri.sln
    • Custom Report Controls
    • References RdlEngine
  • RdlDesign\RdlDesign.sln
    • Is the main graphical drag and drop designer used to create reports.
    • References RdlEngine
    • References RdlViewer
  • RdlDesktop\RdlDesktop.sln
    • References RdlEngine
  • RdlEngine\RdlEngine.sln
    • Main engine. Is referenced in many of the other projects
  • RdlGtkViewer\RdlGtkViewer.sln
    • A Gtk# (gtk-sharp) viewer
  • RdlViewer
    • References RdlEngine
    • Disabled COM interop
  • RdlMapFile\RdlMapFile.sln
    • Map viewer
  • RdlTest\RdlTests.sln
    • Tests
  • ReportSever\

RDL Compliance Report file format specifications can be obtained from microsoft. I believe fyiReporting is currently mostly compatible with RDL 2005. If you want to add more features see the specfications.

User interface tutorials

ReportingCloud (another fork) has made some tutorials for using the designer and creating reports. http://sourceforge.net/projects/reportingcloud/files/

my-fyireporting's People

Contributors

alberti47 avatar arseniishub avatar art8m avatar baragon avatar chripf avatar daniellor avatar darreno1 avatar dependabot[bot] avatar dobriymisha avatar efimov90 avatar enzogord avatar gam6itko avatar gankov avatar grezza123 avatar iamposox avatar ironpig avatar jzielke avatar kernel-klink avatar kmvi avatar kobruleht avatar majorsilence avatar maratoss avatar martin-lain avatar mayazcherquoi avatar mohsenalikhani avatar orellabaccr avatar peter-rohner avatar psoares33 avatar salihkiraz avatar sobolev88 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

my-fyireporting's Issues

Table element is rendered incorrectly in html output

To reproduce, create report containing Table element like in #10 and create html output from it.

Observed result is:

observed

textboxes are rendered in same line.

Textboxes should be placed into separate rows as shown in issue 10 expected image.

Generated html output is:

  <html>
  <head>
  <style type='text/css'>
    td#css3 {border-color:black;border-style:none;border-width:1pt;background- color:transparent;
    background-image:none;font-style:normal;font-family:Times New   Roman;
    font-size:12pt;font-weight:normal;text-decoration:none;text-align:Left;vertical-align:top;
    color:black;padding-left:0pt;padding-right:0pt;padding-top:0pt;padding-bottom:0pt;line-height:normal;}

  table#css2 {}
  table#css1 {border-collapse:collapse;}

  body#css4 {}
  </style>
    <title></title>
    </head>
    <body id='css4'><table>
    <tr><td><div style="POSITION: relative; ">
    <table id='css1' width=793>
  <tbody>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
    <tr><td id='css2'><table id='css2'><tr>
  <td><div class='css3'>field1 line1
  field1 line2</div></td><td><div class='css3'>field2 line3
   field2 line4</div></td></tr></table>
  </td></tr>
  </tbody>
  </table>
  </div></td></tr>
  </table></body></html>

Imagenes & Direccion del reporte

Dear Peter,

From now on I'll tell you that my English is bad, and used a small control during an application period in Vb.net & mysql, you know what I stand in this excelent control? Was a report with images in new table.
The default options when creating a new table are:

We should implement an option in which says that objects are filled to the right, by group and down.

So I could not continue filling all my pictures in the report organized by category, always fills down by row and right. Across (standard colums)

If you could help me with a hint where I can change the settings of these classes and send a pull request.
salu2 fizzvr

directory separator character is misisng in XmlUtil.cs

In RDLEngine XmlUtil.cs line

string d2 = AppDomain.CurrentDomain.RelativeSearchPath;

should probably changed to

string d2 = AppDomain.CurrentDomain.RelativeSearchPath+ Path.DirectorySeparatorChar;

otherwise code module is not searched from this location.

d1 contains directory separator at end so d2 should probably also contain,

Export to Pdf - barcodes

When exporting a report to pdf that includes barcodes the barcodes are not included in the pdf.

Body Height not behaving as expected

If I change the size of the Body band, it makes no difference to the report generated. Whether it's way too large, or very small, the actual report looks the same.
But if I hack the RDL I can get it how I like it - it seems to be using the second of the two "Height" values, whereas the designer changes the first of them.

  </PageHeader>
  <Body>
    <Height>14.5pt</Height>  ---- designer changes this value
    <ReportItems>
      <List Name="List1">
        <DataSetName>Data</DataSetName>
        <Height>71.5pt</Height>   --- report actually uses this value!
        <NoRows>Query returned no rows!</NoRows>
        <ReportItems>

Difficulty adding new column from updated SQL

As discussed in email, no easy way to add a column if the SQL is changed and a new column is to be added to the report.

Even if RDL is adjusted by hand, the designer has trouble with the new field and it can't be selected to move it, etc.
It's as if the number of fields it's comfortable with is set in stone after the initial wizard has done its thing, even though there's no counter in the RDL as such!

Attempt by security transparent method

The following exception occurs when running report server and displaying a report with maps or charts.

{"Attempt by security transparent method
'fyiReporting.RDL.EMF.MetafileCallback(System.Drawing.Imaging.EmfPlusRecordType, Int32,
Int32, IntPtr, System.Drawing.Imaging.PlayRecordCallback)' to access security critical method
'System.Runtime.InteropServices.Marshal.Copy(IntPtr, Byte[], Int32, Int32)' failed.\n\nAssembly
'RdlEngine, Version=4.5.4633.14960, Culture=neutral, PublicKeyToken=null' is marked with
the AllowPartiallyTrustedCallersAttribute, and uses the level 2 security transparency model.
Level 2 transparency causes all methods in AllowPartiallyTrustedCallers assemblies to become
security transparent by default, which may be the cause of this exception."}

.net 3.5 support

Enable .net 3.5 support. There is currently nothing that requires 4. Will need to test and fix any designer code that was generated or opened with the project targeting 4.

RemotingException on re-open RdlDesigner

I'm not sure if this is actually an issue or my misunderstanding of how to use RdlDesigner. We need a very simple designer to allow our users to edit report designs, and it seems RdlDesigner could meet our needs (in fact it does much more than we need).

We are using RdlDesigner as follows

      'manage the designer
    _designer = New fyiReporting.RdlDesign.RdlDesigner("ReportChannel", False)
    _designer.Show()
    _designer.OpenFile(filePath)
    _designer.Text = "Report Designer"

    'add a handler to detect the save
    AddHandler _designer.SavedFileEvent, AddressOf designer_SavedFileEvent

This works very well the first time RdlDesigner is opened, however if the user tries to open the report again, we get a RemotingException:
Failed to create an IPC Port: Access is denied.

If the user continues editing the report in the current window for RdlDesigner, all is good. However many users would click on our design button again in our app, which runs the code above. The same exception occurs if RdlDesigner is closed and we try to reopen again from our app.

Perhaps IpcChannelPortName is not being used correctly? How should RdlDesigner be opened again.

On a possibly releated note, there is no click event associated with File > Exit, so the exit menu does not work (easily fixed by connecting up the event handler, but maybe there is a reason for this).

Thanks,
Tim

Parameters to RdlReader.exe

As mentioned on email :

Can I ask for one simple but powerful change please? It would be so useful to be able to call RdlReader.exe from the cmd line with the .rdl filename as a parameter. A report could therefore be launched from within a .net project, a batch file, powershell, etc... just about any other language!
It would also automatically enable right-click Open With.. from the desktop, and probably being able to drag and drop an rdl file onto the reader icon too.
That would be tremendously useful, and would appeal to newbies like myself who just want to launch a report viewing, from a button click, without all the scary development including the controls. A great way to attract users and suck them into using My-FyiReporting, IMHO.

A quick mod to : RdlViewer / RdlReader / RdlReader.cs

  • hopefully as simple as putting this the end of Main()
    (leaving the /m option to work as before) :

// if long enough to contain ".rdl", launch specified report straight away
If (args.Length >= 5 &&
(File.Exists(args[1]))
{
CreateMDIChild(new Uri(args[1]), false);
RecentFilesMenu();
}

Many thanks

iTextSharp pdf renderer does not work in mono

Trying to create PDF in Mono in Linux in MVC2 fails with exception

/tmp/www-data-temp-aspnet-0/49ed19b6/assembly/shadow/046d6b32/a0505d34_a43d3606_00000001\Fonts\ariali.ttf not found as file or resource.

Description: HTTP 500. Error processing request.

Stack Trace:

System.IO.IOException: /tmp/www-data-temp-aspnet-0/49ed19b6/assembly/shadow/046d6b32/a0505d34_a43d3606_00000001\Fonts\ariali.ttf not found as file or resource.
at iTextSharp.text.pdf.RandomAccessFileOrArray..ctor (string,bool) <0x00343>
at iTextSharp.text.pdf.TrueTypeFont.Process (byte[],bool) <0x0008b>
at iTextSharp.text.pdf.TrueTypeFontUnicode..ctor (string,string,bool,byte[],bool) <0x001db>
at iTextSharp.text.pdf.BaseFont.CreateFont (string,string,bool,bool,byte[],byte[],bool,bool) <0x00487>
at iTextSharp.text.pdf.BaseFont.CreateFont (string,string,bool,bool,byte[],byte[],bool) <0x0004f>
at iTextSharp.text.pdf.BaseFont.CreateFont (string,string,bool) <0x00037>
at fyiReporting.RDL.RenderPdf.iAddText (single,single,single,single,string[],fyiReporting.RDL.StyleInfo,fyiReporting.RDL.PdfFonts,single[],bool,string,bool,string) <0x007eb>
at fyiReporting.RDL.RenderPdf.ProcessPage (fyiReporting.RDL.Pages,System.Collections.IEnumerable) <0x014bf>
at fyiReporting.RDL.RenderPdf.RunPages (fyiReporting.RDL.Pages) <0x00473>
at fyiReporting.RDL.ReportDefn.RunPage (fyiReporting.RDL.IPresent) <0x001c2>
at fyiReporting.RDL.ReportDefn.Run (fyiReporting.RDL.IPresent) <0x00087>
at fyiReporting.RDL.Report.RunRender (fyiReporting.RDL.IStreamGen,fyiReporting.RDL.OutputPresentationType,string) <0x000df>
at fyiReporting.RDL.Report.RunRender (fyiReporting.RDL.IStreamGen,fyiReporting.RDL.OutputPresentationType) <0x00023>
...
Version information: Mono Runtime Version: 2.10.8.1 (mono-2-10/70a5c95 Wed Feb 8 18:11:45 CET 2012); ASP.NET Version: 2.0.50727.1433

RenderPdf.cs contains CreateFont call which does not find font. In Windows it can get fonts from Fonts colder. It looks like Fonts does not exist in Mono/Linux.

I posted this to
http://stackoverflow.com/questions/15056698/how-to-create-pdf-with-unicode-characters-in-linux-with-mono

also.

Missing File

The solution refers to Logging.cs in the ReportDesigner project, but it is not included when pulling from master.

Aggregate Function First() returns data from wrong dataset

We are attempting to use the aggregating function First to display data from a second dataset (Owner) on a table (of InspectionItems), by specifying the dataset name as the scope parameter (InspectionItems is the DataSet for the Table).

=First(Fields!Name.Value, "Owner")

This works as we would expect in Microsoft's ReportViewer. However, in fyiReporting's preview function, we have observed that the data is actually being retrieved from the InspectionItem dataset.

Through debugging, we have determined that when FunctionAggr.GetDataScope is called, it returns the RowEnumerable of the row passed to it, rather than looking at the scope/dataset in this._Scope.
We were able to resolve this ssue by adding the following code to the else/if branches:

            if (t == typeof(DataSetDefn))
            {
                DataSetDefn ds = this._Scope as DataSetDefn;
                if (ds != null && ds.Query != null)
                {
                    Rows rows = ds.Query.GetMyData(rpt);
                    if (rows != null)
                        re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, false);
                }
            }

This is the same code that is executed if row == null.

This code needs to be inserted before

           else if (row != null)
            {
                re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false);
            }

Hope this is helpful.

Regards,
Tim

minor update proposals for rdlengine

I have made 3 minor modifiactions to RDLEngine to make is usable:

In Code.cs

line

re = AppDomain.CurrentDomain.BaseDirectory + "Bin\RdlEngine.dll"; // this can work especially in web scenarios

should changed to

                re = AppDomain.CurrentDomain.BaseDirectory + "Bin" + Path.DirectorySeparatorChar + "RdlEngine.dll"; 

To prevent error hiding in Query.cs try catches should removed in two places:

near line #162

catch (Exception /e/)
{
// original hides errors:
//OwnerReport.rl.LogError(4, "SQL Exception during report compilation: " + e.Message + "\r\nSQL: " + sql);
throw;
}

near line #275

        catch // (Exception e)
        {
            // Try catch removed. Otherwise error is not shown,
            // only data is not retrieved
            throw;
            //Original was: rpt.rl.LogError(8, "SQL Exception" + e.Message + "\r\n" + e.StackTrace);
        }

CanShrink and CanGrow attributes are not implemented

CanShrink is not implemeted in RDLEngine: if field is set to no display, empty rows are rendered.
According to rdl spec this empty space shoudl be removed.

Same for CanGrow: if field has CanGrow attribute set and text wraps to multiple lines, bottom elemens should move down.
Currently text overwrites next element.

allow unicode characters in pdf files

PDF renderer does not support unicode characters. for example, cyrillic characters are rendered as unreadable. Some FYIReporting works may contain ITextSharp usage which allow this. Also FYIReporting.com forum contains patch fpor this, e.q patched RenderPDF.cs:

/* ====================================================================
Copyright (C) 2004-2008 fyiReporting Software, LLC

This file is part of the fyiReporting RDL project.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

For additional information, email [email protected] or visit
the website www.fyiReporting.com.
*/

using System;
using fyiReporting.RDL;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace fyiReporting.RDL
{

///<summary>
/// Renders a report to PDF.   This is a page oriented formatting renderer.
///</summary>
internal class RenderPdf : IPresent
{
    Report r;                   // report
    Stream tw;                  // where the output is going
    PdfAnchor anchor;           // anchor tieing together all pdf objects
    PdfCatalog catalog;
    PdfPageTree pageTree;
    PdfInfo info;
    PdfFonts fonts;
    PdfPattern patterns;
    PdfImages images;
    PdfOutline outline;         // holds the bookmarks (if any)
    PdfUtility pdfUtility;
    int filesize;
    PdfPage page;
    private PdfPageSize _pSize;
    PdfContent content;
    PdfElements elements;        
    static readonly char[] lineBreak = new char[] { '\n' };
    static readonly char[] wordBreak = new char[] { ' ' };
    //      static readonly int MEASUREMAX = int.MaxValue;  //  .Net 2 doesn't seem to have a limit; 1.1 limit was 32
    static readonly int MEASUREMAX = 32;  //  guess I'm wrong -- .Net 2 doesn't seem to have a limit; 1.1 limit was 32
    #region PdfElements Rewrite in iTextSharp (Sinnovasoft add April 14 2010)
    Document pdfdocument = new Document();
    MemoryStream ms = new MemoryStream();
    PdfContentByte cb;
    /// <summary>
    /// List itextSharp Basefont added
    /// </summary>
    private List<BaseFont> BaseFonts = new List<BaseFont>();
    /// <summary>
    /// List font name
    /// </summary>
    private List<string> BaseFontsname = new List<string>();
    /// <summary>
    /// Page line element at the X Y to X2 Y2 position
    /// </summary>
    /// <returns></returns>
    private void iAddLine(float x, float y, float x2, float y2, StyleInfo si)
    {
        iAddLine(x, y, x2, y2, si.BWidthTop, si.BColorTop, si.BStyleTop);
    }
    /// <summary>
    /// Page line element at the X Y to X2 Y2 position
    /// </summary>
    /// <returns></returns>
    private void iAddLine(float x, float y, float x2, float y2, float width, System.Drawing.Color c, BorderStyleEnum ls)
    {
        // Get the line color            
        cb.SetRGBColorStroke(c.R, c.G, c.B);
        cb.SetLineWidth(width);
        // Get the line style Dotted - Dashed - Solid
        switch (ls)
        {
            case BorderStyleEnum.Dashed:
                cb.SetLineDash(new float[] { '3', '2' }, 0);
                break;
            case BorderStyleEnum.Dotted:
                cb.SetLineDash(new float[] { '2' }, 0);
                break;
            case BorderStyleEnum.Solid:
            default:
                cb.SetLineDash(new float[] { }, 0);
                break;
        }
        cb.MoveTo(x, _pSize.yHeight - y);
        cb.LineTo(x2, _pSize.yHeight - y2);
        cb.Stroke();
    }
    /// <summary>
    /// Add a filled rectangle
    /// </summary>
    /// <returns></returns>
    private void iAddFillRect(float x, float y, float width, float height, Color c)
    {
        // Get the fill color
        cb.SetRGBColorStrokeF(c.R, c.G, c.B);
        cb.Rectangle(x, _pSize.yHeight - y - height, width, height);
        cb.ClosePathStroke();
    }

    private void iAddFillRect(float x, float y, float width, float height, StyleInfo si, PdfPattern patterns)
    {
        Color c;
        //Not sure about iTextSharp Pattern => Need check
        if (si.PatternType != patternTypeEnum.None)
        {
            string p = patterns.GetPdfPattern(si.PatternType.ToString());
            c = si.Color;
            double red = Math.Round((c.R / 255.0), 3);
            double green = Math.Round((c.G / 255.0), 3);
            double blue = Math.Round((c.B / 255.0), 3);
            StringBuilder elements = new StringBuilder();
            elements.AppendFormat("\r\nq");
            elements.AppendFormat("\r\n /CS1 cs");
            elements.AppendFormat("\r\n {0} {1} {2} /{3} scn", red, green, blue, p);
            elements.AppendFormat("\r\n {0} {1} {2} RG", red, green, blue);
            elements.AppendFormat("\r\n {0} {1} {2} {3} re\tf", x, _pSize.yHeight - y - height, width, height);
            elements.AppendFormat("\tQ");
            PdfPatternPainter pdfp = cb.CreatePattern(60f, 60f, 60f, 60f);
            pdfp.SetLiteral(elements.ToString());
            cb.SetPatternFill(pdfp);
        }
        // Get the fill color - could be a gradient or pattern etc...
        c = si.BackgroundColor;
        cb.SetRGBColorStrokeF(c.R, c.G, c.B);
        cb.Rectangle(x, _pSize.yHeight - y - height, width, height);
        cb.ClosePathFillStroke();


    }
    /// <summary>
    /// Add border
    /// </summary>
    private void iAddBorder(StyleInfo si, float x, float y, float height, float width)
    {
        // Handle any border required   TODO: optimize border by drawing a rect when possible
        if (height <= 0 || width <= 0)      // no bounding box to use
            return;

        float ybottom = (y + height);
        float xright = x + width;
        if (si.BStyleTop != BorderStyleEnum.None && si.BWidthTop > 0)
            iAddLine(x, y, xright, y, si.BWidthTop, si.BColorTop, si.BStyleTop);

        if (si.BStyleRight != BorderStyleEnum.None && si.BWidthRight > 0)
            iAddLine(xright, y, xright, ybottom, si.BWidthRight, si.BColorRight, si.BStyleRight);

        if (si.BStyleLeft != BorderStyleEnum.None && si.BWidthLeft > 0)
            iAddLine(x, y, x, ybottom, si.BWidthLeft, si.BColorLeft, si.BStyleLeft);

        if (si.BStyleBottom != BorderStyleEnum.None && si.BWidthBottom > 0)
            iAddLine(x, ybottom, xright, ybottom, si.BWidthBottom, si.BColorBottom, si.BStyleBottom);

        return;
    }
    /// <summary>
    /// Add image to the page.
    /// </summary>
    /// <returns>string Image name</returns>
    private void iAddImage(PdfImages images, string name, int contentRef, StyleInfo si,
        ImageFormat imf, float x, float y, float width, float height, RectangleF clipRect,
        byte[] im, int samplesW, int samplesH, string url, string tooltip)
    {

        //Draw a rectangle if needed
        if (!clipRect.IsEmpty)
        {
            cb.SetRGBColorStroke(0, 0, 0);
            cb.Rectangle(clipRect.X, _pSize.yHeight - clipRect.Y - clipRect.Height, clipRect.Width, clipRect.Height);
            cb.Stroke();
        }
        iTextSharp.text.Image pdfImg = iTextSharp.text.Image.GetInstance(im);
        pdfImg.ScaleAbsolute(width, height); //zoom          
        pdfImg.SetAbsolutePosition(x, _pSize.yHeight - y - height);//Set position
        pdfdocument.Add(pdfImg);
        //add url
        if (url != null)
            pdfdocument.Add(new Annotation(x, _pSize.yHeight - y - _pSize.topMargin, height, width, url));
        //add tooltip
        if (!string.IsNullOrEmpty(tooltip))
            pdfdocument.Add(new Annotation(x, _pSize.yHeight - y - _pSize.topMargin, height, width, tooltip));
        iAddBorder(si, x - si.PaddingLeft, y - si.PaddingTop,
            height + si.PaddingTop + si.PaddingBottom,
            width + si.PaddingLeft + si.PaddingRight);          // add any required border
    }
    /// <summary>
    /// Page Polygon
    /// </summary>
    /// <param name="pts"></param>
    /// <param name="si"></param>
    /// <param name="url"></param>
    /// <param name="patterns"></param>
    internal void iAddPolygon(PointF[] pts, StyleInfo si, string url, PdfPattern patterns)
    {
        if (si.BackgroundColor.IsEmpty)
            return;         // nothing to do

        // Get the fill color - could be a gradient or pattern etc...
        Color c = si.BackgroundColor;
        iAddPoints(pts);
        cb.SetRGBColorFillF(c.R, c.G, c.B);
        cb.ClosePathFillStroke();

        //Not sure about iTextSharp Pattern => Need check
        if (si.PatternType != patternTypeEnum.None)
        {
            string p = patterns.GetPdfPattern(si.PatternType.ToString());
            StringBuilder elements = new StringBuilder();
            c = si.Color;
            double red = Math.Round((c.R / 255.0), 3);
            double green = Math.Round((c.G / 255.0), 3);
            double blue = Math.Round((c.B / 255.0), 3);
            elements.AppendFormat("\r\nq");
            elements.AppendFormat("\r\n /CS1 cs");
            elements.AppendFormat("\r\n {0} {1} {2} /{3} scn", red, green, blue, p);
            elements.AppendFormat("\r\n {0} {1} {2} RG", red, green, blue);
            elements.AppendFormat("\tQ");
            PdfPatternPainter pdfp = cb.CreatePattern(60f, 60f, 60f, 60f);
            pdfp.SetLiteral(elements.ToString());
            cb.SetPatternFill(pdfp);
            iAddPoints(pts);
            cb.ClosePathFillStroke();
        }
    }

    private void iAddPoints(PointF[] pts)
    {
        if (pts.Length > 0)
        {
            cb.MoveTo(pts[0].X, _pSize.yHeight - pts[0].Y);
            for (int pi = 1; pi < pts.Length; pi++)
            {
                cb.LineTo(pts[pi].X, _pSize.yHeight - pts[pi].Y);
            }
        }
        return;
    }
    /// <summary>
    /// Page Rectangle element at the X Y position
    /// </summary>
    /// <returns></returns>
    private void iAddRectangle(float x, float y, float height, float width, StyleInfo si, string url, PdfPattern patterns, string tooltip)
    {
        // Draw background rectangle if needed
        if (!si.BackgroundColor.IsEmpty && height > 0 && width > 0)
        {   // background color, height and width are specified
            iAddFillRect(x, y, width, height, si, patterns);
        }

        iAddBorder(si, x, y, height, width);            // add any required border

        if (url != null)
            pdfdocument.Add(new Annotation(x, _pSize.yHeight - y, height, width, url));
        if (!string.IsNullOrEmpty(tooltip))
            pdfdocument.Add(new Annotation(x, _pSize.yHeight - y, height, width, tooltip));

        return;
    }

    /// <summary>
    /// Draw a pie
    /// </summary>
    /// <returns></returns>
    private void iAddPie(float x, float y, float height, float width, StyleInfo si, string url, PdfPattern patterns, string tooltip)
    {
        // Draw background rectangle if needed
        if (!si.BackgroundColor.IsEmpty && height > 0 && width > 0)
        {   // background color, height and width are specified
            iAddFillRect(x, y, width, height, si, patterns);
        }
        iAddBorder(si, x, y, height, width);            // add any required border

        //add url
        if (url != null)
            pdfdocument.Add(new Annotation(x, _pSize.yHeight - y, height, width, url));
        //add tooltip
        if (!string.IsNullOrEmpty(tooltip))
            pdfdocument.Add(new Annotation(x, _pSize.yHeight - y, height, width, tooltip));
        return;
    }

    /// <summary>
    /// Draw a curve
    /// </summary>
    /// <returns></returns>
    private void iAddCurve(PointF[] pts, StyleInfo si)
    {
        if (pts.Length > 2)
        {   // do a spline curve
            PointF[] tangents = iGetCurveTangents(pts);
            iDoCurve(pts, tangents, si);
        }
        else
        {   // we only have two points; just do a line segment
            iAddLine(pts[0].X, pts[0].Y, pts[1].X, pts[1].Y, si);
        }
    }

    private void iDoCurve(PointF[] points, PointF[] tangents, StyleInfo si)
    {
        int i;

        for (i = 0; i < points.Length - 1; i++)
        {
            int j = i + 1;

            float x0 = points[i].X;
            float y0 = points[i].Y;

            float x1 = points[i].X + tangents[i].X;
            float y1 = points[i].Y + tangents[i].Y;

            float x2 = points[j].X - tangents[j].X;
            float y2 = points[j].Y - tangents[j].Y;

            float x3 = points[j].X;
            float y3 = points[j].Y;
            iAddCurve(x0, y0, x1, y1, x2, y2, x3, y3, si, null);
        }
    }

    private PointF[] iGetCurveTangents(PointF[] points)
    {
        float tension = .5f;                 // This  is the tension used on the DrawCurve GDI call.
        float coefficient = tension / 3.0f;
        int i;

        PointF[] tangents = new PointF[points.Length];

        // initialize everything to zero to begin with
        for (i = 0; i < tangents.Length; i++)
        {
            tangents[i].X = 0;
            tangents[i].Y = 0;
        }

        if (tangents.Length <= 2)
            return tangents;
        int count = tangents.Length;
        for (i = 0; i < count; i++)
        {
            int r = i + 1;
            int s = i - 1;

            if (r >= points.Length)
                r = points.Length - 1;
            if (s < 0)
                s = 0;

            tangents[i].X += (coefficient * (points[r].X - points[s].X));
            tangents[i].Y += (coefficient * (points[r].Y - points[s].Y));
        }

        return tangents;
    }

    //25072008 GJL Draw a bezier curve
    private void iAddCurve(float X1, float Y1, float X2, float Y2, float X3, float Y3, float X4, float Y4, StyleInfo si, string url)
    {

        if (si.BStyleTop != BorderStyleEnum.None)
        {
            switch (si.BStyleTop)
            {
                case BorderStyleEnum.Dashed:
                    cb.SetLineDash(new float[] { '3', '2' }, 0);
                    break;
                case BorderStyleEnum.Dotted:
                    cb.SetLineDash(new float[] { '2' }, 0);
                    break;
                case BorderStyleEnum.Solid:
                default:
                    cb.SetLineDash(new float[] { }, 0);
                    break;
            }
            cb.SetRGBColorStroke(si.BColorTop.R, si.BColorTop.G, si.BColorTop.B);
        }

        if (!si.BackgroundColor.IsEmpty)
        {
            cb.SetRGBColorStrokeF(si.BackgroundColor.R, si.BackgroundColor.G, si.BackgroundColor.B);
        }
        cb.CurveTo(X1, _pSize.yHeight - Y1, X2, _pSize.yHeight - Y1, X3, _pSize.yHeight - Y3);
        if (si.BackgroundColor.IsEmpty)
            cb.ClosePathStroke();
        else
            cb.ClosePathFillStroke();
    }

    //25072008 GJL Draw 4 bezier curves to approximate a circle
    private void iAddEllipse(float x, float y, float height, float width, StyleInfo si, string url)
    {
        if (si.BStyleTop != BorderStyleEnum.None)
        {
            switch (si.BStyleTop)
            {
                case BorderStyleEnum.Dashed:
                    cb.SetLineDash(new float[] { '3', '2' }, 0);
                    break;
                case BorderStyleEnum.Dotted:
                    cb.SetLineDash(new float[] { '2' }, 0);
                    break;
                case BorderStyleEnum.Solid:
                default:
                    cb.SetLineDash(new float[] { }, 0);
                    break;
            }
            cb.SetRGBColorStroke(si.BColorTop.R, si.BColorTop.G, si.BColorTop.B);
        }
        float RadiusX = (width / 2.0f);
        float RadiusY = (height / 2.0f);
        cb.Ellipse(x, _pSize.yHeight - y, x + RadiusX, y + RadiusY);
        if (!si.BackgroundColor.IsEmpty)
        {
            cb.SetRGBColorStrokeF(si.BackgroundColor.R, si.BackgroundColor.G, si.BackgroundColor.B);
        }
        if (si.BackgroundColor.IsEmpty)
            cb.ClosePathStroke();
        else
            cb.ClosePathFillStroke();
    }
    /// <summary>
    /// Font name , for my application almost fonts  will be unicode and embedded
    /// </summary>
    /// <returns></returns>
    private string iFontNameNormalize(string face)
    {
        string faceName;
        switch (face.ToLower())
        {
            case "times":
            case "times-roman":
            case "times roman":
            case "timesnewroman":
            case "times new roman":
            case "timesnewromanps":
            case "timesnewromanpsmt":
            case "serif":
                faceName = "Times-Roman";
                break;
            case "helvetica":
            case "arial":
            case "arialmt":
            case "sans-serif":
            case "sans serif":
            default:
                faceName = "Arial";
                break;
            case "courier":
            case "couriernew":
            case "courier new":
            case "couriernewpsmt":
            case "monospace":
                faceName = "Courier New";
                break;
            case "symbol":
                faceName = "Symbol";
                break;
            case "zapfdingbats":
            case "wingdings":
            case "wingding":
                faceName = "ZapfDingbats";
                break;
        }
        return faceName;
    }
    /// <summary>
    /// Page Text element at the X Y position; multiple lines handled
    /// </summary>
    /// <returns></returns>
    private void iAddText(float x, float y, float height, float width, string[] sa,
        StyleInfo si, PdfFonts fonts, float[] tw, bool bWrap, string url, bool bNoClip, string tooltip)
    {

        string pdfFont = fonts.GetPdfFont(si);  // get the pdf font resource name
        BaseFont bf;
        string face = iFontNameNormalize(si.FontFamily);
        string fontname = "";
        bool fonttype1 = true;
        if (face == "Times-Roman")
        {
            if (si.IsFontBold() && si.FontStyle == FontStyleEnum.Italic)
            {
                face = "Times-BoldItalic";
                fontname = "\\timesbi.ttf";
            }
            else if (si.IsFontBold())
            {
                face = "Times-Bold";
                fontname = "\\timesbd.ttf";
            }
            else if (si.FontStyle == FontStyleEnum.Italic)
            {
                face = "Times-Italic";
                fontname = "\\timesi.ttf";
            }
            else
                fontname = "\\times.ttf";
            fonttype1 = false;
        }
        else
            if (face == "Arial")
            {
                if (si.IsFontBold() && si.FontStyle == FontStyleEnum.Italic)
                {
                    face = "Arial-BoldItalic";
                    fontname = "\\arialbi.ttf";

                }
                else if (si.IsFontBold())
                {
                    face = "Arial-Bold";
                    fontname = "\\arialbd.ttf";
                }
                else if (si.FontStyle == FontStyleEnum.Italic)
                {
                    face = "Arial-Italic";
                    fontname = "\\ariali.ttf";
                }
                else
                    fontname = "\\ariali.ttf";
                fonttype1 = false;
            }
            else
                if (face == "Courier New")
                {
                    if (si.IsFontBold() && si.FontStyle == FontStyleEnum.Italic)
                    {
                        face = "Courier New-BoldItalic";
                        fontname = "\\courbi.ttf";
                    }
                    else if (si.IsFontBold())
                    {
                        face = "Courier New-Bold";
                        fontname = "\\courbd.ttf";
                    }
                    else if (si.FontStyle == FontStyleEnum.Italic)
                    {
                        face = "Courier New-Italic";
                        fontname = "\\couri.ttf";
                    }
                    else
                        fontname = "\\cour.ttf";
                    fonttype1 = false;
                }
                else
                {
                    if (si.IsFontBold() &&
                si.FontStyle == FontStyleEnum.Italic)   // bold and italic?
                        face = face + "-BoldOblique";
                    else if (si.IsFontBold())           // just bold?
                        face = face + "-Bold";
                    else if (si.FontStyle == FontStyleEnum.Italic)
                        face = face + "-Oblique";
                    fonttype1 = true;
                }
        //Get index of fontname in List font name
        int indexbf = BaseFontsname.FindIndex(delegate(string _fontname) { return _fontname == face; });
        //If not found then add new BaseFont
        if (indexbf == -1)
        {
            BaseFontsname.Add(face);
            if (fonttype1)
            {
                bf = BaseFont.CreateFont(face, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
            }
            else
            {
                //I uses font embedded in current folder the RdlEngine.dll in.
                string path = Path.GetDirectoryName(this.GetType().Assembly.Location)+"\\Fonts";
                //If manual set FontFolder, use it
        if (r.FontFolder != "")
                    path = r.FontFolder;
                bf = BaseFont.CreateFont(path + fontname, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            }
            BaseFonts.Add(bf);
        }
        else
        //Get from List
        {
            bf = BaseFonts[indexbf];
        }

        // Loop thru the lines of text
        for (int i = 0; i < sa.Length; i++)
        {
            string text = sa[i];
            float textwidth = tw[i];
            // Calculate the x position
            float startX = x + si.PaddingLeft;                      // TODO: handle tb_rl
            float startY = y + si.PaddingTop + (i * si.FontSize);   // TODO: handle tb_rl
            int align = 0;
            if (si.WritingMode == WritingModeEnum.lr_tb)
            {   // TODO: not sure what alignment means with tb_lr so I'll leave it out for now
                switch (si.TextAlign)
                {
                    case TextAlignEnum.Center:
                        if (width > 0)
                        {
                            startX = x + si.PaddingLeft + (width - si.PaddingLeft - si.PaddingRight) / 2 - textwidth / 2;
                            align = Element.ALIGN_CENTER;
                        }
                        break;
                    case TextAlignEnum.Right:
                        if (width > 0)
                        {
                            startX = x + width - textwidth - si.PaddingRight;
                            align = Element.ALIGN_RIGHT;
                        }
                        break;
                    case TextAlignEnum.Left:
                    default:
                        align = Element.ALIGN_LEFT;
                        break;
                }

                // Calculate the y position
                switch (si.VerticalAlign)
                {
                    case VerticalAlignEnum.Middle:
                        if (height <= 0)
                            break;

                        // calculate the middle of the region
                        startY = y + si.PaddingTop + (height - si.PaddingTop - si.PaddingBottom) / 2 - si.FontSize / 2;
                        // now go up or down depending on which line
                        if (sa.Length == 1)
                            break;
                        if (sa.Length % 2 == 0) // even number
                        {
                            startY = startY - ((sa.Length / 2 - i) * si.FontSize) + si.FontSize / 2;
                        }
                        else
                        {
                            startY = startY - ((sa.Length / 2 - i) * si.FontSize);
                        }
                        break;
                    case VerticalAlignEnum.Bottom:
                        if (height <= 0)
                            break;

                        startY = y + height - si.PaddingBottom - (si.FontSize * (sa.Length - i));
                        break;
                    case VerticalAlignEnum.Top:
                    default:
                        break;
                }
            }
            else
            {
                //25072008 GJL - Move x in a little - it draws to close to the edge of the rectangle (25% of the font size seems to work!) and Center or right align vertical text
                startX += si.FontSize / 4;

                switch (si.TextAlign)
                {
                    case TextAlignEnum.Center:
                        if (height > 0)
                            startY = y + si.PaddingLeft + (height - si.PaddingLeft - si.PaddingRight) / 2 - textwidth / 2;
                        break;
                    case TextAlignEnum.Right:
                        if (width > 0)
                            startY = y + height - textwidth - si.PaddingRight;
                        break;
                    case TextAlignEnum.Left:
                    default:
                        break;
                }

            }

            // Draw background rectangle if needed (only put out on the first line, since we do whole rectangle)
            if (!si.BackgroundColor.IsEmpty && height > 0 && width > 0 && i == 0)
            {   // background color, height and width are specified
                iAddFillRect(x, y, width, height, si.BackgroundColor);
            }

            // Set the clipping path, (Itext have no clip)
            if (height > 0 && width > 0)
            {
                cb.SetRGBColorFill(si.Color.R, si.Color.G, si.Color.B);

                if (si.WritingMode == WritingModeEnum.lr_tb)
                {
                    //If textline after measure with word break can fit just simple show Text
                    if (width >= textwidth)
                    {
                        cb.BeginText();
                        cb.SetFontAndSize(bf, si.FontSize);
                        cb.SetTextMatrix(startX, (_pSize.yHeight - startY - si.FontSize));
                        cb.ShowText(text);
                        cb.EndText();
                    }
                    else
                    {                            
                        //else use Column text to wrap or clip (wrap: for example a text like an URL so word break is not working here, itextsharp ColumnText do the work for us)
                        ColumnText ct = new ColumnText(cb);
                        Phrase myPhrase = new Phrase(text, new iTextSharp.text.Font(bf, si.FontSize));
                        ct.SetSimpleColumn(myPhrase, x + si.PaddingLeft, _pSize.yHeight - startY, x + width - si.PaddingRight, _pSize.yHeight - y - si.PaddingBottom - height, 10f, align);
                        ct.Go();
                    }
                }
                else
                {
                    //Not checked
                    double rads = -283.0 / 180.0;
                    double radsCos = Math.Cos(rads);
                    double radsSin = Math.Sin(rads);
                    cb.BeginText();
                    cb.SetFontAndSize(bf, si.FontSize);
                    cb.SetTextMatrix((float)radsCos, (float)radsSin, (float)-radsSin, (float)radsCos, startX, _pSize.yHeight - startY);
                    cb.ShowText(text);
                    cb.EndText();
                }


                //add URL
                if (url != null)
                    pdfdocument.Add(new Annotation(x, _pSize.yHeight - y, height, width, url));
                //add tooltip
                if (tooltip != null)
                    pdfdocument.Add(new Annotation(x, _pSize.yHeight - y, height, width, tooltip));

            }

            // Handle underlining etc.
            float maxX;
            switch (si.TextDecoration)
            {
                case TextDecorationEnum.Underline:
                    maxX = width > 0 ? Math.Min(x + width, startX + textwidth) : startX + textwidth;
                    iAddLine(startX, startY + si.FontSize + 1, maxX, startY + si.FontSize + 1, 1, si.Color, BorderStyleEnum.Solid);
                    break;
                case TextDecorationEnum.LineThrough:
                    maxX = width > 0 ? Math.Min(x + width, startX + textwidth) : startX + textwidth;
                    iAddLine(startX, startY + (si.FontSize / 2) + 1, maxX, startY + (si.FontSize / 2) + 1, 1, si.Color, BorderStyleEnum.Solid);
                    break;
                case TextDecorationEnum.Overline:
                    maxX = width > 0 ? Math.Min(x + width, startX + textwidth) : startX + textwidth;
                    iAddLine(startX, startY + 1, maxX, startY + 1, 1, si.Color, BorderStyleEnum.Solid);
                    break;
                case TextDecorationEnum.None:
                default:
                    break;
            }
        }

        iAddBorder(si, x, y, height, width);            // add any required border

        return;
    }
    #endregion
    public RenderPdf(Report rep, IStreamGen sg)
    {
        r = rep;
        tw = sg.GetStream();
    }

    public Report Report()
    {
        return r;
    }

    public bool IsPagingNeeded()
    {
        return true;
    }

    public void Start()
    {
        // Create the anchor for all pdf objects
        CompressionConfig cc = RdlEngineConfig.GetCompression();
        anchor = new PdfAnchor(cc != null);

        //Create a PdfCatalog
        string lang;
        if (r.ReportDefinition.Language != null)
            lang = r.ReportDefinition.Language.EvaluateString(this.r, null);
        else
            lang = null;
        catalog = new PdfCatalog(anchor, lang);

        //Create a Page Tree Dictionary
        pageTree = new PdfPageTree(anchor);

        //Create a Font Dictionary
        fonts = new PdfFonts(anchor);

        //Create a Pattern Dictionary
        patterns = new PdfPattern(anchor);

        //Create an Image Dictionary
        images = new PdfImages(anchor);

        //Create an Outline Dictionary
        outline = new PdfOutline(anchor);

        //Create the info Dictionary
        info = new PdfInfo(anchor);

        //Set the info Dictionary. 
        info.SetInfo(r.Name, r.Author, r.Description, "");  // title, author, subject, company

        //Create a utility object
        pdfUtility = new PdfUtility(anchor);

        //write out the header
        int size = 0;
        #region ItextsharpPDF handler
        if (r.ItextPDF)
        {                
            PdfWriter writer = PdfWriter.GetInstance(pdfdocument, ms);
            pdfdocument.Open();
            cb = writer.DirectContent;
            pdfdocument.AddAuthor(r.Author);
            pdfdocument.AddCreationDate();
            pdfdocument.AddCreator("RDL fyiReporting");
            pdfdocument.AddSubject(r.Description);
            pdfdocument.AddTitle(r.Name);

        }
        else
            tw.Write(pdfUtility.GetHeader("1.5", out size), 0, size);
        #endregion
        //
        filesize = size;
    }

    public void End()
    {
        //Write everything 
        int size = 0;
        #region ItextsharpPDF handler
        if (r.ItextPDF)
        {
            if (outline.Bookmarks.Count > 0)
            {
                //Not handler 
            }
            pdfdocument.Close();
            //write out ItextSharp pdf stream to RDL stream
            byte[] contentbyte = ms.GetBuffer();
            tw.Write(contentbyte, 0, contentbyte.Length);
            ms.Dispose();
            BaseFonts.Clear();
            BaseFontsname.Clear();
        }
        else
        {
            tw.Write(catalog.GetCatalogDict(outline.GetObjectNumber(), pageTree.objectNum,
                filesize, out size), 0, size);
            filesize += size;
            tw.Write(pageTree.GetPageTree(filesize, out size), 0, size);
            filesize += size;
            tw.Write(fonts.GetFontDict(filesize, out size), 0, size);
            filesize += size;
            tw.Write(patterns.GetPatternDict(filesize, out size), 0, size);
            filesize += size;

            if (images.Images.Count > 0)
            {
                tw.Write(images.GetImageDict(filesize, out size), 0, size);
                filesize += size;
            }
            if (outline.Bookmarks.Count > 0)
            {
                tw.Write(outline.GetOutlineDict(filesize, out size), 0, size);
                filesize += size;
            }

            tw.Write(info.GetInfoDict(filesize, out size), 0, size);
            filesize += size;

            tw.Write(pdfUtility.CreateXrefTable(filesize, out size), 0, size);
            filesize += size;

            tw.Write(pdfUtility.GetTrailer(catalog.objectNum,
                info.objectNum, out size), 0, size);
            filesize += size;
        }
        #endregion
        return;
    }

    public void RunPages(Pages pgs) // this does all the work
    {
        foreach (Page p in pgs)
        {
            //Create a Page Dictionary representing a visible page
            page = new PdfPage(anchor);
            content = new PdfContent(anchor);

            PdfPageSize pSize = new PdfPageSize((int)r.ReportDefinition.PageWidth.Points,
                                (int)r.ReportDefinition.PageHeight.Points);
            _pSize = pSize;
            page.CreatePage(pageTree.objectNum, pSize);
            pageTree.AddPage(page.objectNum);
            #region ItextsharpPDF handler
            if (r.ItextPDF)
            {
                //Itextsharp pdf handler, set pagesize
                pdfdocument.SetPageSize(new iTextSharp.text.Rectangle(r.ReportDefinition.PageWidth.Points, r.ReportDefinition.PageHeight.Points));
                pdfdocument.NewPage();
            }
            #endregion
            //Create object that presents the elements in the page
            elements = new PdfElements(page, pSize);

            ProcessPage(pgs, p);

            // after a page
            content.SetStream(elements.EndElements());

            page.AddResource(fonts, content.objectNum);
            page.AddResource(patterns, content.objectNum);
            //get the pattern colorspace...
            PatternObj po = new PatternObj(anchor);
            page.AddResource(po, content.objectNum);
            if (r.ItextPDF == false)
            {
                int size = 0;
                tw.Write(page.GetPageDict(filesize, out size), 0, size);
                filesize += size;

                tw.Write(content.GetContentDict(filesize, out size), 0, size);
                filesize += size;

                tw.Write(po.GetPatternObj(filesize, out size), 0, size);
                filesize += size;
            }
        }
        return;
    }
    // render all the objects in a page in PDF
    private void ProcessPage(Pages pgs, IEnumerable items)
    {
        foreach (PageItem pi in items)
        {
            if (pi.SI.BackgroundImage != null)
            {   // put out any background image
                PageImage bgImg = pi.SI.BackgroundImage;
                //                  elements.AddImage(images, i.Name, content.objectNum, i.SI, i.ImgFormat, 
                //                      pi.X, pi.Y, pi.W, pi.H, i.ImageData,i.SamplesW, i.SamplesH, null);                   
                //Duc Phan modified 10 Dec, 2007 to support on background image 
                float imW = RSize.PointsFromPixels(pgs.G, bgImg.SamplesW);
                float imH = RSize.PointsFromPixels(pgs.G, bgImg.SamplesH);
                int repeatX = 0;
                int repeatY = 0;
                float itemW = pi.W - (pi.SI.PaddingLeft + pi.SI.PaddingRight);
                float itemH = pi.H - (pi.SI.PaddingTop + pi.SI.PaddingBottom);
                switch (bgImg.Repeat)
                {
                    case ImageRepeat.Repeat:
                        repeatX = (int)Math.Floor(itemW / imW);
                        repeatY = (int)Math.Floor(itemH / imH);
                        break;
                    case ImageRepeat.RepeatX:
                        repeatX = (int)Math.Floor(itemW / imW);
                        repeatY = 1;
                        break;
                    case ImageRepeat.RepeatY:
                        repeatY = (int)Math.Floor(itemH / imH);
                        repeatX = 1;
                        break;
                    case ImageRepeat.NoRepeat:
                    default:
                        repeatX = repeatY = 1;
                        break;
                }

                //make sure the image is drawn at least 1 times 
                repeatX = Math.Max(repeatX, 1);
                repeatY = Math.Max(repeatY, 1);

                float currX = pi.X + pi.SI.PaddingLeft;
                float currY = pi.Y + pi.SI.PaddingTop;
                float startX = currX;
                float startY = currY;
                for (int i = 0; i < repeatX; i++)
                {
                    for (int j = 0; j < repeatY; j++)
                    {
                        currX = startX + i * imW;
                        currY = startY + j * imH;
                        elements.AddImage(images, bgImg.Name,
                                          content.objectNum, bgImg.SI, bgImg.ImgFormat,
                                          currX, currY, imW, imH, RectangleF.Empty, bgImg.ImageData, bgImg.SamplesW, bgImg.SamplesH, null, pi.Tooltip);
                        #region Itextsharp pdf handler
                        if (r.ItextPDF)
                        {

                            iAddImage(images, bgImg.Name,
                                          content.objectNum, bgImg.SI, bgImg.ImgFormat,
                                          currX, currY, imW, imH, RectangleF.Empty, bgImg.ImageData, bgImg.SamplesW, bgImg.SamplesH, null, pi.Tooltip);
                        }
                        #endregion
                    }
                }
            }

            if (pi is PageTextHtml)
            {
                PageTextHtml pth = pi as PageTextHtml;
                pth.Build(pgs.G);
                ProcessPage(pgs, pth);
                continue;
            }

            if (pi is PageText)
            {
                PageText pt = pi as PageText;
                float[] textwidth;
                string[] sa = MeasureString(pt, pgs.G, out textwidth);
                elements.AddText(pt.X, pt.Y, pt.H, pt.W, sa, pt.SI,
                    fonts, textwidth, pt.CanGrow, pt.HyperLink, pt.NoClip, pt.Tooltip);
                #region Itextsharp pdf handler
                if (r.ItextPDF)
                {
                    iAddText(pt.X, pt.Y, pt.H, pt.W, sa, pt.SI,
                    fonts, textwidth, pt.CanGrow, pt.HyperLink, pt.NoClip, pt.Tooltip);
                }
                #endregion
                if (pt.Bookmark != null)
                {
                    outline.Bookmarks.Add(new PdfOutlineEntry(anchor, page.objectNum, pt.Bookmark, pt.X, elements.PageSize.yHeight - pt.Y));
                }
                continue;
            }

            if (pi is PageLine)
            {
                PageLine pl = pi as PageLine;
                elements.AddLine(pl.X, pl.Y, pl.X2, pl.Y2, pl.SI);
                #region Itextsharp pdf handler
                if (r.ItextPDF)
                {
                    iAddLine(pl.X, pl.Y, pl.X2, pl.Y2, pl.SI);
                }
                #endregion
                continue;
            }

            if (pi is PageEllipse)
            {
                PageEllipse pe = pi as PageEllipse;
                elements.AddEllipse(pe.X, pe.Y, pe.H, pe.W, pe.SI, pe.HyperLink);
                #region Itextsharp pdf handler
                if (r.ItextPDF)
                {
                    iAddEllipse(pe.X, pe.Y, pe.H, pe.W, pe.SI, pe.HyperLink);
                }
                #endregion
                continue;
            }



            if (pi is PageImage)
            {
                //PageImage i = pi as PageImage;
                //float x = i.X + i.SI.PaddingLeft;
                //float y = i.Y + i.SI.PaddingTop;
                //float w = i.W - i.SI.PaddingLeft - i.SI.PaddingRight;
                //float h = i.H - i.SI.PaddingTop - i.SI.PaddingBottom;
                //elements.AddImage(images, i.Name, content.objectNum, i.SI, i.ImgFormat, 
                //    x, y, w, h, i.ImageData,i.SamplesW, i.SamplesH, i.HyperLink);
                //continue;
                PageImage i = pi as PageImage;

                //Duc Phan added 20 Dec, 2007 to support sized image 
                RectangleF r2 = new RectangleF(i.X + i.SI.PaddingLeft, i.Y + i.SI.PaddingTop, i.W - i.SI.PaddingLeft - i.SI.PaddingRight, i.H - i.SI.PaddingTop - i.SI.PaddingBottom);

                RectangleF adjustedRect;   // work rectangle 
                RectangleF clipRect = RectangleF.Empty;
                switch (i.Sizing)
                {
                    case ImageSizingEnum.AutoSize:
                        adjustedRect = new RectangleF(r2.Left, r2.Top,
                                      r2.Width, r2.Height);
                        break;
                    case ImageSizingEnum.Clip:
                        adjustedRect = new RectangleF(r2.Left, r2.Top,
                                       RSize.PointsFromPixels(pgs.G, i.SamplesW), RSize.PointsFromPixels(pgs.G, i.SamplesH));
                        clipRect = new RectangleF(r2.Left, r2.Top,
                                      r2.Width, r2.Height);
                        break;
                    case ImageSizingEnum.FitProportional:
                        float height;
                        float width;
                        float ratioIm = (float)i.SamplesH / i.SamplesW;
                        float ratioR = r2.Height / r2.Width;
                        height = r2.Height;
                        width = r2.Width;
                        if (ratioIm > ratioR)
                        {   // this means the rectangle width must be corrected 
                            width = height * (1 / ratioIm);
                        }
                        else if (ratioIm < ratioR)
                        {   // this means the rectangle height must be corrected 
                            height = width * ratioIm;
                        }
                        adjustedRect = new RectangleF(r2.X, r2.Y, width, height);
                        break;
                    case ImageSizingEnum.Fit:
                    default:
                        adjustedRect = r2;
                        break;
                }
                if (i.ImgFormat == System.Drawing.Imaging.ImageFormat.Wmf || i.ImgFormat == System.Drawing.Imaging.ImageFormat.Emf)
                {
                    //We dont want to add it - its already been broken down into page items;
                }
                else
                {
                    elements.AddImage(images, i.Name, content.objectNum, i.SI, i.ImgFormat,
                       adjustedRect.X, adjustedRect.Y, adjustedRect.Width, adjustedRect.Height, clipRect, i.ImageData, i.SamplesW, i.SamplesH, i.HyperLink, i.Tooltip);
                    #region Itextsharp pdf handler
                    if (r.ItextPDF)
                    {
                        iAddImage(images, i.Name, content.objectNum, i.SI, i.ImgFormat,
                        adjustedRect.X, adjustedRect.Y, adjustedRect.Width, adjustedRect.Height, clipRect, i.ImageData, i.SamplesW, i.SamplesH, i.HyperLink, i.Tooltip);
                    }
                    #endregion
                }
                continue;
            }

            if (pi is PageRectangle)
            {
                PageRectangle pr = pi as PageRectangle;
                elements.AddRectangle(pr.X, pr.Y, pr.H, pr.W, pi.SI, pi.HyperLink, patterns, pi.Tooltip);
                #region Itextsharp pdf handler
                if (r.ItextPDF)
                {
                    iAddRectangle(pr.X, pr.Y, pr.H, pr.W, pi.SI, pi.HyperLink, patterns, pi.Tooltip);
                }
                #endregion
                continue;
            }
            if (pi is PagePie)
            {   // TODO
                PagePie pp = pi as PagePie;
                // elements.AddPie(pr.X, pr.Y, pr.H, pr.W, pi.SI, pi.HyperLink, patterns, pi.Tooltip);
                #region Itextsharp pdf handler
                if (r.ItextPDF)
                {
                    iAddPie(pp.X, pp.Y, pp.H, pp.W, pi.SI, pi.HyperLink, patterns, pi.Tooltip);
                }
                #endregion
                continue;
            }
            if (pi is PagePolygon)
            {
                PagePolygon ppo = pi as PagePolygon;
                elements.AddPolygon(ppo.Points, pi.SI, pi.HyperLink, patterns);
                #region Itextsharp pdf handler
                if (r.ItextPDF)
                {
                    iAddPolygon(ppo.Points, pi.SI, pi.HyperLink, patterns);
                }
                #endregion
                continue;
            }
            if (pi is PageCurve)
            {
                PageCurve pc = pi as PageCurve;
                elements.AddCurve(pc.Points, pi.SI);
                #region Itextsharp pdf handler
                if (r.ItextPDF)
                {
                    iAddCurve(pc.Points, pi.SI);
                }
                #endregion
                continue;
            }

        }

    }

    private string[] MeasureString(PageText pt, Graphics g, out float[] width)
    {
        StyleInfo si = pt.SI;
        string s = pt.Text;

        System.Drawing.Font drawFont = null;
        StringFormat drawFormat = null;
        SizeF ms;
        string[] sa = null;
        width = null;
        try
        {
            // STYLE
            System.Drawing.FontStyle fs = 0;
            if (si.FontStyle == FontStyleEnum.Italic)
                fs |= System.Drawing.FontStyle.Italic;

            // WEIGHT
            switch (si.FontWeight)
            {
                case FontWeightEnum.Bold:
                case FontWeightEnum.Bolder:
                case FontWeightEnum.W500:
                case FontWeightEnum.W600:
                case FontWeightEnum.W700:
                case FontWeightEnum.W800:
                case FontWeightEnum.W900:
                    fs |= System.Drawing.FontStyle.Bold;
                    break;
                default:
                    break;
            }

            drawFont = new System.Drawing.Font(StyleInfo.GetFontFamily(si.FontFamilyFull), si.FontSize, fs);
            drawFormat = new StringFormat();
            drawFormat.Alignment = StringAlignment.Near;

            // Measure string   
            //  pt.NoClip indicates that this was generated by PageTextHtml Build.  It has already word wrapped.
            if (pt.NoClip || pt.SI.WritingMode == WritingModeEnum.tb_rl)    // TODO: support multiple lines for vertical text
            {
                ms = MeasureString(s, g, drawFont, drawFormat);
                width = new float[1];
                width[0] = RSize.PointsFromPixels(g, ms.Width); // convert to points from pixels
                sa = new string[1];
                sa[0] = s;
                return sa;
            }

            // handle multiple lines;
            //  1) split the string into the forced line breaks (ie "\n and \r")
            //  2) foreach of the forced line breaks; break these into words and recombine 
            s = s.Replace("\r\n", "\n");    // don't want this to result in double lines
            string[] flines = s.Split(lineBreak);
            List<string> lines = new List<string>();
            List<float> lineWidths = new List<float>();
            // remove the size reserved for left and right padding
            float ptWidth = pt.W - pt.SI.PaddingLeft - pt.SI.PaddingRight;
            if (ptWidth <= 0)
                ptWidth = 1;
            foreach (string tfl in flines)
            {
                string fl;
                if (tfl.Length > 0 && tfl[tfl.Length - 1] == ' ')
                    fl = tfl.TrimEnd(' ');
                else
                    fl = tfl;

                // Check if entire string fits into a line
                ms = MeasureString(fl, g, drawFont, drawFormat);
                float tw = RSize.PointsFromPixels(g, ms.Width);
                if (tw <= ptWidth)
                {                       // line fits don't need to break it down further
                    lines.Add(fl);
                    lineWidths.Add(tw);
                    continue;
                }

                // Line too long; need to break into multiple lines
                // 1) break line into parts; then build up again keeping track of word positions
                string[] parts = fl.Split(wordBreak);   // this is the maximum split of lines
                StringBuilder sb = new StringBuilder(fl.Length);
                CharacterRange[] cra = new CharacterRange[parts.Length];
                for (int i = 0; i < parts.Length; i++)
                {
                    int sc = sb.Length;     // starting character
                    sb.Append(parts[i]);    // endding character
                    if (i != parts.Length - 1)  // last item doesn't need blank
                        sb.Append(" ");
                    int ec = sb.Length;
                    CharacterRange cr = new CharacterRange(sc, ec - sc);
                    cra[i] = cr;            // add to character array
                }

                // 2) Measure the word locations within the line
                string wfl = sb.ToString();
                WordStartFinish[] wordLocations = MeasureString(wfl, g, drawFont, drawFormat, cra);
                if (wordLocations == null)
                    continue;

                // 3) Loop thru creating new lines as needed
                int startLoc = 0;
                CharacterRange crs = cra[startLoc];
                CharacterRange cre = cra[startLoc];
                float cwidth = wordLocations[0].end;    // length of the first
                float bwidth = wordLocations[0].start;  // characters need a little extra on start
                string ts;
                bool bLine = true;
                for (int i = 1; i < cra.Length; i++)
                {
                    cwidth = wordLocations[i].end - wordLocations[startLoc].start + bwidth;
                    if (cwidth > ptWidth)
                    {   // time for a new line
                        cre = cra[i - 1];
                        ts = wfl.Substring(crs.First, cre.First + cre.Length - crs.First);
                        lines.Add(ts);
                        lineWidths.Add(wordLocations[i - 1].end - wordLocations[startLoc].start + bwidth);

                        // Find the first non-blank character of the next line
                        while (i < cra.Length &&
                                cra[i].Length == 1 &&
                                fl[cra[i].First] == ' ')
                        {
                            i++;
                        }
                        if (i < cra.Length)   // any lines left?
                        {  // yes, continue on
                            startLoc = i;
                            crs = cre = cra[startLoc];
                            cwidth = wordLocations[i].end - wordLocations[startLoc].start + bwidth;
                        }
                        else  // no, we can stop
                            bLine = false;
                        //  bwidth = wordLocations[startLoc].start - wordLocations[startLoc - 1].end;
                    }
                    else
                        cre = cra[i];
                }
                if (bLine)
                {
                    ts = fl.Substring(crs.First, cre.First + cre.Length - crs.First);
                    lines.Add(ts);
                    lineWidths.Add(cwidth);
                }
            }
            // create the final array from the Lists
            string[] la = lines.ToArray();
            width = lineWidths.ToArray();
            return la;
        }
        finally
        {
            if (drawFont != null)
                drawFont.Dispose();
            if (drawFormat != null)
                drawFont.Dispose();
        }
    }

    /// <summary>
    /// Measures the location of an arbritrary # of words within a string
    /// </summary>
    private WordStartFinish[] MeasureString(string s, Graphics g, System.Drawing.Font drawFont, StringFormat drawFormat, CharacterRange[] cra)
    {
        if (cra.Length <= MEASUREMAX)       // handle the simple case of < MEASUREMAX words
            return MeasureString32(s, g, drawFont, drawFormat, cra);

        // Need to compensate for SetMeasurableCharacterRanges limitation of 32 (MEASUREMAX)
        int mcra = (cra.Length / MEASUREMAX);   // # of full 32 arrays we need
        int ip = cra.Length % MEASUREMAX;       // # of partial entries needed for last array (if any)
        WordStartFinish[] sz = new WordStartFinish[cra.Length]; // this is the final result;
        float startPos = 0;
        CharacterRange[] cra32 = new CharacterRange[MEASUREMAX];    // fill out         
        int icra = 0;                       // index thru the cra 
        for (int i = 0; i < mcra; i++)
        {
            // fill out the new array
            int ticra = icra;
            for (int j = 0; j < cra32.Length; j++)
            {
                cra32[j] = cra[ticra++];
                cra32[j].First -= cra[icra].First;  // adjust relative offsets of strings
            }

            // measure the word locations (in the new string)
            // ???? should I put a blank in front of it?? 
            string ts = s.Substring(cra[icra].First,
                cra[icra + cra32.Length - 1].First + cra[icra + cra32.Length - 1].Length - cra[icra].First);
            WordStartFinish[] pos = MeasureString32(ts, g, drawFont, drawFormat, cra32);

            // copy the values adding in the new starting positions
            for (int j = 0; j < pos.Length; j++)
            {
                sz[icra].start = pos[j].start + startPos;
                sz[icra++].end = pos[j].end + startPos;
            }
            startPos = sz[icra - 1].end;    // reset the start position for the next line
        }
        // handle the remaining character
        if (ip > 0)
        {
            // resize the range array
            cra32 = new CharacterRange[ip];
            // fill out the new array
            int ticra = icra;
            for (int j = 0; j < cra32.Length; j++)
            {
                cra32[j] = cra[ticra++];
                cra32[j].First -= cra[icra].First;  // adjust relative offsets of strings
            }
            // measure the word locations (in the new string)
            // ???? should I put a blank in front of it?? 
            string ts = s.Substring(cra[icra].First,
                cra[icra + cra32.Length - 1].First + cra[icra + cra32.Length - 1].Length - cra[icra].First);
            WordStartFinish[] pos = MeasureString32(ts, g, drawFont, drawFormat, cra32);

            // copy the values adding in the new starting positions
            for (int j = 0; j < pos.Length; j++)
            {
                sz[icra].start = pos[j].start + startPos;
                sz[icra++].end = pos[j].end + startPos;
            }
        }
        return sz;
    }

    /// <summary>
    /// Measures the location of words within a string;  limited by .Net 1.1 to 32 words
    ///     MEASUREMAX is a constant that defines that limit
    /// </summary>
    /// <param name="s"></param>
    /// <param name="g"></param>
    /// <param name="drawFont"></param>
    /// <param name="drawFormat"></param>
    /// <param name="cra"></param>
    /// <returns></returns>
    private WordStartFinish[] MeasureString32(string s, Graphics g, System.Drawing.Font drawFont, StringFormat drawFormat, CharacterRange[] cra)
    {
        if (s == null || s.Length == 0)
            return null;

        drawFormat.SetMeasurableCharacterRanges(cra);
        Region[] rs = new Region[cra.Length];
        rs = g.MeasureCharacterRanges(s, drawFont, new RectangleF(0, 0, float.MaxValue, float.MaxValue),
            drawFormat);
        WordStartFinish[] sz = new WordStartFinish[cra.Length];
        int isz = 0;
        foreach (Region r in rs)
        {
            RectangleF mr = r.GetBounds(g);
            sz[isz].start = RSize.PointsFromPixels(g, mr.Left);
            sz[isz].end = RSize.PointsFromPixels(g, mr.Right);
            isz++;
        }
        return sz;
    }

    struct WordStartFinish
    {
        internal float start;
        internal float end;
    }

    private SizeF MeasureString(string s, Graphics g, System.Drawing.Font drawFont, StringFormat drawFormat)
    {
        if (s == null || s.Length == 0)
            return SizeF.Empty;

        CharacterRange[] cr = { new CharacterRange(0, s.Length) };
        drawFormat.SetMeasurableCharacterRanges(cr);
        Region[] rs = new Region[1];
        rs = g.MeasureCharacterRanges(s, drawFont, new RectangleF(0, 0, float.MaxValue, float.MaxValue),
            drawFormat);
        RectangleF mr = rs[0].GetBounds(g);

        return new SizeF(mr.Width, mr.Height);
    }

    private float MeasureStringBlank(Graphics g, System.Drawing.Font drawFont, StringFormat drawFormat)
    {
        SizeF ms = MeasureString(" ", g, drawFont, drawFormat);
        float width = RSize.PointsFromPixels(g, ms.Width);  // convert to points from pixels
        return width * 2;
    }

    // Body: main container for the report
    public void BodyStart(Body b)
    {
    }

    public void BodyEnd(Body b)
    {
    }

    public void PageHeaderStart(PageHeader ph)
    {
    }

    public void PageHeaderEnd(PageHeader ph)
    {
    }

    public void PageFooterStart(PageFoo

Max rows calculation is incorrect with Grouping

I found bug. If end of group gets on last row of page than new page created only with total rows and seems empty. And also in this case table footer row always show, even if repeat footer isn't sets.

Footer always shows because in line https://github.com/majorsilence/My-FyiReporting/blob/master/RdlEngine/Definition/Details.cs#L142 row compared with "end" variable, but end variable for grouping equally end of group, not table.
I think we need compare with rs.Data.Count - 1

But, in this case height of group footer is not counted too.

Translations

The web server, designer, and reader need to be changed to allow them to be translated into multiple languages.

More details will be added soon.

Field place holders in Expression builder

The values for User, Global, Fields are displaying in the expression builder (report | Value | Edit Expression) as place holders {!UserID}, {@pagenumber}, {numofdays} etc. they need to be changed so they insert the correct value such as =Fields!accepteduntil.Value.

Add support to directly render from Report class

The report class should be able to be used directly to create reports and export to pdf/excel/etc... if the program does not need to display on a viewer.

Provide an example in the wiki how to do this and if there are any code changes required make them.

Also include support for direct parameters on Report class. See #47 for an example of how they should work.

Report SetParameterValue Function

Add a new function SetParameterValue to make parameters easier to deal with. This will remove the need to concatenate a string together and feed it to the parameters property.

instead of

fyiReporting.RdlViewer.RdlViewer a = new fyiReporting.RdlViewer.RdlViewer();
a.Parameters = "Parameter1=value1&Parameter2=value2&Parameter3=value3";

also include support for

fyiReporting.RdlViewer.RdlViewer a = new fyiReporting.RdlViewer.RdlViewer();
a.SetParameterValue("Parameter1", "Value");
a.SetParameterValue("Parameter2", "Value");
a.SetParameterValue("Parameter3", "Value");

Unhandled Exception - DialogDatabase

The following exception is thrown when create a new report is clicked using the version 4.5.2-setup-my-fyiReporting-dot-net2-x86.msi package but not when debugging in visual studio.

It appears to be a problem with DialogDatabase.InitializeComponent.

************** Exception Text **************
System.InvalidCastException: Unable to cast object of type 'System.Windows.Forms.SplitContainer' to type 'System.ComponentModel.ISupportInitialize'.
at fyiReporting.RdlDesign.DialogDatabase.InitializeComponent()
at fyiReporting.RdlDesign.DialogDatabase..ctor(RdlDesigner rDesigner)
at fyiReporting.RdlDesign.RdlDesigner.menuFileNewReport_Click(Object sender, EventArgs e)
at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
at System.Windows.Forms.ToolStripButton.OnClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ToolStrip.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

************** Loaded Assemblies **************
mscorlib
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.5456 (Win7SP1GDR.050727-5400)

CodeBase: file:///C:/Windows/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll

RdlDesigner
Assembly Version: 4.5.4613.19357
Win32 Version: 4.5.4613.19357

CodeBase: file:///C:/Program%20Files%20(x86)/MajorSilence/MyFyiReporting/RdlDesigner.exe

System.Windows.Forms
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.5460 (Win7SP1GDR.050727-5400)

CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll

System
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.5456 (Win7SP1GDR.050727-5400)

CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll

System.Drawing
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.5462 (Win7SP1GDR.050727-5400)

CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll

RdlEngine
Assembly Version: 4.5.4613.19361
Win32 Version: 4.5.4613.19361

CodeBase: file:///C:/Program%20Files%20(x86)/MajorSilence/MyFyiReporting/RdlEngine.DLL

System.Xml
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.5420 (Win7SP1.050727-5400)

CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll

RdlViewer
Assembly Version: 4.5.4613.19362
Win32 Version: 4.5.4613.19362

CodeBase: file:///C:/Program%20Files%20(x86)/MajorSilence/MyFyiReporting/RdlViewer.DLL

PHP, Python, Ruby RdlCmd wrappers

Using output from https://github.com/majorsilence/My-FyiReporting/blob/master/Release-Builds/BundleRdlCmd.sh create a wrapper library in php, python, and ruby. Make it easy to use the reporting system on linux servers hosting web sites in any of those languages.

Basic testing has already been completed on dreamhost (debian 6) and it seems to be very reasonable.

Create a duplicate of the ReportServer server in php as an example of how to use My-FyiReporting with php.

Designer improvements

Hello!

I tried this out and it seems really nice! My only grips are with the designer... Maybe I'm just used to SSRS's designer, but it seems much more easy to play around especially with complicated reports. Here's a list of improvements I think would be nice to have:

  • Add a border around controls, even if said control has no real border. This would make it a lot easier to see controls. For example, if I have a empty rectangle in the report, it's impossible to see unless I click randomly on it. I would make it bigger when a control is selected. Right now if I want to move a rectangle for example, I have to get my mouse over a 1-pixel wide line and start dragging there
  • I really like the dot grid in SSRS. It makes it easier (along with control borders) to see what's going on in the report. When you see dots, there are no controls there.
  • It's tedious to select a table. Can you even select whole rows/columns?. In SSRS, when you are in a cell, there's a decorator around the table that allows you to select the whole table, rows or columns.
  • Along with the previous one, it would be nice if the table would get selected (instead of a group selection) when you drag-select a whole table
  • How do you resize a table? If I select the table (using the combox in the properties because it seems to be the only way), I can't drag the corners to resize it?
  • For the table control for example, there are not a lot of options in the property grid. I was looking for the NoRows and thought it was nowhere to be seen. It's really hard to right-click on the table and get to its properties (would be easier with a decorator around the table when it's selected). I can see more properties when I go into the popup, but they would be nice to have in the propertygrid. Maybe not all options - I would keep the options that add new rows for example (like the in "Include Table Rows") only in the popup.
  • When I use CTRL+Z to undo something, it would be nice if the things reverting back (for example if I was moving something) would become selected so I know what happened. I'm not even SSRS does this and can't check since I'm not at work, but right not undoing just seems a bit weird and I think that's the reason
  • I had an empty rectangle (unselected). If I try to drag it by clicking on it and dragging my mouse, my cursor is locked in the middle of the (now selected) rectangle :(
  • When I have a table and a rectangle next to it, when I drag around both controls to select them, only the textboxes in the table get selected. Ideally, only the table and rectangle would be selected.
  • Is there no places to see embeded code / referenced assemblies? (http://msdn.microsoft.com/en-us/library/ms159238.aspx)
  • It's a bit annoying when for example you add a new matrix, add a column. If you want to use the checkbox, the item has to be selected first even if you click directly on the checkbox

asp.net exports corrupted

When viewing a report using the asp.net control and the pdf, xml, or csv export option is selected the bottom of the file includes the pages html and corrupts the file.

This is on the ShowReport.aspx page in the report server and examples.

WPF compatibility issues on Windows 8

Our application is written in VB.NET and uses Windows Presentation Framework (WPF). While we have RdlDesigner working with our application, we would prefer to have it integrated directly, and we are wondering if there is a component of RdlDesigner that can be placed within WindowsFormHost - or else could you provide some hints on what would need to be changed to allow this?

fyiReporting being a C#.NET, WinForms application, the programs run and interact perfectly fine on Windows 7, Vista and XP.
However we have encountered some issues with RdlDesigner (forked off 4.3) on Windows 8 (64 bit, not tested on 32 bit).

Our program runs this code to open the RdlDesigner, modelessly:

_designer = New

fyiReporting.RdlDesign.RdlDesigner("AUSReportDesigner", False, True)
ElementHost.EnableModelessKeyboardInterop(Me)
_designer.Show()
_designer.OpenFile(filePath)
'add a handler to detect the save
AddHandler _designer.SavedFileEvent, AddressOf designer_SavedFileEvent
AddHandler _designer.FormClosed, AddressOf designer_ClosedEvent

The typical method of hosting a WinForms component in WPF is to use a WindowsFormHost adapter. Currently, this is not an option with RdlDesigner, as the form is a top-level form - however we would prefer to integrate RdlDesigner more directly, as we believe this will resolve the issues we encountered on Windows 8.

More specifically, the issues we are encountering on Windows 8 are as follows:

  1. Previewing a report for a second time will cause the designer to crash.
    The first time the report is previewed, everything appears correctly.
    However, after making any change on the design (to force a regeneration of the preview), then clicking the Preview tab, the designer will crash.
    This occurs whether the Report Designer is launched standalone (i.e. via the
    EXE) or through our program.
  2. Keyboard Input seems to be blocked after closing the Report Designer.
    When the Report Designer is closed via File > Exit, our WPF application stops listening to keyboard input. The user must restart our application to continue using the keyboard.
    This issue does not occur when the user presses the red X button on the top right of the window.

Due to the modeless launching of the Report Designer, our program is still responsive while the Report Designer is running. What is interesting to note is that our program still processes keyboard input while the Report Designer is running - it is only once it is closed that it stops responding.

You will notice that we added a line in the Report Designer launch code:

ElementHost.EnableModelessKeyboardInterop(Me)

This seems to have had a positive step towards resolving this issue, insofar as keyboard input is correctly registered for the WPF Window that launched the Report Designer. No other WPF windows will register input.

Please note again that this only occurs on Windows 8, which by default features .NET 4.5. On other Windows platforms we use .Net 4.

Thanks for your assistance.

Regards,
Tim

Viewer item click events

The RdlViewer control should support click events on all supported items. For example if a user clicks a textfield an event should be raised with the field name and value.

Report Server Improvments.

Update the report server to be useful. Add user accounts, authentication, themes. Fix the build script to create a zip deployment package ready to use with IIS/apache mod mono.

New Pages:

  • Signup
  • Change password
  • Admin roles (Create, Delete, Add Tags)
  • Admin permission tags (create, delete, link to reports)
  • Admin role users
  • Upload Reports

Edit Pages:

  • Report List

etc...

Needs a gtk# viewer

Currently the viewer is winforms and extremely ugly on Linux. A basic gtk# viewer should be included.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.