using FastReport.Format; using FastReport.Utils; using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Windows.Forms; namespace FastReport.Export.OoXML { /// /// Drawing class /// internal class OoXMLDrawing : OoXMLBase { #region Private properties private int picCount; private StringBuilder drawing_string; private StringBuilder picture_rels; private Excel2007Export ooXML; #endregion Private properties public int PicCount { get { return picCount; } } #region Class overrides public override string RelationType { get { return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"; } } public override string ContentType { get { return "application/vnd.openxmlformats-officedocument.drawing+xml"; } } public override string FileName { get { return "xl/drawings/drawing1.xml"; } } #endregion Class overrides private void ExportBorder(ExportIEMStyle style) { if (style.Border.Lines == BorderLines.All) { drawing_string.AppendFormat("", style.Border.LeftLine.Width); drawing_string.Append(""); drawing_string.AppendFormat("", style.Border.LeftLine.Color.R, style.Border.LeftLine.Color.G, style.Border.LeftLine.Color.B); drawing_string.Append(""); drawing_string.Append(GetDashStyle(style.Border.LeftLine.DashStyle)); drawing_string.Append(""); } } public void Append(ExportIEMObject Obj, int x, int y, int dx, int dy, int rowNum, int matrixWidth) { picCount++; string rid = "\"rId" + picCount.ToString() + "\""; string picFileName = "xl/media/" + Obj.Hash + ".png"; if (!ooXML.Zip.FileExists(picFileName)) { Obj.PictureStream.Position = 0; ooXML.Zip.AddStream(picFileName, Obj.PictureStream); } picture_rels.AppendLine(""); string pictureProperties; switch (ooXML.PictureProperties) { case Excel2007Export.ePictureProperties.OnlyMove: pictureProperties = " editAs=\"oneCell\""; break; case Excel2007Export.ePictureProperties.Unchangeable: pictureProperties = " editAs=\"absolute\""; break; default: pictureProperties = ""; break; } drawing_string.Append($""); drawing_string.Append(""); drawing_string.Append("").Append(x.ToString()).Append(""); drawing_string.Append("0"); if (!ooXML.Seamless) { drawing_string.Append("").Append(y.ToString()).Append(""); } else { drawing_string.Append("").Append((rowNum - 1).ToString()).Append(""); } drawing_string.Append("0"); drawing_string.Append(""); drawing_string.Append(""); int colTo = x + dx; //if (x == 0 && colTo > matrixWidth - 1) // colTo = matrixWidth - 1; drawing_string.Append("").Append(colTo.ToString()).Append(""); drawing_string.Append("0"); if (!ooXML.Seamless) { drawing_string.Append("").Append((y + dy).ToString()).Append(""); } else { drawing_string.Append("").Append((rowNum - 1 + dy).ToString()).Append(""); } drawing_string.Append("0"); drawing_string.Append(""); drawing_string.Append(""); drawing_string.Append(""); drawing_string.Append(" "); if (Obj.URL != null && Obj.URL.Length > 0) { ++picCount; string rIdLink = "\"rId" + picCount.ToString() + "\""; picture_rels.AppendLine(""); drawing_string.Append(""); } drawing_string.Append(""); drawing_string.Append(""); drawing_string.Append(""); drawing_string.Append(""); drawing_string.Append(""); drawing_string.Append(""); drawing_string.Append( ""); //Append(" state=\"hqprint\"/>"); // fix for Excel 2007 drawing_string.Append(""); drawing_string.Append(""); drawing_string.Append(""); drawing_string.Append(""); ExportBorder(Obj.Style); drawing_string.Append(""); drawing_string.Append(""); //drawing_string.Append(""); fix for Excel 2007 drawing_string.Append(""); drawing_string.AppendLine(""); } public void Start() { //=== johnny appended 2012/6/17 drawing_string = new StringBuilder(8192); picture_rels = new StringBuilder(256); drawing_string.Append(xml_header); drawing_string.Append( ""); picture_rels.Append(""); picture_rels.Append(""); } //public void Stop() //=== johnny appended 2012/6/17 public void Stop(string sSheetID) { drawing_string.Append(""); picture_rels.Append(""); if (picCount != 0) { MemoryStream file = new MemoryStream(); ExportUtils.WriteLn(file, picture_rels.ToString()); file.Position = 0; ooXML.Zip.AddStream("xl/drawings/_rels/drawing" + sSheetID + ".xml.rels", file); file = new MemoryStream(); ExportUtils.WriteLn(file, drawing_string.ToString()); file.Position = 0; ooXML.Zip.AddStream("xl/drawings/drawing" + sSheetID + ".xml", file); picCount = 0; } } public OoXMLDrawing(Excel2007Export OoXML) { ooXML = OoXML; picCount = 0; drawing_string = new StringBuilder(8192); picture_rels = new StringBuilder(1024); } } /// /// Share all strings in document /// internal class OoXMLSharedStringTable : OoXMLBase { #region Private properties private List sharedStringList; #endregion Private properties #region Class overrides public override string RelationType { get { return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"; } } public override string ContentType { get { return "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"; } } public override string FileName { get { return "sharedStrings.xml"; } } #endregion Class overrides private struct CurrentStyle { public int Size; public bool Bold; public bool Italic; public bool Underline; public bool Strike; public bool Sub; public bool Sup; public Color Colour; public Font Font; public string LastTag; } private string ConvertHtmlItem(CurrentStyle style) { StringBuilder str = new StringBuilder(256); str.Append(""); if (style.Bold) str.Append(""); if (style.Italic) str.Append(""); if (style.Underline) str.Append(""); if (style.Strike) str.Append(""); if (style.Sup) str.Append(""); if (style.Sub) str.Append(""); str.Append(string.Format(CultureInfo.InvariantCulture, "", style.Size)); str.Append(""); if (!style.Colour.ToArgb().Equals(Color.Black.ToArgb())) { str.Append(string.Format(CultureInfo.InvariantCulture, " ", style.Colour.A, style.Colour.R, style.Colour.G, style.Colour.B)); } str.Append(""); return str.ToString(); } private void ParseFont(string s, CurrentStyle style, out CurrentStyle result_style) { result_style = style; string[] font_items = s.Split('='); string Tag = font_items[0].ToUpper(); switch (Tag) { case "COLOR": string[] val = font_items[1].Split('\"'); result_style.Colour = Color.FromName(val[1]); break; //default: //throw new Exception("Unsupported font item: " + Tag); } } private string ParseHtmlTags(string s, ExportIEMObject obj) { int Index = 0; int Begin = 0; int End = 0; string Tag; string Text; CurrentStyle current_style = new CurrentStyle(); CurrentStyle previos_style; current_style.Size = (obj.Style.Font.Size > 0) ? (int)obj.Style.Font.Size : 10; current_style.Bold = false; current_style.Italic = false; current_style.Underline = false; current_style.Colour = Color.FromName("Black"); current_style.Strike = false; current_style.Sub = false; current_style.Sup = false; current_style.Font = obj.Style.Font; StringBuilder result = new StringBuilder(s.Length + 7); Stack style_stack = new Stack(); Begin = s.IndexOfAny(new char[1] { '<' }, Index); while (Begin != -1) { if (Begin != 0 && Index == 0) { result.Append(""). Append(ExportUtils.Excel2007String(s.Substring(Index, Begin), obj.TextRenderType)). Append(""); } End = s.IndexOfAny(new char[1] { '>' }, Begin + 1); if (End == -1) break; Tag = s.Substring(Begin + 1, End - Begin - 1); bool CloseTag = Tag.StartsWith("/"); if (CloseTag) Tag = Tag.Remove(0, 1); string[] items = Tag.Split(' '); Tag = items[0].ToUpper(); if (!CloseTag) { current_style.LastTag = Tag; style_stack.Push(current_style); switch (Tag) { case "B": current_style.Bold = true; break; case "I": current_style.Italic = true; break; case "U": current_style.Underline = true; break; case "STRIKE": current_style.Strike = true; break; case "SUB": current_style.Sub = true; break; case "SUP": current_style.Sup = true; break; case "FONT": /*current_style.Font = items[1];*/ ParseFont(items[1], current_style, out current_style); break; //default: // throw new Exception("Unsupported HTML TAG"); } } else { if (style_stack.Count > 0) { previos_style = style_stack.Pop(); if (previos_style.LastTag != Tag) { //throw new Exception("Unaligned HTML TAGS"); } current_style = previos_style; } } Index = End + 1; Begin = s.IndexOfAny(new char[1] { '<' }, Index); if (Begin == -1) { Text = s.Substring(Index); } else { Text = s.Substring(Index, Begin - Index); } if (Text.Length > 0) result.Append("").Append(ConvertHtmlItem(current_style)). Append("").Append(ExportUtils.Excel2007String(Text, obj.TextRenderType)). Append(""); } return result.ToString(); } private bool HaveSeqSpc(string s) { int len = s.Length; for (int i = 0; i < len; i++) { if (s[i] == ' ' && // there is only one character in the string, and that character is a space (s.Length == 1 || // the current character is not the last character of the string and the next character after it is also a space (i < (len - 1) && s[i + 1] == ' ') || // the current character is not the first character of the string and the previous character before it is also a space (i > 0 && s[i - 1] == ' ') || // the current character is the last character of the string i == len - 1 || // the first character of the string is a space and the character following it is not a space (i == 0 && s[i + 1] != ' '))) return true; } return false; } public int Add(string s, ExportIEMObject obj) { int idx; string parsed_tags = String.Empty; switch (obj.TextRenderType) { case TextRenderType.HtmlTags: s = s.Replace("
", "\r\n"); parsed_tags = ParseHtmlTags(s, obj); break; case TextRenderType.HtmlParagraph: s = s.Replace("
", "\r\n"); parsed_tags = ParseHtmlTags(s, obj); //TODO DETRAV EXCEL2007 break; } if (!String.IsNullOrEmpty(parsed_tags)) s = parsed_tags; // checking for consecutive spaces in a string else if (HaveSeqSpc(s)) s = "" + s + ""; else s = "" + s + ""; StringBuilder str = new StringBuilder(); foreach (char c in s) { if ((int)c < 32 || ((int)c >= 127 && (int)c < 160)) { str.Append("_x" + ((int)c).ToString("X4") + "_"); } else { str.Append(c); } } s = str.ToString(); if (sharedStringList.Count > 100) idx = sharedStringList.IndexOf(s, sharedStringList.Count - 100); else idx = sharedStringList.IndexOf(s); if (idx == -1) { sharedStringList.Add(s); idx = sharedStringList.Count - 1; } return idx; } private void WriteSharedStringsBuffer(StringBuilder strings, Stream stream) { ExportUtils.WriteLn(stream, strings.ToString()); strings.Length = 0; } public void Export(Excel2007Export OoXML) { Stream file; if (OoXML.UseFileStream) { string tempFileName = OoXML.GetFileName() + "1" + ".tmp"; file = new FileStream(tempFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite); OoXML.TempFileNames.Add(tempFileName); } else file = new MemoryStream(); ExportUtils.WriteLn(file, xml_header); ExportUtils.WriteLn(file, ""); int i = 0; StringBuilder sharedStrings = new StringBuilder(8192); foreach (string item in sharedStringList) { // Next block is a fix of bug with not escaped ampersands. //================================================================================= int start = -1; List indexes = new List(); start = item.IndexOf("&"); // Find index of each ampersand in the string. while (start > -1) { indexes.Add(start); start = item.IndexOf("&", start + 1); } // Remove index of each correct ampersand. for (int j = indexes.Count - 1; j >= 0; j--) { if (item.IndexOf("&", indexes[j]) == indexes[j]) indexes.RemoveAt(j); else if (item.IndexOf(" ", indexes[j]) == indexes[j]) indexes.RemoveAt(j); else if (item.IndexOf(""", indexes[j]) == indexes[j]) indexes.RemoveAt(j); else if (item.IndexOf("'", indexes[j]) == indexes[j]) indexes.RemoveAt(j); else if (item.IndexOf("<", indexes[j]) == indexes[j]) indexes.RemoveAt(j); else if (item.IndexOf(">", indexes[j]) == indexes[j]) indexes.RemoveAt(j); else if (item.IndexOf("&#", indexes[j]) == indexes[j]) indexes.RemoveAt(j); } // Escape each incorrect ampersand. string correctItem = item; for (int k = indexes.Count - 1; k >= 0; k--) { correctItem = correctItem.Remove(indexes[k], 1); correctItem = correctItem.Insert(indexes[k], "&"); } //================================================================================= sharedStrings.Append("").Append(correctItem).Append(""); if (i++ >= 100) { WriteSharedStringsBuffer(sharedStrings, file); i = 0; } } WriteSharedStringsBuffer(sharedStrings, file); ExportUtils.WriteLn(file, ""); file.Position = 0; OoXML.Zip.AddStream("xl/" + FileName, file); } public OoXMLSharedStringTable() { sharedStringList = new List(); } } /// /// Share all URL in document /// internal class OoXMLSharedURLTable : OoXMLBase { #if READONLY_STRUCTS private readonly struct Item #else private struct Item #endif { internal readonly int id; internal readonly int x; internal readonly int y; internal readonly string url; internal Item(int id, int x, int y, string url) { this.id = id; this.x = x; this.y = y; this.url = url; } } #region Private properties private List uRL = new List(); #endregion Private properties #region Class overrides /* "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"; */ public override string RelationType { get { throw new Exception("Not decalred"); } } /* "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"; */ public override string ContentType { get { throw new Exception("Not decalred"); } } /* return "sharedStrings.xml"; */ public override string FileName { get { throw new Exception("Not decalred"); } } #endregion Class overrides internal void Add(int x, int y, string url) { int id = uRL.Count + 2; uRL.Add(new Item(id, x, y, url)); } internal int Count { get { return uRL.Count; } } internal StringBuilder ExportBody(Excel2007Export OoXML) { StringBuilder builder = new StringBuilder(512); builder.Append(""); foreach (Item i in uRL) { builder.AppendFormat("", ExportUtils.GetCellReference(i.x, i.y + 1), // Quoted("A2") "rId", i.id.ToString() // Quoted("rId1") ); } builder.AppendLine(""); return builder; } internal StringBuilder ExportRelationship() { StringBuilder builder = new StringBuilder(256); foreach (Item i in uRL) { builder.AppendFormat( "", Quoted(ExportUtils.Excel2007String(i.url, TextRenderType.Default)), Quoted("rId" + i.id.ToString()) ); } return builder; } } /// /// Document styles /// internal class OoXMLDocumentStyles : OoXMLBase { #region Private properties private List styles; private int formatIndex; private bool currencyToAccounting; private bool generalToText; #endregion Private properties #region Class overrides public override string RelationType { get { return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; } } public override string ContentType { get { return "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"; } } public override string FileName { get { return "styles.xml"; } } internal bool UseLocaleFormating { get; set; } #endregion Class overrides #region Helpers private string GetRGBString(Color c) { return "\"" + ExportUtils.ByteToHex(c.A) + ExportUtils.ByteToHex(c.R) + ExportUtils.ByteToHex(c.G) + ExportUtils.ByteToHex(c.B) + "\""; } private string HAlign2String(HorzAlign ha) { switch (ha) { case HorzAlign.Center: return "center"; case HorzAlign.Left: return "left"; case HorzAlign.Right: return "right"; case HorzAlign.Justify: return "justify"; } return ""; } private string VAlign2String(VertAlign va) { switch (va) { case VertAlign.Bottom: return "bottom"; case VertAlign.Center: return "center"; case VertAlign.Top: return "top"; } return ""; } private string Styles2String(LineStyle style, float Width) { if (Width < 2) switch (style) { case LineStyle.Solid: return "\"thin\""; case LineStyle.Double: return "\"double\""; case LineStyle.Dot: return "\"dotted\""; case LineStyle.DashDotDot: return "\"dashDotDot\""; case LineStyle.DashDot: return "\"dashDot\""; case LineStyle.Dash: return "\"dashed\""; } else if (Width < 3.5) switch (style) { case LineStyle.Solid: return "\"medium\""; case LineStyle.Double: return "\"double\""; case LineStyle.Dot: return "\"mediumDashed\""; // Due no "mediumDotted" do not exist in spec case LineStyle.DashDotDot: return "\"mediumDashDotDot\""; case LineStyle.DashDot: return "\"mediumDashDot\""; case LineStyle.Dash: return "\"mediumDashed\""; } else switch (style) { case LineStyle.Solid: return "\"thick\""; case LineStyle.Double: return "\"double\""; case LineStyle.Dot: return "\"mediumDashed\""; // Due no "mediumDotted" do not exist in spec case LineStyle.DashDotDot: return "\"mediumDashDotDot\""; case LineStyle.DashDot: return "\"slantDashDot\""; case LineStyle.Dash: return "\"mediumDashed\""; } return ""; } private string ConvertRotationAngle(int Angle) { if (Angle != 0 && Angle <= 90) { Angle = 90 + Angle; } else if (Angle >= 270) { Angle = 360 - Angle; } else { Angle = 0; } return Angle.ToString(); } #endregion Helpers private void ExportFormats(Stream file) { StringBuilder result = new StringBuilder(); int res_count = 0; for (int i = 0; i < styles.Count; i++) { ExportIEMStyle EStyle = styles[i]; FormatBase format_base = EStyle.Format; if (format_base is CurrencyFormat || format_base is NumberFormat || format_base is DateFormat || format_base is PercentFormat) { if (GetDefaultNumberCode(format_base) == -1) { ++res_count; result.AppendFormat(CultureInfo.InvariantCulture, "", formatIndex + res_count, ExportUtils.GetExcelFormatSpecifier(format_base, UseLocaleFormating, currencyToAccounting)); } } } if (res_count > 0) { ExportUtils.WriteLn(file, ""); ExportUtils.WriteLn(file, result.ToString()); ExportUtils.WriteLn(file, ""); } } private int GetDefaultNumberCode(FormatBase format_base) { //https://github.com/closedxml/closedxml/wiki/NumberFormatId-Lookup-Table if (format_base is NumberFormat) { NumberFormat nbr = (format_base as NumberFormat); if (nbr.DecimalDigits == 0 && (/*nbr.GroupSeparator == " " ||*/ nbr.GroupSeparator == ""/* || // redmine 2525 nbr.GroupSeparator.ToCharArray()[0] == 160*/) && nbr.NegativePattern == 1) // -n return 1; else if (nbr.DecimalDigits == 2 && nbr.GroupSeparator == "" && //without group separator nbr.NegativePattern == 1) // -n return 2; else if (nbr.DecimalDigits == 0 && nbr.GroupSeparator == "," && nbr.NegativePattern == 1) // -n return 3; else if (nbr.DecimalDigits == 2 && nbr.GroupSeparator == "," && nbr.NegativePattern == 1) // -n return 4; else if (nbr.DecimalDigits == 0 && nbr.GroupSeparator == "," && nbr.NegativePattern == 0) // (n) return 37; else if (nbr.DecimalDigits == 2 && nbr.GroupSeparator == "," && nbr.NegativePattern == 0) // (n) return 39; else return -1; } else return -1; } private int GetFormatCode(ExportIEMStyle LookingForStyle) { int res_count = 0; for (int i = 0; i < styles.Count; i++) { ExportIEMStyle EStyle = styles[i]; FormatBase format_base = EStyle.Format; if (format_base is CurrencyFormat || format_base is NumberFormat || format_base is DateFormat || format_base is PercentFormat) { int code = GetDefaultNumberCode(format_base); bool defaultCode = code != -1; if (!defaultCode) ++res_count; if (LookingForStyle == styles[i]) { if (defaultCode) return code; else return formatIndex + res_count; } } } return generalToText ? 49 : 0; } private void ExportFonts(Stream file) { int i; ExportIEMStyle EStyle; StringBuilder fonts = new StringBuilder(4096); fonts.Append(""); for (i = 0; i < styles.Count; i++) { EStyle = styles[i]; Font font = EStyle.Font; fonts.Append(""); if (font.Bold) fonts.Append(""); if (font.Italic) fonts.Append(""); if (font.Underline) fonts.Append(""); if (font.Strikeout) fonts.Append(""); fonts.Append(""); Color c = EStyle.TextColor; if (c.A == 0 && c.R == 255 && c.G == 255 && c.B == 255) { c = Color.Black; } fonts.Append(""); fonts.Append(""); fonts.AppendLine(""); } fonts.AppendLine(""); ExportUtils.Write(file, fonts.ToString()); } private void ExportFills(Stream file) { int i; ExportIEMStyle EStyle; StringBuilder fills = new StringBuilder(4096); fills.Append(""); fills.AppendLine(""); fills.AppendLine(""); for (i = 0; i < styles.Count; i++) { EStyle = styles[i]; fills.AppendLine(""); if (EStyle.Fill is LinearGradientFill) { LinearGradientFill linear = EStyle.Fill as LinearGradientFill; fills.Append(""); fills.AppendLine(""); fills.Append(" "); fills.AppendLine(""); fills.AppendLine(""); fills.Append(" "); fills.AppendLine(""); fills.AppendLine(""); } else if (EStyle.Fill is HatchFill) { bool swap_color = false; string PatternType = "none"; HatchFill hatch = EStyle.Fill as HatchFill; switch (hatch.Style) { case System.Drawing.Drawing2D.HatchStyle.DarkUpwardDiagonal: PatternType = "lightUp"; swap_color = true; break; case System.Drawing.Drawing2D.HatchStyle.BackwardDiagonal: PatternType = "lightUp"; break; // case System.Drawing.Drawing2D.HatchStyle.Cross: // case System.Drawing.Drawing2D.HatchStyle.Max: case System.Drawing.Drawing2D.HatchStyle.LargeGrid: case System.Drawing.Drawing2D.HatchStyle.SmallGrid: PatternType = "lightGrid"; break; case System.Drawing.Drawing2D.HatchStyle.ForwardDiagonal: swap_color = true; PatternType = "darkDown"; break; case System.Drawing.Drawing2D.HatchStyle.DarkDownwardDiagonal: PatternType = "darkDown"; break; case System.Drawing.Drawing2D.HatchStyle.DarkHorizontal: PatternType = "darkHorizontal"; break; case System.Drawing.Drawing2D.HatchStyle.LightHorizontal: PatternType = "lightHorizontal"; break; case System.Drawing.Drawing2D.HatchStyle.LightVertical: PatternType = "lightVertical"; break; case System.Drawing.Drawing2D.HatchStyle.DarkVertical: PatternType = "darkVertical"; break; case System.Drawing.Drawing2D.HatchStyle.Trellis: PatternType = "darkTrellis"; break; case System.Drawing.Drawing2D.HatchStyle.Percent05: PatternType = "gray0625"; break; //case System.Drawing.Drawing2D.HatchStyle.Min: case System.Drawing.Drawing2D.HatchStyle.Horizontal: case System.Drawing.Drawing2D.HatchStyle.Vertical: case System.Drawing.Drawing2D.HatchStyle.DiagonalCross: case System.Drawing.Drawing2D.HatchStyle.Percent10: case System.Drawing.Drawing2D.HatchStyle.Percent20: case System.Drawing.Drawing2D.HatchStyle.Percent25: case System.Drawing.Drawing2D.HatchStyle.Percent30: case System.Drawing.Drawing2D.HatchStyle.Percent40: case System.Drawing.Drawing2D.HatchStyle.Percent50: case System.Drawing.Drawing2D.HatchStyle.Percent60: case System.Drawing.Drawing2D.HatchStyle.Percent70: case System.Drawing.Drawing2D.HatchStyle.Percent75: case System.Drawing.Drawing2D.HatchStyle.Percent80: case System.Drawing.Drawing2D.HatchStyle.Percent90: case System.Drawing.Drawing2D.HatchStyle.LightDownwardDiagonal: case System.Drawing.Drawing2D.HatchStyle.LightUpwardDiagonal: case System.Drawing.Drawing2D.HatchStyle.WideDownwardDiagonal: case System.Drawing.Drawing2D.HatchStyle.WideUpwardDiagonal: case System.Drawing.Drawing2D.HatchStyle.NarrowVertical: case System.Drawing.Drawing2D.HatchStyle.NarrowHorizontal: case System.Drawing.Drawing2D.HatchStyle.DashedDownwardDiagonal: case System.Drawing.Drawing2D.HatchStyle.DashedUpwardDiagonal: case System.Drawing.Drawing2D.HatchStyle.DashedHorizontal: case System.Drawing.Drawing2D.HatchStyle.DashedVertical: case System.Drawing.Drawing2D.HatchStyle.SmallConfetti: case System.Drawing.Drawing2D.HatchStyle.LargeConfetti: case System.Drawing.Drawing2D.HatchStyle.ZigZag: case System.Drawing.Drawing2D.HatchStyle.Wave: case System.Drawing.Drawing2D.HatchStyle.DiagonalBrick: case System.Drawing.Drawing2D.HatchStyle.HorizontalBrick: case System.Drawing.Drawing2D.HatchStyle.Weave: case System.Drawing.Drawing2D.HatchStyle.Plaid: case System.Drawing.Drawing2D.HatchStyle.Divot: case System.Drawing.Drawing2D.HatchStyle.DottedGrid: case System.Drawing.Drawing2D.HatchStyle.DottedDiamond: case System.Drawing.Drawing2D.HatchStyle.Shingle: case System.Drawing.Drawing2D.HatchStyle.Sphere: case System.Drawing.Drawing2D.HatchStyle.SmallCheckerBoard: case System.Drawing.Drawing2D.HatchStyle.LargeCheckerBoard: case System.Drawing.Drawing2D.HatchStyle.OutlinedDiamond: case System.Drawing.Drawing2D.HatchStyle.SolidDiamond: break; } fills.Append(""); if (!swap_color) { fills.Append(""); fills.Append(""); } else { fills.Append(""); fills.Append(""); } fills.AppendLine(""); } else { if (EStyle.FillColor == Color.Transparent) { fills.AppendLine(""); fills.Append(""); fills.AppendLine(""); } else { fills.AppendLine(""); fills.Append(""); fills.AppendLine(""); } } fills.AppendLine(""); } fills.AppendLine(""); ExportUtils.WriteLn(file, fills.ToString()); } private void ExportBorders(Stream file) { StringBuilder borderResult = new StringBuilder(256); borderResult.Append(""); for (int i = 0; i < styles.Count; i++) { Border border = styles[i].Border; borderResult.AppendLine(""); if ((border.Lines & BorderLines.Left) != 0) borderResult.AppendLine( ""); else borderResult.AppendLine(""); if ((border.Lines & BorderLines.Right) != 0) borderResult.AppendLine( ""); else borderResult.AppendLine(""); if ((border.Lines & BorderLines.Top) != 0) borderResult.AppendLine( ""); else borderResult.AppendLine(""); if ((border.Lines & BorderLines.Bottom) != 0) borderResult.AppendLine( ""); else borderResult.AppendLine(""); borderResult.AppendLine(""); borderResult.AppendLine(""); } borderResult.AppendLine(""); ExportUtils.WriteLn(file, borderResult.ToString()); } private VertAlign TranslateVAligment270(HorzAlign ha) { switch (ha) { case HorzAlign.Left: return VertAlign.Bottom; case HorzAlign.Right: return VertAlign.Top; } return VertAlign.Center; } private HorzAlign TranslateHAligment270(VertAlign va) { switch (va) { case VertAlign.Top: return HorzAlign.Left; case VertAlign.Bottom: return HorzAlign.Right; } return HorzAlign.Center; } private VertAlign TranslateVAligment90(HorzAlign ha) { switch (ha) { case HorzAlign.Left: return VertAlign.Top; case HorzAlign.Right: return VertAlign.Bottom; } return VertAlign.Center; } private HorzAlign TranslateHAligment90(VertAlign va) { switch (va) { case VertAlign.Top: return HorzAlign.Right; case VertAlign.Bottom: return HorzAlign.Left; } return HorzAlign.Center; } private VertAlign TranslateVAligment180(VertAlign va) { switch (va) { case VertAlign.Top: return VertAlign.Bottom; case VertAlign.Bottom: return VertAlign.Top; } return VertAlign.Center; } private HorzAlign TranslateHAligment180(HorzAlign ha) { switch (ha) { case HorzAlign.Left: return HorzAlign.Right; case HorzAlign.Right: return HorzAlign.Left; } return HorzAlign.Center; } private void ExportAlgnment(StringBuilder file, ExportIEMStyle EStyle) { HorzAlign halign = EStyle.HAlign; VertAlign valign = EStyle.VAlign; if (EStyle.Angle != 0) { if (EStyle.Angle == 90) { valign = TranslateVAligment90(EStyle.HAlign); halign = TranslateHAligment90(EStyle.VAlign); } else if (EStyle.Angle == 180) { valign = TranslateVAligment180(EStyle.VAlign); halign = TranslateHAligment180(EStyle.HAlign); } else if (EStyle.Angle == 270) { valign = TranslateVAligment270(EStyle.HAlign); // VertAlign.Bottom; halign = TranslateHAligment270(EStyle.VAlign); // HorzAlign.Right; } else if (EStyle.Angle < 90) { halign = HorzAlign.Center; valign = VertAlign.Center; } else if (EStyle.Angle > 270) { halign = HorzAlign.Center; valign = VertAlign.Center; } } const double paddingScale = 10.0; int padding = 0; if (halign == HorzAlign.Left) padding = EStyle.Padding.Left; else if (halign == HorzAlign.Right) padding = EStyle.Padding.Right; if (EStyle.WordWrap) file.Append(""); else file.Append(""); } private void ExportCellStyles(Stream file) { StringBuilder styles = new StringBuilder(4096); styles.Append(""); for (int i = 0; i < this.styles.Count; i++) { ExportIEMStyle EStyle = this.styles[i]; if (EStyle.FillColor == Color.Transparent) { styles.Append(""); ExportAlgnment(styles, EStyle); styles.AppendLine(""); } else { styles.Append(""); ExportAlgnment(styles, EStyle); styles.AppendLine(""); } } styles.AppendLine(""); ExportUtils.Write(file, styles.ToString()); } public void Export(Excel2007Export OoXML) { Stream file; if (OoXML.UseFileStream) { string tempFileName = OoXML.GetFileName() + "2" + ".tmp"; file = new FileStream(tempFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite); OoXML.TempFileNames.Add(tempFileName); } else file = new MemoryStream(); ExportUtils.WriteLn(file, xml_header); ExportUtils.WriteLn(file, ""); currencyToAccounting = OoXML.CurrencyToAccounting; generalToText = OoXML.GeneralToText; ExportFormats(file); ExportFonts(file); ExportFills(file); ExportBorders(file); // Cell styles ExportCellStyles(file); ExportUtils.WriteLn(file, ""); file.Position = 0; OoXML.Zip.AddStream("xl/" + FileName, file); } public OoXMLDocumentStyles() { styles = new List(); formatIndex = 164; currencyToAccounting = false; generalToText = false; } internal int Add(OoXMLSheet sh) { ExportIEMStyle style = new ExportIEMStyle(); style.Border.Color = Color.Red; style.Border.Lines = BorderLines.All; //style.Font. = Color.Blue; styles.Add(style); styles.AddRange(sh.Matrix.Styles); return styles.Count; } } /// /// Workbook /// internal class OoXMLWorkbook : OoXMLBase { #region Class overrides public override string RelationType { get { return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; } } public override string ContentType { get { return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"; } } public override string FileName { get { return "xl/workbook.xml"; } } #endregion Class overrides #region Private properties private List sheetList = new List(); #endregion Private properties #region Internal properties internal OoXMLSheet[] SheetList { get { return sheetList.ToArray(); } } #endregion Internal properties internal void Export(Excel2007Export OoXML/*, ExportMatrix FMatrix*/) { Stream file; if (OoXML.UseFileStream) { string tempFileName = OoXML.GetFileName() + "3" + ".tmp"; file = new FileStream(tempFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite); OoXML.TempFileNames.Add(tempFileName); } else file = new MemoryStream(); StringBuilder sheets = new StringBuilder(4096); sheets.AppendLine(xml_header); sheets.AppendLine( ""); sheets.AppendLine(""); sheets.AppendLine(""); sheets.AppendLine(""); sheets.AppendLine(""); sheets.AppendLine(""); sheets.AppendLine(""); int page_name_idx = 0; foreach (OoXMLSheet sh in this.sheetList) { StringBuilder page_name_sb = new StringBuilder(sh.Name); if (page_name_sb.Length == 0) { page_name_idx++; page_name_sb.Append("Page_" + page_name_idx.ToString()); } else { page_name_sb.Replace("&", "&"); page_name_sb.Replace("<", "<"); page_name_sb.Replace(">", ">"); //forbidden character in name page title Excel2007 page_name_sb.Replace("?", string.Empty); } sheets.Append(""); } sheets.AppendLine(""); sheets.AppendLine(""); sheets.AppendLine(""); ExportUtils.Write(file, sheets.ToString()); file.Position = 0; OoXML.Zip.AddStream(FileName, file); } internal void AddSheet(OoXMLSheet sh) { sheetList.Add(sh); this.AddRelation(sheetList.Count + 20, sh); } } /// /// OoXMLSheet class /// internal class OoXMLSheet : OoXMLBase { #region Private properties private const float MARG_DIV = 25.4F; private ExportMatrix matrix; private string name; private int internal_index; #endregion Private properties #region Internal properties internal ExportMatrix Matrix { get { return matrix; } } internal string Name { get { return name; } } internal string SheetID { get { return internal_index.ToString(); } } internal int ID { set { internal_index = value; } } #endregion Internal properties #region Class overrides public override string RelationType { get { return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"; } } public override string ContentType { get { return "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"; } } public override string FileName { get { return "worksheets/sheet" + internal_index.ToString() + ".xml"; } } #endregion Class overrides private string ExportCell(Excel2007Export OoXML, ExportIEMObject Obj, int x, int y, int rowNum, int FirstStyleIndex) { StringBuilder cell = new StringBuilder(Obj.Text.Length + 30); if (Obj.IsNumeric || Obj.IsDateTime || Obj.IsPercent) { cell.Append(""); if (Obj.IsDateTime) cell.Append(Convert.ToString(Convert.ToDateTime(Obj.Value).ToOADate(), CultureInfo.InvariantCulture.NumberFormat)).Append(""); else if (Obj.IsPercent) cell.Append(Convert.ToString(Obj.Value, CultureInfo.InvariantCulture.NumberFormat)).Append(""); else cell.Append(Convert.ToString(Obj.Value, CultureInfo.InvariantCulture.NumberFormat)).Append(""); } else { String s = ExportUtils.Excel2007String(Obj.Text, Obj.TextRenderType); if (!String.IsNullOrEmpty(Obj.URL)) OoXML.URLTable.Add(x, y, Obj.URL); cell.Append("").Append(idx.ToString()).Append(""); } else cell.Append("\" t=\"s\">"); } return cell.ToString(); } internal string GetRangeReference(int i) { int fx, fy, dx, dy; matrix.ObjectPos(i, out fx, out fy, out dx, out dy); return "\"" + ExportUtils.GetCellReference(fx, fy + 1) + ":" + ExportUtils.GetCellReference(fx + dx - 1, fy + dy) + "\""; } internal string GetRangeReference(int i, int rowNum) { int fx, fy, dx, dy; matrix.ObjectPos(i, out fx, out fy, out dx, out dy); return "\"" + ExportUtils.GetCellReference(fx, rowNum - dy + 1) + ":" + ExportUtils.GetCellReference(fx + dx - 1, rowNum) + "\""; } internal void Export(Excel2007Export OoXML, int FirstStyleIndex, bool PageBreaks) { int merged_cells_count = 0; Stream file; if (OoXML.UseFileStream) { string tempFileName = OoXML.GetFileName() + "4" + SheetID + ".tmp"; file = new FileStream(tempFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite); OoXML.TempFileNames.Add(tempFileName); } else file = new MemoryStream(); StringBuilder builder = new StringBuilder(8192); StringBuilder merged = new StringBuilder(256); builder.Append(xml_header); builder.AppendLine(""); builder.AppendLine(OoXML.GetPageSetUpPr()); builder.AppendLine(OoXML.GetMatrixDimension(matrix)); builder.Append(""); builder.Append($""); if (OoXML.PinX > 0 || OoXML.PinY > 0) { string pinnedCells = ""; if (OoXML.PinX > 0) { pinnedCells += $" xSplit={Quoted(OoXML.PinX)}"; } if (OoXML.PinY > 0) { pinnedCells += $" ySplit={Quoted(OoXML.PinY)}"; } pinnedCells += $" topLeftCell={Quoted(ExportUtils.IndexToName(OoXML.PinX) + (OoXML.PinY + 1))}"; pinnedCells += " activePane=\"" + (OoXML.PinY > 0 ? "bottom" : "top") + (OoXML.PinX > 0 ? "Right" : "Left") + "\""; builder.Append($""); } builder.AppendLine(""); builder.AppendLine(""); builder.AppendLine(""); // sheet columns if (matrix.ObjectsCount > 0) { builder.Append(""); for (int x = 1; x < matrix.Width; x++) { builder.Append(""); } builder.AppendLine(""); } //if empty sheet if (matrix.Height == 0 && matrix.Width == 0) { builder.AppendLine(""); } else { builder.AppendLine(""); ExportUtils.Write(file, builder.ToString()); builder.Length = 0; for (int y = 0, rowNum = 1; y < matrix.Height - 1; y++) { StringBuilder line = new StringBuilder(128); float ht = 0; if (!matrix.IsYPosByIdNull(y) && !matrix.IsYPosByIdNull(y + 1)) { ht = (matrix.YPosById(y + 1) - matrix.YPosById(y)) / OoXML.YDivider; } else { ht = 14.5f; // Set default row height in Excel with font size equal 11. } int nonEmptyCells = 0; bool firstCellInRow = true; //Open the row without the closing tag ">" for further work with its attributes line.Append(""); } else { line.Append(" r=\"").Append((rowNum).ToString()).Append("\" ht=\""). Append(ExportUtils.FloatToString(ht)).Append("\" customHeight=\"1\">"); } firstCellInRow = false; } if (Obj.Counter < dy) { if ((dy == 1) || Obj.Counter == 0) { line.Append(ExportCell(OoXML, Obj, x, y, rowNum, FirstStyleIndex)); } else { line.Append(""); } for (int j = 1; j < dx; j++) { x++; line.Append(""); } if (!String.IsNullOrEmpty(Obj.Text) || (Obj.Style != null && (Obj.Style.Border.Lines != BorderLines.None || Obj.Style.FillColor != Color.White || Obj.Style.FillColor.A != 0) ) ) nonEmptyCells++; if (!Obj.IsText) { if (Obj.Width > 0 && Obj.Counter == 0) { OoXML.Drawing.Append(Obj, fx, fy, dx, dy, rowNum, matrix.Width); nonEmptyCells++; } } Obj.Counter++; if ((Obj.Counter == dy) && (dx > 1 || dy > 1)) { merged_cells_count++; if (!OoXML.Seamless) { merged.Append(""); } else { merged.Append(""); } } } } } if (firstCellInRow) { line.Append(" r=\"").Append((rowNum).ToString()).Append("\" ht=\""). Append(ExportUtils.FloatToString(ht)).Append("\" customHeight=\"1\">"); } line.AppendLine(""); if (!(OoXML.Seamless && nonEmptyCells == 0)) { ExportUtils.Write(file, line.ToString()); rowNum++; } if (y % 1000 == 0) Config.DoEvent(); } builder.AppendLine(""); } // merge cells if (merged_cells_count != 0) { builder.Append(""); builder.Append(merged); builder.Append(""); } // url list if (OoXML.URLTable.Count != 0) { builder.Append(OoXML.URLTable.ExportBody(OoXML)); } builder.Append(""); /* page setup */ builder.Append(""); /* row breaks */ if (PageBreaks) { int pages = 0; List pageBreaks = new List(); for (int i = 0; i <= matrix.Height - 1 && pages <= 1024; i++) { if (!matrix.IsYPosByIdNull(i) && (matrix.YPosById(i) >= matrix.PageBreak(pages))) { pageBreaks.Add(string.Format("", i)); pages++; } } if (pages > 0) { builder.AppendFormat("", pages - 1, pages - 1); builder.AppendLine(); for (int i = 0; i < pageBreaks.Count; i++) { builder.AppendLine(pageBreaks[i]); } builder.AppendLine(""); } } /* drawing */ if (OoXML.Drawing.PicCount != 0) { builder.Append(""); } /* Relations present in documents */ if (OoXML.URLTable.Count != 0 || OoXML.Drawing.PicCount != 0) { Stream rel_file; if (OoXML.UseFileStream) { string tempFileName = OoXML.GetFileName() + "5" + SheetID + ".tmp"; rel_file = new FileStream(tempFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite); OoXML.TempFileNames.Add(tempFileName); } else rel_file = new MemoryStream(); StreamWriter rel_out = new StreamWriter(rel_file); rel_out.WriteLine(xml_header); rel_out.WriteLine(""); if (OoXML.Drawing.PicCount != 0) { rel_out.WriteLine( ""); OoXML.SheetIDsWithPics.Add(SheetID); } if (OoXML.URLTable.Count != 0) { rel_out.WriteLine(OoXML.URLTable.ExportRelationship()); } rel_out.WriteLine(""); rel_out.Flush(); rel_file.Position = 0; OoXML.Zip.AddStream("xl/worksheets/_rels/sheet" + SheetID + ".xml.rels", rel_file); } builder.Append(""); ExportUtils.Write(file, builder.ToString()); file.Position = 0; OoXML.Zip.AddStream("xl/worksheets/sheet" + SheetID + ".xml", file); } private string GetPrintFitProp(Excel2007Export OoXML) { switch (OoXML.PrintFit) { case Excel2007Export.PrintFitMode.FitAllColumsOnOnePage: return " fitToHeight=\"0\""; case Excel2007Export.PrintFitMode.FitAllRowsOnOnePage: return " fitToWidth=\"0\""; default: return String.Empty; } } // public OoXMLSheet(ExportMatrix matrix, string Name, int Index) { this.matrix = matrix; name = Name; internal_index = Index; } } /// /// Excel 2007 export class /// public partial class Excel2007Export : OOExportBase { #region Enums /// /// Defines Print Scaling Mode. /// public enum PrintFitMode { /// /// Print sheets at thier actual size. /// NoScaling, /// /// Shrink the printout so that it fits on one page. /// FitSheetOnOnePage, /// /// Shrink the printout so that it is one page wide. /// FitAllColumsOnOnePage, /// /// Shrink the printout so that it is one page high. /// FitAllRowsOnOnePage } public enum ePictureProperties { /// /// Move and modify the picture along with the cell. /// MoveAndModify, /// /// Move but not resize the picture along with the cell. /// OnlyMove, /// /// Do not move or resize the picture along with the cell. /// Unchangeable } #endregion Enums #region Constants private const float oxmlXDivider = 6f; private const float oxmlYDivider = 1.333f; private float fontScale = 1f; #endregion Constants #region Private fields private bool useFileStream; private bool wysiwyg; private bool pageBreaks; private bool dataOnly; private bool seamless; private bool showGridlines; private bool groupOnSeparateSheet; private string groupName; private bool usePresetScale; private bool useLocaleFormating; private bool currencyToAccounting; private bool generalToText; private int printScale; private int pinX; private int pinY; private PrintFitMode printFitMode; private ePictureProperties pictureProperties; private OoXMLSharedStringTable stringTable; private OoXMLSharedURLTable uRLTable; internal OoXMLDrawing drawing; private OoXMLCoreDocumentProperties coreDocProp; private OoXMLApplicationProperties appProp; private OoXMLDocumentStyles docStyles; private OoXMLWorkbook workBook; private Dictionary sheets; private List tempFileNames; private ExportMatrix matrix; private bool printOptimized = false; private bool splitPages; private ReportPage currentPage; private bool firstPage = true; private float bandHeight = 0; private bool firstGroupHeaderBand = true; private bool ungroupSheets = false; private List sheetIDsWithPics; private bool needCreateNewList = false; #endregion Private fields #region Properties internal OoXMLDrawing Drawing { get { return drawing; } } internal OoXMLSharedStringTable StringTable { get { return stringTable; } } internal OoXMLSharedURLTable URLTable { get { return uRLTable; } } internal float YDivider { get { return oxmlYDivider; } } internal float XDivider { get { return oxmlXDivider; } } internal List SheetIDsWithPics { get { return sheetIDsWithPics; } set { sheetIDsWithPics = value; } } /// /// Gets or sets the Print Fit Mode. /// public PrintFitMode PrintFit { get { return printFitMode; } set { printFitMode = value; } } /// /// Gets or sets the print scaling (value from 10 to 400). /// public int PrintScale { get { return printScale; } set { printScale = value; } } /// /// Gets or sets the pinned cells in X ordinate. /// public int PinX { get { return pinX; } set { pinX = value; } } /// /// Gets or sets the pinned cells in Y ordinate. /// public int PinY { get { return pinY; } set { pinY = value; } } /// /// Sets or gets the flag using the preset print scale. /// public bool UsePresetScale { get { return usePresetScale; } set { usePresetScale = value; } } /// /// Gets or sets a value that determines whether the using locale data formatting. /// public bool UseLocaleFormating { get { return useLocaleFormating; } set { useLocaleFormating = value; } } /// /// Enable or disable show gridlines. /// public bool ShowGridlines { get { return showGridlines; } set { showGridlines = value; } } /// /// Gets or sets the font scale value. /// Default value is 1 /// public float FontScale { get { return fontScale; } set { fontScale = value != 0 ? value : 0.01f; } } /// /// Enable or disable a resolution optimization. /// public bool PrintOptimized { get { return printOptimized; } set { printOptimized = value; } } /// /// Each report page is placed on a new Excel page. /// public bool SplitPages { get { return splitPages; } set { splitPages = value; } } /// /// Each group is placed on a new Excel page. /// public bool GroupOnSeparateSheet { get { return groupOnSeparateSheet; } set { groupOnSeparateSheet = value; } } /// /// Name of the selected group. /// public string GroupName { get { return groupName; } set { groupName = 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 a value indicating that FileStream should be used instead of MomoryStream during export. /// /// /// Enabling this option will reduce memory consumption, but increase the time of export. /// public bool UseFileStream { get { return useFileStream; } set { useFileStream = value; } } /// /// Gets or sets a value indicating that currency should be converted to accounting format. /// public bool CurrencyToAccounting { get { return currencyToAccounting; } set { currencyToAccounting = value; } } /// /// Gets or sets a value indicating that general should be converted to text format. /// public bool GeneralToText { get { return generalToText; } set { generalToText = value; } } /// /// For delete temp files /// internal List TempFileNames { get { return tempFileNames; } set { tempFileNames = value; } } /// /// 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 to export the databand rows only. /// public bool DataOnly { get { return dataOnly; } set { dataOnly = value; } } /// /// Enable or disable export of page footers and next page headers without table breaks. /// public bool Seamless { get { return seamless; } set { seamless = value; } } /// /// Gets or sets a value that determines whether to export the databand rows only. /// public ePictureProperties PictureProperties { get { return pictureProperties; } set { pictureProperties = value; } } /// /// Grouping or ungrouping sheets. Grouping is enabled by default. /// public bool UngroupSheets { get { return ungroupSheets; } set { ungroupSheets = value; } } #endregion Properties #region Private Methods private void CreateThemes() { // get a reference to the current assembly Assembly a = Assembly.GetExecutingAssembly(); // get a list of resource names from the manifest //string[] resNames = a.GetManifestResourceNames(); using (Stream outStream = a.GetManifestResourceStream("FastReport.Resources.OoXML.theme1.xml")) { Stream fs; if (UseFileStream) { string tempFileName = GetFileName() + "6" + ".tmp"; fs = new FileStream(tempFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite); TempFileNames.Add(tempFileName); } else fs = new MemoryStream(); const int BUFFER_SIZE = 4096; outStream.CopyTo(fs, BUFFER_SIZE); fs.Position = 0; Zip.AddStream("xl/theme/theme1.xml", fs); } } private void CreateContentTypes() { Stream file; if (UseFileStream) { string tempFileName = GetFileName() + "7" + ".tmp"; file = new FileStream(tempFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite); TempFileNames.Add(tempFileName); } else file = new MemoryStream(); ExportUtils.WriteLn(file, xml_header); ExportUtils.Write(file, ""); CreateThemes(); ExportUtils.Write(file, ""); ExportUtils.Write(file, ""); ExportUtils.Write(file, ""); ExportUtils.Write(file, ""); ExportUtils.Write(file, ""); ExportUtils.Write(file, ""); ExportUtils.Write(file, ""); CreateWorkbookRelations(); foreach (OoXMLSheet sh in workBook.SheetList) { ExportUtils.Write(file, ""); //===johnny appended 2012/6/17 if (SheetIDsWithPics.Contains(sh.SheetID)) { ExportUtils.Write(file, ""); } } ExportUtils.Write(file, ""); ExportUtils.Write(file, ""); ExportUtils.Write(file, ""); file.Position = 0; Zip.AddStream("[Content_Types].xml", file); } private void CreateRelations() { MemoryStream file = new MemoryStream(); ExportUtils.WriteLn(file, xml_header); ExportUtils.WriteLn(file, ""); ExportUtils.WriteLn(file, ""); ExportUtils.WriteLn(file, ""); ExportUtils.WriteLn(file, ""); ExportUtils.WriteLn(file, ""); file.Position = 0; Zip.AddStream("_rels/.rels", file); } private void CreateWorkbookRelations() { MemoryStream file = new MemoryStream(); ExportUtils.WriteLn(file, xml_header); ExportUtils.WriteLn(file, ""); ExportUtils.WriteLn(file, ""); ExportUtils.WriteLn(file, ""); foreach (OoXMLSheet sh in workBook.SheetList) { ExportUtils.WriteLn(file, ""); } ExportUtils.WriteLn(file, ""); ExportUtils.WriteLn(file, ""); file.Position = 0; Zip.AddStream("xl/_rels/workbook.xml.rels", file); } internal string GetMatrixDimension(ExportMatrix Matrix) { if (Matrix.Width == 0 && Matrix.Height == 0) return ""; else return ""; } internal string GetPageSetUpPr() { if (PrintFit != PrintFitMode.NoScaling && usePresetScale) return ""; else return String.Empty; } private void ExportOOXML(Stream Stream) { CreateRelations(); int current_style_set = 0; foreach (OoXMLSheet sh in workBook.SheetList) { sh.Matrix.Prepare(); Drawing.Start(); int styles_count = 0; if (FontScale != 1) for (int i = 0; i < sh.Matrix.Styles.Count; i++) { Font font = sh.Matrix.Styles[i].Font; float scaledSize = (float)Math.Round(font.Size * FontScale); float newSize = scaledSize == 0 ? 1 : scaledSize; sh.Matrix.Styles[i].Font = new Font(font.FontFamily, newSize, font.Style); } styles_count = docStyles.Add(sh); sh.Export(this, current_style_set, pageBreaks); current_style_set = styles_count; Drawing.Stop(sh.SheetID); } docStyles.Export(this); appProp.Export(this); stringTable.Export(this); coreDocProp.Export(this); workBook.Export(this); CreateContentTypes(); } private void NewMatrix() { matrix = new ExportMatrix(); if (wysiwyg) matrix.Inaccuracy = 0.05f; else matrix.Inaccuracy = 5; matrix.ShowProgress = ShowProgress; matrix.PlainRich = true; matrix.AreaFill = false; matrix.CropAreaFill = true; matrix.Report = Report; matrix.Images = true; matrix.PrintOptimized = printOptimized; if (printOptimized) matrix.ImageResolution = 300; else matrix.ImageResolution = 150; matrix.WrapText = false; matrix.FullTrust = false; matrix.DataOnly = DataOnly; matrix.MaxCellHeight = 409 * oxmlYDivider; matrix.Seamless = seamless; } #endregion Private Methods #region Protected Methods /// protected override void Start() { base.Start(); Zip = new ZipArchive(); stringTable = new OoXMLSharedStringTable(); uRLTable = new OoXMLSharedURLTable(); drawing = new OoXMLDrawing(this); coreDocProp = new OoXMLCoreDocumentProperties(); appProp = new OoXMLApplicationProperties(); docStyles = new OoXMLDocumentStyles(); docStyles.UseLocaleFormating = UseLocaleFormating; workBook = new OoXMLWorkbook(); sheets = new Dictionary(); } /// protected override void ExportPageBegin(ReportPage page) { if ((groupOnSeparateSheet)) { base.ExportPageBegin(page); if (firstPage) NewMatrix(); if (currentPage != null) matrix.AddPageEnd(currentPage); this.currentPage = page; matrix.AddPageBegin(page); firstPage = false; } else { base.ExportPageBegin(page); // If after exporting the next page, // the number of rows in the matrix (matrix.Height) is greater than 1 000 000, // a new sheet is created if (matrix != null && matrix.Height > 1000000) needCreateNewList = true; else needCreateNewList = false; if (sheets.ContainsKey(page.Name) && !SplitPages && !needCreateNewList) { matrix = sheets.LastOrDefault().Value.Matrix; } else { NewMatrix(); } matrix.AddPageBegin(page); } } /// protected override void ExportBand(BandBase band) { // added a bool variable and a condition that determines by which GroupHeaderBand to divide the report into sheets // firstGroupHeaderBand is true by default and changes its value for the following GroupHeaderBand // so that new sheets are created for them // GroupName contains the name of the group: // if there is one group in the report or the value "All groups" is selected, then the variable will be null, // otherwise - the name of the group by which the report is divided into sheets if (band.ClassName is "GroupHeaderBand" && groupOnSeparateSheet && !firstGroupHeaderBand && (GroupName is null || GroupName == band.Name)) { OoXMLSheet sh = new OoXMLSheet(matrix, "Page" + (sheets.Count + 1), sheets.Count + 1); sheets["Page" + (sheets.Count + 1)] = sh; workBook.AddSheet(sh); NewMatrix(); bandHeight = 0; RectangleF rect = new RectangleF(band.Bounds.X, bandHeight, band.Bounds.Width, band.Bounds.Height); band.Bounds = rect; bandHeight += band.Bounds.Height; matrix.AddPageBegin(currentPage); base.ExportBand(band); matrix.AddBand(band, this); } else { if (band.ClassName is "GroupHeaderBand" && groupOnSeparateSheet && (GroupName is null || GroupName == band.Name)) firstGroupHeaderBand = false; if (groupOnSeparateSheet) { if (bandHeight + band.Bounds.Height > currentPage.Height) bandHeight = 0; RectangleF rect = new RectangleF(band.Bounds.X, bandHeight, band.Bounds.Width, band.Bounds.Height); band.Bounds = rect; bandHeight += band.Bounds.Height; } base.ExportBand(band); matrix.AddBand(band, this); } } /// protected override void ExportPageEnd(ReportPage page) { if (!groupOnSeparateSheet) { matrix.AddPageEnd(page); if (!sheets.ContainsKey(page.Name) || SplitPages || needCreateNewList) { string suffix = ""; if (SplitPages || needCreateNewList) { if (sheets.ContainsKey(page.Name + "-1")) { int repeats = 2; while (sheets.ContainsKey(page.Name + "-" + repeats.ToString())) repeats++; suffix = "-" + repeats.ToString(); } else { ReportPage nextPage = Report.PreparedPages.GetPage(sheets.Count + 1); if (nextPage != null && nextPage.Name == page.Name) suffix = "-1"; } } OoXMLSheet sh = new OoXMLSheet(matrix, (String.IsNullOrEmpty(page.ExportAlias) ? page.Name : page.ExportAlias) + suffix, sheets.Count + 1); sheets[page.Name + suffix] = sh; workBook.AddSheet(sh); } } } /// protected override void Finish() { if (groupOnSeparateSheet) { matrix.AddPageEnd(currentPage); OoXMLSheet sh = new OoXMLSheet(matrix, "Page" + (sheets.Count + 1), sheets.Count + 1); sheets["Page" + (sheets.Count + 1)] = sh; workBook.AddSheet(sh); } ExportOOXML(Stream); Zip.SaveToStream(Stream); if (useFileStream) { Zip.Clear(); Stream.Close(); foreach (string item in TempFileNames) { File.Delete(item); } } else Zip.Clear(); foreach (OoXMLSheet sheet in workBook.SheetList) sheet.Matrix.Dispose(); GC.Collect(2); } /// protected override string GetFileFilter() { return new MyRes("FileFilters").Get("XlsxFile"); } #endregion Protected Methods /// /// Gets the file name to export to. /// /// The full file name to export to. public string GetFileName() { return FileName; } /// public override void Serialize(FRWriter writer) { base.Serialize(writer); writer.WriteBool("Wysiwyg", Wysiwyg); writer.WriteBool("PageBreaks", PageBreaks); writer.WriteBool("DataOnly", DataOnly); writer.WriteBool("GroupOnSeparateSheet", GroupOnSeparateSheet); writer.WriteBool("Seamless", Seamless); writer.WriteBool("PrintOptimized", PrintOptimized); writer.WriteBool("SplitPages", SplitPages); writer.WriteFloat("FontScale", FontScale); writer.WriteValue("PrintFit", PrintFit); writer.WriteBool("ShowGridlines", ShowGridlines); writer.WriteBool("UngroupSheets", UngroupSheets); writer.WriteBool("UsePresetScale", UsePresetScale); writer.WriteInt("PrintScale", PrintScale); writer.WriteValue("PictureProperties", PictureProperties); writer.WriteInt("PinY", PinY); writer.WriteInt("PinX", PinX); writer.WriteBool("UseLocaleFormating", UseLocaleFormating); writer.WriteBool("CurrencyToAccounting", CurrencyToAccounting); writer.WriteBool("GeneralToText", GeneralToText); } /// /// Initializes a new instance of the class. /// public Excel2007Export() { pageBreaks = true; seamless = false; wysiwyg = true; showGridlines = true; printFitMode = PrintFitMode.NoScaling; pictureProperties = ePictureProperties.MoveAndModify; sheetIDsWithPics = new List(); tempFileNames = new List(); printScale = 10; usePresetScale = true; useLocaleFormating = false; currencyToAccounting = false; generalToText = false; useFileStream = false; pinX = 0; pinY = 0; } } }