123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 |
- 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
- {
- /// <summary>
- /// Represents the Excel 2003 XML export filter.
- /// </summary>
- 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<string, XMLSheet> sheets;
- private ExportMatrix matrix;
- private XMLSheet sh;
- private bool splitPages;
- private List<ExportIEMStyle> 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("<Worksheet ss:Name=\"" + name + "\">");
- // add table
- builder.Append("<Table ss:ExpandedColumnCount=\"").Append(matrix.Width.ToString()).Append("\"").
- Append(" ss:ExpandedRowCount=\"").Append(matrix.Height.ToString()).AppendLine("\" x:FullColumns=\"1\" x:FullRows=\"1\">");
- for (x = 1; x < matrix.Width; x++)
- builder.Append("<Column ss:AutoFitWidth=\"0\" ss:Width=\"").
- Append(ExportUtils.FloatToString((matrix.XPosById(x) - matrix.XPosById(x - 1)) / xdivider)).
- AppendLine("\"/>");
- WriteBuf(stream, builder);
- for (int y = 0; y < matrix.Height - 1; y++)
- {
- builder.Append("<Row ss:Height=\"").
- Append(ExportUtils.FloatToString((matrix.YPosById(y + 1) - matrix.YPosById(y)) / ydivider)).
- AppendLine("\">");
- 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("<Cell ss:Index=\"").
- Append(Convert.ToString(x + 1) + "\" ");
- matrix.ObjectPos(i, out fx, out fy, out dx, out dy);
- Obj.Counter = 1;
- if (Obj.IsText)
- {
- if (dx > 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("></Cell>");
- }
- }
- }
- else
- builder.Append("<Cell ss:Index=\"").Append(Convert.ToString(x + 1)).Append("\"/>");
- }
- builder.AppendLine("</Row>");
- if (builder.Length > 8192)
- WriteBuf(stream, builder);
- }
- builder.AppendLine("</Table>");
- builder.AppendLine("<WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">");
- if (matrix.PagesCount > 0)
- {
- builder.AppendLine("<PageSetup>");
- if (matrix.Landscape(0))
- builder.AppendLine("<Layout x:Orientation=\"Landscape\"/>");
- builder.AppendLine(string.Format(CultureInfo.InvariantCulture, "<PageMargins x:Bottom=\"{0:F2}\"" +
- " x:Left=\"{1:F2}\"" +
- " x:Right=\"{2:F2}\"" +
- " x:Top=\"{3:F2}\"/>",
- matrix.PageBMargin(0) / margDiv,
- matrix.PageLMargin(0) / margDiv,
- matrix.PageRMargin(0) / margDiv,
- matrix.PageTMargin(0) / margDiv));
- builder.AppendLine("</PageSetup>");
- builder.AppendLine("<Print>");
- builder.AppendLine("<ValidPrinterInfo/>");
- builder.AppendLine("<PaperSizeIndex>" + matrix.RawPaperSize(0).ToString() + "</PaperSizeIndex>");
- builder.AppendLine("</Print>");
- }
- builder.AppendLine("</WorksheetOptions>");
- // add page breaks
- if (pageBreaks)
- {
- builder.AppendLine("<PageBreaks xmlns=\"urn:schemas-microsoft-com:office:excel\">");
- builder.AppendLine("<RowBreaks>");
- int page = 0;
- for (i = 0; i <= matrix.Height - 1; i++)
- {
- if (matrix.YPosById(i) >= matrix.PageBreak(page))
- {
- builder.AppendLine("<RowBreak>");
- builder.AppendLine(string.Format("<Row>{0}</Row>", i));
- builder.AppendLine("</RowBreak>");
- page++;
- }
- }
- builder.AppendLine("</RowBreaks>");
- builder.AppendLine("</PageBreaks>");
- }
- builder.AppendLine("</Worksheet>");
- WriteBuf(stream, builder);
- }
- public XMLSheet(ExportMatrix matrix, string name, bool pageBreaks)
- {
- this.matrix = matrix;
- this.name = name;
- this.pageBreaks = pageBreaks;
- }
- }
- #region Properties
- /// <summary>
- /// Gets or sets a value that determines whether to insert page breaks in the output file or not.
- /// </summary>
- ///
- public bool PageBreaks
- {
- get { return pageBreaks; }
- set { pageBreaks = value; }
- }
- /// <summary>
- /// Gets or sets a value that determines whether the wysiwyg mode should be used
- /// for better results.
- /// </summary>
- /// <remarks>
- /// Default value is <b>true</b>. 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 <b>false</b>, the number of rows/columns in the resulting file will be decreased.
- /// You will get less wysiwyg, but more editable file.
- /// </remarks>
- public bool Wysiwyg
- {
- get { return wysiwyg; }
- set { wysiwyg = value; }
- }
- /// <summary>
- /// Gets or sets the name of document creator.
- /// </summary>
- public string Creator
- {
- get { return creator; }
- set { creator = value; }
- }
- /// <summary>
- /// Gets or sets a value that determines whether to export the databand rows only.
- /// </summary>
- public bool DataOnly
- {
- get { return dataOnly; }
- set { dataOnly = value; }
- }
- /// <summary>
- /// Each report page is placed on a new Excel page.
- /// </summary>
- 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("<?xml version=\"1.0\"?>");
- builder.AppendLine("<?mso-application progid=\"Excel.Sheet\"?>");
- builder.Append("<?fr-application created=\"").Append(creator).AppendLine("\"?>");
- builder.AppendLine("<?fr-application homesite=\"http://www.fast-report.com\"?>");
- builder.Append("<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"");
- builder.Append(" xmlns:o=\"urn:schemas-microsoft-com:office:office\"");
- builder.Append(" xmlns:x=\"urn:schemas-microsoft-com:office:excel\"");
- builder.Append(" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"");
- builder.AppendLine(" xmlns:html=\"http://www.w3.org/TR/REC-html40\">");
- builder.AppendLine("<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">");
- builder.Append("<Title>").Append(Report.ReportInfo.Name).AppendLine("</Title>");
- builder.Append("<Author>").Append(Report.ReportInfo.Author).AppendLine("</Author>");
- builder.Append("<Created>").Append(SystemFake.DateTime.Now.Date.ToString()).Append("T").Append(SystemFake.DateTime.Now.TimeOfDay.ToString()).AppendLine("Z</Created>");
- builder.Append("<Version>").Append(Report.ReportInfo.Version).AppendLine("</Version>");
- builder.AppendLine("</DocumentProperties>");
- builder.AppendLine("<ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\">");
- builder.AppendLine("<ProtectStructure>False</ProtectStructure>");
- builder.AppendLine("<ProtectWindows>False</ProtectWindows>");
- builder.AppendLine("</ExcelWorkbook>");
- }
- private void ExportSheets(Stream stream, StringBuilder builder)
- {
- foreach (XMLSheet sheet in sheets.Values)
- sheet.ExportSheet(stream, builder);
- builder.AppendLine("</Workbook>");
- 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("<Styles>");
- ExportIEMStyle EStyle;
- for (int x = 0; x < commonStyles.Count; x++)
- {
- EStyle = commonStyles[x];
- builder.Append("<Style ss:ID=\"s").Append(x.ToString()).AppendLine("\">");
- builder.AppendLine(GetXMLFont(EStyle));
- builder.AppendLine(GetXMLInterior(EStyle));
- builder.AppendLine(GetXMLAlignment(EStyle));
- builder.AppendLine(GetXMLBorders(EStyle));
- builder.Append(GetXMLFormat(EStyle));
- builder.AppendLine("</Style>");
- }
- builder.AppendLine("</Styles>");
- }
- 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("<Borders>");
- if ((style.Border.Lines & BorderLines.Left) > 0)
- result.Append("<Border ss:Position=\"Left\" ").
- Append("ss:LineStyle=\"").
- AppendFormat(GetXMLLineStyle(style.Border.LeftLine.Style)).
- Append("\" ").
- Append("ss:Weight=\"").
- Append(GetXMLWeight(style.Border.LeftLine.Width)).
- Append("\" ").
- Append("ss:Color=\"").
- Append(ExportUtils.HTMLColorCode(style.Border.LeftLine.Color)).
- AppendLine("\"/>");
- if ((style.Border.Lines & BorderLines.Top) > 0)
- result.Append("<Border ss:Position=\"Top\" ").
- Append("ss:LineStyle=\"").
- AppendFormat(GetXMLLineStyle(style.Border.TopLine.Style)).
- Append("\" ").
- Append("ss:Weight=\"").
- Append(GetXMLWeight(style.Border.TopLine.Width)).
- Append("\" ").
- Append("ss:Color=\"").
- Append(ExportUtils.HTMLColorCode(style.Border.TopLine.Color)).
- AppendLine("\"/>");
- if ((style.Border.Lines & BorderLines.Bottom) > 0)
- result.AppendLine("<Border ss:Position=\"Bottom\" ").
- Append("ss:LineStyle=\"").
- AppendFormat(GetXMLLineStyle(style.Border.BottomLine.Style)).
- Append("\" ").
- Append("ss:Weight=\"").
- Append(GetXMLWeight(style.Border.BottomLine.Width)).
- Append("\" ").
- Append("ss:Color=\"").
- Append(ExportUtils.HTMLColorCode(style.Border.BottomLine.Color)).
- AppendLine("\"/>");
- if ((style.Border.Lines & BorderLines.Right) > 0)
- result.AppendLine("<Border ss:Position=\"Right\" ").
- Append("ss:LineStyle=\"").
- AppendFormat(GetXMLLineStyle(style.Border.RightLine.Style)).
- Append("\" ").
- Append("ss:Weight=\"").
- Append(GetXMLWeight(style.Border.RightLine.Width)).
- Append("\" ").
- Append("ss:Color=\"").
- Append(ExportUtils.HTMLColorCode(style.Border.RightLine.Color)).
- AppendLine("\"/>");
- result.Append("</Borders>");
- return result.ToString();
- }
- private string GetXMLFont(ExportIEMStyle style)
- {
- StringBuilder result = new StringBuilder(128);
- result.Append("<Font ss:FontName=\"").Append(style.Font.Name).Append("\" ss:Size=\"").
- Append(ExportUtils.FloatToString(style.Font.Size)).Append("\" ss:Color=\"").
- Append(ExportUtils.HTMLColorCode(style.TextColor)).Append("\" ").
- Append(((style.Font.Style & FontStyle.Bold) > 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 "<Interior ss:Color=\"" +
- ExportUtils.HTMLColorCode(style.FillColor) + "\" ss:Pattern=\"Solid\"/>";
- return String.Empty;
- }
- private string GetXMLAlignment(ExportIEMStyle style)
- {
- StringBuilder result = new StringBuilder(64);
- result.Append("<Alignment ").Append(XmlAlign(style.HAlign, style.VAlign, style.Angle)).
- Append(" ss:WrapText=\"1\" ").
- Append(((style.Angle > 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 "<NumberFormat ss:Format=\"" + ExportUtils.GetExcelFormatSpecifier(style.Format) + "\"/>\r\n";
- }
- return String.Empty;
- }
- #endregion
- #region Protected Methods
- /// <inheritdoc/>
- protected override string GetFileFilter()
- {
- return new MyRes("FileFilters").Get("XlsFile");
- }
- /// <inheritdoc/>
- protected override void Start()
- {
- base.Start();
- sheets = new Dictionary<string, XMLSheet>();
- commonStyles = new List<ExportIEMStyle>();
- }
- /// <inheritdoc/>
- 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;
- }
- }
- /// <inheritdoc/>
- 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);
- }
- }
- /// <inheritdoc/>
- 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;
- }
- }
- /// <inheritdoc/>
- 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
- /// <inheritdoc/>
- 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);
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="XMLExport"/> class.
- /// </summary>
- public XMLExport()
- {
- pageBreaks = true;
- Wysiwyg = true;
- creator = "FastReport";
- }
- }
- }
|