using System;
using System.Text;
using System.Drawing;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using FastReport.Utils;
using System.Globalization;
using FastReport.Format;
namespace FastReport.Export.Xml
{
///
/// Represents the Excel 2003 XML export filter.
///
public partial class XMLExport : ExportBase
{
#region Constants
private const int xLMaxHeight = 409;
private const float xdivider = 1.376f;
private const float ydivider = 1.333f;
#endregion
#region Private fields
private bool pageBreaks;
private string creator;
private bool dataOnly;
private bool wysiwyg;
private Dictionary sheets;
private ExportMatrix matrix;
private XMLSheet sh;
private bool splitPages;
private List commonStyles;
#endregion
private class XMLSheet
{
#region Constants
private const float margDiv = 25.4F;
#endregion
#region Private fields
private bool pageBreaks;
private readonly string name;
#endregion
internal readonly ExportMatrix matrix;
public void ExportSheet(Stream stream, StringBuilder builder)
{
int i, x, fx, fy, dx, dy;
ExportIEMObject Obj;
builder.AppendLine("");
// add table
builder.Append("");
for (x = 1; x < matrix.Width; x++)
builder.Append("");
WriteBuf(stream, builder);
for (int y = 0; y < matrix.Height - 1; y++)
{
builder.Append("");
for (x = 0; x < matrix.Width; x++)
{
i = matrix.Cell(x, y);
if (i != -1)
{
Obj = matrix.ObjectById(i);
if (Obj.Counter == 0)
{
builder.Append(" 1)
builder.Append("ss:MergeAcross=\"").Append(Convert.ToString(dx++ - 1)).Append("\" ");
if (dy > 1)
builder.Append("ss:MergeDown=\"").Append(Convert.ToString(dy++ - 1)).Append("\" ");
builder.Append("ss:StyleID=\"s").Append(Obj.StyleIndex.ToString()).AppendLine("\">");
decimal value = 0;
bool isNumeric = ExportUtils.ParseTextToDecimal(Obj.Text, Obj.Style.Format, out value);
string type = isNumeric ? "ss:Type=\"Number\"" : "ss:Type=\"String\"";
string data = Obj.HtmlTags ? "ss:Data" : "Data";
string xmlns = Obj.HtmlTags ? " xmlns=\"http://www.w3.org/TR/REC-html40\"" : String.Empty;
string strValue = isNumeric ?
Convert.ToString(value, CultureInfo.InvariantCulture.NumberFormat) :
ExportUtils.XmlString(Obj.Text, Obj.TextRenderType);
builder.Append("<").Append(data).Append(" ").Append(type).Append(xmlns).
Append(">").Append(strValue).Append("").Append(data).Append("> | ");
}
}
}
else
builder.Append(" | ");
}
builder.AppendLine("
");
if (builder.Length > 8192)
WriteBuf(stream, builder);
}
builder.AppendLine("
");
builder.AppendLine("");
if (matrix.PagesCount > 0)
{
builder.AppendLine("");
if (matrix.Landscape(0))
builder.AppendLine("");
builder.AppendLine(string.Format(CultureInfo.InvariantCulture, "",
matrix.PageBMargin(0) / margDiv,
matrix.PageLMargin(0) / margDiv,
matrix.PageRMargin(0) / margDiv,
matrix.PageTMargin(0) / margDiv));
builder.AppendLine("");
builder.AppendLine("");
builder.AppendLine("");
builder.AppendLine("" + matrix.RawPaperSize(0).ToString() + "");
builder.AppendLine("");
}
builder.AppendLine("");
// add page breaks
if (pageBreaks)
{
builder.AppendLine("");
builder.AppendLine("");
int page = 0;
for (i = 0; i <= matrix.Height - 1; i++)
{
if (matrix.YPosById(i) >= matrix.PageBreak(page))
{
builder.AppendLine("");
builder.AppendLine(string.Format("{0}
", i));
builder.AppendLine("");
page++;
}
}
builder.AppendLine("");
builder.AppendLine("");
}
builder.AppendLine("");
WriteBuf(stream, builder);
}
public XMLSheet(ExportMatrix matrix, string name, bool pageBreaks)
{
this.matrix = matrix;
this.name = name;
this.pageBreaks = pageBreaks;
}
}
#region Properties
///
/// Gets or sets a value that determines whether to insert page breaks in the output file or not.
///
///
public bool PageBreaks
{
get { return pageBreaks; }
set { pageBreaks = value; }
}
///
/// Gets or sets a value that determines whether the wysiwyg mode should be used
/// for better results.
///
///
/// Default value is true. In wysiwyg mode, the resulting Excel file will look
/// as close as possible to the prepared report. On the other side, it may have a lot
/// of small rows/columns, which will make it less editable. If you set this property
/// to false, the number of rows/columns in the resulting file will be decreased.
/// You will get less wysiwyg, but more editable file.
///
public bool Wysiwyg
{
get { return wysiwyg; }
set { wysiwyg = value; }
}
///
/// Gets or sets the name of document creator.
///
public string Creator
{
get { return creator; }
set { creator = value; }
}
///
/// Gets or sets a value that determines whether to export the databand rows only.
///
public bool DataOnly
{
get { return dataOnly; }
set { dataOnly = value; }
}
///
/// Each report page is placed on a new Excel page.
///
public bool SplitPages
{
get { return splitPages; }
set { splitPages = value; }
}
#endregion
#region Private Methods
private static void WriteBuf(Stream stream, StringBuilder buf)
{
// write the resulting string to a stream
byte[] bytes = Encoding.UTF8.GetBytes(buf.ToString());
stream.Write(bytes, 0, bytes.Length);
buf.Length = 0;
}
private void ExportHeader(StringBuilder builder)
{
builder.AppendLine("");
builder.AppendLine("");
builder.Append("");
builder.AppendLine("");
builder.Append("");
builder.AppendLine("");
builder.Append("").Append(Report.ReportInfo.Name).AppendLine("");
builder.Append("").Append(Report.ReportInfo.Author).AppendLine("");
builder.Append("").Append(SystemFake.DateTime.Now.Date.ToString()).Append("T").Append(SystemFake.DateTime.Now.TimeOfDay.ToString()).AppendLine("Z");
builder.Append("").Append(Report.ReportInfo.Version).AppendLine("");
builder.AppendLine("");
builder.AppendLine("");
builder.AppendLine("False");
builder.AppendLine("False");
builder.AppendLine("");
}
private void ExportSheets(Stream stream, StringBuilder builder)
{
foreach (XMLSheet sheet in sheets.Values)
sheet.ExportSheet(stream, builder);
builder.AppendLine("");
WriteBuf(stream, builder);
}
private void ExportXML(Stream stream)
{
StringBuilder builder = new StringBuilder(8448);
ExportHeader(builder);
ExportStyles(builder);
ExportSheets(stream, builder);
}
#endregion
#region StyleMethods
internal void ExportStyles(StringBuilder builder)
{
builder.AppendLine("");
ExportIEMStyle EStyle;
for (int x = 0; x < commonStyles.Count; x++)
{
EStyle = commonStyles[x];
builder.Append("");
}
builder.AppendLine("");
}
private string GetXMLWeight(float lineWeight)
{
float LineWeight = lineWeight * xdivider;
return ((int)Math.Round(LineWeight > 3 ? 3 : LineWeight)).ToString();
}
private string XmlAlign(HorzAlign horzAlign, VertAlign vertAlign, int angle)
{
string Fh = "Left", Fv = "Top";
if (angle == 0 || angle == 180)
{
if (horzAlign == HorzAlign.Left)
Fh = "Left";
else if (horzAlign == HorzAlign.Right)
Fh = "Right";
else if (horzAlign == HorzAlign.Center)
Fh = "Center";
else if (horzAlign == HorzAlign.Justify)
Fh = "Justify";
if (vertAlign == VertAlign.Top)
Fv = "Top";
else if (vertAlign == VertAlign.Bottom)
Fv = "Bottom";
else if (vertAlign == VertAlign.Center)
Fv = "Center";
}
else if (angle == 90)
{
if (horzAlign == HorzAlign.Left)
Fv = "Top";
else if (horzAlign == HorzAlign.Right)
Fv = "Bottom";
else if (horzAlign == HorzAlign.Center)
Fv = "Center";
if (vertAlign == VertAlign.Top)
Fh = "Right";
else if (vertAlign == VertAlign.Bottom)
Fh = "Left";
else if (vertAlign == VertAlign.Center)
Fh = "Center";
}
else
{
if (horzAlign == HorzAlign.Left)
Fv = "Bottom";
else if (horzAlign == HorzAlign.Right)
Fv = "Top";
else if (horzAlign == HorzAlign.Center)
Fv = "Center";
if (vertAlign == VertAlign.Top)
Fh = "Right";
else if (vertAlign == VertAlign.Bottom)
Fh = "Left";
else if (vertAlign == VertAlign.Center)
Fh = "Center";
}
return "ss:Horizontal=\"" + Fh + "\" ss:Vertical=\"" + Fv + "\"";
}
private string GetXMLBorders(ExportIEMStyle style)
{
StringBuilder result = new StringBuilder(128);
result.AppendLine("");
if ((style.Border.Lines & BorderLines.Left) > 0)
result.Append("");
if ((style.Border.Lines & BorderLines.Top) > 0)
result.Append("");
if ((style.Border.Lines & BorderLines.Bottom) > 0)
result.AppendLine("");
if ((style.Border.Lines & BorderLines.Right) > 0)
result.AppendLine("");
result.Append("");
return result.ToString();
}
private string GetXMLFont(ExportIEMStyle style)
{
StringBuilder result = new StringBuilder(128);
result.Append(" 0 ? "ss:Bold=\"1\" " : String.Empty)).
Append(((style.Font.Style & FontStyle.Italic) > 0 ? "ss:Italic=\"1\" " : String.Empty)).
Append(((style.Font.Style & FontStyle.Underline) > 0 ? "ss:Underline=\"Single\" " : String.Empty)).
Append("/>");
return result.ToString();
}
private string GetXMLInterior(ExportIEMStyle style)
{
if (style.FillColor.A != 0)
return "";
return String.Empty;
}
private string GetXMLAlignment(ExportIEMStyle style)
{
StringBuilder result = new StringBuilder(64);
result.Append(" 0 && style.Angle <= 90) ? "ss:Rotate=\"" + (-style.Angle).ToString() + "\"" : String.Empty)).
Append(((style.Angle > 90 && style.Angle <= 180) ? "ss:Rotate=\"" + (180 - style.Angle).ToString() + "\"" : String.Empty)).
Append(((style.Angle > 180 && style.Angle < 270) ? "ss:Rotate=\"" + (270 - style.Angle).ToString() + "\"" : String.Empty)).
Append(((style.Angle >= 270 && style.Angle < 360) ? "ss:Rotate=\"" + (360 - style.Angle).ToString() + "\"" : String.Empty)).
Append("/>");
return result.ToString();
}
private string GetXMLLineStyle(LineStyle style)
{
switch (style)
{
case LineStyle.Dash:
return "Dash";
case LineStyle.DashDot:
return "DashDot";
case LineStyle.DashDotDot:
return "DashDotDot";
case LineStyle.Dot:
return "Dot";
case LineStyle.Double:
return "Double";
default:
return "Continuous";
}
}
private string GetXMLFormat(ExportIEMStyle style)
{
if (style.Format is NumberFormat || style.Format is CurrencyFormat)
{
return "\r\n";
}
return String.Empty;
}
#endregion
#region Protected Methods
///
protected override string GetFileFilter()
{
return new MyRes("FileFilters").Get("XlsFile");
}
///
protected override void Start()
{
base.Start();
sheets = new Dictionary();
commonStyles = new List();
}
///
protected override void ExportPageBegin(ReportPage page)
{
base.ExportPageBegin(page);
if (sheets.ContainsKey(page.Name) && !SplitPages)
{
sh = sheets[page.Name] as XMLSheet;
sh.matrix.AddPageBegin(page);
}
else
{
matrix = new ExportMatrix();
if (Wysiwyg)
matrix.Inaccuracy = 0.5f;
else
matrix.Inaccuracy = 10;
matrix.RotatedAsImage = false;
matrix.PlainRich = true;
matrix.AreaFill = true;
matrix.CropAreaFill = true;
matrix.Report = Report;
matrix.Images = false;
matrix.DataOnly = DataOnly;
matrix.ShowProgress = ShowProgress;
matrix.MaxCellHeight = ydivider * xLMaxHeight;
matrix.AddPageBegin(page);
matrix.Styles = commonStyles;
}
}
///
protected override void ExportBand(BandBase band)
{
base.ExportBand(band);
if (sheets.ContainsKey(band.Page.Name) && !SplitPages)
{
sh = sheets[band.Page.Name];
sh.matrix.AddBand(band, this);
}
else
{
matrix.AddBand(band, this);
}
}
///
protected override void ExportPageEnd(ReportPage page)
{
if (sheets.ContainsKey(page.Name) && !SplitPages)
{
sh = sheets[page.Name] as XMLSheet;
sh.matrix.AddPageEnd(page);
}
else
{
string new_page_name = page.Name;
if (SplitPages)
{
if (sheets.ContainsKey(page.Name + "-1"))
{
int repeats = 2;
while (sheets.ContainsKey(page.Name + "-" + repeats.ToString()))
repeats++;
new_page_name += "-" + repeats.ToString();
}
else if (Report.PreparedPages.GetPage(sheets.Count + 1) != null &&
Report.PreparedPages.GetPage(sheets.Count + 1).Name == page.Name)
{
new_page_name += "-1";
}
}
matrix.AddPageEnd(page);
sh = new XMLSheet(matrix, new_page_name, pageBreaks);
sheets[new_page_name] = sh;
}
}
///
protected override void Finish()
{
foreach (XMLSheet sheet in sheets.Values)
sheet.matrix.Prepare();
MyRes Res = new MyRes("Export,Misc");
if (ShowProgress)
Config.ReportSettings.OnProgress(Report, Res.Get("SaveFile"));
ExportXML(Stream);
}
#endregion
///
public override void Serialize(FRWriter writer)
{
base.Serialize(writer);
writer.WriteBool("Wysiwyg", Wysiwyg);
writer.WriteBool("PageBreaks", PageBreaks);
writer.WriteBool("DataOnly", DataOnly);
writer.WriteBool("SplitPages", SplitPages);
}
///
/// Initializes a new instance of the class.
///
public XMLExport()
{
pageBreaks = true;
Wysiwyg = true;
creator = "FastReport";
}
}
}