diff --git a/ClosedXML/Excel/XLWorkbook.cs b/ClosedXML/Excel/XLWorkbook.cs index 62bc96f..ed6398f 100644 --- a/ClosedXML/Excel/XLWorkbook.cs +++ b/ClosedXML/Excel/XLWorkbook.cs @@ -1,959 +1,959 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Security.AccessControl; -using ClosedXML.Excel.CalcEngine; -using DocumentFormat.OpenXml; - -namespace ClosedXML.Excel -{ - using System.Linq; - using System.Data; - - public enum XLEventTracking { Enabled, Disabled } - public enum XLCalculateMode - { - Auto, - AutoNoTable, - Manual, - Default - }; - - public enum XLReferenceStyle - { - R1C1, - A1, - Default - }; - - public enum XLCellSetValueBehavior - { - /// - /// Analyze input string and convert value. For avoid analyzing use escape symbol ' - /// - Smart = 0, - - /// - /// Direct set value. If value has unsupported type - value will be stored as string returned by - /// - Simple = 1, - } - - public partial class XLWorkbook: IDisposable - { - #region Static - - private static IXLStyle _defaultStyle; - - public static IXLStyle DefaultStyle - { - get - { - return _defaultStyle ?? (_defaultStyle = new XLStyle(null) - { - Font = new XLFont(null, null) - { - Bold = false, - Italic = false, - Underline = XLFontUnderlineValues.None, - Strikethrough = false, - VerticalAlignment = - XLFontVerticalTextAlignmentValues. - Baseline, - FontSize = 11, - FontColor = XLColor.FromArgb(0, 0, 0), - FontName = "Calibri", - FontFamilyNumbering = - XLFontFamilyNumberingValues.Swiss - }, - Fill = new XLFill(null) - { - BackgroundColor = XLColor.FromIndex(64), - PatternType = XLFillPatternValues.None, - PatternColor = XLColor.FromIndex(64) - }, - Border = new XLBorder(null, null) - { - BottomBorder = - XLBorderStyleValues.None, - DiagonalBorder = - XLBorderStyleValues.None, - DiagonalDown = false, - DiagonalUp = false, - LeftBorder = XLBorderStyleValues.None, - RightBorder = XLBorderStyleValues.None, - TopBorder = XLBorderStyleValues.None, - BottomBorderColor = XLColor.Black, - DiagonalBorderColor = XLColor.Black, - LeftBorderColor = XLColor.Black, - RightBorderColor = XLColor.Black, - TopBorderColor = XLColor.Black - }, - NumberFormat = - new XLNumberFormat(null, null) {NumberFormatId = 0}, - Alignment = new XLAlignment(null) - { - Indent = 0, - Horizontal = - XLAlignmentHorizontalValues. - General, - JustifyLastLine = false, - ReadingOrder = - XLAlignmentReadingOrderValues. - ContextDependent, - RelativeIndent = 0, - ShrinkToFit = false, - TextRotation = 0, - Vertical = - XLAlignmentVerticalValues. - Bottom, - WrapText = false - }, - Protection = new XLProtection(null) - { - Locked = true, - Hidden = false - } - }); - } - } - - public static Double DefaultRowHeight { get; private set; } - public static Double DefaultColumnWidth { get; private set; } - - public static IXLPageSetup DefaultPageOptions - { - get - { - var defaultPageOptions = new XLPageSetup(null, null) - { - PageOrientation = XLPageOrientation.Default, - Scale = 100, - PaperSize = XLPaperSize.LetterPaper, - Margins = new XLMargins - { - Top = 0.75, - Bottom = 0.5, - Left = 0.75, - Right = 0.75, - Header = 0.5, - Footer = 0.75 - }, - ScaleHFWithDocument = true, - AlignHFWithMargins = true, - PrintErrorValue = XLPrintErrorValues.Displayed, - ShowComments = XLShowCommentsValues.None - }; - return defaultPageOptions; - } - } - - public static IXLOutline DefaultOutline - { - get - { - return new XLOutline(null) - { - SummaryHLocation = XLOutlineSummaryHLocation.Right, - SummaryVLocation = XLOutlineSummaryVLocation.Bottom - }; - } - } - - /// - /// Behavior for - /// - public static XLCellSetValueBehavior CellSetValueBehavior { get; set; } - - #endregion - - internal readonly List UnsupportedSheets = - new List(); - - private readonly Dictionary _stylesById = new Dictionary(); - private readonly Dictionary _stylesByStyle = new Dictionary(); - - public XLEventTracking EventTracking { get; set; } - - internal Int32 GetStyleId(IXLStyle style) - { - Int32 cached; - if (_stylesByStyle.TryGetValue(style, out cached)) - return cached; - - var count = _stylesByStyle.Count; - var styleToUse = new XLStyle(null, style); - _stylesByStyle.Add(styleToUse, count); - _stylesById.Add(count, styleToUse); - return count; - } - - internal IXLStyle GetStyleById(Int32 id) - { - return _stylesById[id]; - } - - #region Nested Type: XLLoadSource - - private enum XLLoadSource - { - New, - File, - Stream - }; - - #endregion - - internal XLWorksheets WorksheetsInternal { get; private set; } - - /// - /// Gets an object to manipulate the worksheets. - /// - public IXLWorksheets Worksheets - { - get { return WorksheetsInternal; } - } - - /// - /// Gets an object to manipulate this workbook's named ranges. - /// - public IXLNamedRanges NamedRanges { get; private set; } - - /// - /// Gets an object to manipulate this workbook's theme. - /// - public IXLTheme Theme { get; private set; } - - /// - /// Gets or sets the default style for the workbook. - /// All new worksheets will use this style. - /// - public IXLStyle Style { get; set; } - - /// - /// Gets or sets the default row height for the workbook. - /// All new worksheets will use this row height. - /// - public Double RowHeight { get; set; } - - /// - /// Gets or sets the default column width for the workbook. - /// All new worksheets will use this column width. - /// - public Double ColumnWidth { get; set; } - - /// - /// Gets or sets the default page options for the workbook. - /// All new worksheets will use these page options. - /// - public IXLPageSetup PageOptions { get; set; } - - /// - /// Gets or sets the default outline options for the workbook. - /// All new worksheets will use these outline options. - /// - public IXLOutline Outline { get; set; } - - /// - /// Gets or sets the workbook's properties. - /// - public XLWorkbookProperties Properties { get; set; } - - /// - /// Gets or sets the workbook's calculation mode. - /// - public XLCalculateMode CalculateMode { get; set; } - - - public Boolean CalculationOnSave { get; set; } - public Boolean ForceFullCalculation { get; set; } - public Boolean FullCalculationOnLoad { get; set; } - public Boolean FullPrecision { get; set; } - - /// - /// Gets or sets the workbook's reference style. - /// - public XLReferenceStyle ReferenceStyle { get; set; } - - public IXLCustomProperties CustomProperties { get; private set; } - - public Boolean ShowFormulas { get; set; } - public Boolean ShowGridLines { get; set; } - public Boolean ShowOutlineSymbols { get; set; } - public Boolean ShowRowColHeaders { get; set; } - public Boolean ShowRuler { get; set; } - public Boolean ShowWhiteSpace { get; set; } - public Boolean ShowZeros { get; set; } - public Boolean RightToLeft { get; set; } - - public Boolean DefaultShowFormulas - { - get { return false; } - } - - public Boolean DefaultShowGridLines - { - get { return true; } - } - - public Boolean DefaultShowOutlineSymbols - { - get { return true; } - } - - public Boolean DefaultShowRowColHeaders - { - get { return true; } - } - - public Boolean DefaultShowRuler - { - get { return true; } - } - - public Boolean DefaultShowWhiteSpace - { - get { return true; } - } - - public Boolean DefaultShowZeros - { - get { return true; } - } - - public Boolean DefaultRightToLeft - { - get { return false; } - } - - private void InitializeTheme() - { - Theme = new XLTheme - { - Text1 = XLColor.FromHtml("#FF000000"), - Background1 = XLColor.FromHtml("#FFFFFFFF"), - Text2 = XLColor.FromHtml("#FF1F497D"), - Background2 = XLColor.FromHtml("#FFEEECE1"), - Accent1 = XLColor.FromHtml("#FF4F81BD"), - Accent2 = XLColor.FromHtml("#FFC0504D"), - Accent3 = XLColor.FromHtml("#FF9BBB59"), - Accent4 = XLColor.FromHtml("#FF8064A2"), - Accent5 = XLColor.FromHtml("#FF4BACC6"), - Accent6 = XLColor.FromHtml("#FFF79646"), - Hyperlink = XLColor.FromHtml("#FF0000FF"), - FollowedHyperlink = XLColor.FromHtml("#FF800080") - }; - } - - internal XLColor GetXLColor(XLThemeColor themeColor) - { - switch (themeColor) - { - case XLThemeColor.Text1: - return Theme.Text1; - case XLThemeColor.Background1: - return Theme.Background1; - case XLThemeColor.Text2: - return Theme.Text2; - case XLThemeColor.Background2: - return Theme.Background2; - case XLThemeColor.Accent1: - return Theme.Accent1; - case XLThemeColor.Accent2: - return Theme.Accent2; - case XLThemeColor.Accent3: - return Theme.Accent3; - case XLThemeColor.Accent4: - return Theme.Accent4; - case XLThemeColor.Accent5: - return Theme.Accent5; - case XLThemeColor.Accent6: - return Theme.Accent6; - default: - throw new ArgumentException("Invalid theme color"); - } - } - - public IXLNamedRange NamedRange(String rangeName) - { - if (rangeName.Contains("!")) - { - var split = rangeName.Split('!'); - var first = split[0]; - var wsName = first.StartsWith("'") ? first.Substring(1, first.Length - 2) : first; - var name = split[1]; - IXLWorksheet ws; - if (TryGetWorksheet(wsName, out ws)) - { - var range = ws.NamedRange(name); - return range ?? NamedRange(name); - } - return null; - } - return NamedRanges.NamedRange(rangeName); - } - - public Boolean TryGetWorksheet(String name, out IXLWorksheet worksheet) - { - if (Worksheets.Any(w => string.Equals(w.Name, XLWorksheets.TrimSheetName(name), StringComparison.OrdinalIgnoreCase))) - { - worksheet = Worksheet(name); - return true; - } - - worksheet = null; - return false; - } - - public IXLRange RangeFromFullAddress(String rangeAddress, out IXLWorksheet ws) - { - ws = null; - if (!rangeAddress.Contains('!')) return null; - - var split = rangeAddress.Split('!'); - var first = split[0]; - var wsName = first.StartsWith("'") ? first.Substring(1, first.Length - 2) : first; - var localRange = split[1]; - if (TryGetWorksheet(wsName, out ws)) - { - return ws.Range(localRange); - } - return null; - } - - - /// - /// Saves the current workbook. - /// - public void Save() - { -#if DEBUG - Save(true, false); -#else - Save(false, false); -#endif - } - - /// - /// Saves the current workbook and optionally performs validation - /// - public void Save(Boolean validate, Boolean evaluateFormulae = false) - { - checkForWorksheetsPresent(); - if (_loadSource == XLLoadSource.New) - throw new Exception("This is a new file, please use one of the SaveAs methods."); - - if (_loadSource == XLLoadSource.Stream) - { - CreatePackage(_originalStream, false, _spreadsheetDocumentType, validate, evaluateFormulae); - } - else - CreatePackage(_originalFile, _spreadsheetDocumentType, validate, evaluateFormulae); - } - - /// - /// Saves the current workbook to a file. - /// - public void SaveAs(String file) - { -#if DEBUG - SaveAs(file, true, false); -#else - SaveAs(file, false, false); -#endif - } - - /// - /// Saves the current workbook to a file and optionally validates it. - /// - public void SaveAs(String file, Boolean validate, Boolean evaluateFormulae = false) - { - checkForWorksheetsPresent(); - PathHelper.CreateDirectory(Path.GetDirectoryName(file)); - if (_loadSource == XLLoadSource.New) - { - if (File.Exists(file)) - File.Delete(file); - - CreatePackage(file, GetSpreadsheetDocumentType(file), validate, evaluateFormulae); - } - else if (_loadSource == XLLoadSource.File) - { - if (String.Compare(_originalFile.Trim(), file.Trim(), true) != 0) - File.Copy(_originalFile, file, true); - - CreatePackage(file, GetSpreadsheetDocumentType(file), validate, evaluateFormulae); - } - else if (_loadSource == XLLoadSource.Stream) - { - _originalStream.Position = 0; - - using (var fileStream = File.Create(file)) - { - CopyStream(_originalStream, fileStream); - //fileStream.Position = 0; - CreatePackage(fileStream, false, _spreadsheetDocumentType, validate, evaluateFormulae); - fileStream.Close(); - } - } - } - - private static SpreadsheetDocumentType GetSpreadsheetDocumentType(string filePath) - { - var extension = Path.GetExtension(filePath); - if (extension == null) throw new Exception("Empty extension is not supported."); - extension = extension.Substring(1).ToLowerInvariant(); - - switch (extension) - { - case "xlsm": - case "xltm": - return SpreadsheetDocumentType.MacroEnabledWorkbook; - case "xlsx": - case "xltx": - return SpreadsheetDocumentType.Workbook; - default: - throw new ArgumentException(String.Format("Extension '{0}' is not supported. Supported extensions are '.xlsx', '.xslm', '.xltx' and '.xltm'.", extension)); - - } - } - - private void checkForWorksheetsPresent() - { - if (Worksheets.Count() == 0) - throw new Exception("Workbooks need at least one worksheet."); - } - - /// - /// Saves the current workbook to a stream. - /// - public void SaveAs(Stream stream) - { -#if DEBUG - SaveAs(stream, true, false); -#else - SaveAs(stream, false, false); -#endif - } - - /// - /// Saves the current workbook to a stream and optionally validates it. - /// - public void SaveAs(Stream stream, Boolean validate, Boolean evaluateFormulae = false) - { - checkForWorksheetsPresent(); - if (_loadSource == XLLoadSource.New) - { - // dm 20130422, this method or better the method SpreadsheetDocument.Create which is called - // inside of 'CreatePackage' need a stream which CanSeek & CanRead - // and an ordinary Response stream of a webserver can't do this - // so we have to ask and provide a way around this - if (stream.CanRead && stream.CanSeek && stream.CanWrite) - { - // all is fine the package can be created in a direct way - CreatePackage(stream, true, _spreadsheetDocumentType, validate, evaluateFormulae); - } - else - { - // the harder way - MemoryStream ms = new MemoryStream(); - CreatePackage(ms, true, _spreadsheetDocumentType, validate, evaluateFormulae); - // not really nessesary, because I changed CopyStream too. - // but for better understanding and if somebody in the future - // provide an changed version of CopyStream - ms.Position = 0; - CopyStream(ms, stream); - } - } - else if (_loadSource == XLLoadSource.File) - { - using (var fileStream = new FileStream(_originalFile, FileMode.Open, FileAccess.Read)) - { - CopyStream(fileStream, stream); - fileStream.Close(); - } - CreatePackage(stream, false, _spreadsheetDocumentType, validate, evaluateFormulae); - } - else if (_loadSource == XLLoadSource.Stream) - { - _originalStream.Position = 0; - if (_originalStream != stream) - CopyStream(_originalStream, stream); - - CreatePackage(stream, false, _spreadsheetDocumentType, validate, evaluateFormulae); - } - } - - internal static void CopyStream(Stream input, Stream output) - { - var buffer = new byte[8 * 1024]; - int len; - // dm 20130422, it is always a good idea to rewind the input stream, or not? - if (input.CanSeek) - input.Seek(0, SeekOrigin.Begin); - while ((len = input.Read(buffer, 0, buffer.Length)) > 0) - output.Write(buffer, 0, len); - // dm 20130422, and flushing the output after write - output.Flush(); - - } - - public IXLWorksheet Worksheet(String name) - { - return WorksheetsInternal.Worksheet(name); - } - - public IXLWorksheet Worksheet(Int32 position) - { - return WorksheetsInternal.Worksheet(position); - } - - public IXLCustomProperty CustomProperty(String name) - { - return CustomProperties.CustomProperty(name); - } - - public IXLCells FindCells(Func predicate) - { - var cells = new XLCells(false, false); - foreach (XLWorksheet ws in WorksheetsInternal) - { - foreach (XLCell cell in ws.CellsUsed(true)) - { - if (predicate(cell)) - cells.Add(cell); - } - } - return cells; - } - - public IXLRows FindRows(Func predicate) - { - var rows = new XLRows(null); - foreach (XLWorksheet ws in WorksheetsInternal) - { - foreach (IXLRow row in ws.Rows().Where(predicate)) - rows.Add(row as XLRow); - } - return rows; - } - - public IXLColumns FindColumns(Func predicate) - { - var columns = new XLColumns(null); - foreach (XLWorksheet ws in WorksheetsInternal) - { - foreach (IXLColumn column in ws.Columns().Where(predicate)) - columns.Add(column as XLColumn); - } - return columns; - } - -#region Fields - - private readonly XLLoadSource _loadSource = XLLoadSource.New; - private readonly String _originalFile; - private readonly Stream _originalStream; - -#endregion - -#region Constructor - - - /// - /// Creates a new Excel workbook. - /// - public XLWorkbook() - :this(XLEventTracking.Enabled) - { - - } - - public XLWorkbook(XLEventTracking eventTracking) - { - EventTracking = eventTracking; - DefaultRowHeight = 15; - DefaultColumnWidth = 8.43; - Style = new XLStyle(null, DefaultStyle); - RowHeight = DefaultRowHeight; - ColumnWidth = DefaultColumnWidth; - PageOptions = DefaultPageOptions; - Outline = DefaultOutline; - Properties = new XLWorkbookProperties(); - CalculateMode = XLCalculateMode.Default; - ReferenceStyle = XLReferenceStyle.Default; - InitializeTheme(); - ShowFormulas = DefaultShowFormulas; - ShowGridLines = DefaultShowGridLines; - ShowOutlineSymbols = DefaultShowOutlineSymbols; - ShowRowColHeaders = DefaultShowRowColHeaders; - ShowRuler = DefaultShowRuler; - ShowWhiteSpace = DefaultShowWhiteSpace; - ShowZeros = DefaultShowZeros; - RightToLeft = DefaultRightToLeft; - WorksheetsInternal = new XLWorksheets(this); - NamedRanges = new XLNamedRanges(this); - CustomProperties = new XLCustomProperties(this); - ShapeIdManager = new XLIdManager(); - Author = Environment.UserName; - } - - /// - /// Opens an existing workbook from a file. - /// - /// The file to open. - public XLWorkbook(String file) - : this(file, XLEventTracking.Enabled) - { - - } - - public XLWorkbook(String file, XLEventTracking eventTracking) - : this(eventTracking) - { - _loadSource = XLLoadSource.File; - _originalFile = file; - _spreadsheetDocumentType = GetSpreadsheetDocumentType(_originalFile); - Load(file); - } - - - - /// - /// Opens an existing workbook from a stream. - /// - /// The stream to open. - public XLWorkbook(Stream stream):this(stream, XLEventTracking.Enabled) - { - - } - - public XLWorkbook(Stream stream, XLEventTracking eventTracking) - : this(eventTracking) - { - _loadSource = XLLoadSource.Stream; - _originalStream = stream; - Load(stream); - } - -#endregion - -#region Nested type: UnsupportedSheet - - internal sealed class UnsupportedSheet - { - public Boolean IsActive; - public UInt32 SheetId; - public Int32 Position; - } - -#endregion - - public IXLCell Cell(String namedCell) - { - var namedRange = NamedRange(namedCell); - if (namedRange == null) return null; - var range = namedRange.Ranges.FirstOrDefault(); - if (range == null) return null; - return range.FirstCell(); - } - - public IXLCells Cells(String namedCells) - { - return Ranges(namedCells).Cells(); - } - - public IXLRange Range(String range) - { - var namedRange = NamedRange(range); - if (namedRange != null) - return namedRange.Ranges.FirstOrDefault(); - else - { - IXLWorksheet ws; - var r = RangeFromFullAddress(range, out ws); - return r; - } - } - - public IXLRanges Ranges(String ranges) - { - var retVal = new XLRanges(); - var rangePairs = ranges.Split(','); - foreach (var range in rangePairs.Select(r => Range(r.Trim())).Where(range => range != null)) - { - retVal.Add(range); - } - return retVal; - } - - internal XLIdManager ShapeIdManager { get; private set; } - - - public void Dispose() - { - Worksheets.ForEach(w => w.Dispose()); - } - - public Boolean Use1904DateSystem { get; set; } - public XLWorkbook SetUse1904DateSystem() - { - return SetUse1904DateSystem(true); - } - - public XLWorkbook SetUse1904DateSystem(Boolean value) - { - Use1904DateSystem = value; - return this; - } - - public IXLWorksheet AddWorksheet(String sheetName) - { - return Worksheets.Add(sheetName); - } - - public IXLWorksheet AddWorksheet(String sheetName, Int32 position) - { - return Worksheets.Add(sheetName, position); - } - public IXLWorksheet AddWorksheet(DataTable dataTable) - { - return Worksheets.Add(dataTable); - } - public void AddWorksheet(DataSet dataSet) - { - Worksheets.Add(dataSet); - } - - public void AddWorksheet(IXLWorksheet worksheet) - { - worksheet.CopyTo(this, worksheet.Name); - } - - public IXLWorksheet AddWorksheet(DataTable dataTable, String sheetName) - { - return Worksheets.Add(dataTable, sheetName); - } - - private XLCalcEngine _calcEngine; - private XLCalcEngine CalcEngine - { - get { return _calcEngine ?? (_calcEngine = new XLCalcEngine(this)); } - } - public Object Evaluate(String expression) - { - return CalcEngine.Evaluate(expression); - } - - private static XLCalcEngine _calcEngineExpr; - private SpreadsheetDocumentType _spreadsheetDocumentType; - - private static XLCalcEngine CalcEngineExpr - { - get { return _calcEngineExpr ?? (_calcEngineExpr = new XLCalcEngine()); } - } - public static Object EvaluateExpr(String expression) - { - return CalcEngineExpr.Evaluate(expression); - } - - public String Author { get; set; } - - public Boolean LockStructure { get; set; } - public XLWorkbook SetLockStructure(Boolean value) { LockStructure = value; return this; } - public Boolean LockWindows { get; set; } - public XLWorkbook SetLockWindows(Boolean value) { LockWindows = value; return this; } - internal HexBinaryValue LockPassword { get; set; } - - public void Protect(Boolean lockStructure, Boolean lockWindows, String workbookPassword) - { - if (workbookPassword != null) - { - var hashPassword = GetPasswordHash(workbookPassword); - if (LockPassword != null) - { - if (LockPassword != hashPassword) - { - throw new ArgumentException("Invalid password"); - } - else - { - if (lockStructure || lockWindows) - { - throw new InvalidOperationException("The workbook is already protected"); - } - else - { - //Unprotect workbook using password. - LockPassword = null; - } - } - } - else - { - if (lockStructure || lockWindows) - { - //Protect workbook using password. - LockPassword = hashPassword; - } - } - } - else - { - if (LockPassword != null) - { - throw new InvalidOperationException("The workbook is password protected"); - } - } - LockStructure = lockStructure; - LockWindows = lockWindows; - } - - public void Protect() - { - Protect(true); - } - - public void Protect(string workbookPassword) - { - Protect(true, false, workbookPassword); - } - - public void Protect(Boolean lockStructure) - { - Protect(lockStructure, false); - } - - public void Protect(Boolean lockStructure, Boolean lockWindows) - { - Protect(lockStructure, lockWindows, null); - } - - public void Unprotect() - { - Protect(false, false); - } - - public void Unprotect(string workbookPassword) - { - Protect(false, false, workbookPassword); - } - - private String GetPasswordHash(String password) - { - Int32 pLength = password.Length; - Int32 hash = 0; - if (pLength == 0) return String.Empty; - - for (Int32 i = pLength - 1; i >= 0; i--) - { - hash ^= password[i]; - hash = hash >> 14 & 0x01 | hash << 1 & 0x7fff; - } - hash ^= 0x8000 | 'N' << 8 | 'K'; - hash ^= pLength; - return hash.ToString("X"); - } - } +using System; +using System.Collections.Generic; +using System.IO; +using System.Security.AccessControl; +using ClosedXML.Excel.CalcEngine; +using DocumentFormat.OpenXml; + +namespace ClosedXML.Excel +{ + using System.Linq; + using System.Data; + + public enum XLEventTracking { Enabled, Disabled } + public enum XLCalculateMode + { + Auto, + AutoNoTable, + Manual, + Default + }; + + public enum XLReferenceStyle + { + R1C1, + A1, + Default + }; + + public enum XLCellSetValueBehavior + { + /// + /// Analyze input string and convert value. For avoid analyzing use escape symbol ' + /// + Smart = 0, + + /// + /// Direct set value. If value has unsupported type - value will be stored as string returned by + /// + Simple = 1, + } + + public partial class XLWorkbook: IDisposable + { + #region Static + + private static IXLStyle _defaultStyle; + + public static IXLStyle DefaultStyle + { + get + { + return _defaultStyle ?? (_defaultStyle = new XLStyle(null) + { + Font = new XLFont(null, null) + { + Bold = false, + Italic = false, + Underline = XLFontUnderlineValues.None, + Strikethrough = false, + VerticalAlignment = + XLFontVerticalTextAlignmentValues. + Baseline, + FontSize = 11, + FontColor = XLColor.FromArgb(0, 0, 0), + FontName = "Calibri", + FontFamilyNumbering = + XLFontFamilyNumberingValues.Swiss + }, + Fill = new XLFill(null) + { + BackgroundColor = XLColor.FromIndex(64), + PatternType = XLFillPatternValues.None, + PatternColor = XLColor.FromIndex(64) + }, + Border = new XLBorder(null, null) + { + BottomBorder = + XLBorderStyleValues.None, + DiagonalBorder = + XLBorderStyleValues.None, + DiagonalDown = false, + DiagonalUp = false, + LeftBorder = XLBorderStyleValues.None, + RightBorder = XLBorderStyleValues.None, + TopBorder = XLBorderStyleValues.None, + BottomBorderColor = XLColor.Black, + DiagonalBorderColor = XLColor.Black, + LeftBorderColor = XLColor.Black, + RightBorderColor = XLColor.Black, + TopBorderColor = XLColor.Black + }, + NumberFormat = + new XLNumberFormat(null, null) {NumberFormatId = 0}, + Alignment = new XLAlignment(null) + { + Indent = 0, + Horizontal = + XLAlignmentHorizontalValues. + General, + JustifyLastLine = false, + ReadingOrder = + XLAlignmentReadingOrderValues. + ContextDependent, + RelativeIndent = 0, + ShrinkToFit = false, + TextRotation = 0, + Vertical = + XLAlignmentVerticalValues. + Bottom, + WrapText = false + }, + Protection = new XLProtection(null) + { + Locked = true, + Hidden = false + } + }); + } + } + + public static Double DefaultRowHeight { get; private set; } + public static Double DefaultColumnWidth { get; private set; } + + public static IXLPageSetup DefaultPageOptions + { + get + { + var defaultPageOptions = new XLPageSetup(null, null) + { + PageOrientation = XLPageOrientation.Default, + Scale = 100, + PaperSize = XLPaperSize.LetterPaper, + Margins = new XLMargins + { + Top = 0.75, + Bottom = 0.5, + Left = 0.75, + Right = 0.75, + Header = 0.5, + Footer = 0.75 + }, + ScaleHFWithDocument = true, + AlignHFWithMargins = true, + PrintErrorValue = XLPrintErrorValues.Displayed, + ShowComments = XLShowCommentsValues.None + }; + return defaultPageOptions; + } + } + + public static IXLOutline DefaultOutline + { + get + { + return new XLOutline(null) + { + SummaryHLocation = XLOutlineSummaryHLocation.Right, + SummaryVLocation = XLOutlineSummaryVLocation.Bottom + }; + } + } + + /// + /// Behavior for + /// + public static XLCellSetValueBehavior CellSetValueBehavior { get; set; } + + #endregion + + internal readonly List UnsupportedSheets = + new List(); + + private readonly Dictionary _stylesById = new Dictionary(); + private readonly Dictionary _stylesByStyle = new Dictionary(); + + public XLEventTracking EventTracking { get; set; } + + internal Int32 GetStyleId(IXLStyle style) + { + Int32 cached; + if (_stylesByStyle.TryGetValue(style, out cached)) + return cached; + + var count = _stylesByStyle.Count; + var styleToUse = new XLStyle(null, style); + _stylesByStyle.Add(styleToUse, count); + _stylesById.Add(count, styleToUse); + return count; + } + + internal IXLStyle GetStyleById(Int32 id) + { + return _stylesById[id]; + } + + #region Nested Type: XLLoadSource + + private enum XLLoadSource + { + New, + File, + Stream + }; + + #endregion + + internal XLWorksheets WorksheetsInternal { get; private set; } + + /// + /// Gets an object to manipulate the worksheets. + /// + public IXLWorksheets Worksheets + { + get { return WorksheetsInternal; } + } + + /// + /// Gets an object to manipulate this workbook's named ranges. + /// + public IXLNamedRanges NamedRanges { get; private set; } + + /// + /// Gets an object to manipulate this workbook's theme. + /// + public IXLTheme Theme { get; private set; } + + /// + /// Gets or sets the default style for the workbook. + /// All new worksheets will use this style. + /// + public IXLStyle Style { get; set; } + + /// + /// Gets or sets the default row height for the workbook. + /// All new worksheets will use this row height. + /// + public Double RowHeight { get; set; } + + /// + /// Gets or sets the default column width for the workbook. + /// All new worksheets will use this column width. + /// + public Double ColumnWidth { get; set; } + + /// + /// Gets or sets the default page options for the workbook. + /// All new worksheets will use these page options. + /// + public IXLPageSetup PageOptions { get; set; } + + /// + /// Gets or sets the default outline options for the workbook. + /// All new worksheets will use these outline options. + /// + public IXLOutline Outline { get; set; } + + /// + /// Gets or sets the workbook's properties. + /// + public XLWorkbookProperties Properties { get; set; } + + /// + /// Gets or sets the workbook's calculation mode. + /// + public XLCalculateMode CalculateMode { get; set; } + + + public Boolean CalculationOnSave { get; set; } + public Boolean ForceFullCalculation { get; set; } + public Boolean FullCalculationOnLoad { get; set; } + public Boolean FullPrecision { get; set; } + + /// + /// Gets or sets the workbook's reference style. + /// + public XLReferenceStyle ReferenceStyle { get; set; } + + public IXLCustomProperties CustomProperties { get; private set; } + + public Boolean ShowFormulas { get; set; } + public Boolean ShowGridLines { get; set; } + public Boolean ShowOutlineSymbols { get; set; } + public Boolean ShowRowColHeaders { get; set; } + public Boolean ShowRuler { get; set; } + public Boolean ShowWhiteSpace { get; set; } + public Boolean ShowZeros { get; set; } + public Boolean RightToLeft { get; set; } + + public Boolean DefaultShowFormulas + { + get { return false; } + } + + public Boolean DefaultShowGridLines + { + get { return true; } + } + + public Boolean DefaultShowOutlineSymbols + { + get { return true; } + } + + public Boolean DefaultShowRowColHeaders + { + get { return true; } + } + + public Boolean DefaultShowRuler + { + get { return true; } + } + + public Boolean DefaultShowWhiteSpace + { + get { return true; } + } + + public Boolean DefaultShowZeros + { + get { return true; } + } + + public Boolean DefaultRightToLeft + { + get { return false; } + } + + private void InitializeTheme() + { + Theme = new XLTheme + { + Text1 = XLColor.FromHtml("#FF000000"), + Background1 = XLColor.FromHtml("#FFFFFFFF"), + Text2 = XLColor.FromHtml("#FF1F497D"), + Background2 = XLColor.FromHtml("#FFEEECE1"), + Accent1 = XLColor.FromHtml("#FF4F81BD"), + Accent2 = XLColor.FromHtml("#FFC0504D"), + Accent3 = XLColor.FromHtml("#FF9BBB59"), + Accent4 = XLColor.FromHtml("#FF8064A2"), + Accent5 = XLColor.FromHtml("#FF4BACC6"), + Accent6 = XLColor.FromHtml("#FFF79646"), + Hyperlink = XLColor.FromHtml("#FF0000FF"), + FollowedHyperlink = XLColor.FromHtml("#FF800080") + }; + } + + internal XLColor GetXLColor(XLThemeColor themeColor) + { + switch (themeColor) + { + case XLThemeColor.Text1: + return Theme.Text1; + case XLThemeColor.Background1: + return Theme.Background1; + case XLThemeColor.Text2: + return Theme.Text2; + case XLThemeColor.Background2: + return Theme.Background2; + case XLThemeColor.Accent1: + return Theme.Accent1; + case XLThemeColor.Accent2: + return Theme.Accent2; + case XLThemeColor.Accent3: + return Theme.Accent3; + case XLThemeColor.Accent4: + return Theme.Accent4; + case XLThemeColor.Accent5: + return Theme.Accent5; + case XLThemeColor.Accent6: + return Theme.Accent6; + default: + throw new ArgumentException("Invalid theme color"); + } + } + + public IXLNamedRange NamedRange(String rangeName) + { + if (rangeName.Contains("!")) + { + var split = rangeName.Split('!'); + var first = split[0]; + var wsName = first.StartsWith("'") ? first.Substring(1, first.Length - 2) : first; + var name = split[1]; + IXLWorksheet ws; + if (TryGetWorksheet(wsName, out ws)) + { + var range = ws.NamedRange(name); + return range ?? NamedRange(name); + } + return null; + } + return NamedRanges.NamedRange(rangeName); + } + + public Boolean TryGetWorksheet(String name, out IXLWorksheet worksheet) + { + if (Worksheets.Any(w => string.Equals(w.Name, XLWorksheets.TrimSheetName(name), StringComparison.OrdinalIgnoreCase))) + { + worksheet = Worksheet(name); + return true; + } + + worksheet = null; + return false; + } + + public IXLRange RangeFromFullAddress(String rangeAddress, out IXLWorksheet ws) + { + ws = null; + if (!rangeAddress.Contains('!')) return null; + + var split = rangeAddress.Split('!'); + var first = split[0]; + var wsName = first.StartsWith("'") ? first.Substring(1, first.Length - 2) : first; + var localRange = split[1]; + if (TryGetWorksheet(wsName, out ws)) + { + return ws.Range(localRange); + } + return null; + } + + + /// + /// Saves the current workbook. + /// + public void Save() + { +#if DEBUG + Save(true, false); +#else + Save(false, false); +#endif + } + + /// + /// Saves the current workbook and optionally performs validation + /// + public void Save(Boolean validate, Boolean evaluateFormulae = false) + { + checkForWorksheetsPresent(); + if (_loadSource == XLLoadSource.New) + throw new Exception("This is a new file, please use one of the SaveAs methods."); + + if (_loadSource == XLLoadSource.Stream) + { + CreatePackage(_originalStream, false, _spreadsheetDocumentType, validate, evaluateFormulae); + } + else + CreatePackage(_originalFile, _spreadsheetDocumentType, validate, evaluateFormulae); + } + + /// + /// Saves the current workbook to a file. + /// + public void SaveAs(String file) + { +#if DEBUG + SaveAs(file, true, false); +#else + SaveAs(file, false, false); +#endif + } + + /// + /// Saves the current workbook to a file and optionally validates it. + /// + public void SaveAs(String file, Boolean validate, Boolean evaluateFormulae = false) + { + checkForWorksheetsPresent(); + PathHelper.CreateDirectory(Path.GetDirectoryName(file)); + if (_loadSource == XLLoadSource.New) + { + if (File.Exists(file)) + File.Delete(file); + + CreatePackage(file, GetSpreadsheetDocumentType(file), validate, evaluateFormulae); + } + else if (_loadSource == XLLoadSource.File) + { + if (String.Compare(_originalFile.Trim(), file.Trim(), true) != 0) + File.Copy(_originalFile, file, true); + + CreatePackage(file, GetSpreadsheetDocumentType(file), validate, evaluateFormulae); + } + else if (_loadSource == XLLoadSource.Stream) + { + _originalStream.Position = 0; + + using (var fileStream = File.Create(file)) + { + CopyStream(_originalStream, fileStream); + //fileStream.Position = 0; + CreatePackage(fileStream, false, _spreadsheetDocumentType, validate, evaluateFormulae); + fileStream.Close(); + } + } + } + + private static SpreadsheetDocumentType GetSpreadsheetDocumentType(string filePath) + { + var extension = Path.GetExtension(filePath); + if (extension == null) throw new Exception("Empty extension is not supported."); + extension = extension.Substring(1).ToLowerInvariant(); + + switch (extension) + { + case "xlsm": + case "xltm": + return SpreadsheetDocumentType.MacroEnabledWorkbook; + case "xlsx": + case "xltx": + return SpreadsheetDocumentType.Workbook; + default: + throw new ArgumentException(String.Format("Extension '{0}' is not supported. Supported extensions are '.xlsx', '.xslm', '.xltx' and '.xltm'.", extension)); + + } + } + + private void checkForWorksheetsPresent() + { + if (Worksheets.Count() == 0) + throw new Exception("Workbooks need at least one worksheet."); + } + + /// + /// Saves the current workbook to a stream. + /// + public void SaveAs(Stream stream) + { +#if DEBUG + SaveAs(stream, true, false); +#else + SaveAs(stream, false, false); +#endif + } + + /// + /// Saves the current workbook to a stream and optionally validates it. + /// + public void SaveAs(Stream stream, Boolean validate, Boolean evaluateFormulae = false) + { + checkForWorksheetsPresent(); + if (_loadSource == XLLoadSource.New) + { + // dm 20130422, this method or better the method SpreadsheetDocument.Create which is called + // inside of 'CreatePackage' need a stream which CanSeek & CanRead + // and an ordinary Response stream of a webserver can't do this + // so we have to ask and provide a way around this + if (stream.CanRead && stream.CanSeek && stream.CanWrite) + { + // all is fine the package can be created in a direct way + CreatePackage(stream, true, _spreadsheetDocumentType, validate, evaluateFormulae); + } + else + { + // the harder way + MemoryStream ms = new MemoryStream(); + CreatePackage(ms, true, _spreadsheetDocumentType, validate, evaluateFormulae); + // not really nessesary, because I changed CopyStream too. + // but for better understanding and if somebody in the future + // provide an changed version of CopyStream + ms.Position = 0; + CopyStream(ms, stream); + } + } + else if (_loadSource == XLLoadSource.File) + { + using (var fileStream = new FileStream(_originalFile, FileMode.Open, FileAccess.Read)) + { + CopyStream(fileStream, stream); + fileStream.Close(); + } + CreatePackage(stream, false, _spreadsheetDocumentType, validate, evaluateFormulae); + } + else if (_loadSource == XLLoadSource.Stream) + { + _originalStream.Position = 0; + if (_originalStream != stream) + CopyStream(_originalStream, stream); + + CreatePackage(stream, false, _spreadsheetDocumentType, validate, evaluateFormulae); + } + } + + internal static void CopyStream(Stream input, Stream output) + { + var buffer = new byte[8 * 1024]; + int len; + // dm 20130422, it is always a good idea to rewind the input stream, or not? + if (input.CanSeek) + input.Seek(0, SeekOrigin.Begin); + while ((len = input.Read(buffer, 0, buffer.Length)) > 0) + output.Write(buffer, 0, len); + // dm 20130422, and flushing the output after write + output.Flush(); + + } + + public IXLWorksheet Worksheet(String name) + { + return WorksheetsInternal.Worksheet(name); + } + + public IXLWorksheet Worksheet(Int32 position) + { + return WorksheetsInternal.Worksheet(position); + } + + public IXLCustomProperty CustomProperty(String name) + { + return CustomProperties.CustomProperty(name); + } + + public IXLCells FindCells(Func predicate) + { + var cells = new XLCells(false, false); + foreach (XLWorksheet ws in WorksheetsInternal) + { + foreach (XLCell cell in ws.CellsUsed(true)) + { + if (predicate(cell)) + cells.Add(cell); + } + } + return cells; + } + + public IXLRows FindRows(Func predicate) + { + var rows = new XLRows(null); + foreach (XLWorksheet ws in WorksheetsInternal) + { + foreach (IXLRow row in ws.Rows().Where(predicate)) + rows.Add(row as XLRow); + } + return rows; + } + + public IXLColumns FindColumns(Func predicate) + { + var columns = new XLColumns(null); + foreach (XLWorksheet ws in WorksheetsInternal) + { + foreach (IXLColumn column in ws.Columns().Where(predicate)) + columns.Add(column as XLColumn); + } + return columns; + } + +#region Fields + + private readonly XLLoadSource _loadSource = XLLoadSource.New; + private readonly String _originalFile; + private readonly Stream _originalStream; + +#endregion + +#region Constructor + + + /// + /// Creates a new Excel workbook. + /// + public XLWorkbook() + :this(XLEventTracking.Enabled) + { + + } + + public XLWorkbook(XLEventTracking eventTracking) + { + EventTracking = eventTracking; + DefaultRowHeight = 15; + DefaultColumnWidth = 8.43; + Style = new XLStyle(null, DefaultStyle); + RowHeight = DefaultRowHeight; + ColumnWidth = DefaultColumnWidth; + PageOptions = DefaultPageOptions; + Outline = DefaultOutline; + Properties = new XLWorkbookProperties(); + CalculateMode = XLCalculateMode.Default; + ReferenceStyle = XLReferenceStyle.Default; + InitializeTheme(); + ShowFormulas = DefaultShowFormulas; + ShowGridLines = DefaultShowGridLines; + ShowOutlineSymbols = DefaultShowOutlineSymbols; + ShowRowColHeaders = DefaultShowRowColHeaders; + ShowRuler = DefaultShowRuler; + ShowWhiteSpace = DefaultShowWhiteSpace; + ShowZeros = DefaultShowZeros; + RightToLeft = DefaultRightToLeft; + WorksheetsInternal = new XLWorksheets(this); + NamedRanges = new XLNamedRanges(this); + CustomProperties = new XLCustomProperties(this); + ShapeIdManager = new XLIdManager(); + Author = Environment.UserName; + } + + /// + /// Opens an existing workbook from a file. + /// + /// The file to open. + public XLWorkbook(String file) + : this(file, XLEventTracking.Enabled) + { + + } + + public XLWorkbook(String file, XLEventTracking eventTracking) + : this(eventTracking) + { + _loadSource = XLLoadSource.File; + _originalFile = file; + _spreadsheetDocumentType = GetSpreadsheetDocumentType(_originalFile); + Load(file); + } + + + + /// + /// Opens an existing workbook from a stream. + /// + /// The stream to open. + public XLWorkbook(Stream stream):this(stream, XLEventTracking.Enabled) + { + + } + + public XLWorkbook(Stream stream, XLEventTracking eventTracking) + : this(eventTracking) + { + _loadSource = XLLoadSource.Stream; + _originalStream = stream; + Load(stream); + } + +#endregion + +#region Nested type: UnsupportedSheet + + internal sealed class UnsupportedSheet + { + public Boolean IsActive; + public UInt32 SheetId; + public Int32 Position; + } + +#endregion + + public IXLCell Cell(String namedCell) + { + var namedRange = NamedRange(namedCell); + if (namedRange == null) return null; + var range = namedRange.Ranges.FirstOrDefault(); + if (range == null) return null; + return range.FirstCell(); + } + + public IXLCells Cells(String namedCells) + { + return Ranges(namedCells).Cells(); + } + + public IXLRange Range(String range) + { + var namedRange = NamedRange(range); + if (namedRange != null) + return namedRange.Ranges.FirstOrDefault(); + else + { + IXLWorksheet ws; + var r = RangeFromFullAddress(range, out ws); + return r; + } + } + + public IXLRanges Ranges(String ranges) + { + var retVal = new XLRanges(); + var rangePairs = ranges.Split(','); + foreach (var range in rangePairs.Select(r => Range(r.Trim())).Where(range => range != null)) + { + retVal.Add(range); + } + return retVal; + } + + internal XLIdManager ShapeIdManager { get; private set; } + + + public void Dispose() + { + Worksheets.ForEach(w => w.Dispose()); + } + + public Boolean Use1904DateSystem { get; set; } + public XLWorkbook SetUse1904DateSystem() + { + return SetUse1904DateSystem(true); + } + + public XLWorkbook SetUse1904DateSystem(Boolean value) + { + Use1904DateSystem = value; + return this; + } + + public IXLWorksheet AddWorksheet(String sheetName) + { + return Worksheets.Add(sheetName); + } + + public IXLWorksheet AddWorksheet(String sheetName, Int32 position) + { + return Worksheets.Add(sheetName, position); + } + public IXLWorksheet AddWorksheet(DataTable dataTable) + { + return Worksheets.Add(dataTable); + } + public void AddWorksheet(DataSet dataSet) + { + Worksheets.Add(dataSet); + } + + public void AddWorksheet(IXLWorksheet worksheet) + { + worksheet.CopyTo(this, worksheet.Name); + } + + public IXLWorksheet AddWorksheet(DataTable dataTable, String sheetName) + { + return Worksheets.Add(dataTable, sheetName); + } + + private XLCalcEngine _calcEngine; + private XLCalcEngine CalcEngine + { + get { return _calcEngine ?? (_calcEngine = new XLCalcEngine(this)); } + } + public Object Evaluate(String expression) + { + return CalcEngine.Evaluate(expression); + } + + private static XLCalcEngine _calcEngineExpr; + private SpreadsheetDocumentType _spreadsheetDocumentType; + + private static XLCalcEngine CalcEngineExpr + { + get { return _calcEngineExpr ?? (_calcEngineExpr = new XLCalcEngine()); } + } + public static Object EvaluateExpr(String expression) + { + return CalcEngineExpr.Evaluate(expression); + } + + public String Author { get; set; } + + public Boolean LockStructure { get; set; } + public XLWorkbook SetLockStructure(Boolean value) { LockStructure = value; return this; } + public Boolean LockWindows { get; set; } + public XLWorkbook SetLockWindows(Boolean value) { LockWindows = value; return this; } + internal HexBinaryValue LockPassword { get; set; } + + public void Protect(Boolean lockStructure, Boolean lockWindows, String workbookPassword) + { + if (workbookPassword != null) + { + var hashPassword = GetPasswordHash(workbookPassword); + if (LockPassword != null) + { + if (LockPassword != hashPassword) + { + throw new ArgumentException("Invalid password"); + } + else + { + if (lockStructure || lockWindows) + { + throw new InvalidOperationException("The workbook is already protected"); + } + else + { + //Unprotect workbook using password. + LockPassword = null; + } + } + } + else + { + if (lockStructure || lockWindows) + { + //Protect workbook using password. + LockPassword = hashPassword; + } + } + } + else + { + if (LockPassword != null) + { + throw new InvalidOperationException("The workbook is password protected"); + } + } + LockStructure = lockStructure; + LockWindows = lockWindows; + } + + public void Protect() + { + Protect(true); + } + + public void Protect(string workbookPassword) + { + Protect(true, false, workbookPassword); + } + + public void Protect(Boolean lockStructure) + { + Protect(lockStructure, false); + } + + public void Protect(Boolean lockStructure, Boolean lockWindows) + { + Protect(lockStructure, lockWindows, null); + } + + public void Unprotect() + { + Protect(false, false); + } + + public void Unprotect(string workbookPassword) + { + Protect(false, false, workbookPassword); + } + + private String GetPasswordHash(String password) + { + Int32 pLength = password.Length; + Int32 hash = 0; + if (pLength == 0) return String.Empty; + + for (Int32 i = pLength - 1; i >= 0; i--) + { + hash ^= password[i]; + hash = hash >> 14 & 0x01 | hash << 1 & 0x7fff; + } + hash ^= 0x8000 | 'N' << 8 | 'K'; + hash ^= pLength; + return hash.ToString("X"); + } + } } \ No newline at end of file diff --git a/ClosedXML/Excel/XLWorkbook_Load.cs b/ClosedXML/Excel/XLWorkbook_Load.cs index 8e34514..a23ab4e 100644 --- a/ClosedXML/Excel/XLWorkbook_Load.cs +++ b/ClosedXML/Excel/XLWorkbook_Load.cs @@ -1,2402 +1,2402 @@ -#region - -using ClosedXML.Utils; -using DocumentFormat.OpenXml; -using DocumentFormat.OpenXml.Packaging; -using DocumentFormat.OpenXml.Spreadsheet; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Xml.Linq; -using Ap = DocumentFormat.OpenXml.ExtendedProperties; -using Op = DocumentFormat.OpenXml.CustomProperties; -using Xdr = DocumentFormat.OpenXml.Drawing.Spreadsheet; - -#endregion - -namespace ClosedXML.Excel -{ - #region - - using Ap; - using Drawings; - using Op; - using System.Drawing; - - #endregion - - public partial class XLWorkbook - { - private readonly Dictionary _colorList = new Dictionary(); - - private void Load(String file) - { - LoadSheets(file); - } - - private void Load(Stream stream) - { - LoadSheets(stream); - } - - private void LoadSheets(String fileName) - { - using (var dSpreadsheet = SpreadsheetDocument.Open(fileName, false)) - LoadSpreadsheetDocument(dSpreadsheet); - } - - private void LoadSheets(Stream stream) - { - using (var dSpreadsheet = SpreadsheetDocument.Open(stream, false)) - LoadSpreadsheetDocument(dSpreadsheet); - } - - private void LoadSpreadsheetDocument(SpreadsheetDocument dSpreadsheet) - { - ShapeIdManager = new XLIdManager(); - SetProperties(dSpreadsheet); - //var sharedStrings = dSpreadsheet.WorkbookPart.SharedStringTablePart.SharedStringTable.Elements(); - SharedStringItem[] sharedStrings = null; - if (dSpreadsheet.WorkbookPart.GetPartsOfType().Count() > 0) - { - var shareStringPart = dSpreadsheet.WorkbookPart.GetPartsOfType().First(); - sharedStrings = shareStringPart.SharedStringTable.Elements().ToArray(); - } - - if (dSpreadsheet.CustomFilePropertiesPart != null) - { - foreach (var m in dSpreadsheet.CustomFilePropertiesPart.Properties.Elements()) - { - String name = m.Name.Value; - if (m.VTLPWSTR != null) - CustomProperties.Add(name, m.VTLPWSTR.Text); - else if (m.VTFileTime != null) - { - CustomProperties.Add(name, - DateTime.ParseExact(m.VTFileTime.Text, "yyyy'-'MM'-'dd'T'HH':'mm':'ssK", - CultureInfo.InvariantCulture)); - } - else if (m.VTDouble != null) - CustomProperties.Add(name, Double.Parse(m.VTDouble.Text, CultureInfo.InvariantCulture)); - else if (m.VTBool != null) - CustomProperties.Add(name, m.VTBool.Text == "true"); - } - } - - var wbProps = dSpreadsheet.WorkbookPart.Workbook.WorkbookProperties; - Use1904DateSystem = wbProps != null && wbProps.Date1904 != null && wbProps.Date1904.Value; - - var wbProtection = dSpreadsheet.WorkbookPart.Workbook.WorkbookProtection; - if (wbProtection != null) - { - if (wbProtection.LockStructure != null) - LockStructure = wbProtection.LockStructure.Value; - if (wbProtection.LockWindows != null) - LockWindows = wbProtection.LockWindows.Value; - if (wbProtection.WorkbookPassword != null) - LockPassword = wbProtection.WorkbookPassword.Value; - } - - var calculationProperties = dSpreadsheet.WorkbookPart.Workbook.CalculationProperties; - if (calculationProperties != null) - { - var calculateMode = calculationProperties.CalculationMode; - if (calculateMode != null) - CalculateMode = calculateMode.Value.ToClosedXml(); - - var calculationOnSave = calculationProperties.CalculationOnSave; - if (calculationOnSave != null) - CalculationOnSave = calculationOnSave.Value; - - var forceFullCalculation = calculationProperties.ForceFullCalculation; - if (forceFullCalculation != null) - ForceFullCalculation = forceFullCalculation.Value; - - var fullCalculationOnLoad = calculationProperties.FullCalculationOnLoad; - if (fullCalculationOnLoad != null) - FullCalculationOnLoad = fullCalculationOnLoad.Value; - - var fullPrecision = calculationProperties.FullPrecision; - if (fullPrecision != null) - FullPrecision = fullPrecision.Value; - - var referenceMode = calculationProperties.ReferenceMode; - if (referenceMode != null) - ReferenceStyle = referenceMode.Value.ToClosedXml(); - } - - var efp = dSpreadsheet.ExtendedFilePropertiesPart; - if (efp != null && efp.Properties != null) - { - if (efp.Properties.Elements().Any()) - Properties.Company = efp.Properties.GetFirstChild().Text; - - if (efp.Properties.Elements().Any()) - Properties.Manager = efp.Properties.GetFirstChild().Text; - } - - Stylesheet s = null; - if (dSpreadsheet.WorkbookPart.WorkbookStylesPart != null && - dSpreadsheet.WorkbookPart.WorkbookStylesPart.Stylesheet != null) - { - s = dSpreadsheet.WorkbookPart.WorkbookStylesPart.Stylesheet; - } - - NumberingFormats numberingFormats = s == null ? null : s.NumberingFormats; - Fills fills = s == null ? null : s.Fills; - Borders borders = s == null ? null : s.Borders; - Fonts fonts = s == null ? null : s.Fonts; - Int32 dfCount = 0; - Dictionary differentialFormats; - if (s != null && s.DifferentialFormats != null) - differentialFormats = s.DifferentialFormats.Elements().ToDictionary(k => dfCount++); - else - differentialFormats = new Dictionary(); - - var sheets = dSpreadsheet.WorkbookPart.Workbook.Sheets; - Int32 position = 0; - foreach (Sheet dSheet in sheets.OfType()) - { - position++; - var sharedFormulasR1C1 = new Dictionary(); - - var wsPart = dSpreadsheet.WorkbookPart.GetPartById(dSheet.Id) as WorksheetPart; - - if (wsPart == null) - { - UnsupportedSheets.Add(new UnsupportedSheet { SheetId = dSheet.SheetId.Value, Position = position }); - continue; - } - - var sheetName = dSheet.Name; - - var ws = (XLWorksheet)WorksheetsInternal.Add(sheetName, position); - ws.RelId = dSheet.Id; - ws.SheetId = (Int32)dSheet.SheetId.Value; - - if (dSheet.State != null) - ws.Visibility = dSheet.State.Value.ToClosedXml(); - - var styleList = new Dictionary();// {{0, ws.Style}}; - PageSetupProperties pageSetupProperties = null; - - using (var reader = OpenXmlReader.Create(wsPart)) - { - Type[] ignoredElements = new Type[] - { - typeof(CustomSheetViews) // Custom sheet views contain its own auto filter data, and more, which should be ignored for now - }; - - while (reader.Read()) - { - while (ignoredElements.Contains(reader.ElementType)) - reader.ReadNextSibling(); - - if (reader.ElementType == typeof(SheetFormatProperties)) - { - var sheetFormatProperties = (SheetFormatProperties)reader.LoadCurrentElement(); - if (sheetFormatProperties != null) - { - if (sheetFormatProperties.DefaultRowHeight != null) - ws.RowHeight = sheetFormatProperties.DefaultRowHeight; - - ws.RowHeightChanged = (sheetFormatProperties.CustomHeight != null && - sheetFormatProperties.CustomHeight.Value); - - if (sheetFormatProperties.DefaultColumnWidth != null) - { - ws.ColumnWidth = sheetFormatProperties.DefaultColumnWidth; - } - } - } - else if (reader.ElementType == typeof(SheetViews)) - LoadSheetViews((SheetViews)reader.LoadCurrentElement(), ws); - else if (reader.ElementType == typeof(MergeCells)) - { - var mergedCells = (MergeCells)reader.LoadCurrentElement(); - if (mergedCells != null) - { - foreach (MergeCell mergeCell in mergedCells.Elements()) - ws.Range(mergeCell.Reference).Merge(false); - } - } - else if (reader.ElementType == typeof(Columns)) - LoadColumns(s, numberingFormats, fills, borders, fonts, ws, - (Columns)reader.LoadCurrentElement()); - else if (reader.ElementType == typeof(Row)) - { - lastRow = 0; - LoadRows(s, numberingFormats, fills, borders, fonts, ws, sharedStrings, sharedFormulasR1C1, - styleList, (Row)reader.LoadCurrentElement()); - } - else if (reader.ElementType == typeof(AutoFilter)) - LoadAutoFilter((AutoFilter)reader.LoadCurrentElement(), ws); - else if (reader.ElementType == typeof(SheetProtection)) - LoadSheetProtection((SheetProtection)reader.LoadCurrentElement(), ws); - else if (reader.ElementType == typeof(DataValidations)) - LoadDataValidations((DataValidations)reader.LoadCurrentElement(), ws); - else if (reader.ElementType == typeof(ConditionalFormatting)) - LoadConditionalFormatting((ConditionalFormatting)reader.LoadCurrentElement(), ws, differentialFormats); - else if (reader.ElementType == typeof(Hyperlinks)) - LoadHyperlinks((Hyperlinks)reader.LoadCurrentElement(), wsPart, ws); - else if (reader.ElementType == typeof(PrintOptions)) - LoadPrintOptions((PrintOptions)reader.LoadCurrentElement(), ws); - else if (reader.ElementType == typeof(PageMargins)) - LoadPageMargins((PageMargins)reader.LoadCurrentElement(), ws); - else if (reader.ElementType == typeof(PageSetup)) - LoadPageSetup((PageSetup)reader.LoadCurrentElement(), ws, pageSetupProperties); - else if (reader.ElementType == typeof(HeaderFooter)) - LoadHeaderFooter((HeaderFooter)reader.LoadCurrentElement(), ws); - else if (reader.ElementType == typeof(SheetProperties)) - LoadSheetProperties((SheetProperties)reader.LoadCurrentElement(), ws, out pageSetupProperties); - else if (reader.ElementType == typeof(RowBreaks)) - LoadRowBreaks((RowBreaks)reader.LoadCurrentElement(), ws); - else if (reader.ElementType == typeof(ColumnBreaks)) - LoadColumnBreaks((ColumnBreaks)reader.LoadCurrentElement(), ws); - else if (reader.ElementType == typeof(LegacyDrawing)) - ws.LegacyDrawingId = (reader.LoadCurrentElement() as LegacyDrawing).Id.Value; - } - reader.Close(); - } - - #region LoadTables - - foreach (TableDefinitionPart tablePart in wsPart.TableDefinitionParts) - { - var dTable = tablePart.Table; - string reference = dTable.Reference.Value; - XLTable xlTable = ws.Range(reference).CreateTable(dTable.Name, false) as XLTable; - if (dTable.HeaderRowCount != null && dTable.HeaderRowCount == 0) - { - xlTable._showHeaderRow = false; - //foreach (var tableColumn in dTable.TableColumns.Cast()) - xlTable.AddFields(dTable.TableColumns.Cast().Select(t => GetTableColumnName(t.Name.Value))); - } - else - { - xlTable.InitializeAutoFilter(); - } - - if (dTable.TotalsRowCount != null && dTable.TotalsRowCount.Value > 0) - ((XLTable)xlTable)._showTotalsRow = true; - - if (dTable.TableStyleInfo != null) - { - if (dTable.TableStyleInfo.ShowFirstColumn != null) - xlTable.EmphasizeFirstColumn = dTable.TableStyleInfo.ShowFirstColumn.Value; - if (dTable.TableStyleInfo.ShowLastColumn != null) - xlTable.EmphasizeLastColumn = dTable.TableStyleInfo.ShowLastColumn.Value; - if (dTable.TableStyleInfo.ShowRowStripes != null) - xlTable.ShowRowStripes = dTable.TableStyleInfo.ShowRowStripes.Value; - if (dTable.TableStyleInfo.ShowColumnStripes != null) - xlTable.ShowColumnStripes = dTable.TableStyleInfo.ShowColumnStripes.Value; - if (dTable.TableStyleInfo.Name != null) - { - var theme = XLTableTheme.FromName(dTable.TableStyleInfo.Name.Value); - if (theme != null) - xlTable.Theme = theme; - else - xlTable.Theme = new XLTableTheme(dTable.TableStyleInfo.Name.Value); - } - else - xlTable.Theme = XLTableTheme.None; - } - - if (dTable.AutoFilter != null) - { - xlTable.ShowAutoFilter = true; - LoadAutoFilterColumns(dTable.AutoFilter, (xlTable as XLTable).AutoFilter); - } - else - xlTable.ShowAutoFilter = false; - - if (xlTable.ShowTotalsRow) - { - foreach (var tableColumn in dTable.TableColumns.Cast()) - { - var tableColumnName = GetTableColumnName(tableColumn.Name.Value); - if (tableColumn.TotalsRowFunction != null) - xlTable.Field(tableColumnName).TotalsRowFunction = - tableColumn.TotalsRowFunction.Value.ToClosedXml(); - - if (tableColumn.TotalsRowFormula != null) - xlTable.Field(tableColumnName).TotalsRowFormulaA1 = - tableColumn.TotalsRowFormula.Text; - - if (tableColumn.TotalsRowLabel != null) - xlTable.Field(tableColumnName).TotalsRowLabel = tableColumn.TotalsRowLabel.Value; - } - if (xlTable.AutoFilter != null) - xlTable.AutoFilter.Range = xlTable.Worksheet.Range( - xlTable.RangeAddress.FirstAddress.RowNumber, xlTable.RangeAddress.FirstAddress.ColumnNumber, - xlTable.RangeAddress.LastAddress.RowNumber - 1, xlTable.RangeAddress.LastAddress.ColumnNumber); - } - else if (xlTable.AutoFilter != null) - xlTable.AutoFilter.Range = xlTable.Worksheet.Range(xlTable.RangeAddress); - } - - #endregion - - LoadDrawings(wsPart, ws); - - #region LoadComments - - if (wsPart.WorksheetCommentsPart != null) - { - var root = wsPart.WorksheetCommentsPart.Comments; - var authors = root.GetFirstChild().ChildElements; - var comments = root.GetFirstChild().ChildElements; - - // **** MAYBE FUTURE SHAPE SIZE SUPPORT - XDocument xdoc = GetCommentVmlFile(wsPart); - - foreach (Comment c in comments) - { - // find cell by reference - var cell = ws.Cell(c.Reference); - - XLComment xlComment = cell.Comment as XLComment; - xlComment.Author = authors[(int)c.AuthorId.Value].InnerText; - //xlComment.ShapeId = (Int32)c.ShapeId.Value; - //ShapeIdManager.Add(xlComment.ShapeId); - - var runs = c.GetFirstChild().Elements(); - foreach (Run run in runs) - { - var runProperties = run.RunProperties; - String text = run.Text.InnerText.FixNewLines(); - var rt = cell.Comment.AddText(text); - LoadFont(runProperties, rt); - } - - XElement shape = GetCommentShape(xdoc); - - LoadShapeProperties(xlComment, shape); - - var clientData = shape.Elements().First(e => e.Name.LocalName == "ClientData"); - LoadClientData(xlComment, clientData); - - var textBox = shape.Elements().First(e => e.Name.LocalName == "textbox"); - LoadTextBox(xlComment, textBox); - - var alt = shape.Attribute("alt"); - if (alt != null) xlComment.Style.Web.SetAlternateText(alt.Value); - - LoadColorsAndLines(xlComment, shape); - - //var insetmode = (string)shape.Attributes().First(a=> a.Name.LocalName == "insetmode"); - //xlComment.Style.Margins.Automatic = insetmode != null && insetmode.Equals("auto"); - - shape.Remove(); - } - } - - #endregion - } - - var workbook = dSpreadsheet.WorkbookPart.Workbook; - - var bookViews = workbook.BookViews; - if (bookViews != null && bookViews.Any()) - { - var workbookView = bookViews.First() as WorkbookView; - if (workbookView != null && workbookView.ActiveTab != null) - { - UnsupportedSheet unsupportedSheet = - UnsupportedSheets.FirstOrDefault(us => us.Position == (Int32)(workbookView.ActiveTab.Value + 1)); - if (unsupportedSheet != null) - unsupportedSheet.IsActive = true; - else - { - Worksheet((Int32)(workbookView.ActiveTab.Value + 1)).SetTabActive(); - } - } - } - LoadDefinedNames(workbook); - - #region Pivot tables - - // Delay loading of pivot tables until all sheets have been loaded - foreach (Sheet dSheet in sheets.OfType()) - { - var wsPart = dSpreadsheet.WorkbookPart.GetPartById(dSheet.Id) as WorksheetPart; - - if (wsPart != null) - { - var ws = (XLWorksheet)WorksheetsInternal.Worksheet(dSheet.Name); - - foreach (var pivotTablePart in wsPart.PivotTableParts) - { - var pivotTableCacheDefinitionPart = pivotTablePart.PivotTableCacheDefinitionPart; - var pivotTableDefinition = pivotTablePart.PivotTableDefinition; - - var target = ws.FirstCell(); - if (pivotTableDefinition.Location != null && pivotTableDefinition.Location.Reference != null && pivotTableDefinition.Location.Reference.HasValue) - { - target = ws.Range(pivotTableDefinition.Location.Reference.Value).FirstCell(); - } - - IXLRange source = null; - if (pivotTableCacheDefinitionPart.PivotCacheDefinition != null - && pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheSource != null - && pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheSource.WorksheetSource != null) - { - // TODO: Implement other sources besides worksheetSource (e.g. Table source?) - // But for now assume names and references point directly to a range - var wss = pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheSource.WorksheetSource; - string rangeAddress = string.Empty; - if (wss.Name != null) - rangeAddress = wss.Name.Value; - else - { - var sourceSheet = wss.Sheet == null ? ws : this.Worksheet(wss.Sheet.Value); - rangeAddress = sourceSheet.Range(wss.Reference.Value).RangeAddress.ToStringRelative(true); - } - - source = this.Range(rangeAddress); - if (source == null) - continue; - } - - if (target != null && source != null) - { - var pt = ws.PivotTables.AddNew(pivotTableDefinition.Name, target, source) as XLPivotTable; - pt.RelId = wsPart.GetIdOfPart(pivotTablePart); - pt.CacheDefinitionRelId = pivotTablePart.GetIdOfPart(pivotTableCacheDefinitionPart); - pt.WorkbookCacheRelId = dSpreadsheet.WorkbookPart.GetIdOfPart(pivotTableCacheDefinitionPart); - - if (pivotTableDefinition.MergeItem != null) pt.MergeAndCenterWithLabels = pivotTableDefinition.MergeItem.Value; - if (pivotTableDefinition.Indent != null) pt.RowLabelIndent = (int)pivotTableDefinition.Indent.Value; - if (pivotTableDefinition.PageOverThenDown != null) pt.FilterAreaOrder = pivotTableDefinition.PageOverThenDown.Value ? XLFilterAreaOrder.OverThenDown : XLFilterAreaOrder.DownThenOver; - if (pivotTableDefinition.PageWrap != null) pt.FilterFieldsPageWrap = (int)pivotTableDefinition.PageWrap.Value; - if (pivotTableDefinition.UseAutoFormatting != null) pt.AutofitColumns = pivotTableDefinition.UseAutoFormatting.Value; - if (pivotTableDefinition.PreserveFormatting != null) pt.PreserveCellFormatting = pivotTableDefinition.PreserveFormatting.Value; - if (pivotTableDefinition.RowGrandTotals != null) pt.ShowGrandTotalsRows = pivotTableDefinition.RowGrandTotals.Value; - if (pivotTableDefinition.ColumnGrandTotals != null) pt.ShowGrandTotalsColumns = pivotTableDefinition.ColumnGrandTotals.Value; - if (pivotTableDefinition.SubtotalHiddenItems != null) pt.FilteredItemsInSubtotals = pivotTableDefinition.SubtotalHiddenItems.Value; - if (pivotTableDefinition.MultipleFieldFilters != null) pt.AllowMultipleFilters = pivotTableDefinition.MultipleFieldFilters.Value; - if (pivotTableDefinition.CustomListSort != null) pt.UseCustomListsForSorting = pivotTableDefinition.CustomListSort.Value; - if (pivotTableDefinition.ShowDrill != null) pt.ShowExpandCollapseButtons = pivotTableDefinition.ShowDrill.Value; - if (pivotTableDefinition.ShowDataTips != null) pt.ShowContextualTooltips = pivotTableDefinition.ShowDataTips.Value; - if (pivotTableDefinition.ShowMemberPropertyTips != null) pt.ShowPropertiesInTooltips = pivotTableDefinition.ShowMemberPropertyTips.Value; - if (pivotTableDefinition.ShowHeaders != null) pt.DisplayCaptionsAndDropdowns = pivotTableDefinition.ShowHeaders.Value; - if (pivotTableDefinition.GridDropZones != null) pt.ClassicPivotTableLayout = pivotTableDefinition.GridDropZones.Value; - if (pivotTableDefinition.ShowEmptyRow != null) pt.ShowEmptyItemsOnRows = pivotTableDefinition.ShowEmptyRow.Value; - if (pivotTableDefinition.ShowEmptyColumn != null) pt.ShowEmptyItemsOnColumns = pivotTableDefinition.ShowEmptyColumn.Value; - if (pivotTableDefinition.ShowItems != null) pt.DisplayItemLabels = pivotTableDefinition.ShowItems.Value; - if (pivotTableDefinition.FieldListSortAscending != null) pt.SortFieldsAtoZ = pivotTableDefinition.FieldListSortAscending.Value; - if (pivotTableDefinition.PrintDrill != null) pt.PrintExpandCollapsedButtons = pivotTableDefinition.PrintDrill.Value; - if (pivotTableDefinition.ItemPrintTitles != null) pt.RepeatRowLabels = pivotTableDefinition.ItemPrintTitles.Value; - if (pivotTableDefinition.FieldPrintTitles != null) pt.PrintTitles = pivotTableDefinition.FieldPrintTitles.Value; - if (pivotTableDefinition.EnableDrill != null) pt.EnableShowDetails = pivotTableDefinition.EnableDrill.Value; - - if (pivotTableDefinition.ShowMissing != null && pivotTableDefinition.MissingCaption != null) - pt.EmptyCellReplacement = pivotTableDefinition.MissingCaption.Value; - - if (pivotTableDefinition.ShowError != null && pivotTableDefinition.ErrorCaption != null) - pt.ErrorValueReplacement = pivotTableDefinition.ErrorCaption.Value; - - // Row labels - if (pivotTableDefinition.RowFields != null) - { - foreach (var rf in pivotTableDefinition.RowFields.Cast()) - { - if (rf.Index < pivotTableDefinition.PivotFields.Count) - { - IXLPivotField pivotField = null; - if (rf.Index.Value == -2) - pivotField = pt.RowLabels.Add(XLConstants.PivotTableValuesSentinalLabel); - else - { - var pf = pivotTableDefinition.PivotFields.ElementAt(rf.Index.Value) as PivotField; - if (pf == null) - continue; - - var cacheField = pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheFields.ElementAt(rf.Index.Value) as CacheField; - if (pf.Name != null) - pivotField = pt.RowLabels.Add(pf.Name.Value); - else if (cacheField.Name != null) - pivotField = pt.RowLabels.Add(cacheField.Name.Value); - else - continue; - - if (pivotField != null) - { - var items = pf.Items.OfType().Where(i => i.Index != null && i.Index.HasValue); - if (!items.Any(i => i.HideDetails == null || BooleanValue.ToBoolean(i.HideDetails))) - pivotField.SetCollapsed(); - } - } - } - } - } - - // Column labels - if (pivotTableDefinition.ColumnFields != null) - { - foreach (var cf in pivotTableDefinition.ColumnFields.Cast()) - { - IXLPivotField pivotField = null; - if (cf.Index.Value == -2) - pivotField = pt.ColumnLabels.Add(XLConstants.PivotTableValuesSentinalLabel); - else if (cf.Index < pivotTableDefinition.PivotFields.Count) - { - var pf = pivotTableDefinition.PivotFields.ElementAt(cf.Index.Value) as PivotField; - if (pf == null) - continue; - - var cacheField = pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheFields.ElementAt(cf.Index.Value) as CacheField; - if (pf.Name != null) - pivotField = pt.ColumnLabels.Add(pf.Name.Value); - else if (cacheField.Name != null) - pivotField = pt.ColumnLabels.Add(cacheField.Name.Value); - else - continue; - - if (pivotField != null) - { - var items = pf.Items.OfType().Where(i => i.Index != null && i.Index.HasValue); - if (!items.Any(i => i.HideDetails == null || BooleanValue.ToBoolean(i.HideDetails))) - pivotField.SetCollapsed(); - } - } - } - } - - // Values - if (pivotTableDefinition.DataFields != null) - { - foreach (var df in pivotTableDefinition.DataFields.Cast()) - { - IXLPivotValue pivotValue = null; - if ((int)df.Field.Value == -2) - pivotValue = pt.Values.Add(XLConstants.PivotTableValuesSentinalLabel); - else if (df.Field.Value < pivotTableDefinition.PivotFields.Count) - { - var pf = pivotTableDefinition.PivotFields.ElementAt((int)df.Field.Value) as PivotField; - if (pf == null) - continue; - - var cacheField = pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheFields.ElementAt((int)df.Field.Value) as CacheField; - - if (pf.Name != null) - pivotValue = pt.Values.Add(pf.Name.Value, df.Name.Value); - else if (cacheField.Name != null) - pivotValue = pt.Values.Add(cacheField.Name.Value, df.Name.Value); - else - continue; - - if (df.NumberFormatId != null) pivotValue.NumberFormat.SetNumberFormatId((int)df.NumberFormatId.Value); - if (df.Subtotal != null) pivotValue = pivotValue.SetSummaryFormula(df.Subtotal.Value.ToClosedXml()); - if (df.ShowDataAs != null) - { - var calculation = pivotValue.Calculation; - calculation = df.ShowDataAs.Value.ToClosedXml(); - pivotValue = pivotValue.SetCalculation(calculation); - } - - if (df.BaseField != null) - { - var col = pt.SourceRange.Column(df.BaseField.Value + 1); - - var items = col.CellsUsed() - .Select(c => c.Value) - .Skip(1) // Skip header column - .Distinct().ToList(); - - pivotValue.BaseField = col.FirstCell().GetValue(); - if (df.BaseItem != null) pivotValue.BaseItem = items[(int)df.BaseItem.Value].ToString(); - } - } - } - } - } - } - } - } - - #endregion - } - - private void LoadDrawings(WorksheetPart wsPart, IXLWorksheet ws) - { - if (wsPart.DrawingsPart != null) - { - var drawingsPart = wsPart.DrawingsPart; - - foreach (var anchor in drawingsPart.WorksheetDrawing.ChildElements) - { - var imgId = GetImageRelIdFromAnchor(anchor); - - //If imgId is null, we're probably dealing with a TextBox (or another shape) instead of a picture - if (imgId == null) continue; - - var imagePart = drawingsPart.GetPartById(imgId); - using (var stream = imagePart.GetStream()) - { - var vsdp = GetPropertiesFromAnchor(anchor); - - var picture = ws.AddPicture(stream, vsdp.Name) as XLPicture; - picture.RelId = imgId; - - Xdr.ShapeProperties spPr = anchor.Descendants().First(); - picture.Placement = XLPicturePlacement.FreeFloating; - picture.Width = ConvertFromEnglishMetricUnits(spPr.Transform2D.Extents.Cx, GraphicsUtils.Graphics.DpiX); - picture.Height = ConvertFromEnglishMetricUnits(spPr.Transform2D.Extents.Cy, GraphicsUtils.Graphics.DpiY); - - if (anchor is Xdr.AbsoluteAnchor) - { - var absoluteAnchor = anchor as Xdr.AbsoluteAnchor; - picture.MoveTo( - ConvertFromEnglishMetricUnits(absoluteAnchor.Position.X.Value, GraphicsUtils.Graphics.DpiX), - ConvertFromEnglishMetricUnits(absoluteAnchor.Position.Y.Value, GraphicsUtils.Graphics.DpiY) - ); - } - else if (anchor is Xdr.OneCellAnchor) - { - var oneCellAnchor = anchor as Xdr.OneCellAnchor; - var from = LoadMarker(ws, oneCellAnchor.FromMarker); - picture.MoveTo(from.Address, from.Offset); - } - else if (anchor is Xdr.TwoCellAnchor) - { - var twoCellAnchor = anchor as Xdr.TwoCellAnchor; - var from = LoadMarker(ws, twoCellAnchor.FromMarker); - var to = LoadMarker(ws, twoCellAnchor.ToMarker); - - if (twoCellAnchor.EditAs == null || !twoCellAnchor.EditAs.HasValue || twoCellAnchor.EditAs.Value == Xdr.EditAsValues.TwoCell) - { - picture.MoveTo(from.Address, from.Offset, to.Address, to.Offset); - } - else if (twoCellAnchor.EditAs.Value == Xdr.EditAsValues.Absolute) - { - var shapeProperties = twoCellAnchor.Descendants().FirstOrDefault(); - if (shapeProperties != null) - { - picture.MoveTo( - ConvertFromEnglishMetricUnits(spPr.Transform2D.Offset.X, GraphicsUtils.Graphics.DpiX), - ConvertFromEnglishMetricUnits(spPr.Transform2D.Offset.Y, GraphicsUtils.Graphics.DpiY) - ); - } - } - else if (twoCellAnchor.EditAs.Value == Xdr.EditAsValues.OneCell) - { - picture.MoveTo(from.Address, from.Offset); - } - } - } - } - } - } - - private static Int32 ConvertFromEnglishMetricUnits(long emu, float resolution) - { - return Convert.ToInt32(emu * resolution / 914400); - } - - private static IXLMarker LoadMarker(IXLWorksheet ws, Xdr.MarkerType marker) - { - return new XLMarker( - ws.Cell(Convert.ToInt32(marker.RowId.InnerText) + 1, Convert.ToInt32(marker.ColumnId.InnerText) + 1).Address, - new Point( - ConvertFromEnglishMetricUnits(Convert.ToInt32(marker.ColumnOffset.InnerText), GraphicsUtils.Graphics.DpiX), - ConvertFromEnglishMetricUnits(Convert.ToInt32(marker.RowOffset.InnerText), GraphicsUtils.Graphics.DpiY) - ) - ); - } - - #region Comment Helpers - - private XDocument GetCommentVmlFile(WorksheetPart wsPart) - { - XDocument xdoc = null; - - foreach (var vmlPart in wsPart.VmlDrawingParts) - { - xdoc = XDocumentExtensions.Load(vmlPart.GetStream(FileMode.Open)); - - //Probe for comments - if (xdoc.Root == null) continue; - var shape = GetCommentShape(xdoc); - if (shape != null) break; - } - - if (xdoc == null) throw new Exception("Could not load comments file"); - return xdoc; - } - - private static XElement GetCommentShape(XDocument xdoc) - { - var xml = xdoc.Root.Element("xml"); - - XElement shape; - if (xml != null) - shape = - xml.Elements().FirstOrDefault(e => (string)e.Attribute("type") == XLConstants.Comment.ShapeTypeId); - else - shape = xdoc.Root.Elements().FirstOrDefault(e => - (string)e.Attribute("type") == - XLConstants.Comment.ShapeTypeId || - (string)e.Attribute("type") == - XLConstants.Comment.AlternateShapeTypeId); - return shape; - } - - #endregion - - private String GetTableColumnName(string name) - { - return name.Replace("_x000a_", Environment.NewLine).Replace("_x005f_x000a_", "_x000a_"); - } - - // This may be part of XLHelper or XLColor - // Leaving it here for now. Can't decide what to call it and where to put it. - private XLColor ExtractColor(String color) - { - if (color.IndexOf("[") >= 0) - { - int start = color.IndexOf("[") + 1; - int end = color.IndexOf("]", start); - return XLColor.FromIndex(Int32.Parse(color.Substring(start, end - start))); - } - else - { - return XLColor.FromHtml(color); - } - } - - private void LoadColorsAndLines(IXLDrawing drawing, XElement shape) - { - var strokeColor = shape.Attribute("strokecolor"); - if (strokeColor != null) drawing.Style.ColorsAndLines.LineColor = ExtractColor(strokeColor.Value); - - var strokeWeight = shape.Attribute("strokeweight"); - if (strokeWeight != null) - drawing.Style.ColorsAndLines.LineWeight = GetPtValue(strokeWeight.Value); - - var fillColor = shape.Attribute("fillcolor"); - if (fillColor != null && !fillColor.Value.ToLower().Contains("infobackground")) drawing.Style.ColorsAndLines.FillColor = ExtractColor(fillColor.Value); - - var fill = shape.Elements().FirstOrDefault(e => e.Name.LocalName == "fill"); - if (fill != null) - { - var opacity = fill.Attribute("opacity"); - if (opacity != null) - { - String opacityVal = opacity.Value; - if (opacityVal.EndsWith("f")) - drawing.Style.ColorsAndLines.FillTransparency = - Double.Parse(opacityVal.Substring(0, opacityVal.Length - 1), CultureInfo.InvariantCulture) / 65536.0; - else - drawing.Style.ColorsAndLines.FillTransparency = Double.Parse(opacityVal, CultureInfo.InvariantCulture); - } - } - - var stroke = shape.Elements().FirstOrDefault(e => e.Name.LocalName == "stroke"); - if (stroke != null) - { - var opacity = stroke.Attribute("opacity"); - if (opacity != null) - { - String opacityVal = opacity.Value; - if (opacityVal.EndsWith("f")) - drawing.Style.ColorsAndLines.LineTransparency = - Double.Parse(opacityVal.Substring(0, opacityVal.Length - 1), CultureInfo.InvariantCulture) / 65536.0; - else - drawing.Style.ColorsAndLines.LineTransparency = Double.Parse(opacityVal, CultureInfo.InvariantCulture); - } - - var dashStyle = stroke.Attribute("dashstyle"); - if (dashStyle != null) - { - String dashStyleVal = dashStyle.Value.ToLower(); - if (dashStyleVal == "1 1" || dashStyleVal == "shortdot") - { - var endCap = stroke.Attribute("endcap"); - if (endCap != null && endCap.Value == "round") - drawing.Style.ColorsAndLines.LineDash = XLDashStyle.RoundDot; - else - drawing.Style.ColorsAndLines.LineDash = XLDashStyle.SquareDot; - } - else - { - switch (dashStyleVal) - { - case "dash": drawing.Style.ColorsAndLines.LineDash = XLDashStyle.Dash; break; - case "dashdot": drawing.Style.ColorsAndLines.LineDash = XLDashStyle.DashDot; break; - case "longdash": drawing.Style.ColorsAndLines.LineDash = XLDashStyle.LongDash; break; - case "longdashdot": drawing.Style.ColorsAndLines.LineDash = XLDashStyle.LongDashDot; break; - case "longdashdotdot": drawing.Style.ColorsAndLines.LineDash = XLDashStyle.LongDashDotDot; break; - } - } - } - - var lineStyle = stroke.Attribute("linestyle"); - if (lineStyle != null) - { - String lineStyleVal = lineStyle.Value.ToLower(); - switch (lineStyleVal) - { - case "single": drawing.Style.ColorsAndLines.LineStyle = XLLineStyle.Single; break; - case "thickbetweenthin": drawing.Style.ColorsAndLines.LineStyle = XLLineStyle.ThickBetweenThin; break; - case "thickthin": drawing.Style.ColorsAndLines.LineStyle = XLLineStyle.ThickThin; break; - case "thinthick": drawing.Style.ColorsAndLines.LineStyle = XLLineStyle.ThinThick; break; - case "thinthin": drawing.Style.ColorsAndLines.LineStyle = XLLineStyle.ThinThin; break; - } - } - } - } - - private void LoadTextBox(IXLDrawing xlDrawing, XElement textBox) - { - var attStyle = textBox.Attribute("style"); - if (attStyle != null) LoadTextBoxStyle(xlDrawing, attStyle); - - var attInset = textBox.Attribute("inset"); - if (attInset != null) LoadTextBoxInset(xlDrawing, attInset); - } - - private void LoadTextBoxInset(IXLDrawing xlDrawing, XAttribute attInset) - { - var split = attInset.Value.Split(','); - xlDrawing.Style.Margins.Left = GetInsetValue(split[0]); - xlDrawing.Style.Margins.Top = GetInsetValue(split[1]); - xlDrawing.Style.Margins.Right = GetInsetValue(split[2]); - xlDrawing.Style.Margins.Bottom = GetInsetValue(split[3]); - } - - private double GetInsetValue(string value) - { - String v = value.Trim(); - if (v.EndsWith("pt")) - return Double.Parse(v.Substring(0, v.Length - 2), CultureInfo.InvariantCulture) / 72.0; - else - return Double.Parse(v.Substring(0, v.Length - 2), CultureInfo.InvariantCulture); - } - - private static void LoadTextBoxStyle(IXLDrawing xlDrawing, XAttribute attStyle) - { - var style = attStyle.Value; - var attributes = style.Split(';'); - foreach (String pair in attributes) - { - var split = pair.Split(':'); - if (split.Length != 2) continue; - - var attribute = split[0].Trim().ToLower(); - var value = split[1].Trim(); - Boolean isVertical = false; - switch (attribute) - { - case "mso-fit-shape-to-text": xlDrawing.Style.Size.SetAutomaticSize(value.Equals("t")); break; - case "mso-layout-flow-alt": - if (value.Equals("bottom-to-top")) xlDrawing.Style.Alignment.SetOrientation(XLDrawingTextOrientation.BottomToTop); - else if (value.Equals("top-to-bottom")) xlDrawing.Style.Alignment.SetOrientation(XLDrawingTextOrientation.Vertical); - break; - - case "layout-flow": isVertical = value.Equals("vertical"); break; - case "mso-direction-alt": if (value == "auto") xlDrawing.Style.Alignment.Direction = XLDrawingTextDirection.Context; break; - case "direction": if (value == "RTL") xlDrawing.Style.Alignment.Direction = XLDrawingTextDirection.RightToLeft; break; - } - if (isVertical && xlDrawing.Style.Alignment.Orientation == XLDrawingTextOrientation.LeftToRight) - xlDrawing.Style.Alignment.Orientation = XLDrawingTextOrientation.TopToBottom; - } - } - - private void LoadClientData(IXLDrawing drawing, XElement clientData) - { - var anchor = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "Anchor"); - if (anchor != null) LoadClientDataAnchor(drawing, anchor); - - LoadDrawingPositioning(drawing, clientData); - LoadDrawingProtection(drawing, clientData); - - var visible = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "Visible"); - drawing.Visible = visible != null && visible.Value.ToLower().StartsWith("t"); - - LoadDrawingHAlignment(drawing, clientData); - LoadDrawingVAlignment(drawing, clientData); - } - - private void LoadDrawingHAlignment(IXLDrawing drawing, XElement clientData) - { - var textHAlign = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "TextHAlign"); - if (textHAlign != null) - drawing.Style.Alignment.Horizontal = (XLDrawingHorizontalAlignment)Enum.Parse(typeof(XLDrawingHorizontalAlignment), textHAlign.Value.ToProper()); - } - - private void LoadDrawingVAlignment(IXLDrawing drawing, XElement clientData) - { - var textVAlign = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "TextVAlign"); - if (textVAlign != null) - drawing.Style.Alignment.Vertical = (XLDrawingVerticalAlignment)Enum.Parse(typeof(XLDrawingVerticalAlignment), textVAlign.Value.ToProper()); - } - - private void LoadDrawingProtection(IXLDrawing drawing, XElement clientData) - { - var lockedElement = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "Locked"); - var lockTextElement = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "LockText"); - Boolean locked = lockedElement != null && lockedElement.Value.ToLower() == "true"; - Boolean lockText = lockTextElement != null && lockTextElement.Value.ToLower() == "true"; - drawing.Style.Protection.Locked = locked; - drawing.Style.Protection.LockText = lockText; - } - - private static void LoadDrawingPositioning(IXLDrawing drawing, XElement clientData) - { - var moveWithCellsElement = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "MoveWithCells"); - var sizeWithCellsElement = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "SizeWithCells"); - Boolean moveWithCells = !(moveWithCellsElement != null && moveWithCellsElement.Value.ToLower() == "true"); - Boolean sizeWithCells = !(sizeWithCellsElement != null && sizeWithCellsElement.Value.ToLower() == "true"); - if (moveWithCells && !sizeWithCells) - drawing.Style.Properties.Positioning = XLDrawingAnchor.MoveWithCells; - else if (moveWithCells && sizeWithCells) - drawing.Style.Properties.Positioning = XLDrawingAnchor.MoveAndSizeWithCells; - else - drawing.Style.Properties.Positioning = XLDrawingAnchor.Absolute; - } - - private static void LoadClientDataAnchor(IXLDrawing drawing, XElement anchor) - { - var location = anchor.Value.Split(','); - drawing.Position.Column = int.Parse(location[0]) + 1; - drawing.Position.ColumnOffset = Double.Parse(location[1], CultureInfo.InvariantCulture) / 7.2; - drawing.Position.Row = int.Parse(location[2]) + 1; - drawing.Position.RowOffset = Double.Parse(location[3], CultureInfo.InvariantCulture); - } - - private void LoadShapeProperties(IXLDrawing xlDrawing, XElement shape) - { - var attStyle = shape.Attribute("style"); - if (attStyle == null) return; - - var style = attStyle.Value; - var attributes = style.Split(';'); - foreach (String pair in attributes) - { - var split = pair.Split(':'); - if (split.Length != 2) continue; - - var attribute = split[0].Trim().ToLower(); - var value = split[1].Trim(); - - switch (attribute) - { - case "visibility": xlDrawing.Visible = value.ToLower().Equals("visible"); break; - case "width": xlDrawing.Style.Size.Width = GetPtValue(value) / 7.5; break; - case "height": xlDrawing.Style.Size.Height = GetPtValue(value); break; - case "z-index": xlDrawing.ZOrder = Int32.Parse(value); break; - } - } - } - - private readonly Dictionary knownUnits = new Dictionary - { - {"pt", 1.0}, - {"in", 72.0}, - {"mm", 72.0/25.4} - }; - - private double GetPtValue(string value) - { - var knownUnit = knownUnits.FirstOrDefault(ku => value.Contains(ku.Key)); - - if (knownUnit.Key == null) - return Double.Parse(value); - - return Double.Parse(value.Replace(knownUnit.Key, String.Empty), CultureInfo.InvariantCulture) * knownUnit.Value; - } - - private void LoadDefinedNames(Workbook workbook) - { - if (workbook.DefinedNames == null) return; - - foreach (var definedName in workbook.DefinedNames.OfType()) - { - var name = definedName.Name; - var visible = true; - if (definedName.Hidden != null) visible = !BooleanValue.ToBoolean(definedName.Hidden); - if (name == "_xlnm.Print_Area") - { - var fixedNames = validateDefinedNames(definedName.Text.Split(',')); - foreach (string area in fixedNames) - { - if (area.Contains("[")) - { - var ws = Worksheets.FirstOrDefault(w => (w as XLWorksheet).SheetId == definedName.LocalSheetId + 1); - if (ws != null) - { - ws.PageSetup.PrintAreas.Add(area); - } - } - else - { - string sheetName, sheetArea; - ParseReference(area, out sheetName, out sheetArea); - if (!(sheetArea.Equals("#REF") || sheetArea.EndsWith("#REF!") || sheetArea.Length == 0)) - WorksheetsInternal.Worksheet(sheetName).PageSetup.PrintAreas.Add(sheetArea); - } - } - } - else if (name == "_xlnm.Print_Titles") - { - LoadPrintTitles(definedName); - } - else - { - string text = definedName.Text; - - if (!(text.Equals("#REF") || text.EndsWith("#REF!"))) - { - var localSheetId = definedName.LocalSheetId; - var comment = definedName.Comment; - if (localSheetId == null) - { - if (!NamedRanges.Any(nr => nr.Name == name)) - (NamedRanges as XLNamedRanges).Add(name, text, comment, true).Visible = visible; - } - else - { - if (!Worksheet(Int32.Parse(localSheetId) + 1).NamedRanges.Any(nr => nr.Name == name)) - Worksheet(Int32.Parse(localSheetId) + 1).NamedRanges.Add(name, text, comment).Visible = visible; - } - } - } - } - } - - private static Regex definedNameRegex = new Regex(@"\A'.*'!.*\z", RegexOptions.Compiled); - - private IEnumerable validateDefinedNames(IEnumerable definedNames) - { - var fixedNames = new List(); - var sb = new StringBuilder(); - foreach (string testName in definedNames) - { - if (sb.Length > 0) - sb.Append(','); - - sb.Append(testName); - - Match matchedValidPattern = definedNameRegex.Match(sb.ToString()); - if (matchedValidPattern.Success) - { - yield return sb.ToString(); - sb = new StringBuilder(); - } - } - - if (sb.Length > 0) - yield return sb.ToString(); - } - - private void LoadPrintTitles(DefinedName definedName) - { - var areas = validateDefinedNames(definedName.Text.Split(',')); - foreach (var item in areas) - { - if (this.Range(item) != null) - SetColumnsOrRowsToRepeat(item); - } - } - - private void SetColumnsOrRowsToRepeat(string area) - { - string sheetName, sheetArea; - ParseReference(area, out sheetName, out sheetArea); - if (sheetArea.Equals("#REF")) return; - if (IsColReference(sheetArea)) - WorksheetsInternal.Worksheet(sheetName).PageSetup.SetColumnsToRepeatAtLeft(sheetArea); - if (IsRowReference(sheetArea)) - WorksheetsInternal.Worksheet(sheetName).PageSetup.SetRowsToRepeatAtTop(sheetArea); - } - - // either $A:$X => true or $1:$99 => false - private static bool IsColReference(string sheetArea) - { - char c = sheetArea[0] == '$' ? sheetArea[1] : sheetArea[0]; - return char.IsLetter(c); - } - - private static bool IsRowReference(string sheetArea) - { - char c = sheetArea[0] == '$' ? sheetArea[1] : sheetArea[0]; - return char.IsNumber(c); - } - - private static void ParseReference(string item, out string sheetName, out string sheetArea) - { - var sections = item.Trim().Split('!'); - if (sections.Count() == 1) - { - sheetName = string.Empty; - sheetArea = item; - } - else - { - sheetName = sections[0].Replace("\'", ""); - sheetArea = sections[1]; - } - } - - private Int32 lastCell; - - private void LoadCells(SharedStringItem[] sharedStrings, Stylesheet s, NumberingFormats numberingFormats, - Fills fills, Borders borders, Fonts fonts, Dictionary sharedFormulasR1C1, - XLWorksheet ws, Dictionary styleList, Cell cell, Int32 rowIndex) - { - Int32 styleIndex = cell.StyleIndex != null ? Int32.Parse(cell.StyleIndex.InnerText) : 0; - - String cellReference = cell.CellReference == null - ? XLHelper.GetColumnLetterFromNumber(++lastCell) + rowIndex - : cell.CellReference.Value; - var xlCell = ws.CellFast(cellReference); - - if (styleList.ContainsKey(styleIndex)) - { - xlCell.Style = styleList[styleIndex]; - } - else - { - ApplyStyle(xlCell, styleIndex, s, fills, borders, fonts, numberingFormats); - styleList.Add(styleIndex, xlCell.Style); - } - - if (cell.CellFormula != null && cell.CellFormula.SharedIndex != null && cell.CellFormula.Reference != null) - { - String formula; - if (cell.CellFormula.FormulaType != null && cell.CellFormula.FormulaType == CellFormulaValues.Array) - formula = "{" + cell.CellFormula.Text + "}"; - else - formula = cell.CellFormula.Text; - - if (cell.CellFormula.Reference != null) - xlCell.FormulaReference = ws.Range(cell.CellFormula.Reference.Value).RangeAddress; - - xlCell.FormulaA1 = formula; - sharedFormulasR1C1.Add(cell.CellFormula.SharedIndex.Value, xlCell.FormulaR1C1); - - if (cell.CellValue != null) - xlCell.ValueCached = cell.CellValue.Text; - } - else if (cell.CellFormula != null) - { - if (cell.CellFormula.SharedIndex != null) - xlCell.FormulaR1C1 = sharedFormulasR1C1[cell.CellFormula.SharedIndex.Value]; - else - { - String formula; - if (cell.CellFormula.FormulaType != null && cell.CellFormula.FormulaType == CellFormulaValues.Array) - formula = "{" + cell.CellFormula.Text + "}"; - else - formula = cell.CellFormula.Text; - - xlCell.FormulaA1 = formula; - } - - if (cell.CellFormula.Reference != null) - xlCell.FormulaReference = ws.Range(cell.CellFormula.Reference.Value).RangeAddress; - - if (cell.CellValue != null) - xlCell.ValueCached = cell.CellValue.Text; - } - else if (cell.DataType != null) - { - if (cell.DataType == CellValues.InlineString) - { - if (cell.InlineString != null) - { - if (cell.InlineString.Text != null) - xlCell._cellValue = cell.InlineString.Text.Text.FixNewLines(); - else - ParseCellValue(cell.InlineString, xlCell); - } - else - xlCell._cellValue = String.Empty; - - xlCell._dataType = XLCellValues.Text; - xlCell.ShareString = false; - } - else if (cell.DataType == CellValues.SharedString) - { - if (cell.CellValue != null && !XLHelper.IsNullOrWhiteSpace(cell.CellValue.Text)) - { - var sharedString = sharedStrings[Int32.Parse(cell.CellValue.Text, XLHelper.NumberStyle, XLHelper.ParseCulture)]; - ParseCellValue(sharedString, xlCell); - } - else - xlCell._cellValue = String.Empty; - - xlCell._dataType = XLCellValues.Text; - } - else if (cell.DataType == CellValues.Date) - { - if (cell.CellValue != null && !XLHelper.IsNullOrWhiteSpace(cell.CellValue.Text)) - xlCell._cellValue = Double.Parse(cell.CellValue.Text, XLHelper.NumberStyle, XLHelper.ParseCulture).ToInvariantString(); - xlCell._dataType = XLCellValues.DateTime; - } - else if (cell.DataType == CellValues.Boolean) - { - if (cell.CellValue != null) - xlCell._cellValue = cell.CellValue.Text; - xlCell._dataType = XLCellValues.Boolean; - } - else if (cell.DataType == CellValues.Number) - { - if (cell.CellValue != null && !XLHelper.IsNullOrWhiteSpace(cell.CellValue.Text)) - xlCell._cellValue = Double.Parse(cell.CellValue.Text, XLHelper.NumberStyle, XLHelper.ParseCulture).ToInvariantString(); - - if (s == null) - xlCell._dataType = XLCellValues.Number; - else - xlCell.DataType = GetDataTypeFromCell(xlCell.Style.NumberFormat); - } - } - else if (cell.CellValue != null) - { - if (s == null) - { - xlCell._dataType = XLCellValues.Number; - } - else - { - var numberFormatId = ((CellFormat)(s.CellFormats).ElementAt(styleIndex)).NumberFormatId; - if (!XLHelper.IsNullOrWhiteSpace(cell.CellValue.Text)) - xlCell._cellValue = Double.Parse(cell.CellValue.Text, CultureInfo.InvariantCulture).ToInvariantString(); - - if (s.NumberingFormats != null && - s.NumberingFormats.Any(nf => ((NumberingFormat)nf).NumberFormatId.Value == numberFormatId)) - { - xlCell.Style.NumberFormat.Format = - ((NumberingFormat)s.NumberingFormats - .First( - nf => ((NumberingFormat)nf).NumberFormatId.Value == numberFormatId) - ).FormatCode.Value; - } - else - xlCell.Style.NumberFormat.NumberFormatId = Int32.Parse(numberFormatId); - - xlCell.DataType = GetDataTypeFromCell(xlCell.Style.NumberFormat); - } - } - } - - /// - /// Parses the cell value for normal or rich text - /// Input element should either be a shared string or inline string - /// - /// The element (either a shared string or inline string) - /// The cell. - private void ParseCellValue(RstType element, XLCell xlCell) - { - var runs = element.Elements(); - var phoneticRuns = element.Elements(); - var phoneticProperties = element.Elements(); - Boolean hasRuns = false; - foreach (Run run in runs) - { - var runProperties = run.RunProperties; - String text = run.Text.InnerText.FixNewLines(); - - if (runProperties == null) - xlCell.RichText.AddText(text, xlCell.Style.Font); - else - { - var rt = xlCell.RichText.AddText(text); - LoadFont(runProperties, rt); - } - if (!hasRuns) - hasRuns = true; - } - - if (!hasRuns) - xlCell._cellValue = XmlEncoder.DecodeString(element.Text.InnerText); - - #region Load PhoneticProperties - - var pp = phoneticProperties.FirstOrDefault(); - if (pp != null) - { - if (pp.Alignment != null) - xlCell.RichText.Phonetics.Alignment = pp.Alignment.Value.ToClosedXml(); - if (pp.Type != null) - xlCell.RichText.Phonetics.Type = pp.Type.Value.ToClosedXml(); - - LoadFont(pp, xlCell.RichText.Phonetics); - } - - #endregion - - #region Load Phonetic Runs - - foreach (PhoneticRun pr in phoneticRuns) - { - xlCell.RichText.Phonetics.Add(pr.Text.InnerText.FixNewLines(), (Int32)pr.BaseTextStartIndex.Value, - (Int32)pr.EndingBaseIndex.Value); - } - - #endregion - } - - private void LoadNumberFormat(NumberingFormat nfSource, IXLNumberFormat nf) - { - if (nfSource == null) return; - - if (nfSource.FormatCode != null) - nf.Format = nfSource.FormatCode.Value; - //if (nfSource.NumberFormatId != null) - // nf.NumberFormatId = (Int32)nfSource.NumberFormatId.Value; - } - - private void LoadBorder(Border borderSource, IXLBorder border) - { - if (borderSource == null) return; - - LoadBorderValues(borderSource.DiagonalBorder, border.SetDiagonalBorder, border.SetDiagonalBorderColor); - - if (borderSource.DiagonalUp != null) - border.DiagonalUp = borderSource.DiagonalUp.Value; - if (borderSource.DiagonalDown != null) - border.DiagonalDown = borderSource.DiagonalDown.Value; - - LoadBorderValues(borderSource.LeftBorder, border.SetLeftBorder, border.SetLeftBorderColor); - LoadBorderValues(borderSource.RightBorder, border.SetRightBorder, border.SetRightBorderColor); - LoadBorderValues(borderSource.TopBorder, border.SetTopBorder, border.SetTopBorderColor); - LoadBorderValues(borderSource.BottomBorder, border.SetBottomBorder, border.SetBottomBorderColor); - } - - private void LoadBorderValues(BorderPropertiesType source, Func setBorder, Func setColor) - { - if (source != null) - { - if (source.Style != null) - setBorder(source.Style.Value.ToClosedXml()); - if (source.Color != null) - setColor(GetColor(source.Color)); - } - } - - private void LoadFill(Fill fillSource, IXLFill fill) - { - if (fillSource == null) return; - - if (fillSource.PatternFill != null) - { - if (fillSource.PatternFill.PatternType != null) - fill.PatternType = fillSource.PatternFill.PatternType.Value.ToClosedXml(); - else - fill.PatternType = XLFillPatternValues.Solid; - - if (fillSource.PatternFill.ForegroundColor != null) - fill.PatternColor = GetColor(fillSource.PatternFill.ForegroundColor); - if (fillSource.PatternFill.BackgroundColor != null) - fill.PatternBackgroundColor = GetColor(fillSource.PatternFill.BackgroundColor); - } - } - - private void LoadFont(OpenXmlElement fontSource, IXLFontBase fontBase) - { - if (fontSource == null) return; - - fontBase.Bold = GetBoolean(fontSource.Elements().FirstOrDefault()); - var fontColor = GetColor(fontSource.Elements().FirstOrDefault()); - if (fontColor.HasValue) - fontBase.FontColor = fontColor; - - var fontFamilyNumbering = - fontSource.Elements().FirstOrDefault(); - if (fontFamilyNumbering != null && fontFamilyNumbering.Val != null) - fontBase.FontFamilyNumbering = - (XLFontFamilyNumberingValues)Int32.Parse(fontFamilyNumbering.Val.ToString()); - var runFont = fontSource.Elements().FirstOrDefault(); - if (runFont != null) - { - if (runFont.Val != null) - fontBase.FontName = runFont.Val; - } - var fontSize = fontSource.Elements().FirstOrDefault(); - if (fontSize != null) - { - if ((fontSize).Val != null) - fontBase.FontSize = (fontSize).Val; - } - - fontBase.Italic = GetBoolean(fontSource.Elements().FirstOrDefault()); - fontBase.Shadow = GetBoolean(fontSource.Elements().FirstOrDefault()); - fontBase.Strikethrough = GetBoolean(fontSource.Elements().FirstOrDefault()); - - var underline = fontSource.Elements().FirstOrDefault(); - if (underline != null) - { - fontBase.Underline = underline.Val != null ? underline.Val.Value.ToClosedXml() : XLFontUnderlineValues.Single; - } - - var verticalTextAlignment = fontSource.Elements().FirstOrDefault(); - - if (verticalTextAlignment == null) return; - - fontBase.VerticalAlignment = verticalTextAlignment.Val != null ? verticalTextAlignment.Val.Value.ToClosedXml() : XLFontVerticalTextAlignmentValues.Baseline; - } - - private Int32 lastRow; - - private void LoadRows(Stylesheet s, NumberingFormats numberingFormats, Fills fills, Borders borders, Fonts fonts, - XLWorksheet ws, SharedStringItem[] sharedStrings, - Dictionary sharedFormulasR1C1, Dictionary styleList, - Row row) - { - Int32 rowIndex = row.RowIndex == null ? ++lastRow : (Int32)row.RowIndex.Value; - var xlRow = ws.Row(rowIndex, false); - - if (row.Height != null) - xlRow.Height = row.Height; - else - { - xlRow.Loading = true; - xlRow.Height = ws.RowHeight; - xlRow.Loading = false; - } - - if (row.Hidden != null && row.Hidden) - xlRow.Hide(); - - if (row.Collapsed != null && row.Collapsed) - xlRow.Collapsed = true; - - if (row.OutlineLevel != null && row.OutlineLevel > 0) - xlRow.OutlineLevel = row.OutlineLevel; - - if (row.CustomFormat != null) - { - Int32 styleIndex = row.StyleIndex != null ? Int32.Parse(row.StyleIndex.InnerText) : -1; - if (styleIndex > 0) - { - ApplyStyle(xlRow, styleIndex, s, fills, borders, fonts, numberingFormats); - } - else - { - xlRow.Style = DefaultStyle; - } - } - - lastCell = 0; - foreach (Cell cell in row.Elements()) - LoadCells(sharedStrings, s, numberingFormats, fills, borders, fonts, sharedFormulasR1C1, ws, styleList, - cell, rowIndex); - } - - private void LoadColumns(Stylesheet s, NumberingFormats numberingFormats, Fills fills, Borders borders, - Fonts fonts, XLWorksheet ws, Columns columns) - { - if (columns == null) return; - - var wsDefaultColumn = - columns.Elements().Where(c => c.Max == XLHelper.MaxColumnNumber).FirstOrDefault(); - - if (wsDefaultColumn != null && wsDefaultColumn.Width != null) - ws.ColumnWidth = wsDefaultColumn.Width - ColumnWidthOffset; - - Int32 styleIndexDefault = wsDefaultColumn != null && wsDefaultColumn.Style != null - ? Int32.Parse(wsDefaultColumn.Style.InnerText) - : -1; - if (styleIndexDefault >= 0) - ApplyStyle(ws, styleIndexDefault, s, fills, borders, fonts, numberingFormats); - - foreach (Column col in columns.Elements()) - { - //IXLStylized toApply; - if (col.Max == XLHelper.MaxColumnNumber) continue; - - var xlColumns = (XLColumns)ws.Columns(col.Min, col.Max); - if (col.Width != null) - { - Double width = col.Width - ColumnWidthOffset; - //if (width < 0) width = 0; - xlColumns.Width = width; - } - else - xlColumns.Width = ws.ColumnWidth; - - if (col.Hidden != null && col.Hidden) - xlColumns.Hide(); - - if (col.Collapsed != null && col.Collapsed) - xlColumns.CollapseOnly(); - - if (col.OutlineLevel != null) - { - var outlineLevel = col.OutlineLevel; - xlColumns.ForEach(c => c.OutlineLevel = outlineLevel); - } - - Int32 styleIndex = col.Style != null ? Int32.Parse(col.Style.InnerText) : -1; - if (styleIndex > 0) - { - ApplyStyle(xlColumns, styleIndex, s, fills, borders, fonts, numberingFormats); - } - else - { - xlColumns.Style = DefaultStyle; - } - } - } - - private static XLCellValues GetDataTypeFromCell(IXLNumberFormat numberFormat) - { - var numberFormatId = numberFormat.NumberFormatId; - if (numberFormatId == 46U) - return XLCellValues.TimeSpan; - else if ((numberFormatId >= 14 && numberFormatId <= 22) || - (numberFormatId >= 45 && numberFormatId <= 47)) - return XLCellValues.DateTime; - else if (numberFormatId == 49) - return XLCellValues.Text; - else - { - if (!XLHelper.IsNullOrWhiteSpace(numberFormat.Format)) - { - var dataType = GetDataTypeFromFormat(numberFormat.Format); - return dataType.HasValue ? dataType.Value : XLCellValues.Number; - } - else - return XLCellValues.Number; - } - } - - private static XLCellValues? GetDataTypeFromFormat(String format) - { - int length = format.Length; - String f = format.ToLower(); - for (Int32 i = 0; i < length; i++) - { - Char c = f[i]; - if (c == '"') - i = f.IndexOf('"', i + 1); - else if (c == '0' || c == '#' || c == '?') - return XLCellValues.Number; - else if (c == 'y' || c == 'm' || c == 'd' || c == 'h' || c == 's') - return XLCellValues.DateTime; - } - return null; - } - - private static void LoadAutoFilter(AutoFilter af, XLWorksheet ws) - { - if (af != null) - { - ws.Range(af.Reference.Value).SetAutoFilter(); - var autoFilter = ws.AutoFilter; - LoadAutoFilterSort(af, ws, autoFilter); - LoadAutoFilterColumns(af, autoFilter); - } - } - - private static void LoadAutoFilterColumns(AutoFilter af, XLAutoFilter autoFilter) - { - foreach (var filterColumn in af.Elements()) - { - Int32 column = (int)filterColumn.ColumnId.Value + 1; - if (filterColumn.CustomFilters != null) - { - var filterList = new List(); - autoFilter.Column(column).FilterType = XLFilterType.Custom; - autoFilter.Filters.Add(column, filterList); - XLConnector connector = filterColumn.CustomFilters.And != null && filterColumn.CustomFilters.And.Value ? XLConnector.And : XLConnector.Or; - - Boolean isText = false; - foreach (CustomFilter filter in filterColumn.CustomFilters) - { - Double dTest; - String val = filter.Val.Value; - if (!Double.TryParse(val, out dTest)) - { - isText = true; - break; - } - } - - foreach (CustomFilter filter in filterColumn.CustomFilters) - { - var xlFilter = new XLFilter { Value = filter.Val.Value, Connector = connector }; - if (isText) - xlFilter.Value = filter.Val.Value; - else - xlFilter.Value = Double.Parse(filter.Val.Value, CultureInfo.InvariantCulture); - - if (filter.Operator != null) - xlFilter.Operator = filter.Operator.Value.ToClosedXml(); - else - xlFilter.Operator = XLFilterOperator.Equal; - - Func condition = null; - switch (xlFilter.Operator) - { - case XLFilterOperator.Equal: - if (isText) - condition = o => o.ToString().Equals(xlFilter.Value.ToString(), StringComparison.InvariantCultureIgnoreCase); - else - condition = o => (o as IComparable).CompareTo(xlFilter.Value) == 0; - break; - - case XLFilterOperator.EqualOrGreaterThan: condition = o => (o as IComparable).CompareTo(xlFilter.Value) >= 0; break; - case XLFilterOperator.EqualOrLessThan: condition = o => (o as IComparable).CompareTo(xlFilter.Value) <= 0; break; - case XLFilterOperator.GreaterThan: condition = o => (o as IComparable).CompareTo(xlFilter.Value) > 0; break; - case XLFilterOperator.LessThan: condition = o => (o as IComparable).CompareTo(xlFilter.Value) < 0; break; - case XLFilterOperator.NotEqual: - if (isText) - condition = o => !o.ToString().Equals(xlFilter.Value.ToString(), StringComparison.InvariantCultureIgnoreCase); - else - condition = o => (o as IComparable).CompareTo(xlFilter.Value) != 0; - break; - } - - xlFilter.Condition = condition; - filterList.Add(xlFilter); - } - } - else if (filterColumn.Filters != null) - { - var filterList = new List(); - autoFilter.Column(column).FilterType = XLFilterType.Regular; - autoFilter.Filters.Add((int)filterColumn.ColumnId.Value + 1, filterList); - - Boolean isText = false; - foreach (Filter filter in filterColumn.Filters.OfType()) - { - Double dTest; - String val = filter.Val.Value; - if (!Double.TryParse(val, out dTest)) - { - isText = true; - break; - } - } - - foreach (Filter filter in filterColumn.Filters.OfType()) - { - var xlFilter = new XLFilter { Connector = XLConnector.Or, Operator = XLFilterOperator.Equal }; - - Func condition; - if (isText) - { - xlFilter.Value = filter.Val.Value; - condition = o => o.ToString().Equals(xlFilter.Value.ToString(), StringComparison.InvariantCultureIgnoreCase); - } - else - { - xlFilter.Value = Double.Parse(filter.Val.Value, CultureInfo.InvariantCulture); - condition = o => (o as IComparable).CompareTo(xlFilter.Value) == 0; - } - - xlFilter.Condition = condition; - filterList.Add(xlFilter); - } - } - else if (filterColumn.Top10 != null) - { - var xlFilterColumn = autoFilter.Column(column); - autoFilter.Filters.Add(column, null); - xlFilterColumn.FilterType = XLFilterType.TopBottom; - if (filterColumn.Top10.Percent != null && filterColumn.Top10.Percent.Value) - xlFilterColumn.TopBottomType = XLTopBottomType.Percent; - else - xlFilterColumn.TopBottomType = XLTopBottomType.Items; - - if (filterColumn.Top10.Top != null && !filterColumn.Top10.Top.Value) - xlFilterColumn.TopBottomPart = XLTopBottomPart.Bottom; - else - xlFilterColumn.TopBottomPart = XLTopBottomPart.Top; - - xlFilterColumn.TopBottomValue = (int)filterColumn.Top10.Val.Value; - } - else if (filterColumn.DynamicFilter != null) - { - autoFilter.Filters.Add(column, null); - var xlFilterColumn = autoFilter.Column(column); - xlFilterColumn.FilterType = XLFilterType.Dynamic; - if (filterColumn.DynamicFilter.Type != null) - xlFilterColumn.DynamicType = filterColumn.DynamicFilter.Type.Value.ToClosedXml(); - else - xlFilterColumn.DynamicType = XLFilterDynamicType.AboveAverage; - - xlFilterColumn.DynamicValue = filterColumn.DynamicFilter.Val.Value; - } - } - } - - private static void LoadAutoFilterSort(AutoFilter af, XLWorksheet ws, IXLBaseAutoFilter autoFilter) - { - var sort = af.Elements().FirstOrDefault(); - if (sort != null) - { - var condition = sort.Elements().FirstOrDefault(); - if (condition != null) - { - Int32 column = ws.Range(condition.Reference.Value).FirstCell().Address.ColumnNumber - autoFilter.Range.FirstCell().Address.ColumnNumber + 1; - autoFilter.SortColumn = column; - autoFilter.Sorted = true; - autoFilter.SortOrder = condition.Descending != null && condition.Descending.Value ? XLSortOrder.Descending : XLSortOrder.Ascending; - } - } - } - - private static void LoadSheetProtection(SheetProtection sp, XLWorksheet ws) - { - if (sp == null) return; - - if (sp.Sheet != null) ws.Protection.Protected = sp.Sheet.Value; - if (sp.Password != null) ws.Protection.PasswordHash = sp.Password.Value; - if (sp.FormatCells != null) ws.Protection.FormatCells = !sp.FormatCells.Value; - if (sp.FormatColumns != null) ws.Protection.FormatColumns = !sp.FormatColumns.Value; - if (sp.FormatRows != null) ws.Protection.FormatRows = !sp.FormatRows.Value; - if (sp.InsertColumns != null) ws.Protection.InsertColumns = !sp.InsertColumns.Value; - if (sp.InsertHyperlinks != null) ws.Protection.InsertHyperlinks = !sp.InsertHyperlinks.Value; - if (sp.InsertRows != null) ws.Protection.InsertRows = !sp.InsertRows.Value; - if (sp.DeleteColumns != null) ws.Protection.DeleteColumns = !sp.DeleteColumns.Value; - if (sp.DeleteRows != null) ws.Protection.DeleteRows = !sp.DeleteRows.Value; - if (sp.AutoFilter != null) ws.Protection.AutoFilter = !sp.AutoFilter.Value; - if (sp.PivotTables != null) ws.Protection.PivotTables = !sp.PivotTables.Value; - if (sp.Sort != null) ws.Protection.Sort = !sp.Sort.Value; - if (sp.SelectLockedCells != null) ws.Protection.SelectLockedCells = sp.SelectLockedCells.Value; - if (sp.SelectUnlockedCells != null) ws.Protection.SelectUnlockedCells = sp.SelectUnlockedCells.Value; - } - - private static void LoadDataValidations(DataValidations dataValidations, XLWorksheet ws) - { - if (dataValidations == null) return; - - foreach (DataValidation dvs in dataValidations.Elements()) - { - String txt = dvs.SequenceOfReferences.InnerText; - if (XLHelper.IsNullOrWhiteSpace(txt)) continue; - foreach (var dvt in txt.Split(' ').Select(rangeAddress => ws.Range(rangeAddress).DataValidation)) - { - if (dvs.AllowBlank != null) dvt.IgnoreBlanks = dvs.AllowBlank; - if (dvs.ShowDropDown != null) dvt.InCellDropdown = !dvs.ShowDropDown.Value; - if (dvs.ShowErrorMessage != null) dvt.ShowErrorMessage = dvs.ShowErrorMessage; - if (dvs.ShowInputMessage != null) dvt.ShowInputMessage = dvs.ShowInputMessage; - if (dvs.PromptTitle != null) dvt.InputTitle = dvs.PromptTitle; - if (dvs.Prompt != null) dvt.InputMessage = dvs.Prompt; - if (dvs.ErrorTitle != null) dvt.ErrorTitle = dvs.ErrorTitle; - if (dvs.Error != null) dvt.ErrorMessage = dvs.Error; - if (dvs.ErrorStyle != null) dvt.ErrorStyle = dvs.ErrorStyle.Value.ToClosedXml(); - if (dvs.Type != null) dvt.AllowedValues = dvs.Type.Value.ToClosedXml(); - if (dvs.Operator != null) dvt.Operator = dvs.Operator.Value.ToClosedXml(); - if (dvs.Formula1 != null) dvt.MinValue = dvs.Formula1.Text; - if (dvs.Formula2 != null) dvt.MaxValue = dvs.Formula2.Text; - } - } - } - - /// - /// Loads the conditional formatting. - /// - // https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.conditionalformattingrule%28v=office.15%29.aspx?f=255&MSPPError=-2147217396 - private void LoadConditionalFormatting(ConditionalFormatting conditionalFormatting, XLWorksheet ws, Dictionary differentialFormats) - { - if (conditionalFormatting == null) return; - - foreach (var sor in conditionalFormatting.SequenceOfReferences.Items) - { - foreach (var fr in conditionalFormatting.Elements()) - { - var conditionalFormat = new XLConditionalFormat(ws.Range(sor.Value)); - if (fr.FormatId != null) - { - LoadFont(differentialFormats[(Int32)fr.FormatId.Value].Font, conditionalFormat.Style.Font); - LoadFill(differentialFormats[(Int32)fr.FormatId.Value].Fill, conditionalFormat.Style.Fill); - LoadBorder(differentialFormats[(Int32)fr.FormatId.Value].Border, conditionalFormat.Style.Border); - LoadNumberFormat(differentialFormats[(Int32)fr.FormatId.Value].NumberingFormat, conditionalFormat.Style.NumberFormat); - } - - // The conditional formatting type is compulsory. If it doesn't exist, skip the entire rule. - if (fr.Type == null) continue; - conditionalFormat.ConditionalFormatType = fr.Type.Value.ToClosedXml(); - - if (conditionalFormat.ConditionalFormatType == XLConditionalFormatType.CellIs && fr.Operator != null) - conditionalFormat.Operator = fr.Operator.Value.ToClosedXml(); - - if (fr.Text != null && !XLHelper.IsNullOrWhiteSpace(fr.Text)) - conditionalFormat.Values.Add(GetFormula(fr.Text.Value)); - - if (conditionalFormat.ConditionalFormatType == XLConditionalFormatType.Top10) - { - if (fr.Percent != null) - conditionalFormat.Percent = fr.Percent.Value; - if (fr.Bottom != null) - conditionalFormat.Bottom = fr.Bottom.Value; - if (fr.Rank != null) - conditionalFormat.Values.Add(GetFormula(fr.Rank.Value.ToString())); - } - - if (fr.Elements().Any()) - { - var colorScale = fr.Elements().First(); - ExtractConditionalFormatValueObjects(conditionalFormat, colorScale); - } - else if (fr.Elements().Any()) - { - var dataBar = fr.Elements().First(); - if (dataBar.ShowValue != null) - conditionalFormat.ShowBarOnly = !dataBar.ShowValue.Value; - ExtractConditionalFormatValueObjects(conditionalFormat, dataBar); - } - else if (fr.Elements().Any()) - { - var iconSet = fr.Elements().First(); - if (iconSet.ShowValue != null) - conditionalFormat.ShowIconOnly = !iconSet.ShowValue.Value; - if (iconSet.Reverse != null) - conditionalFormat.ReverseIconOrder = iconSet.Reverse.Value; - - if (iconSet.IconSetValue != null) - conditionalFormat.IconSetStyle = iconSet.IconSetValue.Value.ToClosedXml(); - else - conditionalFormat.IconSetStyle = XLIconSetStyle.ThreeTrafficLights1; - - ExtractConditionalFormatValueObjects(conditionalFormat, iconSet); - } - else - { - foreach (var formula in fr.Elements()) - { - if (formula.Text != null - && (conditionalFormat.ConditionalFormatType == XLConditionalFormatType.CellIs - || conditionalFormat.ConditionalFormatType == XLConditionalFormatType.Expression)) - { - conditionalFormat.Values.Add(GetFormula(formula.Text)); - } - } - } - ws.ConditionalFormats.Add(conditionalFormat); - } - } - } - - private static XLFormula GetFormula(String value) - { - var formula = new XLFormula(); - formula._value = value; - formula.IsFormula = !(value[0] == '"' && value.EndsWith("\"")); - return formula; - } - - private void ExtractConditionalFormatValueObjects(XLConditionalFormat conditionalFormat, OpenXmlElement element) - { - foreach (var c in element.Elements()) - { - if (c.Type != null) - conditionalFormat.ContentTypes.Add(c.Type.Value.ToClosedXml()); - if (c.Val != null) - conditionalFormat.Values.Add(new XLFormula { Value = c.Val.Value }); - else - conditionalFormat.Values.Add(null); - - if (c.GreaterThanOrEqual != null) - conditionalFormat.IconSetOperators.Add(c.GreaterThanOrEqual.Value ? XLCFIconSetOperator.EqualOrGreaterThan : XLCFIconSetOperator.GreaterThan); - else - conditionalFormat.IconSetOperators.Add(XLCFIconSetOperator.EqualOrGreaterThan); - } - foreach (var c in element.Elements()) - { - conditionalFormat.Colors.Add(GetColor(c)); - } - } - - private static void LoadHyperlinks(Hyperlinks hyperlinks, WorksheetPart worksheetPart, XLWorksheet ws) - { - var hyperlinkDictionary = new Dictionary(); - if (worksheetPart.HyperlinkRelationships != null) - hyperlinkDictionary = worksheetPart.HyperlinkRelationships.ToDictionary(hr => hr.Id, hr => hr.Uri); - - if (hyperlinks == null) return; - - foreach (Hyperlink hl in hyperlinks.Elements()) - { - if (hl.Reference.Value.Equals("#REF")) continue; - String tooltip = hl.Tooltip != null ? hl.Tooltip.Value : String.Empty; - var xlRange = ws.Range(hl.Reference.Value); - foreach (XLCell xlCell in xlRange.Cells()) - { - xlCell.SettingHyperlink = true; - - if (hl.Id != null) - xlCell.Hyperlink = new XLHyperlink(hyperlinkDictionary[hl.Id], tooltip); - else if (hl.Location != null) - xlCell.Hyperlink = new XLHyperlink(hl.Location.Value, tooltip); - else - xlCell.Hyperlink = new XLHyperlink(hl.Reference.Value, tooltip); - - xlCell.SettingHyperlink = false; - } - } - } - - private static void LoadColumnBreaks(ColumnBreaks columnBreaks, XLWorksheet ws) - { - if (columnBreaks == null) return; - - foreach (Break columnBreak in columnBreaks.Elements().Where(columnBreak => columnBreak.Id != null)) - { - ws.PageSetup.ColumnBreaks.Add(Int32.Parse(columnBreak.Id.InnerText)); - } - } - - private static void LoadRowBreaks(RowBreaks rowBreaks, XLWorksheet ws) - { - if (rowBreaks == null) return; - - foreach (Break rowBreak in rowBreaks.Elements()) - ws.PageSetup.RowBreaks.Add(Int32.Parse(rowBreak.Id.InnerText)); - } - - private void LoadSheetProperties(SheetProperties sheetProperty, XLWorksheet ws, out PageSetupProperties pageSetupProperties) - { - pageSetupProperties = null; - if (sheetProperty == null) return; - - if (sheetProperty.TabColor != null) - ws.TabColor = GetColor(sheetProperty.TabColor); - - if (sheetProperty.OutlineProperties != null) - { - if (sheetProperty.OutlineProperties.SummaryBelow != null) - { - ws.Outline.SummaryVLocation = sheetProperty.OutlineProperties.SummaryBelow - ? XLOutlineSummaryVLocation.Bottom - : XLOutlineSummaryVLocation.Top; - } - - if (sheetProperty.OutlineProperties.SummaryRight != null) - { - ws.Outline.SummaryHLocation = sheetProperty.OutlineProperties.SummaryRight - ? XLOutlineSummaryHLocation.Right - : XLOutlineSummaryHLocation.Left; - } - } - - if (sheetProperty.PageSetupProperties != null) - pageSetupProperties = sheetProperty.PageSetupProperties; - } - - private static void LoadHeaderFooter(HeaderFooter headerFooter, XLWorksheet ws) - { - if (headerFooter == null) return; - - if (headerFooter.AlignWithMargins != null) - ws.PageSetup.AlignHFWithMargins = headerFooter.AlignWithMargins; - if (headerFooter.ScaleWithDoc != null) - ws.PageSetup.ScaleHFWithDocument = headerFooter.ScaleWithDoc; - - if (headerFooter.DifferentFirst != null) - ws.PageSetup.DifferentFirstPageOnHF = headerFooter.DifferentFirst; - if (headerFooter.DifferentOddEven != null) - ws.PageSetup.DifferentOddEvenPagesOnHF = headerFooter.DifferentOddEven; - - // Footers - var xlFooter = (XLHeaderFooter)ws.PageSetup.Footer; - var evenFooter = headerFooter.EvenFooter; - if (evenFooter != null) - xlFooter.SetInnerText(XLHFOccurrence.EvenPages, evenFooter.Text); - var oddFooter = headerFooter.OddFooter; - if (oddFooter != null) - xlFooter.SetInnerText(XLHFOccurrence.OddPages, oddFooter.Text); - var firstFooter = headerFooter.FirstFooter; - if (firstFooter != null) - xlFooter.SetInnerText(XLHFOccurrence.FirstPage, firstFooter.Text); - // Headers - var xlHeader = (XLHeaderFooter)ws.PageSetup.Header; - var evenHeader = headerFooter.EvenHeader; - if (evenHeader != null) - xlHeader.SetInnerText(XLHFOccurrence.EvenPages, evenHeader.Text); - var oddHeader = headerFooter.OddHeader; - if (oddHeader != null) - xlHeader.SetInnerText(XLHFOccurrence.OddPages, oddHeader.Text); - var firstHeader = headerFooter.FirstHeader; - if (firstHeader != null) - xlHeader.SetInnerText(XLHFOccurrence.FirstPage, firstHeader.Text); - - ((XLHeaderFooter)ws.PageSetup.Header).SetAsInitial(); - ((XLHeaderFooter)ws.PageSetup.Footer).SetAsInitial(); - } - - private static void LoadPageSetup(PageSetup pageSetup, XLWorksheet ws, PageSetupProperties pageSetupProperties) - { - if (pageSetup == null) return; - - if (pageSetup.PaperSize != null) - ws.PageSetup.PaperSize = (XLPaperSize)Int32.Parse(pageSetup.PaperSize.InnerText); - if (pageSetup.Scale != null) - ws.PageSetup.Scale = Int32.Parse(pageSetup.Scale.InnerText); - if (pageSetupProperties != null && pageSetupProperties.FitToPage != null && pageSetupProperties.FitToPage.Value) - { - if (pageSetup.FitToWidth == null) - ws.PageSetup.PagesWide = 1; - else - ws.PageSetup.PagesWide = Int32.Parse(pageSetup.FitToWidth.InnerText); - - if (pageSetup.FitToHeight == null) - ws.PageSetup.PagesTall = 1; - else - ws.PageSetup.PagesTall = Int32.Parse(pageSetup.FitToHeight.InnerText); - } - if (pageSetup.PageOrder != null) - ws.PageSetup.PageOrder = pageSetup.PageOrder.Value.ToClosedXml(); - if (pageSetup.Orientation != null) - ws.PageSetup.PageOrientation = pageSetup.Orientation.Value.ToClosedXml(); - if (pageSetup.BlackAndWhite != null) - ws.PageSetup.BlackAndWhite = pageSetup.BlackAndWhite; - if (pageSetup.Draft != null) - ws.PageSetup.DraftQuality = pageSetup.Draft; - if (pageSetup.CellComments != null) - ws.PageSetup.ShowComments = pageSetup.CellComments.Value.ToClosedXml(); - if (pageSetup.Errors != null) - ws.PageSetup.PrintErrorValue = pageSetup.Errors.Value.ToClosedXml(); - if (pageSetup.HorizontalDpi != null) ws.PageSetup.HorizontalDpi = (Int32)pageSetup.HorizontalDpi.Value; - if (pageSetup.VerticalDpi != null) ws.PageSetup.VerticalDpi = (Int32)pageSetup.VerticalDpi.Value; - if (pageSetup.FirstPageNumber != null) - ws.PageSetup.FirstPageNumber = UInt32.Parse(pageSetup.FirstPageNumber.InnerText); - } - - private static void LoadPageMargins(PageMargins pageMargins, XLWorksheet ws) - { - if (pageMargins == null) return; - - if (pageMargins.Bottom != null) - ws.PageSetup.Margins.Bottom = pageMargins.Bottom; - if (pageMargins.Footer != null) - ws.PageSetup.Margins.Footer = pageMargins.Footer; - if (pageMargins.Header != null) - ws.PageSetup.Margins.Header = pageMargins.Header; - if (pageMargins.Left != null) - ws.PageSetup.Margins.Left = pageMargins.Left; - if (pageMargins.Right != null) - ws.PageSetup.Margins.Right = pageMargins.Right; - if (pageMargins.Top != null) - ws.PageSetup.Margins.Top = pageMargins.Top; - } - - private static void LoadPrintOptions(PrintOptions printOptions, XLWorksheet ws) - { - if (printOptions == null) return; - - if (printOptions.GridLines != null) - ws.PageSetup.ShowGridlines = printOptions.GridLines; - if (printOptions.HorizontalCentered != null) - ws.PageSetup.CenterHorizontally = printOptions.HorizontalCentered; - if (printOptions.VerticalCentered != null) - ws.PageSetup.CenterVertically = printOptions.VerticalCentered; - if (printOptions.Headings != null) - ws.PageSetup.ShowRowAndColumnHeadings = printOptions.Headings; - } - - private static void LoadSheetViews(SheetViews sheetViews, XLWorksheet ws) - { - if (sheetViews == null) return; - - var sheetView = sheetViews.Elements().FirstOrDefault(); - - if (sheetView == null) return; - - if (sheetView.RightToLeft != null) ws.RightToLeft = sheetView.RightToLeft.Value; - if (sheetView.ShowFormulas != null) ws.ShowFormulas = sheetView.ShowFormulas.Value; - if (sheetView.ShowGridLines != null) ws.ShowGridLines = sheetView.ShowGridLines.Value; - if (sheetView.ShowOutlineSymbols != null) - ws.ShowOutlineSymbols = sheetView.ShowOutlineSymbols.Value; - if (sheetView.ShowRowColHeaders != null) ws.ShowRowColHeaders = sheetView.ShowRowColHeaders.Value; - if (sheetView.ShowRuler != null) ws.ShowRuler = sheetView.ShowRuler.Value; - if (sheetView.ShowWhiteSpace != null) ws.ShowWhiteSpace = sheetView.ShowWhiteSpace.Value; - if (sheetView.ShowZeros != null) ws.ShowZeros = sheetView.ShowZeros.Value; - if (sheetView.TabSelected != null) ws.TabSelected = sheetView.TabSelected.Value; - - var selection = sheetView.Elements().FirstOrDefault(); - if (selection != null) - { - if (selection.SequenceOfReferences != null) - ws.Ranges(selection.SequenceOfReferences.InnerText.Replace(" ", ",")).Select(); - - if (selection.ActiveCell != null) - ws.Cell(selection.ActiveCell).SetActive(); - } - - if (sheetView.ZoomScale != null) - ws.SheetView.ZoomScale = (int)UInt32Value.ToUInt32(sheetView.ZoomScale); - if (sheetView.ZoomScaleNormal != null) - ws.SheetView.ZoomScaleNormal = (int)UInt32Value.ToUInt32(sheetView.ZoomScaleNormal); - if (sheetView.ZoomScalePageLayoutView != null) - ws.SheetView.ZoomScalePageLayoutView = (int)UInt32Value.ToUInt32(sheetView.ZoomScalePageLayoutView); - if (sheetView.ZoomScaleSheetLayoutView != null) - ws.SheetView.ZoomScaleSheetLayoutView = (int)UInt32Value.ToUInt32(sheetView.ZoomScaleSheetLayoutView); - - var pane = sheetView.Elements().FirstOrDefault(); - if (pane == null) return; - - if (pane.State == null || - (pane.State != PaneStateValues.FrozenSplit && pane.State != PaneStateValues.Frozen)) return; - - if (pane.HorizontalSplit != null) - ws.SheetView.SplitColumn = (Int32)pane.HorizontalSplit.Value; - if (pane.VerticalSplit != null) - ws.SheetView.SplitRow = (Int32)pane.VerticalSplit.Value; - } - - private void SetProperties(SpreadsheetDocument dSpreadsheet) - { - var p = dSpreadsheet.PackageProperties; - Properties.Author = p.Creator; - Properties.Category = p.Category; - Properties.Comments = p.Description; - if (p.Created != null) - Properties.Created = p.Created.Value; - Properties.Keywords = p.Keywords; - Properties.LastModifiedBy = p.LastModifiedBy; - Properties.Status = p.ContentStatus; - Properties.Subject = p.Subject; - Properties.Title = p.Title; - } - - private XLColor GetColor(ColorType color) - { - XLColor retVal = null; - if (color != null) - { - if (color.Rgb != null) - { - String htmlColor = "#" + color.Rgb.Value; - Color thisColor; - if (!_colorList.ContainsKey(htmlColor)) - { - thisColor = ColorTranslator.FromHtml(htmlColor); - _colorList.Add(htmlColor, thisColor); - } - else - thisColor = _colorList[htmlColor]; - retVal = XLColor.FromColor(thisColor); - } - else if (color.Indexed != null && color.Indexed < 64) - retVal = XLColor.FromIndex((Int32)color.Indexed.Value); - else if (color.Theme != null) - { - retVal = color.Tint != null ? XLColor.FromTheme((XLThemeColor)color.Theme.Value, color.Tint.Value) : XLColor.FromTheme((XLThemeColor)color.Theme.Value); - } - } - return retVal ?? XLColor.NoColor; - } - - private void ApplyStyle(IXLStylized xlStylized, Int32 styleIndex, Stylesheet s, Fills fills, Borders borders, - Fonts fonts, NumberingFormats numberingFormats) - { - if (s == null) return; //No Stylesheet, no Styles - - var cellFormat = (CellFormat)s.CellFormats.ElementAt(styleIndex); - - if (cellFormat.ApplyProtection != null) - { - var protection = cellFormat.Protection; - - if (protection == null) - xlStylized.InnerStyle.Protection = new XLProtection(null, DefaultStyle.Protection); - else - { - xlStylized.InnerStyle.Protection.Hidden = protection.Hidden != null && protection.Hidden.HasValue && - protection.Hidden.Value; - xlStylized.InnerStyle.Protection.Locked = protection.Locked == null || - (protection.Locked.HasValue && protection.Locked.Value); - } - } - - if (UInt32HasValue(cellFormat.FillId)) - { - var fill = (Fill)fills.ElementAt((Int32)cellFormat.FillId.Value); - if (fill.PatternFill != null) - { - if (fill.PatternFill.PatternType != null) - xlStylized.InnerStyle.Fill.PatternType = fill.PatternFill.PatternType.Value.ToClosedXml(); - - var fgColor = GetColor(fill.PatternFill.ForegroundColor); - if (fgColor.HasValue) xlStylized.InnerStyle.Fill.PatternColor = fgColor; - - var bgColor = GetColor(fill.PatternFill.BackgroundColor); - if (bgColor.HasValue) - xlStylized.InnerStyle.Fill.PatternBackgroundColor = bgColor; - } - } - - var alignment = cellFormat.Alignment; - if (alignment != null) - { - if (alignment.Horizontal != null) - xlStylized.InnerStyle.Alignment.Horizontal = alignment.Horizontal.Value.ToClosedXml(); - if (alignment.Indent != null && alignment.Indent != 0) - xlStylized.InnerStyle.Alignment.Indent = Int32.Parse(alignment.Indent.ToString()); - if (alignment.JustifyLastLine != null) - xlStylized.InnerStyle.Alignment.JustifyLastLine = alignment.JustifyLastLine; - if (alignment.ReadingOrder != null) - { - xlStylized.InnerStyle.Alignment.ReadingOrder = - (XLAlignmentReadingOrderValues)Int32.Parse(alignment.ReadingOrder.ToString()); - } - if (alignment.RelativeIndent != null) - xlStylized.InnerStyle.Alignment.RelativeIndent = alignment.RelativeIndent; - if (alignment.ShrinkToFit != null) - xlStylized.InnerStyle.Alignment.ShrinkToFit = alignment.ShrinkToFit; - if (alignment.TextRotation != null) - xlStylized.InnerStyle.Alignment.TextRotation = (Int32)alignment.TextRotation.Value; - if (alignment.Vertical != null) - xlStylized.InnerStyle.Alignment.Vertical = alignment.Vertical.Value.ToClosedXml(); - if (alignment.WrapText != null) - xlStylized.InnerStyle.Alignment.WrapText = alignment.WrapText; - } - - if (UInt32HasValue(cellFormat.BorderId)) - { - uint borderId = cellFormat.BorderId.Value; - var border = (Border)borders.ElementAt((Int32)borderId); - if (border != null) - { - var bottomBorder = border.BottomBorder; - if (bottomBorder != null) - { - if (bottomBorder.Style != null) - xlStylized.InnerStyle.Border.BottomBorder = bottomBorder.Style.Value.ToClosedXml(); - - var bottomBorderColor = GetColor(bottomBorder.Color); - if (bottomBorderColor.HasValue) - xlStylized.InnerStyle.Border.BottomBorderColor = bottomBorderColor; - } - var topBorder = border.TopBorder; - if (topBorder != null) - { - if (topBorder.Style != null) - xlStylized.InnerStyle.Border.TopBorder = topBorder.Style.Value.ToClosedXml(); - var topBorderColor = GetColor(topBorder.Color); - if (topBorderColor.HasValue) - xlStylized.InnerStyle.Border.TopBorderColor = topBorderColor; - } - var leftBorder = border.LeftBorder; - if (leftBorder != null) - { - if (leftBorder.Style != null) - xlStylized.InnerStyle.Border.LeftBorder = leftBorder.Style.Value.ToClosedXml(); - var leftBorderColor = GetColor(leftBorder.Color); - if (leftBorderColor.HasValue) - xlStylized.InnerStyle.Border.LeftBorderColor = leftBorderColor; - } - var rightBorder = border.RightBorder; - if (rightBorder != null) - { - if (rightBorder.Style != null) - xlStylized.InnerStyle.Border.RightBorder = rightBorder.Style.Value.ToClosedXml(); - var rightBorderColor = GetColor(rightBorder.Color); - if (rightBorderColor.HasValue) - xlStylized.InnerStyle.Border.RightBorderColor = rightBorderColor; - } - var diagonalBorder = border.DiagonalBorder; - if (diagonalBorder != null) - { - if (diagonalBorder.Style != null) - xlStylized.InnerStyle.Border.DiagonalBorder = diagonalBorder.Style.Value.ToClosedXml(); - var diagonalBorderColor = GetColor(diagonalBorder.Color); - if (diagonalBorderColor.HasValue) - xlStylized.InnerStyle.Border.DiagonalBorderColor = diagonalBorderColor; - if (border.DiagonalDown != null) - xlStylized.InnerStyle.Border.DiagonalDown = border.DiagonalDown; - if (border.DiagonalUp != null) - xlStylized.InnerStyle.Border.DiagonalUp = border.DiagonalUp; - } - } - } - - if (UInt32HasValue(cellFormat.FontId)) - { - var fontId = cellFormat.FontId; - var font = (DocumentFormat.OpenXml.Spreadsheet.Font)fonts.ElementAt((Int32)fontId.Value); - if (font != null) - { - xlStylized.InnerStyle.Font.Bold = GetBoolean(font.Bold); - - var fontColor = GetColor(font.Color); - if (fontColor.HasValue) - xlStylized.InnerStyle.Font.FontColor = fontColor; - - if (font.FontFamilyNumbering != null && (font.FontFamilyNumbering).Val != null) - { - xlStylized.InnerStyle.Font.FontFamilyNumbering = - (XLFontFamilyNumberingValues)Int32.Parse((font.FontFamilyNumbering).Val.ToString()); - } - if (font.FontName != null) - { - if ((font.FontName).Val != null) - xlStylized.InnerStyle.Font.FontName = (font.FontName).Val; - } - if (font.FontSize != null) - { - if ((font.FontSize).Val != null) - xlStylized.InnerStyle.Font.FontSize = (font.FontSize).Val; - } - - xlStylized.InnerStyle.Font.Italic = GetBoolean(font.Italic); - xlStylized.InnerStyle.Font.Shadow = GetBoolean(font.Shadow); - xlStylized.InnerStyle.Font.Strikethrough = GetBoolean(font.Strike); - - if (font.Underline != null) - { - xlStylized.InnerStyle.Font.Underline = font.Underline.Val != null - ? (font.Underline).Val.Value.ToClosedXml() - : XLFontUnderlineValues.Single; - } - - if (font.VerticalTextAlignment != null) - { - xlStylized.InnerStyle.Font.VerticalAlignment = font.VerticalTextAlignment.Val != null - ? (font.VerticalTextAlignment).Val.Value. - ToClosedXml() - : XLFontVerticalTextAlignmentValues.Baseline; - } - } - } - - if (!UInt32HasValue(cellFormat.NumberFormatId)) return; - - var numberFormatId = cellFormat.NumberFormatId; - - string formatCode = String.Empty; - if (numberingFormats != null) - { - var numberingFormat = - numberingFormats.FirstOrDefault( - nf => - ((NumberingFormat)nf).NumberFormatId != null && - ((NumberingFormat)nf).NumberFormatId.Value == numberFormatId) as NumberingFormat; - - if (numberingFormat != null && numberingFormat.FormatCode != null) - formatCode = numberingFormat.FormatCode.Value; - } - if (formatCode.Length > 0) - xlStylized.InnerStyle.NumberFormat.Format = formatCode; - else - xlStylized.InnerStyle.NumberFormat.NumberFormatId = (Int32)numberFormatId.Value; - } - - private static Boolean UInt32HasValue(UInt32Value value) - { - return value != null && value.HasValue; - } - - private static Boolean GetBoolean(BooleanPropertyType property) - { - if (property != null) - { - if (property.Val != null) - return property.Val; - return true; - } - - return false; - } - } +#region + +using ClosedXML.Utils; +using DocumentFormat.OpenXml; +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Spreadsheet; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml.Linq; +using Ap = DocumentFormat.OpenXml.ExtendedProperties; +using Op = DocumentFormat.OpenXml.CustomProperties; +using Xdr = DocumentFormat.OpenXml.Drawing.Spreadsheet; + +#endregion + +namespace ClosedXML.Excel +{ + #region + + using Ap; + using Drawings; + using Op; + using System.Drawing; + + #endregion + + public partial class XLWorkbook + { + private readonly Dictionary _colorList = new Dictionary(); + + private void Load(String file) + { + LoadSheets(file); + } + + private void Load(Stream stream) + { + LoadSheets(stream); + } + + private void LoadSheets(String fileName) + { + using (var dSpreadsheet = SpreadsheetDocument.Open(fileName, false)) + LoadSpreadsheetDocument(dSpreadsheet); + } + + private void LoadSheets(Stream stream) + { + using (var dSpreadsheet = SpreadsheetDocument.Open(stream, false)) + LoadSpreadsheetDocument(dSpreadsheet); + } + + private void LoadSpreadsheetDocument(SpreadsheetDocument dSpreadsheet) + { + ShapeIdManager = new XLIdManager(); + SetProperties(dSpreadsheet); + //var sharedStrings = dSpreadsheet.WorkbookPart.SharedStringTablePart.SharedStringTable.Elements(); + SharedStringItem[] sharedStrings = null; + if (dSpreadsheet.WorkbookPart.GetPartsOfType().Count() > 0) + { + var shareStringPart = dSpreadsheet.WorkbookPart.GetPartsOfType().First(); + sharedStrings = shareStringPart.SharedStringTable.Elements().ToArray(); + } + + if (dSpreadsheet.CustomFilePropertiesPart != null) + { + foreach (var m in dSpreadsheet.CustomFilePropertiesPart.Properties.Elements()) + { + String name = m.Name.Value; + if (m.VTLPWSTR != null) + CustomProperties.Add(name, m.VTLPWSTR.Text); + else if (m.VTFileTime != null) + { + CustomProperties.Add(name, + DateTime.ParseExact(m.VTFileTime.Text, "yyyy'-'MM'-'dd'T'HH':'mm':'ssK", + CultureInfo.InvariantCulture)); + } + else if (m.VTDouble != null) + CustomProperties.Add(name, Double.Parse(m.VTDouble.Text, CultureInfo.InvariantCulture)); + else if (m.VTBool != null) + CustomProperties.Add(name, m.VTBool.Text == "true"); + } + } + + var wbProps = dSpreadsheet.WorkbookPart.Workbook.WorkbookProperties; + Use1904DateSystem = wbProps != null && wbProps.Date1904 != null && wbProps.Date1904.Value; + + var wbProtection = dSpreadsheet.WorkbookPart.Workbook.WorkbookProtection; + if (wbProtection != null) + { + if (wbProtection.LockStructure != null) + LockStructure = wbProtection.LockStructure.Value; + if (wbProtection.LockWindows != null) + LockWindows = wbProtection.LockWindows.Value; + if (wbProtection.WorkbookPassword != null) + LockPassword = wbProtection.WorkbookPassword.Value; + } + + var calculationProperties = dSpreadsheet.WorkbookPart.Workbook.CalculationProperties; + if (calculationProperties != null) + { + var calculateMode = calculationProperties.CalculationMode; + if (calculateMode != null) + CalculateMode = calculateMode.Value.ToClosedXml(); + + var calculationOnSave = calculationProperties.CalculationOnSave; + if (calculationOnSave != null) + CalculationOnSave = calculationOnSave.Value; + + var forceFullCalculation = calculationProperties.ForceFullCalculation; + if (forceFullCalculation != null) + ForceFullCalculation = forceFullCalculation.Value; + + var fullCalculationOnLoad = calculationProperties.FullCalculationOnLoad; + if (fullCalculationOnLoad != null) + FullCalculationOnLoad = fullCalculationOnLoad.Value; + + var fullPrecision = calculationProperties.FullPrecision; + if (fullPrecision != null) + FullPrecision = fullPrecision.Value; + + var referenceMode = calculationProperties.ReferenceMode; + if (referenceMode != null) + ReferenceStyle = referenceMode.Value.ToClosedXml(); + } + + var efp = dSpreadsheet.ExtendedFilePropertiesPart; + if (efp != null && efp.Properties != null) + { + if (efp.Properties.Elements().Any()) + Properties.Company = efp.Properties.GetFirstChild().Text; + + if (efp.Properties.Elements().Any()) + Properties.Manager = efp.Properties.GetFirstChild().Text; + } + + Stylesheet s = null; + if (dSpreadsheet.WorkbookPart.WorkbookStylesPart != null && + dSpreadsheet.WorkbookPart.WorkbookStylesPart.Stylesheet != null) + { + s = dSpreadsheet.WorkbookPart.WorkbookStylesPart.Stylesheet; + } + + NumberingFormats numberingFormats = s == null ? null : s.NumberingFormats; + Fills fills = s == null ? null : s.Fills; + Borders borders = s == null ? null : s.Borders; + Fonts fonts = s == null ? null : s.Fonts; + Int32 dfCount = 0; + Dictionary differentialFormats; + if (s != null && s.DifferentialFormats != null) + differentialFormats = s.DifferentialFormats.Elements().ToDictionary(k => dfCount++); + else + differentialFormats = new Dictionary(); + + var sheets = dSpreadsheet.WorkbookPart.Workbook.Sheets; + Int32 position = 0; + foreach (Sheet dSheet in sheets.OfType()) + { + position++; + var sharedFormulasR1C1 = new Dictionary(); + + var wsPart = dSpreadsheet.WorkbookPart.GetPartById(dSheet.Id) as WorksheetPart; + + if (wsPart == null) + { + UnsupportedSheets.Add(new UnsupportedSheet { SheetId = dSheet.SheetId.Value, Position = position }); + continue; + } + + var sheetName = dSheet.Name; + + var ws = (XLWorksheet)WorksheetsInternal.Add(sheetName, position); + ws.RelId = dSheet.Id; + ws.SheetId = (Int32)dSheet.SheetId.Value; + + if (dSheet.State != null) + ws.Visibility = dSheet.State.Value.ToClosedXml(); + + var styleList = new Dictionary();// {{0, ws.Style}}; + PageSetupProperties pageSetupProperties = null; + + using (var reader = OpenXmlReader.Create(wsPart)) + { + Type[] ignoredElements = new Type[] + { + typeof(CustomSheetViews) // Custom sheet views contain its own auto filter data, and more, which should be ignored for now + }; + + while (reader.Read()) + { + while (ignoredElements.Contains(reader.ElementType)) + reader.ReadNextSibling(); + + if (reader.ElementType == typeof(SheetFormatProperties)) + { + var sheetFormatProperties = (SheetFormatProperties)reader.LoadCurrentElement(); + if (sheetFormatProperties != null) + { + if (sheetFormatProperties.DefaultRowHeight != null) + ws.RowHeight = sheetFormatProperties.DefaultRowHeight; + + ws.RowHeightChanged = (sheetFormatProperties.CustomHeight != null && + sheetFormatProperties.CustomHeight.Value); + + if (sheetFormatProperties.DefaultColumnWidth != null) + { + ws.ColumnWidth = sheetFormatProperties.DefaultColumnWidth; + } + } + } + else if (reader.ElementType == typeof(SheetViews)) + LoadSheetViews((SheetViews)reader.LoadCurrentElement(), ws); + else if (reader.ElementType == typeof(MergeCells)) + { + var mergedCells = (MergeCells)reader.LoadCurrentElement(); + if (mergedCells != null) + { + foreach (MergeCell mergeCell in mergedCells.Elements()) + ws.Range(mergeCell.Reference).Merge(false); + } + } + else if (reader.ElementType == typeof(Columns)) + LoadColumns(s, numberingFormats, fills, borders, fonts, ws, + (Columns)reader.LoadCurrentElement()); + else if (reader.ElementType == typeof(Row)) + { + lastRow = 0; + LoadRows(s, numberingFormats, fills, borders, fonts, ws, sharedStrings, sharedFormulasR1C1, + styleList, (Row)reader.LoadCurrentElement()); + } + else if (reader.ElementType == typeof(AutoFilter)) + LoadAutoFilter((AutoFilter)reader.LoadCurrentElement(), ws); + else if (reader.ElementType == typeof(SheetProtection)) + LoadSheetProtection((SheetProtection)reader.LoadCurrentElement(), ws); + else if (reader.ElementType == typeof(DataValidations)) + LoadDataValidations((DataValidations)reader.LoadCurrentElement(), ws); + else if (reader.ElementType == typeof(ConditionalFormatting)) + LoadConditionalFormatting((ConditionalFormatting)reader.LoadCurrentElement(), ws, differentialFormats); + else if (reader.ElementType == typeof(Hyperlinks)) + LoadHyperlinks((Hyperlinks)reader.LoadCurrentElement(), wsPart, ws); + else if (reader.ElementType == typeof(PrintOptions)) + LoadPrintOptions((PrintOptions)reader.LoadCurrentElement(), ws); + else if (reader.ElementType == typeof(PageMargins)) + LoadPageMargins((PageMargins)reader.LoadCurrentElement(), ws); + else if (reader.ElementType == typeof(PageSetup)) + LoadPageSetup((PageSetup)reader.LoadCurrentElement(), ws, pageSetupProperties); + else if (reader.ElementType == typeof(HeaderFooter)) + LoadHeaderFooter((HeaderFooter)reader.LoadCurrentElement(), ws); + else if (reader.ElementType == typeof(SheetProperties)) + LoadSheetProperties((SheetProperties)reader.LoadCurrentElement(), ws, out pageSetupProperties); + else if (reader.ElementType == typeof(RowBreaks)) + LoadRowBreaks((RowBreaks)reader.LoadCurrentElement(), ws); + else if (reader.ElementType == typeof(ColumnBreaks)) + LoadColumnBreaks((ColumnBreaks)reader.LoadCurrentElement(), ws); + else if (reader.ElementType == typeof(LegacyDrawing)) + ws.LegacyDrawingId = (reader.LoadCurrentElement() as LegacyDrawing).Id.Value; + } + reader.Close(); + } + + #region LoadTables + + foreach (TableDefinitionPart tablePart in wsPart.TableDefinitionParts) + { + var dTable = tablePart.Table; + string reference = dTable.Reference.Value; + XLTable xlTable = ws.Range(reference).CreateTable(dTable.Name, false) as XLTable; + if (dTable.HeaderRowCount != null && dTable.HeaderRowCount == 0) + { + xlTable._showHeaderRow = false; + //foreach (var tableColumn in dTable.TableColumns.Cast()) + xlTable.AddFields(dTable.TableColumns.Cast().Select(t => GetTableColumnName(t.Name.Value))); + } + else + { + xlTable.InitializeAutoFilter(); + } + + if (dTable.TotalsRowCount != null && dTable.TotalsRowCount.Value > 0) + ((XLTable)xlTable)._showTotalsRow = true; + + if (dTable.TableStyleInfo != null) + { + if (dTable.TableStyleInfo.ShowFirstColumn != null) + xlTable.EmphasizeFirstColumn = dTable.TableStyleInfo.ShowFirstColumn.Value; + if (dTable.TableStyleInfo.ShowLastColumn != null) + xlTable.EmphasizeLastColumn = dTable.TableStyleInfo.ShowLastColumn.Value; + if (dTable.TableStyleInfo.ShowRowStripes != null) + xlTable.ShowRowStripes = dTable.TableStyleInfo.ShowRowStripes.Value; + if (dTable.TableStyleInfo.ShowColumnStripes != null) + xlTable.ShowColumnStripes = dTable.TableStyleInfo.ShowColumnStripes.Value; + if (dTable.TableStyleInfo.Name != null) + { + var theme = XLTableTheme.FromName(dTable.TableStyleInfo.Name.Value); + if (theme != null) + xlTable.Theme = theme; + else + xlTable.Theme = new XLTableTheme(dTable.TableStyleInfo.Name.Value); + } + else + xlTable.Theme = XLTableTheme.None; + } + + if (dTable.AutoFilter != null) + { + xlTable.ShowAutoFilter = true; + LoadAutoFilterColumns(dTable.AutoFilter, (xlTable as XLTable).AutoFilter); + } + else + xlTable.ShowAutoFilter = false; + + if (xlTable.ShowTotalsRow) + { + foreach (var tableColumn in dTable.TableColumns.Cast()) + { + var tableColumnName = GetTableColumnName(tableColumn.Name.Value); + if (tableColumn.TotalsRowFunction != null) + xlTable.Field(tableColumnName).TotalsRowFunction = + tableColumn.TotalsRowFunction.Value.ToClosedXml(); + + if (tableColumn.TotalsRowFormula != null) + xlTable.Field(tableColumnName).TotalsRowFormulaA1 = + tableColumn.TotalsRowFormula.Text; + + if (tableColumn.TotalsRowLabel != null) + xlTable.Field(tableColumnName).TotalsRowLabel = tableColumn.TotalsRowLabel.Value; + } + if (xlTable.AutoFilter != null) + xlTable.AutoFilter.Range = xlTable.Worksheet.Range( + xlTable.RangeAddress.FirstAddress.RowNumber, xlTable.RangeAddress.FirstAddress.ColumnNumber, + xlTable.RangeAddress.LastAddress.RowNumber - 1, xlTable.RangeAddress.LastAddress.ColumnNumber); + } + else if (xlTable.AutoFilter != null) + xlTable.AutoFilter.Range = xlTable.Worksheet.Range(xlTable.RangeAddress); + } + + #endregion + + LoadDrawings(wsPart, ws); + + #region LoadComments + + if (wsPart.WorksheetCommentsPart != null) + { + var root = wsPart.WorksheetCommentsPart.Comments; + var authors = root.GetFirstChild().ChildElements; + var comments = root.GetFirstChild().ChildElements; + + // **** MAYBE FUTURE SHAPE SIZE SUPPORT + XDocument xdoc = GetCommentVmlFile(wsPart); + + foreach (Comment c in comments) + { + // find cell by reference + var cell = ws.Cell(c.Reference); + + XLComment xlComment = cell.Comment as XLComment; + xlComment.Author = authors[(int)c.AuthorId.Value].InnerText; + //xlComment.ShapeId = (Int32)c.ShapeId.Value; + //ShapeIdManager.Add(xlComment.ShapeId); + + var runs = c.GetFirstChild().Elements(); + foreach (Run run in runs) + { + var runProperties = run.RunProperties; + String text = run.Text.InnerText.FixNewLines(); + var rt = cell.Comment.AddText(text); + LoadFont(runProperties, rt); + } + + XElement shape = GetCommentShape(xdoc); + + LoadShapeProperties(xlComment, shape); + + var clientData = shape.Elements().First(e => e.Name.LocalName == "ClientData"); + LoadClientData(xlComment, clientData); + + var textBox = shape.Elements().First(e => e.Name.LocalName == "textbox"); + LoadTextBox(xlComment, textBox); + + var alt = shape.Attribute("alt"); + if (alt != null) xlComment.Style.Web.SetAlternateText(alt.Value); + + LoadColorsAndLines(xlComment, shape); + + //var insetmode = (string)shape.Attributes().First(a=> a.Name.LocalName == "insetmode"); + //xlComment.Style.Margins.Automatic = insetmode != null && insetmode.Equals("auto"); + + shape.Remove(); + } + } + + #endregion + } + + var workbook = dSpreadsheet.WorkbookPart.Workbook; + + var bookViews = workbook.BookViews; + if (bookViews != null && bookViews.Any()) + { + var workbookView = bookViews.First() as WorkbookView; + if (workbookView != null && workbookView.ActiveTab != null) + { + UnsupportedSheet unsupportedSheet = + UnsupportedSheets.FirstOrDefault(us => us.Position == (Int32)(workbookView.ActiveTab.Value + 1)); + if (unsupportedSheet != null) + unsupportedSheet.IsActive = true; + else + { + Worksheet((Int32)(workbookView.ActiveTab.Value + 1)).SetTabActive(); + } + } + } + LoadDefinedNames(workbook); + + #region Pivot tables + + // Delay loading of pivot tables until all sheets have been loaded + foreach (Sheet dSheet in sheets.OfType()) + { + var wsPart = dSpreadsheet.WorkbookPart.GetPartById(dSheet.Id) as WorksheetPart; + + if (wsPart != null) + { + var ws = (XLWorksheet)WorksheetsInternal.Worksheet(dSheet.Name); + + foreach (var pivotTablePart in wsPart.PivotTableParts) + { + var pivotTableCacheDefinitionPart = pivotTablePart.PivotTableCacheDefinitionPart; + var pivotTableDefinition = pivotTablePart.PivotTableDefinition; + + var target = ws.FirstCell(); + if (pivotTableDefinition.Location != null && pivotTableDefinition.Location.Reference != null && pivotTableDefinition.Location.Reference.HasValue) + { + target = ws.Range(pivotTableDefinition.Location.Reference.Value).FirstCell(); + } + + IXLRange source = null; + if (pivotTableCacheDefinitionPart.PivotCacheDefinition != null + && pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheSource != null + && pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheSource.WorksheetSource != null) + { + // TODO: Implement other sources besides worksheetSource (e.g. Table source?) + // But for now assume names and references point directly to a range + var wss = pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheSource.WorksheetSource; + string rangeAddress = string.Empty; + if (wss.Name != null) + rangeAddress = wss.Name.Value; + else + { + var sourceSheet = wss.Sheet == null ? ws : this.Worksheet(wss.Sheet.Value); + rangeAddress = sourceSheet.Range(wss.Reference.Value).RangeAddress.ToStringRelative(true); + } + + source = this.Range(rangeAddress); + if (source == null) + continue; + } + + if (target != null && source != null) + { + var pt = ws.PivotTables.AddNew(pivotTableDefinition.Name, target, source) as XLPivotTable; + pt.RelId = wsPart.GetIdOfPart(pivotTablePart); + pt.CacheDefinitionRelId = pivotTablePart.GetIdOfPart(pivotTableCacheDefinitionPart); + pt.WorkbookCacheRelId = dSpreadsheet.WorkbookPart.GetIdOfPart(pivotTableCacheDefinitionPart); + + if (pivotTableDefinition.MergeItem != null) pt.MergeAndCenterWithLabels = pivotTableDefinition.MergeItem.Value; + if (pivotTableDefinition.Indent != null) pt.RowLabelIndent = (int)pivotTableDefinition.Indent.Value; + if (pivotTableDefinition.PageOverThenDown != null) pt.FilterAreaOrder = pivotTableDefinition.PageOverThenDown.Value ? XLFilterAreaOrder.OverThenDown : XLFilterAreaOrder.DownThenOver; + if (pivotTableDefinition.PageWrap != null) pt.FilterFieldsPageWrap = (int)pivotTableDefinition.PageWrap.Value; + if (pivotTableDefinition.UseAutoFormatting != null) pt.AutofitColumns = pivotTableDefinition.UseAutoFormatting.Value; + if (pivotTableDefinition.PreserveFormatting != null) pt.PreserveCellFormatting = pivotTableDefinition.PreserveFormatting.Value; + if (pivotTableDefinition.RowGrandTotals != null) pt.ShowGrandTotalsRows = pivotTableDefinition.RowGrandTotals.Value; + if (pivotTableDefinition.ColumnGrandTotals != null) pt.ShowGrandTotalsColumns = pivotTableDefinition.ColumnGrandTotals.Value; + if (pivotTableDefinition.SubtotalHiddenItems != null) pt.FilteredItemsInSubtotals = pivotTableDefinition.SubtotalHiddenItems.Value; + if (pivotTableDefinition.MultipleFieldFilters != null) pt.AllowMultipleFilters = pivotTableDefinition.MultipleFieldFilters.Value; + if (pivotTableDefinition.CustomListSort != null) pt.UseCustomListsForSorting = pivotTableDefinition.CustomListSort.Value; + if (pivotTableDefinition.ShowDrill != null) pt.ShowExpandCollapseButtons = pivotTableDefinition.ShowDrill.Value; + if (pivotTableDefinition.ShowDataTips != null) pt.ShowContextualTooltips = pivotTableDefinition.ShowDataTips.Value; + if (pivotTableDefinition.ShowMemberPropertyTips != null) pt.ShowPropertiesInTooltips = pivotTableDefinition.ShowMemberPropertyTips.Value; + if (pivotTableDefinition.ShowHeaders != null) pt.DisplayCaptionsAndDropdowns = pivotTableDefinition.ShowHeaders.Value; + if (pivotTableDefinition.GridDropZones != null) pt.ClassicPivotTableLayout = pivotTableDefinition.GridDropZones.Value; + if (pivotTableDefinition.ShowEmptyRow != null) pt.ShowEmptyItemsOnRows = pivotTableDefinition.ShowEmptyRow.Value; + if (pivotTableDefinition.ShowEmptyColumn != null) pt.ShowEmptyItemsOnColumns = pivotTableDefinition.ShowEmptyColumn.Value; + if (pivotTableDefinition.ShowItems != null) pt.DisplayItemLabels = pivotTableDefinition.ShowItems.Value; + if (pivotTableDefinition.FieldListSortAscending != null) pt.SortFieldsAtoZ = pivotTableDefinition.FieldListSortAscending.Value; + if (pivotTableDefinition.PrintDrill != null) pt.PrintExpandCollapsedButtons = pivotTableDefinition.PrintDrill.Value; + if (pivotTableDefinition.ItemPrintTitles != null) pt.RepeatRowLabels = pivotTableDefinition.ItemPrintTitles.Value; + if (pivotTableDefinition.FieldPrintTitles != null) pt.PrintTitles = pivotTableDefinition.FieldPrintTitles.Value; + if (pivotTableDefinition.EnableDrill != null) pt.EnableShowDetails = pivotTableDefinition.EnableDrill.Value; + + if (pivotTableDefinition.ShowMissing != null && pivotTableDefinition.MissingCaption != null) + pt.EmptyCellReplacement = pivotTableDefinition.MissingCaption.Value; + + if (pivotTableDefinition.ShowError != null && pivotTableDefinition.ErrorCaption != null) + pt.ErrorValueReplacement = pivotTableDefinition.ErrorCaption.Value; + + // Row labels + if (pivotTableDefinition.RowFields != null) + { + foreach (var rf in pivotTableDefinition.RowFields.Cast()) + { + if (rf.Index < pivotTableDefinition.PivotFields.Count) + { + IXLPivotField pivotField = null; + if (rf.Index.Value == -2) + pivotField = pt.RowLabels.Add(XLConstants.PivotTableValuesSentinalLabel); + else + { + var pf = pivotTableDefinition.PivotFields.ElementAt(rf.Index.Value) as PivotField; + if (pf == null) + continue; + + var cacheField = pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheFields.ElementAt(rf.Index.Value) as CacheField; + if (pf.Name != null) + pivotField = pt.RowLabels.Add(pf.Name.Value); + else if (cacheField.Name != null) + pivotField = pt.RowLabels.Add(cacheField.Name.Value); + else + continue; + + if (pivotField != null) + { + var items = pf.Items.OfType().Where(i => i.Index != null && i.Index.HasValue); + if (!items.Any(i => i.HideDetails == null || BooleanValue.ToBoolean(i.HideDetails))) + pivotField.SetCollapsed(); + } + } + } + } + } + + // Column labels + if (pivotTableDefinition.ColumnFields != null) + { + foreach (var cf in pivotTableDefinition.ColumnFields.Cast()) + { + IXLPivotField pivotField = null; + if (cf.Index.Value == -2) + pivotField = pt.ColumnLabels.Add(XLConstants.PivotTableValuesSentinalLabel); + else if (cf.Index < pivotTableDefinition.PivotFields.Count) + { + var pf = pivotTableDefinition.PivotFields.ElementAt(cf.Index.Value) as PivotField; + if (pf == null) + continue; + + var cacheField = pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheFields.ElementAt(cf.Index.Value) as CacheField; + if (pf.Name != null) + pivotField = pt.ColumnLabels.Add(pf.Name.Value); + else if (cacheField.Name != null) + pivotField = pt.ColumnLabels.Add(cacheField.Name.Value); + else + continue; + + if (pivotField != null) + { + var items = pf.Items.OfType().Where(i => i.Index != null && i.Index.HasValue); + if (!items.Any(i => i.HideDetails == null || BooleanValue.ToBoolean(i.HideDetails))) + pivotField.SetCollapsed(); + } + } + } + } + + // Values + if (pivotTableDefinition.DataFields != null) + { + foreach (var df in pivotTableDefinition.DataFields.Cast()) + { + IXLPivotValue pivotValue = null; + if ((int)df.Field.Value == -2) + pivotValue = pt.Values.Add(XLConstants.PivotTableValuesSentinalLabel); + else if (df.Field.Value < pivotTableDefinition.PivotFields.Count) + { + var pf = pivotTableDefinition.PivotFields.ElementAt((int)df.Field.Value) as PivotField; + if (pf == null) + continue; + + var cacheField = pivotTableCacheDefinitionPart.PivotCacheDefinition.CacheFields.ElementAt((int)df.Field.Value) as CacheField; + + if (pf.Name != null) + pivotValue = pt.Values.Add(pf.Name.Value, df.Name.Value); + else if (cacheField.Name != null) + pivotValue = pt.Values.Add(cacheField.Name.Value, df.Name.Value); + else + continue; + + if (df.NumberFormatId != null) pivotValue.NumberFormat.SetNumberFormatId((int)df.NumberFormatId.Value); + if (df.Subtotal != null) pivotValue = pivotValue.SetSummaryFormula(df.Subtotal.Value.ToClosedXml()); + if (df.ShowDataAs != null) + { + var calculation = pivotValue.Calculation; + calculation = df.ShowDataAs.Value.ToClosedXml(); + pivotValue = pivotValue.SetCalculation(calculation); + } + + if (df.BaseField != null) + { + var col = pt.SourceRange.Column(df.BaseField.Value + 1); + + var items = col.CellsUsed() + .Select(c => c.Value) + .Skip(1) // Skip header column + .Distinct().ToList(); + + pivotValue.BaseField = col.FirstCell().GetValue(); + if (df.BaseItem != null) pivotValue.BaseItem = items[(int)df.BaseItem.Value].ToString(); + } + } + } + } + } + } + } + } + + #endregion + } + + private void LoadDrawings(WorksheetPart wsPart, IXLWorksheet ws) + { + if (wsPart.DrawingsPart != null) + { + var drawingsPart = wsPart.DrawingsPart; + + foreach (var anchor in drawingsPart.WorksheetDrawing.ChildElements) + { + var imgId = GetImageRelIdFromAnchor(anchor); + + //If imgId is null, we're probably dealing with a TextBox (or another shape) instead of a picture + if (imgId == null) continue; + + var imagePart = drawingsPart.GetPartById(imgId); + using (var stream = imagePart.GetStream()) + { + var vsdp = GetPropertiesFromAnchor(anchor); + + var picture = ws.AddPicture(stream, vsdp.Name) as XLPicture; + picture.RelId = imgId; + + Xdr.ShapeProperties spPr = anchor.Descendants().First(); + picture.Placement = XLPicturePlacement.FreeFloating; + picture.Width = ConvertFromEnglishMetricUnits(spPr.Transform2D.Extents.Cx, GraphicsUtils.Graphics.DpiX); + picture.Height = ConvertFromEnglishMetricUnits(spPr.Transform2D.Extents.Cy, GraphicsUtils.Graphics.DpiY); + + if (anchor is Xdr.AbsoluteAnchor) + { + var absoluteAnchor = anchor as Xdr.AbsoluteAnchor; + picture.MoveTo( + ConvertFromEnglishMetricUnits(absoluteAnchor.Position.X.Value, GraphicsUtils.Graphics.DpiX), + ConvertFromEnglishMetricUnits(absoluteAnchor.Position.Y.Value, GraphicsUtils.Graphics.DpiY) + ); + } + else if (anchor is Xdr.OneCellAnchor) + { + var oneCellAnchor = anchor as Xdr.OneCellAnchor; + var from = LoadMarker(ws, oneCellAnchor.FromMarker); + picture.MoveTo(from.Address, from.Offset); + } + else if (anchor is Xdr.TwoCellAnchor) + { + var twoCellAnchor = anchor as Xdr.TwoCellAnchor; + var from = LoadMarker(ws, twoCellAnchor.FromMarker); + var to = LoadMarker(ws, twoCellAnchor.ToMarker); + + if (twoCellAnchor.EditAs == null || !twoCellAnchor.EditAs.HasValue || twoCellAnchor.EditAs.Value == Xdr.EditAsValues.TwoCell) + { + picture.MoveTo(from.Address, from.Offset, to.Address, to.Offset); + } + else if (twoCellAnchor.EditAs.Value == Xdr.EditAsValues.Absolute) + { + var shapeProperties = twoCellAnchor.Descendants().FirstOrDefault(); + if (shapeProperties != null) + { + picture.MoveTo( + ConvertFromEnglishMetricUnits(spPr.Transform2D.Offset.X, GraphicsUtils.Graphics.DpiX), + ConvertFromEnglishMetricUnits(spPr.Transform2D.Offset.Y, GraphicsUtils.Graphics.DpiY) + ); + } + } + else if (twoCellAnchor.EditAs.Value == Xdr.EditAsValues.OneCell) + { + picture.MoveTo(from.Address, from.Offset); + } + } + } + } + } + } + + private static Int32 ConvertFromEnglishMetricUnits(long emu, float resolution) + { + return Convert.ToInt32(emu * resolution / 914400); + } + + private static IXLMarker LoadMarker(IXLWorksheet ws, Xdr.MarkerType marker) + { + return new XLMarker( + ws.Cell(Convert.ToInt32(marker.RowId.InnerText) + 1, Convert.ToInt32(marker.ColumnId.InnerText) + 1).Address, + new Point( + ConvertFromEnglishMetricUnits(Convert.ToInt32(marker.ColumnOffset.InnerText), GraphicsUtils.Graphics.DpiX), + ConvertFromEnglishMetricUnits(Convert.ToInt32(marker.RowOffset.InnerText), GraphicsUtils.Graphics.DpiY) + ) + ); + } + + #region Comment Helpers + + private XDocument GetCommentVmlFile(WorksheetPart wsPart) + { + XDocument xdoc = null; + + foreach (var vmlPart in wsPart.VmlDrawingParts) + { + xdoc = XDocumentExtensions.Load(vmlPart.GetStream(FileMode.Open)); + + //Probe for comments + if (xdoc.Root == null) continue; + var shape = GetCommentShape(xdoc); + if (shape != null) break; + } + + if (xdoc == null) throw new Exception("Could not load comments file"); + return xdoc; + } + + private static XElement GetCommentShape(XDocument xdoc) + { + var xml = xdoc.Root.Element("xml"); + + XElement shape; + if (xml != null) + shape = + xml.Elements().FirstOrDefault(e => (string)e.Attribute("type") == XLConstants.Comment.ShapeTypeId); + else + shape = xdoc.Root.Elements().FirstOrDefault(e => + (string)e.Attribute("type") == + XLConstants.Comment.ShapeTypeId || + (string)e.Attribute("type") == + XLConstants.Comment.AlternateShapeTypeId); + return shape; + } + + #endregion + + private String GetTableColumnName(string name) + { + return name.Replace("_x000a_", Environment.NewLine).Replace("_x005f_x000a_", "_x000a_"); + } + + // This may be part of XLHelper or XLColor + // Leaving it here for now. Can't decide what to call it and where to put it. + private XLColor ExtractColor(String color) + { + if (color.IndexOf("[") >= 0) + { + int start = color.IndexOf("[") + 1; + int end = color.IndexOf("]", start); + return XLColor.FromIndex(Int32.Parse(color.Substring(start, end - start))); + } + else + { + return XLColor.FromHtml(color); + } + } + + private void LoadColorsAndLines(IXLDrawing drawing, XElement shape) + { + var strokeColor = shape.Attribute("strokecolor"); + if (strokeColor != null) drawing.Style.ColorsAndLines.LineColor = ExtractColor(strokeColor.Value); + + var strokeWeight = shape.Attribute("strokeweight"); + if (strokeWeight != null) + drawing.Style.ColorsAndLines.LineWeight = GetPtValue(strokeWeight.Value); + + var fillColor = shape.Attribute("fillcolor"); + if (fillColor != null && !fillColor.Value.ToLower().Contains("infobackground")) drawing.Style.ColorsAndLines.FillColor = ExtractColor(fillColor.Value); + + var fill = shape.Elements().FirstOrDefault(e => e.Name.LocalName == "fill"); + if (fill != null) + { + var opacity = fill.Attribute("opacity"); + if (opacity != null) + { + String opacityVal = opacity.Value; + if (opacityVal.EndsWith("f")) + drawing.Style.ColorsAndLines.FillTransparency = + Double.Parse(opacityVal.Substring(0, opacityVal.Length - 1), CultureInfo.InvariantCulture) / 65536.0; + else + drawing.Style.ColorsAndLines.FillTransparency = Double.Parse(opacityVal, CultureInfo.InvariantCulture); + } + } + + var stroke = shape.Elements().FirstOrDefault(e => e.Name.LocalName == "stroke"); + if (stroke != null) + { + var opacity = stroke.Attribute("opacity"); + if (opacity != null) + { + String opacityVal = opacity.Value; + if (opacityVal.EndsWith("f")) + drawing.Style.ColorsAndLines.LineTransparency = + Double.Parse(opacityVal.Substring(0, opacityVal.Length - 1), CultureInfo.InvariantCulture) / 65536.0; + else + drawing.Style.ColorsAndLines.LineTransparency = Double.Parse(opacityVal, CultureInfo.InvariantCulture); + } + + var dashStyle = stroke.Attribute("dashstyle"); + if (dashStyle != null) + { + String dashStyleVal = dashStyle.Value.ToLower(); + if (dashStyleVal == "1 1" || dashStyleVal == "shortdot") + { + var endCap = stroke.Attribute("endcap"); + if (endCap != null && endCap.Value == "round") + drawing.Style.ColorsAndLines.LineDash = XLDashStyle.RoundDot; + else + drawing.Style.ColorsAndLines.LineDash = XLDashStyle.SquareDot; + } + else + { + switch (dashStyleVal) + { + case "dash": drawing.Style.ColorsAndLines.LineDash = XLDashStyle.Dash; break; + case "dashdot": drawing.Style.ColorsAndLines.LineDash = XLDashStyle.DashDot; break; + case "longdash": drawing.Style.ColorsAndLines.LineDash = XLDashStyle.LongDash; break; + case "longdashdot": drawing.Style.ColorsAndLines.LineDash = XLDashStyle.LongDashDot; break; + case "longdashdotdot": drawing.Style.ColorsAndLines.LineDash = XLDashStyle.LongDashDotDot; break; + } + } + } + + var lineStyle = stroke.Attribute("linestyle"); + if (lineStyle != null) + { + String lineStyleVal = lineStyle.Value.ToLower(); + switch (lineStyleVal) + { + case "single": drawing.Style.ColorsAndLines.LineStyle = XLLineStyle.Single; break; + case "thickbetweenthin": drawing.Style.ColorsAndLines.LineStyle = XLLineStyle.ThickBetweenThin; break; + case "thickthin": drawing.Style.ColorsAndLines.LineStyle = XLLineStyle.ThickThin; break; + case "thinthick": drawing.Style.ColorsAndLines.LineStyle = XLLineStyle.ThinThick; break; + case "thinthin": drawing.Style.ColorsAndLines.LineStyle = XLLineStyle.ThinThin; break; + } + } + } + } + + private void LoadTextBox(IXLDrawing xlDrawing, XElement textBox) + { + var attStyle = textBox.Attribute("style"); + if (attStyle != null) LoadTextBoxStyle(xlDrawing, attStyle); + + var attInset = textBox.Attribute("inset"); + if (attInset != null) LoadTextBoxInset(xlDrawing, attInset); + } + + private void LoadTextBoxInset(IXLDrawing xlDrawing, XAttribute attInset) + { + var split = attInset.Value.Split(','); + xlDrawing.Style.Margins.Left = GetInsetValue(split[0]); + xlDrawing.Style.Margins.Top = GetInsetValue(split[1]); + xlDrawing.Style.Margins.Right = GetInsetValue(split[2]); + xlDrawing.Style.Margins.Bottom = GetInsetValue(split[3]); + } + + private double GetInsetValue(string value) + { + String v = value.Trim(); + if (v.EndsWith("pt")) + return Double.Parse(v.Substring(0, v.Length - 2), CultureInfo.InvariantCulture) / 72.0; + else + return Double.Parse(v.Substring(0, v.Length - 2), CultureInfo.InvariantCulture); + } + + private static void LoadTextBoxStyle(IXLDrawing xlDrawing, XAttribute attStyle) + { + var style = attStyle.Value; + var attributes = style.Split(';'); + foreach (String pair in attributes) + { + var split = pair.Split(':'); + if (split.Length != 2) continue; + + var attribute = split[0].Trim().ToLower(); + var value = split[1].Trim(); + Boolean isVertical = false; + switch (attribute) + { + case "mso-fit-shape-to-text": xlDrawing.Style.Size.SetAutomaticSize(value.Equals("t")); break; + case "mso-layout-flow-alt": + if (value.Equals("bottom-to-top")) xlDrawing.Style.Alignment.SetOrientation(XLDrawingTextOrientation.BottomToTop); + else if (value.Equals("top-to-bottom")) xlDrawing.Style.Alignment.SetOrientation(XLDrawingTextOrientation.Vertical); + break; + + case "layout-flow": isVertical = value.Equals("vertical"); break; + case "mso-direction-alt": if (value == "auto") xlDrawing.Style.Alignment.Direction = XLDrawingTextDirection.Context; break; + case "direction": if (value == "RTL") xlDrawing.Style.Alignment.Direction = XLDrawingTextDirection.RightToLeft; break; + } + if (isVertical && xlDrawing.Style.Alignment.Orientation == XLDrawingTextOrientation.LeftToRight) + xlDrawing.Style.Alignment.Orientation = XLDrawingTextOrientation.TopToBottom; + } + } + + private void LoadClientData(IXLDrawing drawing, XElement clientData) + { + var anchor = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "Anchor"); + if (anchor != null) LoadClientDataAnchor(drawing, anchor); + + LoadDrawingPositioning(drawing, clientData); + LoadDrawingProtection(drawing, clientData); + + var visible = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "Visible"); + drawing.Visible = visible != null && visible.Value.ToLower().StartsWith("t"); + + LoadDrawingHAlignment(drawing, clientData); + LoadDrawingVAlignment(drawing, clientData); + } + + private void LoadDrawingHAlignment(IXLDrawing drawing, XElement clientData) + { + var textHAlign = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "TextHAlign"); + if (textHAlign != null) + drawing.Style.Alignment.Horizontal = (XLDrawingHorizontalAlignment)Enum.Parse(typeof(XLDrawingHorizontalAlignment), textHAlign.Value.ToProper()); + } + + private void LoadDrawingVAlignment(IXLDrawing drawing, XElement clientData) + { + var textVAlign = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "TextVAlign"); + if (textVAlign != null) + drawing.Style.Alignment.Vertical = (XLDrawingVerticalAlignment)Enum.Parse(typeof(XLDrawingVerticalAlignment), textVAlign.Value.ToProper()); + } + + private void LoadDrawingProtection(IXLDrawing drawing, XElement clientData) + { + var lockedElement = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "Locked"); + var lockTextElement = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "LockText"); + Boolean locked = lockedElement != null && lockedElement.Value.ToLower() == "true"; + Boolean lockText = lockTextElement != null && lockTextElement.Value.ToLower() == "true"; + drawing.Style.Protection.Locked = locked; + drawing.Style.Protection.LockText = lockText; + } + + private static void LoadDrawingPositioning(IXLDrawing drawing, XElement clientData) + { + var moveWithCellsElement = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "MoveWithCells"); + var sizeWithCellsElement = clientData.Elements().FirstOrDefault(e => e.Name.LocalName == "SizeWithCells"); + Boolean moveWithCells = !(moveWithCellsElement != null && moveWithCellsElement.Value.ToLower() == "true"); + Boolean sizeWithCells = !(sizeWithCellsElement != null && sizeWithCellsElement.Value.ToLower() == "true"); + if (moveWithCells && !sizeWithCells) + drawing.Style.Properties.Positioning = XLDrawingAnchor.MoveWithCells; + else if (moveWithCells && sizeWithCells) + drawing.Style.Properties.Positioning = XLDrawingAnchor.MoveAndSizeWithCells; + else + drawing.Style.Properties.Positioning = XLDrawingAnchor.Absolute; + } + + private static void LoadClientDataAnchor(IXLDrawing drawing, XElement anchor) + { + var location = anchor.Value.Split(','); + drawing.Position.Column = int.Parse(location[0]) + 1; + drawing.Position.ColumnOffset = Double.Parse(location[1], CultureInfo.InvariantCulture) / 7.2; + drawing.Position.Row = int.Parse(location[2]) + 1; + drawing.Position.RowOffset = Double.Parse(location[3], CultureInfo.InvariantCulture); + } + + private void LoadShapeProperties(IXLDrawing xlDrawing, XElement shape) + { + var attStyle = shape.Attribute("style"); + if (attStyle == null) return; + + var style = attStyle.Value; + var attributes = style.Split(';'); + foreach (String pair in attributes) + { + var split = pair.Split(':'); + if (split.Length != 2) continue; + + var attribute = split[0].Trim().ToLower(); + var value = split[1].Trim(); + + switch (attribute) + { + case "visibility": xlDrawing.Visible = value.ToLower().Equals("visible"); break; + case "width": xlDrawing.Style.Size.Width = GetPtValue(value) / 7.5; break; + case "height": xlDrawing.Style.Size.Height = GetPtValue(value); break; + case "z-index": xlDrawing.ZOrder = Int32.Parse(value); break; + } + } + } + + private readonly Dictionary knownUnits = new Dictionary + { + {"pt", 1.0}, + {"in", 72.0}, + {"mm", 72.0/25.4} + }; + + private double GetPtValue(string value) + { + var knownUnit = knownUnits.FirstOrDefault(ku => value.Contains(ku.Key)); + + if (knownUnit.Key == null) + return Double.Parse(value); + + return Double.Parse(value.Replace(knownUnit.Key, String.Empty), CultureInfo.InvariantCulture) * knownUnit.Value; + } + + private void LoadDefinedNames(Workbook workbook) + { + if (workbook.DefinedNames == null) return; + + foreach (var definedName in workbook.DefinedNames.OfType()) + { + var name = definedName.Name; + var visible = true; + if (definedName.Hidden != null) visible = !BooleanValue.ToBoolean(definedName.Hidden); + if (name == "_xlnm.Print_Area") + { + var fixedNames = validateDefinedNames(definedName.Text.Split(',')); + foreach (string area in fixedNames) + { + if (area.Contains("[")) + { + var ws = Worksheets.FirstOrDefault(w => (w as XLWorksheet).SheetId == definedName.LocalSheetId + 1); + if (ws != null) + { + ws.PageSetup.PrintAreas.Add(area); + } + } + else + { + string sheetName, sheetArea; + ParseReference(area, out sheetName, out sheetArea); + if (!(sheetArea.Equals("#REF") || sheetArea.EndsWith("#REF!") || sheetArea.Length == 0)) + WorksheetsInternal.Worksheet(sheetName).PageSetup.PrintAreas.Add(sheetArea); + } + } + } + else if (name == "_xlnm.Print_Titles") + { + LoadPrintTitles(definedName); + } + else + { + string text = definedName.Text; + + if (!(text.Equals("#REF") || text.EndsWith("#REF!"))) + { + var localSheetId = definedName.LocalSheetId; + var comment = definedName.Comment; + if (localSheetId == null) + { + if (!NamedRanges.Any(nr => nr.Name == name)) + (NamedRanges as XLNamedRanges).Add(name, text, comment, true).Visible = visible; + } + else + { + if (!Worksheet(Int32.Parse(localSheetId) + 1).NamedRanges.Any(nr => nr.Name == name)) + Worksheet(Int32.Parse(localSheetId) + 1).NamedRanges.Add(name, text, comment).Visible = visible; + } + } + } + } + } + + private static Regex definedNameRegex = new Regex(@"\A'.*'!.*\z", RegexOptions.Compiled); + + private IEnumerable validateDefinedNames(IEnumerable definedNames) + { + var fixedNames = new List(); + var sb = new StringBuilder(); + foreach (string testName in definedNames) + { + if (sb.Length > 0) + sb.Append(','); + + sb.Append(testName); + + Match matchedValidPattern = definedNameRegex.Match(sb.ToString()); + if (matchedValidPattern.Success) + { + yield return sb.ToString(); + sb = new StringBuilder(); + } + } + + if (sb.Length > 0) + yield return sb.ToString(); + } + + private void LoadPrintTitles(DefinedName definedName) + { + var areas = validateDefinedNames(definedName.Text.Split(',')); + foreach (var item in areas) + { + if (this.Range(item) != null) + SetColumnsOrRowsToRepeat(item); + } + } + + private void SetColumnsOrRowsToRepeat(string area) + { + string sheetName, sheetArea; + ParseReference(area, out sheetName, out sheetArea); + if (sheetArea.Equals("#REF")) return; + if (IsColReference(sheetArea)) + WorksheetsInternal.Worksheet(sheetName).PageSetup.SetColumnsToRepeatAtLeft(sheetArea); + if (IsRowReference(sheetArea)) + WorksheetsInternal.Worksheet(sheetName).PageSetup.SetRowsToRepeatAtTop(sheetArea); + } + + // either $A:$X => true or $1:$99 => false + private static bool IsColReference(string sheetArea) + { + char c = sheetArea[0] == '$' ? sheetArea[1] : sheetArea[0]; + return char.IsLetter(c); + } + + private static bool IsRowReference(string sheetArea) + { + char c = sheetArea[0] == '$' ? sheetArea[1] : sheetArea[0]; + return char.IsNumber(c); + } + + private static void ParseReference(string item, out string sheetName, out string sheetArea) + { + var sections = item.Trim().Split('!'); + if (sections.Count() == 1) + { + sheetName = string.Empty; + sheetArea = item; + } + else + { + sheetName = sections[0].Replace("\'", ""); + sheetArea = sections[1]; + } + } + + private Int32 lastCell; + + private void LoadCells(SharedStringItem[] sharedStrings, Stylesheet s, NumberingFormats numberingFormats, + Fills fills, Borders borders, Fonts fonts, Dictionary sharedFormulasR1C1, + XLWorksheet ws, Dictionary styleList, Cell cell, Int32 rowIndex) + { + Int32 styleIndex = cell.StyleIndex != null ? Int32.Parse(cell.StyleIndex.InnerText) : 0; + + String cellReference = cell.CellReference == null + ? XLHelper.GetColumnLetterFromNumber(++lastCell) + rowIndex + : cell.CellReference.Value; + var xlCell = ws.CellFast(cellReference); + + if (styleList.ContainsKey(styleIndex)) + { + xlCell.Style = styleList[styleIndex]; + } + else + { + ApplyStyle(xlCell, styleIndex, s, fills, borders, fonts, numberingFormats); + styleList.Add(styleIndex, xlCell.Style); + } + + if (cell.CellFormula != null && cell.CellFormula.SharedIndex != null && cell.CellFormula.Reference != null) + { + String formula; + if (cell.CellFormula.FormulaType != null && cell.CellFormula.FormulaType == CellFormulaValues.Array) + formula = "{" + cell.CellFormula.Text + "}"; + else + formula = cell.CellFormula.Text; + + if (cell.CellFormula.Reference != null) + xlCell.FormulaReference = ws.Range(cell.CellFormula.Reference.Value).RangeAddress; + + xlCell.FormulaA1 = formula; + sharedFormulasR1C1.Add(cell.CellFormula.SharedIndex.Value, xlCell.FormulaR1C1); + + if (cell.CellValue != null) + xlCell.ValueCached = cell.CellValue.Text; + } + else if (cell.CellFormula != null) + { + if (cell.CellFormula.SharedIndex != null) + xlCell.FormulaR1C1 = sharedFormulasR1C1[cell.CellFormula.SharedIndex.Value]; + else + { + String formula; + if (cell.CellFormula.FormulaType != null && cell.CellFormula.FormulaType == CellFormulaValues.Array) + formula = "{" + cell.CellFormula.Text + "}"; + else + formula = cell.CellFormula.Text; + + xlCell.FormulaA1 = formula; + } + + if (cell.CellFormula.Reference != null) + xlCell.FormulaReference = ws.Range(cell.CellFormula.Reference.Value).RangeAddress; + + if (cell.CellValue != null) + xlCell.ValueCached = cell.CellValue.Text; + } + else if (cell.DataType != null) + { + if (cell.DataType == CellValues.InlineString) + { + if (cell.InlineString != null) + { + if (cell.InlineString.Text != null) + xlCell._cellValue = cell.InlineString.Text.Text.FixNewLines(); + else + ParseCellValue(cell.InlineString, xlCell); + } + else + xlCell._cellValue = String.Empty; + + xlCell._dataType = XLCellValues.Text; + xlCell.ShareString = false; + } + else if (cell.DataType == CellValues.SharedString) + { + if (cell.CellValue != null && !XLHelper.IsNullOrWhiteSpace(cell.CellValue.Text)) + { + var sharedString = sharedStrings[Int32.Parse(cell.CellValue.Text, XLHelper.NumberStyle, XLHelper.ParseCulture)]; + ParseCellValue(sharedString, xlCell); + } + else + xlCell._cellValue = String.Empty; + + xlCell._dataType = XLCellValues.Text; + } + else if (cell.DataType == CellValues.Date) + { + if (cell.CellValue != null && !XLHelper.IsNullOrWhiteSpace(cell.CellValue.Text)) + xlCell._cellValue = Double.Parse(cell.CellValue.Text, XLHelper.NumberStyle, XLHelper.ParseCulture).ToInvariantString(); + xlCell._dataType = XLCellValues.DateTime; + } + else if (cell.DataType == CellValues.Boolean) + { + if (cell.CellValue != null) + xlCell._cellValue = cell.CellValue.Text; + xlCell._dataType = XLCellValues.Boolean; + } + else if (cell.DataType == CellValues.Number) + { + if (cell.CellValue != null && !XLHelper.IsNullOrWhiteSpace(cell.CellValue.Text)) + xlCell._cellValue = Double.Parse(cell.CellValue.Text, XLHelper.NumberStyle, XLHelper.ParseCulture).ToInvariantString(); + + if (s == null) + xlCell._dataType = XLCellValues.Number; + else + xlCell.DataType = GetDataTypeFromCell(xlCell.Style.NumberFormat); + } + } + else if (cell.CellValue != null) + { + if (s == null) + { + xlCell._dataType = XLCellValues.Number; + } + else + { + var numberFormatId = ((CellFormat)(s.CellFormats).ElementAt(styleIndex)).NumberFormatId; + if (!XLHelper.IsNullOrWhiteSpace(cell.CellValue.Text)) + xlCell._cellValue = Double.Parse(cell.CellValue.Text, CultureInfo.InvariantCulture).ToInvariantString(); + + if (s.NumberingFormats != null && + s.NumberingFormats.Any(nf => ((NumberingFormat)nf).NumberFormatId.Value == numberFormatId)) + { + xlCell.Style.NumberFormat.Format = + ((NumberingFormat)s.NumberingFormats + .First( + nf => ((NumberingFormat)nf).NumberFormatId.Value == numberFormatId) + ).FormatCode.Value; + } + else + xlCell.Style.NumberFormat.NumberFormatId = Int32.Parse(numberFormatId); + + xlCell.DataType = GetDataTypeFromCell(xlCell.Style.NumberFormat); + } + } + } + + /// + /// Parses the cell value for normal or rich text + /// Input element should either be a shared string or inline string + /// + /// The element (either a shared string or inline string) + /// The cell. + private void ParseCellValue(RstType element, XLCell xlCell) + { + var runs = element.Elements(); + var phoneticRuns = element.Elements(); + var phoneticProperties = element.Elements(); + Boolean hasRuns = false; + foreach (Run run in runs) + { + var runProperties = run.RunProperties; + String text = run.Text.InnerText.FixNewLines(); + + if (runProperties == null) + xlCell.RichText.AddText(text, xlCell.Style.Font); + else + { + var rt = xlCell.RichText.AddText(text); + LoadFont(runProperties, rt); + } + if (!hasRuns) + hasRuns = true; + } + + if (!hasRuns) + xlCell._cellValue = XmlEncoder.DecodeString(element.Text.InnerText); + + #region Load PhoneticProperties + + var pp = phoneticProperties.FirstOrDefault(); + if (pp != null) + { + if (pp.Alignment != null) + xlCell.RichText.Phonetics.Alignment = pp.Alignment.Value.ToClosedXml(); + if (pp.Type != null) + xlCell.RichText.Phonetics.Type = pp.Type.Value.ToClosedXml(); + + LoadFont(pp, xlCell.RichText.Phonetics); + } + + #endregion + + #region Load Phonetic Runs + + foreach (PhoneticRun pr in phoneticRuns) + { + xlCell.RichText.Phonetics.Add(pr.Text.InnerText.FixNewLines(), (Int32)pr.BaseTextStartIndex.Value, + (Int32)pr.EndingBaseIndex.Value); + } + + #endregion + } + + private void LoadNumberFormat(NumberingFormat nfSource, IXLNumberFormat nf) + { + if (nfSource == null) return; + + if (nfSource.FormatCode != null) + nf.Format = nfSource.FormatCode.Value; + //if (nfSource.NumberFormatId != null) + // nf.NumberFormatId = (Int32)nfSource.NumberFormatId.Value; + } + + private void LoadBorder(Border borderSource, IXLBorder border) + { + if (borderSource == null) return; + + LoadBorderValues(borderSource.DiagonalBorder, border.SetDiagonalBorder, border.SetDiagonalBorderColor); + + if (borderSource.DiagonalUp != null) + border.DiagonalUp = borderSource.DiagonalUp.Value; + if (borderSource.DiagonalDown != null) + border.DiagonalDown = borderSource.DiagonalDown.Value; + + LoadBorderValues(borderSource.LeftBorder, border.SetLeftBorder, border.SetLeftBorderColor); + LoadBorderValues(borderSource.RightBorder, border.SetRightBorder, border.SetRightBorderColor); + LoadBorderValues(borderSource.TopBorder, border.SetTopBorder, border.SetTopBorderColor); + LoadBorderValues(borderSource.BottomBorder, border.SetBottomBorder, border.SetBottomBorderColor); + } + + private void LoadBorderValues(BorderPropertiesType source, Func setBorder, Func setColor) + { + if (source != null) + { + if (source.Style != null) + setBorder(source.Style.Value.ToClosedXml()); + if (source.Color != null) + setColor(GetColor(source.Color)); + } + } + + private void LoadFill(Fill fillSource, IXLFill fill) + { + if (fillSource == null) return; + + if (fillSource.PatternFill != null) + { + if (fillSource.PatternFill.PatternType != null) + fill.PatternType = fillSource.PatternFill.PatternType.Value.ToClosedXml(); + else + fill.PatternType = XLFillPatternValues.Solid; + + if (fillSource.PatternFill.ForegroundColor != null) + fill.PatternColor = GetColor(fillSource.PatternFill.ForegroundColor); + if (fillSource.PatternFill.BackgroundColor != null) + fill.PatternBackgroundColor = GetColor(fillSource.PatternFill.BackgroundColor); + } + } + + private void LoadFont(OpenXmlElement fontSource, IXLFontBase fontBase) + { + if (fontSource == null) return; + + fontBase.Bold = GetBoolean(fontSource.Elements().FirstOrDefault()); + var fontColor = GetColor(fontSource.Elements().FirstOrDefault()); + if (fontColor.HasValue) + fontBase.FontColor = fontColor; + + var fontFamilyNumbering = + fontSource.Elements().FirstOrDefault(); + if (fontFamilyNumbering != null && fontFamilyNumbering.Val != null) + fontBase.FontFamilyNumbering = + (XLFontFamilyNumberingValues)Int32.Parse(fontFamilyNumbering.Val.ToString()); + var runFont = fontSource.Elements().FirstOrDefault(); + if (runFont != null) + { + if (runFont.Val != null) + fontBase.FontName = runFont.Val; + } + var fontSize = fontSource.Elements().FirstOrDefault(); + if (fontSize != null) + { + if ((fontSize).Val != null) + fontBase.FontSize = (fontSize).Val; + } + + fontBase.Italic = GetBoolean(fontSource.Elements().FirstOrDefault()); + fontBase.Shadow = GetBoolean(fontSource.Elements().FirstOrDefault()); + fontBase.Strikethrough = GetBoolean(fontSource.Elements().FirstOrDefault()); + + var underline = fontSource.Elements().FirstOrDefault(); + if (underline != null) + { + fontBase.Underline = underline.Val != null ? underline.Val.Value.ToClosedXml() : XLFontUnderlineValues.Single; + } + + var verticalTextAlignment = fontSource.Elements().FirstOrDefault(); + + if (verticalTextAlignment == null) return; + + fontBase.VerticalAlignment = verticalTextAlignment.Val != null ? verticalTextAlignment.Val.Value.ToClosedXml() : XLFontVerticalTextAlignmentValues.Baseline; + } + + private Int32 lastRow; + + private void LoadRows(Stylesheet s, NumberingFormats numberingFormats, Fills fills, Borders borders, Fonts fonts, + XLWorksheet ws, SharedStringItem[] sharedStrings, + Dictionary sharedFormulasR1C1, Dictionary styleList, + Row row) + { + Int32 rowIndex = row.RowIndex == null ? ++lastRow : (Int32)row.RowIndex.Value; + var xlRow = ws.Row(rowIndex, false); + + if (row.Height != null) + xlRow.Height = row.Height; + else + { + xlRow.Loading = true; + xlRow.Height = ws.RowHeight; + xlRow.Loading = false; + } + + if (row.Hidden != null && row.Hidden) + xlRow.Hide(); + + if (row.Collapsed != null && row.Collapsed) + xlRow.Collapsed = true; + + if (row.OutlineLevel != null && row.OutlineLevel > 0) + xlRow.OutlineLevel = row.OutlineLevel; + + if (row.CustomFormat != null) + { + Int32 styleIndex = row.StyleIndex != null ? Int32.Parse(row.StyleIndex.InnerText) : -1; + if (styleIndex > 0) + { + ApplyStyle(xlRow, styleIndex, s, fills, borders, fonts, numberingFormats); + } + else + { + xlRow.Style = DefaultStyle; + } + } + + lastCell = 0; + foreach (Cell cell in row.Elements()) + LoadCells(sharedStrings, s, numberingFormats, fills, borders, fonts, sharedFormulasR1C1, ws, styleList, + cell, rowIndex); + } + + private void LoadColumns(Stylesheet s, NumberingFormats numberingFormats, Fills fills, Borders borders, + Fonts fonts, XLWorksheet ws, Columns columns) + { + if (columns == null) return; + + var wsDefaultColumn = + columns.Elements().Where(c => c.Max == XLHelper.MaxColumnNumber).FirstOrDefault(); + + if (wsDefaultColumn != null && wsDefaultColumn.Width != null) + ws.ColumnWidth = wsDefaultColumn.Width - ColumnWidthOffset; + + Int32 styleIndexDefault = wsDefaultColumn != null && wsDefaultColumn.Style != null + ? Int32.Parse(wsDefaultColumn.Style.InnerText) + : -1; + if (styleIndexDefault >= 0) + ApplyStyle(ws, styleIndexDefault, s, fills, borders, fonts, numberingFormats); + + foreach (Column col in columns.Elements()) + { + //IXLStylized toApply; + if (col.Max == XLHelper.MaxColumnNumber) continue; + + var xlColumns = (XLColumns)ws.Columns(col.Min, col.Max); + if (col.Width != null) + { + Double width = col.Width - ColumnWidthOffset; + //if (width < 0) width = 0; + xlColumns.Width = width; + } + else + xlColumns.Width = ws.ColumnWidth; + + if (col.Hidden != null && col.Hidden) + xlColumns.Hide(); + + if (col.Collapsed != null && col.Collapsed) + xlColumns.CollapseOnly(); + + if (col.OutlineLevel != null) + { + var outlineLevel = col.OutlineLevel; + xlColumns.ForEach(c => c.OutlineLevel = outlineLevel); + } + + Int32 styleIndex = col.Style != null ? Int32.Parse(col.Style.InnerText) : -1; + if (styleIndex > 0) + { + ApplyStyle(xlColumns, styleIndex, s, fills, borders, fonts, numberingFormats); + } + else + { + xlColumns.Style = DefaultStyle; + } + } + } + + private static XLCellValues GetDataTypeFromCell(IXLNumberFormat numberFormat) + { + var numberFormatId = numberFormat.NumberFormatId; + if (numberFormatId == 46U) + return XLCellValues.TimeSpan; + else if ((numberFormatId >= 14 && numberFormatId <= 22) || + (numberFormatId >= 45 && numberFormatId <= 47)) + return XLCellValues.DateTime; + else if (numberFormatId == 49) + return XLCellValues.Text; + else + { + if (!XLHelper.IsNullOrWhiteSpace(numberFormat.Format)) + { + var dataType = GetDataTypeFromFormat(numberFormat.Format); + return dataType.HasValue ? dataType.Value : XLCellValues.Number; + } + else + return XLCellValues.Number; + } + } + + private static XLCellValues? GetDataTypeFromFormat(String format) + { + int length = format.Length; + String f = format.ToLower(); + for (Int32 i = 0; i < length; i++) + { + Char c = f[i]; + if (c == '"') + i = f.IndexOf('"', i + 1); + else if (c == '0' || c == '#' || c == '?') + return XLCellValues.Number; + else if (c == 'y' || c == 'm' || c == 'd' || c == 'h' || c == 's') + return XLCellValues.DateTime; + } + return null; + } + + private static void LoadAutoFilter(AutoFilter af, XLWorksheet ws) + { + if (af != null) + { + ws.Range(af.Reference.Value).SetAutoFilter(); + var autoFilter = ws.AutoFilter; + LoadAutoFilterSort(af, ws, autoFilter); + LoadAutoFilterColumns(af, autoFilter); + } + } + + private static void LoadAutoFilterColumns(AutoFilter af, XLAutoFilter autoFilter) + { + foreach (var filterColumn in af.Elements()) + { + Int32 column = (int)filterColumn.ColumnId.Value + 1; + if (filterColumn.CustomFilters != null) + { + var filterList = new List(); + autoFilter.Column(column).FilterType = XLFilterType.Custom; + autoFilter.Filters.Add(column, filterList); + XLConnector connector = filterColumn.CustomFilters.And != null && filterColumn.CustomFilters.And.Value ? XLConnector.And : XLConnector.Or; + + Boolean isText = false; + foreach (CustomFilter filter in filterColumn.CustomFilters) + { + Double dTest; + String val = filter.Val.Value; + if (!Double.TryParse(val, out dTest)) + { + isText = true; + break; + } + } + + foreach (CustomFilter filter in filterColumn.CustomFilters) + { + var xlFilter = new XLFilter { Value = filter.Val.Value, Connector = connector }; + if (isText) + xlFilter.Value = filter.Val.Value; + else + xlFilter.Value = Double.Parse(filter.Val.Value, CultureInfo.InvariantCulture); + + if (filter.Operator != null) + xlFilter.Operator = filter.Operator.Value.ToClosedXml(); + else + xlFilter.Operator = XLFilterOperator.Equal; + + Func condition = null; + switch (xlFilter.Operator) + { + case XLFilterOperator.Equal: + if (isText) + condition = o => o.ToString().Equals(xlFilter.Value.ToString(), StringComparison.InvariantCultureIgnoreCase); + else + condition = o => (o as IComparable).CompareTo(xlFilter.Value) == 0; + break; + + case XLFilterOperator.EqualOrGreaterThan: condition = o => (o as IComparable).CompareTo(xlFilter.Value) >= 0; break; + case XLFilterOperator.EqualOrLessThan: condition = o => (o as IComparable).CompareTo(xlFilter.Value) <= 0; break; + case XLFilterOperator.GreaterThan: condition = o => (o as IComparable).CompareTo(xlFilter.Value) > 0; break; + case XLFilterOperator.LessThan: condition = o => (o as IComparable).CompareTo(xlFilter.Value) < 0; break; + case XLFilterOperator.NotEqual: + if (isText) + condition = o => !o.ToString().Equals(xlFilter.Value.ToString(), StringComparison.InvariantCultureIgnoreCase); + else + condition = o => (o as IComparable).CompareTo(xlFilter.Value) != 0; + break; + } + + xlFilter.Condition = condition; + filterList.Add(xlFilter); + } + } + else if (filterColumn.Filters != null) + { + var filterList = new List(); + autoFilter.Column(column).FilterType = XLFilterType.Regular; + autoFilter.Filters.Add((int)filterColumn.ColumnId.Value + 1, filterList); + + Boolean isText = false; + foreach (Filter filter in filterColumn.Filters.OfType()) + { + Double dTest; + String val = filter.Val.Value; + if (!Double.TryParse(val, out dTest)) + { + isText = true; + break; + } + } + + foreach (Filter filter in filterColumn.Filters.OfType()) + { + var xlFilter = new XLFilter { Connector = XLConnector.Or, Operator = XLFilterOperator.Equal }; + + Func condition; + if (isText) + { + xlFilter.Value = filter.Val.Value; + condition = o => o.ToString().Equals(xlFilter.Value.ToString(), StringComparison.InvariantCultureIgnoreCase); + } + else + { + xlFilter.Value = Double.Parse(filter.Val.Value, CultureInfo.InvariantCulture); + condition = o => (o as IComparable).CompareTo(xlFilter.Value) == 0; + } + + xlFilter.Condition = condition; + filterList.Add(xlFilter); + } + } + else if (filterColumn.Top10 != null) + { + var xlFilterColumn = autoFilter.Column(column); + autoFilter.Filters.Add(column, null); + xlFilterColumn.FilterType = XLFilterType.TopBottom; + if (filterColumn.Top10.Percent != null && filterColumn.Top10.Percent.Value) + xlFilterColumn.TopBottomType = XLTopBottomType.Percent; + else + xlFilterColumn.TopBottomType = XLTopBottomType.Items; + + if (filterColumn.Top10.Top != null && !filterColumn.Top10.Top.Value) + xlFilterColumn.TopBottomPart = XLTopBottomPart.Bottom; + else + xlFilterColumn.TopBottomPart = XLTopBottomPart.Top; + + xlFilterColumn.TopBottomValue = (int)filterColumn.Top10.Val.Value; + } + else if (filterColumn.DynamicFilter != null) + { + autoFilter.Filters.Add(column, null); + var xlFilterColumn = autoFilter.Column(column); + xlFilterColumn.FilterType = XLFilterType.Dynamic; + if (filterColumn.DynamicFilter.Type != null) + xlFilterColumn.DynamicType = filterColumn.DynamicFilter.Type.Value.ToClosedXml(); + else + xlFilterColumn.DynamicType = XLFilterDynamicType.AboveAverage; + + xlFilterColumn.DynamicValue = filterColumn.DynamicFilter.Val.Value; + } + } + } + + private static void LoadAutoFilterSort(AutoFilter af, XLWorksheet ws, IXLBaseAutoFilter autoFilter) + { + var sort = af.Elements().FirstOrDefault(); + if (sort != null) + { + var condition = sort.Elements().FirstOrDefault(); + if (condition != null) + { + Int32 column = ws.Range(condition.Reference.Value).FirstCell().Address.ColumnNumber - autoFilter.Range.FirstCell().Address.ColumnNumber + 1; + autoFilter.SortColumn = column; + autoFilter.Sorted = true; + autoFilter.SortOrder = condition.Descending != null && condition.Descending.Value ? XLSortOrder.Descending : XLSortOrder.Ascending; + } + } + } + + private static void LoadSheetProtection(SheetProtection sp, XLWorksheet ws) + { + if (sp == null) return; + + if (sp.Sheet != null) ws.Protection.Protected = sp.Sheet.Value; + if (sp.Password != null) ws.Protection.PasswordHash = sp.Password.Value; + if (sp.FormatCells != null) ws.Protection.FormatCells = !sp.FormatCells.Value; + if (sp.FormatColumns != null) ws.Protection.FormatColumns = !sp.FormatColumns.Value; + if (sp.FormatRows != null) ws.Protection.FormatRows = !sp.FormatRows.Value; + if (sp.InsertColumns != null) ws.Protection.InsertColumns = !sp.InsertColumns.Value; + if (sp.InsertHyperlinks != null) ws.Protection.InsertHyperlinks = !sp.InsertHyperlinks.Value; + if (sp.InsertRows != null) ws.Protection.InsertRows = !sp.InsertRows.Value; + if (sp.DeleteColumns != null) ws.Protection.DeleteColumns = !sp.DeleteColumns.Value; + if (sp.DeleteRows != null) ws.Protection.DeleteRows = !sp.DeleteRows.Value; + if (sp.AutoFilter != null) ws.Protection.AutoFilter = !sp.AutoFilter.Value; + if (sp.PivotTables != null) ws.Protection.PivotTables = !sp.PivotTables.Value; + if (sp.Sort != null) ws.Protection.Sort = !sp.Sort.Value; + if (sp.SelectLockedCells != null) ws.Protection.SelectLockedCells = sp.SelectLockedCells.Value; + if (sp.SelectUnlockedCells != null) ws.Protection.SelectUnlockedCells = sp.SelectUnlockedCells.Value; + } + + private static void LoadDataValidations(DataValidations dataValidations, XLWorksheet ws) + { + if (dataValidations == null) return; + + foreach (DataValidation dvs in dataValidations.Elements()) + { + String txt = dvs.SequenceOfReferences.InnerText; + if (XLHelper.IsNullOrWhiteSpace(txt)) continue; + foreach (var dvt in txt.Split(' ').Select(rangeAddress => ws.Range(rangeAddress).DataValidation)) + { + if (dvs.AllowBlank != null) dvt.IgnoreBlanks = dvs.AllowBlank; + if (dvs.ShowDropDown != null) dvt.InCellDropdown = !dvs.ShowDropDown.Value; + if (dvs.ShowErrorMessage != null) dvt.ShowErrorMessage = dvs.ShowErrorMessage; + if (dvs.ShowInputMessage != null) dvt.ShowInputMessage = dvs.ShowInputMessage; + if (dvs.PromptTitle != null) dvt.InputTitle = dvs.PromptTitle; + if (dvs.Prompt != null) dvt.InputMessage = dvs.Prompt; + if (dvs.ErrorTitle != null) dvt.ErrorTitle = dvs.ErrorTitle; + if (dvs.Error != null) dvt.ErrorMessage = dvs.Error; + if (dvs.ErrorStyle != null) dvt.ErrorStyle = dvs.ErrorStyle.Value.ToClosedXml(); + if (dvs.Type != null) dvt.AllowedValues = dvs.Type.Value.ToClosedXml(); + if (dvs.Operator != null) dvt.Operator = dvs.Operator.Value.ToClosedXml(); + if (dvs.Formula1 != null) dvt.MinValue = dvs.Formula1.Text; + if (dvs.Formula2 != null) dvt.MaxValue = dvs.Formula2.Text; + } + } + } + + /// + /// Loads the conditional formatting. + /// + // https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.conditionalformattingrule%28v=office.15%29.aspx?f=255&MSPPError=-2147217396 + private void LoadConditionalFormatting(ConditionalFormatting conditionalFormatting, XLWorksheet ws, Dictionary differentialFormats) + { + if (conditionalFormatting == null) return; + + foreach (var sor in conditionalFormatting.SequenceOfReferences.Items) + { + foreach (var fr in conditionalFormatting.Elements()) + { + var conditionalFormat = new XLConditionalFormat(ws.Range(sor.Value)); + if (fr.FormatId != null) + { + LoadFont(differentialFormats[(Int32)fr.FormatId.Value].Font, conditionalFormat.Style.Font); + LoadFill(differentialFormats[(Int32)fr.FormatId.Value].Fill, conditionalFormat.Style.Fill); + LoadBorder(differentialFormats[(Int32)fr.FormatId.Value].Border, conditionalFormat.Style.Border); + LoadNumberFormat(differentialFormats[(Int32)fr.FormatId.Value].NumberingFormat, conditionalFormat.Style.NumberFormat); + } + + // The conditional formatting type is compulsory. If it doesn't exist, skip the entire rule. + if (fr.Type == null) continue; + conditionalFormat.ConditionalFormatType = fr.Type.Value.ToClosedXml(); + + if (conditionalFormat.ConditionalFormatType == XLConditionalFormatType.CellIs && fr.Operator != null) + conditionalFormat.Operator = fr.Operator.Value.ToClosedXml(); + + if (fr.Text != null && !XLHelper.IsNullOrWhiteSpace(fr.Text)) + conditionalFormat.Values.Add(GetFormula(fr.Text.Value)); + + if (conditionalFormat.ConditionalFormatType == XLConditionalFormatType.Top10) + { + if (fr.Percent != null) + conditionalFormat.Percent = fr.Percent.Value; + if (fr.Bottom != null) + conditionalFormat.Bottom = fr.Bottom.Value; + if (fr.Rank != null) + conditionalFormat.Values.Add(GetFormula(fr.Rank.Value.ToString())); + } + + if (fr.Elements().Any()) + { + var colorScale = fr.Elements().First(); + ExtractConditionalFormatValueObjects(conditionalFormat, colorScale); + } + else if (fr.Elements().Any()) + { + var dataBar = fr.Elements().First(); + if (dataBar.ShowValue != null) + conditionalFormat.ShowBarOnly = !dataBar.ShowValue.Value; + ExtractConditionalFormatValueObjects(conditionalFormat, dataBar); + } + else if (fr.Elements().Any()) + { + var iconSet = fr.Elements().First(); + if (iconSet.ShowValue != null) + conditionalFormat.ShowIconOnly = !iconSet.ShowValue.Value; + if (iconSet.Reverse != null) + conditionalFormat.ReverseIconOrder = iconSet.Reverse.Value; + + if (iconSet.IconSetValue != null) + conditionalFormat.IconSetStyle = iconSet.IconSetValue.Value.ToClosedXml(); + else + conditionalFormat.IconSetStyle = XLIconSetStyle.ThreeTrafficLights1; + + ExtractConditionalFormatValueObjects(conditionalFormat, iconSet); + } + else + { + foreach (var formula in fr.Elements()) + { + if (formula.Text != null + && (conditionalFormat.ConditionalFormatType == XLConditionalFormatType.CellIs + || conditionalFormat.ConditionalFormatType == XLConditionalFormatType.Expression)) + { + conditionalFormat.Values.Add(GetFormula(formula.Text)); + } + } + } + ws.ConditionalFormats.Add(conditionalFormat); + } + } + } + + private static XLFormula GetFormula(String value) + { + var formula = new XLFormula(); + formula._value = value; + formula.IsFormula = !(value[0] == '"' && value.EndsWith("\"")); + return formula; + } + + private void ExtractConditionalFormatValueObjects(XLConditionalFormat conditionalFormat, OpenXmlElement element) + { + foreach (var c in element.Elements()) + { + if (c.Type != null) + conditionalFormat.ContentTypes.Add(c.Type.Value.ToClosedXml()); + if (c.Val != null) + conditionalFormat.Values.Add(new XLFormula { Value = c.Val.Value }); + else + conditionalFormat.Values.Add(null); + + if (c.GreaterThanOrEqual != null) + conditionalFormat.IconSetOperators.Add(c.GreaterThanOrEqual.Value ? XLCFIconSetOperator.EqualOrGreaterThan : XLCFIconSetOperator.GreaterThan); + else + conditionalFormat.IconSetOperators.Add(XLCFIconSetOperator.EqualOrGreaterThan); + } + foreach (var c in element.Elements()) + { + conditionalFormat.Colors.Add(GetColor(c)); + } + } + + private static void LoadHyperlinks(Hyperlinks hyperlinks, WorksheetPart worksheetPart, XLWorksheet ws) + { + var hyperlinkDictionary = new Dictionary(); + if (worksheetPart.HyperlinkRelationships != null) + hyperlinkDictionary = worksheetPart.HyperlinkRelationships.ToDictionary(hr => hr.Id, hr => hr.Uri); + + if (hyperlinks == null) return; + + foreach (Hyperlink hl in hyperlinks.Elements()) + { + if (hl.Reference.Value.Equals("#REF")) continue; + String tooltip = hl.Tooltip != null ? hl.Tooltip.Value : String.Empty; + var xlRange = ws.Range(hl.Reference.Value); + foreach (XLCell xlCell in xlRange.Cells()) + { + xlCell.SettingHyperlink = true; + + if (hl.Id != null) + xlCell.Hyperlink = new XLHyperlink(hyperlinkDictionary[hl.Id], tooltip); + else if (hl.Location != null) + xlCell.Hyperlink = new XLHyperlink(hl.Location.Value, tooltip); + else + xlCell.Hyperlink = new XLHyperlink(hl.Reference.Value, tooltip); + + xlCell.SettingHyperlink = false; + } + } + } + + private static void LoadColumnBreaks(ColumnBreaks columnBreaks, XLWorksheet ws) + { + if (columnBreaks == null) return; + + foreach (Break columnBreak in columnBreaks.Elements().Where(columnBreak => columnBreak.Id != null)) + { + ws.PageSetup.ColumnBreaks.Add(Int32.Parse(columnBreak.Id.InnerText)); + } + } + + private static void LoadRowBreaks(RowBreaks rowBreaks, XLWorksheet ws) + { + if (rowBreaks == null) return; + + foreach (Break rowBreak in rowBreaks.Elements()) + ws.PageSetup.RowBreaks.Add(Int32.Parse(rowBreak.Id.InnerText)); + } + + private void LoadSheetProperties(SheetProperties sheetProperty, XLWorksheet ws, out PageSetupProperties pageSetupProperties) + { + pageSetupProperties = null; + if (sheetProperty == null) return; + + if (sheetProperty.TabColor != null) + ws.TabColor = GetColor(sheetProperty.TabColor); + + if (sheetProperty.OutlineProperties != null) + { + if (sheetProperty.OutlineProperties.SummaryBelow != null) + { + ws.Outline.SummaryVLocation = sheetProperty.OutlineProperties.SummaryBelow + ? XLOutlineSummaryVLocation.Bottom + : XLOutlineSummaryVLocation.Top; + } + + if (sheetProperty.OutlineProperties.SummaryRight != null) + { + ws.Outline.SummaryHLocation = sheetProperty.OutlineProperties.SummaryRight + ? XLOutlineSummaryHLocation.Right + : XLOutlineSummaryHLocation.Left; + } + } + + if (sheetProperty.PageSetupProperties != null) + pageSetupProperties = sheetProperty.PageSetupProperties; + } + + private static void LoadHeaderFooter(HeaderFooter headerFooter, XLWorksheet ws) + { + if (headerFooter == null) return; + + if (headerFooter.AlignWithMargins != null) + ws.PageSetup.AlignHFWithMargins = headerFooter.AlignWithMargins; + if (headerFooter.ScaleWithDoc != null) + ws.PageSetup.ScaleHFWithDocument = headerFooter.ScaleWithDoc; + + if (headerFooter.DifferentFirst != null) + ws.PageSetup.DifferentFirstPageOnHF = headerFooter.DifferentFirst; + if (headerFooter.DifferentOddEven != null) + ws.PageSetup.DifferentOddEvenPagesOnHF = headerFooter.DifferentOddEven; + + // Footers + var xlFooter = (XLHeaderFooter)ws.PageSetup.Footer; + var evenFooter = headerFooter.EvenFooter; + if (evenFooter != null) + xlFooter.SetInnerText(XLHFOccurrence.EvenPages, evenFooter.Text); + var oddFooter = headerFooter.OddFooter; + if (oddFooter != null) + xlFooter.SetInnerText(XLHFOccurrence.OddPages, oddFooter.Text); + var firstFooter = headerFooter.FirstFooter; + if (firstFooter != null) + xlFooter.SetInnerText(XLHFOccurrence.FirstPage, firstFooter.Text); + // Headers + var xlHeader = (XLHeaderFooter)ws.PageSetup.Header; + var evenHeader = headerFooter.EvenHeader; + if (evenHeader != null) + xlHeader.SetInnerText(XLHFOccurrence.EvenPages, evenHeader.Text); + var oddHeader = headerFooter.OddHeader; + if (oddHeader != null) + xlHeader.SetInnerText(XLHFOccurrence.OddPages, oddHeader.Text); + var firstHeader = headerFooter.FirstHeader; + if (firstHeader != null) + xlHeader.SetInnerText(XLHFOccurrence.FirstPage, firstHeader.Text); + + ((XLHeaderFooter)ws.PageSetup.Header).SetAsInitial(); + ((XLHeaderFooter)ws.PageSetup.Footer).SetAsInitial(); + } + + private static void LoadPageSetup(PageSetup pageSetup, XLWorksheet ws, PageSetupProperties pageSetupProperties) + { + if (pageSetup == null) return; + + if (pageSetup.PaperSize != null) + ws.PageSetup.PaperSize = (XLPaperSize)Int32.Parse(pageSetup.PaperSize.InnerText); + if (pageSetup.Scale != null) + ws.PageSetup.Scale = Int32.Parse(pageSetup.Scale.InnerText); + if (pageSetupProperties != null && pageSetupProperties.FitToPage != null && pageSetupProperties.FitToPage.Value) + { + if (pageSetup.FitToWidth == null) + ws.PageSetup.PagesWide = 1; + else + ws.PageSetup.PagesWide = Int32.Parse(pageSetup.FitToWidth.InnerText); + + if (pageSetup.FitToHeight == null) + ws.PageSetup.PagesTall = 1; + else + ws.PageSetup.PagesTall = Int32.Parse(pageSetup.FitToHeight.InnerText); + } + if (pageSetup.PageOrder != null) + ws.PageSetup.PageOrder = pageSetup.PageOrder.Value.ToClosedXml(); + if (pageSetup.Orientation != null) + ws.PageSetup.PageOrientation = pageSetup.Orientation.Value.ToClosedXml(); + if (pageSetup.BlackAndWhite != null) + ws.PageSetup.BlackAndWhite = pageSetup.BlackAndWhite; + if (pageSetup.Draft != null) + ws.PageSetup.DraftQuality = pageSetup.Draft; + if (pageSetup.CellComments != null) + ws.PageSetup.ShowComments = pageSetup.CellComments.Value.ToClosedXml(); + if (pageSetup.Errors != null) + ws.PageSetup.PrintErrorValue = pageSetup.Errors.Value.ToClosedXml(); + if (pageSetup.HorizontalDpi != null) ws.PageSetup.HorizontalDpi = (Int32)pageSetup.HorizontalDpi.Value; + if (pageSetup.VerticalDpi != null) ws.PageSetup.VerticalDpi = (Int32)pageSetup.VerticalDpi.Value; + if (pageSetup.FirstPageNumber != null) + ws.PageSetup.FirstPageNumber = UInt32.Parse(pageSetup.FirstPageNumber.InnerText); + } + + private static void LoadPageMargins(PageMargins pageMargins, XLWorksheet ws) + { + if (pageMargins == null) return; + + if (pageMargins.Bottom != null) + ws.PageSetup.Margins.Bottom = pageMargins.Bottom; + if (pageMargins.Footer != null) + ws.PageSetup.Margins.Footer = pageMargins.Footer; + if (pageMargins.Header != null) + ws.PageSetup.Margins.Header = pageMargins.Header; + if (pageMargins.Left != null) + ws.PageSetup.Margins.Left = pageMargins.Left; + if (pageMargins.Right != null) + ws.PageSetup.Margins.Right = pageMargins.Right; + if (pageMargins.Top != null) + ws.PageSetup.Margins.Top = pageMargins.Top; + } + + private static void LoadPrintOptions(PrintOptions printOptions, XLWorksheet ws) + { + if (printOptions == null) return; + + if (printOptions.GridLines != null) + ws.PageSetup.ShowGridlines = printOptions.GridLines; + if (printOptions.HorizontalCentered != null) + ws.PageSetup.CenterHorizontally = printOptions.HorizontalCentered; + if (printOptions.VerticalCentered != null) + ws.PageSetup.CenterVertically = printOptions.VerticalCentered; + if (printOptions.Headings != null) + ws.PageSetup.ShowRowAndColumnHeadings = printOptions.Headings; + } + + private static void LoadSheetViews(SheetViews sheetViews, XLWorksheet ws) + { + if (sheetViews == null) return; + + var sheetView = sheetViews.Elements().FirstOrDefault(); + + if (sheetView == null) return; + + if (sheetView.RightToLeft != null) ws.RightToLeft = sheetView.RightToLeft.Value; + if (sheetView.ShowFormulas != null) ws.ShowFormulas = sheetView.ShowFormulas.Value; + if (sheetView.ShowGridLines != null) ws.ShowGridLines = sheetView.ShowGridLines.Value; + if (sheetView.ShowOutlineSymbols != null) + ws.ShowOutlineSymbols = sheetView.ShowOutlineSymbols.Value; + if (sheetView.ShowRowColHeaders != null) ws.ShowRowColHeaders = sheetView.ShowRowColHeaders.Value; + if (sheetView.ShowRuler != null) ws.ShowRuler = sheetView.ShowRuler.Value; + if (sheetView.ShowWhiteSpace != null) ws.ShowWhiteSpace = sheetView.ShowWhiteSpace.Value; + if (sheetView.ShowZeros != null) ws.ShowZeros = sheetView.ShowZeros.Value; + if (sheetView.TabSelected != null) ws.TabSelected = sheetView.TabSelected.Value; + + var selection = sheetView.Elements().FirstOrDefault(); + if (selection != null) + { + if (selection.SequenceOfReferences != null) + ws.Ranges(selection.SequenceOfReferences.InnerText.Replace(" ", ",")).Select(); + + if (selection.ActiveCell != null) + ws.Cell(selection.ActiveCell).SetActive(); + } + + if (sheetView.ZoomScale != null) + ws.SheetView.ZoomScale = (int)UInt32Value.ToUInt32(sheetView.ZoomScale); + if (sheetView.ZoomScaleNormal != null) + ws.SheetView.ZoomScaleNormal = (int)UInt32Value.ToUInt32(sheetView.ZoomScaleNormal); + if (sheetView.ZoomScalePageLayoutView != null) + ws.SheetView.ZoomScalePageLayoutView = (int)UInt32Value.ToUInt32(sheetView.ZoomScalePageLayoutView); + if (sheetView.ZoomScaleSheetLayoutView != null) + ws.SheetView.ZoomScaleSheetLayoutView = (int)UInt32Value.ToUInt32(sheetView.ZoomScaleSheetLayoutView); + + var pane = sheetView.Elements().FirstOrDefault(); + if (pane == null) return; + + if (pane.State == null || + (pane.State != PaneStateValues.FrozenSplit && pane.State != PaneStateValues.Frozen)) return; + + if (pane.HorizontalSplit != null) + ws.SheetView.SplitColumn = (Int32)pane.HorizontalSplit.Value; + if (pane.VerticalSplit != null) + ws.SheetView.SplitRow = (Int32)pane.VerticalSplit.Value; + } + + private void SetProperties(SpreadsheetDocument dSpreadsheet) + { + var p = dSpreadsheet.PackageProperties; + Properties.Author = p.Creator; + Properties.Category = p.Category; + Properties.Comments = p.Description; + if (p.Created != null) + Properties.Created = p.Created.Value; + Properties.Keywords = p.Keywords; + Properties.LastModifiedBy = p.LastModifiedBy; + Properties.Status = p.ContentStatus; + Properties.Subject = p.Subject; + Properties.Title = p.Title; + } + + private XLColor GetColor(ColorType color) + { + XLColor retVal = null; + if (color != null) + { + if (color.Rgb != null) + { + String htmlColor = "#" + color.Rgb.Value; + Color thisColor; + if (!_colorList.ContainsKey(htmlColor)) + { + thisColor = ColorTranslator.FromHtml(htmlColor); + _colorList.Add(htmlColor, thisColor); + } + else + thisColor = _colorList[htmlColor]; + retVal = XLColor.FromColor(thisColor); + } + else if (color.Indexed != null && color.Indexed < 64) + retVal = XLColor.FromIndex((Int32)color.Indexed.Value); + else if (color.Theme != null) + { + retVal = color.Tint != null ? XLColor.FromTheme((XLThemeColor)color.Theme.Value, color.Tint.Value) : XLColor.FromTheme((XLThemeColor)color.Theme.Value); + } + } + return retVal ?? XLColor.NoColor; + } + + private void ApplyStyle(IXLStylized xlStylized, Int32 styleIndex, Stylesheet s, Fills fills, Borders borders, + Fonts fonts, NumberingFormats numberingFormats) + { + if (s == null) return; //No Stylesheet, no Styles + + var cellFormat = (CellFormat)s.CellFormats.ElementAt(styleIndex); + + if (cellFormat.ApplyProtection != null) + { + var protection = cellFormat.Protection; + + if (protection == null) + xlStylized.InnerStyle.Protection = new XLProtection(null, DefaultStyle.Protection); + else + { + xlStylized.InnerStyle.Protection.Hidden = protection.Hidden != null && protection.Hidden.HasValue && + protection.Hidden.Value; + xlStylized.InnerStyle.Protection.Locked = protection.Locked == null || + (protection.Locked.HasValue && protection.Locked.Value); + } + } + + if (UInt32HasValue(cellFormat.FillId)) + { + var fill = (Fill)fills.ElementAt((Int32)cellFormat.FillId.Value); + if (fill.PatternFill != null) + { + if (fill.PatternFill.PatternType != null) + xlStylized.InnerStyle.Fill.PatternType = fill.PatternFill.PatternType.Value.ToClosedXml(); + + var fgColor = GetColor(fill.PatternFill.ForegroundColor); + if (fgColor.HasValue) xlStylized.InnerStyle.Fill.PatternColor = fgColor; + + var bgColor = GetColor(fill.PatternFill.BackgroundColor); + if (bgColor.HasValue) + xlStylized.InnerStyle.Fill.PatternBackgroundColor = bgColor; + } + } + + var alignment = cellFormat.Alignment; + if (alignment != null) + { + if (alignment.Horizontal != null) + xlStylized.InnerStyle.Alignment.Horizontal = alignment.Horizontal.Value.ToClosedXml(); + if (alignment.Indent != null && alignment.Indent != 0) + xlStylized.InnerStyle.Alignment.Indent = Int32.Parse(alignment.Indent.ToString()); + if (alignment.JustifyLastLine != null) + xlStylized.InnerStyle.Alignment.JustifyLastLine = alignment.JustifyLastLine; + if (alignment.ReadingOrder != null) + { + xlStylized.InnerStyle.Alignment.ReadingOrder = + (XLAlignmentReadingOrderValues)Int32.Parse(alignment.ReadingOrder.ToString()); + } + if (alignment.RelativeIndent != null) + xlStylized.InnerStyle.Alignment.RelativeIndent = alignment.RelativeIndent; + if (alignment.ShrinkToFit != null) + xlStylized.InnerStyle.Alignment.ShrinkToFit = alignment.ShrinkToFit; + if (alignment.TextRotation != null) + xlStylized.InnerStyle.Alignment.TextRotation = (Int32)alignment.TextRotation.Value; + if (alignment.Vertical != null) + xlStylized.InnerStyle.Alignment.Vertical = alignment.Vertical.Value.ToClosedXml(); + if (alignment.WrapText != null) + xlStylized.InnerStyle.Alignment.WrapText = alignment.WrapText; + } + + if (UInt32HasValue(cellFormat.BorderId)) + { + uint borderId = cellFormat.BorderId.Value; + var border = (Border)borders.ElementAt((Int32)borderId); + if (border != null) + { + var bottomBorder = border.BottomBorder; + if (bottomBorder != null) + { + if (bottomBorder.Style != null) + xlStylized.InnerStyle.Border.BottomBorder = bottomBorder.Style.Value.ToClosedXml(); + + var bottomBorderColor = GetColor(bottomBorder.Color); + if (bottomBorderColor.HasValue) + xlStylized.InnerStyle.Border.BottomBorderColor = bottomBorderColor; + } + var topBorder = border.TopBorder; + if (topBorder != null) + { + if (topBorder.Style != null) + xlStylized.InnerStyle.Border.TopBorder = topBorder.Style.Value.ToClosedXml(); + var topBorderColor = GetColor(topBorder.Color); + if (topBorderColor.HasValue) + xlStylized.InnerStyle.Border.TopBorderColor = topBorderColor; + } + var leftBorder = border.LeftBorder; + if (leftBorder != null) + { + if (leftBorder.Style != null) + xlStylized.InnerStyle.Border.LeftBorder = leftBorder.Style.Value.ToClosedXml(); + var leftBorderColor = GetColor(leftBorder.Color); + if (leftBorderColor.HasValue) + xlStylized.InnerStyle.Border.LeftBorderColor = leftBorderColor; + } + var rightBorder = border.RightBorder; + if (rightBorder != null) + { + if (rightBorder.Style != null) + xlStylized.InnerStyle.Border.RightBorder = rightBorder.Style.Value.ToClosedXml(); + var rightBorderColor = GetColor(rightBorder.Color); + if (rightBorderColor.HasValue) + xlStylized.InnerStyle.Border.RightBorderColor = rightBorderColor; + } + var diagonalBorder = border.DiagonalBorder; + if (diagonalBorder != null) + { + if (diagonalBorder.Style != null) + xlStylized.InnerStyle.Border.DiagonalBorder = diagonalBorder.Style.Value.ToClosedXml(); + var diagonalBorderColor = GetColor(diagonalBorder.Color); + if (diagonalBorderColor.HasValue) + xlStylized.InnerStyle.Border.DiagonalBorderColor = diagonalBorderColor; + if (border.DiagonalDown != null) + xlStylized.InnerStyle.Border.DiagonalDown = border.DiagonalDown; + if (border.DiagonalUp != null) + xlStylized.InnerStyle.Border.DiagonalUp = border.DiagonalUp; + } + } + } + + if (UInt32HasValue(cellFormat.FontId)) + { + var fontId = cellFormat.FontId; + var font = (DocumentFormat.OpenXml.Spreadsheet.Font)fonts.ElementAt((Int32)fontId.Value); + if (font != null) + { + xlStylized.InnerStyle.Font.Bold = GetBoolean(font.Bold); + + var fontColor = GetColor(font.Color); + if (fontColor.HasValue) + xlStylized.InnerStyle.Font.FontColor = fontColor; + + if (font.FontFamilyNumbering != null && (font.FontFamilyNumbering).Val != null) + { + xlStylized.InnerStyle.Font.FontFamilyNumbering = + (XLFontFamilyNumberingValues)Int32.Parse((font.FontFamilyNumbering).Val.ToString()); + } + if (font.FontName != null) + { + if ((font.FontName).Val != null) + xlStylized.InnerStyle.Font.FontName = (font.FontName).Val; + } + if (font.FontSize != null) + { + if ((font.FontSize).Val != null) + xlStylized.InnerStyle.Font.FontSize = (font.FontSize).Val; + } + + xlStylized.InnerStyle.Font.Italic = GetBoolean(font.Italic); + xlStylized.InnerStyle.Font.Shadow = GetBoolean(font.Shadow); + xlStylized.InnerStyle.Font.Strikethrough = GetBoolean(font.Strike); + + if (font.Underline != null) + { + xlStylized.InnerStyle.Font.Underline = font.Underline.Val != null + ? (font.Underline).Val.Value.ToClosedXml() + : XLFontUnderlineValues.Single; + } + + if (font.VerticalTextAlignment != null) + { + xlStylized.InnerStyle.Font.VerticalAlignment = font.VerticalTextAlignment.Val != null + ? (font.VerticalTextAlignment).Val.Value. + ToClosedXml() + : XLFontVerticalTextAlignmentValues.Baseline; + } + } + } + + if (!UInt32HasValue(cellFormat.NumberFormatId)) return; + + var numberFormatId = cellFormat.NumberFormatId; + + string formatCode = String.Empty; + if (numberingFormats != null) + { + var numberingFormat = + numberingFormats.FirstOrDefault( + nf => + ((NumberingFormat)nf).NumberFormatId != null && + ((NumberingFormat)nf).NumberFormatId.Value == numberFormatId) as NumberingFormat; + + if (numberingFormat != null && numberingFormat.FormatCode != null) + formatCode = numberingFormat.FormatCode.Value; + } + if (formatCode.Length > 0) + xlStylized.InnerStyle.NumberFormat.Format = formatCode; + else + xlStylized.InnerStyle.NumberFormat.NumberFormatId = (Int32)numberFormatId.Value; + } + + private static Boolean UInt32HasValue(UInt32Value value) + { + return value != null && value.HasValue; + } + + private static Boolean GetBoolean(BooleanPropertyType property) + { + if (property != null) + { + if (property.Val != null) + return property.Val; + return true; + } + + return false; + } + } } \ No newline at end of file diff --git a/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/Excel/XLWorkbook_Save.cs index e8e970a..19ba801 100644 --- a/ClosedXML/Excel/XLWorkbook_Save.cs +++ b/ClosedXML/Excel/XLWorkbook_Save.cs @@ -1,5048 +1,5048 @@ -using ClosedXML.Extensions; -using ClosedXML.Utils; -using DocumentFormat.OpenXml; -using DocumentFormat.OpenXml.CustomProperties; -using DocumentFormat.OpenXml.Drawing; -using DocumentFormat.OpenXml.ExtendedProperties; -using DocumentFormat.OpenXml.Packaging; -using DocumentFormat.OpenXml.Spreadsheet; -using DocumentFormat.OpenXml.Validation; -using DocumentFormat.OpenXml.VariantTypes; -using DocumentFormat.OpenXml.Vml.Office; -using DocumentFormat.OpenXml.Vml.Spreadsheet; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Xml; -using System.Xml.Linq; -using Anchor = DocumentFormat.OpenXml.Vml.Spreadsheet.Anchor; -using BackgroundColor = DocumentFormat.OpenXml.Spreadsheet.BackgroundColor; -using BottomBorder = DocumentFormat.OpenXml.Spreadsheet.BottomBorder; -using Break = DocumentFormat.OpenXml.Spreadsheet.Break; -using Field = DocumentFormat.OpenXml.Spreadsheet.Field; -using Fill = DocumentFormat.OpenXml.Spreadsheet.Fill; -using Fonts = DocumentFormat.OpenXml.Spreadsheet.Fonts; -using FontScheme = DocumentFormat.OpenXml.Drawing.FontScheme; -using ForegroundColor = DocumentFormat.OpenXml.Spreadsheet.ForegroundColor; -using GradientFill = DocumentFormat.OpenXml.Drawing.GradientFill; -using GradientStop = DocumentFormat.OpenXml.Drawing.GradientStop; -using Hyperlink = DocumentFormat.OpenXml.Spreadsheet.Hyperlink; -using LeftBorder = DocumentFormat.OpenXml.Spreadsheet.LeftBorder; -using Outline = DocumentFormat.OpenXml.Drawing.Outline; -using Path = System.IO.Path; -using PatternFill = DocumentFormat.OpenXml.Spreadsheet.PatternFill; -using Properties = DocumentFormat.OpenXml.ExtendedProperties.Properties; -using RightBorder = DocumentFormat.OpenXml.Spreadsheet.RightBorder; -using Run = DocumentFormat.OpenXml.Spreadsheet.Run; -using RunProperties = DocumentFormat.OpenXml.Spreadsheet.RunProperties; -using Table = DocumentFormat.OpenXml.Spreadsheet.Table; -using Text = DocumentFormat.OpenXml.Spreadsheet.Text; -using TopBorder = DocumentFormat.OpenXml.Spreadsheet.TopBorder; -using Underline = DocumentFormat.OpenXml.Spreadsheet.Underline; -using VerticalTextAlignment = DocumentFormat.OpenXml.Spreadsheet.VerticalTextAlignment; -using Vml = DocumentFormat.OpenXml.Vml; -using Xdr = DocumentFormat.OpenXml.Drawing.Spreadsheet; - -namespace ClosedXML.Excel -{ - public partial class XLWorkbook - { - private const Double ColumnWidthOffset = 0.710625; - - //private Dictionary sharedStrings; - //private Dictionary context.SharedStyles; - - private static readonly EnumValue CvSharedString = new EnumValue(CellValues.SharedString); - private static readonly EnumValue CvInlineString = new EnumValue(CellValues.InlineString); - private static readonly EnumValue CvNumber = new EnumValue(CellValues.Number); - private static readonly EnumValue CvDate = new EnumValue(CellValues.Date); - private static readonly EnumValue CvBoolean = new EnumValue(CellValues.Boolean); - - private static EnumValue GetCellValueType(XLCell xlCell) - { - switch (xlCell.DataType) - { - case XLCellValues.Text: - { - return xlCell.ShareString ? CvSharedString : CvInlineString; - } - case XLCellValues.Number: - return CvNumber; - - case XLCellValues.DateTime: - return CvDate; - - case XLCellValues.Boolean: - return CvBoolean; - - case XLCellValues.TimeSpan: - return CvNumber; - - default: - throw new NotImplementedException(); - } - } - - private bool Validate(SpreadsheetDocument package) - { - var backupCulture = Thread.CurrentThread.CurrentCulture; - - IEnumerable errors; - try - { - Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; - var validator = new OpenXmlValidator(); - errors = validator.Validate(package); - } - finally - { - Thread.CurrentThread.CurrentCulture = backupCulture; - } - - if (errors.Any()) - { - var message = string.Join("\r\n", errors.Select(e => string.Format("{0} in {1}", e.Description, e.Path.XPath)).ToArray()); - throw new ApplicationException(message); - } - return true; - } - - private void CreatePackage(String filePath, SpreadsheetDocumentType spreadsheetDocumentType, bool validate, bool evaluateFormulae) - { - PathHelper.CreateDirectory(Path.GetDirectoryName(filePath)); - var package = File.Exists(filePath) - ? SpreadsheetDocument.Open(filePath, true) - : SpreadsheetDocument.Create(filePath, spreadsheetDocumentType); - - using (package) - { - CreateParts(package, evaluateFormulae); - if (validate) Validate(package); - } - } - - private void CreatePackage(Stream stream, bool newStream, SpreadsheetDocumentType spreadsheetDocumentType, bool validate, bool evaluateFormulae) - { - var package = newStream - ? SpreadsheetDocument.Create(stream, spreadsheetDocumentType) - : SpreadsheetDocument.Open(stream, true); - - using (package) - { - CreateParts(package, evaluateFormulae); - if (validate) Validate(package); - } - } - - // http://blogs.msdn.com/b/vsod/archive/2010/02/05/how-to-delete-a-worksheet-from-excel-using-open-xml-sdk-2-0.aspx - private void DeleteSheetAndDependencies(WorkbookPart wbPart, string sheetId) - { - //Get the SheetToDelete from workbook.xml - Sheet worksheet = wbPart.Workbook.Descendants().Where(s => s.Id == sheetId).FirstOrDefault(); - if (worksheet == null) - { } - - string sheetName = worksheet.Name; - // Get the pivot Table Parts - IEnumerable pvtTableCacheParts = wbPart.PivotTableCacheDefinitionParts; - Dictionary pvtTableCacheDefinationPart = new Dictionary(); - foreach (PivotTableCacheDefinitionPart Item in pvtTableCacheParts) - { - PivotCacheDefinition pvtCacheDef = Item.PivotCacheDefinition; - //Check if this CacheSource is linked to SheetToDelete - var pvtCahce = pvtCacheDef.Descendants().Where(s => s.WorksheetSource.Sheet == sheetName); - if (pvtCahce.Count() > 0) - { - pvtTableCacheDefinationPart.Add(Item, Item.ToString()); - } - } - foreach (var Item in pvtTableCacheDefinationPart) - { - wbPart.DeletePart(Item.Key); - } - - // Remove the sheet reference from the workbook. - WorksheetPart worksheetPart = (WorksheetPart)(wbPart.GetPartById(sheetId)); - worksheet.Remove(); - - // Delete the worksheet part. - wbPart.DeletePart(worksheetPart); - - //Get the DefinedNames - var definedNames = wbPart.Workbook.Descendants().FirstOrDefault(); - if (definedNames != null) - { - List defNamesToDelete = new List(); - - foreach (DefinedName Item in definedNames) - { - // This condition checks to delete only those names which are part of Sheet in question - if (Item.Text.Contains(worksheet.Name + "!")) - defNamesToDelete.Add(Item); - } - - foreach (DefinedName Item in defNamesToDelete) - { - Item.Remove(); - } - } - // Get the CalculationChainPart - //Note: An instance of this part type contains an ordered set of references to all cells in all worksheets in the - //workbook whose value is calculated from any formula - - CalculationChainPart calChainPart; - calChainPart = wbPart.CalculationChainPart; - if (calChainPart != null) - { - var calChainEntries = calChainPart.CalculationChain.Descendants().Where(c => c.SheetId == sheetId); - List calcsToDelete = new List(); - foreach (CalculationCell Item in calChainEntries) - { - calcsToDelete.Add(Item); - } - - foreach (CalculationCell Item in calcsToDelete) - { - Item.Remove(); - } - - if (calChainPart.CalculationChain.Count() == 0) - { - wbPart.DeletePart(calChainPart); - } - } - } - - // Adds child parts and generates content of the specified part. - private void CreateParts(SpreadsheetDocument document, bool evaluateFormulae) - { - var context = new SaveContext(); - - var workbookPart = document.WorkbookPart ?? document.AddWorkbookPart(); - - var worksheets = WorksheetsInternal; - - var partsToRemove = workbookPart.Parts.Where(s => worksheets.Deleted.Contains(s.RelationshipId)).ToList(); - - var pivotCacheDefinitionsToRemove = partsToRemove.SelectMany(s => ((WorksheetPart)s.OpenXmlPart).PivotTableParts.Select(pt => pt.PivotTableCacheDefinitionPart)).Distinct().ToList(); - pivotCacheDefinitionsToRemove.ForEach(c => workbookPart.DeletePart(c)); - - if (workbookPart.Workbook != null && workbookPart.Workbook.PivotCaches != null) - { - var pivotCachesToRemove = workbookPart.Workbook.PivotCaches.Where(pc => pivotCacheDefinitionsToRemove.Select(pcd => workbookPart.GetIdOfPart(pcd)).ToList().Contains(((PivotCache)pc).Id)).Distinct().ToList(); - pivotCachesToRemove.ForEach(c => workbookPart.Workbook.PivotCaches.RemoveChild(c)); - } - - worksheets.Deleted.ToList().ForEach(ws => DeleteSheetAndDependencies(workbookPart, ws)); - - // Ensure all RelId's have been added to the context - context.RelIdGenerator.AddValues(workbookPart.Parts.Select(p => p.RelationshipId), RelType.Workbook); - context.RelIdGenerator.AddValues(WorksheetsInternal.Cast().Where(ws => !XLHelper.IsNullOrWhiteSpace(ws.RelId)).Select(ws => ws.RelId), RelType.Workbook); - context.RelIdGenerator.AddValues(WorksheetsInternal.Cast().Where(ws => !XLHelper.IsNullOrWhiteSpace(ws.LegacyDrawingId)).Select(ws => ws.LegacyDrawingId), RelType.Workbook); - context.RelIdGenerator.AddValues(WorksheetsInternal - .Cast() - .SelectMany(ws => ws.Tables.Cast()) - .Where(t => !XLHelper.IsNullOrWhiteSpace(t.RelId)) - .Select(t => t.RelId), RelType.Workbook); - - var extendedFilePropertiesPart = document.ExtendedFilePropertiesPart ?? - document.AddNewPart( - context.RelIdGenerator.GetNext(RelType.Workbook)); - - GenerateExtendedFilePropertiesPartContent(extendedFilePropertiesPart); - - GenerateWorkbookPartContent(workbookPart, context); - - var sharedStringTablePart = workbookPart.SharedStringTablePart ?? - workbookPart.AddNewPart( - context.RelIdGenerator.GetNext(RelType.Workbook)); - - GenerateSharedStringTablePartContent(sharedStringTablePart, context); - - var workbookStylesPart = workbookPart.WorkbookStylesPart ?? - workbookPart.AddNewPart( - context.RelIdGenerator.GetNext(RelType.Workbook)); - - GenerateWorkbookStylesPartContent(workbookStylesPart, context); - - foreach (var worksheet in WorksheetsInternal.Cast().OrderBy(w => w.Position)) - { - //context.RelIdGenerator.Reset(RelType.); - WorksheetPart worksheetPart; - var wsRelId = worksheet.RelId; - if (workbookPart.Parts.Any(p => p.RelationshipId == wsRelId)) - { - worksheetPart = (WorksheetPart)workbookPart.GetPartById(wsRelId); - var wsPartsToRemove = worksheetPart.TableDefinitionParts.ToList(); - wsPartsToRemove.ForEach(tdp => worksheetPart.DeletePart(tdp)); - } - else - worksheetPart = workbookPart.AddNewPart(wsRelId); - - context.RelIdGenerator.AddValues(worksheetPart.HyperlinkRelationships.Select(hr => hr.Id), RelType.Workbook); - context.RelIdGenerator.AddValues(worksheetPart.Parts.Select(p => p.RelationshipId), RelType.Workbook); - if (worksheetPart.DrawingsPart != null) - context.RelIdGenerator.AddValues(worksheetPart.DrawingsPart.Parts.Select(p => p.RelationshipId), RelType.Workbook); - - // delete comment related parts (todo: review) - DeleteComments(worksheetPart, worksheet, context); - - if (worksheet.Internals.CellsCollection.GetCells(c => c.HasComment).Any()) - { - var id = context.RelIdGenerator.GetNext(RelType.Workbook); - var worksheetCommentsPart = - worksheetPart.AddNewPart(id); - - GenerateWorksheetCommentsPartContent(worksheetCommentsPart, worksheet); - - //VmlDrawingPart vmlDrawingPart = worksheetPart.AddNewPart(worksheet.LegacyDrawingId); - var vmlDrawingPart = worksheetPart.VmlDrawingParts.FirstOrDefault(); - if (vmlDrawingPart == null) - { - if (XLHelper.IsNullOrWhiteSpace(worksheet.LegacyDrawingId)) - { - worksheet.LegacyDrawingId = context.RelIdGenerator.GetNext(RelType.Workbook); - worksheet.LegacyDrawingIsNew = true; - } - - vmlDrawingPart = worksheetPart.AddNewPart(worksheet.LegacyDrawingId); - } - GenerateVmlDrawingPartContent(vmlDrawingPart, worksheet, context); - } - - GenerateWorksheetPartContent(worksheetPart, worksheet, evaluateFormulae, context); - - if (worksheet.PivotTables.Any()) - { - GeneratePivotTables(workbookPart, worksheetPart, worksheet, context); - } - - // Remove any orphaned references - maybe more types? - foreach (var orphan in worksheetPart.Worksheet.OfType().Where(lg => !worksheetPart.Parts.Any(p => p.RelationshipId == lg.Id))) - worksheetPart.Worksheet.RemoveChild(orphan); - - foreach (var orphan in worksheetPart.Worksheet.OfType().Where(d => !worksheetPart.Parts.Any(p => p.RelationshipId == d.Id))) - worksheetPart.Worksheet.RemoveChild(orphan); - } - - // Remove empty pivot cache part - if (workbookPart.Workbook.PivotCaches != null && !workbookPart.Workbook.PivotCaches.Any()) - workbookPart.Workbook.RemoveChild(workbookPart.Workbook.PivotCaches); - - GenerateCalculationChainPartContent(workbookPart, context); - - if (workbookPart.ThemePart == null) - { - var themePart = workbookPart.AddNewPart(context.RelIdGenerator.GetNext(RelType.Workbook)); - GenerateThemePartContent(themePart); - } - - if (CustomProperties.Any()) - { - document.GetPartsOfType().ToList().ForEach(p => document.DeletePart(p)); - var customFilePropertiesPart = - document.AddNewPart(context.RelIdGenerator.GetNext(RelType.Workbook)); - - GenerateCustomFilePropertiesPartContent(customFilePropertiesPart); - } - SetPackageProperties(document); - } - - private void DeleteComments(WorksheetPart worksheetPart, XLWorksheet worksheet, SaveContext context) - { - // We have the comments so we can delete the comments part - worksheetPart.DeletePart(worksheetPart.WorksheetCommentsPart); - var vmlDrawingPart = worksheetPart.VmlDrawingParts.FirstOrDefault(); - - // Only delete the VmlDrawingParts for comments. - if (vmlDrawingPart != null) - { - var xdoc = XDocumentExtensions.Load(vmlDrawingPart.GetStream(FileMode.Open)); - //xdoc.Root.Elements().Where(e => e.Name.LocalName == "shapelayout").Remove(); - xdoc.Root.Elements().Where( - e => e.Name.LocalName == "shapetype" && (string)e.Attribute("id") == @"_x0000_t202").Remove(); - xdoc.Root.Elements().Where( - e => e.Name.LocalName == "shape" && (string)e.Attribute("type") == @"#_x0000_t202").Remove(); - var imageParts = vmlDrawingPart.ImageParts.ToList(); - var legacyParts = vmlDrawingPart.LegacyDiagramTextParts.ToList(); - var rId = worksheetPart.GetIdOfPart(vmlDrawingPart); - worksheet.LegacyDrawingId = rId; - worksheetPart.ChangeIdOfPart(vmlDrawingPart, "xxRRxx"); // Anything will do for the new relationship id - // we just want it alive enough to create the copy - - var hasShapes = xdoc.Root.Elements().Any(e => e.Name.LocalName == "shape" || e.Name.LocalName == "group"); - - VmlDrawingPart vmlDrawingPartNew = null; - var hasNewPart = (imageParts.Count > 0 || legacyParts.Count > 0 || hasShapes); - if (hasNewPart) - { - vmlDrawingPartNew = worksheetPart.AddNewPart(rId); - - using (var writer = new XmlTextWriter(vmlDrawingPartNew.GetStream(FileMode.Create), Encoding.UTF8)) - { - writer.WriteRaw(xdoc.ToString()); - } - - imageParts.ForEach(p => vmlDrawingPartNew.AddPart(p, vmlDrawingPart.GetIdOfPart(p))); - legacyParts.ForEach(p => vmlDrawingPartNew.AddPart(p, vmlDrawingPart.GetIdOfPart(p))); - } - - worksheetPart.DeletePart(vmlDrawingPart); - - if (hasNewPart && rId != worksheetPart.GetIdOfPart(vmlDrawingPartNew)) - worksheetPart.ChangeIdOfPart(vmlDrawingPartNew, rId); - } - } - - private static void GenerateTables(XLWorksheet worksheet, WorksheetPart worksheetPart, SaveContext context) - { - worksheetPart.Worksheet.RemoveAllChildren(); - - if (!worksheet.Tables.Any()) return; - - foreach (var table in worksheet.Tables) - { - var tableRelId = context.RelIdGenerator.GetNext(RelType.Workbook); - - var xlTable = (XLTable)table; - xlTable.RelId = tableRelId; - - var tableDefinitionPart = worksheetPart.AddNewPart(tableRelId); - GenerateTableDefinitionPartContent(tableDefinitionPart, xlTable, context); - } - } - - private void GenerateExtendedFilePropertiesPartContent(ExtendedFilePropertiesPart extendedFilePropertiesPart) - { - if (extendedFilePropertiesPart.Properties == null) - extendedFilePropertiesPart.Properties = new Properties(); - - var properties = extendedFilePropertiesPart.Properties; - if ( - !properties.NamespaceDeclarations.Contains(new KeyValuePair("vt", - "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"))) - { - properties.AddNamespaceDeclaration("vt", - "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"); - } - - if (properties.Application == null) - properties.AppendChild(new Application { Text = "Microsoft Excel" }); - - if (properties.DocumentSecurity == null) - properties.AppendChild(new DocumentSecurity { Text = "0" }); - - if (properties.ScaleCrop == null) - properties.AppendChild(new ScaleCrop { Text = "false" }); - - if (properties.HeadingPairs == null) - properties.HeadingPairs = new HeadingPairs(); - - if (properties.TitlesOfParts == null) - properties.TitlesOfParts = new TitlesOfParts(); - - properties.HeadingPairs.VTVector = new VTVector { BaseType = VectorBaseValues.Variant }; - - properties.TitlesOfParts.VTVector = new VTVector { BaseType = VectorBaseValues.Lpstr }; - - var vTVectorOne = properties.HeadingPairs.VTVector; - - var vTVectorTwo = properties.TitlesOfParts.VTVector; - - var modifiedWorksheets = - ((IEnumerable)WorksheetsInternal).Select(w => new { w.Name, Order = w.Position }).ToList(); - var modifiedNamedRanges = GetModifiedNamedRanges(); - var modifiedWorksheetsCount = modifiedWorksheets.Count; - var modifiedNamedRangesCount = modifiedNamedRanges.Count; - - InsertOnVtVector(vTVectorOne, "Worksheets", 0, modifiedWorksheetsCount.ToString()); - InsertOnVtVector(vTVectorOne, "Named Ranges", 2, modifiedNamedRangesCount.ToString()); - - vTVectorTwo.Size = (UInt32)(modifiedNamedRangesCount + modifiedWorksheetsCount); - - foreach ( - var vTlpstr3 in modifiedWorksheets.OrderBy(w => w.Order).Select(w => new VTLPSTR { Text = w.Name })) - vTVectorTwo.AppendChild(vTlpstr3); - - foreach (var vTlpstr7 in modifiedNamedRanges.Select(nr => new VTLPSTR { Text = nr })) - vTVectorTwo.AppendChild(vTlpstr7); - - if (Properties.Manager != null) - { - if (!XLHelper.IsNullOrWhiteSpace(Properties.Manager)) - { - if (properties.Manager == null) - properties.Manager = new Manager(); - - properties.Manager.Text = Properties.Manager; - } - else - properties.Manager = null; - } - - if (Properties.Company == null) return; - - if (!XLHelper.IsNullOrWhiteSpace(Properties.Company)) - { - if (properties.Company == null) - properties.Company = new Company(); - - properties.Company.Text = Properties.Company; - } - else - properties.Company = null; - } - - private static void InsertOnVtVector(VTVector vTVector, String property, Int32 index, String text) - { - var m = from e1 in vTVector.Elements() - where e1.Elements().Any(e2 => e2.Text == property) - select e1; - if (!m.Any()) - { - if (vTVector.Size == null) - vTVector.Size = new UInt32Value(0U); - - vTVector.Size += 2U; - var variant1 = new Variant(); - var vTlpstr1 = new VTLPSTR { Text = property }; - variant1.AppendChild(vTlpstr1); - vTVector.InsertAt(variant1, index); - - var variant2 = new Variant(); - var vTInt321 = new VTInt32(); - variant2.AppendChild(vTInt321); - vTVector.InsertAt(variant2, index + 1); - } - - var targetIndex = 0; - foreach (var e in vTVector.Elements()) - { - if (e.Elements().Any(e2 => e2.Text == property)) - { - vTVector.ElementAt(targetIndex + 1).GetFirstChild().Text = text; - break; - } - targetIndex++; - } - } - - private List GetModifiedNamedRanges() - { - var namedRanges = new List(); - foreach (var w in WorksheetsInternal) - { - var wName = w.Name; - namedRanges.AddRange(w.NamedRanges.Select(n => wName + "!" + n.Name)); - namedRanges.Add(w.Name + "!Print_Area"); - namedRanges.Add(w.Name + "!Print_Titles"); - } - namedRanges.AddRange(NamedRanges.Select(n => n.Name)); - return namedRanges; - } - - private void GenerateWorkbookPartContent(WorkbookPart workbookPart, SaveContext context) - { - if (workbookPart.Workbook == null) - workbookPart.Workbook = new Workbook(); - - var workbook = workbookPart.Workbook; - if ( - !workbook.NamespaceDeclarations.Contains(new KeyValuePair("r", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships"))) - { - workbook.AddNamespaceDeclaration("r", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); - } - - #region WorkbookProperties - - if (workbook.WorkbookProperties == null) - workbook.WorkbookProperties = new WorkbookProperties(); - - if (workbook.WorkbookProperties.CodeName == null) - workbook.WorkbookProperties.CodeName = "ThisWorkbook"; - - if (Use1904DateSystem) - workbook.WorkbookProperties.Date1904 = true; - - #endregion WorkbookProperties - - #region WorkbookProtection - - if (LockStructure || LockWindows) - { - if (workbook.WorkbookProtection == null) - workbook.WorkbookProtection = new WorkbookProtection(); - - workbook.WorkbookProtection.LockStructure = LockStructure; - workbook.WorkbookProtection.LockWindows = LockWindows; - - if (LockPassword != null) - workbook.WorkbookProtection.WorkbookPassword = LockPassword; - } - else - { - workbook.WorkbookProtection = null; - } - - #endregion - - if (workbook.BookViews == null) - workbook.BookViews = new BookViews(); - - if (workbook.Sheets == null) - workbook.Sheets = new Sheets(); - - var worksheets = WorksheetsInternal; - workbook.Sheets.Elements().Where(s => worksheets.Deleted.Contains(s.Id)).ToList().ForEach( - s => s.Remove()); - - foreach (var sheet in workbook.Sheets.Elements()) - { - var sheetId = (Int32)sheet.SheetId.Value; - - if (WorksheetsInternal.All(w => w.SheetId != sheetId)) continue; - - var wks = WorksheetsInternal.Single(w => w.SheetId == sheetId); - wks.RelId = sheet.Id; - sheet.Name = wks.Name; - } - - foreach (var xlSheet in WorksheetsInternal.Cast().OrderBy(w => w.Position)) - { - string rId; - if (xlSheet.SheetId == 0 && XLHelper.IsNullOrWhiteSpace(xlSheet.RelId)) - { - rId = context.RelIdGenerator.GetNext(RelType.Workbook); - - while (WorksheetsInternal.Cast().Any(w => w.SheetId == Int32.Parse(rId.Substring(3)))) - rId = context.RelIdGenerator.GetNext(RelType.Workbook); - - xlSheet.SheetId = Int32.Parse(rId.Substring(3)); - xlSheet.RelId = rId; - } - else - { - if (XLHelper.IsNullOrWhiteSpace(xlSheet.RelId)) - { - rId = String.Format("rId{0}", xlSheet.SheetId); - context.RelIdGenerator.AddValues(new List { rId }, RelType.Workbook); - } - else - rId = xlSheet.RelId; - } - - if (!workbook.Sheets.Cast().Any(s => s.Id == rId)) - { - var newSheet = new Sheet - { - Name = xlSheet.Name, - Id = rId, - SheetId = (UInt32)xlSheet.SheetId - }; - - workbook.Sheets.AppendChild(newSheet); - } - } - - var sheetElements = from sheet in workbook.Sheets.Elements() - join worksheet in ((IEnumerable)WorksheetsInternal) on sheet.Id.Value - equals worksheet.RelId - orderby worksheet.Position - select sheet; - - UInt32 firstSheetVisible = 0; - var activeTab = - (from us in UnsupportedSheets where us.IsActive select (UInt32)us.Position - 1).FirstOrDefault(); - var foundVisible = false; - - var totalSheets = sheetElements.Count() + UnsupportedSheets.Count; - for (var p = 1; p <= totalSheets; p++) - { - if (UnsupportedSheets.All(us => us.Position != p)) - { - var sheet = sheetElements.ElementAt(p - UnsupportedSheets.Count(us => us.Position <= p) - 1); - workbook.Sheets.RemoveChild(sheet); - workbook.Sheets.AppendChild(sheet); - var xlSheet = Worksheet(sheet.Name); - if (xlSheet.Visibility != XLWorksheetVisibility.Visible) - sheet.State = xlSheet.Visibility.ToOpenXml(); - - if (foundVisible) continue; - - if (sheet.State == null || sheet.State == SheetStateValues.Visible) - foundVisible = true; - else - firstSheetVisible++; - } - else - { - var sheetId = UnsupportedSheets.First(us => us.Position == p).SheetId; - var sheet = workbook.Sheets.Elements().First(s => s.SheetId == sheetId); - workbook.Sheets.RemoveChild(sheet); - workbook.Sheets.AppendChild(sheet); - } - } - - var workbookView = workbook.BookViews.Elements().FirstOrDefault(); - - if (activeTab == 0) - { - activeTab = firstSheetVisible; - foreach (var ws in worksheets) - { - if (!ws.TabActive) continue; - - activeTab = (UInt32)(ws.Position - 1); - break; - } - } - - if (workbookView == null) - { - workbookView = new WorkbookView { ActiveTab = activeTab, FirstSheet = firstSheetVisible }; - workbook.BookViews.AppendChild(workbookView); - } - else - { - workbookView.ActiveTab = activeTab; - workbookView.FirstSheet = firstSheetVisible; - } - - var definedNames = new DefinedNames(); - foreach (var worksheet in WorksheetsInternal) - { - var wsSheetId = (UInt32)worksheet.SheetId; - UInt32 sheetId = 0; - foreach (var s in workbook.Sheets.Elements().TakeWhile(s => s.SheetId != wsSheetId)) - { - sheetId++; - } - - if (worksheet.PageSetup.PrintAreas.Any()) - { - var definedName = new DefinedName { Name = "_xlnm.Print_Area", LocalSheetId = sheetId }; - var worksheetName = worksheet.Name; - var definedNameText = worksheet.PageSetup.PrintAreas.Aggregate(String.Empty, - (current, printArea) => - current + - ("'" + worksheetName + "'!" + - printArea.RangeAddress. - FirstAddress.ToStringFixed( - XLReferenceStyle.A1) + - ":" + - printArea.RangeAddress. - LastAddress.ToStringFixed( - XLReferenceStyle.A1) + - ",")); - definedName.Text = definedNameText.Substring(0, definedNameText.Length - 1); - definedNames.AppendChild(definedName); - } - - if (worksheet.AutoFilter.Enabled) - { - var definedName = new DefinedName - { - Name = "_xlnm._FilterDatabase", - LocalSheetId = sheetId, - Text = "'" + worksheet.Name + "'!" + - worksheet.AutoFilter.Range.RangeAddress.FirstAddress.ToStringFixed( - XLReferenceStyle.A1) + - ":" + - worksheet.AutoFilter.Range.RangeAddress.LastAddress.ToStringFixed( - XLReferenceStyle.A1), - Hidden = BooleanValue.FromBoolean(true) - }; - definedNames.AppendChild(definedName); - } - - foreach (var nr in worksheet.NamedRanges.Where(n => n.Name != "_xlnm._FilterDatabase")) - { - var definedName = new DefinedName - { - Name = nr.Name, - LocalSheetId = sheetId, - Text = nr.ToString() - }; - - if (!nr.Visible) - definedName.Hidden = BooleanValue.FromBoolean(true); - - if (!XLHelper.IsNullOrWhiteSpace(nr.Comment)) - definedName.Comment = nr.Comment; - definedNames.AppendChild(definedName); - } - - var definedNameTextRow = String.Empty; - var definedNameTextColumn = String.Empty; - if (worksheet.PageSetup.FirstRowToRepeatAtTop > 0) - { - definedNameTextRow = "'" + worksheet.Name + "'!" + worksheet.PageSetup.FirstRowToRepeatAtTop - + ":" + worksheet.PageSetup.LastRowToRepeatAtTop; - } - if (worksheet.PageSetup.FirstColumnToRepeatAtLeft > 0) - { - var minColumn = worksheet.PageSetup.FirstColumnToRepeatAtLeft; - var maxColumn = worksheet.PageSetup.LastColumnToRepeatAtLeft; - definedNameTextColumn = "'" + worksheet.Name + "'!" + - XLHelper.GetColumnLetterFromNumber(minColumn) - + ":" + XLHelper.GetColumnLetterFromNumber(maxColumn); - } - - string titles; - if (definedNameTextColumn.Length > 0) - { - titles = definedNameTextColumn; - if (definedNameTextRow.Length > 0) - titles += "," + definedNameTextRow; - } - else - titles = definedNameTextRow; - - if (titles.Length <= 0) continue; - - var definedName2 = new DefinedName - { - Name = "_xlnm.Print_Titles", - LocalSheetId = sheetId, - Text = titles - }; - - definedNames.AppendChild(definedName2); - } - - foreach (var nr in NamedRanges) - { - var definedName = new DefinedName - { - Name = nr.Name, - Text = nr.ToString() - }; - - if (!nr.Visible) - definedName.Hidden = BooleanValue.FromBoolean(true); - - if (!XLHelper.IsNullOrWhiteSpace(nr.Comment)) - definedName.Comment = nr.Comment; - definedNames.AppendChild(definedName); - } - - workbook.DefinedNames = definedNames; - - if (workbook.CalculationProperties == null) - workbook.CalculationProperties = new CalculationProperties { CalculationId = 125725U }; - - if (CalculateMode == XLCalculateMode.Default) - workbook.CalculationProperties.CalculationMode = null; - else - workbook.CalculationProperties.CalculationMode = CalculateMode.ToOpenXml(); - - if (ReferenceStyle == XLReferenceStyle.Default) - workbook.CalculationProperties.ReferenceMode = null; - else - workbook.CalculationProperties.ReferenceMode = ReferenceStyle.ToOpenXml(); - - if (CalculationOnSave) workbook.CalculationProperties.CalculationOnSave = CalculationOnSave; - if (ForceFullCalculation) workbook.CalculationProperties.ForceFullCalculation = ForceFullCalculation; - if (FullCalculationOnLoad) workbook.CalculationProperties.FullCalculationOnLoad = FullCalculationOnLoad; - if (FullPrecision) workbook.CalculationProperties.FullPrecision = FullPrecision; - } - - private void GenerateSharedStringTablePartContent(SharedStringTablePart sharedStringTablePart, - SaveContext context) - { - // Call all table headers to make sure their names are filled - var x = 0; - Worksheets.ForEach(w => w.Tables.ForEach(t => x = (t as XLTable).FieldNames.Count)); - - sharedStringTablePart.SharedStringTable = new SharedStringTable { Count = 0, UniqueCount = 0 }; - - var stringId = 0; - - var newStrings = new Dictionary(); - var newRichStrings = new Dictionary(); - foreach ( - var c in - Worksheets.Cast().SelectMany( - w => - w.Internals.CellsCollection.GetCells( - c => ((c.DataType == XLCellValues.Text && c.ShareString) || c.HasRichText) - && (c as XLCell).InnerText.Length > 0 - && XLHelper.IsNullOrWhiteSpace(c.FormulaA1) - ))) - { - c.DataType = XLCellValues.Text; - if (c.HasRichText) - { - if (newRichStrings.ContainsKey(c.RichText)) - c.SharedStringId = newRichStrings[c.RichText]; - else - { - var sharedStringItem = new SharedStringItem(); - foreach (var rt in c.RichText.Where(r => !String.IsNullOrEmpty(r.Text))) - { - sharedStringItem.Append(GetRun(rt)); - } - - if (c.RichText.HasPhonetics) - { - foreach (var p in c.RichText.Phonetics) - { - var phoneticRun = new PhoneticRun - { - BaseTextStartIndex = (UInt32)p.Start, - EndingBaseIndex = (UInt32)p.End - }; - - var text = new Text { Text = p.Text }; - if (p.Text.PreserveSpaces()) - text.Space = SpaceProcessingModeValues.Preserve; - - phoneticRun.Append(text); - sharedStringItem.Append(phoneticRun); - } - var f = new XLFont(null, c.RichText.Phonetics); - if (!context.SharedFonts.ContainsKey(f)) - context.SharedFonts.Add(f, new FontInfo { Font = f }); - - var phoneticProperties = new PhoneticProperties - { - FontId = - context.SharedFonts[ - new XLFont(null, c.RichText.Phonetics)]. - FontId - }; - if (c.RichText.Phonetics.Alignment != XLPhoneticAlignment.Left) - phoneticProperties.Alignment = c.RichText.Phonetics.Alignment.ToOpenXml(); - if (c.RichText.Phonetics.Type != XLPhoneticType.FullWidthKatakana) - phoneticProperties.Type = c.RichText.Phonetics.Type.ToOpenXml(); - - sharedStringItem.Append(phoneticProperties); - } - - sharedStringTablePart.SharedStringTable.Append(sharedStringItem); - sharedStringTablePart.SharedStringTable.Count += 1; - sharedStringTablePart.SharedStringTable.UniqueCount += 1; - - newRichStrings.Add(c.RichText, stringId); - c.SharedStringId = stringId; - - stringId++; - } - } - else - { - if (newStrings.ContainsKey(c.Value.ToString())) - c.SharedStringId = newStrings[c.Value.ToString()]; - else - { - var s = c.Value.ToString(); - var sharedStringItem = new SharedStringItem(); - var text = new Text { Text = XmlEncoder.EncodeString(s) }; - if (!s.Trim().Equals(s)) - text.Space = SpaceProcessingModeValues.Preserve; - sharedStringItem.Append(text); - sharedStringTablePart.SharedStringTable.Append(sharedStringItem); - sharedStringTablePart.SharedStringTable.Count += 1; - sharedStringTablePart.SharedStringTable.UniqueCount += 1; - - newStrings.Add(c.Value.ToString(), stringId); - c.SharedStringId = stringId; - - stringId++; - } - } - } - } - - private static Run GetRun(IXLRichString rt) - { - var run = new Run(); - - var runProperties = new RunProperties(); - - var bold = rt.Bold ? new Bold() : null; - var italic = rt.Italic ? new Italic() : null; - var underline = rt.Underline != XLFontUnderlineValues.None - ? new Underline { Val = rt.Underline.ToOpenXml() } - : null; - var strike = rt.Strikethrough ? new Strike() : null; - var verticalAlignment = new VerticalTextAlignment - { Val = rt.VerticalAlignment.ToOpenXml() }; - var shadow = rt.Shadow ? new Shadow() : null; - var fontSize = new FontSize { Val = rt.FontSize }; - var color = GetNewColor(rt.FontColor); - var fontName = new RunFont { Val = rt.FontName }; - var fontFamilyNumbering = new FontFamily { Val = (Int32)rt.FontFamilyNumbering }; - - if (bold != null) runProperties.Append(bold); - if (italic != null) runProperties.Append(italic); - - if (strike != null) runProperties.Append(strike); - if (shadow != null) runProperties.Append(shadow); - if (underline != null) runProperties.Append(underline); - runProperties.Append(verticalAlignment); - - runProperties.Append(fontSize); - runProperties.Append(color); - runProperties.Append(fontName); - runProperties.Append(fontFamilyNumbering); - - var text = new Text { Text = rt.Text }; - if (rt.Text.PreserveSpaces()) - text.Space = SpaceProcessingModeValues.Preserve; - - run.Append(runProperties); - run.Append(text); - return run; - } - - private void GenerateCalculationChainPartContent(WorkbookPart workbookPart, SaveContext context) - { - var thisRelId = context.RelIdGenerator.GetNext(RelType.Workbook); - if (workbookPart.CalculationChainPart == null) - workbookPart.AddNewPart(thisRelId); - - if (workbookPart.CalculationChainPart.CalculationChain == null) - workbookPart.CalculationChainPart.CalculationChain = new CalculationChain(); - - var calculationChain = workbookPart.CalculationChainPart.CalculationChain; - calculationChain.RemoveAllChildren(); - - foreach (var worksheet in WorksheetsInternal) - { - var cellsWithoutFormulas = new HashSet(); - foreach (var c in worksheet.Internals.CellsCollection.GetCells()) - { - if (XLHelper.IsNullOrWhiteSpace(c.FormulaA1)) - cellsWithoutFormulas.Add(c.Address.ToStringRelative()); - else - { - if (c.FormulaA1.StartsWith("{")) - { - var cc = new CalculationCell - { - CellReference = c.Address.ToString(), - SheetId = worksheet.SheetId - }; - - if (c.FormulaReference == null) - c.FormulaReference = c.AsRange().RangeAddress; - if (c.FormulaReference.FirstAddress.Equals(c.Address)) - { - cc.Array = true; - calculationChain.AppendChild(cc); - calculationChain.AppendChild(new CalculationCell { CellReference = c.Address.ToString(), InChildChain = true }); - } - else - { - calculationChain.AppendChild(cc); - } - } - else - { - calculationChain.AppendChild(new CalculationCell - { - CellReference = c.Address.ToString(), - SheetId = worksheet.SheetId - }); - } - } - } - - //var cCellsToRemove = new List(); - var m = from cc in calculationChain.Elements() - where !(cc.SheetId != null || cc.InChildChain != null) - && calculationChain.Elements() - .Where(c1 => c1.SheetId != null) - .Select(c1 => c1.CellReference.Value) - .Contains(cc.CellReference.Value) - || cellsWithoutFormulas.Contains(cc.CellReference.Value) - select cc; - //m.ToList().ForEach(cc => cCellsToRemove.Add(cc)); - m.ToList().ForEach(cc => calculationChain.RemoveChild(cc)); - } - - if (!calculationChain.Any()) - workbookPart.DeletePart(workbookPart.CalculationChainPart); - } - - private void GenerateThemePartContent(ThemePart themePart) - { - var theme1 = new Theme { Name = "Office Theme" }; - theme1.AddNamespaceDeclaration("a", "http://schemas.openxmlformats.org/drawingml/2006/main"); - - var themeElements1 = new ThemeElements(); - - var colorScheme1 = new ColorScheme { Name = "Office" }; - - var dark1Color1 = new Dark1Color(); - var systemColor1 = new SystemColor - { - Val = SystemColorValues.WindowText, - LastColor = Theme.Text1.Color.ToHex().Substring(2) - }; - - dark1Color1.AppendChild(systemColor1); - - var light1Color1 = new Light1Color(); - var systemColor2 = new SystemColor - { - Val = SystemColorValues.Window, - LastColor = Theme.Background1.Color.ToHex().Substring(2) - }; - - light1Color1.AppendChild(systemColor2); - - var dark2Color1 = new Dark2Color(); - var rgbColorModelHex1 = new RgbColorModelHex { Val = Theme.Text2.Color.ToHex().Substring(2) }; - - dark2Color1.AppendChild(rgbColorModelHex1); - - var light2Color1 = new Light2Color(); - var rgbColorModelHex2 = new RgbColorModelHex { Val = Theme.Background2.Color.ToHex().Substring(2) }; - - light2Color1.AppendChild(rgbColorModelHex2); - - var accent1Color1 = new Accent1Color(); - var rgbColorModelHex3 = new RgbColorModelHex { Val = Theme.Accent1.Color.ToHex().Substring(2) }; - - accent1Color1.AppendChild(rgbColorModelHex3); - - var accent2Color1 = new Accent2Color(); - var rgbColorModelHex4 = new RgbColorModelHex { Val = Theme.Accent2.Color.ToHex().Substring(2) }; - - accent2Color1.AppendChild(rgbColorModelHex4); - - var accent3Color1 = new Accent3Color(); - var rgbColorModelHex5 = new RgbColorModelHex { Val = Theme.Accent3.Color.ToHex().Substring(2) }; - - accent3Color1.AppendChild(rgbColorModelHex5); - - var accent4Color1 = new Accent4Color(); - var rgbColorModelHex6 = new RgbColorModelHex { Val = Theme.Accent4.Color.ToHex().Substring(2) }; - - accent4Color1.AppendChild(rgbColorModelHex6); - - var accent5Color1 = new Accent5Color(); - var rgbColorModelHex7 = new RgbColorModelHex { Val = Theme.Accent5.Color.ToHex().Substring(2) }; - - accent5Color1.AppendChild(rgbColorModelHex7); - - var accent6Color1 = new Accent6Color(); - var rgbColorModelHex8 = new RgbColorModelHex { Val = Theme.Accent6.Color.ToHex().Substring(2) }; - - accent6Color1.AppendChild(rgbColorModelHex8); - - var hyperlink1 = new DocumentFormat.OpenXml.Drawing.Hyperlink(); - var rgbColorModelHex9 = new RgbColorModelHex { Val = Theme.Hyperlink.Color.ToHex().Substring(2) }; - - hyperlink1.AppendChild(rgbColorModelHex9); - - var followedHyperlinkColor1 = new FollowedHyperlinkColor(); - var rgbColorModelHex10 = new RgbColorModelHex { Val = Theme.FollowedHyperlink.Color.ToHex().Substring(2) }; - - followedHyperlinkColor1.AppendChild(rgbColorModelHex10); - - colorScheme1.AppendChild(dark1Color1); - colorScheme1.AppendChild(light1Color1); - colorScheme1.AppendChild(dark2Color1); - colorScheme1.AppendChild(light2Color1); - colorScheme1.AppendChild(accent1Color1); - colorScheme1.AppendChild(accent2Color1); - colorScheme1.AppendChild(accent3Color1); - colorScheme1.AppendChild(accent4Color1); - colorScheme1.AppendChild(accent5Color1); - colorScheme1.AppendChild(accent6Color1); - colorScheme1.AppendChild(hyperlink1); - colorScheme1.AppendChild(followedHyperlinkColor1); - - var fontScheme2 = new FontScheme { Name = "Office" }; - - var majorFont1 = new MajorFont(); - var latinFont1 = new LatinFont { Typeface = "Cambria" }; - var eastAsianFont1 = new EastAsianFont { Typeface = "" }; - var complexScriptFont1 = new ComplexScriptFont { Typeface = "" }; - var supplementalFont1 = new SupplementalFont { Script = "Jpan", Typeface = "MS Pゴシック" }; - var supplementalFont2 = new SupplementalFont { Script = "Hang", Typeface = "맑은 고딕" }; - var supplementalFont3 = new SupplementalFont { Script = "Hans", Typeface = "宋体" }; - var supplementalFont4 = new SupplementalFont { Script = "Hant", Typeface = "新細明體" }; - var supplementalFont5 = new SupplementalFont { Script = "Arab", Typeface = "Times New Roman" }; - var supplementalFont6 = new SupplementalFont { Script = "Hebr", Typeface = "Times New Roman" }; - var supplementalFont7 = new SupplementalFont { Script = "Thai", Typeface = "Tahoma" }; - var supplementalFont8 = new SupplementalFont { Script = "Ethi", Typeface = "Nyala" }; - var supplementalFont9 = new SupplementalFont { Script = "Beng", Typeface = "Vrinda" }; - var supplementalFont10 = new SupplementalFont { Script = "Gujr", Typeface = "Shruti" }; - var supplementalFont11 = new SupplementalFont { Script = "Khmr", Typeface = "MoolBoran" }; - var supplementalFont12 = new SupplementalFont { Script = "Knda", Typeface = "Tunga" }; - var supplementalFont13 = new SupplementalFont { Script = "Guru", Typeface = "Raavi" }; - var supplementalFont14 = new SupplementalFont { Script = "Cans", Typeface = "Euphemia" }; - var supplementalFont15 = new SupplementalFont { Script = "Cher", Typeface = "Plantagenet Cherokee" }; - var supplementalFont16 = new SupplementalFont { Script = "Yiii", Typeface = "Microsoft Yi Baiti" }; - var supplementalFont17 = new SupplementalFont { Script = "Tibt", Typeface = "Microsoft Himalaya" }; - var supplementalFont18 = new SupplementalFont { Script = "Thaa", Typeface = "MV Boli" }; - var supplementalFont19 = new SupplementalFont { Script = "Deva", Typeface = "Mangal" }; - var supplementalFont20 = new SupplementalFont { Script = "Telu", Typeface = "Gautami" }; - var supplementalFont21 = new SupplementalFont { Script = "Taml", Typeface = "Latha" }; - var supplementalFont22 = new SupplementalFont { Script = "Syrc", Typeface = "Estrangelo Edessa" }; - var supplementalFont23 = new SupplementalFont { Script = "Orya", Typeface = "Kalinga" }; - var supplementalFont24 = new SupplementalFont { Script = "Mlym", Typeface = "Kartika" }; - var supplementalFont25 = new SupplementalFont { Script = "Laoo", Typeface = "DokChampa" }; - var supplementalFont26 = new SupplementalFont { Script = "Sinh", Typeface = "Iskoola Pota" }; - var supplementalFont27 = new SupplementalFont { Script = "Mong", Typeface = "Mongolian Baiti" }; - var supplementalFont28 = new SupplementalFont { Script = "Viet", Typeface = "Times New Roman" }; - var supplementalFont29 = new SupplementalFont { Script = "Uigh", Typeface = "Microsoft Uighur" }; - - majorFont1.AppendChild(latinFont1); - majorFont1.AppendChild(eastAsianFont1); - majorFont1.AppendChild(complexScriptFont1); - majorFont1.AppendChild(supplementalFont1); - majorFont1.AppendChild(supplementalFont2); - majorFont1.AppendChild(supplementalFont3); - majorFont1.AppendChild(supplementalFont4); - majorFont1.AppendChild(supplementalFont5); - majorFont1.AppendChild(supplementalFont6); - majorFont1.AppendChild(supplementalFont7); - majorFont1.AppendChild(supplementalFont8); - majorFont1.AppendChild(supplementalFont9); - majorFont1.AppendChild(supplementalFont10); - majorFont1.AppendChild(supplementalFont11); - majorFont1.AppendChild(supplementalFont12); - majorFont1.AppendChild(supplementalFont13); - majorFont1.AppendChild(supplementalFont14); - majorFont1.AppendChild(supplementalFont15); - majorFont1.AppendChild(supplementalFont16); - majorFont1.AppendChild(supplementalFont17); - majorFont1.AppendChild(supplementalFont18); - majorFont1.AppendChild(supplementalFont19); - majorFont1.AppendChild(supplementalFont20); - majorFont1.AppendChild(supplementalFont21); - majorFont1.AppendChild(supplementalFont22); - majorFont1.AppendChild(supplementalFont23); - majorFont1.AppendChild(supplementalFont24); - majorFont1.AppendChild(supplementalFont25); - majorFont1.AppendChild(supplementalFont26); - majorFont1.AppendChild(supplementalFont27); - majorFont1.AppendChild(supplementalFont28); - majorFont1.AppendChild(supplementalFont29); - - var minorFont1 = new MinorFont(); - var latinFont2 = new LatinFont { Typeface = "Calibri" }; - var eastAsianFont2 = new EastAsianFont { Typeface = "" }; - var complexScriptFont2 = new ComplexScriptFont { Typeface = "" }; - var supplementalFont30 = new SupplementalFont { Script = "Jpan", Typeface = "MS Pゴシック" }; - var supplementalFont31 = new SupplementalFont { Script = "Hang", Typeface = "맑은 고딕" }; - var supplementalFont32 = new SupplementalFont { Script = "Hans", Typeface = "宋体" }; - var supplementalFont33 = new SupplementalFont { Script = "Hant", Typeface = "新細明體" }; - var supplementalFont34 = new SupplementalFont { Script = "Arab", Typeface = "Arial" }; - var supplementalFont35 = new SupplementalFont { Script = "Hebr", Typeface = "Arial" }; - var supplementalFont36 = new SupplementalFont { Script = "Thai", Typeface = "Tahoma" }; - var supplementalFont37 = new SupplementalFont { Script = "Ethi", Typeface = "Nyala" }; - var supplementalFont38 = new SupplementalFont { Script = "Beng", Typeface = "Vrinda" }; - var supplementalFont39 = new SupplementalFont { Script = "Gujr", Typeface = "Shruti" }; - var supplementalFont40 = new SupplementalFont { Script = "Khmr", Typeface = "DaunPenh" }; - var supplementalFont41 = new SupplementalFont { Script = "Knda", Typeface = "Tunga" }; - var supplementalFont42 = new SupplementalFont { Script = "Guru", Typeface = "Raavi" }; - var supplementalFont43 = new SupplementalFont { Script = "Cans", Typeface = "Euphemia" }; - var supplementalFont44 = new SupplementalFont { Script = "Cher", Typeface = "Plantagenet Cherokee" }; - var supplementalFont45 = new SupplementalFont { Script = "Yiii", Typeface = "Microsoft Yi Baiti" }; - var supplementalFont46 = new SupplementalFont { Script = "Tibt", Typeface = "Microsoft Himalaya" }; - var supplementalFont47 = new SupplementalFont { Script = "Thaa", Typeface = "MV Boli" }; - var supplementalFont48 = new SupplementalFont { Script = "Deva", Typeface = "Mangal" }; - var supplementalFont49 = new SupplementalFont { Script = "Telu", Typeface = "Gautami" }; - var supplementalFont50 = new SupplementalFont { Script = "Taml", Typeface = "Latha" }; - var supplementalFont51 = new SupplementalFont { Script = "Syrc", Typeface = "Estrangelo Edessa" }; - var supplementalFont52 = new SupplementalFont { Script = "Orya", Typeface = "Kalinga" }; - var supplementalFont53 = new SupplementalFont { Script = "Mlym", Typeface = "Kartika" }; - var supplementalFont54 = new SupplementalFont { Script = "Laoo", Typeface = "DokChampa" }; - var supplementalFont55 = new SupplementalFont { Script = "Sinh", Typeface = "Iskoola Pota" }; - var supplementalFont56 = new SupplementalFont { Script = "Mong", Typeface = "Mongolian Baiti" }; - var supplementalFont57 = new SupplementalFont { Script = "Viet", Typeface = "Arial" }; - var supplementalFont58 = new SupplementalFont { Script = "Uigh", Typeface = "Microsoft Uighur" }; - - minorFont1.AppendChild(latinFont2); - minorFont1.AppendChild(eastAsianFont2); - minorFont1.AppendChild(complexScriptFont2); - minorFont1.AppendChild(supplementalFont30); - minorFont1.AppendChild(supplementalFont31); - minorFont1.AppendChild(supplementalFont32); - minorFont1.AppendChild(supplementalFont33); - minorFont1.AppendChild(supplementalFont34); - minorFont1.AppendChild(supplementalFont35); - minorFont1.AppendChild(supplementalFont36); - minorFont1.AppendChild(supplementalFont37); - minorFont1.AppendChild(supplementalFont38); - minorFont1.AppendChild(supplementalFont39); - minorFont1.AppendChild(supplementalFont40); - minorFont1.AppendChild(supplementalFont41); - minorFont1.AppendChild(supplementalFont42); - minorFont1.AppendChild(supplementalFont43); - minorFont1.AppendChild(supplementalFont44); - minorFont1.AppendChild(supplementalFont45); - minorFont1.AppendChild(supplementalFont46); - minorFont1.AppendChild(supplementalFont47); - minorFont1.AppendChild(supplementalFont48); - minorFont1.AppendChild(supplementalFont49); - minorFont1.AppendChild(supplementalFont50); - minorFont1.AppendChild(supplementalFont51); - minorFont1.AppendChild(supplementalFont52); - minorFont1.AppendChild(supplementalFont53); - minorFont1.AppendChild(supplementalFont54); - minorFont1.AppendChild(supplementalFont55); - minorFont1.AppendChild(supplementalFont56); - minorFont1.AppendChild(supplementalFont57); - minorFont1.AppendChild(supplementalFont58); - - fontScheme2.AppendChild(majorFont1); - fontScheme2.AppendChild(minorFont1); - - var formatScheme1 = new FormatScheme { Name = "Office" }; - - var fillStyleList1 = new FillStyleList(); - - var solidFill1 = new SolidFill(); - var schemeColor1 = new SchemeColor { Val = SchemeColorValues.PhColor }; - - solidFill1.AppendChild(schemeColor1); - - var gradientFill1 = new GradientFill { RotateWithShape = true }; - - var gradientStopList1 = new GradientStopList(); - - var gradientStop1 = new GradientStop { Position = 0 }; - - var schemeColor2 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var tint1 = new Tint { Val = 50000 }; - var saturationModulation1 = new SaturationModulation { Val = 300000 }; - - schemeColor2.AppendChild(tint1); - schemeColor2.AppendChild(saturationModulation1); - - gradientStop1.AppendChild(schemeColor2); - - var gradientStop2 = new GradientStop { Position = 35000 }; - - var schemeColor3 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var tint2 = new Tint { Val = 37000 }; - var saturationModulation2 = new SaturationModulation { Val = 300000 }; - - schemeColor3.AppendChild(tint2); - schemeColor3.AppendChild(saturationModulation2); - - gradientStop2.AppendChild(schemeColor3); - - var gradientStop3 = new GradientStop { Position = 100000 }; - - var schemeColor4 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var tint3 = new Tint { Val = 15000 }; - var saturationModulation3 = new SaturationModulation { Val = 350000 }; - - schemeColor4.AppendChild(tint3); - schemeColor4.AppendChild(saturationModulation3); - - gradientStop3.AppendChild(schemeColor4); - - gradientStopList1.AppendChild(gradientStop1); - gradientStopList1.AppendChild(gradientStop2); - gradientStopList1.AppendChild(gradientStop3); - var linearGradientFill1 = new LinearGradientFill { Angle = 16200000, Scaled = true }; - - gradientFill1.AppendChild(gradientStopList1); - gradientFill1.AppendChild(linearGradientFill1); - - var gradientFill2 = new GradientFill { RotateWithShape = true }; - - var gradientStopList2 = new GradientStopList(); - - var gradientStop4 = new GradientStop { Position = 0 }; - - var schemeColor5 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var shade1 = new Shade { Val = 51000 }; - var saturationModulation4 = new SaturationModulation { Val = 130000 }; - - schemeColor5.AppendChild(shade1); - schemeColor5.AppendChild(saturationModulation4); - - gradientStop4.AppendChild(schemeColor5); - - var gradientStop5 = new GradientStop { Position = 80000 }; - - var schemeColor6 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var shade2 = new Shade { Val = 93000 }; - var saturationModulation5 = new SaturationModulation { Val = 130000 }; - - schemeColor6.AppendChild(shade2); - schemeColor6.AppendChild(saturationModulation5); - - gradientStop5.AppendChild(schemeColor6); - - var gradientStop6 = new GradientStop { Position = 100000 }; - - var schemeColor7 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var shade3 = new Shade { Val = 94000 }; - var saturationModulation6 = new SaturationModulation { Val = 135000 }; - - schemeColor7.AppendChild(shade3); - schemeColor7.AppendChild(saturationModulation6); - - gradientStop6.AppendChild(schemeColor7); - - gradientStopList2.AppendChild(gradientStop4); - gradientStopList2.AppendChild(gradientStop5); - gradientStopList2.AppendChild(gradientStop6); - var linearGradientFill2 = new LinearGradientFill { Angle = 16200000, Scaled = false }; - - gradientFill2.AppendChild(gradientStopList2); - gradientFill2.AppendChild(linearGradientFill2); - - fillStyleList1.AppendChild(solidFill1); - fillStyleList1.AppendChild(gradientFill1); - fillStyleList1.AppendChild(gradientFill2); - - var lineStyleList1 = new LineStyleList(); - - var outline1 = new Outline - { - Width = 9525, - CapType = LineCapValues.Flat, - CompoundLineType = CompoundLineValues.Single, - Alignment = PenAlignmentValues.Center - }; - - var solidFill2 = new SolidFill(); - - var schemeColor8 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var shade4 = new Shade { Val = 95000 }; - var saturationModulation7 = new SaturationModulation { Val = 105000 }; - - schemeColor8.AppendChild(shade4); - schemeColor8.AppendChild(saturationModulation7); - - solidFill2.AppendChild(schemeColor8); - var presetDash1 = new PresetDash { Val = PresetLineDashValues.Solid }; - - outline1.AppendChild(solidFill2); - outline1.AppendChild(presetDash1); - - var outline2 = new Outline - { - Width = 25400, - CapType = LineCapValues.Flat, - CompoundLineType = CompoundLineValues.Single, - Alignment = PenAlignmentValues.Center - }; - - var solidFill3 = new SolidFill(); - var schemeColor9 = new SchemeColor { Val = SchemeColorValues.PhColor }; - - solidFill3.AppendChild(schemeColor9); - var presetDash2 = new PresetDash { Val = PresetLineDashValues.Solid }; - - outline2.AppendChild(solidFill3); - outline2.AppendChild(presetDash2); - - var outline3 = new Outline - { - Width = 38100, - CapType = LineCapValues.Flat, - CompoundLineType = CompoundLineValues.Single, - Alignment = PenAlignmentValues.Center - }; - - var solidFill4 = new SolidFill(); - var schemeColor10 = new SchemeColor { Val = SchemeColorValues.PhColor }; - - solidFill4.AppendChild(schemeColor10); - var presetDash3 = new PresetDash { Val = PresetLineDashValues.Solid }; - - outline3.AppendChild(solidFill4); - outline3.AppendChild(presetDash3); - - lineStyleList1.AppendChild(outline1); - lineStyleList1.AppendChild(outline2); - lineStyleList1.AppendChild(outline3); - - var effectStyleList1 = new EffectStyleList(); - - var effectStyle1 = new EffectStyle(); - - var effectList1 = new EffectList(); - - var outerShadow1 = new OuterShadow - { - BlurRadius = 40000L, - Distance = 20000L, - Direction = 5400000, - RotateWithShape = false - }; - - var rgbColorModelHex11 = new RgbColorModelHex { Val = "000000" }; - var alpha1 = new Alpha { Val = 38000 }; - - rgbColorModelHex11.AppendChild(alpha1); - - outerShadow1.AppendChild(rgbColorModelHex11); - - effectList1.AppendChild(outerShadow1); - - effectStyle1.AppendChild(effectList1); - - var effectStyle2 = new EffectStyle(); - - var effectList2 = new EffectList(); - - var outerShadow2 = new OuterShadow - { - BlurRadius = 40000L, - Distance = 23000L, - Direction = 5400000, - RotateWithShape = false - }; - - var rgbColorModelHex12 = new RgbColorModelHex { Val = "000000" }; - var alpha2 = new Alpha { Val = 35000 }; - - rgbColorModelHex12.AppendChild(alpha2); - - outerShadow2.AppendChild(rgbColorModelHex12); - - effectList2.AppendChild(outerShadow2); - - effectStyle2.AppendChild(effectList2); - - var effectStyle3 = new EffectStyle(); - - var effectList3 = new EffectList(); - - var outerShadow3 = new OuterShadow - { - BlurRadius = 40000L, - Distance = 23000L, - Direction = 5400000, - RotateWithShape = false - }; - - var rgbColorModelHex13 = new RgbColorModelHex { Val = "000000" }; - var alpha3 = new Alpha { Val = 35000 }; - - rgbColorModelHex13.AppendChild(alpha3); - - outerShadow3.AppendChild(rgbColorModelHex13); - - effectList3.AppendChild(outerShadow3); - - var scene3DType1 = new Scene3DType(); - - var camera1 = new Camera { Preset = PresetCameraValues.OrthographicFront }; - var rotation1 = new Rotation { Latitude = 0, Longitude = 0, Revolution = 0 }; - - camera1.AppendChild(rotation1); - - var lightRig1 = new LightRig { Rig = LightRigValues.ThreePoints, Direction = LightRigDirectionValues.Top }; - var rotation2 = new Rotation { Latitude = 0, Longitude = 0, Revolution = 1200000 }; - - lightRig1.AppendChild(rotation2); - - scene3DType1.AppendChild(camera1); - scene3DType1.AppendChild(lightRig1); - - var shape3DType1 = new Shape3DType(); - var bevelTop1 = new BevelTop { Width = 63500L, Height = 25400L }; - - shape3DType1.AppendChild(bevelTop1); - - effectStyle3.AppendChild(effectList3); - effectStyle3.AppendChild(scene3DType1); - effectStyle3.AppendChild(shape3DType1); - - effectStyleList1.AppendChild(effectStyle1); - effectStyleList1.AppendChild(effectStyle2); - effectStyleList1.AppendChild(effectStyle3); - - var backgroundFillStyleList1 = new BackgroundFillStyleList(); - - var solidFill5 = new SolidFill(); - var schemeColor11 = new SchemeColor { Val = SchemeColorValues.PhColor }; - - solidFill5.AppendChild(schemeColor11); - - var gradientFill3 = new GradientFill { RotateWithShape = true }; - - var gradientStopList3 = new GradientStopList(); - - var gradientStop7 = new GradientStop { Position = 0 }; - - var schemeColor12 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var tint4 = new Tint { Val = 40000 }; - var saturationModulation8 = new SaturationModulation { Val = 350000 }; - - schemeColor12.AppendChild(tint4); - schemeColor12.AppendChild(saturationModulation8); - - gradientStop7.AppendChild(schemeColor12); - - var gradientStop8 = new GradientStop { Position = 40000 }; - - var schemeColor13 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var tint5 = new Tint { Val = 45000 }; - var shade5 = new Shade { Val = 99000 }; - var saturationModulation9 = new SaturationModulation { Val = 350000 }; - - schemeColor13.AppendChild(tint5); - schemeColor13.AppendChild(shade5); - schemeColor13.AppendChild(saturationModulation9); - - gradientStop8.AppendChild(schemeColor13); - - var gradientStop9 = new GradientStop { Position = 100000 }; - - var schemeColor14 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var shade6 = new Shade { Val = 20000 }; - var saturationModulation10 = new SaturationModulation { Val = 255000 }; - - schemeColor14.AppendChild(shade6); - schemeColor14.AppendChild(saturationModulation10); - - gradientStop9.AppendChild(schemeColor14); - - gradientStopList3.AppendChild(gradientStop7); - gradientStopList3.AppendChild(gradientStop8); - gradientStopList3.AppendChild(gradientStop9); - - var pathGradientFill1 = new PathGradientFill { Path = PathShadeValues.Circle }; - var fillToRectangle1 = new FillToRectangle { Left = 50000, Top = -80000, Right = 50000, Bottom = 180000 }; - - pathGradientFill1.AppendChild(fillToRectangle1); - - gradientFill3.AppendChild(gradientStopList3); - gradientFill3.AppendChild(pathGradientFill1); - - var gradientFill4 = new GradientFill { RotateWithShape = true }; - - var gradientStopList4 = new GradientStopList(); - - var gradientStop10 = new GradientStop { Position = 0 }; - - var schemeColor15 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var tint6 = new Tint { Val = 80000 }; - var saturationModulation11 = new SaturationModulation { Val = 300000 }; - - schemeColor15.AppendChild(tint6); - schemeColor15.AppendChild(saturationModulation11); - - gradientStop10.AppendChild(schemeColor15); - - var gradientStop11 = new GradientStop { Position = 100000 }; - - var schemeColor16 = new SchemeColor { Val = SchemeColorValues.PhColor }; - var shade7 = new Shade { Val = 30000 }; - var saturationModulation12 = new SaturationModulation { Val = 200000 }; - - schemeColor16.AppendChild(shade7); - schemeColor16.AppendChild(saturationModulation12); - - gradientStop11.AppendChild(schemeColor16); - - gradientStopList4.AppendChild(gradientStop10); - gradientStopList4.AppendChild(gradientStop11); - - var pathGradientFill2 = new PathGradientFill { Path = PathShadeValues.Circle }; - var fillToRectangle2 = new FillToRectangle { Left = 50000, Top = 50000, Right = 50000, Bottom = 50000 }; - - pathGradientFill2.AppendChild(fillToRectangle2); - - gradientFill4.AppendChild(gradientStopList4); - gradientFill4.AppendChild(pathGradientFill2); - - backgroundFillStyleList1.AppendChild(solidFill5); - backgroundFillStyleList1.AppendChild(gradientFill3); - backgroundFillStyleList1.AppendChild(gradientFill4); - - formatScheme1.AppendChild(fillStyleList1); - formatScheme1.AppendChild(lineStyleList1); - formatScheme1.AppendChild(effectStyleList1); - formatScheme1.AppendChild(backgroundFillStyleList1); - - themeElements1.AppendChild(colorScheme1); - themeElements1.AppendChild(fontScheme2); - themeElements1.AppendChild(formatScheme1); - var objectDefaults1 = new ObjectDefaults(); - var extraColorSchemeList1 = new ExtraColorSchemeList(); - - theme1.AppendChild(themeElements1); - theme1.AppendChild(objectDefaults1); - theme1.AppendChild(extraColorSchemeList1); - - themePart.Theme = theme1; - } - - private void GenerateCustomFilePropertiesPartContent(CustomFilePropertiesPart customFilePropertiesPart1) - { - var properties2 = new DocumentFormat.OpenXml.CustomProperties.Properties(); - properties2.AddNamespaceDeclaration("vt", - "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"); - var propertyId = 1; - foreach (var p in CustomProperties) - { - propertyId++; - var customDocumentProperty = new CustomDocumentProperty - { - FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", - PropertyId = propertyId, - Name = p.Name - }; - if (p.Type == XLCustomPropertyType.Text) - { - var vTlpwstr1 = new VTLPWSTR { Text = p.GetValue() }; - customDocumentProperty.AppendChild(vTlpwstr1); - } - else if (p.Type == XLCustomPropertyType.Date) - { - var vTFileTime1 = new VTFileTime - { - Text = - p.GetValue().ToUniversalTime().ToString( - "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'") - }; - customDocumentProperty.AppendChild(vTFileTime1); - } - else if (p.Type == XLCustomPropertyType.Number) - { - var vTDouble1 = new VTDouble - { - Text = p.GetValue().ToInvariantString() - }; - customDocumentProperty.AppendChild(vTDouble1); - } - else - { - var vTBool1 = new VTBool { Text = p.GetValue().ToString().ToLower() }; - customDocumentProperty.AppendChild(vTBool1); - } - properties2.AppendChild(customDocumentProperty); - } - - customFilePropertiesPart1.Properties = properties2; - } - - private void SetPackageProperties(OpenXmlPackage document) - { - var created = Properties.Created == DateTime.MinValue ? DateTime.Now : Properties.Created; - var modified = Properties.Modified == DateTime.MinValue ? DateTime.Now : Properties.Modified; - document.PackageProperties.Created = created; - document.PackageProperties.Modified = modified; - document.PackageProperties.LastModifiedBy = Properties.LastModifiedBy; - - document.PackageProperties.Creator = Properties.Author; - document.PackageProperties.Title = Properties.Title; - document.PackageProperties.Subject = Properties.Subject; - document.PackageProperties.Category = Properties.Category; - document.PackageProperties.Keywords = Properties.Keywords; - document.PackageProperties.Description = Properties.Comments; - document.PackageProperties.ContentStatus = Properties.Status; - } - - private static string GetTableName(String originalTableName, SaveContext context) - { - var tableName = originalTableName.RemoveSpecialCharacters(); - var name = tableName; - if (context.TableNames.Contains(name)) - { - var i = 1; - name = tableName + i.ToInvariantString(); - while (context.TableNames.Contains(name)) - { - i++; - name = tableName + i.ToInvariantString(); - } - } - - context.TableNames.Add(name); - return name; - } - - private static void GenerateTableDefinitionPartContent(TableDefinitionPart tableDefinitionPart, XLTable xlTable, - SaveContext context) - { - context.TableId++; - var reference = xlTable.RangeAddress.FirstAddress + ":" + xlTable.RangeAddress.LastAddress; - var tableName = GetTableName(xlTable.Name, context); - var table = new Table - { - Id = context.TableId, - Name = tableName, - DisplayName = tableName, - Reference = reference - }; - - if (!xlTable.ShowHeaderRow) - table.HeaderRowCount = 0; - - if (xlTable.ShowTotalsRow) - table.TotalsRowCount = 1; - else - table.TotalsRowShown = false; - - var tableColumns1 = new TableColumns { Count = (UInt32)xlTable.ColumnCount() }; - - UInt32 columnId = 0; - foreach (var xlField in xlTable.Fields) - { - columnId++; - var fieldName = xlField.Name; - var tableColumn1 = new TableColumn - { - Id = columnId, - Name = fieldName.Replace("_x000a_", "_x005f_x000a_").Replace(Environment.NewLine, "_x000a_") - }; - if (xlTable.ShowTotalsRow) - { - if (xlField.TotalsRowFunction != XLTotalsRowFunction.None) - { - tableColumn1.TotalsRowFunction = xlField.TotalsRowFunction.ToOpenXml(); - - if (xlField.TotalsRowFunction == XLTotalsRowFunction.Custom) - tableColumn1.TotalsRowFormula = new TotalsRowFormula(xlField.TotalsRowFormulaA1); - } - - if (!XLHelper.IsNullOrWhiteSpace(xlField.TotalsRowLabel)) - tableColumn1.TotalsRowLabel = xlField.TotalsRowLabel; - } - tableColumns1.AppendChild(tableColumn1); - } - - var tableStyleInfo1 = new TableStyleInfo - { - ShowFirstColumn = xlTable.EmphasizeFirstColumn, - ShowLastColumn = xlTable.EmphasizeLastColumn, - ShowRowStripes = xlTable.ShowRowStripes, - ShowColumnStripes = xlTable.ShowColumnStripes - }; - - if (xlTable.Theme != XLTableTheme.None) - tableStyleInfo1.Name = xlTable.Theme.Name; - - if (xlTable.ShowAutoFilter) - { - var autoFilter1 = new AutoFilter(); - if (xlTable.ShowTotalsRow) - { - xlTable.AutoFilter.Range = xlTable.Worksheet.Range( - xlTable.RangeAddress.FirstAddress.RowNumber, xlTable.RangeAddress.FirstAddress.ColumnNumber, - xlTable.RangeAddress.LastAddress.RowNumber - 1, xlTable.RangeAddress.LastAddress.ColumnNumber); - } - else - xlTable.AutoFilter.Range = xlTable.Worksheet.Range(xlTable.RangeAddress); - - PopulateAutoFilter(xlTable.AutoFilter, autoFilter1); - - table.AppendChild(autoFilter1); - } - - table.AppendChild(tableColumns1); - table.AppendChild(tableStyleInfo1); - - tableDefinitionPart.Table = table; - } - - private static void GeneratePivotTables(WorkbookPart workbookPart, WorksheetPart worksheetPart, - XLWorksheet xlWorksheet, - SaveContext context) - { - PivotCaches pivotCaches; - uint cacheId = 0; - if (workbookPart.Workbook.PivotCaches == null) - pivotCaches = workbookPart.Workbook.InsertAfter(new PivotCaches(), workbookPart.Workbook.CalculationProperties); - else - { - pivotCaches = workbookPart.Workbook.PivotCaches; - if (pivotCaches.Any()) - cacheId = pivotCaches.Cast().Max(pc => pc.CacheId.Value) + 1; - } - - foreach (var pt in xlWorksheet.PivotTables.Cast()) - { - // TODO: Avoid duplicate pivot caches of same source range - - var workbookCacheRelId = pt.WorkbookCacheRelId; - PivotCache pivotCache; - PivotTableCacheDefinitionPart pivotTableCacheDefinitionPart; - if (!XLHelper.IsNullOrWhiteSpace(pt.WorkbookCacheRelId)) - { - pivotCache = pivotCaches.Cast().Single(pc => pc.Id.Value == pt.WorkbookCacheRelId); - pivotTableCacheDefinitionPart = workbookPart.GetPartById(pt.WorkbookCacheRelId) as PivotTableCacheDefinitionPart; - } - else - { - workbookCacheRelId = context.RelIdGenerator.GetNext(RelType.Workbook); - pivotCache = new PivotCache { CacheId = cacheId++, Id = workbookCacheRelId }; - pivotTableCacheDefinitionPart = workbookPart.AddNewPart(workbookCacheRelId); - } - - GeneratePivotTableCacheDefinitionPartContent(pivotTableCacheDefinitionPart, pt); - - if (XLHelper.IsNullOrWhiteSpace(pt.WorkbookCacheRelId)) - pivotCaches.AppendChild(pivotCache); - - PivotTablePart pivotTablePart; - if (XLHelper.IsNullOrWhiteSpace(pt.RelId)) - pivotTablePart = worksheetPart.AddNewPart(context.RelIdGenerator.GetNext(RelType.Workbook)); - else - pivotTablePart = worksheetPart.GetPartById(pt.RelId) as PivotTablePart; - - GeneratePivotTablePartContent(pivotTablePart, pt, pivotCache.CacheId, context); - - if (XLHelper.IsNullOrWhiteSpace(pt.RelId)) - pivotTablePart.AddPart(pivotTableCacheDefinitionPart, context.RelIdGenerator.GetNext(RelType.Workbook)); - } - } - - // Generates content of pivotTableCacheDefinitionPart - private static void GeneratePivotTableCacheDefinitionPartContent( - PivotTableCacheDefinitionPart pivotTableCacheDefinitionPart, IXLPivotTable pt) - { - var source = pt.SourceRange; - - var pivotCacheDefinition = new PivotCacheDefinition - { - Id = "rId1", - SaveData = pt.SaveSourceData, - RefreshOnLoad = true //pt.RefreshDataOnOpen - }; - if (pt.ItemsToRetainPerField == XLItemsToRetain.None) - pivotCacheDefinition.MissingItemsLimit = 0U; - else if (pt.ItemsToRetainPerField == XLItemsToRetain.Max) - pivotCacheDefinition.MissingItemsLimit = XLHelper.MaxRowNumber; - - pivotCacheDefinition.AddNamespaceDeclaration("r", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); - - var cacheSource = new CacheSource { Type = SourceValues.Worksheet }; - cacheSource.AppendChild(new WorksheetSource { Name = source.ToString() }); - - var cacheFields = new CacheFields(); - - foreach (var c in source.Columns()) - { - var columnNumber = c.ColumnNumber(); - var columnName = c.FirstCell().Value.ToString(); - var xlpf = pt.Fields.Add(columnName); - - var field = - pt.RowLabels.Union(pt.ColumnLabels).Union(pt.ReportFilters).FirstOrDefault(f => f.SourceName == columnName); - if (field != null) - { - xlpf.CustomName = field.CustomName; - xlpf.Subtotals.AddRange(field.Subtotals); - } - - var sharedItems = new SharedItems(); - - var onlyNumbers = - !source.Cells().Any( - cell => - cell.Address.ColumnNumber == columnNumber && - cell.Address.RowNumber > source.FirstRow().RowNumber() && cell.DataType != XLCellValues.Number); - if (onlyNumbers) - { - sharedItems = new SharedItems - { ContainsSemiMixedTypes = false, ContainsString = false, ContainsNumber = true }; - } - else - { - foreach (var cellValue in source.Cells() - .Where(cell => cell.Address.ColumnNumber == columnNumber && cell.Address.RowNumber > source.FirstRow().RowNumber()) - .Select(cell => cell.Value.ToString()) - .Where(cellValue => !xlpf.SharedStrings.Select(ss => ss.ToLower()).Contains(cellValue.ToLower()))) - { - xlpf.SharedStrings.Add(cellValue); - } - - foreach (var li in xlpf.SharedStrings) - { - sharedItems.AppendChild(new StringItem { Val = li }); - } - } - - var cacheField = new CacheField { Name = xlpf.SourceName }; - cacheField.AppendChild(sharedItems); - cacheFields.AppendChild(cacheField); - } - - pivotCacheDefinition.AppendChild(cacheSource); - pivotCacheDefinition.AppendChild(cacheFields); - - pivotTableCacheDefinitionPart.PivotCacheDefinition = pivotCacheDefinition; - - var pivotTableCacheRecordsPart = pivotTableCacheDefinitionPart.GetPartsOfType().Any() ? - pivotTableCacheDefinitionPart.GetPartsOfType().First() : - pivotTableCacheDefinitionPart.AddNewPart("rId1"); - - var pivotCacheRecords = new PivotCacheRecords(); - pivotCacheRecords.AddNamespaceDeclaration("r", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); - pivotTableCacheRecordsPart.PivotCacheRecords = pivotCacheRecords; - } - - // Generates content of pivotTablePart - private static void GeneratePivotTablePartContent(PivotTablePart pivotTablePart, IXLPivotTable pt, uint cacheId, SaveContext context) - { - var pivotTableDefinition = new PivotTableDefinition - { - Name = pt.Name, - CacheId = cacheId, - DataCaption = "Values", - MergeItem = GetBooleanValue(pt.MergeAndCenterWithLabels, true), - Indent = Convert.ToUInt32(pt.RowLabelIndent), - PageOverThenDown = (pt.FilterAreaOrder == XLFilterAreaOrder.OverThenDown), - PageWrap = Convert.ToUInt32(pt.FilterFieldsPageWrap), - ShowError = String.IsNullOrEmpty(pt.ErrorValueReplacement), - UseAutoFormatting = GetBooleanValue(pt.AutofitColumns, true), - PreserveFormatting = GetBooleanValue(pt.PreserveCellFormatting, true), - RowGrandTotals = GetBooleanValue(pt.ShowGrandTotalsRows, true), - ColumnGrandTotals = GetBooleanValue(pt.ShowGrandTotalsColumns, true), - SubtotalHiddenItems = GetBooleanValue(pt.FilteredItemsInSubtotals, true), - MultipleFieldFilters = GetBooleanValue(pt.AllowMultipleFilters, true), - CustomListSort = GetBooleanValue(pt.UseCustomListsForSorting, true), - ShowDrill = GetBooleanValue(pt.ShowExpandCollapseButtons, true), - ShowDataTips = GetBooleanValue(pt.ShowContextualTooltips, true), - ShowMemberPropertyTips = GetBooleanValue(pt.ShowPropertiesInTooltips, true), - ShowHeaders = GetBooleanValue(pt.DisplayCaptionsAndDropdowns, true), - GridDropZones = GetBooleanValue(pt.ClassicPivotTableLayout, false), - ShowEmptyRow = GetBooleanValue(pt.ShowEmptyItemsOnRows, true), - ShowEmptyColumn = GetBooleanValue(pt.ShowEmptyItemsOnColumns, true), - ShowItems = GetBooleanValue(pt.DisplayItemLabels, true), - FieldListSortAscending = GetBooleanValue(pt.SortFieldsAtoZ, true), - PrintDrill = GetBooleanValue(pt.PrintExpandCollapsedButtons, true), - ItemPrintTitles = GetBooleanValue(pt.RepeatRowLabels, true), - FieldPrintTitles = GetBooleanValue(pt.PrintTitles, true), - EnableDrill = GetBooleanValue(pt.EnableShowDetails, true) - }; - - if (pt.EmptyCellReplacement != null) - { - pivotTableDefinition.ShowMissing = true; - pivotTableDefinition.MissingCaption = pt.EmptyCellReplacement; - } - else - { - pivotTableDefinition.ShowMissing = false; - } - - if (pt.ErrorValueReplacement != null) - { - pivotTableDefinition.ShowError = true; - pivotTableDefinition.ErrorCaption = pt.ErrorValueReplacement; - } - else - { - pivotTableDefinition.ShowError = false; - } - - var location = new Location - { - Reference = pt.TargetCell.Address.ToString(), - FirstHeaderRow = 1U, - FirstDataRow = 1U, - FirstDataColumn = 1U - }; - - var rowFields = new RowFields(); - var columnFields = new ColumnFields(); - var rowItems = new RowItems(); - var columnItems = new ColumnItems(); - var pageFields = new PageFields { Count = (uint)pt.ReportFilters.Count() }; - var pivotFields = new PivotFields { Count = Convert.ToUInt32(pt.SourceRange.ColumnCount()) }; - - foreach (var xlpf in pt.Fields.OrderBy(f => pt.RowLabels.Any(p => p.SourceName == f.SourceName) ? pt.RowLabels.IndexOf(f) : Int32.MaxValue)) - { - if (pt.RowLabels.Any(p => p.SourceName == xlpf.SourceName)) - { - var f = new Field { Index = pt.Fields.IndexOf(xlpf) }; - rowFields.AppendChild(f); - - for (var i = 0; i < xlpf.SharedStrings.Count; i++) - { - var rowItem = new RowItem(); - rowItem.AppendChild(new MemberPropertyIndex { Val = i }); - rowItems.AppendChild(rowItem); - } - - var rowItemTotal = new RowItem { ItemType = ItemValues.Grand }; - rowItemTotal.AppendChild(new MemberPropertyIndex()); - rowItems.AppendChild(rowItemTotal); - } - else if (pt.ColumnLabels.Any(p => p.SourceName == xlpf.SourceName)) - { - var f = new Field { Index = pt.Fields.IndexOf(xlpf) }; - columnFields.AppendChild(f); - - for (var i = 0; i < xlpf.SharedStrings.Count; i++) - { - var rowItem = new RowItem(); - rowItem.AppendChild(new MemberPropertyIndex { Val = i }); - columnItems.AppendChild(rowItem); - } - - var rowItemTotal = new RowItem { ItemType = ItemValues.Grand }; - rowItemTotal.AppendChild(new MemberPropertyIndex()); - columnItems.AppendChild(rowItemTotal); - } - } - - if (pt.Values.Count() > 1) - { - // -2 is the sentinal value for "Values" - if (pt.ColumnLabels.Any(cl => cl.SourceName == XLConstants.PivotTableValuesSentinalLabel)) - columnFields.AppendChild(new Field { Index = -2 }); - else if (pt.RowLabels.Any(rl => rl.SourceName == XLConstants.PivotTableValuesSentinalLabel)) - { - pivotTableDefinition.DataOnRows = true; - rowFields.AppendChild(new Field { Index = -2 }); - } - } - - foreach (var xlpf in pt.Fields) - { - IXLPivotField labelField = null; - var pf = new PivotField { ShowAll = false, Name = xlpf.CustomName }; - - if (pt.RowLabels.Any(p => p.SourceName == xlpf.SourceName)) - { - labelField = pt.RowLabels.Single(p => p.SourceName == xlpf.SourceName); - pf.Axis = PivotTableAxisValues.AxisRow; - } - else if (pt.ColumnLabels.Any(p => p.SourceName == xlpf.SourceName)) - { - labelField = pt.ColumnLabels.Single(p => p.SourceName == xlpf.SourceName); - pf.Axis = PivotTableAxisValues.AxisColumn; - } - else if (pt.ReportFilters.Any(p => p.SourceName == xlpf.SourceName)) - { - location.ColumnsPerPage = 1; - location.RowPageCount = 1; - pf.Axis = PivotTableAxisValues.AxisPage; - pageFields.AppendChild(new PageField { Hierarchy = -1, Field = pt.Fields.IndexOf(xlpf) }); - } - - if (pt.Values.Any(p => p.SourceName == xlpf.SourceName)) - pf.DataField = true; - - var fieldItems = new Items(); - - if (xlpf.SharedStrings.Count > 0) - { - for (uint i = 0; i < xlpf.SharedStrings.Count; i++) - { - var item = new Item { Index = i }; - if (labelField != null && labelField.Collapsed) - item.HideDetails = BooleanValue.FromBoolean(false); - fieldItems.AppendChild(item); - } - } - - if (xlpf.Subtotals.Count > 0) - { - foreach (var subtotal in xlpf.Subtotals) - { - var itemSubtotal = new Item(); - switch (subtotal) - { - case XLSubtotalFunction.Average: - pf.AverageSubTotal = true; - itemSubtotal.ItemType = ItemValues.Average; - break; - - case XLSubtotalFunction.Count: - pf.CountASubtotal = true; - itemSubtotal.ItemType = ItemValues.CountA; - break; - - case XLSubtotalFunction.CountNumbers: - pf.CountSubtotal = true; - itemSubtotal.ItemType = ItemValues.Count; - break; - - case XLSubtotalFunction.Maximum: - pf.MaxSubtotal = true; - itemSubtotal.ItemType = ItemValues.Maximum; - break; - - case XLSubtotalFunction.Minimum: - pf.MinSubtotal = true; - itemSubtotal.ItemType = ItemValues.Minimum; - break; - - case XLSubtotalFunction.PopulationStandardDeviation: - pf.ApplyStandardDeviationPInSubtotal = true; - itemSubtotal.ItemType = ItemValues.StandardDeviationP; - break; - - case XLSubtotalFunction.PopulationVariance: - pf.ApplyVariancePInSubtotal = true; - itemSubtotal.ItemType = ItemValues.VarianceP; - break; - - case XLSubtotalFunction.Product: - pf.ApplyProductInSubtotal = true; - itemSubtotal.ItemType = ItemValues.Product; - break; - - case XLSubtotalFunction.StandardDeviation: - pf.ApplyStandardDeviationInSubtotal = true; - itemSubtotal.ItemType = ItemValues.StandardDeviation; - break; - - case XLSubtotalFunction.Sum: - pf.SumSubtotal = true; - itemSubtotal.ItemType = ItemValues.Sum; - break; - - case XLSubtotalFunction.Variance: - pf.ApplyVarianceInSubtotal = true; - itemSubtotal.ItemType = ItemValues.Variance; - break; - } - fieldItems.AppendChild(itemSubtotal); - } - } - else - { - fieldItems.AppendChild(new Item { ItemType = ItemValues.Default }); - } - - fieldItems.Count = Convert.ToUInt32(fieldItems.Count()); - pf.AppendChild(fieldItems); - pivotFields.AppendChild(pf); - } - - pivotTableDefinition.AppendChild(location); - pivotTableDefinition.AppendChild(pivotFields); - - if (pt.RowLabels.Any()) - { - rowFields.Count = Convert.ToUInt32(rowFields.Count()); - pivotTableDefinition.AppendChild(rowFields); - } - else - { - rowItems.AppendChild(new RowItem()); - } - - if (rowItems.Any()) - { - rowItems.Count = Convert.ToUInt32(rowItems.Count()); - pivotTableDefinition.AppendChild(rowItems); - } - - if (!pt.ColumnLabels.Any(cl => cl.CustomName != XLConstants.PivotTableValuesSentinalLabel)) - { - for (int i = 0; i < pt.Values.Count(); i++) - { - var rowItem = new RowItem(); - rowItem.Index = Convert.ToUInt32(i); - rowItem.AppendChild(new MemberPropertyIndex() { Val = i }); - columnItems.AppendChild(rowItem); - } - } - - if (columnFields.Any()) - { - columnFields.Count = Convert.ToUInt32(columnFields.Count()); - pivotTableDefinition.AppendChild(columnFields); - } - - if (columnItems.Any()) - { - columnItems.Count = Convert.ToUInt32(columnItems.Count()); - pivotTableDefinition.AppendChild(columnItems); - } - - if (pt.ReportFilters.Any()) - { - pageFields.Count = Convert.ToUInt32(pageFields.Count()); - pivotTableDefinition.AppendChild(pageFields); - } - - var dataFields = new DataFields(); - foreach (var value in pt.Values) - { - var sourceColumn = - pt.SourceRange.Columns().FirstOrDefault(c => c.Cell(1).Value.ToString() == value.SourceName); - if (sourceColumn == null) continue; - - UInt32 numberFormatId = 0; - if (value.NumberFormat.NumberFormatId != -1 || context.SharedNumberFormats.ContainsKey(value.NumberFormat.NumberFormatId)) - numberFormatId = (UInt32)value.NumberFormat.NumberFormatId; - else if (context.SharedNumberFormats.Any(snf => snf.Value.NumberFormat.Format == value.NumberFormat.Format)) - numberFormatId = (UInt32)context.SharedNumberFormats.First(snf => snf.Value.NumberFormat.Format == value.NumberFormat.Format).Key; - - var df = new DataField - { - Name = value.CustomName, - Field = (UInt32)sourceColumn.ColumnNumber() - 1, - Subtotal = value.SummaryFormula.ToOpenXml(), - ShowDataAs = value.Calculation.ToOpenXml(), - NumberFormatId = numberFormatId - }; - - if (!String.IsNullOrEmpty(value.BaseField)) - { - var baseField = pt.SourceRange.Columns().FirstOrDefault(c => c.Cell(1).Value.ToString() == value.BaseField); - if (baseField != null) - { - df.BaseField = baseField.ColumnNumber() - 1; - - var items = baseField.CellsUsed() - .Select(c => c.Value) - .Skip(1) // Skip header column - .Distinct().ToList(); - - if (items.Any(i => i.Equals(value.BaseItem))) - df.BaseItem = Convert.ToUInt32(items.IndexOf(value.BaseItem)); - } - } - else - { - df.BaseField = 0; - } - - if (value.CalculationItem == XLPivotCalculationItem.Previous) - df.BaseItem = 1048828U; - else if (value.CalculationItem == XLPivotCalculationItem.Next) - df.BaseItem = 1048829U; - else if (df.BaseItem == null || !df.BaseItem.HasValue) - df.BaseItem = 0U; - - dataFields.AppendChild(df); - } - - if (dataFields.Any()) - { - dataFields.Count = Convert.ToUInt32(dataFields.Count()); - pivotTableDefinition.AppendChild(dataFields); - } - - pivotTableDefinition.AppendChild(new PivotTableStyle - { - Name = Enum.GetName(typeof(XLPivotTableTheme), pt.Theme), - ShowRowHeaders = pt.ShowRowHeaders, - ShowColumnHeaders = pt.ShowColumnHeaders, - ShowRowStripes = pt.ShowRowStripes, - ShowColumnStripes = pt.ShowColumnStripes - }); - - #region Excel 2010 Features - - var pivotTableDefinitionExtensionList = new PivotTableDefinitionExtensionList(); - - var pivotTableDefinitionExtension = new PivotTableDefinitionExtension - { Uri = "{962EF5D1-5CA2-4c93-8EF4-DBF5C05439D2}" }; - pivotTableDefinitionExtension.AddNamespaceDeclaration("x14", - "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"); - - var pivotTableDefinition2 = new DocumentFormat.OpenXml.Office2010.Excel.PivotTableDefinition - { EnableEdit = pt.EnableCellEditing, HideValuesRow = !pt.ShowValuesRow }; - pivotTableDefinition2.AddNamespaceDeclaration("xm", "http://schemas.microsoft.com/office/excel/2006/main"); - - pivotTableDefinitionExtension.AppendChild(pivotTableDefinition2); - - pivotTableDefinitionExtensionList.AppendChild(pivotTableDefinitionExtension); - pivotTableDefinition.AppendChild(pivotTableDefinitionExtensionList); - - #endregion Excel 2010 Features - - pivotTablePart.PivotTableDefinition = pivotTableDefinition; - } - - private static void GenerateWorksheetCommentsPartContent(WorksheetCommentsPart worksheetCommentsPart, - XLWorksheet xlWorksheet) - { - var comments = new Comments(); - var commentList = new CommentList(); - var authorsDict = new Dictionary(); - foreach (var c in xlWorksheet.Internals.CellsCollection.GetCells(c => c.HasComment)) - { - var comment = new Comment { Reference = c.Address.ToStringRelative() }; - var authorName = c.Comment.Author; - - Int32 authorId; - if (!authorsDict.TryGetValue(authorName, out authorId)) - { - authorId = authorsDict.Count; - authorsDict.Add(authorName, authorId); - } - comment.AuthorId = (UInt32)authorId; - - var commentText = new CommentText(); - foreach (var rt in c.Comment) - { - commentText.Append(GetRun(rt)); - } - - comment.Append(commentText); - commentList.Append(comment); - } - - var authors = new Authors(); - foreach (var author in authorsDict.Select(a => new Author { Text = a.Key })) - { - authors.Append(author); - } - comments.Append(authors); - comments.Append(commentList); - - worksheetCommentsPart.Comments = comments; - } - - // Generates content of vmlDrawingPart1. - private static void GenerateVmlDrawingPartContent(VmlDrawingPart vmlDrawingPart, XLWorksheet xlWorksheet, - SaveContext context) - { - var ms = new MemoryStream(); - CopyStream(vmlDrawingPart.GetStream(FileMode.OpenOrCreate), ms); - ms.Position = 0; - var writer = new XmlTextWriter(vmlDrawingPart.GetStream(FileMode.Create), Encoding.UTF8); - - writer.WriteStartElement("xml"); - - const string shapeTypeId = "_x0000_t202"; // arbitrary, assigned by office - - new Vml.Shapetype( - new Vml.Stroke { JoinStyle = Vml.StrokeJoinStyleValues.Miter }, - new Vml.Path { AllowGradientShape = true, ConnectionPointType = ConnectValues.Rectangle } - ) - { - Id = shapeTypeId, - CoordinateSize = "21600,21600", - OptionalNumber = 202, - EdgePath = "m,l,21600r21600,l21600,xe", - } - .WriteTo(writer); - - var cellWithComments = xlWorksheet.Internals.CellsCollection.GetCells().Where(c => c.HasComment); - - foreach (var c in cellWithComments) - { - GenerateShape(c, shapeTypeId).WriteTo(writer); - } - - if (ms.Length > 0) - { - ms.Position = 0; - var xdoc = XDocumentExtensions.Load(ms); - xdoc.Root.Elements().ForEach(e => writer.WriteRaw(e.ToString())); - } - - writer.WriteEndElement(); - writer.Flush(); - writer.Close(); - } - - // VML Shape for Comment - private static Vml.Shape GenerateShape(XLCell c, string shapeTypeId) - { - var rowNumber = c.Address.RowNumber; - var columnNumber = c.Address.ColumnNumber; - - var shapeId = String.Format("_x0000_s{0}", c.Comment.ShapeId); - // Unique per cell (workbook?), e.g.: "_x0000_s1026" - var anchor = GetAnchor(c); - var textBox = GetTextBox(c.Comment.Style); - var fill = new Vml.Fill { Color2 = "#" + c.Comment.Style.ColorsAndLines.FillColor.Color.ToHex().Substring(2) }; - if (c.Comment.Style.ColorsAndLines.FillTransparency < 1) - fill.Opacity = - Math.Round(Convert.ToDouble(c.Comment.Style.ColorsAndLines.FillTransparency), 2).ToString( - CultureInfo.InvariantCulture); - var stroke = GetStroke(c); - var shape = new Vml.Shape( - fill, - stroke, - new Vml.Shadow { On = true, Color = "black", Obscured = true }, - new Vml.Path { ConnectionPointType = ConnectValues.None }, - textBox, - new ClientData( - new MoveWithCells(c.Comment.Style.Properties.Positioning == XLDrawingAnchor.Absolute - ? "True" - : "False"), // Counterintuitive - new ResizeWithCells(c.Comment.Style.Properties.Positioning == XLDrawingAnchor.MoveAndSizeWithCells - ? "False" - : "True"), // Counterintuitive - anchor, - new HorizontalTextAlignment(c.Comment.Style.Alignment.Horizontal.ToString().ToCamel()), - new Vml.Spreadsheet.VerticalTextAlignment(c.Comment.Style.Alignment.Vertical.ToString().ToCamel()), - new AutoFill("False"), - new CommentRowTarget { Text = (rowNumber - 1).ToString() }, - new CommentColumnTarget { Text = (columnNumber - 1).ToString() }, - new Locked(c.Comment.Style.Protection.Locked ? "True" : "False"), - new LockText(c.Comment.Style.Protection.LockText ? "True" : "False"), - new Visible(c.Comment.Visible ? "True" : "False") - ) - { ObjectType = ObjectValues.Note } - ) - { - Id = shapeId, - Type = "#" + shapeTypeId, - Style = GetCommentStyle(c), - FillColor = "#" + c.Comment.Style.ColorsAndLines.FillColor.Color.ToHex().Substring(2), - StrokeColor = "#" + c.Comment.Style.ColorsAndLines.LineColor.Color.ToHex().Substring(2), - StrokeWeight = String.Format(CultureInfo.InvariantCulture, "{0}pt", c.Comment.Style.ColorsAndLines.LineWeight), - InsetMode = c.Comment.Style.Margins.Automatic ? InsetMarginValues.Auto : InsetMarginValues.Custom - }; - if (!XLHelper.IsNullOrWhiteSpace(c.Comment.Style.Web.AlternateText)) - shape.Alternate = c.Comment.Style.Web.AlternateText; - - return shape; - } - - private static Vml.Stroke GetStroke(XLCell c) - { - var lineDash = c.Comment.Style.ColorsAndLines.LineDash; - var stroke = new Vml.Stroke - { - LineStyle = c.Comment.Style.ColorsAndLines.LineStyle.ToOpenXml(), - DashStyle = - lineDash == XLDashStyle.RoundDot || lineDash == XLDashStyle.SquareDot - ? "shortDot" - : lineDash.ToString().ToCamel() - }; - if (lineDash == XLDashStyle.RoundDot) - stroke.EndCap = Vml.StrokeEndCapValues.Round; - if (c.Comment.Style.ColorsAndLines.LineTransparency < 1) - stroke.Opacity = - Math.Round(Convert.ToDouble(c.Comment.Style.ColorsAndLines.LineTransparency), 2).ToString( - CultureInfo.InvariantCulture); - return stroke; - } - - // http://polymathprogrammer.com/2009/10/22/english-metric-units-and-open-xml/ - // http://archive.oreilly.com/pub/post/what_is_an_emu.html - // https://en.wikipedia.org/wiki/Office_Open_XML_file_formats#DrawingML - private static Int64 ConvertToEnglishMetricUnits(Int32 pixels, Double resolution) - { - return Convert.ToInt64(914400 * pixels / resolution); - } - - private static void AddPictureAnchor(WorksheetPart worksheetPart, Drawings.IXLPicture picture, SaveContext context) - { - var pic = picture as Drawings.XLPicture; - var drawingsPart = worksheetPart.DrawingsPart ?? - worksheetPart.AddNewPart(context.RelIdGenerator.GetNext(RelType.Workbook)); - - if (drawingsPart.WorksheetDrawing == null) - drawingsPart.WorksheetDrawing = new Xdr.WorksheetDrawing(); - - var worksheetDrawing = drawingsPart.WorksheetDrawing; - - // Add namespaces - if (!worksheetDrawing.NamespaceDeclarations.Any(nd => nd.Value.Equals("http://schemas.openxmlformats.org/drawingml/2006/main"))) - worksheetDrawing.AddNamespaceDeclaration("a", "http://schemas.openxmlformats.org/drawingml/2006/main"); - - if (!worksheetDrawing.NamespaceDeclarations.Any(nd => nd.Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships"))) - worksheetDrawing.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); - ///////// - - // Overwrite actual image binary data - ImagePart imagePart; - if (drawingsPart.HasPartWithId(pic.RelId)) - imagePart = drawingsPart.GetPartById(pic.RelId) as ImagePart; - else - imagePart = drawingsPart.AddImagePart(pic.Format.ToOpenXml(), context.RelIdGenerator.GetNext(RelType.Workbook)); - - using (var stream = new MemoryStream()) - { - pic.ImageStream.CopyTo(stream); - stream.Seek(0, SeekOrigin.Begin); - imagePart.FeedData(stream); - } - ///////// - - // Clear current anchors - var existingAnchor = GetAnchorFromImageId(worksheetPart, pic.RelId); - if (existingAnchor != null) - worksheetDrawing.RemoveChild(existingAnchor); - - var extentsCx = ConvertToEnglishMetricUnits(pic.Width, GraphicsUtils.Graphics.DpiX); - var extentsCy = ConvertToEnglishMetricUnits(pic.Height, GraphicsUtils.Graphics.DpiY); - - var nvps = worksheetDrawing.Descendants(); - var nvpId = nvps.Any() ? - (UInt32Value)worksheetDrawing.Descendants().Max(p => p.Id.Value) + 1 : - 1U; - - Xdr.FromMarker fMark; - Xdr.ToMarker tMark; - switch (pic.Placement) - { - case Drawings.XLPicturePlacement.FreeFloating: - var absoluteAnchor = new Xdr.AbsoluteAnchor( - new Xdr.Position - { - X = ConvertToEnglishMetricUnits(pic.Left, GraphicsUtils.Graphics.DpiX), - Y = ConvertToEnglishMetricUnits(pic.Top, GraphicsUtils.Graphics.DpiY) - }, - new Xdr.Extent - { - Cx = extentsCx, - Cy = extentsCy - }, - new Xdr.Picture( - new Xdr.NonVisualPictureProperties( - new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = pic.Name }, - new Xdr.NonVisualPictureDrawingProperties(new PictureLocks { NoChangeAspect = true }) - ), - new Xdr.BlipFill( - new Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = BlipCompressionValues.Print }, - new Stretch(new FillRectangle()) - ), - new Xdr.ShapeProperties( - new Transform2D( - new Offset { X = 0, Y = 0 }, - new Extents { Cx = extentsCx, Cy = extentsCy } - ), - new PresetGeometry { Preset = ShapeTypeValues.Rectangle } - ) - ), - new Xdr.ClientData() - ); - - worksheetDrawing.Append(absoluteAnchor); - break; - - case Drawings.XLPicturePlacement.MoveAndSize: - var moveAndSizeFromMarker = pic.Markers[Drawings.XLMarkerPosition.TopLeft]; - fMark = new Xdr.FromMarker - { - ColumnId = new Xdr.ColumnId((moveAndSizeFromMarker.Address.ColumnNumber - 1).ToString()), - RowId = new Xdr.RowId((moveAndSizeFromMarker.Address.RowNumber - 1).ToString()), - ColumnOffset = new Xdr.ColumnOffset(ConvertToEnglishMetricUnits(moveAndSizeFromMarker.Offset.X, GraphicsUtils.Graphics.DpiX).ToString()), - RowOffset = new Xdr.RowOffset(ConvertToEnglishMetricUnits(moveAndSizeFromMarker.Offset.Y, GraphicsUtils.Graphics.DpiY).ToString()) - }; - - var moveAndSizeToMarker = pic.Markers[Drawings.XLMarkerPosition.BottomRight]; - tMark = new Xdr.ToMarker - { - ColumnId = new Xdr.ColumnId((moveAndSizeToMarker.Address.ColumnNumber - 1).ToString()), - RowId = new Xdr.RowId((moveAndSizeToMarker.Address.RowNumber - 1).ToString()), - ColumnOffset = new Xdr.ColumnOffset(ConvertToEnglishMetricUnits(moveAndSizeToMarker.Offset.X, GraphicsUtils.Graphics.DpiX).ToString()), - RowOffset = new Xdr.RowOffset(ConvertToEnglishMetricUnits(moveAndSizeToMarker.Offset.Y, GraphicsUtils.Graphics.DpiY).ToString()) - }; - - var twoCellAnchor = new Xdr.TwoCellAnchor( - fMark, - tMark, - new Xdr.Picture( - new Xdr.NonVisualPictureProperties( - new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = pic.Name }, - new Xdr.NonVisualPictureDrawingProperties(new PictureLocks { NoChangeAspect = true }) - ), - new Xdr.BlipFill( - new Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = BlipCompressionValues.Print }, - new Stretch(new FillRectangle()) - ), - new Xdr.ShapeProperties( - new Transform2D( - new Offset { X = 0, Y = 0 }, - new Extents { Cx = extentsCx, Cy = extentsCy } - ), - new PresetGeometry { Preset = ShapeTypeValues.Rectangle } - ) - ), - new Xdr.ClientData() - ); - - worksheetDrawing.Append(twoCellAnchor); - break; - - case Drawings.XLPicturePlacement.Move: - var moveFromMarker = pic.Markers[Drawings.XLMarkerPosition.TopLeft]; - fMark = new Xdr.FromMarker - { - ColumnId = new Xdr.ColumnId((moveFromMarker.Address.ColumnNumber - 1).ToString()), - RowId = new Xdr.RowId((moveFromMarker.Address.RowNumber - 1).ToString()), - ColumnOffset = new Xdr.ColumnOffset(ConvertToEnglishMetricUnits(moveFromMarker.Offset.X, GraphicsUtils.Graphics.DpiX).ToString()), - RowOffset = new Xdr.RowOffset(ConvertToEnglishMetricUnits(moveFromMarker.Offset.Y, GraphicsUtils.Graphics.DpiY).ToString()) - }; - - var oneCellAnchor = new Xdr.OneCellAnchor( - fMark, - new Xdr.Extent - { - Cx = extentsCx, - Cy = extentsCy - }, - new Xdr.Picture( - new Xdr.NonVisualPictureProperties( - new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = pic.Name }, - new Xdr.NonVisualPictureDrawingProperties(new PictureLocks { NoChangeAspect = true }) - ), - new Xdr.BlipFill( - new Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = BlipCompressionValues.Print }, - new Stretch(new FillRectangle()) - ), - new Xdr.ShapeProperties( - new Transform2D( - new Offset { X = 0, Y = 0 }, - new Extents { Cx = extentsCx, Cy = extentsCy } - ), - new PresetGeometry { Preset = ShapeTypeValues.Rectangle } - ) - ), - new Xdr.ClientData() - ); - - worksheetDrawing.Append(oneCellAnchor); - break; - } - } - - private static void RebasePictureIds(WorksheetPart worksheetPart) - { - for (var i = 0; i < worksheetPart.DrawingsPart.WorksheetDrawing.ChildElements.Count; i++) - { - var anchor = worksheetPart.DrawingsPart.WorksheetDrawing.ElementAt(i); - var props = GetPropertiesFromAnchor(anchor); - props.Id = Convert.ToUInt32(i + 1); - } - } - - private static Vml.TextBox GetTextBox(IXLDrawingStyle ds) - { - var sb = new StringBuilder(); - var a = ds.Alignment; - - if (a.Direction == XLDrawingTextDirection.Context) - sb.Append("mso-direction-alt:auto;"); - else if (a.Direction == XLDrawingTextDirection.RightToLeft) - sb.Append("direction:RTL;"); - - if (a.Orientation != XLDrawingTextOrientation.LeftToRight) - { - sb.Append("layout-flow:vertical;"); - if (a.Orientation == XLDrawingTextOrientation.BottomToTop) - sb.Append("mso-layout-flow-alt:bottom-to-top;"); - else if (a.Orientation == XLDrawingTextOrientation.Vertical) - sb.Append("mso-layout-flow-alt:top-to-bottom;"); - } - if (a.AutomaticSize) - sb.Append("mso-fit-shape-to-text:t;"); - var retVal = new Vml.TextBox { Style = sb.ToString() }; - var dm = ds.Margins; - if (!dm.Automatic) - retVal.Inset = String.Format("{0}in,{1}in,{2}in,{3}in", - dm.Left.ToInvariantString(), - dm.Top.ToInvariantString(), - dm.Right.ToInvariantString(), - dm.Bottom.ToInvariantString()); - - return retVal; - } - - private static Anchor GetAnchor(XLCell cell) - { - var c = cell.Comment; - var cWidth = c.Style.Size.Width; - var fcNumber = c.Position.Column - 1; - var fcOffset = Convert.ToInt32(c.Position.ColumnOffset * 7.5); - var widthFromColumns = cell.Worksheet.Column(c.Position.Column).Width - c.Position.ColumnOffset; - var lastCell = cell.CellRight(c.Position.Column - cell.Address.ColumnNumber); - while (widthFromColumns <= cWidth) - { - lastCell = lastCell.CellRight(); - widthFromColumns += lastCell.WorksheetColumn().Width; - } - - var lcNumber = lastCell.WorksheetColumn().ColumnNumber() - 1; - var lcOffset = Convert.ToInt32((lastCell.WorksheetColumn().Width - (widthFromColumns - cWidth)) * 7.5); - - var cHeight = c.Style.Size.Height; //c.Style.Size.Height * 72.0; - var frNumber = c.Position.Row - 1; - var frOffset = Convert.ToInt32(c.Position.RowOffset); - var heightFromRows = cell.Worksheet.Row(c.Position.Row).Height - c.Position.RowOffset; - lastCell = cell.CellBelow(c.Position.Row - cell.Address.RowNumber); - while (heightFromRows <= cHeight) - { - lastCell = lastCell.CellBelow(); - heightFromRows += lastCell.WorksheetRow().Height; - } - - var lrNumber = lastCell.WorksheetRow().RowNumber() - 1; - var lrOffset = Convert.ToInt32(lastCell.WorksheetRow().Height - (heightFromRows - cHeight)); - return new Anchor - { - Text = string.Format("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}", - fcNumber, fcOffset, - frNumber, frOffset, - lcNumber, lcOffset, - lrNumber, lrOffset - ) - }; - } - - private static StringValue GetCommentStyle(XLCell cell) - { - var c = cell.Comment; - var sb = new StringBuilder("position:absolute; "); - - sb.Append("visibility:"); - sb.Append(c.Visible ? "visible" : "hidden"); - sb.Append(";"); - - sb.Append("width:"); - sb.Append(Math.Round(c.Style.Size.Width * 7.5, 2).ToInvariantString()); - sb.Append("pt;"); - sb.Append("height:"); - sb.Append(Math.Round(c.Style.Size.Height, 2).ToInvariantString()); - sb.Append("pt;"); - - sb.Append("z-index:"); - sb.Append(c.ZOrder.ToString()); - - return sb.ToString(); - } - - #region GenerateWorkbookStylesPartContent - - private void GenerateWorkbookStylesPartContent(WorkbookStylesPart workbookStylesPart, SaveContext context) - { - var defaultStyle = new XLStyle(null, DefaultStyle); - var defaultStyleId = GetStyleId(defaultStyle); - if (!context.SharedFonts.ContainsKey(defaultStyle.Font)) - context.SharedFonts.Add(defaultStyle.Font, new FontInfo { FontId = 0, Font = defaultStyle.Font as XLFont }); - - var sharedFills = new Dictionary - {{defaultStyle.Fill, new FillInfo {FillId = 2, Fill = defaultStyle.Fill as XLFill}}}; - - var sharedBorders = new Dictionary - {{defaultStyle.Border, new BorderInfo {BorderId = 0, Border = defaultStyle.Border as XLBorder}}}; - - var sharedNumberFormats = new Dictionary - { - { - defaultStyle.NumberFormat, - new NumberFormatInfo - {NumberFormatId = 0, NumberFormat = defaultStyle.NumberFormat} - } - }; - - //Dictionary sharedAlignments = new Dictionary(); - //sharedAlignments.Add(defaultStyle.Alignment.ToString(), new AlignmentInfo() { AlignmentId = 0, Alignment = defaultStyle.Alignment }); - - if (workbookStylesPart.Stylesheet == null) - workbookStylesPart.Stylesheet = new Stylesheet(); - - // Cell styles = Named styles - if (workbookStylesPart.Stylesheet.CellStyles == null) - workbookStylesPart.Stylesheet.CellStyles = new CellStyles(); - - // To determine the default workbook style, we look for the style with builtInId = 0 (I hope that is the correct approach) - UInt32 defaultFormatId; - if (workbookStylesPart.Stylesheet.CellStyles.Elements().Any(c => c.BuiltinId != null && c.BuiltinId.HasValue && c.BuiltinId.Value == 0)) - { - // Possible to have duplicate default cell styles - occurs when file gets saved under different cultures. - // We prefer the style that is named Normal - var normalCellStyles = workbookStylesPart.Stylesheet.CellStyles.Elements() - .Where(c => c.BuiltinId != null && c.BuiltinId.HasValue && c.BuiltinId.Value == 0) - .OrderBy(c => c.Name != null && c.Name.HasValue && c.Name.Value == "Normal"); - - defaultFormatId = normalCellStyles.Last().FormatId.Value; - } - else if (workbookStylesPart.Stylesheet.CellStyles.Elements().Any()) - defaultFormatId = workbookStylesPart.Stylesheet.CellStyles.Elements().Max(c => c.FormatId.Value) + 1; - else - defaultFormatId = 0; - - context.SharedStyles.Add(defaultStyleId, - new StyleInfo - { - StyleId = defaultFormatId, - Style = defaultStyle, - FontId = 0, - FillId = 0, - BorderId = 0, - NumberFormatId = 0 - //AlignmentId = 0 - }); - - UInt32 styleCount = 1; - UInt32 fontCount = 1; - UInt32 fillCount = 3; - UInt32 borderCount = 1; - var numberFormatCount = 1; - var xlStyles = new HashSet(); - var pivotTableNumberFormats = new HashSet(); - - foreach (var worksheet in WorksheetsInternal) - { - foreach (var s in worksheet.GetStyleIds().Where(s => !xlStyles.Contains(s))) - xlStyles.Add(s); - - foreach ( - var s in - worksheet.Internals.ColumnsCollection.Select(kp => kp.Value.GetStyleId()).Where( - s => !xlStyles.Contains(s))) - xlStyles.Add(s); - - foreach ( - var s in - worksheet.Internals.RowsCollection.Select(kp => kp.Value.GetStyleId()).Where( - s => !xlStyles.Contains(s)) - ) - xlStyles.Add(s); - - foreach (var ptnf in worksheet.PivotTables.SelectMany(pt => pt.Values.Select(ptv => ptv.NumberFormat)).Distinct().Where(nf => !pivotTableNumberFormats.Contains(nf))) - pivotTableNumberFormats.Add(ptnf); - } - - foreach (var numberFormat in pivotTableNumberFormats) - { - if (numberFormat.NumberFormatId != -1 - || sharedNumberFormats.ContainsKey(numberFormat)) - continue; - - sharedNumberFormats.Add(numberFormat, - new NumberFormatInfo - { - NumberFormatId = XLConstants.NumberOfBuiltInStyles + numberFormatCount, - NumberFormat = numberFormat - }); - numberFormatCount++; - } - - foreach (var xlStyle in xlStyles.Select(GetStyleById)) - { - if (!context.SharedFonts.ContainsKey(xlStyle.Font)) - context.SharedFonts.Add(xlStyle.Font, - new FontInfo { FontId = fontCount++, Font = xlStyle.Font as XLFont }); - - if (!sharedFills.ContainsKey(xlStyle.Fill)) - sharedFills.Add(xlStyle.Fill, new FillInfo { FillId = fillCount++, Fill = xlStyle.Fill as XLFill }); - - if (!sharedBorders.ContainsKey(xlStyle.Border)) - sharedBorders.Add(xlStyle.Border, - new BorderInfo { BorderId = borderCount++, Border = xlStyle.Border as XLBorder }); - - if (xlStyle.NumberFormat.NumberFormatId != -1 - || sharedNumberFormats.ContainsKey(xlStyle.NumberFormat)) - continue; - - sharedNumberFormats.Add(xlStyle.NumberFormat, - new NumberFormatInfo - { - NumberFormatId = XLConstants.NumberOfBuiltInStyles + numberFormatCount, - NumberFormat = xlStyle.NumberFormat - }); - numberFormatCount++; - } - - var allSharedNumberFormats = ResolveNumberFormats(workbookStylesPart, sharedNumberFormats, defaultFormatId); - foreach (var nf in allSharedNumberFormats) - { - context.SharedNumberFormats.Add(nf.Value.NumberFormatId, nf.Value); - } - - ResolveFonts(workbookStylesPart, context); - var allSharedFills = ResolveFills(workbookStylesPart, sharedFills); - var allSharedBorders = ResolveBorders(workbookStylesPart, sharedBorders); - - foreach (var id in xlStyles) - { - var xlStyle = GetStyleById(id); - if (context.SharedStyles.ContainsKey(id)) continue; - - var numberFormatId = xlStyle.NumberFormat.NumberFormatId >= 0 - ? xlStyle.NumberFormat.NumberFormatId - : allSharedNumberFormats[xlStyle.NumberFormat].NumberFormatId; - - context.SharedStyles.Add(id, - new StyleInfo - { - StyleId = styleCount++, - Style = xlStyle, - FontId = context.SharedFonts[xlStyle.Font].FontId, - FillId = allSharedFills[xlStyle.Fill].FillId, - BorderId = allSharedBorders[xlStyle.Border].BorderId, - NumberFormatId = numberFormatId - }); - } - - ResolveCellStyleFormats(workbookStylesPart, context); - ResolveRest(workbookStylesPart, context); - - if (!workbookStylesPart.Stylesheet.CellStyles.Elements().Any(c => c.BuiltinId != null && c.BuiltinId.HasValue && c.BuiltinId.Value == 0U)) - workbookStylesPart.Stylesheet.CellStyles.AppendChild(new CellStyle { Name = "Normal", FormatId = defaultFormatId, BuiltinId = 0U }); - - workbookStylesPart.Stylesheet.CellStyles.Count = (UInt32)workbookStylesPart.Stylesheet.CellStyles.Count(); - - var newSharedStyles = new Dictionary(); - foreach (var ss in context.SharedStyles) - { - var styleId = -1; - foreach (CellFormat f in workbookStylesPart.Stylesheet.CellFormats) - { - styleId++; - if (CellFormatsAreEqual(f, ss.Value)) - break; - } - if (styleId == -1) - styleId = 0; - var si = ss.Value; - si.StyleId = (UInt32)styleId; - newSharedStyles.Add(ss.Key, si); - } - context.SharedStyles.Clear(); - newSharedStyles.ForEach(kp => context.SharedStyles.Add(kp.Key, kp.Value)); - - AddDifferentialFormats(workbookStylesPart, context); - } - - private void AddDifferentialFormats(WorkbookStylesPart workbookStylesPart, SaveContext context) - { - if (workbookStylesPart.Stylesheet.DifferentialFormats == null) - workbookStylesPart.Stylesheet.DifferentialFormats = new DifferentialFormats(); - - var differentialFormats = workbookStylesPart.Stylesheet.DifferentialFormats; - - FillDifferentialFormatsCollection(differentialFormats, context.DifferentialFormats); - - foreach (var ws in Worksheets) - { - foreach (var cf in ws.ConditionalFormats) - { - if (!context.DifferentialFormats.ContainsKey(cf.Style)) - AddDifferentialFormat(workbookStylesPart.Stylesheet.DifferentialFormats, cf, context); - } - } - - differentialFormats.Count = (UInt32)differentialFormats.Count(); - if (differentialFormats.Count == 0) - workbookStylesPart.Stylesheet.DifferentialFormats = null; - } - - private void FillDifferentialFormatsCollection(DifferentialFormats differentialFormats, - Dictionary dictionary) - { - dictionary.Clear(); - var id = 0; - foreach (var df in differentialFormats.Elements()) - { - var style = new XLStyle(new XLStylizedEmpty(DefaultStyle), DefaultStyle); - LoadFont(df.Font, style.Font); - LoadBorder(df.Border, style.Border); - LoadNumberFormat(df.NumberingFormat, style.NumberFormat); - LoadFill(df.Fill, style.Fill); - if (!dictionary.ContainsKey(style)) - dictionary.Add(style, ++id); - } - } - - private static void AddDifferentialFormat(DifferentialFormats differentialFormats, IXLConditionalFormat cf, - SaveContext context) - { - var differentialFormat = new DifferentialFormat(); - differentialFormat.Append(GetNewFont(new FontInfo { Font = cf.Style.Font as XLFont }, false)); - if (!XLHelper.IsNullOrWhiteSpace(cf.Style.NumberFormat.Format)) - { - var numberFormat = new NumberingFormat - { - NumberFormatId = (UInt32)(XLConstants.NumberOfBuiltInStyles + differentialFormats.Count()), - FormatCode = cf.Style.NumberFormat.Format - }; - differentialFormat.Append(numberFormat); - } - differentialFormat.Append(GetNewFill(new FillInfo { Fill = cf.Style.Fill as XLFill }, false)); - differentialFormat.Append(GetNewBorder(new BorderInfo { Border = cf.Style.Border as XLBorder }, false)); - - differentialFormats.Append(differentialFormat); - - context.DifferentialFormats.Add(cf.Style, differentialFormats.Count() - 1); - } - - private static void ResolveRest(WorkbookStylesPart workbookStylesPart, SaveContext context) - { - if (workbookStylesPart.Stylesheet.CellFormats == null) - workbookStylesPart.Stylesheet.CellFormats = new CellFormats(); - - foreach (var styleInfo in context.SharedStyles.Values) - { - var info = styleInfo; - var foundOne = - workbookStylesPart.Stylesheet.CellFormats.Cast().Any(f => CellFormatsAreEqual(f, info)); - - if (foundOne) continue; - - var cellFormat = GetCellFormat(styleInfo); - cellFormat.FormatId = 0; - var alignment = new Alignment - { - Horizontal = styleInfo.Style.Alignment.Horizontal.ToOpenXml(), - Vertical = styleInfo.Style.Alignment.Vertical.ToOpenXml(), - Indent = (UInt32)styleInfo.Style.Alignment.Indent, - ReadingOrder = (UInt32)styleInfo.Style.Alignment.ReadingOrder, - WrapText = styleInfo.Style.Alignment.WrapText, - TextRotation = (UInt32)styleInfo.Style.Alignment.TextRotation, - ShrinkToFit = styleInfo.Style.Alignment.ShrinkToFit, - RelativeIndent = styleInfo.Style.Alignment.RelativeIndent, - JustifyLastLine = styleInfo.Style.Alignment.JustifyLastLine - }; - cellFormat.AppendChild(alignment); - - if (cellFormat.ApplyProtection.Value) - cellFormat.AppendChild(GetProtection(styleInfo)); - - workbookStylesPart.Stylesheet.CellFormats.AppendChild(cellFormat); - } - workbookStylesPart.Stylesheet.CellFormats.Count = (UInt32)workbookStylesPart.Stylesheet.CellFormats.Count(); - } - - private static void ResolveCellStyleFormats(WorkbookStylesPart workbookStylesPart, - SaveContext context) - { - if (workbookStylesPart.Stylesheet.CellStyleFormats == null) - workbookStylesPart.Stylesheet.CellStyleFormats = new CellStyleFormats(); - - foreach (var styleInfo in context.SharedStyles.Values) - { - var info = styleInfo; - var foundOne = - workbookStylesPart.Stylesheet.CellStyleFormats.Cast().Any( - f => CellFormatsAreEqual(f, info)); - - if (foundOne) continue; - - var cellStyleFormat = GetCellFormat(styleInfo); - - if (cellStyleFormat.ApplyProtection.Value) - cellStyleFormat.AppendChild(GetProtection(styleInfo)); - - workbookStylesPart.Stylesheet.CellStyleFormats.AppendChild(cellStyleFormat); - } - workbookStylesPart.Stylesheet.CellStyleFormats.Count = - (UInt32)workbookStylesPart.Stylesheet.CellStyleFormats.Count(); - } - - private static bool ApplyFill(StyleInfo styleInfo) - { - return styleInfo.Style.Fill.PatternType.ToOpenXml() == PatternValues.None; - } - - private static bool ApplyBorder(StyleInfo styleInfo) - { - var opBorder = styleInfo.Style.Border; - return (opBorder.BottomBorder.ToOpenXml() != BorderStyleValues.None - || opBorder.DiagonalBorder.ToOpenXml() != BorderStyleValues.None - || opBorder.RightBorder.ToOpenXml() != BorderStyleValues.None - || opBorder.LeftBorder.ToOpenXml() != BorderStyleValues.None - || opBorder.TopBorder.ToOpenXml() != BorderStyleValues.None); - } - - private static bool ApplyProtection(StyleInfo styleInfo) - { - return styleInfo.Style.Protection != null; - } - - private static CellFormat GetCellFormat(StyleInfo styleInfo) - { - var cellFormat = new CellFormat - { - NumberFormatId = (UInt32)styleInfo.NumberFormatId, - FontId = styleInfo.FontId, - FillId = styleInfo.FillId, - BorderId = styleInfo.BorderId, - ApplyNumberFormat = true, - ApplyAlignment = true, - ApplyFill = ApplyFill(styleInfo), - ApplyBorder = ApplyBorder(styleInfo), - ApplyProtection = ApplyProtection(styleInfo) - }; - return cellFormat; - } - - private static Protection GetProtection(StyleInfo styleInfo) - { - return new Protection - { - Locked = styleInfo.Style.Protection.Locked, - Hidden = styleInfo.Style.Protection.Hidden - }; - } - - private static bool CellFormatsAreEqual(CellFormat f, StyleInfo styleInfo) - { - return - f.BorderId != null && styleInfo.BorderId == f.BorderId - && f.FillId != null && styleInfo.FillId == f.FillId - && f.FontId != null && styleInfo.FontId == f.FontId - && f.NumberFormatId != null && styleInfo.NumberFormatId == f.NumberFormatId - && f.ApplyFill != null && f.ApplyFill == ApplyFill(styleInfo) - && f.ApplyBorder != null && f.ApplyBorder == ApplyBorder(styleInfo) - && AlignmentsAreEqual(f.Alignment, styleInfo.Style.Alignment) - && ProtectionsAreEqual(f.Protection, styleInfo.Style.Protection) - ; - } - - private static bool ProtectionsAreEqual(Protection protection, IXLProtection xlProtection) - { - var p = new XLProtection(); - if (protection != null) - { - if (protection.Locked != null) - p.Locked = protection.Locked.Value; - if (protection.Hidden != null) - p.Hidden = protection.Hidden.Value; - } - return p.Equals(xlProtection); - } - - private static bool AlignmentsAreEqual(Alignment alignment, IXLAlignment xlAlignment) - { - var a = new XLAlignment(); - if (alignment != null) - { - if (alignment.Indent != null) - a.Indent = (Int32)alignment.Indent.Value; - - if (alignment.Horizontal != null) - a.Horizontal = alignment.Horizontal.Value.ToClosedXml(); - if (alignment.Vertical != null) - a.Vertical = alignment.Vertical.Value.ToClosedXml(); - - if (alignment.ReadingOrder != null) - a.ReadingOrder = alignment.ReadingOrder.Value.ToClosedXml(); - if (alignment.WrapText != null) - a.WrapText = alignment.WrapText.Value; - if (alignment.TextRotation != null) - a.TextRotation = (Int32)alignment.TextRotation.Value; - if (alignment.ShrinkToFit != null) - a.ShrinkToFit = alignment.ShrinkToFit.Value; - if (alignment.RelativeIndent != null) - a.RelativeIndent = alignment.RelativeIndent.Value; - if (alignment.JustifyLastLine != null) - a.JustifyLastLine = alignment.JustifyLastLine.Value; - } - return a.Equals(xlAlignment); - } - - private Dictionary ResolveBorders(WorkbookStylesPart workbookStylesPart, - Dictionary sharedBorders) - { - if (workbookStylesPart.Stylesheet.Borders == null) - workbookStylesPart.Stylesheet.Borders = new Borders(); - - var allSharedBorders = new Dictionary(); - foreach (var borderInfo in sharedBorders.Values) - { - var borderId = 0; - var foundOne = false; - foreach (Border f in workbookStylesPart.Stylesheet.Borders) - { - if (BordersAreEqual(f, borderInfo.Border)) - { - foundOne = true; - break; - } - borderId++; - } - if (!foundOne) - { - var border = GetNewBorder(borderInfo); - workbookStylesPart.Stylesheet.Borders.AppendChild(border); - } - allSharedBorders.Add(borderInfo.Border, - new BorderInfo { Border = borderInfo.Border, BorderId = (UInt32)borderId }); - } - workbookStylesPart.Stylesheet.Borders.Count = (UInt32)workbookStylesPart.Stylesheet.Borders.Count(); - return allSharedBorders; - } - - private static Border GetNewBorder(BorderInfo borderInfo, Boolean ignoreMod = true) - { - var border = new Border(); - if (borderInfo.Border.DiagonalUpModified || ignoreMod) - border.DiagonalUp = borderInfo.Border.DiagonalUp; - - if (borderInfo.Border.DiagonalDownModified || ignoreMod) - border.DiagonalDown = borderInfo.Border.DiagonalDown; - - if (borderInfo.Border.LeftBorderModified || borderInfo.Border.LeftBorderColorModified || ignoreMod) - { - var leftBorder = new LeftBorder { Style = borderInfo.Border.LeftBorder.ToOpenXml() }; - if (borderInfo.Border.LeftBorderColorModified || ignoreMod) - { - var leftBorderColor = GetNewColor(borderInfo.Border.LeftBorderColor); - leftBorder.AppendChild(leftBorderColor); - } - border.AppendChild(leftBorder); - } - - if (borderInfo.Border.RightBorderModified || borderInfo.Border.RightBorderColorModified || ignoreMod) - { - var rightBorder = new RightBorder { Style = borderInfo.Border.RightBorder.ToOpenXml() }; - if (borderInfo.Border.RightBorderColorModified || ignoreMod) - { - var rightBorderColor = GetNewColor(borderInfo.Border.RightBorderColor); - rightBorder.AppendChild(rightBorderColor); - } - border.AppendChild(rightBorder); - } - - if (borderInfo.Border.TopBorderModified || borderInfo.Border.TopBorderColorModified || ignoreMod) - { - var topBorder = new TopBorder { Style = borderInfo.Border.TopBorder.ToOpenXml() }; - if (borderInfo.Border.TopBorderColorModified || ignoreMod) - { - var topBorderColor = GetNewColor(borderInfo.Border.TopBorderColor); - topBorder.AppendChild(topBorderColor); - } - border.AppendChild(topBorder); - } - - if (borderInfo.Border.BottomBorderModified || borderInfo.Border.BottomBorderColorModified || ignoreMod) - { - var bottomBorder = new BottomBorder { Style = borderInfo.Border.BottomBorder.ToOpenXml() }; - if (borderInfo.Border.BottomBorderColorModified || ignoreMod) - { - var bottomBorderColor = GetNewColor(borderInfo.Border.BottomBorderColor); - bottomBorder.AppendChild(bottomBorderColor); - } - border.AppendChild(bottomBorder); - } - - if (borderInfo.Border.DiagonalBorderModified || borderInfo.Border.DiagonalBorderColorModified || ignoreMod) - { - var DiagonalBorder = new DiagonalBorder { Style = borderInfo.Border.DiagonalBorder.ToOpenXml() }; - if (borderInfo.Border.DiagonalBorderColorModified || ignoreMod) - { - var DiagonalBorderColor = GetNewColor(borderInfo.Border.DiagonalBorderColor); - DiagonalBorder.AppendChild(DiagonalBorderColor); - } - border.AppendChild(DiagonalBorder); - } - - return border; - } - - private bool BordersAreEqual(Border b, IXLBorder xlBorder) - { - var nb = new XLBorder(); - if (b.DiagonalUp != null) - nb.DiagonalUp = b.DiagonalUp.Value; - - if (b.DiagonalDown != null) - nb.DiagonalDown = b.DiagonalDown.Value; - - if (b.LeftBorder != null) - { - if (b.LeftBorder.Style != null) - nb.LeftBorder = b.LeftBorder.Style.Value.ToClosedXml(); - var bColor = GetColor(b.LeftBorder.Color); - if (bColor.HasValue) - nb.LeftBorderColor = bColor; - } - - if (b.RightBorder != null) - { - if (b.RightBorder.Style != null) - nb.RightBorder = b.RightBorder.Style.Value.ToClosedXml(); - var bColor = GetColor(b.RightBorder.Color); - if (bColor.HasValue) - nb.RightBorderColor = bColor; - } - - if (b.TopBorder != null) - { - if (b.TopBorder.Style != null) - nb.TopBorder = b.TopBorder.Style.Value.ToClosedXml(); - var bColor = GetColor(b.TopBorder.Color); - if (bColor.HasValue) - nb.TopBorderColor = bColor; - } - - if (b.BottomBorder != null) - { - if (b.BottomBorder.Style != null) - nb.BottomBorder = b.BottomBorder.Style.Value.ToClosedXml(); - var bColor = GetColor(b.BottomBorder.Color); - if (bColor.HasValue) - nb.BottomBorderColor = bColor; - } - - return nb.Equals(xlBorder); - } - - private Dictionary ResolveFills(WorkbookStylesPart workbookStylesPart, - Dictionary sharedFills) - { - if (workbookStylesPart.Stylesheet.Fills == null) - workbookStylesPart.Stylesheet.Fills = new Fills(); - - ResolveFillWithPattern(workbookStylesPart.Stylesheet.Fills, PatternValues.None); - ResolveFillWithPattern(workbookStylesPart.Stylesheet.Fills, PatternValues.Gray125); - - var allSharedFills = new Dictionary(); - foreach (var fillInfo in sharedFills.Values) - { - var fillId = 0; - var foundOne = false; - foreach (Fill f in workbookStylesPart.Stylesheet.Fills) - { - if (FillsAreEqual(f, fillInfo.Fill)) - { - foundOne = true; - break; - } - fillId++; - } - if (!foundOne) - { - var fill = GetNewFill(fillInfo); - workbookStylesPart.Stylesheet.Fills.AppendChild(fill); - } - allSharedFills.Add(fillInfo.Fill, new FillInfo { Fill = fillInfo.Fill, FillId = (UInt32)fillId }); - } - - workbookStylesPart.Stylesheet.Fills.Count = (UInt32)workbookStylesPart.Stylesheet.Fills.Count(); - return allSharedFills; - } - - private static void ResolveFillWithPattern(Fills fills, PatternValues patternValues) - { - if (fills.Elements().Any(f => - f.PatternFill.PatternType == patternValues - && f.PatternFill.ForegroundColor == null - && f.PatternFill.BackgroundColor == null - )) return; - - var fill1 = new Fill(); - var patternFill1 = new PatternFill { PatternType = patternValues }; - fill1.AppendChild(patternFill1); - fills.AppendChild(fill1); - } - - private static Fill GetNewFill(FillInfo fillInfo, Boolean ignoreMod = true) - { - var fill = new Fill(); - - var patternFill = new PatternFill(); - if (fillInfo.Fill.PatternTypeModified || ignoreMod) - patternFill.PatternType = fillInfo.Fill.PatternType.ToOpenXml(); - - if (fillInfo.Fill.PatternColorModified || ignoreMod) - { - var foregroundColor = new ForegroundColor(); - if (fillInfo.Fill.PatternColor.ColorType == XLColorType.Color) - foregroundColor.Rgb = fillInfo.Fill.PatternColor.Color.ToHex(); - else if (fillInfo.Fill.PatternColor.ColorType == XLColorType.Indexed) - foregroundColor.Indexed = (UInt32)fillInfo.Fill.PatternColor.Indexed; - else - { - foregroundColor.Theme = (UInt32)fillInfo.Fill.PatternColor.ThemeColor; - if (fillInfo.Fill.PatternColor.ThemeTint != 0) - foregroundColor.Tint = fillInfo.Fill.PatternColor.ThemeTint; - } - patternFill.AppendChild(foregroundColor); - } - - if (fillInfo.Fill.PatternBackgroundColorModified || ignoreMod) - { - var backgroundColor = new BackgroundColor(); - if (fillInfo.Fill.PatternBackgroundColor.ColorType == XLColorType.Color) - backgroundColor.Rgb = fillInfo.Fill.PatternBackgroundColor.Color.ToHex(); - else if (fillInfo.Fill.PatternBackgroundColor.ColorType == XLColorType.Indexed) - backgroundColor.Indexed = (UInt32)fillInfo.Fill.PatternBackgroundColor.Indexed; - else - { - backgroundColor.Theme = (UInt32)fillInfo.Fill.PatternBackgroundColor.ThemeColor; - if (fillInfo.Fill.PatternBackgroundColor.ThemeTint != 0) - backgroundColor.Tint = fillInfo.Fill.PatternBackgroundColor.ThemeTint; - } - patternFill.AppendChild(backgroundColor); - } - - fill.AppendChild(patternFill); - - return fill; - } - - private bool FillsAreEqual(Fill f, IXLFill xlFill) - { - var nF = new XLFill(); - if (f.PatternFill != null) - { - if (f.PatternFill.PatternType != null) - nF.PatternType = f.PatternFill.PatternType.Value.ToClosedXml(); - - var fColor = GetColor(f.PatternFill.ForegroundColor); - if (fColor.HasValue) - nF.PatternColor = fColor; - - var bColor = GetColor(f.PatternFill.BackgroundColor); - if (bColor.HasValue) - nF.PatternBackgroundColor = bColor; - } - return nF.Equals(xlFill); - } - - private void ResolveFonts(WorkbookStylesPart workbookStylesPart, SaveContext context) - { - if (workbookStylesPart.Stylesheet.Fonts == null) - workbookStylesPart.Stylesheet.Fonts = new Fonts(); - - var newFonts = new Dictionary(); - foreach (var fontInfo in context.SharedFonts.Values) - { - var fontId = 0; - var foundOne = false; - foreach (Font f in workbookStylesPart.Stylesheet.Fonts) - { - if (FontsAreEqual(f, fontInfo.Font)) - { - foundOne = true; - break; - } - fontId++; - } - if (!foundOne) - { - var font = GetNewFont(fontInfo); - workbookStylesPart.Stylesheet.Fonts.AppendChild(font); - } - newFonts.Add(fontInfo.Font, new FontInfo { Font = fontInfo.Font, FontId = (UInt32)fontId }); - } - context.SharedFonts.Clear(); - foreach (var kp in newFonts) - context.SharedFonts.Add(kp.Key, kp.Value); - - workbookStylesPart.Stylesheet.Fonts.Count = (UInt32)workbookStylesPart.Stylesheet.Fonts.Count(); - } - - private static Font GetNewFont(FontInfo fontInfo, Boolean ignoreMod = true) - { - var font = new Font(); - var bold = (fontInfo.Font.BoldModified || ignoreMod) && fontInfo.Font.Bold ? new Bold() : null; - var italic = (fontInfo.Font.ItalicModified || ignoreMod) && fontInfo.Font.Italic ? new Italic() : null; - var underline = (fontInfo.Font.UnderlineModified || ignoreMod) && - fontInfo.Font.Underline != XLFontUnderlineValues.None - ? new Underline { Val = fontInfo.Font.Underline.ToOpenXml() } - : null; - var strike = (fontInfo.Font.StrikethroughModified || ignoreMod) && fontInfo.Font.Strikethrough - ? new Strike() - : null; - var verticalAlignment = fontInfo.Font.VerticalAlignmentModified || ignoreMod - ? new VerticalTextAlignment { Val = fontInfo.Font.VerticalAlignment.ToOpenXml() } - : null; - var shadow = (fontInfo.Font.ShadowModified || ignoreMod) && fontInfo.Font.Shadow ? new Shadow() : null; - var fontSize = fontInfo.Font.FontSizeModified || ignoreMod - ? new FontSize { Val = fontInfo.Font.FontSize } - : null; - var color = fontInfo.Font.FontColorModified || ignoreMod ? GetNewColor(fontInfo.Font.FontColor) : null; - - var fontName = fontInfo.Font.FontNameModified || ignoreMod - ? new FontName { Val = fontInfo.Font.FontName } - : null; - var fontFamilyNumbering = fontInfo.Font.FontFamilyNumberingModified || ignoreMod - ? new FontFamilyNumbering { Val = (Int32)fontInfo.Font.FontFamilyNumbering } - : null; - - if (bold != null) - font.AppendChild(bold); - if (italic != null) - font.AppendChild(italic); - if (underline != null) - font.AppendChild(underline); - if (strike != null) - font.AppendChild(strike); - if (verticalAlignment != null) - font.AppendChild(verticalAlignment); - if (shadow != null) - font.AppendChild(shadow); - if (fontSize != null) - font.AppendChild(fontSize); - if (color != null) - font.AppendChild(color); - if (fontName != null) - font.AppendChild(fontName); - if (fontFamilyNumbering != null) - font.AppendChild(fontFamilyNumbering); - - return font; - } - - private static Color GetNewColor(XLColor xlColor) - { - var color = new Color(); - if (xlColor.ColorType == XLColorType.Color) - color.Rgb = xlColor.Color.ToHex(); - else if (xlColor.ColorType == XLColorType.Indexed) - color.Indexed = (UInt32)xlColor.Indexed; - else - { - color.Theme = (UInt32)xlColor.ThemeColor; - if (xlColor.ThemeTint != 0) - color.Tint = xlColor.ThemeTint; - } - return color; - } - - private static TabColor GetTabColor(XLColor xlColor) - { - var color = new TabColor(); - if (xlColor.ColorType == XLColorType.Color) - color.Rgb = xlColor.Color.ToHex(); - else if (xlColor.ColorType == XLColorType.Indexed) - color.Indexed = (UInt32)xlColor.Indexed; - else - { - color.Theme = (UInt32)xlColor.ThemeColor; - if (xlColor.ThemeTint != 0) - color.Tint = xlColor.ThemeTint; - } - return color; - } - - private bool FontsAreEqual(Font f, IXLFont xlFont) - { - var nf = new XLFont { Bold = f.Bold != null, Italic = f.Italic != null }; - if (f.Underline != null) - { - nf.Underline = f.Underline.Val != null - ? f.Underline.Val.Value.ToClosedXml() - : XLFontUnderlineValues.Single; - } - nf.Strikethrough = f.Strike != null; - if (f.VerticalTextAlignment != null) - { - nf.VerticalAlignment = f.VerticalTextAlignment.Val != null - ? f.VerticalTextAlignment.Val.Value.ToClosedXml() - : XLFontVerticalTextAlignmentValues.Baseline; - } - nf.Shadow = f.Shadow != null; - if (f.FontSize != null) - nf.FontSize = f.FontSize.Val; - var fColor = GetColor(f.Color); - if (fColor.HasValue) - nf.FontColor = fColor; - if (f.FontName != null) - nf.FontName = f.FontName.Val; - if (f.FontFamilyNumbering != null) - nf.FontFamilyNumbering = (XLFontFamilyNumberingValues)f.FontFamilyNumbering.Val.Value; - - return nf.Equals(xlFont); - } - - private static Dictionary ResolveNumberFormats( - WorkbookStylesPart workbookStylesPart, - Dictionary sharedNumberFormats, - UInt32 defaultFormatId) - { - if (workbookStylesPart.Stylesheet.NumberingFormats == null) - { - workbookStylesPart.Stylesheet.NumberingFormats = new NumberingFormats(); - workbookStylesPart.Stylesheet.NumberingFormats.AppendChild(new NumberingFormat() - { - NumberFormatId = 0, - FormatCode = "" - }); - } - - var allSharedNumberFormats = new Dictionary(); - foreach (var numberFormatInfo in sharedNumberFormats.Values.Where(nf => nf.NumberFormatId != defaultFormatId)) - { - var numberingFormatId = XLConstants.NumberOfBuiltInStyles + 1; - var foundOne = false; - foreach (NumberingFormat nf in workbookStylesPart.Stylesheet.NumberingFormats) - { - if (NumberFormatsAreEqual(nf, numberFormatInfo.NumberFormat)) - { - foundOne = true; - numberingFormatId = (Int32)nf.NumberFormatId.Value; - break; - } - numberingFormatId++; - } - if (!foundOne) - { - var numberingFormat = new NumberingFormat - { - NumberFormatId = (UInt32)numberingFormatId, - FormatCode = numberFormatInfo.NumberFormat.Format - }; - workbookStylesPart.Stylesheet.NumberingFormats.AppendChild(numberingFormat); - } - allSharedNumberFormats.Add(numberFormatInfo.NumberFormat, - new NumberFormatInfo - { - NumberFormat = numberFormatInfo.NumberFormat, - NumberFormatId = numberingFormatId - }); - } - workbookStylesPart.Stylesheet.NumberingFormats.Count = - (UInt32)workbookStylesPart.Stylesheet.NumberingFormats.Count(); - return allSharedNumberFormats; - } - - private static bool NumberFormatsAreEqual(NumberingFormat nf, IXLNumberFormatBase xlNumberFormat) - { - var newXLNumberFormat = new XLNumberFormat(); - - if (nf.FormatCode != null && !XLHelper.IsNullOrWhiteSpace(nf.FormatCode.Value)) - newXLNumberFormat.Format = nf.FormatCode.Value; - else if (nf.NumberFormatId != null) - newXLNumberFormat.NumberFormatId = (Int32)nf.NumberFormatId.Value; - - return newXLNumberFormat.Equals(xlNumberFormat); - } - - #endregion GenerateWorkbookStylesPartContent - - #region GenerateWorksheetPartContent - - private static void GenerateWorksheetPartContent( - WorksheetPart worksheetPart, XLWorksheet xlWorksheet, bool evaluateFormulae, SaveContext context) - { - #region Worksheet - - if (worksheetPart.Worksheet == null) - worksheetPart.Worksheet = new Worksheet(); - - GenerateTables(xlWorksheet, worksheetPart, context); - - if ( - !worksheetPart.Worksheet.NamespaceDeclarations.Contains(new KeyValuePair("r", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships"))) - { - worksheetPart.Worksheet.AddNamespaceDeclaration("r", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); - } - - #endregion Worksheet - - var cm = new XLWSContentManager(worksheetPart.Worksheet); - - #region SheetProperties - - if (worksheetPart.Worksheet.SheetProperties == null) - worksheetPart.Worksheet.SheetProperties = new SheetProperties(); - - worksheetPart.Worksheet.SheetProperties.TabColor = xlWorksheet.TabColor.HasValue - ? GetTabColor(xlWorksheet.TabColor) - : null; - - cm.SetElement(XLWSContentManager.XLWSContents.SheetProperties, worksheetPart.Worksheet.SheetProperties); - - if (worksheetPart.Worksheet.SheetProperties.OutlineProperties == null) - worksheetPart.Worksheet.SheetProperties.OutlineProperties = new OutlineProperties(); - - worksheetPart.Worksheet.SheetProperties.OutlineProperties.SummaryBelow = - (xlWorksheet.Outline.SummaryVLocation == - XLOutlineSummaryVLocation.Bottom); - worksheetPart.Worksheet.SheetProperties.OutlineProperties.SummaryRight = - (xlWorksheet.Outline.SummaryHLocation == - XLOutlineSummaryHLocation.Right); - - if (worksheetPart.Worksheet.SheetProperties.PageSetupProperties == null - && (xlWorksheet.PageSetup.PagesTall > 0 || xlWorksheet.PageSetup.PagesWide > 0)) - worksheetPart.Worksheet.SheetProperties.PageSetupProperties = new PageSetupProperties { FitToPage = true }; - - #endregion SheetProperties - - var maxColumn = 0; - - var sheetDimensionReference = "A1"; - if (xlWorksheet.Internals.CellsCollection.Count > 0) - { - maxColumn = xlWorksheet.Internals.CellsCollection.MaxColumnUsed; - var maxRow = xlWorksheet.Internals.CellsCollection.MaxRowUsed; - sheetDimensionReference = "A1:" + XLHelper.GetColumnLetterFromNumber(maxColumn) + - maxRow.ToInvariantString(); - } - - if (xlWorksheet.Internals.ColumnsCollection.Count > 0) - { - var maxColCollection = xlWorksheet.Internals.ColumnsCollection.Keys.Max(); - if (maxColCollection > maxColumn) - maxColumn = maxColCollection; - } - - #region SheetViews - - if (worksheetPart.Worksheet.SheetDimension == null) - worksheetPart.Worksheet.SheetDimension = new SheetDimension { Reference = sheetDimensionReference }; - - cm.SetElement(XLWSContentManager.XLWSContents.SheetDimension, worksheetPart.Worksheet.SheetDimension); - - if (worksheetPart.Worksheet.SheetViews == null) - worksheetPart.Worksheet.SheetViews = new SheetViews(); - - cm.SetElement(XLWSContentManager.XLWSContents.SheetViews, worksheetPart.Worksheet.SheetViews); - - var sheetView = (SheetView)worksheetPart.Worksheet.SheetViews.FirstOrDefault(); - if (sheetView == null) - { - sheetView = new SheetView { WorkbookViewId = 0U }; - worksheetPart.Worksheet.SheetViews.AppendChild(sheetView); - } - - if (xlWorksheet.TabSelected) - sheetView.TabSelected = true; - else - sheetView.TabSelected = null; - - if (xlWorksheet.RightToLeft) - sheetView.RightToLeft = true; - else - sheetView.RightToLeft = null; - - if (xlWorksheet.ShowFormulas) - sheetView.ShowFormulas = true; - else - sheetView.ShowFormulas = null; - - if (xlWorksheet.ShowGridLines) - sheetView.ShowGridLines = null; - else - sheetView.ShowGridLines = false; - - if (xlWorksheet.ShowOutlineSymbols) - sheetView.ShowOutlineSymbols = null; - else - sheetView.ShowOutlineSymbols = false; - - if (xlWorksheet.ShowRowColHeaders) - sheetView.ShowRowColHeaders = null; - else - sheetView.ShowRowColHeaders = false; - - if (xlWorksheet.ShowRuler) - sheetView.ShowRuler = null; - else - sheetView.ShowRuler = false; - - if (xlWorksheet.ShowWhiteSpace) - sheetView.ShowWhiteSpace = null; - else - sheetView.ShowWhiteSpace = false; - - if (xlWorksheet.ShowZeros) - sheetView.ShowZeros = null; - else - sheetView.ShowZeros = false; - - if (xlWorksheet.RightToLeft) - sheetView.RightToLeft = true; - else - sheetView.RightToLeft = null; - - if (xlWorksheet.SheetView.View == XLSheetViewOptions.Normal) - sheetView.View = null; - else - sheetView.View = xlWorksheet.SheetView.View.ToOpenXml(); - - var pane = sheetView.Elements().FirstOrDefault(); - if (pane == null) - { - pane = new Pane(); - sheetView.AppendChild(pane); - } - - pane.State = PaneStateValues.FrozenSplit; - Double hSplit = xlWorksheet.SheetView.SplitColumn; - Double ySplit = xlWorksheet.SheetView.SplitRow; - - pane.HorizontalSplit = hSplit; - pane.VerticalSplit = ySplit; - - pane.TopLeftCell = XLHelper.GetColumnLetterFromNumber(xlWorksheet.SheetView.SplitColumn + 1) - + (xlWorksheet.SheetView.SplitRow + 1); - - if (hSplit == 0 && ySplit == 0) - sheetView.RemoveAllChildren(); - - if (xlWorksheet.SelectedRanges.Any() || xlWorksheet.ActiveCell != null) - { - sheetView.RemoveAllChildren(); - - var firstSelection = xlWorksheet.SelectedRanges.FirstOrDefault(); - var selection = new Selection(); - if (xlWorksheet.ActiveCell != null) - selection.ActiveCell = xlWorksheet.ActiveCell.Address.ToStringRelative(false); - else if (firstSelection != null) - selection.ActiveCell = firstSelection.RangeAddress.FirstAddress.ToStringRelative(false); - - var seqRef = new List { selection.ActiveCell.Value }; - seqRef.AddRange(xlWorksheet.SelectedRanges - .Select(range => range.RangeAddress.ToStringRelative(false))); - - selection.SequenceOfReferences = new ListValue { InnerText = String.Join(" ", seqRef.Distinct().ToArray()) }; - - sheetView.Append(selection); - } - - if (xlWorksheet.SheetView.ZoomScale == 100) - sheetView.ZoomScale = null; - else - sheetView.ZoomScale = (UInt32)Math.Max(10, Math.Min(400, xlWorksheet.SheetView.ZoomScale)); - - if (xlWorksheet.SheetView.ZoomScaleNormal == 100) - sheetView.ZoomScaleNormal = null; - else - sheetView.ZoomScaleNormal = (UInt32)Math.Max(10, Math.Min(400, xlWorksheet.SheetView.ZoomScaleNormal)); - - if (xlWorksheet.SheetView.ZoomScalePageLayoutView == 100) - sheetView.ZoomScalePageLayoutView = null; - else - sheetView.ZoomScalePageLayoutView = (UInt32)Math.Max(10, Math.Min(400, xlWorksheet.SheetView.ZoomScalePageLayoutView)); - - if (xlWorksheet.SheetView.ZoomScaleSheetLayoutView == 100) - sheetView.ZoomScaleSheetLayoutView = null; - else - sheetView.ZoomScaleSheetLayoutView = (UInt32)Math.Max(10, Math.Min(400, xlWorksheet.SheetView.ZoomScaleSheetLayoutView)); - - #endregion SheetViews - - var maxOutlineColumn = 0; - if (xlWorksheet.ColumnCount() > 0) - maxOutlineColumn = xlWorksheet.GetMaxColumnOutline(); - - var maxOutlineRow = 0; - if (xlWorksheet.RowCount() > 0) - maxOutlineRow = xlWorksheet.GetMaxRowOutline(); - - #region SheetFormatProperties - - if (worksheetPart.Worksheet.SheetFormatProperties == null) - worksheetPart.Worksheet.SheetFormatProperties = new SheetFormatProperties(); - - cm.SetElement(XLWSContentManager.XLWSContents.SheetFormatProperties, - worksheetPart.Worksheet.SheetFormatProperties); - - worksheetPart.Worksheet.SheetFormatProperties.DefaultRowHeight = xlWorksheet.RowHeight.SaveRound(); - - if (xlWorksheet.RowHeightChanged) - worksheetPart.Worksheet.SheetFormatProperties.CustomHeight = true; - else - worksheetPart.Worksheet.SheetFormatProperties.CustomHeight = null; - - var worksheetColumnWidth = GetColumnWidth(xlWorksheet.ColumnWidth).SaveRound(); - if (xlWorksheet.ColumnWidthChanged) - worksheetPart.Worksheet.SheetFormatProperties.DefaultColumnWidth = worksheetColumnWidth; - else - worksheetPart.Worksheet.SheetFormatProperties.DefaultColumnWidth = null; - - if (maxOutlineColumn > 0) - worksheetPart.Worksheet.SheetFormatProperties.OutlineLevelColumn = (byte)maxOutlineColumn; - else - worksheetPart.Worksheet.SheetFormatProperties.OutlineLevelColumn = null; - - if (maxOutlineRow > 0) - worksheetPart.Worksheet.SheetFormatProperties.OutlineLevelRow = (byte)maxOutlineRow; - else - worksheetPart.Worksheet.SheetFormatProperties.OutlineLevelRow = null; - - #endregion SheetFormatProperties - - #region Columns - - if (xlWorksheet.Internals.CellsCollection.Count == 0 && - xlWorksheet.Internals.ColumnsCollection.Count == 0 - && xlWorksheet.Style.Equals(DefaultStyle)) - worksheetPart.Worksheet.RemoveAllChildren(); - else - { - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.Columns); - worksheetPart.Worksheet.InsertAfter(new Columns(), previousElement); - } - - var columns = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.Columns, columns); - - var sheetColumnsByMin = columns.Elements().ToDictionary(c => c.Min.Value, c => c); - //Dictionary sheetColumnsByMax = columns.Elements().ToDictionary(c => c.Max.Value, c => c); - - Int32 minInColumnsCollection; - Int32 maxInColumnsCollection; - if (xlWorksheet.Internals.ColumnsCollection.Count > 0) - { - minInColumnsCollection = xlWorksheet.Internals.ColumnsCollection.Keys.Min(); - maxInColumnsCollection = xlWorksheet.Internals.ColumnsCollection.Keys.Max(); - } - else - { - minInColumnsCollection = 1; - maxInColumnsCollection = 0; - } - - var worksheetStyleId = context.SharedStyles[xlWorksheet.GetStyleId()].StyleId; - if (minInColumnsCollection > 1) - { - UInt32Value min = 1; - UInt32Value max = (UInt32)(minInColumnsCollection - 1); - - for (var co = min; co <= max; co++) - { - var column = new Column - { - Min = co, - Max = co, - Style = worksheetStyleId, - Width = worksheetColumnWidth, - CustomWidth = true - }; - - UpdateColumn(column, columns, sheetColumnsByMin); //, sheetColumnsByMax); - } - } - - for (var co = minInColumnsCollection; co <= maxInColumnsCollection; co++) - { - UInt32 styleId; - Double columnWidth; - var isHidden = false; - var collapsed = false; - var outlineLevel = 0; - if (xlWorksheet.Internals.ColumnsCollection.ContainsKey(co)) - { - styleId = context.SharedStyles[xlWorksheet.Internals.ColumnsCollection[co].GetStyleId()].StyleId; - columnWidth = GetColumnWidth(xlWorksheet.Internals.ColumnsCollection[co].Width).SaveRound(); - isHidden = xlWorksheet.Internals.ColumnsCollection[co].IsHidden; - collapsed = xlWorksheet.Internals.ColumnsCollection[co].Collapsed; - outlineLevel = xlWorksheet.Internals.ColumnsCollection[co].OutlineLevel; - } - else - { - styleId = context.SharedStyles[xlWorksheet.GetStyleId()].StyleId; - columnWidth = worksheetColumnWidth; - } - - var column = new Column - { - Min = (UInt32)co, - Max = (UInt32)co, - Style = styleId, - Width = columnWidth, - CustomWidth = true - }; - - if (isHidden) - column.Hidden = true; - if (collapsed) - column.Collapsed = true; - if (outlineLevel > 0) - column.OutlineLevel = (byte)outlineLevel; - - UpdateColumn(column, columns, sheetColumnsByMin); //, sheetColumnsByMax); - } - - var collection = maxInColumnsCollection; - foreach ( - var col in - columns.Elements().Where(c => c.Min > (UInt32)(collection)).OrderBy( - c => c.Min.Value)) - { - col.Style = worksheetStyleId; - col.Width = worksheetColumnWidth; - col.CustomWidth = true; - - if ((Int32)col.Max.Value > maxInColumnsCollection) - maxInColumnsCollection = (Int32)col.Max.Value; - } - - if (maxInColumnsCollection < XLHelper.MaxColumnNumber && !xlWorksheet.Style.Equals(DefaultStyle)) - { - var column = new Column - { - Min = (UInt32)(maxInColumnsCollection + 1), - Max = (UInt32)(XLHelper.MaxColumnNumber), - Style = worksheetStyleId, - Width = worksheetColumnWidth, - CustomWidth = true - }; - columns.AppendChild(column); - } - - CollapseColumns(columns, sheetColumnsByMin); - - if (!columns.Any()) - { - worksheetPart.Worksheet.RemoveAllChildren(); - cm.SetElement(XLWSContentManager.XLWSContents.Columns, null); - } - } - - #endregion Columns - - #region SheetData - - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.SheetData); - worksheetPart.Worksheet.InsertAfter(new SheetData(), previousElement); - } - - var sheetData = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.SheetData, sheetData); - - var lastRow = 0; - var sheetDataRows = - sheetData.Elements().ToDictionary(r => r.RowIndex == null ? ++lastRow : (Int32)r.RowIndex.Value, - r => r); - foreach ( - var r in - xlWorksheet.Internals.RowsCollection.Deleted.Where(r => sheetDataRows.ContainsKey(r.Key))) - { - sheetData.RemoveChild(sheetDataRows[r.Key]); - sheetDataRows.Remove(r.Key); - xlWorksheet.Internals.CellsCollection.deleted.Remove(r.Key); - } - - var distinctRows = xlWorksheet.Internals.CellsCollection.RowsCollection.Keys.Union(xlWorksheet.Internals.RowsCollection.Keys); - var noRows = !sheetData.Elements().Any(); - foreach (var distinctRow in distinctRows.OrderBy(r => r)) - { - Row row; - if (sheetDataRows.ContainsKey(distinctRow)) - row = sheetDataRows[distinctRow]; - else - { - row = new Row { RowIndex = (UInt32)distinctRow }; - if (noRows) - { - sheetData.AppendChild(row); - noRows = false; - } - else - { - if (sheetDataRows.Any(r => r.Key > row.RowIndex.Value)) - { - var minRow = sheetDataRows.Where(r => r.Key > (Int32)row.RowIndex.Value).Min(r => r.Key); - var rowBeforeInsert = sheetDataRows[minRow]; - sheetData.InsertBefore(row, rowBeforeInsert); - } - else - sheetData.AppendChild(row); - } - } - - if (maxColumn > 0) - row.Spans = new ListValue { InnerText = "1:" + maxColumn.ToInvariantString() }; - - row.Height = null; - row.CustomHeight = null; - row.Hidden = null; - row.StyleIndex = null; - row.CustomFormat = null; - row.Collapsed = null; - if (xlWorksheet.Internals.RowsCollection.ContainsKey(distinctRow)) - { - var thisRow = xlWorksheet.Internals.RowsCollection[distinctRow]; - if (thisRow.HeightChanged) - { - row.Height = thisRow.Height.SaveRound(); - row.CustomHeight = true; - row.CustomFormat = true; - } - - if (thisRow.GetStyleId() != xlWorksheet.GetStyleId()) - { - row.StyleIndex = context.SharedStyles[thisRow.GetStyleId()].StyleId; - row.CustomFormat = true; - } - - if (thisRow.IsHidden) - row.Hidden = true; - if (thisRow.Collapsed) - row.Collapsed = true; - if (thisRow.OutlineLevel > 0) - row.OutlineLevel = (byte)thisRow.OutlineLevel; - } - - var lastCell = 0; - var cellsByReference = row.Elements().ToDictionary(c => c.CellReference == null - ? XLHelper.GetColumnLetterFromNumber( - ++lastCell) + distinctRow - : c.CellReference.Value, c => c); - - foreach (var kpDel in xlWorksheet.Internals.CellsCollection.deleted.ToList()) - { - foreach (var delCo in kpDel.Value.ToList()) - { - var key = XLHelper.GetColumnLetterFromNumber(delCo) + kpDel.Key.ToInvariantString(); - if (!cellsByReference.ContainsKey(key)) continue; - row.RemoveChild(cellsByReference[key]); - kpDel.Value.Remove(delCo); - } - if (kpDel.Value.Count == 0) - xlWorksheet.Internals.CellsCollection.deleted.Remove(kpDel.Key); - } - - if (!xlWorksheet.Internals.CellsCollection.RowsCollection.ContainsKey(distinctRow)) continue; - - var isNewRow = !row.Elements().Any(); - lastCell = 0; - var mRows = row.Elements().ToDictionary(c => XLHelper.GetColumnNumberFromAddress(c.CellReference == null - ? (XLHelper.GetColumnLetterFromNumber(++lastCell) + distinctRow) : c.CellReference.Value), c => c); - foreach (var xlCell in xlWorksheet.Internals.CellsCollection.RowsCollection[distinctRow].Values - .OrderBy(c => c.Address.ColumnNumber) - .Select(c => c)) - { - var styleId = context.SharedStyles[xlCell.GetStyleId()].StyleId; - var cellReference = (xlCell.Address).GetTrimmedAddress(); - var isEmpty = xlCell.IsEmpty(true); - - Cell cell = null; - if (cellsByReference.ContainsKey(cellReference)) - { - cell = cellsByReference[cellReference]; - if (isEmpty) - { - cell.Remove(); - } - } - - if (!isEmpty) - { - if (cell == null) - { - cell = new Cell(); - cell.CellReference = new StringValue(cellReference); - - if (isNewRow) - row.AppendChild(cell); - else - { - var newColumn = XLHelper.GetColumnNumberFromAddress(cellReference); - - Cell cellBeforeInsert = null; - int[] lastCo = { Int32.MaxValue }; - foreach (var c in mRows.Where(kp => kp.Key > newColumn).Where(c => lastCo[0] > c.Key)) - { - cellBeforeInsert = c.Value; - lastCo[0] = c.Key; - } - if (cellBeforeInsert == null) - row.AppendChild(cell); - else - row.InsertBefore(cell, cellBeforeInsert); - } - } - - cell.StyleIndex = styleId; - var formula = xlCell.FormulaA1; - if (xlCell.HasFormula) - { - if (formula.StartsWith("{")) - { - formula = formula.Substring(1, formula.Length - 2); - var f = new CellFormula { FormulaType = CellFormulaValues.Array }; - - if (xlCell.FormulaReference == null) - xlCell.FormulaReference = xlCell.AsRange().RangeAddress; - if (xlCell.FormulaReference.FirstAddress.Equals(xlCell.Address)) - { - f.Text = formula; - f.Reference = xlCell.FormulaReference.ToStringRelative(); - } - - cell.CellFormula = f; - } - else - { - cell.CellFormula = new CellFormula(); - cell.CellFormula.Text = formula; - } - - cell.CellValue = null; - } - else - { - cell.CellFormula = null; - cell.DataType = xlCell.DataType == XLCellValues.DateTime ? null : GetCellValueType(xlCell); - } - - if (!xlCell.HasFormula || evaluateFormulae) - SetCellValue(xlCell, cell); - - } - } - xlWorksheet.Internals.CellsCollection.deleted.Remove(distinctRow); - } - foreach ( - var r in - xlWorksheet.Internals.CellsCollection.deleted.Keys.Where( - sheetDataRows.ContainsKey)) - { - sheetData.RemoveChild(sheetDataRows[r]); - sheetDataRows.Remove(r); - } - - #endregion SheetData - - #region SheetProtection - - if (xlWorksheet.Protection.Protected) - { - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.SheetProtection); - worksheetPart.Worksheet.InsertAfter(new SheetProtection(), previousElement); - } - - var sheetProtection = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.SheetProtection, sheetProtection); - - var protection = xlWorksheet.Protection; - sheetProtection.Sheet = protection.Protected; - if (!XLHelper.IsNullOrWhiteSpace(protection.PasswordHash)) - sheetProtection.Password = protection.PasswordHash; - sheetProtection.FormatCells = GetBooleanValue(!protection.FormatCells, true); - sheetProtection.FormatColumns = GetBooleanValue(!protection.FormatColumns, true); - sheetProtection.FormatRows = GetBooleanValue(!protection.FormatRows, true); - sheetProtection.InsertColumns = GetBooleanValue(!protection.InsertColumns, true); - sheetProtection.InsertHyperlinks = GetBooleanValue(!protection.InsertHyperlinks, true); - sheetProtection.InsertRows = GetBooleanValue(!protection.InsertRows, true); - sheetProtection.DeleteColumns = GetBooleanValue(!protection.DeleteColumns, true); - sheetProtection.DeleteRows = GetBooleanValue(!protection.DeleteRows, true); - sheetProtection.AutoFilter = GetBooleanValue(!protection.AutoFilter, true); - sheetProtection.PivotTables = GetBooleanValue(!protection.PivotTables, true); - sheetProtection.Sort = GetBooleanValue(!protection.Sort, true); - sheetProtection.SelectLockedCells = GetBooleanValue(!protection.SelectLockedCells, false); - sheetProtection.SelectUnlockedCells = GetBooleanValue(!protection.SelectUnlockedCells, false); - } - else - { - worksheetPart.Worksheet.RemoveAllChildren(); - cm.SetElement(XLWSContentManager.XLWSContents.SheetProtection, null); - } - - #endregion SheetProtection - - #region AutoFilter - - worksheetPart.Worksheet.RemoveAllChildren(); - if (xlWorksheet.AutoFilter.Enabled) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.AutoFilter); - worksheetPart.Worksheet.InsertAfter(new AutoFilter(), previousElement); - - var autoFilter = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.AutoFilter, autoFilter); - - PopulateAutoFilter(xlWorksheet.AutoFilter, autoFilter); - } - else - { - cm.SetElement(XLWSContentManager.XLWSContents.AutoFilter, null); - } - - #endregion AutoFilter - - #region MergeCells - - if ((xlWorksheet).Internals.MergedRanges.Any()) - { - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.MergeCells); - worksheetPart.Worksheet.InsertAfter(new MergeCells(), previousElement); - } - - var mergeCells = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.MergeCells, mergeCells); - mergeCells.RemoveAllChildren(); - - foreach (var mergeCell in (xlWorksheet).Internals.MergedRanges.Select( - m => m.RangeAddress.FirstAddress.ToString() + ":" + m.RangeAddress.LastAddress.ToString()).Select( - merged => new MergeCell { Reference = merged })) - mergeCells.AppendChild(mergeCell); - - mergeCells.Count = (UInt32)mergeCells.Count(); - } - else - { - worksheetPart.Worksheet.RemoveAllChildren(); - cm.SetElement(XLWSContentManager.XLWSContents.MergeCells, null); - } - - #endregion MergeCells - - #region Conditional Formatting - - if (!xlWorksheet.ConditionalFormats.Any()) - { - worksheetPart.Worksheet.RemoveAllChildren(); - cm.SetElement(XLWSContentManager.XLWSContents.ConditionalFormatting, null); - } - else - { - worksheetPart.Worksheet.RemoveAllChildren(); - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.ConditionalFormatting); - - var priority = 1; // priority is 1 origin in Microsoft Excel - foreach (var cfGroup in xlWorksheet.ConditionalFormats - .GroupBy( - c => c.Range.RangeAddress.ToStringRelative(false), - c => c, - (key, g) => new { RangeId = key, CfList = g.ToList() } - ) - ) - { - var conditionalFormatting = new ConditionalFormatting - { - SequenceOfReferences = - new ListValue { InnerText = cfGroup.RangeId } - }; - foreach (var cf in cfGroup.CfList) - { - conditionalFormatting.Append(XLCFConverters.Convert(cf, priority, context)); - priority++; - } - worksheetPart.Worksheet.InsertAfter(conditionalFormatting, previousElement); - previousElement = conditionalFormatting; - cm.SetElement(XLWSContentManager.XLWSContents.ConditionalFormatting, conditionalFormatting); - } - } - - #endregion Conditional Formatting - - #region DataValidations - - if (!xlWorksheet.DataValidations.Any(d => d.IsDirty())) - { - worksheetPart.Worksheet.RemoveAllChildren(); - cm.SetElement(XLWSContentManager.XLWSContents.DataValidations, null); - } - else - { - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.DataValidations); - worksheetPart.Worksheet.InsertAfter(new DataValidations(), previousElement); - } - - var dataValidations = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.DataValidations, dataValidations); - dataValidations.RemoveAllChildren(); - foreach (var dv in xlWorksheet.DataValidations) - { - var sequence = dv.Ranges.Aggregate(String.Empty, (current, r) => current + (r.RangeAddress + " ")); - - if (sequence.Length > 0) - sequence = sequence.Substring(0, sequence.Length - 1); - - var dataValidation = new DataValidation - { - AllowBlank = dv.IgnoreBlanks, - Formula1 = new Formula1(dv.MinValue), - Formula2 = new Formula2(dv.MaxValue), - Type = dv.AllowedValues.ToOpenXml(), - ShowErrorMessage = dv.ShowErrorMessage, - Prompt = dv.InputMessage, - PromptTitle = dv.InputTitle, - ErrorTitle = dv.ErrorTitle, - Error = dv.ErrorMessage, - ShowDropDown = !dv.InCellDropdown, - ShowInputMessage = dv.ShowInputMessage, - ErrorStyle = dv.ErrorStyle.ToOpenXml(), - Operator = dv.Operator.ToOpenXml(), - SequenceOfReferences = - new ListValue { InnerText = sequence } - }; - - dataValidations.AppendChild(dataValidation); - } - dataValidations.Count = (UInt32)xlWorksheet.DataValidations.Count(); - } - - #endregion DataValidations - - #region Hyperlinks - - var relToRemove = worksheetPart.HyperlinkRelationships.ToList(); - relToRemove.ForEach(worksheetPart.DeleteReferenceRelationship); - if (!xlWorksheet.Hyperlinks.Any()) - { - worksheetPart.Worksheet.RemoveAllChildren(); - cm.SetElement(XLWSContentManager.XLWSContents.Hyperlinks, null); - } - else - { - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.Hyperlinks); - worksheetPart.Worksheet.InsertAfter(new Hyperlinks(), previousElement); - } - - var hyperlinks = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.Hyperlinks, hyperlinks); - hyperlinks.RemoveAllChildren(); - foreach (var hl in xlWorksheet.Hyperlinks) - { - Hyperlink hyperlink; - if (hl.IsExternal) - { - var rId = context.RelIdGenerator.GetNext(RelType.Workbook); - hyperlink = new Hyperlink { Reference = hl.Cell.Address.ToString(), Id = rId }; - worksheetPart.AddHyperlinkRelationship(hl.ExternalAddress, true, rId); - } - else - { - hyperlink = new Hyperlink - { - Reference = hl.Cell.Address.ToString(), - Location = hl.InternalAddress, - Display = hl.Cell.GetFormattedString() - }; - } - if (!XLHelper.IsNullOrWhiteSpace(hl.Tooltip)) - hyperlink.Tooltip = hl.Tooltip; - hyperlinks.AppendChild(hyperlink); - } - } - - #endregion Hyperlinks - - #region PrintOptions - - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.PrintOptions); - worksheetPart.Worksheet.InsertAfter(new PrintOptions(), previousElement); - } - - var printOptions = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.PrintOptions, printOptions); - - printOptions.HorizontalCentered = xlWorksheet.PageSetup.CenterHorizontally; - printOptions.VerticalCentered = xlWorksheet.PageSetup.CenterVertically; - printOptions.Headings = xlWorksheet.PageSetup.ShowRowAndColumnHeadings; - printOptions.GridLines = xlWorksheet.PageSetup.ShowGridlines; - - #endregion PrintOptions - - #region PageMargins - - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.PageMargins); - worksheetPart.Worksheet.InsertAfter(new PageMargins(), previousElement); - } - - var pageMargins = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.PageMargins, pageMargins); - pageMargins.Left = xlWorksheet.PageSetup.Margins.Left; - pageMargins.Right = xlWorksheet.PageSetup.Margins.Right; - pageMargins.Top = xlWorksheet.PageSetup.Margins.Top; - pageMargins.Bottom = xlWorksheet.PageSetup.Margins.Bottom; - pageMargins.Header = xlWorksheet.PageSetup.Margins.Header; - pageMargins.Footer = xlWorksheet.PageSetup.Margins.Footer; - - #endregion PageMargins - - #region PageSetup - - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.PageSetup); - worksheetPart.Worksheet.InsertAfter(new PageSetup(), previousElement); - } - - var pageSetup = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.PageSetup, pageSetup); - - pageSetup.Orientation = xlWorksheet.PageSetup.PageOrientation.ToOpenXml(); - pageSetup.PaperSize = (UInt32)xlWorksheet.PageSetup.PaperSize; - pageSetup.BlackAndWhite = xlWorksheet.PageSetup.BlackAndWhite; - pageSetup.Draft = xlWorksheet.PageSetup.DraftQuality; - pageSetup.PageOrder = xlWorksheet.PageSetup.PageOrder.ToOpenXml(); - pageSetup.CellComments = xlWorksheet.PageSetup.ShowComments.ToOpenXml(); - pageSetup.Errors = xlWorksheet.PageSetup.PrintErrorValue.ToOpenXml(); - - if (xlWorksheet.PageSetup.FirstPageNumber > 0) - { - pageSetup.FirstPageNumber = (UInt32)xlWorksheet.PageSetup.FirstPageNumber; - pageSetup.UseFirstPageNumber = true; - } - else - { - pageSetup.FirstPageNumber = null; - pageSetup.UseFirstPageNumber = null; - } - - if (xlWorksheet.PageSetup.HorizontalDpi > 0) - pageSetup.HorizontalDpi = (UInt32)xlWorksheet.PageSetup.HorizontalDpi; - else - pageSetup.HorizontalDpi = null; - - if (xlWorksheet.PageSetup.VerticalDpi > 0) - pageSetup.VerticalDpi = (UInt32)xlWorksheet.PageSetup.VerticalDpi; - else - pageSetup.VerticalDpi = null; - - if (xlWorksheet.PageSetup.Scale > 0) - { - pageSetup.Scale = (UInt32)xlWorksheet.PageSetup.Scale; - pageSetup.FitToWidth = null; - pageSetup.FitToHeight = null; - } - else - { - pageSetup.Scale = null; - - if (xlWorksheet.PageSetup.PagesWide >= 0 && xlWorksheet.PageSetup.PagesWide != 1) - pageSetup.FitToWidth = (UInt32)xlWorksheet.PageSetup.PagesWide; - - if (xlWorksheet.PageSetup.PagesTall >= 0 && xlWorksheet.PageSetup.PagesTall != 1) - pageSetup.FitToHeight = (UInt32)xlWorksheet.PageSetup.PagesTall; - } - - #endregion PageSetup - - #region HeaderFooter - - var headerFooter = worksheetPart.Worksheet.Elements().FirstOrDefault(); - if (headerFooter == null) - headerFooter = new HeaderFooter(); - else - worksheetPart.Worksheet.RemoveAllChildren(); - - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.HeaderFooter); - worksheetPart.Worksheet.InsertAfter(headerFooter, previousElement); - cm.SetElement(XLWSContentManager.XLWSContents.HeaderFooter, headerFooter); - } - if (((XLHeaderFooter)xlWorksheet.PageSetup.Header).Changed - || ((XLHeaderFooter)xlWorksheet.PageSetup.Footer).Changed) - { - //var headerFooter = worksheetPart.Worksheet.Elements().First(); - - headerFooter.RemoveAllChildren(); - - headerFooter.ScaleWithDoc = xlWorksheet.PageSetup.ScaleHFWithDocument; - headerFooter.AlignWithMargins = xlWorksheet.PageSetup.AlignHFWithMargins; - headerFooter.DifferentFirst = xlWorksheet.PageSetup.DifferentFirstPageOnHF; - headerFooter.DifferentOddEven = xlWorksheet.PageSetup.DifferentOddEvenPagesOnHF; - - var oddHeader = new OddHeader(xlWorksheet.PageSetup.Header.GetText(XLHFOccurrence.OddPages)); - headerFooter.AppendChild(oddHeader); - var oddFooter = new OddFooter(xlWorksheet.PageSetup.Footer.GetText(XLHFOccurrence.OddPages)); - headerFooter.AppendChild(oddFooter); - - var evenHeader = new EvenHeader(xlWorksheet.PageSetup.Header.GetText(XLHFOccurrence.EvenPages)); - headerFooter.AppendChild(evenHeader); - var evenFooter = new EvenFooter(xlWorksheet.PageSetup.Footer.GetText(XLHFOccurrence.EvenPages)); - headerFooter.AppendChild(evenFooter); - - var firstHeader = new FirstHeader(xlWorksheet.PageSetup.Header.GetText(XLHFOccurrence.FirstPage)); - headerFooter.AppendChild(firstHeader); - var firstFooter = new FirstFooter(xlWorksheet.PageSetup.Footer.GetText(XLHFOccurrence.FirstPage)); - headerFooter.AppendChild(firstFooter); - } - - #endregion HeaderFooter - - #region RowBreaks - - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.RowBreaks); - worksheetPart.Worksheet.InsertAfter(new RowBreaks(), previousElement); - } - - var rowBreaks = worksheetPart.Worksheet.Elements().First(); - - var rowBreakCount = xlWorksheet.PageSetup.RowBreaks.Count; - if (rowBreakCount > 0) - { - rowBreaks.Count = (UInt32)rowBreakCount; - rowBreaks.ManualBreakCount = (UInt32)rowBreakCount; - var lastRowNum = (UInt32)xlWorksheet.RangeAddress.LastAddress.RowNumber; - foreach (var break1 in xlWorksheet.PageSetup.RowBreaks.Select(rb => new Break - { - Id = (UInt32)rb, - Max = lastRowNum, - ManualPageBreak = true - })) - rowBreaks.AppendChild(break1); - cm.SetElement(XLWSContentManager.XLWSContents.RowBreaks, rowBreaks); - } - else - { - worksheetPart.Worksheet.RemoveAllChildren(); - cm.SetElement(XLWSContentManager.XLWSContents.RowBreaks, null); - } - - #endregion RowBreaks - - #region ColumnBreaks - - if (!worksheetPart.Worksheet.Elements().Any()) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.ColumnBreaks); - worksheetPart.Worksheet.InsertAfter(new ColumnBreaks(), previousElement); - } - - var columnBreaks = worksheetPart.Worksheet.Elements().First(); - - var columnBreakCount = xlWorksheet.PageSetup.ColumnBreaks.Count; - if (columnBreakCount > 0) - { - columnBreaks.Count = (UInt32)columnBreakCount; - columnBreaks.ManualBreakCount = (UInt32)columnBreakCount; - var maxColumnNumber = (UInt32)xlWorksheet.RangeAddress.LastAddress.ColumnNumber; - foreach (var break1 in xlWorksheet.PageSetup.ColumnBreaks.Select(cb => new Break - { - Id = (UInt32)cb, - Max = maxColumnNumber, - ManualPageBreak = true - })) - columnBreaks.AppendChild(break1); - cm.SetElement(XLWSContentManager.XLWSContents.ColumnBreaks, columnBreaks); - } - else - { - worksheetPart.Worksheet.RemoveAllChildren(); - cm.SetElement(XLWSContentManager.XLWSContents.ColumnBreaks, null); - } - - #endregion ColumnBreaks - - #region Tables - - worksheetPart.Worksheet.RemoveAllChildren(); - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.TableParts); - worksheetPart.Worksheet.InsertAfter(new TableParts(), previousElement); - } - - var tableParts = worksheetPart.Worksheet.Elements().First(); - cm.SetElement(XLWSContentManager.XLWSContents.TableParts, tableParts); - - tableParts.Count = (UInt32)xlWorksheet.Tables.Count(); - foreach ( - var tablePart in - from XLTable xlTable in xlWorksheet.Tables select new TablePart { Id = xlTable.RelId }) - tableParts.AppendChild(tablePart); - - #endregion Tables - - #region Drawings - - foreach (var pic in xlWorksheet.Pictures) - { - AddPictureAnchor(worksheetPart, pic, context); - } - - if (xlWorksheet.Pictures.Any()) - RebasePictureIds(worksheetPart); - - if (xlWorksheet.Pictures.Any() && !worksheetPart.Worksheet.OfType().Any()) - { - var worksheetDrawing = new Drawing { Id = worksheetPart.GetIdOfPart(worksheetPart.DrawingsPart) }; - worksheetDrawing.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); - worksheetPart.Worksheet.InsertBefore(worksheetDrawing, tableParts); - } - - #endregion Drawings - - #region LegacyDrawing - - if (xlWorksheet.LegacyDrawingIsNew) - { - worksheetPart.Worksheet.RemoveAllChildren(); - { - if (!XLHelper.IsNullOrWhiteSpace(xlWorksheet.LegacyDrawingId)) - { - var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.LegacyDrawing); - worksheetPart.Worksheet.InsertAfter(new LegacyDrawing { Id = xlWorksheet.LegacyDrawingId }, - previousElement); - } - } - } - - #endregion LegacyDrawing - - #region LegacyDrawingHeaderFooter - - //LegacyDrawingHeaderFooter legacyHeaderFooter = worksheetPart.Worksheet.Elements().FirstOrDefault(); - //if (legacyHeaderFooter != null) - //{ - // worksheetPart.Worksheet.RemoveAllChildren(); - // { - // var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.LegacyDrawingHeaderFooter); - // worksheetPart.Worksheet.InsertAfter(new LegacyDrawingHeaderFooter { Id = xlWorksheet.LegacyDrawingId }, - // previousElement); - // } - //} - - #endregion LegacyDrawingHeaderFooter - } - - private static void SetCellValue(XLCell xlCell, Cell openXmlCell) - { - if (xlCell.HasFormula) - { - var cellValue = new CellValue(); - try - { - cellValue.Text = xlCell.Value.ToString(); - openXmlCell.DataType = new EnumValue(CellValues.String); - } - catch - { - cellValue = null; - } - - openXmlCell.CellValue = cellValue; - return; - } - - var dataType = xlCell.DataType; - if (dataType == XLCellValues.Text) - { - if (xlCell.InnerText.Length == 0) - openXmlCell.CellValue = null; - else - { - if (xlCell.ShareString) - { - var cellValue = new CellValue(); - cellValue.Text = xlCell.SharedStringId.ToString(); - openXmlCell.CellValue = cellValue; - } - else - { - var text = xlCell.GetString(); - var t = new Text(text); - if (text.PreserveSpaces()) - t.Space = SpaceProcessingModeValues.Preserve; - - openXmlCell.InlineString = new InlineString { Text = t }; - } - } - } - else if (dataType == XLCellValues.TimeSpan) - { - var timeSpan = xlCell.GetTimeSpan(); - var cellValue = new CellValue(); - cellValue.Text = - XLCell.BaseDate.Add(timeSpan).ToOADate().ToInvariantString(); - openXmlCell.CellValue = cellValue; - } - else if (dataType == XLCellValues.DateTime || dataType == XLCellValues.Number) - { - if (!XLHelper.IsNullOrWhiteSpace(xlCell.InnerText)) - { - var cellValue = new CellValue(); - cellValue.Text = Double.Parse(xlCell.InnerText, XLHelper.NumberStyle, XLHelper.ParseCulture).ToInvariantString(); - openXmlCell.CellValue = cellValue; - } - } - else - { - var cellValue = new CellValue(); - cellValue.Text = xlCell.InnerText; - openXmlCell.CellValue = cellValue; - } - } - - private static void PopulateAutoFilter(XLAutoFilter xlAutoFilter, AutoFilter autoFilter) - { - var filterRange = xlAutoFilter.Range; - autoFilter.Reference = filterRange.RangeAddress.ToString(); - - foreach (var kp in xlAutoFilter.Filters) - { - var filterColumn = new FilterColumn { ColumnId = (UInt32)kp.Key - 1 }; - var xlFilterColumn = xlAutoFilter.Column(kp.Key); - var filterType = xlFilterColumn.FilterType; - if (filterType == XLFilterType.Custom) - { - var customFilters = new CustomFilters(); - foreach (var filter in kp.Value) - { - var customFilter = new CustomFilter { Val = filter.Value.ToString() }; - - if (filter.Operator != XLFilterOperator.Equal) - customFilter.Operator = filter.Operator.ToOpenXml(); - - if (filter.Connector == XLConnector.And) - customFilters.And = true; - - customFilters.Append(customFilter); - } - filterColumn.Append(customFilters); - } - else if (filterType == XLFilterType.TopBottom) - { - var top101 = new Top10 { Val = (double)xlFilterColumn.TopBottomValue }; - if (xlFilterColumn.TopBottomType == XLTopBottomType.Percent) - top101.Percent = true; - if (xlFilterColumn.TopBottomPart == XLTopBottomPart.Bottom) - top101.Top = false; - - filterColumn.Append(top101); - } - else if (filterType == XLFilterType.Dynamic) - { - var dynamicFilter = new DynamicFilter - { Type = xlFilterColumn.DynamicType.ToOpenXml(), Val = xlFilterColumn.DynamicValue }; - filterColumn.Append(dynamicFilter); - } - else - { - var filters = new Filters(); - foreach (var filter in kp.Value) - { - filters.Append(new Filter { Val = filter.Value.ToString() }); - } - - filterColumn.Append(filters); - } - autoFilter.Append(filterColumn); - } - - if (xlAutoFilter.Sorted) - { - var sortState = new SortState - { - Reference = - filterRange.Range(filterRange.FirstCell().CellBelow(), filterRange.LastCell()).RangeAddress. - ToString() - }; - var sortCondition = new SortCondition - { - Reference = - filterRange.Range(1, xlAutoFilter.SortColumn, filterRange.RowCount(), - xlAutoFilter.SortColumn).RangeAddress.ToString() - }; - if (xlAutoFilter.SortOrder == XLSortOrder.Descending) - sortCondition.Descending = true; - - sortState.Append(sortCondition); - autoFilter.Append(sortState); - } - } - - private static BooleanValue GetBooleanValue(bool value, bool defaultValue) - { - return value == defaultValue ? null : new BooleanValue(value); - } - - private static void CollapseColumns(Columns columns, Dictionary sheetColumns) - { - UInt32 lastMin = 1; - var count = sheetColumns.Count; - var arr = sheetColumns.OrderBy(kp => kp.Key).ToArray(); - // sheetColumns[kp.Key + 1] - //Int32 i = 0; - //foreach (KeyValuePair kp in arr - // //.Where(kp => !(kp.Key < count && ColumnsAreEqual(kp.Value, ))) - // ) - for (var i = 0; i < count; i++) - { - var kp = arr[i]; - if (i + 1 != count && ColumnsAreEqual(kp.Value, arr[i + 1].Value)) continue; - - var newColumn = (Column)kp.Value.CloneNode(true); - newColumn.Min = lastMin; - var newColumnMax = newColumn.Max.Value; - var columnsToRemove = - columns.Elements().Where(co => co.Min >= lastMin && co.Max <= newColumnMax). - Select(co => co).ToList(); - columnsToRemove.ForEach(c => columns.RemoveChild(c)); - - columns.AppendChild(newColumn); - lastMin = kp.Key + 1; - //i++; - } - } - - private static double GetColumnWidth(double columnWidth) - { - return Math.Min(255.0, Math.Max(0.0, columnWidth + ColumnWidthOffset)); - } - - private static void UpdateColumn(Column column, Columns columns, Dictionary sheetColumnsByMin) - { - var co = column.Min.Value; - Column newColumn; - if (!sheetColumnsByMin.ContainsKey(co)) - { - newColumn = (Column)column.CloneNode(true); - columns.AppendChild(newColumn); - sheetColumnsByMin.Add(co, newColumn); - } - else - { - var existingColumn = sheetColumnsByMin[column.Min.Value]; - newColumn = (Column)existingColumn.CloneNode(true); - newColumn.Min = column.Min; - newColumn.Max = column.Max; - newColumn.Style = column.Style; - newColumn.Width = column.Width.SaveRound(); - newColumn.CustomWidth = column.CustomWidth; - - if (column.Hidden != null) - newColumn.Hidden = true; - else - newColumn.Hidden = null; - - if (column.Collapsed != null) - newColumn.Collapsed = true; - else - newColumn.Collapsed = null; - - if (column.OutlineLevel != null && column.OutlineLevel > 0) - newColumn.OutlineLevel = (byte)column.OutlineLevel; - else - newColumn.OutlineLevel = null; - - sheetColumnsByMin.Remove(column.Min.Value); - if (existingColumn.Min + 1 > existingColumn.Max) - { - //existingColumn.Min = existingColumn.Min + 1; - //columns.InsertBefore(existingColumn, newColumn); - //existingColumn.Remove(); - columns.RemoveChild(existingColumn); - columns.AppendChild(newColumn); - sheetColumnsByMin.Add(newColumn.Min.Value, newColumn); - } - else - { - //columns.InsertBefore(existingColumn, newColumn); - columns.AppendChild(newColumn); - sheetColumnsByMin.Add(newColumn.Min.Value, newColumn); - existingColumn.Min = existingColumn.Min + 1; - sheetColumnsByMin.Add(existingColumn.Min.Value, existingColumn); - } - } - } - - private static bool ColumnsAreEqual(Column left, Column right) - { - return - ((left.Style == null && right.Style == null) - || (left.Style != null && right.Style != null && left.Style.Value == right.Style.Value)) - && ((left.Width == null && right.Width == null) - || (left.Width != null && right.Width != null && left.Width.Value == right.Width.Value)) - && ((left.Hidden == null && right.Hidden == null) - || (left.Hidden != null && right.Hidden != null && left.Hidden.Value == right.Hidden.Value)) - && ((left.Collapsed == null && right.Collapsed == null) - || - (left.Collapsed != null && right.Collapsed != null && left.Collapsed.Value == right.Collapsed.Value)) - && ((left.OutlineLevel == null && right.OutlineLevel == null) - || - (left.OutlineLevel != null && right.OutlineLevel != null && - left.OutlineLevel.Value == right.OutlineLevel.Value)); - } - - #endregion GenerateWorksheetPartContent - } +using ClosedXML.Extensions; +using ClosedXML.Utils; +using DocumentFormat.OpenXml; +using DocumentFormat.OpenXml.CustomProperties; +using DocumentFormat.OpenXml.Drawing; +using DocumentFormat.OpenXml.ExtendedProperties; +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Spreadsheet; +using DocumentFormat.OpenXml.Validation; +using DocumentFormat.OpenXml.VariantTypes; +using DocumentFormat.OpenXml.Vml.Office; +using DocumentFormat.OpenXml.Vml.Spreadsheet; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Xml; +using System.Xml.Linq; +using Anchor = DocumentFormat.OpenXml.Vml.Spreadsheet.Anchor; +using BackgroundColor = DocumentFormat.OpenXml.Spreadsheet.BackgroundColor; +using BottomBorder = DocumentFormat.OpenXml.Spreadsheet.BottomBorder; +using Break = DocumentFormat.OpenXml.Spreadsheet.Break; +using Field = DocumentFormat.OpenXml.Spreadsheet.Field; +using Fill = DocumentFormat.OpenXml.Spreadsheet.Fill; +using Fonts = DocumentFormat.OpenXml.Spreadsheet.Fonts; +using FontScheme = DocumentFormat.OpenXml.Drawing.FontScheme; +using ForegroundColor = DocumentFormat.OpenXml.Spreadsheet.ForegroundColor; +using GradientFill = DocumentFormat.OpenXml.Drawing.GradientFill; +using GradientStop = DocumentFormat.OpenXml.Drawing.GradientStop; +using Hyperlink = DocumentFormat.OpenXml.Spreadsheet.Hyperlink; +using LeftBorder = DocumentFormat.OpenXml.Spreadsheet.LeftBorder; +using Outline = DocumentFormat.OpenXml.Drawing.Outline; +using Path = System.IO.Path; +using PatternFill = DocumentFormat.OpenXml.Spreadsheet.PatternFill; +using Properties = DocumentFormat.OpenXml.ExtendedProperties.Properties; +using RightBorder = DocumentFormat.OpenXml.Spreadsheet.RightBorder; +using Run = DocumentFormat.OpenXml.Spreadsheet.Run; +using RunProperties = DocumentFormat.OpenXml.Spreadsheet.RunProperties; +using Table = DocumentFormat.OpenXml.Spreadsheet.Table; +using Text = DocumentFormat.OpenXml.Spreadsheet.Text; +using TopBorder = DocumentFormat.OpenXml.Spreadsheet.TopBorder; +using Underline = DocumentFormat.OpenXml.Spreadsheet.Underline; +using VerticalTextAlignment = DocumentFormat.OpenXml.Spreadsheet.VerticalTextAlignment; +using Vml = DocumentFormat.OpenXml.Vml; +using Xdr = DocumentFormat.OpenXml.Drawing.Spreadsheet; + +namespace ClosedXML.Excel +{ + public partial class XLWorkbook + { + private const Double ColumnWidthOffset = 0.710625; + + //private Dictionary sharedStrings; + //private Dictionary context.SharedStyles; + + private static readonly EnumValue CvSharedString = new EnumValue(CellValues.SharedString); + private static readonly EnumValue CvInlineString = new EnumValue(CellValues.InlineString); + private static readonly EnumValue CvNumber = new EnumValue(CellValues.Number); + private static readonly EnumValue CvDate = new EnumValue(CellValues.Date); + private static readonly EnumValue CvBoolean = new EnumValue(CellValues.Boolean); + + private static EnumValue GetCellValueType(XLCell xlCell) + { + switch (xlCell.DataType) + { + case XLCellValues.Text: + { + return xlCell.ShareString ? CvSharedString : CvInlineString; + } + case XLCellValues.Number: + return CvNumber; + + case XLCellValues.DateTime: + return CvDate; + + case XLCellValues.Boolean: + return CvBoolean; + + case XLCellValues.TimeSpan: + return CvNumber; + + default: + throw new NotImplementedException(); + } + } + + private bool Validate(SpreadsheetDocument package) + { + var backupCulture = Thread.CurrentThread.CurrentCulture; + + IEnumerable errors; + try + { + Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; + var validator = new OpenXmlValidator(); + errors = validator.Validate(package); + } + finally + { + Thread.CurrentThread.CurrentCulture = backupCulture; + } + + if (errors.Any()) + { + var message = string.Join("\r\n", errors.Select(e => string.Format("{0} in {1}", e.Description, e.Path.XPath)).ToArray()); + throw new ApplicationException(message); + } + return true; + } + + private void CreatePackage(String filePath, SpreadsheetDocumentType spreadsheetDocumentType, bool validate, bool evaluateFormulae) + { + PathHelper.CreateDirectory(Path.GetDirectoryName(filePath)); + var package = File.Exists(filePath) + ? SpreadsheetDocument.Open(filePath, true) + : SpreadsheetDocument.Create(filePath, spreadsheetDocumentType); + + using (package) + { + CreateParts(package, evaluateFormulae); + if (validate) Validate(package); + } + } + + private void CreatePackage(Stream stream, bool newStream, SpreadsheetDocumentType spreadsheetDocumentType, bool validate, bool evaluateFormulae) + { + var package = newStream + ? SpreadsheetDocument.Create(stream, spreadsheetDocumentType) + : SpreadsheetDocument.Open(stream, true); + + using (package) + { + CreateParts(package, evaluateFormulae); + if (validate) Validate(package); + } + } + + // http://blogs.msdn.com/b/vsod/archive/2010/02/05/how-to-delete-a-worksheet-from-excel-using-open-xml-sdk-2-0.aspx + private void DeleteSheetAndDependencies(WorkbookPart wbPart, string sheetId) + { + //Get the SheetToDelete from workbook.xml + Sheet worksheet = wbPart.Workbook.Descendants().Where(s => s.Id == sheetId).FirstOrDefault(); + if (worksheet == null) + { } + + string sheetName = worksheet.Name; + // Get the pivot Table Parts + IEnumerable pvtTableCacheParts = wbPart.PivotTableCacheDefinitionParts; + Dictionary pvtTableCacheDefinationPart = new Dictionary(); + foreach (PivotTableCacheDefinitionPart Item in pvtTableCacheParts) + { + PivotCacheDefinition pvtCacheDef = Item.PivotCacheDefinition; + //Check if this CacheSource is linked to SheetToDelete + var pvtCahce = pvtCacheDef.Descendants().Where(s => s.WorksheetSource.Sheet == sheetName); + if (pvtCahce.Count() > 0) + { + pvtTableCacheDefinationPart.Add(Item, Item.ToString()); + } + } + foreach (var Item in pvtTableCacheDefinationPart) + { + wbPart.DeletePart(Item.Key); + } + + // Remove the sheet reference from the workbook. + WorksheetPart worksheetPart = (WorksheetPart)(wbPart.GetPartById(sheetId)); + worksheet.Remove(); + + // Delete the worksheet part. + wbPart.DeletePart(worksheetPart); + + //Get the DefinedNames + var definedNames = wbPart.Workbook.Descendants().FirstOrDefault(); + if (definedNames != null) + { + List defNamesToDelete = new List(); + + foreach (DefinedName Item in definedNames) + { + // This condition checks to delete only those names which are part of Sheet in question + if (Item.Text.Contains(worksheet.Name + "!")) + defNamesToDelete.Add(Item); + } + + foreach (DefinedName Item in defNamesToDelete) + { + Item.Remove(); + } + } + // Get the CalculationChainPart + //Note: An instance of this part type contains an ordered set of references to all cells in all worksheets in the + //workbook whose value is calculated from any formula + + CalculationChainPart calChainPart; + calChainPart = wbPart.CalculationChainPart; + if (calChainPart != null) + { + var calChainEntries = calChainPart.CalculationChain.Descendants().Where(c => c.SheetId == sheetId); + List calcsToDelete = new List(); + foreach (CalculationCell Item in calChainEntries) + { + calcsToDelete.Add(Item); + } + + foreach (CalculationCell Item in calcsToDelete) + { + Item.Remove(); + } + + if (calChainPart.CalculationChain.Count() == 0) + { + wbPart.DeletePart(calChainPart); + } + } + } + + // Adds child parts and generates content of the specified part. + private void CreateParts(SpreadsheetDocument document, bool evaluateFormulae) + { + var context = new SaveContext(); + + var workbookPart = document.WorkbookPart ?? document.AddWorkbookPart(); + + var worksheets = WorksheetsInternal; + + var partsToRemove = workbookPart.Parts.Where(s => worksheets.Deleted.Contains(s.RelationshipId)).ToList(); + + var pivotCacheDefinitionsToRemove = partsToRemove.SelectMany(s => ((WorksheetPart)s.OpenXmlPart).PivotTableParts.Select(pt => pt.PivotTableCacheDefinitionPart)).Distinct().ToList(); + pivotCacheDefinitionsToRemove.ForEach(c => workbookPart.DeletePart(c)); + + if (workbookPart.Workbook != null && workbookPart.Workbook.PivotCaches != null) + { + var pivotCachesToRemove = workbookPart.Workbook.PivotCaches.Where(pc => pivotCacheDefinitionsToRemove.Select(pcd => workbookPart.GetIdOfPart(pcd)).ToList().Contains(((PivotCache)pc).Id)).Distinct().ToList(); + pivotCachesToRemove.ForEach(c => workbookPart.Workbook.PivotCaches.RemoveChild(c)); + } + + worksheets.Deleted.ToList().ForEach(ws => DeleteSheetAndDependencies(workbookPart, ws)); + + // Ensure all RelId's have been added to the context + context.RelIdGenerator.AddValues(workbookPart.Parts.Select(p => p.RelationshipId), RelType.Workbook); + context.RelIdGenerator.AddValues(WorksheetsInternal.Cast().Where(ws => !XLHelper.IsNullOrWhiteSpace(ws.RelId)).Select(ws => ws.RelId), RelType.Workbook); + context.RelIdGenerator.AddValues(WorksheetsInternal.Cast().Where(ws => !XLHelper.IsNullOrWhiteSpace(ws.LegacyDrawingId)).Select(ws => ws.LegacyDrawingId), RelType.Workbook); + context.RelIdGenerator.AddValues(WorksheetsInternal + .Cast() + .SelectMany(ws => ws.Tables.Cast()) + .Where(t => !XLHelper.IsNullOrWhiteSpace(t.RelId)) + .Select(t => t.RelId), RelType.Workbook); + + var extendedFilePropertiesPart = document.ExtendedFilePropertiesPart ?? + document.AddNewPart( + context.RelIdGenerator.GetNext(RelType.Workbook)); + + GenerateExtendedFilePropertiesPartContent(extendedFilePropertiesPart); + + GenerateWorkbookPartContent(workbookPart, context); + + var sharedStringTablePart = workbookPart.SharedStringTablePart ?? + workbookPart.AddNewPart( + context.RelIdGenerator.GetNext(RelType.Workbook)); + + GenerateSharedStringTablePartContent(sharedStringTablePart, context); + + var workbookStylesPart = workbookPart.WorkbookStylesPart ?? + workbookPart.AddNewPart( + context.RelIdGenerator.GetNext(RelType.Workbook)); + + GenerateWorkbookStylesPartContent(workbookStylesPart, context); + + foreach (var worksheet in WorksheetsInternal.Cast().OrderBy(w => w.Position)) + { + //context.RelIdGenerator.Reset(RelType.); + WorksheetPart worksheetPart; + var wsRelId = worksheet.RelId; + if (workbookPart.Parts.Any(p => p.RelationshipId == wsRelId)) + { + worksheetPart = (WorksheetPart)workbookPart.GetPartById(wsRelId); + var wsPartsToRemove = worksheetPart.TableDefinitionParts.ToList(); + wsPartsToRemove.ForEach(tdp => worksheetPart.DeletePart(tdp)); + } + else + worksheetPart = workbookPart.AddNewPart(wsRelId); + + context.RelIdGenerator.AddValues(worksheetPart.HyperlinkRelationships.Select(hr => hr.Id), RelType.Workbook); + context.RelIdGenerator.AddValues(worksheetPart.Parts.Select(p => p.RelationshipId), RelType.Workbook); + if (worksheetPart.DrawingsPart != null) + context.RelIdGenerator.AddValues(worksheetPart.DrawingsPart.Parts.Select(p => p.RelationshipId), RelType.Workbook); + + // delete comment related parts (todo: review) + DeleteComments(worksheetPart, worksheet, context); + + if (worksheet.Internals.CellsCollection.GetCells(c => c.HasComment).Any()) + { + var id = context.RelIdGenerator.GetNext(RelType.Workbook); + var worksheetCommentsPart = + worksheetPart.AddNewPart(id); + + GenerateWorksheetCommentsPartContent(worksheetCommentsPart, worksheet); + + //VmlDrawingPart vmlDrawingPart = worksheetPart.AddNewPart(worksheet.LegacyDrawingId); + var vmlDrawingPart = worksheetPart.VmlDrawingParts.FirstOrDefault(); + if (vmlDrawingPart == null) + { + if (XLHelper.IsNullOrWhiteSpace(worksheet.LegacyDrawingId)) + { + worksheet.LegacyDrawingId = context.RelIdGenerator.GetNext(RelType.Workbook); + worksheet.LegacyDrawingIsNew = true; + } + + vmlDrawingPart = worksheetPart.AddNewPart(worksheet.LegacyDrawingId); + } + GenerateVmlDrawingPartContent(vmlDrawingPart, worksheet, context); + } + + GenerateWorksheetPartContent(worksheetPart, worksheet, evaluateFormulae, context); + + if (worksheet.PivotTables.Any()) + { + GeneratePivotTables(workbookPart, worksheetPart, worksheet, context); + } + + // Remove any orphaned references - maybe more types? + foreach (var orphan in worksheetPart.Worksheet.OfType().Where(lg => !worksheetPart.Parts.Any(p => p.RelationshipId == lg.Id))) + worksheetPart.Worksheet.RemoveChild(orphan); + + foreach (var orphan in worksheetPart.Worksheet.OfType().Where(d => !worksheetPart.Parts.Any(p => p.RelationshipId == d.Id))) + worksheetPart.Worksheet.RemoveChild(orphan); + } + + // Remove empty pivot cache part + if (workbookPart.Workbook.PivotCaches != null && !workbookPart.Workbook.PivotCaches.Any()) + workbookPart.Workbook.RemoveChild(workbookPart.Workbook.PivotCaches); + + GenerateCalculationChainPartContent(workbookPart, context); + + if (workbookPart.ThemePart == null) + { + var themePart = workbookPart.AddNewPart(context.RelIdGenerator.GetNext(RelType.Workbook)); + GenerateThemePartContent(themePart); + } + + if (CustomProperties.Any()) + { + document.GetPartsOfType().ToList().ForEach(p => document.DeletePart(p)); + var customFilePropertiesPart = + document.AddNewPart(context.RelIdGenerator.GetNext(RelType.Workbook)); + + GenerateCustomFilePropertiesPartContent(customFilePropertiesPart); + } + SetPackageProperties(document); + } + + private void DeleteComments(WorksheetPart worksheetPart, XLWorksheet worksheet, SaveContext context) + { + // We have the comments so we can delete the comments part + worksheetPart.DeletePart(worksheetPart.WorksheetCommentsPart); + var vmlDrawingPart = worksheetPart.VmlDrawingParts.FirstOrDefault(); + + // Only delete the VmlDrawingParts for comments. + if (vmlDrawingPart != null) + { + var xdoc = XDocumentExtensions.Load(vmlDrawingPart.GetStream(FileMode.Open)); + //xdoc.Root.Elements().Where(e => e.Name.LocalName == "shapelayout").Remove(); + xdoc.Root.Elements().Where( + e => e.Name.LocalName == "shapetype" && (string)e.Attribute("id") == @"_x0000_t202").Remove(); + xdoc.Root.Elements().Where( + e => e.Name.LocalName == "shape" && (string)e.Attribute("type") == @"#_x0000_t202").Remove(); + var imageParts = vmlDrawingPart.ImageParts.ToList(); + var legacyParts = vmlDrawingPart.LegacyDiagramTextParts.ToList(); + var rId = worksheetPart.GetIdOfPart(vmlDrawingPart); + worksheet.LegacyDrawingId = rId; + worksheetPart.ChangeIdOfPart(vmlDrawingPart, "xxRRxx"); // Anything will do for the new relationship id + // we just want it alive enough to create the copy + + var hasShapes = xdoc.Root.Elements().Any(e => e.Name.LocalName == "shape" || e.Name.LocalName == "group"); + + VmlDrawingPart vmlDrawingPartNew = null; + var hasNewPart = (imageParts.Count > 0 || legacyParts.Count > 0 || hasShapes); + if (hasNewPart) + { + vmlDrawingPartNew = worksheetPart.AddNewPart(rId); + + using (var writer = new XmlTextWriter(vmlDrawingPartNew.GetStream(FileMode.Create), Encoding.UTF8)) + { + writer.WriteRaw(xdoc.ToString()); + } + + imageParts.ForEach(p => vmlDrawingPartNew.AddPart(p, vmlDrawingPart.GetIdOfPart(p))); + legacyParts.ForEach(p => vmlDrawingPartNew.AddPart(p, vmlDrawingPart.GetIdOfPart(p))); + } + + worksheetPart.DeletePart(vmlDrawingPart); + + if (hasNewPart && rId != worksheetPart.GetIdOfPart(vmlDrawingPartNew)) + worksheetPart.ChangeIdOfPart(vmlDrawingPartNew, rId); + } + } + + private static void GenerateTables(XLWorksheet worksheet, WorksheetPart worksheetPart, SaveContext context) + { + worksheetPart.Worksheet.RemoveAllChildren(); + + if (!worksheet.Tables.Any()) return; + + foreach (var table in worksheet.Tables) + { + var tableRelId = context.RelIdGenerator.GetNext(RelType.Workbook); + + var xlTable = (XLTable)table; + xlTable.RelId = tableRelId; + + var tableDefinitionPart = worksheetPart.AddNewPart(tableRelId); + GenerateTableDefinitionPartContent(tableDefinitionPart, xlTable, context); + } + } + + private void GenerateExtendedFilePropertiesPartContent(ExtendedFilePropertiesPart extendedFilePropertiesPart) + { + if (extendedFilePropertiesPart.Properties == null) + extendedFilePropertiesPart.Properties = new Properties(); + + var properties = extendedFilePropertiesPart.Properties; + if ( + !properties.NamespaceDeclarations.Contains(new KeyValuePair("vt", + "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"))) + { + properties.AddNamespaceDeclaration("vt", + "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"); + } + + if (properties.Application == null) + properties.AppendChild(new Application { Text = "Microsoft Excel" }); + + if (properties.DocumentSecurity == null) + properties.AppendChild(new DocumentSecurity { Text = "0" }); + + if (properties.ScaleCrop == null) + properties.AppendChild(new ScaleCrop { Text = "false" }); + + if (properties.HeadingPairs == null) + properties.HeadingPairs = new HeadingPairs(); + + if (properties.TitlesOfParts == null) + properties.TitlesOfParts = new TitlesOfParts(); + + properties.HeadingPairs.VTVector = new VTVector { BaseType = VectorBaseValues.Variant }; + + properties.TitlesOfParts.VTVector = new VTVector { BaseType = VectorBaseValues.Lpstr }; + + var vTVectorOne = properties.HeadingPairs.VTVector; + + var vTVectorTwo = properties.TitlesOfParts.VTVector; + + var modifiedWorksheets = + ((IEnumerable)WorksheetsInternal).Select(w => new { w.Name, Order = w.Position }).ToList(); + var modifiedNamedRanges = GetModifiedNamedRanges(); + var modifiedWorksheetsCount = modifiedWorksheets.Count; + var modifiedNamedRangesCount = modifiedNamedRanges.Count; + + InsertOnVtVector(vTVectorOne, "Worksheets", 0, modifiedWorksheetsCount.ToString()); + InsertOnVtVector(vTVectorOne, "Named Ranges", 2, modifiedNamedRangesCount.ToString()); + + vTVectorTwo.Size = (UInt32)(modifiedNamedRangesCount + modifiedWorksheetsCount); + + foreach ( + var vTlpstr3 in modifiedWorksheets.OrderBy(w => w.Order).Select(w => new VTLPSTR { Text = w.Name })) + vTVectorTwo.AppendChild(vTlpstr3); + + foreach (var vTlpstr7 in modifiedNamedRanges.Select(nr => new VTLPSTR { Text = nr })) + vTVectorTwo.AppendChild(vTlpstr7); + + if (Properties.Manager != null) + { + if (!XLHelper.IsNullOrWhiteSpace(Properties.Manager)) + { + if (properties.Manager == null) + properties.Manager = new Manager(); + + properties.Manager.Text = Properties.Manager; + } + else + properties.Manager = null; + } + + if (Properties.Company == null) return; + + if (!XLHelper.IsNullOrWhiteSpace(Properties.Company)) + { + if (properties.Company == null) + properties.Company = new Company(); + + properties.Company.Text = Properties.Company; + } + else + properties.Company = null; + } + + private static void InsertOnVtVector(VTVector vTVector, String property, Int32 index, String text) + { + var m = from e1 in vTVector.Elements() + where e1.Elements().Any(e2 => e2.Text == property) + select e1; + if (!m.Any()) + { + if (vTVector.Size == null) + vTVector.Size = new UInt32Value(0U); + + vTVector.Size += 2U; + var variant1 = new Variant(); + var vTlpstr1 = new VTLPSTR { Text = property }; + variant1.AppendChild(vTlpstr1); + vTVector.InsertAt(variant1, index); + + var variant2 = new Variant(); + var vTInt321 = new VTInt32(); + variant2.AppendChild(vTInt321); + vTVector.InsertAt(variant2, index + 1); + } + + var targetIndex = 0; + foreach (var e in vTVector.Elements()) + { + if (e.Elements().Any(e2 => e2.Text == property)) + { + vTVector.ElementAt(targetIndex + 1).GetFirstChild().Text = text; + break; + } + targetIndex++; + } + } + + private List GetModifiedNamedRanges() + { + var namedRanges = new List(); + foreach (var w in WorksheetsInternal) + { + var wName = w.Name; + namedRanges.AddRange(w.NamedRanges.Select(n => wName + "!" + n.Name)); + namedRanges.Add(w.Name + "!Print_Area"); + namedRanges.Add(w.Name + "!Print_Titles"); + } + namedRanges.AddRange(NamedRanges.Select(n => n.Name)); + return namedRanges; + } + + private void GenerateWorkbookPartContent(WorkbookPart workbookPart, SaveContext context) + { + if (workbookPart.Workbook == null) + workbookPart.Workbook = new Workbook(); + + var workbook = workbookPart.Workbook; + if ( + !workbook.NamespaceDeclarations.Contains(new KeyValuePair("r", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships"))) + { + workbook.AddNamespaceDeclaration("r", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + } + + #region WorkbookProperties + + if (workbook.WorkbookProperties == null) + workbook.WorkbookProperties = new WorkbookProperties(); + + if (workbook.WorkbookProperties.CodeName == null) + workbook.WorkbookProperties.CodeName = "ThisWorkbook"; + + if (Use1904DateSystem) + workbook.WorkbookProperties.Date1904 = true; + + #endregion WorkbookProperties + + #region WorkbookProtection + + if (LockStructure || LockWindows) + { + if (workbook.WorkbookProtection == null) + workbook.WorkbookProtection = new WorkbookProtection(); + + workbook.WorkbookProtection.LockStructure = LockStructure; + workbook.WorkbookProtection.LockWindows = LockWindows; + + if (LockPassword != null) + workbook.WorkbookProtection.WorkbookPassword = LockPassword; + } + else + { + workbook.WorkbookProtection = null; + } + + #endregion + + if (workbook.BookViews == null) + workbook.BookViews = new BookViews(); + + if (workbook.Sheets == null) + workbook.Sheets = new Sheets(); + + var worksheets = WorksheetsInternal; + workbook.Sheets.Elements().Where(s => worksheets.Deleted.Contains(s.Id)).ToList().ForEach( + s => s.Remove()); + + foreach (var sheet in workbook.Sheets.Elements()) + { + var sheetId = (Int32)sheet.SheetId.Value; + + if (WorksheetsInternal.All(w => w.SheetId != sheetId)) continue; + + var wks = WorksheetsInternal.Single(w => w.SheetId == sheetId); + wks.RelId = sheet.Id; + sheet.Name = wks.Name; + } + + foreach (var xlSheet in WorksheetsInternal.Cast().OrderBy(w => w.Position)) + { + string rId; + if (xlSheet.SheetId == 0 && XLHelper.IsNullOrWhiteSpace(xlSheet.RelId)) + { + rId = context.RelIdGenerator.GetNext(RelType.Workbook); + + while (WorksheetsInternal.Cast().Any(w => w.SheetId == Int32.Parse(rId.Substring(3)))) + rId = context.RelIdGenerator.GetNext(RelType.Workbook); + + xlSheet.SheetId = Int32.Parse(rId.Substring(3)); + xlSheet.RelId = rId; + } + else + { + if (XLHelper.IsNullOrWhiteSpace(xlSheet.RelId)) + { + rId = String.Format("rId{0}", xlSheet.SheetId); + context.RelIdGenerator.AddValues(new List { rId }, RelType.Workbook); + } + else + rId = xlSheet.RelId; + } + + if (!workbook.Sheets.Cast().Any(s => s.Id == rId)) + { + var newSheet = new Sheet + { + Name = xlSheet.Name, + Id = rId, + SheetId = (UInt32)xlSheet.SheetId + }; + + workbook.Sheets.AppendChild(newSheet); + } + } + + var sheetElements = from sheet in workbook.Sheets.Elements() + join worksheet in ((IEnumerable)WorksheetsInternal) on sheet.Id.Value + equals worksheet.RelId + orderby worksheet.Position + select sheet; + + UInt32 firstSheetVisible = 0; + var activeTab = + (from us in UnsupportedSheets where us.IsActive select (UInt32)us.Position - 1).FirstOrDefault(); + var foundVisible = false; + + var totalSheets = sheetElements.Count() + UnsupportedSheets.Count; + for (var p = 1; p <= totalSheets; p++) + { + if (UnsupportedSheets.All(us => us.Position != p)) + { + var sheet = sheetElements.ElementAt(p - UnsupportedSheets.Count(us => us.Position <= p) - 1); + workbook.Sheets.RemoveChild(sheet); + workbook.Sheets.AppendChild(sheet); + var xlSheet = Worksheet(sheet.Name); + if (xlSheet.Visibility != XLWorksheetVisibility.Visible) + sheet.State = xlSheet.Visibility.ToOpenXml(); + + if (foundVisible) continue; + + if (sheet.State == null || sheet.State == SheetStateValues.Visible) + foundVisible = true; + else + firstSheetVisible++; + } + else + { + var sheetId = UnsupportedSheets.First(us => us.Position == p).SheetId; + var sheet = workbook.Sheets.Elements().First(s => s.SheetId == sheetId); + workbook.Sheets.RemoveChild(sheet); + workbook.Sheets.AppendChild(sheet); + } + } + + var workbookView = workbook.BookViews.Elements().FirstOrDefault(); + + if (activeTab == 0) + { + activeTab = firstSheetVisible; + foreach (var ws in worksheets) + { + if (!ws.TabActive) continue; + + activeTab = (UInt32)(ws.Position - 1); + break; + } + } + + if (workbookView == null) + { + workbookView = new WorkbookView { ActiveTab = activeTab, FirstSheet = firstSheetVisible }; + workbook.BookViews.AppendChild(workbookView); + } + else + { + workbookView.ActiveTab = activeTab; + workbookView.FirstSheet = firstSheetVisible; + } + + var definedNames = new DefinedNames(); + foreach (var worksheet in WorksheetsInternal) + { + var wsSheetId = (UInt32)worksheet.SheetId; + UInt32 sheetId = 0; + foreach (var s in workbook.Sheets.Elements().TakeWhile(s => s.SheetId != wsSheetId)) + { + sheetId++; + } + + if (worksheet.PageSetup.PrintAreas.Any()) + { + var definedName = new DefinedName { Name = "_xlnm.Print_Area", LocalSheetId = sheetId }; + var worksheetName = worksheet.Name; + var definedNameText = worksheet.PageSetup.PrintAreas.Aggregate(String.Empty, + (current, printArea) => + current + + ("'" + worksheetName + "'!" + + printArea.RangeAddress. + FirstAddress.ToStringFixed( + XLReferenceStyle.A1) + + ":" + + printArea.RangeAddress. + LastAddress.ToStringFixed( + XLReferenceStyle.A1) + + ",")); + definedName.Text = definedNameText.Substring(0, definedNameText.Length - 1); + definedNames.AppendChild(definedName); + } + + if (worksheet.AutoFilter.Enabled) + { + var definedName = new DefinedName + { + Name = "_xlnm._FilterDatabase", + LocalSheetId = sheetId, + Text = "'" + worksheet.Name + "'!" + + worksheet.AutoFilter.Range.RangeAddress.FirstAddress.ToStringFixed( + XLReferenceStyle.A1) + + ":" + + worksheet.AutoFilter.Range.RangeAddress.LastAddress.ToStringFixed( + XLReferenceStyle.A1), + Hidden = BooleanValue.FromBoolean(true) + }; + definedNames.AppendChild(definedName); + } + + foreach (var nr in worksheet.NamedRanges.Where(n => n.Name != "_xlnm._FilterDatabase")) + { + var definedName = new DefinedName + { + Name = nr.Name, + LocalSheetId = sheetId, + Text = nr.ToString() + }; + + if (!nr.Visible) + definedName.Hidden = BooleanValue.FromBoolean(true); + + if (!XLHelper.IsNullOrWhiteSpace(nr.Comment)) + definedName.Comment = nr.Comment; + definedNames.AppendChild(definedName); + } + + var definedNameTextRow = String.Empty; + var definedNameTextColumn = String.Empty; + if (worksheet.PageSetup.FirstRowToRepeatAtTop > 0) + { + definedNameTextRow = "'" + worksheet.Name + "'!" + worksheet.PageSetup.FirstRowToRepeatAtTop + + ":" + worksheet.PageSetup.LastRowToRepeatAtTop; + } + if (worksheet.PageSetup.FirstColumnToRepeatAtLeft > 0) + { + var minColumn = worksheet.PageSetup.FirstColumnToRepeatAtLeft; + var maxColumn = worksheet.PageSetup.LastColumnToRepeatAtLeft; + definedNameTextColumn = "'" + worksheet.Name + "'!" + + XLHelper.GetColumnLetterFromNumber(minColumn) + + ":" + XLHelper.GetColumnLetterFromNumber(maxColumn); + } + + string titles; + if (definedNameTextColumn.Length > 0) + { + titles = definedNameTextColumn; + if (definedNameTextRow.Length > 0) + titles += "," + definedNameTextRow; + } + else + titles = definedNameTextRow; + + if (titles.Length <= 0) continue; + + var definedName2 = new DefinedName + { + Name = "_xlnm.Print_Titles", + LocalSheetId = sheetId, + Text = titles + }; + + definedNames.AppendChild(definedName2); + } + + foreach (var nr in NamedRanges) + { + var definedName = new DefinedName + { + Name = nr.Name, + Text = nr.ToString() + }; + + if (!nr.Visible) + definedName.Hidden = BooleanValue.FromBoolean(true); + + if (!XLHelper.IsNullOrWhiteSpace(nr.Comment)) + definedName.Comment = nr.Comment; + definedNames.AppendChild(definedName); + } + + workbook.DefinedNames = definedNames; + + if (workbook.CalculationProperties == null) + workbook.CalculationProperties = new CalculationProperties { CalculationId = 125725U }; + + if (CalculateMode == XLCalculateMode.Default) + workbook.CalculationProperties.CalculationMode = null; + else + workbook.CalculationProperties.CalculationMode = CalculateMode.ToOpenXml(); + + if (ReferenceStyle == XLReferenceStyle.Default) + workbook.CalculationProperties.ReferenceMode = null; + else + workbook.CalculationProperties.ReferenceMode = ReferenceStyle.ToOpenXml(); + + if (CalculationOnSave) workbook.CalculationProperties.CalculationOnSave = CalculationOnSave; + if (ForceFullCalculation) workbook.CalculationProperties.ForceFullCalculation = ForceFullCalculation; + if (FullCalculationOnLoad) workbook.CalculationProperties.FullCalculationOnLoad = FullCalculationOnLoad; + if (FullPrecision) workbook.CalculationProperties.FullPrecision = FullPrecision; + } + + private void GenerateSharedStringTablePartContent(SharedStringTablePart sharedStringTablePart, + SaveContext context) + { + // Call all table headers to make sure their names are filled + var x = 0; + Worksheets.ForEach(w => w.Tables.ForEach(t => x = (t as XLTable).FieldNames.Count)); + + sharedStringTablePart.SharedStringTable = new SharedStringTable { Count = 0, UniqueCount = 0 }; + + var stringId = 0; + + var newStrings = new Dictionary(); + var newRichStrings = new Dictionary(); + foreach ( + var c in + Worksheets.Cast().SelectMany( + w => + w.Internals.CellsCollection.GetCells( + c => ((c.DataType == XLCellValues.Text && c.ShareString) || c.HasRichText) + && (c as XLCell).InnerText.Length > 0 + && XLHelper.IsNullOrWhiteSpace(c.FormulaA1) + ))) + { + c.DataType = XLCellValues.Text; + if (c.HasRichText) + { + if (newRichStrings.ContainsKey(c.RichText)) + c.SharedStringId = newRichStrings[c.RichText]; + else + { + var sharedStringItem = new SharedStringItem(); + foreach (var rt in c.RichText.Where(r => !String.IsNullOrEmpty(r.Text))) + { + sharedStringItem.Append(GetRun(rt)); + } + + if (c.RichText.HasPhonetics) + { + foreach (var p in c.RichText.Phonetics) + { + var phoneticRun = new PhoneticRun + { + BaseTextStartIndex = (UInt32)p.Start, + EndingBaseIndex = (UInt32)p.End + }; + + var text = new Text { Text = p.Text }; + if (p.Text.PreserveSpaces()) + text.Space = SpaceProcessingModeValues.Preserve; + + phoneticRun.Append(text); + sharedStringItem.Append(phoneticRun); + } + var f = new XLFont(null, c.RichText.Phonetics); + if (!context.SharedFonts.ContainsKey(f)) + context.SharedFonts.Add(f, new FontInfo { Font = f }); + + var phoneticProperties = new PhoneticProperties + { + FontId = + context.SharedFonts[ + new XLFont(null, c.RichText.Phonetics)]. + FontId + }; + if (c.RichText.Phonetics.Alignment != XLPhoneticAlignment.Left) + phoneticProperties.Alignment = c.RichText.Phonetics.Alignment.ToOpenXml(); + if (c.RichText.Phonetics.Type != XLPhoneticType.FullWidthKatakana) + phoneticProperties.Type = c.RichText.Phonetics.Type.ToOpenXml(); + + sharedStringItem.Append(phoneticProperties); + } + + sharedStringTablePart.SharedStringTable.Append(sharedStringItem); + sharedStringTablePart.SharedStringTable.Count += 1; + sharedStringTablePart.SharedStringTable.UniqueCount += 1; + + newRichStrings.Add(c.RichText, stringId); + c.SharedStringId = stringId; + + stringId++; + } + } + else + { + if (newStrings.ContainsKey(c.Value.ToString())) + c.SharedStringId = newStrings[c.Value.ToString()]; + else + { + var s = c.Value.ToString(); + var sharedStringItem = new SharedStringItem(); + var text = new Text { Text = XmlEncoder.EncodeString(s) }; + if (!s.Trim().Equals(s)) + text.Space = SpaceProcessingModeValues.Preserve; + sharedStringItem.Append(text); + sharedStringTablePart.SharedStringTable.Append(sharedStringItem); + sharedStringTablePart.SharedStringTable.Count += 1; + sharedStringTablePart.SharedStringTable.UniqueCount += 1; + + newStrings.Add(c.Value.ToString(), stringId); + c.SharedStringId = stringId; + + stringId++; + } + } + } + } + + private static Run GetRun(IXLRichString rt) + { + var run = new Run(); + + var runProperties = new RunProperties(); + + var bold = rt.Bold ? new Bold() : null; + var italic = rt.Italic ? new Italic() : null; + var underline = rt.Underline != XLFontUnderlineValues.None + ? new Underline { Val = rt.Underline.ToOpenXml() } + : null; + var strike = rt.Strikethrough ? new Strike() : null; + var verticalAlignment = new VerticalTextAlignment + { Val = rt.VerticalAlignment.ToOpenXml() }; + var shadow = rt.Shadow ? new Shadow() : null; + var fontSize = new FontSize { Val = rt.FontSize }; + var color = GetNewColor(rt.FontColor); + var fontName = new RunFont { Val = rt.FontName }; + var fontFamilyNumbering = new FontFamily { Val = (Int32)rt.FontFamilyNumbering }; + + if (bold != null) runProperties.Append(bold); + if (italic != null) runProperties.Append(italic); + + if (strike != null) runProperties.Append(strike); + if (shadow != null) runProperties.Append(shadow); + if (underline != null) runProperties.Append(underline); + runProperties.Append(verticalAlignment); + + runProperties.Append(fontSize); + runProperties.Append(color); + runProperties.Append(fontName); + runProperties.Append(fontFamilyNumbering); + + var text = new Text { Text = rt.Text }; + if (rt.Text.PreserveSpaces()) + text.Space = SpaceProcessingModeValues.Preserve; + + run.Append(runProperties); + run.Append(text); + return run; + } + + private void GenerateCalculationChainPartContent(WorkbookPart workbookPart, SaveContext context) + { + var thisRelId = context.RelIdGenerator.GetNext(RelType.Workbook); + if (workbookPart.CalculationChainPart == null) + workbookPart.AddNewPart(thisRelId); + + if (workbookPart.CalculationChainPart.CalculationChain == null) + workbookPart.CalculationChainPart.CalculationChain = new CalculationChain(); + + var calculationChain = workbookPart.CalculationChainPart.CalculationChain; + calculationChain.RemoveAllChildren(); + + foreach (var worksheet in WorksheetsInternal) + { + var cellsWithoutFormulas = new HashSet(); + foreach (var c in worksheet.Internals.CellsCollection.GetCells()) + { + if (XLHelper.IsNullOrWhiteSpace(c.FormulaA1)) + cellsWithoutFormulas.Add(c.Address.ToStringRelative()); + else + { + if (c.FormulaA1.StartsWith("{")) + { + var cc = new CalculationCell + { + CellReference = c.Address.ToString(), + SheetId = worksheet.SheetId + }; + + if (c.FormulaReference == null) + c.FormulaReference = c.AsRange().RangeAddress; + if (c.FormulaReference.FirstAddress.Equals(c.Address)) + { + cc.Array = true; + calculationChain.AppendChild(cc); + calculationChain.AppendChild(new CalculationCell { CellReference = c.Address.ToString(), InChildChain = true }); + } + else + { + calculationChain.AppendChild(cc); + } + } + else + { + calculationChain.AppendChild(new CalculationCell + { + CellReference = c.Address.ToString(), + SheetId = worksheet.SheetId + }); + } + } + } + + //var cCellsToRemove = new List(); + var m = from cc in calculationChain.Elements() + where !(cc.SheetId != null || cc.InChildChain != null) + && calculationChain.Elements() + .Where(c1 => c1.SheetId != null) + .Select(c1 => c1.CellReference.Value) + .Contains(cc.CellReference.Value) + || cellsWithoutFormulas.Contains(cc.CellReference.Value) + select cc; + //m.ToList().ForEach(cc => cCellsToRemove.Add(cc)); + m.ToList().ForEach(cc => calculationChain.RemoveChild(cc)); + } + + if (!calculationChain.Any()) + workbookPart.DeletePart(workbookPart.CalculationChainPart); + } + + private void GenerateThemePartContent(ThemePart themePart) + { + var theme1 = new Theme { Name = "Office Theme" }; + theme1.AddNamespaceDeclaration("a", "http://schemas.openxmlformats.org/drawingml/2006/main"); + + var themeElements1 = new ThemeElements(); + + var colorScheme1 = new ColorScheme { Name = "Office" }; + + var dark1Color1 = new Dark1Color(); + var systemColor1 = new SystemColor + { + Val = SystemColorValues.WindowText, + LastColor = Theme.Text1.Color.ToHex().Substring(2) + }; + + dark1Color1.AppendChild(systemColor1); + + var light1Color1 = new Light1Color(); + var systemColor2 = new SystemColor + { + Val = SystemColorValues.Window, + LastColor = Theme.Background1.Color.ToHex().Substring(2) + }; + + light1Color1.AppendChild(systemColor2); + + var dark2Color1 = new Dark2Color(); + var rgbColorModelHex1 = new RgbColorModelHex { Val = Theme.Text2.Color.ToHex().Substring(2) }; + + dark2Color1.AppendChild(rgbColorModelHex1); + + var light2Color1 = new Light2Color(); + var rgbColorModelHex2 = new RgbColorModelHex { Val = Theme.Background2.Color.ToHex().Substring(2) }; + + light2Color1.AppendChild(rgbColorModelHex2); + + var accent1Color1 = new Accent1Color(); + var rgbColorModelHex3 = new RgbColorModelHex { Val = Theme.Accent1.Color.ToHex().Substring(2) }; + + accent1Color1.AppendChild(rgbColorModelHex3); + + var accent2Color1 = new Accent2Color(); + var rgbColorModelHex4 = new RgbColorModelHex { Val = Theme.Accent2.Color.ToHex().Substring(2) }; + + accent2Color1.AppendChild(rgbColorModelHex4); + + var accent3Color1 = new Accent3Color(); + var rgbColorModelHex5 = new RgbColorModelHex { Val = Theme.Accent3.Color.ToHex().Substring(2) }; + + accent3Color1.AppendChild(rgbColorModelHex5); + + var accent4Color1 = new Accent4Color(); + var rgbColorModelHex6 = new RgbColorModelHex { Val = Theme.Accent4.Color.ToHex().Substring(2) }; + + accent4Color1.AppendChild(rgbColorModelHex6); + + var accent5Color1 = new Accent5Color(); + var rgbColorModelHex7 = new RgbColorModelHex { Val = Theme.Accent5.Color.ToHex().Substring(2) }; + + accent5Color1.AppendChild(rgbColorModelHex7); + + var accent6Color1 = new Accent6Color(); + var rgbColorModelHex8 = new RgbColorModelHex { Val = Theme.Accent6.Color.ToHex().Substring(2) }; + + accent6Color1.AppendChild(rgbColorModelHex8); + + var hyperlink1 = new DocumentFormat.OpenXml.Drawing.Hyperlink(); + var rgbColorModelHex9 = new RgbColorModelHex { Val = Theme.Hyperlink.Color.ToHex().Substring(2) }; + + hyperlink1.AppendChild(rgbColorModelHex9); + + var followedHyperlinkColor1 = new FollowedHyperlinkColor(); + var rgbColorModelHex10 = new RgbColorModelHex { Val = Theme.FollowedHyperlink.Color.ToHex().Substring(2) }; + + followedHyperlinkColor1.AppendChild(rgbColorModelHex10); + + colorScheme1.AppendChild(dark1Color1); + colorScheme1.AppendChild(light1Color1); + colorScheme1.AppendChild(dark2Color1); + colorScheme1.AppendChild(light2Color1); + colorScheme1.AppendChild(accent1Color1); + colorScheme1.AppendChild(accent2Color1); + colorScheme1.AppendChild(accent3Color1); + colorScheme1.AppendChild(accent4Color1); + colorScheme1.AppendChild(accent5Color1); + colorScheme1.AppendChild(accent6Color1); + colorScheme1.AppendChild(hyperlink1); + colorScheme1.AppendChild(followedHyperlinkColor1); + + var fontScheme2 = new FontScheme { Name = "Office" }; + + var majorFont1 = new MajorFont(); + var latinFont1 = new LatinFont { Typeface = "Cambria" }; + var eastAsianFont1 = new EastAsianFont { Typeface = "" }; + var complexScriptFont1 = new ComplexScriptFont { Typeface = "" }; + var supplementalFont1 = new SupplementalFont { Script = "Jpan", Typeface = "MS Pゴシック" }; + var supplementalFont2 = new SupplementalFont { Script = "Hang", Typeface = "맑은 고딕" }; + var supplementalFont3 = new SupplementalFont { Script = "Hans", Typeface = "宋体" }; + var supplementalFont4 = new SupplementalFont { Script = "Hant", Typeface = "新細明體" }; + var supplementalFont5 = new SupplementalFont { Script = "Arab", Typeface = "Times New Roman" }; + var supplementalFont6 = new SupplementalFont { Script = "Hebr", Typeface = "Times New Roman" }; + var supplementalFont7 = new SupplementalFont { Script = "Thai", Typeface = "Tahoma" }; + var supplementalFont8 = new SupplementalFont { Script = "Ethi", Typeface = "Nyala" }; + var supplementalFont9 = new SupplementalFont { Script = "Beng", Typeface = "Vrinda" }; + var supplementalFont10 = new SupplementalFont { Script = "Gujr", Typeface = "Shruti" }; + var supplementalFont11 = new SupplementalFont { Script = "Khmr", Typeface = "MoolBoran" }; + var supplementalFont12 = new SupplementalFont { Script = "Knda", Typeface = "Tunga" }; + var supplementalFont13 = new SupplementalFont { Script = "Guru", Typeface = "Raavi" }; + var supplementalFont14 = new SupplementalFont { Script = "Cans", Typeface = "Euphemia" }; + var supplementalFont15 = new SupplementalFont { Script = "Cher", Typeface = "Plantagenet Cherokee" }; + var supplementalFont16 = new SupplementalFont { Script = "Yiii", Typeface = "Microsoft Yi Baiti" }; + var supplementalFont17 = new SupplementalFont { Script = "Tibt", Typeface = "Microsoft Himalaya" }; + var supplementalFont18 = new SupplementalFont { Script = "Thaa", Typeface = "MV Boli" }; + var supplementalFont19 = new SupplementalFont { Script = "Deva", Typeface = "Mangal" }; + var supplementalFont20 = new SupplementalFont { Script = "Telu", Typeface = "Gautami" }; + var supplementalFont21 = new SupplementalFont { Script = "Taml", Typeface = "Latha" }; + var supplementalFont22 = new SupplementalFont { Script = "Syrc", Typeface = "Estrangelo Edessa" }; + var supplementalFont23 = new SupplementalFont { Script = "Orya", Typeface = "Kalinga" }; + var supplementalFont24 = new SupplementalFont { Script = "Mlym", Typeface = "Kartika" }; + var supplementalFont25 = new SupplementalFont { Script = "Laoo", Typeface = "DokChampa" }; + var supplementalFont26 = new SupplementalFont { Script = "Sinh", Typeface = "Iskoola Pota" }; + var supplementalFont27 = new SupplementalFont { Script = "Mong", Typeface = "Mongolian Baiti" }; + var supplementalFont28 = new SupplementalFont { Script = "Viet", Typeface = "Times New Roman" }; + var supplementalFont29 = new SupplementalFont { Script = "Uigh", Typeface = "Microsoft Uighur" }; + + majorFont1.AppendChild(latinFont1); + majorFont1.AppendChild(eastAsianFont1); + majorFont1.AppendChild(complexScriptFont1); + majorFont1.AppendChild(supplementalFont1); + majorFont1.AppendChild(supplementalFont2); + majorFont1.AppendChild(supplementalFont3); + majorFont1.AppendChild(supplementalFont4); + majorFont1.AppendChild(supplementalFont5); + majorFont1.AppendChild(supplementalFont6); + majorFont1.AppendChild(supplementalFont7); + majorFont1.AppendChild(supplementalFont8); + majorFont1.AppendChild(supplementalFont9); + majorFont1.AppendChild(supplementalFont10); + majorFont1.AppendChild(supplementalFont11); + majorFont1.AppendChild(supplementalFont12); + majorFont1.AppendChild(supplementalFont13); + majorFont1.AppendChild(supplementalFont14); + majorFont1.AppendChild(supplementalFont15); + majorFont1.AppendChild(supplementalFont16); + majorFont1.AppendChild(supplementalFont17); + majorFont1.AppendChild(supplementalFont18); + majorFont1.AppendChild(supplementalFont19); + majorFont1.AppendChild(supplementalFont20); + majorFont1.AppendChild(supplementalFont21); + majorFont1.AppendChild(supplementalFont22); + majorFont1.AppendChild(supplementalFont23); + majorFont1.AppendChild(supplementalFont24); + majorFont1.AppendChild(supplementalFont25); + majorFont1.AppendChild(supplementalFont26); + majorFont1.AppendChild(supplementalFont27); + majorFont1.AppendChild(supplementalFont28); + majorFont1.AppendChild(supplementalFont29); + + var minorFont1 = new MinorFont(); + var latinFont2 = new LatinFont { Typeface = "Calibri" }; + var eastAsianFont2 = new EastAsianFont { Typeface = "" }; + var complexScriptFont2 = new ComplexScriptFont { Typeface = "" }; + var supplementalFont30 = new SupplementalFont { Script = "Jpan", Typeface = "MS Pゴシック" }; + var supplementalFont31 = new SupplementalFont { Script = "Hang", Typeface = "맑은 고딕" }; + var supplementalFont32 = new SupplementalFont { Script = "Hans", Typeface = "宋体" }; + var supplementalFont33 = new SupplementalFont { Script = "Hant", Typeface = "新細明體" }; + var supplementalFont34 = new SupplementalFont { Script = "Arab", Typeface = "Arial" }; + var supplementalFont35 = new SupplementalFont { Script = "Hebr", Typeface = "Arial" }; + var supplementalFont36 = new SupplementalFont { Script = "Thai", Typeface = "Tahoma" }; + var supplementalFont37 = new SupplementalFont { Script = "Ethi", Typeface = "Nyala" }; + var supplementalFont38 = new SupplementalFont { Script = "Beng", Typeface = "Vrinda" }; + var supplementalFont39 = new SupplementalFont { Script = "Gujr", Typeface = "Shruti" }; + var supplementalFont40 = new SupplementalFont { Script = "Khmr", Typeface = "DaunPenh" }; + var supplementalFont41 = new SupplementalFont { Script = "Knda", Typeface = "Tunga" }; + var supplementalFont42 = new SupplementalFont { Script = "Guru", Typeface = "Raavi" }; + var supplementalFont43 = new SupplementalFont { Script = "Cans", Typeface = "Euphemia" }; + var supplementalFont44 = new SupplementalFont { Script = "Cher", Typeface = "Plantagenet Cherokee" }; + var supplementalFont45 = new SupplementalFont { Script = "Yiii", Typeface = "Microsoft Yi Baiti" }; + var supplementalFont46 = new SupplementalFont { Script = "Tibt", Typeface = "Microsoft Himalaya" }; + var supplementalFont47 = new SupplementalFont { Script = "Thaa", Typeface = "MV Boli" }; + var supplementalFont48 = new SupplementalFont { Script = "Deva", Typeface = "Mangal" }; + var supplementalFont49 = new SupplementalFont { Script = "Telu", Typeface = "Gautami" }; + var supplementalFont50 = new SupplementalFont { Script = "Taml", Typeface = "Latha" }; + var supplementalFont51 = new SupplementalFont { Script = "Syrc", Typeface = "Estrangelo Edessa" }; + var supplementalFont52 = new SupplementalFont { Script = "Orya", Typeface = "Kalinga" }; + var supplementalFont53 = new SupplementalFont { Script = "Mlym", Typeface = "Kartika" }; + var supplementalFont54 = new SupplementalFont { Script = "Laoo", Typeface = "DokChampa" }; + var supplementalFont55 = new SupplementalFont { Script = "Sinh", Typeface = "Iskoola Pota" }; + var supplementalFont56 = new SupplementalFont { Script = "Mong", Typeface = "Mongolian Baiti" }; + var supplementalFont57 = new SupplementalFont { Script = "Viet", Typeface = "Arial" }; + var supplementalFont58 = new SupplementalFont { Script = "Uigh", Typeface = "Microsoft Uighur" }; + + minorFont1.AppendChild(latinFont2); + minorFont1.AppendChild(eastAsianFont2); + minorFont1.AppendChild(complexScriptFont2); + minorFont1.AppendChild(supplementalFont30); + minorFont1.AppendChild(supplementalFont31); + minorFont1.AppendChild(supplementalFont32); + minorFont1.AppendChild(supplementalFont33); + minorFont1.AppendChild(supplementalFont34); + minorFont1.AppendChild(supplementalFont35); + minorFont1.AppendChild(supplementalFont36); + minorFont1.AppendChild(supplementalFont37); + minorFont1.AppendChild(supplementalFont38); + minorFont1.AppendChild(supplementalFont39); + minorFont1.AppendChild(supplementalFont40); + minorFont1.AppendChild(supplementalFont41); + minorFont1.AppendChild(supplementalFont42); + minorFont1.AppendChild(supplementalFont43); + minorFont1.AppendChild(supplementalFont44); + minorFont1.AppendChild(supplementalFont45); + minorFont1.AppendChild(supplementalFont46); + minorFont1.AppendChild(supplementalFont47); + minorFont1.AppendChild(supplementalFont48); + minorFont1.AppendChild(supplementalFont49); + minorFont1.AppendChild(supplementalFont50); + minorFont1.AppendChild(supplementalFont51); + minorFont1.AppendChild(supplementalFont52); + minorFont1.AppendChild(supplementalFont53); + minorFont1.AppendChild(supplementalFont54); + minorFont1.AppendChild(supplementalFont55); + minorFont1.AppendChild(supplementalFont56); + minorFont1.AppendChild(supplementalFont57); + minorFont1.AppendChild(supplementalFont58); + + fontScheme2.AppendChild(majorFont1); + fontScheme2.AppendChild(minorFont1); + + var formatScheme1 = new FormatScheme { Name = "Office" }; + + var fillStyleList1 = new FillStyleList(); + + var solidFill1 = new SolidFill(); + var schemeColor1 = new SchemeColor { Val = SchemeColorValues.PhColor }; + + solidFill1.AppendChild(schemeColor1); + + var gradientFill1 = new GradientFill { RotateWithShape = true }; + + var gradientStopList1 = new GradientStopList(); + + var gradientStop1 = new GradientStop { Position = 0 }; + + var schemeColor2 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var tint1 = new Tint { Val = 50000 }; + var saturationModulation1 = new SaturationModulation { Val = 300000 }; + + schemeColor2.AppendChild(tint1); + schemeColor2.AppendChild(saturationModulation1); + + gradientStop1.AppendChild(schemeColor2); + + var gradientStop2 = new GradientStop { Position = 35000 }; + + var schemeColor3 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var tint2 = new Tint { Val = 37000 }; + var saturationModulation2 = new SaturationModulation { Val = 300000 }; + + schemeColor3.AppendChild(tint2); + schemeColor3.AppendChild(saturationModulation2); + + gradientStop2.AppendChild(schemeColor3); + + var gradientStop3 = new GradientStop { Position = 100000 }; + + var schemeColor4 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var tint3 = new Tint { Val = 15000 }; + var saturationModulation3 = new SaturationModulation { Val = 350000 }; + + schemeColor4.AppendChild(tint3); + schemeColor4.AppendChild(saturationModulation3); + + gradientStop3.AppendChild(schemeColor4); + + gradientStopList1.AppendChild(gradientStop1); + gradientStopList1.AppendChild(gradientStop2); + gradientStopList1.AppendChild(gradientStop3); + var linearGradientFill1 = new LinearGradientFill { Angle = 16200000, Scaled = true }; + + gradientFill1.AppendChild(gradientStopList1); + gradientFill1.AppendChild(linearGradientFill1); + + var gradientFill2 = new GradientFill { RotateWithShape = true }; + + var gradientStopList2 = new GradientStopList(); + + var gradientStop4 = new GradientStop { Position = 0 }; + + var schemeColor5 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var shade1 = new Shade { Val = 51000 }; + var saturationModulation4 = new SaturationModulation { Val = 130000 }; + + schemeColor5.AppendChild(shade1); + schemeColor5.AppendChild(saturationModulation4); + + gradientStop4.AppendChild(schemeColor5); + + var gradientStop5 = new GradientStop { Position = 80000 }; + + var schemeColor6 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var shade2 = new Shade { Val = 93000 }; + var saturationModulation5 = new SaturationModulation { Val = 130000 }; + + schemeColor6.AppendChild(shade2); + schemeColor6.AppendChild(saturationModulation5); + + gradientStop5.AppendChild(schemeColor6); + + var gradientStop6 = new GradientStop { Position = 100000 }; + + var schemeColor7 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var shade3 = new Shade { Val = 94000 }; + var saturationModulation6 = new SaturationModulation { Val = 135000 }; + + schemeColor7.AppendChild(shade3); + schemeColor7.AppendChild(saturationModulation6); + + gradientStop6.AppendChild(schemeColor7); + + gradientStopList2.AppendChild(gradientStop4); + gradientStopList2.AppendChild(gradientStop5); + gradientStopList2.AppendChild(gradientStop6); + var linearGradientFill2 = new LinearGradientFill { Angle = 16200000, Scaled = false }; + + gradientFill2.AppendChild(gradientStopList2); + gradientFill2.AppendChild(linearGradientFill2); + + fillStyleList1.AppendChild(solidFill1); + fillStyleList1.AppendChild(gradientFill1); + fillStyleList1.AppendChild(gradientFill2); + + var lineStyleList1 = new LineStyleList(); + + var outline1 = new Outline + { + Width = 9525, + CapType = LineCapValues.Flat, + CompoundLineType = CompoundLineValues.Single, + Alignment = PenAlignmentValues.Center + }; + + var solidFill2 = new SolidFill(); + + var schemeColor8 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var shade4 = new Shade { Val = 95000 }; + var saturationModulation7 = new SaturationModulation { Val = 105000 }; + + schemeColor8.AppendChild(shade4); + schemeColor8.AppendChild(saturationModulation7); + + solidFill2.AppendChild(schemeColor8); + var presetDash1 = new PresetDash { Val = PresetLineDashValues.Solid }; + + outline1.AppendChild(solidFill2); + outline1.AppendChild(presetDash1); + + var outline2 = new Outline + { + Width = 25400, + CapType = LineCapValues.Flat, + CompoundLineType = CompoundLineValues.Single, + Alignment = PenAlignmentValues.Center + }; + + var solidFill3 = new SolidFill(); + var schemeColor9 = new SchemeColor { Val = SchemeColorValues.PhColor }; + + solidFill3.AppendChild(schemeColor9); + var presetDash2 = new PresetDash { Val = PresetLineDashValues.Solid }; + + outline2.AppendChild(solidFill3); + outline2.AppendChild(presetDash2); + + var outline3 = new Outline + { + Width = 38100, + CapType = LineCapValues.Flat, + CompoundLineType = CompoundLineValues.Single, + Alignment = PenAlignmentValues.Center + }; + + var solidFill4 = new SolidFill(); + var schemeColor10 = new SchemeColor { Val = SchemeColorValues.PhColor }; + + solidFill4.AppendChild(schemeColor10); + var presetDash3 = new PresetDash { Val = PresetLineDashValues.Solid }; + + outline3.AppendChild(solidFill4); + outline3.AppendChild(presetDash3); + + lineStyleList1.AppendChild(outline1); + lineStyleList1.AppendChild(outline2); + lineStyleList1.AppendChild(outline3); + + var effectStyleList1 = new EffectStyleList(); + + var effectStyle1 = new EffectStyle(); + + var effectList1 = new EffectList(); + + var outerShadow1 = new OuterShadow + { + BlurRadius = 40000L, + Distance = 20000L, + Direction = 5400000, + RotateWithShape = false + }; + + var rgbColorModelHex11 = new RgbColorModelHex { Val = "000000" }; + var alpha1 = new Alpha { Val = 38000 }; + + rgbColorModelHex11.AppendChild(alpha1); + + outerShadow1.AppendChild(rgbColorModelHex11); + + effectList1.AppendChild(outerShadow1); + + effectStyle1.AppendChild(effectList1); + + var effectStyle2 = new EffectStyle(); + + var effectList2 = new EffectList(); + + var outerShadow2 = new OuterShadow + { + BlurRadius = 40000L, + Distance = 23000L, + Direction = 5400000, + RotateWithShape = false + }; + + var rgbColorModelHex12 = new RgbColorModelHex { Val = "000000" }; + var alpha2 = new Alpha { Val = 35000 }; + + rgbColorModelHex12.AppendChild(alpha2); + + outerShadow2.AppendChild(rgbColorModelHex12); + + effectList2.AppendChild(outerShadow2); + + effectStyle2.AppendChild(effectList2); + + var effectStyle3 = new EffectStyle(); + + var effectList3 = new EffectList(); + + var outerShadow3 = new OuterShadow + { + BlurRadius = 40000L, + Distance = 23000L, + Direction = 5400000, + RotateWithShape = false + }; + + var rgbColorModelHex13 = new RgbColorModelHex { Val = "000000" }; + var alpha3 = new Alpha { Val = 35000 }; + + rgbColorModelHex13.AppendChild(alpha3); + + outerShadow3.AppendChild(rgbColorModelHex13); + + effectList3.AppendChild(outerShadow3); + + var scene3DType1 = new Scene3DType(); + + var camera1 = new Camera { Preset = PresetCameraValues.OrthographicFront }; + var rotation1 = new Rotation { Latitude = 0, Longitude = 0, Revolution = 0 }; + + camera1.AppendChild(rotation1); + + var lightRig1 = new LightRig { Rig = LightRigValues.ThreePoints, Direction = LightRigDirectionValues.Top }; + var rotation2 = new Rotation { Latitude = 0, Longitude = 0, Revolution = 1200000 }; + + lightRig1.AppendChild(rotation2); + + scene3DType1.AppendChild(camera1); + scene3DType1.AppendChild(lightRig1); + + var shape3DType1 = new Shape3DType(); + var bevelTop1 = new BevelTop { Width = 63500L, Height = 25400L }; + + shape3DType1.AppendChild(bevelTop1); + + effectStyle3.AppendChild(effectList3); + effectStyle3.AppendChild(scene3DType1); + effectStyle3.AppendChild(shape3DType1); + + effectStyleList1.AppendChild(effectStyle1); + effectStyleList1.AppendChild(effectStyle2); + effectStyleList1.AppendChild(effectStyle3); + + var backgroundFillStyleList1 = new BackgroundFillStyleList(); + + var solidFill5 = new SolidFill(); + var schemeColor11 = new SchemeColor { Val = SchemeColorValues.PhColor }; + + solidFill5.AppendChild(schemeColor11); + + var gradientFill3 = new GradientFill { RotateWithShape = true }; + + var gradientStopList3 = new GradientStopList(); + + var gradientStop7 = new GradientStop { Position = 0 }; + + var schemeColor12 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var tint4 = new Tint { Val = 40000 }; + var saturationModulation8 = new SaturationModulation { Val = 350000 }; + + schemeColor12.AppendChild(tint4); + schemeColor12.AppendChild(saturationModulation8); + + gradientStop7.AppendChild(schemeColor12); + + var gradientStop8 = new GradientStop { Position = 40000 }; + + var schemeColor13 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var tint5 = new Tint { Val = 45000 }; + var shade5 = new Shade { Val = 99000 }; + var saturationModulation9 = new SaturationModulation { Val = 350000 }; + + schemeColor13.AppendChild(tint5); + schemeColor13.AppendChild(shade5); + schemeColor13.AppendChild(saturationModulation9); + + gradientStop8.AppendChild(schemeColor13); + + var gradientStop9 = new GradientStop { Position = 100000 }; + + var schemeColor14 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var shade6 = new Shade { Val = 20000 }; + var saturationModulation10 = new SaturationModulation { Val = 255000 }; + + schemeColor14.AppendChild(shade6); + schemeColor14.AppendChild(saturationModulation10); + + gradientStop9.AppendChild(schemeColor14); + + gradientStopList3.AppendChild(gradientStop7); + gradientStopList3.AppendChild(gradientStop8); + gradientStopList3.AppendChild(gradientStop9); + + var pathGradientFill1 = new PathGradientFill { Path = PathShadeValues.Circle }; + var fillToRectangle1 = new FillToRectangle { Left = 50000, Top = -80000, Right = 50000, Bottom = 180000 }; + + pathGradientFill1.AppendChild(fillToRectangle1); + + gradientFill3.AppendChild(gradientStopList3); + gradientFill3.AppendChild(pathGradientFill1); + + var gradientFill4 = new GradientFill { RotateWithShape = true }; + + var gradientStopList4 = new GradientStopList(); + + var gradientStop10 = new GradientStop { Position = 0 }; + + var schemeColor15 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var tint6 = new Tint { Val = 80000 }; + var saturationModulation11 = new SaturationModulation { Val = 300000 }; + + schemeColor15.AppendChild(tint6); + schemeColor15.AppendChild(saturationModulation11); + + gradientStop10.AppendChild(schemeColor15); + + var gradientStop11 = new GradientStop { Position = 100000 }; + + var schemeColor16 = new SchemeColor { Val = SchemeColorValues.PhColor }; + var shade7 = new Shade { Val = 30000 }; + var saturationModulation12 = new SaturationModulation { Val = 200000 }; + + schemeColor16.AppendChild(shade7); + schemeColor16.AppendChild(saturationModulation12); + + gradientStop11.AppendChild(schemeColor16); + + gradientStopList4.AppendChild(gradientStop10); + gradientStopList4.AppendChild(gradientStop11); + + var pathGradientFill2 = new PathGradientFill { Path = PathShadeValues.Circle }; + var fillToRectangle2 = new FillToRectangle { Left = 50000, Top = 50000, Right = 50000, Bottom = 50000 }; + + pathGradientFill2.AppendChild(fillToRectangle2); + + gradientFill4.AppendChild(gradientStopList4); + gradientFill4.AppendChild(pathGradientFill2); + + backgroundFillStyleList1.AppendChild(solidFill5); + backgroundFillStyleList1.AppendChild(gradientFill3); + backgroundFillStyleList1.AppendChild(gradientFill4); + + formatScheme1.AppendChild(fillStyleList1); + formatScheme1.AppendChild(lineStyleList1); + formatScheme1.AppendChild(effectStyleList1); + formatScheme1.AppendChild(backgroundFillStyleList1); + + themeElements1.AppendChild(colorScheme1); + themeElements1.AppendChild(fontScheme2); + themeElements1.AppendChild(formatScheme1); + var objectDefaults1 = new ObjectDefaults(); + var extraColorSchemeList1 = new ExtraColorSchemeList(); + + theme1.AppendChild(themeElements1); + theme1.AppendChild(objectDefaults1); + theme1.AppendChild(extraColorSchemeList1); + + themePart.Theme = theme1; + } + + private void GenerateCustomFilePropertiesPartContent(CustomFilePropertiesPart customFilePropertiesPart1) + { + var properties2 = new DocumentFormat.OpenXml.CustomProperties.Properties(); + properties2.AddNamespaceDeclaration("vt", + "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"); + var propertyId = 1; + foreach (var p in CustomProperties) + { + propertyId++; + var customDocumentProperty = new CustomDocumentProperty + { + FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", + PropertyId = propertyId, + Name = p.Name + }; + if (p.Type == XLCustomPropertyType.Text) + { + var vTlpwstr1 = new VTLPWSTR { Text = p.GetValue() }; + customDocumentProperty.AppendChild(vTlpwstr1); + } + else if (p.Type == XLCustomPropertyType.Date) + { + var vTFileTime1 = new VTFileTime + { + Text = + p.GetValue().ToUniversalTime().ToString( + "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'") + }; + customDocumentProperty.AppendChild(vTFileTime1); + } + else if (p.Type == XLCustomPropertyType.Number) + { + var vTDouble1 = new VTDouble + { + Text = p.GetValue().ToInvariantString() + }; + customDocumentProperty.AppendChild(vTDouble1); + } + else + { + var vTBool1 = new VTBool { Text = p.GetValue().ToString().ToLower() }; + customDocumentProperty.AppendChild(vTBool1); + } + properties2.AppendChild(customDocumentProperty); + } + + customFilePropertiesPart1.Properties = properties2; + } + + private void SetPackageProperties(OpenXmlPackage document) + { + var created = Properties.Created == DateTime.MinValue ? DateTime.Now : Properties.Created; + var modified = Properties.Modified == DateTime.MinValue ? DateTime.Now : Properties.Modified; + document.PackageProperties.Created = created; + document.PackageProperties.Modified = modified; + document.PackageProperties.LastModifiedBy = Properties.LastModifiedBy; + + document.PackageProperties.Creator = Properties.Author; + document.PackageProperties.Title = Properties.Title; + document.PackageProperties.Subject = Properties.Subject; + document.PackageProperties.Category = Properties.Category; + document.PackageProperties.Keywords = Properties.Keywords; + document.PackageProperties.Description = Properties.Comments; + document.PackageProperties.ContentStatus = Properties.Status; + } + + private static string GetTableName(String originalTableName, SaveContext context) + { + var tableName = originalTableName.RemoveSpecialCharacters(); + var name = tableName; + if (context.TableNames.Contains(name)) + { + var i = 1; + name = tableName + i.ToInvariantString(); + while (context.TableNames.Contains(name)) + { + i++; + name = tableName + i.ToInvariantString(); + } + } + + context.TableNames.Add(name); + return name; + } + + private static void GenerateTableDefinitionPartContent(TableDefinitionPart tableDefinitionPart, XLTable xlTable, + SaveContext context) + { + context.TableId++; + var reference = xlTable.RangeAddress.FirstAddress + ":" + xlTable.RangeAddress.LastAddress; + var tableName = GetTableName(xlTable.Name, context); + var table = new Table + { + Id = context.TableId, + Name = tableName, + DisplayName = tableName, + Reference = reference + }; + + if (!xlTable.ShowHeaderRow) + table.HeaderRowCount = 0; + + if (xlTable.ShowTotalsRow) + table.TotalsRowCount = 1; + else + table.TotalsRowShown = false; + + var tableColumns1 = new TableColumns { Count = (UInt32)xlTable.ColumnCount() }; + + UInt32 columnId = 0; + foreach (var xlField in xlTable.Fields) + { + columnId++; + var fieldName = xlField.Name; + var tableColumn1 = new TableColumn + { + Id = columnId, + Name = fieldName.Replace("_x000a_", "_x005f_x000a_").Replace(Environment.NewLine, "_x000a_") + }; + if (xlTable.ShowTotalsRow) + { + if (xlField.TotalsRowFunction != XLTotalsRowFunction.None) + { + tableColumn1.TotalsRowFunction = xlField.TotalsRowFunction.ToOpenXml(); + + if (xlField.TotalsRowFunction == XLTotalsRowFunction.Custom) + tableColumn1.TotalsRowFormula = new TotalsRowFormula(xlField.TotalsRowFormulaA1); + } + + if (!XLHelper.IsNullOrWhiteSpace(xlField.TotalsRowLabel)) + tableColumn1.TotalsRowLabel = xlField.TotalsRowLabel; + } + tableColumns1.AppendChild(tableColumn1); + } + + var tableStyleInfo1 = new TableStyleInfo + { + ShowFirstColumn = xlTable.EmphasizeFirstColumn, + ShowLastColumn = xlTable.EmphasizeLastColumn, + ShowRowStripes = xlTable.ShowRowStripes, + ShowColumnStripes = xlTable.ShowColumnStripes + }; + + if (xlTable.Theme != XLTableTheme.None) + tableStyleInfo1.Name = xlTable.Theme.Name; + + if (xlTable.ShowAutoFilter) + { + var autoFilter1 = new AutoFilter(); + if (xlTable.ShowTotalsRow) + { + xlTable.AutoFilter.Range = xlTable.Worksheet.Range( + xlTable.RangeAddress.FirstAddress.RowNumber, xlTable.RangeAddress.FirstAddress.ColumnNumber, + xlTable.RangeAddress.LastAddress.RowNumber - 1, xlTable.RangeAddress.LastAddress.ColumnNumber); + } + else + xlTable.AutoFilter.Range = xlTable.Worksheet.Range(xlTable.RangeAddress); + + PopulateAutoFilter(xlTable.AutoFilter, autoFilter1); + + table.AppendChild(autoFilter1); + } + + table.AppendChild(tableColumns1); + table.AppendChild(tableStyleInfo1); + + tableDefinitionPart.Table = table; + } + + private static void GeneratePivotTables(WorkbookPart workbookPart, WorksheetPart worksheetPart, + XLWorksheet xlWorksheet, + SaveContext context) + { + PivotCaches pivotCaches; + uint cacheId = 0; + if (workbookPart.Workbook.PivotCaches == null) + pivotCaches = workbookPart.Workbook.InsertAfter(new PivotCaches(), workbookPart.Workbook.CalculationProperties); + else + { + pivotCaches = workbookPart.Workbook.PivotCaches; + if (pivotCaches.Any()) + cacheId = pivotCaches.Cast().Max(pc => pc.CacheId.Value) + 1; + } + + foreach (var pt in xlWorksheet.PivotTables.Cast()) + { + // TODO: Avoid duplicate pivot caches of same source range + + var workbookCacheRelId = pt.WorkbookCacheRelId; + PivotCache pivotCache; + PivotTableCacheDefinitionPart pivotTableCacheDefinitionPart; + if (!XLHelper.IsNullOrWhiteSpace(pt.WorkbookCacheRelId)) + { + pivotCache = pivotCaches.Cast().Single(pc => pc.Id.Value == pt.WorkbookCacheRelId); + pivotTableCacheDefinitionPart = workbookPart.GetPartById(pt.WorkbookCacheRelId) as PivotTableCacheDefinitionPart; + } + else + { + workbookCacheRelId = context.RelIdGenerator.GetNext(RelType.Workbook); + pivotCache = new PivotCache { CacheId = cacheId++, Id = workbookCacheRelId }; + pivotTableCacheDefinitionPart = workbookPart.AddNewPart(workbookCacheRelId); + } + + GeneratePivotTableCacheDefinitionPartContent(pivotTableCacheDefinitionPart, pt); + + if (XLHelper.IsNullOrWhiteSpace(pt.WorkbookCacheRelId)) + pivotCaches.AppendChild(pivotCache); + + PivotTablePart pivotTablePart; + if (XLHelper.IsNullOrWhiteSpace(pt.RelId)) + pivotTablePart = worksheetPart.AddNewPart(context.RelIdGenerator.GetNext(RelType.Workbook)); + else + pivotTablePart = worksheetPart.GetPartById(pt.RelId) as PivotTablePart; + + GeneratePivotTablePartContent(pivotTablePart, pt, pivotCache.CacheId, context); + + if (XLHelper.IsNullOrWhiteSpace(pt.RelId)) + pivotTablePart.AddPart(pivotTableCacheDefinitionPart, context.RelIdGenerator.GetNext(RelType.Workbook)); + } + } + + // Generates content of pivotTableCacheDefinitionPart + private static void GeneratePivotTableCacheDefinitionPartContent( + PivotTableCacheDefinitionPart pivotTableCacheDefinitionPart, IXLPivotTable pt) + { + var source = pt.SourceRange; + + var pivotCacheDefinition = new PivotCacheDefinition + { + Id = "rId1", + SaveData = pt.SaveSourceData, + RefreshOnLoad = true //pt.RefreshDataOnOpen + }; + if (pt.ItemsToRetainPerField == XLItemsToRetain.None) + pivotCacheDefinition.MissingItemsLimit = 0U; + else if (pt.ItemsToRetainPerField == XLItemsToRetain.Max) + pivotCacheDefinition.MissingItemsLimit = XLHelper.MaxRowNumber; + + pivotCacheDefinition.AddNamespaceDeclaration("r", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + + var cacheSource = new CacheSource { Type = SourceValues.Worksheet }; + cacheSource.AppendChild(new WorksheetSource { Name = source.ToString() }); + + var cacheFields = new CacheFields(); + + foreach (var c in source.Columns()) + { + var columnNumber = c.ColumnNumber(); + var columnName = c.FirstCell().Value.ToString(); + var xlpf = pt.Fields.Add(columnName); + + var field = + pt.RowLabels.Union(pt.ColumnLabels).Union(pt.ReportFilters).FirstOrDefault(f => f.SourceName == columnName); + if (field != null) + { + xlpf.CustomName = field.CustomName; + xlpf.Subtotals.AddRange(field.Subtotals); + } + + var sharedItems = new SharedItems(); + + var onlyNumbers = + !source.Cells().Any( + cell => + cell.Address.ColumnNumber == columnNumber && + cell.Address.RowNumber > source.FirstRow().RowNumber() && cell.DataType != XLCellValues.Number); + if (onlyNumbers) + { + sharedItems = new SharedItems + { ContainsSemiMixedTypes = false, ContainsString = false, ContainsNumber = true }; + } + else + { + foreach (var cellValue in source.Cells() + .Where(cell => cell.Address.ColumnNumber == columnNumber && cell.Address.RowNumber > source.FirstRow().RowNumber()) + .Select(cell => cell.Value.ToString()) + .Where(cellValue => !xlpf.SharedStrings.Select(ss => ss.ToLower()).Contains(cellValue.ToLower()))) + { + xlpf.SharedStrings.Add(cellValue); + } + + foreach (var li in xlpf.SharedStrings) + { + sharedItems.AppendChild(new StringItem { Val = li }); + } + } + + var cacheField = new CacheField { Name = xlpf.SourceName }; + cacheField.AppendChild(sharedItems); + cacheFields.AppendChild(cacheField); + } + + pivotCacheDefinition.AppendChild(cacheSource); + pivotCacheDefinition.AppendChild(cacheFields); + + pivotTableCacheDefinitionPart.PivotCacheDefinition = pivotCacheDefinition; + + var pivotTableCacheRecordsPart = pivotTableCacheDefinitionPart.GetPartsOfType().Any() ? + pivotTableCacheDefinitionPart.GetPartsOfType().First() : + pivotTableCacheDefinitionPart.AddNewPart("rId1"); + + var pivotCacheRecords = new PivotCacheRecords(); + pivotCacheRecords.AddNamespaceDeclaration("r", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + pivotTableCacheRecordsPart.PivotCacheRecords = pivotCacheRecords; + } + + // Generates content of pivotTablePart + private static void GeneratePivotTablePartContent(PivotTablePart pivotTablePart, IXLPivotTable pt, uint cacheId, SaveContext context) + { + var pivotTableDefinition = new PivotTableDefinition + { + Name = pt.Name, + CacheId = cacheId, + DataCaption = "Values", + MergeItem = GetBooleanValue(pt.MergeAndCenterWithLabels, true), + Indent = Convert.ToUInt32(pt.RowLabelIndent), + PageOverThenDown = (pt.FilterAreaOrder == XLFilterAreaOrder.OverThenDown), + PageWrap = Convert.ToUInt32(pt.FilterFieldsPageWrap), + ShowError = String.IsNullOrEmpty(pt.ErrorValueReplacement), + UseAutoFormatting = GetBooleanValue(pt.AutofitColumns, true), + PreserveFormatting = GetBooleanValue(pt.PreserveCellFormatting, true), + RowGrandTotals = GetBooleanValue(pt.ShowGrandTotalsRows, true), + ColumnGrandTotals = GetBooleanValue(pt.ShowGrandTotalsColumns, true), + SubtotalHiddenItems = GetBooleanValue(pt.FilteredItemsInSubtotals, true), + MultipleFieldFilters = GetBooleanValue(pt.AllowMultipleFilters, true), + CustomListSort = GetBooleanValue(pt.UseCustomListsForSorting, true), + ShowDrill = GetBooleanValue(pt.ShowExpandCollapseButtons, true), + ShowDataTips = GetBooleanValue(pt.ShowContextualTooltips, true), + ShowMemberPropertyTips = GetBooleanValue(pt.ShowPropertiesInTooltips, true), + ShowHeaders = GetBooleanValue(pt.DisplayCaptionsAndDropdowns, true), + GridDropZones = GetBooleanValue(pt.ClassicPivotTableLayout, false), + ShowEmptyRow = GetBooleanValue(pt.ShowEmptyItemsOnRows, true), + ShowEmptyColumn = GetBooleanValue(pt.ShowEmptyItemsOnColumns, true), + ShowItems = GetBooleanValue(pt.DisplayItemLabels, true), + FieldListSortAscending = GetBooleanValue(pt.SortFieldsAtoZ, true), + PrintDrill = GetBooleanValue(pt.PrintExpandCollapsedButtons, true), + ItemPrintTitles = GetBooleanValue(pt.RepeatRowLabels, true), + FieldPrintTitles = GetBooleanValue(pt.PrintTitles, true), + EnableDrill = GetBooleanValue(pt.EnableShowDetails, true) + }; + + if (pt.EmptyCellReplacement != null) + { + pivotTableDefinition.ShowMissing = true; + pivotTableDefinition.MissingCaption = pt.EmptyCellReplacement; + } + else + { + pivotTableDefinition.ShowMissing = false; + } + + if (pt.ErrorValueReplacement != null) + { + pivotTableDefinition.ShowError = true; + pivotTableDefinition.ErrorCaption = pt.ErrorValueReplacement; + } + else + { + pivotTableDefinition.ShowError = false; + } + + var location = new Location + { + Reference = pt.TargetCell.Address.ToString(), + FirstHeaderRow = 1U, + FirstDataRow = 1U, + FirstDataColumn = 1U + }; + + var rowFields = new RowFields(); + var columnFields = new ColumnFields(); + var rowItems = new RowItems(); + var columnItems = new ColumnItems(); + var pageFields = new PageFields { Count = (uint)pt.ReportFilters.Count() }; + var pivotFields = new PivotFields { Count = Convert.ToUInt32(pt.SourceRange.ColumnCount()) }; + + foreach (var xlpf in pt.Fields.OrderBy(f => pt.RowLabels.Any(p => p.SourceName == f.SourceName) ? pt.RowLabels.IndexOf(f) : Int32.MaxValue)) + { + if (pt.RowLabels.Any(p => p.SourceName == xlpf.SourceName)) + { + var f = new Field { Index = pt.Fields.IndexOf(xlpf) }; + rowFields.AppendChild(f); + + for (var i = 0; i < xlpf.SharedStrings.Count; i++) + { + var rowItem = new RowItem(); + rowItem.AppendChild(new MemberPropertyIndex { Val = i }); + rowItems.AppendChild(rowItem); + } + + var rowItemTotal = new RowItem { ItemType = ItemValues.Grand }; + rowItemTotal.AppendChild(new MemberPropertyIndex()); + rowItems.AppendChild(rowItemTotal); + } + else if (pt.ColumnLabels.Any(p => p.SourceName == xlpf.SourceName)) + { + var f = new Field { Index = pt.Fields.IndexOf(xlpf) }; + columnFields.AppendChild(f); + + for (var i = 0; i < xlpf.SharedStrings.Count; i++) + { + var rowItem = new RowItem(); + rowItem.AppendChild(new MemberPropertyIndex { Val = i }); + columnItems.AppendChild(rowItem); + } + + var rowItemTotal = new RowItem { ItemType = ItemValues.Grand }; + rowItemTotal.AppendChild(new MemberPropertyIndex()); + columnItems.AppendChild(rowItemTotal); + } + } + + if (pt.Values.Count() > 1) + { + // -2 is the sentinal value for "Values" + if (pt.ColumnLabels.Any(cl => cl.SourceName == XLConstants.PivotTableValuesSentinalLabel)) + columnFields.AppendChild(new Field { Index = -2 }); + else if (pt.RowLabels.Any(rl => rl.SourceName == XLConstants.PivotTableValuesSentinalLabel)) + { + pivotTableDefinition.DataOnRows = true; + rowFields.AppendChild(new Field { Index = -2 }); + } + } + + foreach (var xlpf in pt.Fields) + { + IXLPivotField labelField = null; + var pf = new PivotField { ShowAll = false, Name = xlpf.CustomName }; + + if (pt.RowLabels.Any(p => p.SourceName == xlpf.SourceName)) + { + labelField = pt.RowLabels.Single(p => p.SourceName == xlpf.SourceName); + pf.Axis = PivotTableAxisValues.AxisRow; + } + else if (pt.ColumnLabels.Any(p => p.SourceName == xlpf.SourceName)) + { + labelField = pt.ColumnLabels.Single(p => p.SourceName == xlpf.SourceName); + pf.Axis = PivotTableAxisValues.AxisColumn; + } + else if (pt.ReportFilters.Any(p => p.SourceName == xlpf.SourceName)) + { + location.ColumnsPerPage = 1; + location.RowPageCount = 1; + pf.Axis = PivotTableAxisValues.AxisPage; + pageFields.AppendChild(new PageField { Hierarchy = -1, Field = pt.Fields.IndexOf(xlpf) }); + } + + if (pt.Values.Any(p => p.SourceName == xlpf.SourceName)) + pf.DataField = true; + + var fieldItems = new Items(); + + if (xlpf.SharedStrings.Count > 0) + { + for (uint i = 0; i < xlpf.SharedStrings.Count; i++) + { + var item = new Item { Index = i }; + if (labelField != null && labelField.Collapsed) + item.HideDetails = BooleanValue.FromBoolean(false); + fieldItems.AppendChild(item); + } + } + + if (xlpf.Subtotals.Count > 0) + { + foreach (var subtotal in xlpf.Subtotals) + { + var itemSubtotal = new Item(); + switch (subtotal) + { + case XLSubtotalFunction.Average: + pf.AverageSubTotal = true; + itemSubtotal.ItemType = ItemValues.Average; + break; + + case XLSubtotalFunction.Count: + pf.CountASubtotal = true; + itemSubtotal.ItemType = ItemValues.CountA; + break; + + case XLSubtotalFunction.CountNumbers: + pf.CountSubtotal = true; + itemSubtotal.ItemType = ItemValues.Count; + break; + + case XLSubtotalFunction.Maximum: + pf.MaxSubtotal = true; + itemSubtotal.ItemType = ItemValues.Maximum; + break; + + case XLSubtotalFunction.Minimum: + pf.MinSubtotal = true; + itemSubtotal.ItemType = ItemValues.Minimum; + break; + + case XLSubtotalFunction.PopulationStandardDeviation: + pf.ApplyStandardDeviationPInSubtotal = true; + itemSubtotal.ItemType = ItemValues.StandardDeviationP; + break; + + case XLSubtotalFunction.PopulationVariance: + pf.ApplyVariancePInSubtotal = true; + itemSubtotal.ItemType = ItemValues.VarianceP; + break; + + case XLSubtotalFunction.Product: + pf.ApplyProductInSubtotal = true; + itemSubtotal.ItemType = ItemValues.Product; + break; + + case XLSubtotalFunction.StandardDeviation: + pf.ApplyStandardDeviationInSubtotal = true; + itemSubtotal.ItemType = ItemValues.StandardDeviation; + break; + + case XLSubtotalFunction.Sum: + pf.SumSubtotal = true; + itemSubtotal.ItemType = ItemValues.Sum; + break; + + case XLSubtotalFunction.Variance: + pf.ApplyVarianceInSubtotal = true; + itemSubtotal.ItemType = ItemValues.Variance; + break; + } + fieldItems.AppendChild(itemSubtotal); + } + } + else + { + fieldItems.AppendChild(new Item { ItemType = ItemValues.Default }); + } + + fieldItems.Count = Convert.ToUInt32(fieldItems.Count()); + pf.AppendChild(fieldItems); + pivotFields.AppendChild(pf); + } + + pivotTableDefinition.AppendChild(location); + pivotTableDefinition.AppendChild(pivotFields); + + if (pt.RowLabels.Any()) + { + rowFields.Count = Convert.ToUInt32(rowFields.Count()); + pivotTableDefinition.AppendChild(rowFields); + } + else + { + rowItems.AppendChild(new RowItem()); + } + + if (rowItems.Any()) + { + rowItems.Count = Convert.ToUInt32(rowItems.Count()); + pivotTableDefinition.AppendChild(rowItems); + } + + if (!pt.ColumnLabels.Any(cl => cl.CustomName != XLConstants.PivotTableValuesSentinalLabel)) + { + for (int i = 0; i < pt.Values.Count(); i++) + { + var rowItem = new RowItem(); + rowItem.Index = Convert.ToUInt32(i); + rowItem.AppendChild(new MemberPropertyIndex() { Val = i }); + columnItems.AppendChild(rowItem); + } + } + + if (columnFields.Any()) + { + columnFields.Count = Convert.ToUInt32(columnFields.Count()); + pivotTableDefinition.AppendChild(columnFields); + } + + if (columnItems.Any()) + { + columnItems.Count = Convert.ToUInt32(columnItems.Count()); + pivotTableDefinition.AppendChild(columnItems); + } + + if (pt.ReportFilters.Any()) + { + pageFields.Count = Convert.ToUInt32(pageFields.Count()); + pivotTableDefinition.AppendChild(pageFields); + } + + var dataFields = new DataFields(); + foreach (var value in pt.Values) + { + var sourceColumn = + pt.SourceRange.Columns().FirstOrDefault(c => c.Cell(1).Value.ToString() == value.SourceName); + if (sourceColumn == null) continue; + + UInt32 numberFormatId = 0; + if (value.NumberFormat.NumberFormatId != -1 || context.SharedNumberFormats.ContainsKey(value.NumberFormat.NumberFormatId)) + numberFormatId = (UInt32)value.NumberFormat.NumberFormatId; + else if (context.SharedNumberFormats.Any(snf => snf.Value.NumberFormat.Format == value.NumberFormat.Format)) + numberFormatId = (UInt32)context.SharedNumberFormats.First(snf => snf.Value.NumberFormat.Format == value.NumberFormat.Format).Key; + + var df = new DataField + { + Name = value.CustomName, + Field = (UInt32)sourceColumn.ColumnNumber() - 1, + Subtotal = value.SummaryFormula.ToOpenXml(), + ShowDataAs = value.Calculation.ToOpenXml(), + NumberFormatId = numberFormatId + }; + + if (!String.IsNullOrEmpty(value.BaseField)) + { + var baseField = pt.SourceRange.Columns().FirstOrDefault(c => c.Cell(1).Value.ToString() == value.BaseField); + if (baseField != null) + { + df.BaseField = baseField.ColumnNumber() - 1; + + var items = baseField.CellsUsed() + .Select(c => c.Value) + .Skip(1) // Skip header column + .Distinct().ToList(); + + if (items.Any(i => i.Equals(value.BaseItem))) + df.BaseItem = Convert.ToUInt32(items.IndexOf(value.BaseItem)); + } + } + else + { + df.BaseField = 0; + } + + if (value.CalculationItem == XLPivotCalculationItem.Previous) + df.BaseItem = 1048828U; + else if (value.CalculationItem == XLPivotCalculationItem.Next) + df.BaseItem = 1048829U; + else if (df.BaseItem == null || !df.BaseItem.HasValue) + df.BaseItem = 0U; + + dataFields.AppendChild(df); + } + + if (dataFields.Any()) + { + dataFields.Count = Convert.ToUInt32(dataFields.Count()); + pivotTableDefinition.AppendChild(dataFields); + } + + pivotTableDefinition.AppendChild(new PivotTableStyle + { + Name = Enum.GetName(typeof(XLPivotTableTheme), pt.Theme), + ShowRowHeaders = pt.ShowRowHeaders, + ShowColumnHeaders = pt.ShowColumnHeaders, + ShowRowStripes = pt.ShowRowStripes, + ShowColumnStripes = pt.ShowColumnStripes + }); + + #region Excel 2010 Features + + var pivotTableDefinitionExtensionList = new PivotTableDefinitionExtensionList(); + + var pivotTableDefinitionExtension = new PivotTableDefinitionExtension + { Uri = "{962EF5D1-5CA2-4c93-8EF4-DBF5C05439D2}" }; + pivotTableDefinitionExtension.AddNamespaceDeclaration("x14", + "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"); + + var pivotTableDefinition2 = new DocumentFormat.OpenXml.Office2010.Excel.PivotTableDefinition + { EnableEdit = pt.EnableCellEditing, HideValuesRow = !pt.ShowValuesRow }; + pivotTableDefinition2.AddNamespaceDeclaration("xm", "http://schemas.microsoft.com/office/excel/2006/main"); + + pivotTableDefinitionExtension.AppendChild(pivotTableDefinition2); + + pivotTableDefinitionExtensionList.AppendChild(pivotTableDefinitionExtension); + pivotTableDefinition.AppendChild(pivotTableDefinitionExtensionList); + + #endregion Excel 2010 Features + + pivotTablePart.PivotTableDefinition = pivotTableDefinition; + } + + private static void GenerateWorksheetCommentsPartContent(WorksheetCommentsPart worksheetCommentsPart, + XLWorksheet xlWorksheet) + { + var comments = new Comments(); + var commentList = new CommentList(); + var authorsDict = new Dictionary(); + foreach (var c in xlWorksheet.Internals.CellsCollection.GetCells(c => c.HasComment)) + { + var comment = new Comment { Reference = c.Address.ToStringRelative() }; + var authorName = c.Comment.Author; + + Int32 authorId; + if (!authorsDict.TryGetValue(authorName, out authorId)) + { + authorId = authorsDict.Count; + authorsDict.Add(authorName, authorId); + } + comment.AuthorId = (UInt32)authorId; + + var commentText = new CommentText(); + foreach (var rt in c.Comment) + { + commentText.Append(GetRun(rt)); + } + + comment.Append(commentText); + commentList.Append(comment); + } + + var authors = new Authors(); + foreach (var author in authorsDict.Select(a => new Author { Text = a.Key })) + { + authors.Append(author); + } + comments.Append(authors); + comments.Append(commentList); + + worksheetCommentsPart.Comments = comments; + } + + // Generates content of vmlDrawingPart1. + private static void GenerateVmlDrawingPartContent(VmlDrawingPart vmlDrawingPart, XLWorksheet xlWorksheet, + SaveContext context) + { + var ms = new MemoryStream(); + CopyStream(vmlDrawingPart.GetStream(FileMode.OpenOrCreate), ms); + ms.Position = 0; + var writer = new XmlTextWriter(vmlDrawingPart.GetStream(FileMode.Create), Encoding.UTF8); + + writer.WriteStartElement("xml"); + + const string shapeTypeId = "_x0000_t202"; // arbitrary, assigned by office + + new Vml.Shapetype( + new Vml.Stroke { JoinStyle = Vml.StrokeJoinStyleValues.Miter }, + new Vml.Path { AllowGradientShape = true, ConnectionPointType = ConnectValues.Rectangle } + ) + { + Id = shapeTypeId, + CoordinateSize = "21600,21600", + OptionalNumber = 202, + EdgePath = "m,l,21600r21600,l21600,xe", + } + .WriteTo(writer); + + var cellWithComments = xlWorksheet.Internals.CellsCollection.GetCells().Where(c => c.HasComment); + + foreach (var c in cellWithComments) + { + GenerateShape(c, shapeTypeId).WriteTo(writer); + } + + if (ms.Length > 0) + { + ms.Position = 0; + var xdoc = XDocumentExtensions.Load(ms); + xdoc.Root.Elements().ForEach(e => writer.WriteRaw(e.ToString())); + } + + writer.WriteEndElement(); + writer.Flush(); + writer.Close(); + } + + // VML Shape for Comment + private static Vml.Shape GenerateShape(XLCell c, string shapeTypeId) + { + var rowNumber = c.Address.RowNumber; + var columnNumber = c.Address.ColumnNumber; + + var shapeId = String.Format("_x0000_s{0}", c.Comment.ShapeId); + // Unique per cell (workbook?), e.g.: "_x0000_s1026" + var anchor = GetAnchor(c); + var textBox = GetTextBox(c.Comment.Style); + var fill = new Vml.Fill { Color2 = "#" + c.Comment.Style.ColorsAndLines.FillColor.Color.ToHex().Substring(2) }; + if (c.Comment.Style.ColorsAndLines.FillTransparency < 1) + fill.Opacity = + Math.Round(Convert.ToDouble(c.Comment.Style.ColorsAndLines.FillTransparency), 2).ToString( + CultureInfo.InvariantCulture); + var stroke = GetStroke(c); + var shape = new Vml.Shape( + fill, + stroke, + new Vml.Shadow { On = true, Color = "black", Obscured = true }, + new Vml.Path { ConnectionPointType = ConnectValues.None }, + textBox, + new ClientData( + new MoveWithCells(c.Comment.Style.Properties.Positioning == XLDrawingAnchor.Absolute + ? "True" + : "False"), // Counterintuitive + new ResizeWithCells(c.Comment.Style.Properties.Positioning == XLDrawingAnchor.MoveAndSizeWithCells + ? "False" + : "True"), // Counterintuitive + anchor, + new HorizontalTextAlignment(c.Comment.Style.Alignment.Horizontal.ToString().ToCamel()), + new Vml.Spreadsheet.VerticalTextAlignment(c.Comment.Style.Alignment.Vertical.ToString().ToCamel()), + new AutoFill("False"), + new CommentRowTarget { Text = (rowNumber - 1).ToString() }, + new CommentColumnTarget { Text = (columnNumber - 1).ToString() }, + new Locked(c.Comment.Style.Protection.Locked ? "True" : "False"), + new LockText(c.Comment.Style.Protection.LockText ? "True" : "False"), + new Visible(c.Comment.Visible ? "True" : "False") + ) + { ObjectType = ObjectValues.Note } + ) + { + Id = shapeId, + Type = "#" + shapeTypeId, + Style = GetCommentStyle(c), + FillColor = "#" + c.Comment.Style.ColorsAndLines.FillColor.Color.ToHex().Substring(2), + StrokeColor = "#" + c.Comment.Style.ColorsAndLines.LineColor.Color.ToHex().Substring(2), + StrokeWeight = String.Format(CultureInfo.InvariantCulture, "{0}pt", c.Comment.Style.ColorsAndLines.LineWeight), + InsetMode = c.Comment.Style.Margins.Automatic ? InsetMarginValues.Auto : InsetMarginValues.Custom + }; + if (!XLHelper.IsNullOrWhiteSpace(c.Comment.Style.Web.AlternateText)) + shape.Alternate = c.Comment.Style.Web.AlternateText; + + return shape; + } + + private static Vml.Stroke GetStroke(XLCell c) + { + var lineDash = c.Comment.Style.ColorsAndLines.LineDash; + var stroke = new Vml.Stroke + { + LineStyle = c.Comment.Style.ColorsAndLines.LineStyle.ToOpenXml(), + DashStyle = + lineDash == XLDashStyle.RoundDot || lineDash == XLDashStyle.SquareDot + ? "shortDot" + : lineDash.ToString().ToCamel() + }; + if (lineDash == XLDashStyle.RoundDot) + stroke.EndCap = Vml.StrokeEndCapValues.Round; + if (c.Comment.Style.ColorsAndLines.LineTransparency < 1) + stroke.Opacity = + Math.Round(Convert.ToDouble(c.Comment.Style.ColorsAndLines.LineTransparency), 2).ToString( + CultureInfo.InvariantCulture); + return stroke; + } + + // http://polymathprogrammer.com/2009/10/22/english-metric-units-and-open-xml/ + // http://archive.oreilly.com/pub/post/what_is_an_emu.html + // https://en.wikipedia.org/wiki/Office_Open_XML_file_formats#DrawingML + private static Int64 ConvertToEnglishMetricUnits(Int32 pixels, Double resolution) + { + return Convert.ToInt64(914400 * pixels / resolution); + } + + private static void AddPictureAnchor(WorksheetPart worksheetPart, Drawings.IXLPicture picture, SaveContext context) + { + var pic = picture as Drawings.XLPicture; + var drawingsPart = worksheetPart.DrawingsPart ?? + worksheetPart.AddNewPart(context.RelIdGenerator.GetNext(RelType.Workbook)); + + if (drawingsPart.WorksheetDrawing == null) + drawingsPart.WorksheetDrawing = new Xdr.WorksheetDrawing(); + + var worksheetDrawing = drawingsPart.WorksheetDrawing; + + // Add namespaces + if (!worksheetDrawing.NamespaceDeclarations.Any(nd => nd.Value.Equals("http://schemas.openxmlformats.org/drawingml/2006/main"))) + worksheetDrawing.AddNamespaceDeclaration("a", "http://schemas.openxmlformats.org/drawingml/2006/main"); + + if (!worksheetDrawing.NamespaceDeclarations.Any(nd => nd.Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships"))) + worksheetDrawing.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + ///////// + + // Overwrite actual image binary data + ImagePart imagePart; + if (drawingsPart.HasPartWithId(pic.RelId)) + imagePart = drawingsPart.GetPartById(pic.RelId) as ImagePart; + else + imagePart = drawingsPart.AddImagePart(pic.Format.ToOpenXml(), context.RelIdGenerator.GetNext(RelType.Workbook)); + + using (var stream = new MemoryStream()) + { + pic.ImageStream.CopyTo(stream); + stream.Seek(0, SeekOrigin.Begin); + imagePart.FeedData(stream); + } + ///////// + + // Clear current anchors + var existingAnchor = GetAnchorFromImageId(worksheetPart, pic.RelId); + if (existingAnchor != null) + worksheetDrawing.RemoveChild(existingAnchor); + + var extentsCx = ConvertToEnglishMetricUnits(pic.Width, GraphicsUtils.Graphics.DpiX); + var extentsCy = ConvertToEnglishMetricUnits(pic.Height, GraphicsUtils.Graphics.DpiY); + + var nvps = worksheetDrawing.Descendants(); + var nvpId = nvps.Any() ? + (UInt32Value)worksheetDrawing.Descendants().Max(p => p.Id.Value) + 1 : + 1U; + + Xdr.FromMarker fMark; + Xdr.ToMarker tMark; + switch (pic.Placement) + { + case Drawings.XLPicturePlacement.FreeFloating: + var absoluteAnchor = new Xdr.AbsoluteAnchor( + new Xdr.Position + { + X = ConvertToEnglishMetricUnits(pic.Left, GraphicsUtils.Graphics.DpiX), + Y = ConvertToEnglishMetricUnits(pic.Top, GraphicsUtils.Graphics.DpiY) + }, + new Xdr.Extent + { + Cx = extentsCx, + Cy = extentsCy + }, + new Xdr.Picture( + new Xdr.NonVisualPictureProperties( + new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = pic.Name }, + new Xdr.NonVisualPictureDrawingProperties(new PictureLocks { NoChangeAspect = true }) + ), + new Xdr.BlipFill( + new Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = BlipCompressionValues.Print }, + new Stretch(new FillRectangle()) + ), + new Xdr.ShapeProperties( + new Transform2D( + new Offset { X = 0, Y = 0 }, + new Extents { Cx = extentsCx, Cy = extentsCy } + ), + new PresetGeometry { Preset = ShapeTypeValues.Rectangle } + ) + ), + new Xdr.ClientData() + ); + + worksheetDrawing.Append(absoluteAnchor); + break; + + case Drawings.XLPicturePlacement.MoveAndSize: + var moveAndSizeFromMarker = pic.Markers[Drawings.XLMarkerPosition.TopLeft]; + fMark = new Xdr.FromMarker + { + ColumnId = new Xdr.ColumnId((moveAndSizeFromMarker.Address.ColumnNumber - 1).ToString()), + RowId = new Xdr.RowId((moveAndSizeFromMarker.Address.RowNumber - 1).ToString()), + ColumnOffset = new Xdr.ColumnOffset(ConvertToEnglishMetricUnits(moveAndSizeFromMarker.Offset.X, GraphicsUtils.Graphics.DpiX).ToString()), + RowOffset = new Xdr.RowOffset(ConvertToEnglishMetricUnits(moveAndSizeFromMarker.Offset.Y, GraphicsUtils.Graphics.DpiY).ToString()) + }; + + var moveAndSizeToMarker = pic.Markers[Drawings.XLMarkerPosition.BottomRight]; + tMark = new Xdr.ToMarker + { + ColumnId = new Xdr.ColumnId((moveAndSizeToMarker.Address.ColumnNumber - 1).ToString()), + RowId = new Xdr.RowId((moveAndSizeToMarker.Address.RowNumber - 1).ToString()), + ColumnOffset = new Xdr.ColumnOffset(ConvertToEnglishMetricUnits(moveAndSizeToMarker.Offset.X, GraphicsUtils.Graphics.DpiX).ToString()), + RowOffset = new Xdr.RowOffset(ConvertToEnglishMetricUnits(moveAndSizeToMarker.Offset.Y, GraphicsUtils.Graphics.DpiY).ToString()) + }; + + var twoCellAnchor = new Xdr.TwoCellAnchor( + fMark, + tMark, + new Xdr.Picture( + new Xdr.NonVisualPictureProperties( + new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = pic.Name }, + new Xdr.NonVisualPictureDrawingProperties(new PictureLocks { NoChangeAspect = true }) + ), + new Xdr.BlipFill( + new Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = BlipCompressionValues.Print }, + new Stretch(new FillRectangle()) + ), + new Xdr.ShapeProperties( + new Transform2D( + new Offset { X = 0, Y = 0 }, + new Extents { Cx = extentsCx, Cy = extentsCy } + ), + new PresetGeometry { Preset = ShapeTypeValues.Rectangle } + ) + ), + new Xdr.ClientData() + ); + + worksheetDrawing.Append(twoCellAnchor); + break; + + case Drawings.XLPicturePlacement.Move: + var moveFromMarker = pic.Markers[Drawings.XLMarkerPosition.TopLeft]; + fMark = new Xdr.FromMarker + { + ColumnId = new Xdr.ColumnId((moveFromMarker.Address.ColumnNumber - 1).ToString()), + RowId = new Xdr.RowId((moveFromMarker.Address.RowNumber - 1).ToString()), + ColumnOffset = new Xdr.ColumnOffset(ConvertToEnglishMetricUnits(moveFromMarker.Offset.X, GraphicsUtils.Graphics.DpiX).ToString()), + RowOffset = new Xdr.RowOffset(ConvertToEnglishMetricUnits(moveFromMarker.Offset.Y, GraphicsUtils.Graphics.DpiY).ToString()) + }; + + var oneCellAnchor = new Xdr.OneCellAnchor( + fMark, + new Xdr.Extent + { + Cx = extentsCx, + Cy = extentsCy + }, + new Xdr.Picture( + new Xdr.NonVisualPictureProperties( + new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = pic.Name }, + new Xdr.NonVisualPictureDrawingProperties(new PictureLocks { NoChangeAspect = true }) + ), + new Xdr.BlipFill( + new Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = BlipCompressionValues.Print }, + new Stretch(new FillRectangle()) + ), + new Xdr.ShapeProperties( + new Transform2D( + new Offset { X = 0, Y = 0 }, + new Extents { Cx = extentsCx, Cy = extentsCy } + ), + new PresetGeometry { Preset = ShapeTypeValues.Rectangle } + ) + ), + new Xdr.ClientData() + ); + + worksheetDrawing.Append(oneCellAnchor); + break; + } + } + + private static void RebasePictureIds(WorksheetPart worksheetPart) + { + for (var i = 0; i < worksheetPart.DrawingsPart.WorksheetDrawing.ChildElements.Count; i++) + { + var anchor = worksheetPart.DrawingsPart.WorksheetDrawing.ElementAt(i); + var props = GetPropertiesFromAnchor(anchor); + props.Id = Convert.ToUInt32(i + 1); + } + } + + private static Vml.TextBox GetTextBox(IXLDrawingStyle ds) + { + var sb = new StringBuilder(); + var a = ds.Alignment; + + if (a.Direction == XLDrawingTextDirection.Context) + sb.Append("mso-direction-alt:auto;"); + else if (a.Direction == XLDrawingTextDirection.RightToLeft) + sb.Append("direction:RTL;"); + + if (a.Orientation != XLDrawingTextOrientation.LeftToRight) + { + sb.Append("layout-flow:vertical;"); + if (a.Orientation == XLDrawingTextOrientation.BottomToTop) + sb.Append("mso-layout-flow-alt:bottom-to-top;"); + else if (a.Orientation == XLDrawingTextOrientation.Vertical) + sb.Append("mso-layout-flow-alt:top-to-bottom;"); + } + if (a.AutomaticSize) + sb.Append("mso-fit-shape-to-text:t;"); + var retVal = new Vml.TextBox { Style = sb.ToString() }; + var dm = ds.Margins; + if (!dm.Automatic) + retVal.Inset = String.Format("{0}in,{1}in,{2}in,{3}in", + dm.Left.ToInvariantString(), + dm.Top.ToInvariantString(), + dm.Right.ToInvariantString(), + dm.Bottom.ToInvariantString()); + + return retVal; + } + + private static Anchor GetAnchor(XLCell cell) + { + var c = cell.Comment; + var cWidth = c.Style.Size.Width; + var fcNumber = c.Position.Column - 1; + var fcOffset = Convert.ToInt32(c.Position.ColumnOffset * 7.5); + var widthFromColumns = cell.Worksheet.Column(c.Position.Column).Width - c.Position.ColumnOffset; + var lastCell = cell.CellRight(c.Position.Column - cell.Address.ColumnNumber); + while (widthFromColumns <= cWidth) + { + lastCell = lastCell.CellRight(); + widthFromColumns += lastCell.WorksheetColumn().Width; + } + + var lcNumber = lastCell.WorksheetColumn().ColumnNumber() - 1; + var lcOffset = Convert.ToInt32((lastCell.WorksheetColumn().Width - (widthFromColumns - cWidth)) * 7.5); + + var cHeight = c.Style.Size.Height; //c.Style.Size.Height * 72.0; + var frNumber = c.Position.Row - 1; + var frOffset = Convert.ToInt32(c.Position.RowOffset); + var heightFromRows = cell.Worksheet.Row(c.Position.Row).Height - c.Position.RowOffset; + lastCell = cell.CellBelow(c.Position.Row - cell.Address.RowNumber); + while (heightFromRows <= cHeight) + { + lastCell = lastCell.CellBelow(); + heightFromRows += lastCell.WorksheetRow().Height; + } + + var lrNumber = lastCell.WorksheetRow().RowNumber() - 1; + var lrOffset = Convert.ToInt32(lastCell.WorksheetRow().Height - (heightFromRows - cHeight)); + return new Anchor + { + Text = string.Format("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}", + fcNumber, fcOffset, + frNumber, frOffset, + lcNumber, lcOffset, + lrNumber, lrOffset + ) + }; + } + + private static StringValue GetCommentStyle(XLCell cell) + { + var c = cell.Comment; + var sb = new StringBuilder("position:absolute; "); + + sb.Append("visibility:"); + sb.Append(c.Visible ? "visible" : "hidden"); + sb.Append(";"); + + sb.Append("width:"); + sb.Append(Math.Round(c.Style.Size.Width * 7.5, 2).ToInvariantString()); + sb.Append("pt;"); + sb.Append("height:"); + sb.Append(Math.Round(c.Style.Size.Height, 2).ToInvariantString()); + sb.Append("pt;"); + + sb.Append("z-index:"); + sb.Append(c.ZOrder.ToString()); + + return sb.ToString(); + } + + #region GenerateWorkbookStylesPartContent + + private void GenerateWorkbookStylesPartContent(WorkbookStylesPart workbookStylesPart, SaveContext context) + { + var defaultStyle = new XLStyle(null, DefaultStyle); + var defaultStyleId = GetStyleId(defaultStyle); + if (!context.SharedFonts.ContainsKey(defaultStyle.Font)) + context.SharedFonts.Add(defaultStyle.Font, new FontInfo { FontId = 0, Font = defaultStyle.Font as XLFont }); + + var sharedFills = new Dictionary + {{defaultStyle.Fill, new FillInfo {FillId = 2, Fill = defaultStyle.Fill as XLFill}}}; + + var sharedBorders = new Dictionary + {{defaultStyle.Border, new BorderInfo {BorderId = 0, Border = defaultStyle.Border as XLBorder}}}; + + var sharedNumberFormats = new Dictionary + { + { + defaultStyle.NumberFormat, + new NumberFormatInfo + {NumberFormatId = 0, NumberFormat = defaultStyle.NumberFormat} + } + }; + + //Dictionary sharedAlignments = new Dictionary(); + //sharedAlignments.Add(defaultStyle.Alignment.ToString(), new AlignmentInfo() { AlignmentId = 0, Alignment = defaultStyle.Alignment }); + + if (workbookStylesPart.Stylesheet == null) + workbookStylesPart.Stylesheet = new Stylesheet(); + + // Cell styles = Named styles + if (workbookStylesPart.Stylesheet.CellStyles == null) + workbookStylesPart.Stylesheet.CellStyles = new CellStyles(); + + // To determine the default workbook style, we look for the style with builtInId = 0 (I hope that is the correct approach) + UInt32 defaultFormatId; + if (workbookStylesPart.Stylesheet.CellStyles.Elements().Any(c => c.BuiltinId != null && c.BuiltinId.HasValue && c.BuiltinId.Value == 0)) + { + // Possible to have duplicate default cell styles - occurs when file gets saved under different cultures. + // We prefer the style that is named Normal + var normalCellStyles = workbookStylesPart.Stylesheet.CellStyles.Elements() + .Where(c => c.BuiltinId != null && c.BuiltinId.HasValue && c.BuiltinId.Value == 0) + .OrderBy(c => c.Name != null && c.Name.HasValue && c.Name.Value == "Normal"); + + defaultFormatId = normalCellStyles.Last().FormatId.Value; + } + else if (workbookStylesPart.Stylesheet.CellStyles.Elements().Any()) + defaultFormatId = workbookStylesPart.Stylesheet.CellStyles.Elements().Max(c => c.FormatId.Value) + 1; + else + defaultFormatId = 0; + + context.SharedStyles.Add(defaultStyleId, + new StyleInfo + { + StyleId = defaultFormatId, + Style = defaultStyle, + FontId = 0, + FillId = 0, + BorderId = 0, + NumberFormatId = 0 + //AlignmentId = 0 + }); + + UInt32 styleCount = 1; + UInt32 fontCount = 1; + UInt32 fillCount = 3; + UInt32 borderCount = 1; + var numberFormatCount = 1; + var xlStyles = new HashSet(); + var pivotTableNumberFormats = new HashSet(); + + foreach (var worksheet in WorksheetsInternal) + { + foreach (var s in worksheet.GetStyleIds().Where(s => !xlStyles.Contains(s))) + xlStyles.Add(s); + + foreach ( + var s in + worksheet.Internals.ColumnsCollection.Select(kp => kp.Value.GetStyleId()).Where( + s => !xlStyles.Contains(s))) + xlStyles.Add(s); + + foreach ( + var s in + worksheet.Internals.RowsCollection.Select(kp => kp.Value.GetStyleId()).Where( + s => !xlStyles.Contains(s)) + ) + xlStyles.Add(s); + + foreach (var ptnf in worksheet.PivotTables.SelectMany(pt => pt.Values.Select(ptv => ptv.NumberFormat)).Distinct().Where(nf => !pivotTableNumberFormats.Contains(nf))) + pivotTableNumberFormats.Add(ptnf); + } + + foreach (var numberFormat in pivotTableNumberFormats) + { + if (numberFormat.NumberFormatId != -1 + || sharedNumberFormats.ContainsKey(numberFormat)) + continue; + + sharedNumberFormats.Add(numberFormat, + new NumberFormatInfo + { + NumberFormatId = XLConstants.NumberOfBuiltInStyles + numberFormatCount, + NumberFormat = numberFormat + }); + numberFormatCount++; + } + + foreach (var xlStyle in xlStyles.Select(GetStyleById)) + { + if (!context.SharedFonts.ContainsKey(xlStyle.Font)) + context.SharedFonts.Add(xlStyle.Font, + new FontInfo { FontId = fontCount++, Font = xlStyle.Font as XLFont }); + + if (!sharedFills.ContainsKey(xlStyle.Fill)) + sharedFills.Add(xlStyle.Fill, new FillInfo { FillId = fillCount++, Fill = xlStyle.Fill as XLFill }); + + if (!sharedBorders.ContainsKey(xlStyle.Border)) + sharedBorders.Add(xlStyle.Border, + new BorderInfo { BorderId = borderCount++, Border = xlStyle.Border as XLBorder }); + + if (xlStyle.NumberFormat.NumberFormatId != -1 + || sharedNumberFormats.ContainsKey(xlStyle.NumberFormat)) + continue; + + sharedNumberFormats.Add(xlStyle.NumberFormat, + new NumberFormatInfo + { + NumberFormatId = XLConstants.NumberOfBuiltInStyles + numberFormatCount, + NumberFormat = xlStyle.NumberFormat + }); + numberFormatCount++; + } + + var allSharedNumberFormats = ResolveNumberFormats(workbookStylesPart, sharedNumberFormats, defaultFormatId); + foreach (var nf in allSharedNumberFormats) + { + context.SharedNumberFormats.Add(nf.Value.NumberFormatId, nf.Value); + } + + ResolveFonts(workbookStylesPart, context); + var allSharedFills = ResolveFills(workbookStylesPart, sharedFills); + var allSharedBorders = ResolveBorders(workbookStylesPart, sharedBorders); + + foreach (var id in xlStyles) + { + var xlStyle = GetStyleById(id); + if (context.SharedStyles.ContainsKey(id)) continue; + + var numberFormatId = xlStyle.NumberFormat.NumberFormatId >= 0 + ? xlStyle.NumberFormat.NumberFormatId + : allSharedNumberFormats[xlStyle.NumberFormat].NumberFormatId; + + context.SharedStyles.Add(id, + new StyleInfo + { + StyleId = styleCount++, + Style = xlStyle, + FontId = context.SharedFonts[xlStyle.Font].FontId, + FillId = allSharedFills[xlStyle.Fill].FillId, + BorderId = allSharedBorders[xlStyle.Border].BorderId, + NumberFormatId = numberFormatId + }); + } + + ResolveCellStyleFormats(workbookStylesPart, context); + ResolveRest(workbookStylesPart, context); + + if (!workbookStylesPart.Stylesheet.CellStyles.Elements().Any(c => c.BuiltinId != null && c.BuiltinId.HasValue && c.BuiltinId.Value == 0U)) + workbookStylesPart.Stylesheet.CellStyles.AppendChild(new CellStyle { Name = "Normal", FormatId = defaultFormatId, BuiltinId = 0U }); + + workbookStylesPart.Stylesheet.CellStyles.Count = (UInt32)workbookStylesPart.Stylesheet.CellStyles.Count(); + + var newSharedStyles = new Dictionary(); + foreach (var ss in context.SharedStyles) + { + var styleId = -1; + foreach (CellFormat f in workbookStylesPart.Stylesheet.CellFormats) + { + styleId++; + if (CellFormatsAreEqual(f, ss.Value)) + break; + } + if (styleId == -1) + styleId = 0; + var si = ss.Value; + si.StyleId = (UInt32)styleId; + newSharedStyles.Add(ss.Key, si); + } + context.SharedStyles.Clear(); + newSharedStyles.ForEach(kp => context.SharedStyles.Add(kp.Key, kp.Value)); + + AddDifferentialFormats(workbookStylesPart, context); + } + + private void AddDifferentialFormats(WorkbookStylesPart workbookStylesPart, SaveContext context) + { + if (workbookStylesPart.Stylesheet.DifferentialFormats == null) + workbookStylesPart.Stylesheet.DifferentialFormats = new DifferentialFormats(); + + var differentialFormats = workbookStylesPart.Stylesheet.DifferentialFormats; + + FillDifferentialFormatsCollection(differentialFormats, context.DifferentialFormats); + + foreach (var ws in Worksheets) + { + foreach (var cf in ws.ConditionalFormats) + { + if (!context.DifferentialFormats.ContainsKey(cf.Style)) + AddDifferentialFormat(workbookStylesPart.Stylesheet.DifferentialFormats, cf, context); + } + } + + differentialFormats.Count = (UInt32)differentialFormats.Count(); + if (differentialFormats.Count == 0) + workbookStylesPart.Stylesheet.DifferentialFormats = null; + } + + private void FillDifferentialFormatsCollection(DifferentialFormats differentialFormats, + Dictionary dictionary) + { + dictionary.Clear(); + var id = 0; + foreach (var df in differentialFormats.Elements()) + { + var style = new XLStyle(new XLStylizedEmpty(DefaultStyle), DefaultStyle); + LoadFont(df.Font, style.Font); + LoadBorder(df.Border, style.Border); + LoadNumberFormat(df.NumberingFormat, style.NumberFormat); + LoadFill(df.Fill, style.Fill); + if (!dictionary.ContainsKey(style)) + dictionary.Add(style, ++id); + } + } + + private static void AddDifferentialFormat(DifferentialFormats differentialFormats, IXLConditionalFormat cf, + SaveContext context) + { + var differentialFormat = new DifferentialFormat(); + differentialFormat.Append(GetNewFont(new FontInfo { Font = cf.Style.Font as XLFont }, false)); + if (!XLHelper.IsNullOrWhiteSpace(cf.Style.NumberFormat.Format)) + { + var numberFormat = new NumberingFormat + { + NumberFormatId = (UInt32)(XLConstants.NumberOfBuiltInStyles + differentialFormats.Count()), + FormatCode = cf.Style.NumberFormat.Format + }; + differentialFormat.Append(numberFormat); + } + differentialFormat.Append(GetNewFill(new FillInfo { Fill = cf.Style.Fill as XLFill }, false)); + differentialFormat.Append(GetNewBorder(new BorderInfo { Border = cf.Style.Border as XLBorder }, false)); + + differentialFormats.Append(differentialFormat); + + context.DifferentialFormats.Add(cf.Style, differentialFormats.Count() - 1); + } + + private static void ResolveRest(WorkbookStylesPart workbookStylesPart, SaveContext context) + { + if (workbookStylesPart.Stylesheet.CellFormats == null) + workbookStylesPart.Stylesheet.CellFormats = new CellFormats(); + + foreach (var styleInfo in context.SharedStyles.Values) + { + var info = styleInfo; + var foundOne = + workbookStylesPart.Stylesheet.CellFormats.Cast().Any(f => CellFormatsAreEqual(f, info)); + + if (foundOne) continue; + + var cellFormat = GetCellFormat(styleInfo); + cellFormat.FormatId = 0; + var alignment = new Alignment + { + Horizontal = styleInfo.Style.Alignment.Horizontal.ToOpenXml(), + Vertical = styleInfo.Style.Alignment.Vertical.ToOpenXml(), + Indent = (UInt32)styleInfo.Style.Alignment.Indent, + ReadingOrder = (UInt32)styleInfo.Style.Alignment.ReadingOrder, + WrapText = styleInfo.Style.Alignment.WrapText, + TextRotation = (UInt32)styleInfo.Style.Alignment.TextRotation, + ShrinkToFit = styleInfo.Style.Alignment.ShrinkToFit, + RelativeIndent = styleInfo.Style.Alignment.RelativeIndent, + JustifyLastLine = styleInfo.Style.Alignment.JustifyLastLine + }; + cellFormat.AppendChild(alignment); + + if (cellFormat.ApplyProtection.Value) + cellFormat.AppendChild(GetProtection(styleInfo)); + + workbookStylesPart.Stylesheet.CellFormats.AppendChild(cellFormat); + } + workbookStylesPart.Stylesheet.CellFormats.Count = (UInt32)workbookStylesPart.Stylesheet.CellFormats.Count(); + } + + private static void ResolveCellStyleFormats(WorkbookStylesPart workbookStylesPart, + SaveContext context) + { + if (workbookStylesPart.Stylesheet.CellStyleFormats == null) + workbookStylesPart.Stylesheet.CellStyleFormats = new CellStyleFormats(); + + foreach (var styleInfo in context.SharedStyles.Values) + { + var info = styleInfo; + var foundOne = + workbookStylesPart.Stylesheet.CellStyleFormats.Cast().Any( + f => CellFormatsAreEqual(f, info)); + + if (foundOne) continue; + + var cellStyleFormat = GetCellFormat(styleInfo); + + if (cellStyleFormat.ApplyProtection.Value) + cellStyleFormat.AppendChild(GetProtection(styleInfo)); + + workbookStylesPart.Stylesheet.CellStyleFormats.AppendChild(cellStyleFormat); + } + workbookStylesPart.Stylesheet.CellStyleFormats.Count = + (UInt32)workbookStylesPart.Stylesheet.CellStyleFormats.Count(); + } + + private static bool ApplyFill(StyleInfo styleInfo) + { + return styleInfo.Style.Fill.PatternType.ToOpenXml() == PatternValues.None; + } + + private static bool ApplyBorder(StyleInfo styleInfo) + { + var opBorder = styleInfo.Style.Border; + return (opBorder.BottomBorder.ToOpenXml() != BorderStyleValues.None + || opBorder.DiagonalBorder.ToOpenXml() != BorderStyleValues.None + || opBorder.RightBorder.ToOpenXml() != BorderStyleValues.None + || opBorder.LeftBorder.ToOpenXml() != BorderStyleValues.None + || opBorder.TopBorder.ToOpenXml() != BorderStyleValues.None); + } + + private static bool ApplyProtection(StyleInfo styleInfo) + { + return styleInfo.Style.Protection != null; + } + + private static CellFormat GetCellFormat(StyleInfo styleInfo) + { + var cellFormat = new CellFormat + { + NumberFormatId = (UInt32)styleInfo.NumberFormatId, + FontId = styleInfo.FontId, + FillId = styleInfo.FillId, + BorderId = styleInfo.BorderId, + ApplyNumberFormat = true, + ApplyAlignment = true, + ApplyFill = ApplyFill(styleInfo), + ApplyBorder = ApplyBorder(styleInfo), + ApplyProtection = ApplyProtection(styleInfo) + }; + return cellFormat; + } + + private static Protection GetProtection(StyleInfo styleInfo) + { + return new Protection + { + Locked = styleInfo.Style.Protection.Locked, + Hidden = styleInfo.Style.Protection.Hidden + }; + } + + private static bool CellFormatsAreEqual(CellFormat f, StyleInfo styleInfo) + { + return + f.BorderId != null && styleInfo.BorderId == f.BorderId + && f.FillId != null && styleInfo.FillId == f.FillId + && f.FontId != null && styleInfo.FontId == f.FontId + && f.NumberFormatId != null && styleInfo.NumberFormatId == f.NumberFormatId + && f.ApplyFill != null && f.ApplyFill == ApplyFill(styleInfo) + && f.ApplyBorder != null && f.ApplyBorder == ApplyBorder(styleInfo) + && AlignmentsAreEqual(f.Alignment, styleInfo.Style.Alignment) + && ProtectionsAreEqual(f.Protection, styleInfo.Style.Protection) + ; + } + + private static bool ProtectionsAreEqual(Protection protection, IXLProtection xlProtection) + { + var p = new XLProtection(); + if (protection != null) + { + if (protection.Locked != null) + p.Locked = protection.Locked.Value; + if (protection.Hidden != null) + p.Hidden = protection.Hidden.Value; + } + return p.Equals(xlProtection); + } + + private static bool AlignmentsAreEqual(Alignment alignment, IXLAlignment xlAlignment) + { + var a = new XLAlignment(); + if (alignment != null) + { + if (alignment.Indent != null) + a.Indent = (Int32)alignment.Indent.Value; + + if (alignment.Horizontal != null) + a.Horizontal = alignment.Horizontal.Value.ToClosedXml(); + if (alignment.Vertical != null) + a.Vertical = alignment.Vertical.Value.ToClosedXml(); + + if (alignment.ReadingOrder != null) + a.ReadingOrder = alignment.ReadingOrder.Value.ToClosedXml(); + if (alignment.WrapText != null) + a.WrapText = alignment.WrapText.Value; + if (alignment.TextRotation != null) + a.TextRotation = (Int32)alignment.TextRotation.Value; + if (alignment.ShrinkToFit != null) + a.ShrinkToFit = alignment.ShrinkToFit.Value; + if (alignment.RelativeIndent != null) + a.RelativeIndent = alignment.RelativeIndent.Value; + if (alignment.JustifyLastLine != null) + a.JustifyLastLine = alignment.JustifyLastLine.Value; + } + return a.Equals(xlAlignment); + } + + private Dictionary ResolveBorders(WorkbookStylesPart workbookStylesPart, + Dictionary sharedBorders) + { + if (workbookStylesPart.Stylesheet.Borders == null) + workbookStylesPart.Stylesheet.Borders = new Borders(); + + var allSharedBorders = new Dictionary(); + foreach (var borderInfo in sharedBorders.Values) + { + var borderId = 0; + var foundOne = false; + foreach (Border f in workbookStylesPart.Stylesheet.Borders) + { + if (BordersAreEqual(f, borderInfo.Border)) + { + foundOne = true; + break; + } + borderId++; + } + if (!foundOne) + { + var border = GetNewBorder(borderInfo); + workbookStylesPart.Stylesheet.Borders.AppendChild(border); + } + allSharedBorders.Add(borderInfo.Border, + new BorderInfo { Border = borderInfo.Border, BorderId = (UInt32)borderId }); + } + workbookStylesPart.Stylesheet.Borders.Count = (UInt32)workbookStylesPart.Stylesheet.Borders.Count(); + return allSharedBorders; + } + + private static Border GetNewBorder(BorderInfo borderInfo, Boolean ignoreMod = true) + { + var border = new Border(); + if (borderInfo.Border.DiagonalUpModified || ignoreMod) + border.DiagonalUp = borderInfo.Border.DiagonalUp; + + if (borderInfo.Border.DiagonalDownModified || ignoreMod) + border.DiagonalDown = borderInfo.Border.DiagonalDown; + + if (borderInfo.Border.LeftBorderModified || borderInfo.Border.LeftBorderColorModified || ignoreMod) + { + var leftBorder = new LeftBorder { Style = borderInfo.Border.LeftBorder.ToOpenXml() }; + if (borderInfo.Border.LeftBorderColorModified || ignoreMod) + { + var leftBorderColor = GetNewColor(borderInfo.Border.LeftBorderColor); + leftBorder.AppendChild(leftBorderColor); + } + border.AppendChild(leftBorder); + } + + if (borderInfo.Border.RightBorderModified || borderInfo.Border.RightBorderColorModified || ignoreMod) + { + var rightBorder = new RightBorder { Style = borderInfo.Border.RightBorder.ToOpenXml() }; + if (borderInfo.Border.RightBorderColorModified || ignoreMod) + { + var rightBorderColor = GetNewColor(borderInfo.Border.RightBorderColor); + rightBorder.AppendChild(rightBorderColor); + } + border.AppendChild(rightBorder); + } + + if (borderInfo.Border.TopBorderModified || borderInfo.Border.TopBorderColorModified || ignoreMod) + { + var topBorder = new TopBorder { Style = borderInfo.Border.TopBorder.ToOpenXml() }; + if (borderInfo.Border.TopBorderColorModified || ignoreMod) + { + var topBorderColor = GetNewColor(borderInfo.Border.TopBorderColor); + topBorder.AppendChild(topBorderColor); + } + border.AppendChild(topBorder); + } + + if (borderInfo.Border.BottomBorderModified || borderInfo.Border.BottomBorderColorModified || ignoreMod) + { + var bottomBorder = new BottomBorder { Style = borderInfo.Border.BottomBorder.ToOpenXml() }; + if (borderInfo.Border.BottomBorderColorModified || ignoreMod) + { + var bottomBorderColor = GetNewColor(borderInfo.Border.BottomBorderColor); + bottomBorder.AppendChild(bottomBorderColor); + } + border.AppendChild(bottomBorder); + } + + if (borderInfo.Border.DiagonalBorderModified || borderInfo.Border.DiagonalBorderColorModified || ignoreMod) + { + var DiagonalBorder = new DiagonalBorder { Style = borderInfo.Border.DiagonalBorder.ToOpenXml() }; + if (borderInfo.Border.DiagonalBorderColorModified || ignoreMod) + { + var DiagonalBorderColor = GetNewColor(borderInfo.Border.DiagonalBorderColor); + DiagonalBorder.AppendChild(DiagonalBorderColor); + } + border.AppendChild(DiagonalBorder); + } + + return border; + } + + private bool BordersAreEqual(Border b, IXLBorder xlBorder) + { + var nb = new XLBorder(); + if (b.DiagonalUp != null) + nb.DiagonalUp = b.DiagonalUp.Value; + + if (b.DiagonalDown != null) + nb.DiagonalDown = b.DiagonalDown.Value; + + if (b.LeftBorder != null) + { + if (b.LeftBorder.Style != null) + nb.LeftBorder = b.LeftBorder.Style.Value.ToClosedXml(); + var bColor = GetColor(b.LeftBorder.Color); + if (bColor.HasValue) + nb.LeftBorderColor = bColor; + } + + if (b.RightBorder != null) + { + if (b.RightBorder.Style != null) + nb.RightBorder = b.RightBorder.Style.Value.ToClosedXml(); + var bColor = GetColor(b.RightBorder.Color); + if (bColor.HasValue) + nb.RightBorderColor = bColor; + } + + if (b.TopBorder != null) + { + if (b.TopBorder.Style != null) + nb.TopBorder = b.TopBorder.Style.Value.ToClosedXml(); + var bColor = GetColor(b.TopBorder.Color); + if (bColor.HasValue) + nb.TopBorderColor = bColor; + } + + if (b.BottomBorder != null) + { + if (b.BottomBorder.Style != null) + nb.BottomBorder = b.BottomBorder.Style.Value.ToClosedXml(); + var bColor = GetColor(b.BottomBorder.Color); + if (bColor.HasValue) + nb.BottomBorderColor = bColor; + } + + return nb.Equals(xlBorder); + } + + private Dictionary ResolveFills(WorkbookStylesPart workbookStylesPart, + Dictionary sharedFills) + { + if (workbookStylesPart.Stylesheet.Fills == null) + workbookStylesPart.Stylesheet.Fills = new Fills(); + + ResolveFillWithPattern(workbookStylesPart.Stylesheet.Fills, PatternValues.None); + ResolveFillWithPattern(workbookStylesPart.Stylesheet.Fills, PatternValues.Gray125); + + var allSharedFills = new Dictionary(); + foreach (var fillInfo in sharedFills.Values) + { + var fillId = 0; + var foundOne = false; + foreach (Fill f in workbookStylesPart.Stylesheet.Fills) + { + if (FillsAreEqual(f, fillInfo.Fill)) + { + foundOne = true; + break; + } + fillId++; + } + if (!foundOne) + { + var fill = GetNewFill(fillInfo); + workbookStylesPart.Stylesheet.Fills.AppendChild(fill); + } + allSharedFills.Add(fillInfo.Fill, new FillInfo { Fill = fillInfo.Fill, FillId = (UInt32)fillId }); + } + + workbookStylesPart.Stylesheet.Fills.Count = (UInt32)workbookStylesPart.Stylesheet.Fills.Count(); + return allSharedFills; + } + + private static void ResolveFillWithPattern(Fills fills, PatternValues patternValues) + { + if (fills.Elements().Any(f => + f.PatternFill.PatternType == patternValues + && f.PatternFill.ForegroundColor == null + && f.PatternFill.BackgroundColor == null + )) return; + + var fill1 = new Fill(); + var patternFill1 = new PatternFill { PatternType = patternValues }; + fill1.AppendChild(patternFill1); + fills.AppendChild(fill1); + } + + private static Fill GetNewFill(FillInfo fillInfo, Boolean ignoreMod = true) + { + var fill = new Fill(); + + var patternFill = new PatternFill(); + if (fillInfo.Fill.PatternTypeModified || ignoreMod) + patternFill.PatternType = fillInfo.Fill.PatternType.ToOpenXml(); + + if (fillInfo.Fill.PatternColorModified || ignoreMod) + { + var foregroundColor = new ForegroundColor(); + if (fillInfo.Fill.PatternColor.ColorType == XLColorType.Color) + foregroundColor.Rgb = fillInfo.Fill.PatternColor.Color.ToHex(); + else if (fillInfo.Fill.PatternColor.ColorType == XLColorType.Indexed) + foregroundColor.Indexed = (UInt32)fillInfo.Fill.PatternColor.Indexed; + else + { + foregroundColor.Theme = (UInt32)fillInfo.Fill.PatternColor.ThemeColor; + if (fillInfo.Fill.PatternColor.ThemeTint != 0) + foregroundColor.Tint = fillInfo.Fill.PatternColor.ThemeTint; + } + patternFill.AppendChild(foregroundColor); + } + + if (fillInfo.Fill.PatternBackgroundColorModified || ignoreMod) + { + var backgroundColor = new BackgroundColor(); + if (fillInfo.Fill.PatternBackgroundColor.ColorType == XLColorType.Color) + backgroundColor.Rgb = fillInfo.Fill.PatternBackgroundColor.Color.ToHex(); + else if (fillInfo.Fill.PatternBackgroundColor.ColorType == XLColorType.Indexed) + backgroundColor.Indexed = (UInt32)fillInfo.Fill.PatternBackgroundColor.Indexed; + else + { + backgroundColor.Theme = (UInt32)fillInfo.Fill.PatternBackgroundColor.ThemeColor; + if (fillInfo.Fill.PatternBackgroundColor.ThemeTint != 0) + backgroundColor.Tint = fillInfo.Fill.PatternBackgroundColor.ThemeTint; + } + patternFill.AppendChild(backgroundColor); + } + + fill.AppendChild(patternFill); + + return fill; + } + + private bool FillsAreEqual(Fill f, IXLFill xlFill) + { + var nF = new XLFill(); + if (f.PatternFill != null) + { + if (f.PatternFill.PatternType != null) + nF.PatternType = f.PatternFill.PatternType.Value.ToClosedXml(); + + var fColor = GetColor(f.PatternFill.ForegroundColor); + if (fColor.HasValue) + nF.PatternColor = fColor; + + var bColor = GetColor(f.PatternFill.BackgroundColor); + if (bColor.HasValue) + nF.PatternBackgroundColor = bColor; + } + return nF.Equals(xlFill); + } + + private void ResolveFonts(WorkbookStylesPart workbookStylesPart, SaveContext context) + { + if (workbookStylesPart.Stylesheet.Fonts == null) + workbookStylesPart.Stylesheet.Fonts = new Fonts(); + + var newFonts = new Dictionary(); + foreach (var fontInfo in context.SharedFonts.Values) + { + var fontId = 0; + var foundOne = false; + foreach (Font f in workbookStylesPart.Stylesheet.Fonts) + { + if (FontsAreEqual(f, fontInfo.Font)) + { + foundOne = true; + break; + } + fontId++; + } + if (!foundOne) + { + var font = GetNewFont(fontInfo); + workbookStylesPart.Stylesheet.Fonts.AppendChild(font); + } + newFonts.Add(fontInfo.Font, new FontInfo { Font = fontInfo.Font, FontId = (UInt32)fontId }); + } + context.SharedFonts.Clear(); + foreach (var kp in newFonts) + context.SharedFonts.Add(kp.Key, kp.Value); + + workbookStylesPart.Stylesheet.Fonts.Count = (UInt32)workbookStylesPart.Stylesheet.Fonts.Count(); + } + + private static Font GetNewFont(FontInfo fontInfo, Boolean ignoreMod = true) + { + var font = new Font(); + var bold = (fontInfo.Font.BoldModified || ignoreMod) && fontInfo.Font.Bold ? new Bold() : null; + var italic = (fontInfo.Font.ItalicModified || ignoreMod) && fontInfo.Font.Italic ? new Italic() : null; + var underline = (fontInfo.Font.UnderlineModified || ignoreMod) && + fontInfo.Font.Underline != XLFontUnderlineValues.None + ? new Underline { Val = fontInfo.Font.Underline.ToOpenXml() } + : null; + var strike = (fontInfo.Font.StrikethroughModified || ignoreMod) && fontInfo.Font.Strikethrough + ? new Strike() + : null; + var verticalAlignment = fontInfo.Font.VerticalAlignmentModified || ignoreMod + ? new VerticalTextAlignment { Val = fontInfo.Font.VerticalAlignment.ToOpenXml() } + : null; + var shadow = (fontInfo.Font.ShadowModified || ignoreMod) && fontInfo.Font.Shadow ? new Shadow() : null; + var fontSize = fontInfo.Font.FontSizeModified || ignoreMod + ? new FontSize { Val = fontInfo.Font.FontSize } + : null; + var color = fontInfo.Font.FontColorModified || ignoreMod ? GetNewColor(fontInfo.Font.FontColor) : null; + + var fontName = fontInfo.Font.FontNameModified || ignoreMod + ? new FontName { Val = fontInfo.Font.FontName } + : null; + var fontFamilyNumbering = fontInfo.Font.FontFamilyNumberingModified || ignoreMod + ? new FontFamilyNumbering { Val = (Int32)fontInfo.Font.FontFamilyNumbering } + : null; + + if (bold != null) + font.AppendChild(bold); + if (italic != null) + font.AppendChild(italic); + if (underline != null) + font.AppendChild(underline); + if (strike != null) + font.AppendChild(strike); + if (verticalAlignment != null) + font.AppendChild(verticalAlignment); + if (shadow != null) + font.AppendChild(shadow); + if (fontSize != null) + font.AppendChild(fontSize); + if (color != null) + font.AppendChild(color); + if (fontName != null) + font.AppendChild(fontName); + if (fontFamilyNumbering != null) + font.AppendChild(fontFamilyNumbering); + + return font; + } + + private static Color GetNewColor(XLColor xlColor) + { + var color = new Color(); + if (xlColor.ColorType == XLColorType.Color) + color.Rgb = xlColor.Color.ToHex(); + else if (xlColor.ColorType == XLColorType.Indexed) + color.Indexed = (UInt32)xlColor.Indexed; + else + { + color.Theme = (UInt32)xlColor.ThemeColor; + if (xlColor.ThemeTint != 0) + color.Tint = xlColor.ThemeTint; + } + return color; + } + + private static TabColor GetTabColor(XLColor xlColor) + { + var color = new TabColor(); + if (xlColor.ColorType == XLColorType.Color) + color.Rgb = xlColor.Color.ToHex(); + else if (xlColor.ColorType == XLColorType.Indexed) + color.Indexed = (UInt32)xlColor.Indexed; + else + { + color.Theme = (UInt32)xlColor.ThemeColor; + if (xlColor.ThemeTint != 0) + color.Tint = xlColor.ThemeTint; + } + return color; + } + + private bool FontsAreEqual(Font f, IXLFont xlFont) + { + var nf = new XLFont { Bold = f.Bold != null, Italic = f.Italic != null }; + if (f.Underline != null) + { + nf.Underline = f.Underline.Val != null + ? f.Underline.Val.Value.ToClosedXml() + : XLFontUnderlineValues.Single; + } + nf.Strikethrough = f.Strike != null; + if (f.VerticalTextAlignment != null) + { + nf.VerticalAlignment = f.VerticalTextAlignment.Val != null + ? f.VerticalTextAlignment.Val.Value.ToClosedXml() + : XLFontVerticalTextAlignmentValues.Baseline; + } + nf.Shadow = f.Shadow != null; + if (f.FontSize != null) + nf.FontSize = f.FontSize.Val; + var fColor = GetColor(f.Color); + if (fColor.HasValue) + nf.FontColor = fColor; + if (f.FontName != null) + nf.FontName = f.FontName.Val; + if (f.FontFamilyNumbering != null) + nf.FontFamilyNumbering = (XLFontFamilyNumberingValues)f.FontFamilyNumbering.Val.Value; + + return nf.Equals(xlFont); + } + + private static Dictionary ResolveNumberFormats( + WorkbookStylesPart workbookStylesPart, + Dictionary sharedNumberFormats, + UInt32 defaultFormatId) + { + if (workbookStylesPart.Stylesheet.NumberingFormats == null) + { + workbookStylesPart.Stylesheet.NumberingFormats = new NumberingFormats(); + workbookStylesPart.Stylesheet.NumberingFormats.AppendChild(new NumberingFormat() + { + NumberFormatId = 0, + FormatCode = "" + }); + } + + var allSharedNumberFormats = new Dictionary(); + foreach (var numberFormatInfo in sharedNumberFormats.Values.Where(nf => nf.NumberFormatId != defaultFormatId)) + { + var numberingFormatId = XLConstants.NumberOfBuiltInStyles + 1; + var foundOne = false; + foreach (NumberingFormat nf in workbookStylesPart.Stylesheet.NumberingFormats) + { + if (NumberFormatsAreEqual(nf, numberFormatInfo.NumberFormat)) + { + foundOne = true; + numberingFormatId = (Int32)nf.NumberFormatId.Value; + break; + } + numberingFormatId++; + } + if (!foundOne) + { + var numberingFormat = new NumberingFormat + { + NumberFormatId = (UInt32)numberingFormatId, + FormatCode = numberFormatInfo.NumberFormat.Format + }; + workbookStylesPart.Stylesheet.NumberingFormats.AppendChild(numberingFormat); + } + allSharedNumberFormats.Add(numberFormatInfo.NumberFormat, + new NumberFormatInfo + { + NumberFormat = numberFormatInfo.NumberFormat, + NumberFormatId = numberingFormatId + }); + } + workbookStylesPart.Stylesheet.NumberingFormats.Count = + (UInt32)workbookStylesPart.Stylesheet.NumberingFormats.Count(); + return allSharedNumberFormats; + } + + private static bool NumberFormatsAreEqual(NumberingFormat nf, IXLNumberFormatBase xlNumberFormat) + { + var newXLNumberFormat = new XLNumberFormat(); + + if (nf.FormatCode != null && !XLHelper.IsNullOrWhiteSpace(nf.FormatCode.Value)) + newXLNumberFormat.Format = nf.FormatCode.Value; + else if (nf.NumberFormatId != null) + newXLNumberFormat.NumberFormatId = (Int32)nf.NumberFormatId.Value; + + return newXLNumberFormat.Equals(xlNumberFormat); + } + + #endregion GenerateWorkbookStylesPartContent + + #region GenerateWorksheetPartContent + + private static void GenerateWorksheetPartContent( + WorksheetPart worksheetPart, XLWorksheet xlWorksheet, bool evaluateFormulae, SaveContext context) + { + #region Worksheet + + if (worksheetPart.Worksheet == null) + worksheetPart.Worksheet = new Worksheet(); + + GenerateTables(xlWorksheet, worksheetPart, context); + + if ( + !worksheetPart.Worksheet.NamespaceDeclarations.Contains(new KeyValuePair("r", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships"))) + { + worksheetPart.Worksheet.AddNamespaceDeclaration("r", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + } + + #endregion Worksheet + + var cm = new XLWSContentManager(worksheetPart.Worksheet); + + #region SheetProperties + + if (worksheetPart.Worksheet.SheetProperties == null) + worksheetPart.Worksheet.SheetProperties = new SheetProperties(); + + worksheetPart.Worksheet.SheetProperties.TabColor = xlWorksheet.TabColor.HasValue + ? GetTabColor(xlWorksheet.TabColor) + : null; + + cm.SetElement(XLWSContentManager.XLWSContents.SheetProperties, worksheetPart.Worksheet.SheetProperties); + + if (worksheetPart.Worksheet.SheetProperties.OutlineProperties == null) + worksheetPart.Worksheet.SheetProperties.OutlineProperties = new OutlineProperties(); + + worksheetPart.Worksheet.SheetProperties.OutlineProperties.SummaryBelow = + (xlWorksheet.Outline.SummaryVLocation == + XLOutlineSummaryVLocation.Bottom); + worksheetPart.Worksheet.SheetProperties.OutlineProperties.SummaryRight = + (xlWorksheet.Outline.SummaryHLocation == + XLOutlineSummaryHLocation.Right); + + if (worksheetPart.Worksheet.SheetProperties.PageSetupProperties == null + && (xlWorksheet.PageSetup.PagesTall > 0 || xlWorksheet.PageSetup.PagesWide > 0)) + worksheetPart.Worksheet.SheetProperties.PageSetupProperties = new PageSetupProperties { FitToPage = true }; + + #endregion SheetProperties + + var maxColumn = 0; + + var sheetDimensionReference = "A1"; + if (xlWorksheet.Internals.CellsCollection.Count > 0) + { + maxColumn = xlWorksheet.Internals.CellsCollection.MaxColumnUsed; + var maxRow = xlWorksheet.Internals.CellsCollection.MaxRowUsed; + sheetDimensionReference = "A1:" + XLHelper.GetColumnLetterFromNumber(maxColumn) + + maxRow.ToInvariantString(); + } + + if (xlWorksheet.Internals.ColumnsCollection.Count > 0) + { + var maxColCollection = xlWorksheet.Internals.ColumnsCollection.Keys.Max(); + if (maxColCollection > maxColumn) + maxColumn = maxColCollection; + } + + #region SheetViews + + if (worksheetPart.Worksheet.SheetDimension == null) + worksheetPart.Worksheet.SheetDimension = new SheetDimension { Reference = sheetDimensionReference }; + + cm.SetElement(XLWSContentManager.XLWSContents.SheetDimension, worksheetPart.Worksheet.SheetDimension); + + if (worksheetPart.Worksheet.SheetViews == null) + worksheetPart.Worksheet.SheetViews = new SheetViews(); + + cm.SetElement(XLWSContentManager.XLWSContents.SheetViews, worksheetPart.Worksheet.SheetViews); + + var sheetView = (SheetView)worksheetPart.Worksheet.SheetViews.FirstOrDefault(); + if (sheetView == null) + { + sheetView = new SheetView { WorkbookViewId = 0U }; + worksheetPart.Worksheet.SheetViews.AppendChild(sheetView); + } + + if (xlWorksheet.TabSelected) + sheetView.TabSelected = true; + else + sheetView.TabSelected = null; + + if (xlWorksheet.RightToLeft) + sheetView.RightToLeft = true; + else + sheetView.RightToLeft = null; + + if (xlWorksheet.ShowFormulas) + sheetView.ShowFormulas = true; + else + sheetView.ShowFormulas = null; + + if (xlWorksheet.ShowGridLines) + sheetView.ShowGridLines = null; + else + sheetView.ShowGridLines = false; + + if (xlWorksheet.ShowOutlineSymbols) + sheetView.ShowOutlineSymbols = null; + else + sheetView.ShowOutlineSymbols = false; + + if (xlWorksheet.ShowRowColHeaders) + sheetView.ShowRowColHeaders = null; + else + sheetView.ShowRowColHeaders = false; + + if (xlWorksheet.ShowRuler) + sheetView.ShowRuler = null; + else + sheetView.ShowRuler = false; + + if (xlWorksheet.ShowWhiteSpace) + sheetView.ShowWhiteSpace = null; + else + sheetView.ShowWhiteSpace = false; + + if (xlWorksheet.ShowZeros) + sheetView.ShowZeros = null; + else + sheetView.ShowZeros = false; + + if (xlWorksheet.RightToLeft) + sheetView.RightToLeft = true; + else + sheetView.RightToLeft = null; + + if (xlWorksheet.SheetView.View == XLSheetViewOptions.Normal) + sheetView.View = null; + else + sheetView.View = xlWorksheet.SheetView.View.ToOpenXml(); + + var pane = sheetView.Elements().FirstOrDefault(); + if (pane == null) + { + pane = new Pane(); + sheetView.AppendChild(pane); + } + + pane.State = PaneStateValues.FrozenSplit; + Double hSplit = xlWorksheet.SheetView.SplitColumn; + Double ySplit = xlWorksheet.SheetView.SplitRow; + + pane.HorizontalSplit = hSplit; + pane.VerticalSplit = ySplit; + + pane.TopLeftCell = XLHelper.GetColumnLetterFromNumber(xlWorksheet.SheetView.SplitColumn + 1) + + (xlWorksheet.SheetView.SplitRow + 1); + + if (hSplit == 0 && ySplit == 0) + sheetView.RemoveAllChildren(); + + if (xlWorksheet.SelectedRanges.Any() || xlWorksheet.ActiveCell != null) + { + sheetView.RemoveAllChildren(); + + var firstSelection = xlWorksheet.SelectedRanges.FirstOrDefault(); + var selection = new Selection(); + if (xlWorksheet.ActiveCell != null) + selection.ActiveCell = xlWorksheet.ActiveCell.Address.ToStringRelative(false); + else if (firstSelection != null) + selection.ActiveCell = firstSelection.RangeAddress.FirstAddress.ToStringRelative(false); + + var seqRef = new List { selection.ActiveCell.Value }; + seqRef.AddRange(xlWorksheet.SelectedRanges + .Select(range => range.RangeAddress.ToStringRelative(false))); + + selection.SequenceOfReferences = new ListValue { InnerText = String.Join(" ", seqRef.Distinct().ToArray()) }; + + sheetView.Append(selection); + } + + if (xlWorksheet.SheetView.ZoomScale == 100) + sheetView.ZoomScale = null; + else + sheetView.ZoomScale = (UInt32)Math.Max(10, Math.Min(400, xlWorksheet.SheetView.ZoomScale)); + + if (xlWorksheet.SheetView.ZoomScaleNormal == 100) + sheetView.ZoomScaleNormal = null; + else + sheetView.ZoomScaleNormal = (UInt32)Math.Max(10, Math.Min(400, xlWorksheet.SheetView.ZoomScaleNormal)); + + if (xlWorksheet.SheetView.ZoomScalePageLayoutView == 100) + sheetView.ZoomScalePageLayoutView = null; + else + sheetView.ZoomScalePageLayoutView = (UInt32)Math.Max(10, Math.Min(400, xlWorksheet.SheetView.ZoomScalePageLayoutView)); + + if (xlWorksheet.SheetView.ZoomScaleSheetLayoutView == 100) + sheetView.ZoomScaleSheetLayoutView = null; + else + sheetView.ZoomScaleSheetLayoutView = (UInt32)Math.Max(10, Math.Min(400, xlWorksheet.SheetView.ZoomScaleSheetLayoutView)); + + #endregion SheetViews + + var maxOutlineColumn = 0; + if (xlWorksheet.ColumnCount() > 0) + maxOutlineColumn = xlWorksheet.GetMaxColumnOutline(); + + var maxOutlineRow = 0; + if (xlWorksheet.RowCount() > 0) + maxOutlineRow = xlWorksheet.GetMaxRowOutline(); + + #region SheetFormatProperties + + if (worksheetPart.Worksheet.SheetFormatProperties == null) + worksheetPart.Worksheet.SheetFormatProperties = new SheetFormatProperties(); + + cm.SetElement(XLWSContentManager.XLWSContents.SheetFormatProperties, + worksheetPart.Worksheet.SheetFormatProperties); + + worksheetPart.Worksheet.SheetFormatProperties.DefaultRowHeight = xlWorksheet.RowHeight.SaveRound(); + + if (xlWorksheet.RowHeightChanged) + worksheetPart.Worksheet.SheetFormatProperties.CustomHeight = true; + else + worksheetPart.Worksheet.SheetFormatProperties.CustomHeight = null; + + var worksheetColumnWidth = GetColumnWidth(xlWorksheet.ColumnWidth).SaveRound(); + if (xlWorksheet.ColumnWidthChanged) + worksheetPart.Worksheet.SheetFormatProperties.DefaultColumnWidth = worksheetColumnWidth; + else + worksheetPart.Worksheet.SheetFormatProperties.DefaultColumnWidth = null; + + if (maxOutlineColumn > 0) + worksheetPart.Worksheet.SheetFormatProperties.OutlineLevelColumn = (byte)maxOutlineColumn; + else + worksheetPart.Worksheet.SheetFormatProperties.OutlineLevelColumn = null; + + if (maxOutlineRow > 0) + worksheetPart.Worksheet.SheetFormatProperties.OutlineLevelRow = (byte)maxOutlineRow; + else + worksheetPart.Worksheet.SheetFormatProperties.OutlineLevelRow = null; + + #endregion SheetFormatProperties + + #region Columns + + if (xlWorksheet.Internals.CellsCollection.Count == 0 && + xlWorksheet.Internals.ColumnsCollection.Count == 0 + && xlWorksheet.Style.Equals(DefaultStyle)) + worksheetPart.Worksheet.RemoveAllChildren(); + else + { + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.Columns); + worksheetPart.Worksheet.InsertAfter(new Columns(), previousElement); + } + + var columns = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.Columns, columns); + + var sheetColumnsByMin = columns.Elements().ToDictionary(c => c.Min.Value, c => c); + //Dictionary sheetColumnsByMax = columns.Elements().ToDictionary(c => c.Max.Value, c => c); + + Int32 minInColumnsCollection; + Int32 maxInColumnsCollection; + if (xlWorksheet.Internals.ColumnsCollection.Count > 0) + { + minInColumnsCollection = xlWorksheet.Internals.ColumnsCollection.Keys.Min(); + maxInColumnsCollection = xlWorksheet.Internals.ColumnsCollection.Keys.Max(); + } + else + { + minInColumnsCollection = 1; + maxInColumnsCollection = 0; + } + + var worksheetStyleId = context.SharedStyles[xlWorksheet.GetStyleId()].StyleId; + if (minInColumnsCollection > 1) + { + UInt32Value min = 1; + UInt32Value max = (UInt32)(minInColumnsCollection - 1); + + for (var co = min; co <= max; co++) + { + var column = new Column + { + Min = co, + Max = co, + Style = worksheetStyleId, + Width = worksheetColumnWidth, + CustomWidth = true + }; + + UpdateColumn(column, columns, sheetColumnsByMin); //, sheetColumnsByMax); + } + } + + for (var co = minInColumnsCollection; co <= maxInColumnsCollection; co++) + { + UInt32 styleId; + Double columnWidth; + var isHidden = false; + var collapsed = false; + var outlineLevel = 0; + if (xlWorksheet.Internals.ColumnsCollection.ContainsKey(co)) + { + styleId = context.SharedStyles[xlWorksheet.Internals.ColumnsCollection[co].GetStyleId()].StyleId; + columnWidth = GetColumnWidth(xlWorksheet.Internals.ColumnsCollection[co].Width).SaveRound(); + isHidden = xlWorksheet.Internals.ColumnsCollection[co].IsHidden; + collapsed = xlWorksheet.Internals.ColumnsCollection[co].Collapsed; + outlineLevel = xlWorksheet.Internals.ColumnsCollection[co].OutlineLevel; + } + else + { + styleId = context.SharedStyles[xlWorksheet.GetStyleId()].StyleId; + columnWidth = worksheetColumnWidth; + } + + var column = new Column + { + Min = (UInt32)co, + Max = (UInt32)co, + Style = styleId, + Width = columnWidth, + CustomWidth = true + }; + + if (isHidden) + column.Hidden = true; + if (collapsed) + column.Collapsed = true; + if (outlineLevel > 0) + column.OutlineLevel = (byte)outlineLevel; + + UpdateColumn(column, columns, sheetColumnsByMin); //, sheetColumnsByMax); + } + + var collection = maxInColumnsCollection; + foreach ( + var col in + columns.Elements().Where(c => c.Min > (UInt32)(collection)).OrderBy( + c => c.Min.Value)) + { + col.Style = worksheetStyleId; + col.Width = worksheetColumnWidth; + col.CustomWidth = true; + + if ((Int32)col.Max.Value > maxInColumnsCollection) + maxInColumnsCollection = (Int32)col.Max.Value; + } + + if (maxInColumnsCollection < XLHelper.MaxColumnNumber && !xlWorksheet.Style.Equals(DefaultStyle)) + { + var column = new Column + { + Min = (UInt32)(maxInColumnsCollection + 1), + Max = (UInt32)(XLHelper.MaxColumnNumber), + Style = worksheetStyleId, + Width = worksheetColumnWidth, + CustomWidth = true + }; + columns.AppendChild(column); + } + + CollapseColumns(columns, sheetColumnsByMin); + + if (!columns.Any()) + { + worksheetPart.Worksheet.RemoveAllChildren(); + cm.SetElement(XLWSContentManager.XLWSContents.Columns, null); + } + } + + #endregion Columns + + #region SheetData + + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.SheetData); + worksheetPart.Worksheet.InsertAfter(new SheetData(), previousElement); + } + + var sheetData = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.SheetData, sheetData); + + var lastRow = 0; + var sheetDataRows = + sheetData.Elements().ToDictionary(r => r.RowIndex == null ? ++lastRow : (Int32)r.RowIndex.Value, + r => r); + foreach ( + var r in + xlWorksheet.Internals.RowsCollection.Deleted.Where(r => sheetDataRows.ContainsKey(r.Key))) + { + sheetData.RemoveChild(sheetDataRows[r.Key]); + sheetDataRows.Remove(r.Key); + xlWorksheet.Internals.CellsCollection.deleted.Remove(r.Key); + } + + var distinctRows = xlWorksheet.Internals.CellsCollection.RowsCollection.Keys.Union(xlWorksheet.Internals.RowsCollection.Keys); + var noRows = !sheetData.Elements().Any(); + foreach (var distinctRow in distinctRows.OrderBy(r => r)) + { + Row row; + if (sheetDataRows.ContainsKey(distinctRow)) + row = sheetDataRows[distinctRow]; + else + { + row = new Row { RowIndex = (UInt32)distinctRow }; + if (noRows) + { + sheetData.AppendChild(row); + noRows = false; + } + else + { + if (sheetDataRows.Any(r => r.Key > row.RowIndex.Value)) + { + var minRow = sheetDataRows.Where(r => r.Key > (Int32)row.RowIndex.Value).Min(r => r.Key); + var rowBeforeInsert = sheetDataRows[minRow]; + sheetData.InsertBefore(row, rowBeforeInsert); + } + else + sheetData.AppendChild(row); + } + } + + if (maxColumn > 0) + row.Spans = new ListValue { InnerText = "1:" + maxColumn.ToInvariantString() }; + + row.Height = null; + row.CustomHeight = null; + row.Hidden = null; + row.StyleIndex = null; + row.CustomFormat = null; + row.Collapsed = null; + if (xlWorksheet.Internals.RowsCollection.ContainsKey(distinctRow)) + { + var thisRow = xlWorksheet.Internals.RowsCollection[distinctRow]; + if (thisRow.HeightChanged) + { + row.Height = thisRow.Height.SaveRound(); + row.CustomHeight = true; + row.CustomFormat = true; + } + + if (thisRow.GetStyleId() != xlWorksheet.GetStyleId()) + { + row.StyleIndex = context.SharedStyles[thisRow.GetStyleId()].StyleId; + row.CustomFormat = true; + } + + if (thisRow.IsHidden) + row.Hidden = true; + if (thisRow.Collapsed) + row.Collapsed = true; + if (thisRow.OutlineLevel > 0) + row.OutlineLevel = (byte)thisRow.OutlineLevel; + } + + var lastCell = 0; + var cellsByReference = row.Elements().ToDictionary(c => c.CellReference == null + ? XLHelper.GetColumnLetterFromNumber( + ++lastCell) + distinctRow + : c.CellReference.Value, c => c); + + foreach (var kpDel in xlWorksheet.Internals.CellsCollection.deleted.ToList()) + { + foreach (var delCo in kpDel.Value.ToList()) + { + var key = XLHelper.GetColumnLetterFromNumber(delCo) + kpDel.Key.ToInvariantString(); + if (!cellsByReference.ContainsKey(key)) continue; + row.RemoveChild(cellsByReference[key]); + kpDel.Value.Remove(delCo); + } + if (kpDel.Value.Count == 0) + xlWorksheet.Internals.CellsCollection.deleted.Remove(kpDel.Key); + } + + if (!xlWorksheet.Internals.CellsCollection.RowsCollection.ContainsKey(distinctRow)) continue; + + var isNewRow = !row.Elements().Any(); + lastCell = 0; + var mRows = row.Elements().ToDictionary(c => XLHelper.GetColumnNumberFromAddress(c.CellReference == null + ? (XLHelper.GetColumnLetterFromNumber(++lastCell) + distinctRow) : c.CellReference.Value), c => c); + foreach (var xlCell in xlWorksheet.Internals.CellsCollection.RowsCollection[distinctRow].Values + .OrderBy(c => c.Address.ColumnNumber) + .Select(c => c)) + { + var styleId = context.SharedStyles[xlCell.GetStyleId()].StyleId; + var cellReference = (xlCell.Address).GetTrimmedAddress(); + var isEmpty = xlCell.IsEmpty(true); + + Cell cell = null; + if (cellsByReference.ContainsKey(cellReference)) + { + cell = cellsByReference[cellReference]; + if (isEmpty) + { + cell.Remove(); + } + } + + if (!isEmpty) + { + if (cell == null) + { + cell = new Cell(); + cell.CellReference = new StringValue(cellReference); + + if (isNewRow) + row.AppendChild(cell); + else + { + var newColumn = XLHelper.GetColumnNumberFromAddress(cellReference); + + Cell cellBeforeInsert = null; + int[] lastCo = { Int32.MaxValue }; + foreach (var c in mRows.Where(kp => kp.Key > newColumn).Where(c => lastCo[0] > c.Key)) + { + cellBeforeInsert = c.Value; + lastCo[0] = c.Key; + } + if (cellBeforeInsert == null) + row.AppendChild(cell); + else + row.InsertBefore(cell, cellBeforeInsert); + } + } + + cell.StyleIndex = styleId; + var formula = xlCell.FormulaA1; + if (xlCell.HasFormula) + { + if (formula.StartsWith("{")) + { + formula = formula.Substring(1, formula.Length - 2); + var f = new CellFormula { FormulaType = CellFormulaValues.Array }; + + if (xlCell.FormulaReference == null) + xlCell.FormulaReference = xlCell.AsRange().RangeAddress; + if (xlCell.FormulaReference.FirstAddress.Equals(xlCell.Address)) + { + f.Text = formula; + f.Reference = xlCell.FormulaReference.ToStringRelative(); + } + + cell.CellFormula = f; + } + else + { + cell.CellFormula = new CellFormula(); + cell.CellFormula.Text = formula; + } + + cell.CellValue = null; + } + else + { + cell.CellFormula = null; + cell.DataType = xlCell.DataType == XLCellValues.DateTime ? null : GetCellValueType(xlCell); + } + + if (!xlCell.HasFormula || evaluateFormulae) + SetCellValue(xlCell, cell); + + } + } + xlWorksheet.Internals.CellsCollection.deleted.Remove(distinctRow); + } + foreach ( + var r in + xlWorksheet.Internals.CellsCollection.deleted.Keys.Where( + sheetDataRows.ContainsKey)) + { + sheetData.RemoveChild(sheetDataRows[r]); + sheetDataRows.Remove(r); + } + + #endregion SheetData + + #region SheetProtection + + if (xlWorksheet.Protection.Protected) + { + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.SheetProtection); + worksheetPart.Worksheet.InsertAfter(new SheetProtection(), previousElement); + } + + var sheetProtection = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.SheetProtection, sheetProtection); + + var protection = xlWorksheet.Protection; + sheetProtection.Sheet = protection.Protected; + if (!XLHelper.IsNullOrWhiteSpace(protection.PasswordHash)) + sheetProtection.Password = protection.PasswordHash; + sheetProtection.FormatCells = GetBooleanValue(!protection.FormatCells, true); + sheetProtection.FormatColumns = GetBooleanValue(!protection.FormatColumns, true); + sheetProtection.FormatRows = GetBooleanValue(!protection.FormatRows, true); + sheetProtection.InsertColumns = GetBooleanValue(!protection.InsertColumns, true); + sheetProtection.InsertHyperlinks = GetBooleanValue(!protection.InsertHyperlinks, true); + sheetProtection.InsertRows = GetBooleanValue(!protection.InsertRows, true); + sheetProtection.DeleteColumns = GetBooleanValue(!protection.DeleteColumns, true); + sheetProtection.DeleteRows = GetBooleanValue(!protection.DeleteRows, true); + sheetProtection.AutoFilter = GetBooleanValue(!protection.AutoFilter, true); + sheetProtection.PivotTables = GetBooleanValue(!protection.PivotTables, true); + sheetProtection.Sort = GetBooleanValue(!protection.Sort, true); + sheetProtection.SelectLockedCells = GetBooleanValue(!protection.SelectLockedCells, false); + sheetProtection.SelectUnlockedCells = GetBooleanValue(!protection.SelectUnlockedCells, false); + } + else + { + worksheetPart.Worksheet.RemoveAllChildren(); + cm.SetElement(XLWSContentManager.XLWSContents.SheetProtection, null); + } + + #endregion SheetProtection + + #region AutoFilter + + worksheetPart.Worksheet.RemoveAllChildren(); + if (xlWorksheet.AutoFilter.Enabled) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.AutoFilter); + worksheetPart.Worksheet.InsertAfter(new AutoFilter(), previousElement); + + var autoFilter = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.AutoFilter, autoFilter); + + PopulateAutoFilter(xlWorksheet.AutoFilter, autoFilter); + } + else + { + cm.SetElement(XLWSContentManager.XLWSContents.AutoFilter, null); + } + + #endregion AutoFilter + + #region MergeCells + + if ((xlWorksheet).Internals.MergedRanges.Any()) + { + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.MergeCells); + worksheetPart.Worksheet.InsertAfter(new MergeCells(), previousElement); + } + + var mergeCells = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.MergeCells, mergeCells); + mergeCells.RemoveAllChildren(); + + foreach (var mergeCell in (xlWorksheet).Internals.MergedRanges.Select( + m => m.RangeAddress.FirstAddress.ToString() + ":" + m.RangeAddress.LastAddress.ToString()).Select( + merged => new MergeCell { Reference = merged })) + mergeCells.AppendChild(mergeCell); + + mergeCells.Count = (UInt32)mergeCells.Count(); + } + else + { + worksheetPart.Worksheet.RemoveAllChildren(); + cm.SetElement(XLWSContentManager.XLWSContents.MergeCells, null); + } + + #endregion MergeCells + + #region Conditional Formatting + + if (!xlWorksheet.ConditionalFormats.Any()) + { + worksheetPart.Worksheet.RemoveAllChildren(); + cm.SetElement(XLWSContentManager.XLWSContents.ConditionalFormatting, null); + } + else + { + worksheetPart.Worksheet.RemoveAllChildren(); + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.ConditionalFormatting); + + var priority = 1; // priority is 1 origin in Microsoft Excel + foreach (var cfGroup in xlWorksheet.ConditionalFormats + .GroupBy( + c => c.Range.RangeAddress.ToStringRelative(false), + c => c, + (key, g) => new { RangeId = key, CfList = g.ToList() } + ) + ) + { + var conditionalFormatting = new ConditionalFormatting + { + SequenceOfReferences = + new ListValue { InnerText = cfGroup.RangeId } + }; + foreach (var cf in cfGroup.CfList) + { + conditionalFormatting.Append(XLCFConverters.Convert(cf, priority, context)); + priority++; + } + worksheetPart.Worksheet.InsertAfter(conditionalFormatting, previousElement); + previousElement = conditionalFormatting; + cm.SetElement(XLWSContentManager.XLWSContents.ConditionalFormatting, conditionalFormatting); + } + } + + #endregion Conditional Formatting + + #region DataValidations + + if (!xlWorksheet.DataValidations.Any(d => d.IsDirty())) + { + worksheetPart.Worksheet.RemoveAllChildren(); + cm.SetElement(XLWSContentManager.XLWSContents.DataValidations, null); + } + else + { + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.DataValidations); + worksheetPart.Worksheet.InsertAfter(new DataValidations(), previousElement); + } + + var dataValidations = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.DataValidations, dataValidations); + dataValidations.RemoveAllChildren(); + foreach (var dv in xlWorksheet.DataValidations) + { + var sequence = dv.Ranges.Aggregate(String.Empty, (current, r) => current + (r.RangeAddress + " ")); + + if (sequence.Length > 0) + sequence = sequence.Substring(0, sequence.Length - 1); + + var dataValidation = new DataValidation + { + AllowBlank = dv.IgnoreBlanks, + Formula1 = new Formula1(dv.MinValue), + Formula2 = new Formula2(dv.MaxValue), + Type = dv.AllowedValues.ToOpenXml(), + ShowErrorMessage = dv.ShowErrorMessage, + Prompt = dv.InputMessage, + PromptTitle = dv.InputTitle, + ErrorTitle = dv.ErrorTitle, + Error = dv.ErrorMessage, + ShowDropDown = !dv.InCellDropdown, + ShowInputMessage = dv.ShowInputMessage, + ErrorStyle = dv.ErrorStyle.ToOpenXml(), + Operator = dv.Operator.ToOpenXml(), + SequenceOfReferences = + new ListValue { InnerText = sequence } + }; + + dataValidations.AppendChild(dataValidation); + } + dataValidations.Count = (UInt32)xlWorksheet.DataValidations.Count(); + } + + #endregion DataValidations + + #region Hyperlinks + + var relToRemove = worksheetPart.HyperlinkRelationships.ToList(); + relToRemove.ForEach(worksheetPart.DeleteReferenceRelationship); + if (!xlWorksheet.Hyperlinks.Any()) + { + worksheetPart.Worksheet.RemoveAllChildren(); + cm.SetElement(XLWSContentManager.XLWSContents.Hyperlinks, null); + } + else + { + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.Hyperlinks); + worksheetPart.Worksheet.InsertAfter(new Hyperlinks(), previousElement); + } + + var hyperlinks = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.Hyperlinks, hyperlinks); + hyperlinks.RemoveAllChildren(); + foreach (var hl in xlWorksheet.Hyperlinks) + { + Hyperlink hyperlink; + if (hl.IsExternal) + { + var rId = context.RelIdGenerator.GetNext(RelType.Workbook); + hyperlink = new Hyperlink { Reference = hl.Cell.Address.ToString(), Id = rId }; + worksheetPart.AddHyperlinkRelationship(hl.ExternalAddress, true, rId); + } + else + { + hyperlink = new Hyperlink + { + Reference = hl.Cell.Address.ToString(), + Location = hl.InternalAddress, + Display = hl.Cell.GetFormattedString() + }; + } + if (!XLHelper.IsNullOrWhiteSpace(hl.Tooltip)) + hyperlink.Tooltip = hl.Tooltip; + hyperlinks.AppendChild(hyperlink); + } + } + + #endregion Hyperlinks + + #region PrintOptions + + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.PrintOptions); + worksheetPart.Worksheet.InsertAfter(new PrintOptions(), previousElement); + } + + var printOptions = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.PrintOptions, printOptions); + + printOptions.HorizontalCentered = xlWorksheet.PageSetup.CenterHorizontally; + printOptions.VerticalCentered = xlWorksheet.PageSetup.CenterVertically; + printOptions.Headings = xlWorksheet.PageSetup.ShowRowAndColumnHeadings; + printOptions.GridLines = xlWorksheet.PageSetup.ShowGridlines; + + #endregion PrintOptions + + #region PageMargins + + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.PageMargins); + worksheetPart.Worksheet.InsertAfter(new PageMargins(), previousElement); + } + + var pageMargins = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.PageMargins, pageMargins); + pageMargins.Left = xlWorksheet.PageSetup.Margins.Left; + pageMargins.Right = xlWorksheet.PageSetup.Margins.Right; + pageMargins.Top = xlWorksheet.PageSetup.Margins.Top; + pageMargins.Bottom = xlWorksheet.PageSetup.Margins.Bottom; + pageMargins.Header = xlWorksheet.PageSetup.Margins.Header; + pageMargins.Footer = xlWorksheet.PageSetup.Margins.Footer; + + #endregion PageMargins + + #region PageSetup + + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.PageSetup); + worksheetPart.Worksheet.InsertAfter(new PageSetup(), previousElement); + } + + var pageSetup = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.PageSetup, pageSetup); + + pageSetup.Orientation = xlWorksheet.PageSetup.PageOrientation.ToOpenXml(); + pageSetup.PaperSize = (UInt32)xlWorksheet.PageSetup.PaperSize; + pageSetup.BlackAndWhite = xlWorksheet.PageSetup.BlackAndWhite; + pageSetup.Draft = xlWorksheet.PageSetup.DraftQuality; + pageSetup.PageOrder = xlWorksheet.PageSetup.PageOrder.ToOpenXml(); + pageSetup.CellComments = xlWorksheet.PageSetup.ShowComments.ToOpenXml(); + pageSetup.Errors = xlWorksheet.PageSetup.PrintErrorValue.ToOpenXml(); + + if (xlWorksheet.PageSetup.FirstPageNumber > 0) + { + pageSetup.FirstPageNumber = (UInt32)xlWorksheet.PageSetup.FirstPageNumber; + pageSetup.UseFirstPageNumber = true; + } + else + { + pageSetup.FirstPageNumber = null; + pageSetup.UseFirstPageNumber = null; + } + + if (xlWorksheet.PageSetup.HorizontalDpi > 0) + pageSetup.HorizontalDpi = (UInt32)xlWorksheet.PageSetup.HorizontalDpi; + else + pageSetup.HorizontalDpi = null; + + if (xlWorksheet.PageSetup.VerticalDpi > 0) + pageSetup.VerticalDpi = (UInt32)xlWorksheet.PageSetup.VerticalDpi; + else + pageSetup.VerticalDpi = null; + + if (xlWorksheet.PageSetup.Scale > 0) + { + pageSetup.Scale = (UInt32)xlWorksheet.PageSetup.Scale; + pageSetup.FitToWidth = null; + pageSetup.FitToHeight = null; + } + else + { + pageSetup.Scale = null; + + if (xlWorksheet.PageSetup.PagesWide >= 0 && xlWorksheet.PageSetup.PagesWide != 1) + pageSetup.FitToWidth = (UInt32)xlWorksheet.PageSetup.PagesWide; + + if (xlWorksheet.PageSetup.PagesTall >= 0 && xlWorksheet.PageSetup.PagesTall != 1) + pageSetup.FitToHeight = (UInt32)xlWorksheet.PageSetup.PagesTall; + } + + #endregion PageSetup + + #region HeaderFooter + + var headerFooter = worksheetPart.Worksheet.Elements().FirstOrDefault(); + if (headerFooter == null) + headerFooter = new HeaderFooter(); + else + worksheetPart.Worksheet.RemoveAllChildren(); + + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.HeaderFooter); + worksheetPart.Worksheet.InsertAfter(headerFooter, previousElement); + cm.SetElement(XLWSContentManager.XLWSContents.HeaderFooter, headerFooter); + } + if (((XLHeaderFooter)xlWorksheet.PageSetup.Header).Changed + || ((XLHeaderFooter)xlWorksheet.PageSetup.Footer).Changed) + { + //var headerFooter = worksheetPart.Worksheet.Elements().First(); + + headerFooter.RemoveAllChildren(); + + headerFooter.ScaleWithDoc = xlWorksheet.PageSetup.ScaleHFWithDocument; + headerFooter.AlignWithMargins = xlWorksheet.PageSetup.AlignHFWithMargins; + headerFooter.DifferentFirst = xlWorksheet.PageSetup.DifferentFirstPageOnHF; + headerFooter.DifferentOddEven = xlWorksheet.PageSetup.DifferentOddEvenPagesOnHF; + + var oddHeader = new OddHeader(xlWorksheet.PageSetup.Header.GetText(XLHFOccurrence.OddPages)); + headerFooter.AppendChild(oddHeader); + var oddFooter = new OddFooter(xlWorksheet.PageSetup.Footer.GetText(XLHFOccurrence.OddPages)); + headerFooter.AppendChild(oddFooter); + + var evenHeader = new EvenHeader(xlWorksheet.PageSetup.Header.GetText(XLHFOccurrence.EvenPages)); + headerFooter.AppendChild(evenHeader); + var evenFooter = new EvenFooter(xlWorksheet.PageSetup.Footer.GetText(XLHFOccurrence.EvenPages)); + headerFooter.AppendChild(evenFooter); + + var firstHeader = new FirstHeader(xlWorksheet.PageSetup.Header.GetText(XLHFOccurrence.FirstPage)); + headerFooter.AppendChild(firstHeader); + var firstFooter = new FirstFooter(xlWorksheet.PageSetup.Footer.GetText(XLHFOccurrence.FirstPage)); + headerFooter.AppendChild(firstFooter); + } + + #endregion HeaderFooter + + #region RowBreaks + + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.RowBreaks); + worksheetPart.Worksheet.InsertAfter(new RowBreaks(), previousElement); + } + + var rowBreaks = worksheetPart.Worksheet.Elements().First(); + + var rowBreakCount = xlWorksheet.PageSetup.RowBreaks.Count; + if (rowBreakCount > 0) + { + rowBreaks.Count = (UInt32)rowBreakCount; + rowBreaks.ManualBreakCount = (UInt32)rowBreakCount; + var lastRowNum = (UInt32)xlWorksheet.RangeAddress.LastAddress.RowNumber; + foreach (var break1 in xlWorksheet.PageSetup.RowBreaks.Select(rb => new Break + { + Id = (UInt32)rb, + Max = lastRowNum, + ManualPageBreak = true + })) + rowBreaks.AppendChild(break1); + cm.SetElement(XLWSContentManager.XLWSContents.RowBreaks, rowBreaks); + } + else + { + worksheetPart.Worksheet.RemoveAllChildren(); + cm.SetElement(XLWSContentManager.XLWSContents.RowBreaks, null); + } + + #endregion RowBreaks + + #region ColumnBreaks + + if (!worksheetPart.Worksheet.Elements().Any()) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.ColumnBreaks); + worksheetPart.Worksheet.InsertAfter(new ColumnBreaks(), previousElement); + } + + var columnBreaks = worksheetPart.Worksheet.Elements().First(); + + var columnBreakCount = xlWorksheet.PageSetup.ColumnBreaks.Count; + if (columnBreakCount > 0) + { + columnBreaks.Count = (UInt32)columnBreakCount; + columnBreaks.ManualBreakCount = (UInt32)columnBreakCount; + var maxColumnNumber = (UInt32)xlWorksheet.RangeAddress.LastAddress.ColumnNumber; + foreach (var break1 in xlWorksheet.PageSetup.ColumnBreaks.Select(cb => new Break + { + Id = (UInt32)cb, + Max = maxColumnNumber, + ManualPageBreak = true + })) + columnBreaks.AppendChild(break1); + cm.SetElement(XLWSContentManager.XLWSContents.ColumnBreaks, columnBreaks); + } + else + { + worksheetPart.Worksheet.RemoveAllChildren(); + cm.SetElement(XLWSContentManager.XLWSContents.ColumnBreaks, null); + } + + #endregion ColumnBreaks + + #region Tables + + worksheetPart.Worksheet.RemoveAllChildren(); + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.TableParts); + worksheetPart.Worksheet.InsertAfter(new TableParts(), previousElement); + } + + var tableParts = worksheetPart.Worksheet.Elements().First(); + cm.SetElement(XLWSContentManager.XLWSContents.TableParts, tableParts); + + tableParts.Count = (UInt32)xlWorksheet.Tables.Count(); + foreach ( + var tablePart in + from XLTable xlTable in xlWorksheet.Tables select new TablePart { Id = xlTable.RelId }) + tableParts.AppendChild(tablePart); + + #endregion Tables + + #region Drawings + + foreach (var pic in xlWorksheet.Pictures) + { + AddPictureAnchor(worksheetPart, pic, context); + } + + if (xlWorksheet.Pictures.Any()) + RebasePictureIds(worksheetPart); + + if (xlWorksheet.Pictures.Any() && !worksheetPart.Worksheet.OfType().Any()) + { + var worksheetDrawing = new Drawing { Id = worksheetPart.GetIdOfPart(worksheetPart.DrawingsPart) }; + worksheetDrawing.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + worksheetPart.Worksheet.InsertBefore(worksheetDrawing, tableParts); + } + + #endregion Drawings + + #region LegacyDrawing + + if (xlWorksheet.LegacyDrawingIsNew) + { + worksheetPart.Worksheet.RemoveAllChildren(); + { + if (!XLHelper.IsNullOrWhiteSpace(xlWorksheet.LegacyDrawingId)) + { + var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.LegacyDrawing); + worksheetPart.Worksheet.InsertAfter(new LegacyDrawing { Id = xlWorksheet.LegacyDrawingId }, + previousElement); + } + } + } + + #endregion LegacyDrawing + + #region LegacyDrawingHeaderFooter + + //LegacyDrawingHeaderFooter legacyHeaderFooter = worksheetPart.Worksheet.Elements().FirstOrDefault(); + //if (legacyHeaderFooter != null) + //{ + // worksheetPart.Worksheet.RemoveAllChildren(); + // { + // var previousElement = cm.GetPreviousElementFor(XLWSContentManager.XLWSContents.LegacyDrawingHeaderFooter); + // worksheetPart.Worksheet.InsertAfter(new LegacyDrawingHeaderFooter { Id = xlWorksheet.LegacyDrawingId }, + // previousElement); + // } + //} + + #endregion LegacyDrawingHeaderFooter + } + + private static void SetCellValue(XLCell xlCell, Cell openXmlCell) + { + if (xlCell.HasFormula) + { + var cellValue = new CellValue(); + try + { + cellValue.Text = xlCell.Value.ToString(); + openXmlCell.DataType = new EnumValue(CellValues.String); + } + catch + { + cellValue = null; + } + + openXmlCell.CellValue = cellValue; + return; + } + + var dataType = xlCell.DataType; + if (dataType == XLCellValues.Text) + { + if (xlCell.InnerText.Length == 0) + openXmlCell.CellValue = null; + else + { + if (xlCell.ShareString) + { + var cellValue = new CellValue(); + cellValue.Text = xlCell.SharedStringId.ToString(); + openXmlCell.CellValue = cellValue; + } + else + { + var text = xlCell.GetString(); + var t = new Text(text); + if (text.PreserveSpaces()) + t.Space = SpaceProcessingModeValues.Preserve; + + openXmlCell.InlineString = new InlineString { Text = t }; + } + } + } + else if (dataType == XLCellValues.TimeSpan) + { + var timeSpan = xlCell.GetTimeSpan(); + var cellValue = new CellValue(); + cellValue.Text = + XLCell.BaseDate.Add(timeSpan).ToOADate().ToInvariantString(); + openXmlCell.CellValue = cellValue; + } + else if (dataType == XLCellValues.DateTime || dataType == XLCellValues.Number) + { + if (!XLHelper.IsNullOrWhiteSpace(xlCell.InnerText)) + { + var cellValue = new CellValue(); + cellValue.Text = Double.Parse(xlCell.InnerText, XLHelper.NumberStyle, XLHelper.ParseCulture).ToInvariantString(); + openXmlCell.CellValue = cellValue; + } + } + else + { + var cellValue = new CellValue(); + cellValue.Text = xlCell.InnerText; + openXmlCell.CellValue = cellValue; + } + } + + private static void PopulateAutoFilter(XLAutoFilter xlAutoFilter, AutoFilter autoFilter) + { + var filterRange = xlAutoFilter.Range; + autoFilter.Reference = filterRange.RangeAddress.ToString(); + + foreach (var kp in xlAutoFilter.Filters) + { + var filterColumn = new FilterColumn { ColumnId = (UInt32)kp.Key - 1 }; + var xlFilterColumn = xlAutoFilter.Column(kp.Key); + var filterType = xlFilterColumn.FilterType; + if (filterType == XLFilterType.Custom) + { + var customFilters = new CustomFilters(); + foreach (var filter in kp.Value) + { + var customFilter = new CustomFilter { Val = filter.Value.ToString() }; + + if (filter.Operator != XLFilterOperator.Equal) + customFilter.Operator = filter.Operator.ToOpenXml(); + + if (filter.Connector == XLConnector.And) + customFilters.And = true; + + customFilters.Append(customFilter); + } + filterColumn.Append(customFilters); + } + else if (filterType == XLFilterType.TopBottom) + { + var top101 = new Top10 { Val = (double)xlFilterColumn.TopBottomValue }; + if (xlFilterColumn.TopBottomType == XLTopBottomType.Percent) + top101.Percent = true; + if (xlFilterColumn.TopBottomPart == XLTopBottomPart.Bottom) + top101.Top = false; + + filterColumn.Append(top101); + } + else if (filterType == XLFilterType.Dynamic) + { + var dynamicFilter = new DynamicFilter + { Type = xlFilterColumn.DynamicType.ToOpenXml(), Val = xlFilterColumn.DynamicValue }; + filterColumn.Append(dynamicFilter); + } + else + { + var filters = new Filters(); + foreach (var filter in kp.Value) + { + filters.Append(new Filter { Val = filter.Value.ToString() }); + } + + filterColumn.Append(filters); + } + autoFilter.Append(filterColumn); + } + + if (xlAutoFilter.Sorted) + { + var sortState = new SortState + { + Reference = + filterRange.Range(filterRange.FirstCell().CellBelow(), filterRange.LastCell()).RangeAddress. + ToString() + }; + var sortCondition = new SortCondition + { + Reference = + filterRange.Range(1, xlAutoFilter.SortColumn, filterRange.RowCount(), + xlAutoFilter.SortColumn).RangeAddress.ToString() + }; + if (xlAutoFilter.SortOrder == XLSortOrder.Descending) + sortCondition.Descending = true; + + sortState.Append(sortCondition); + autoFilter.Append(sortState); + } + } + + private static BooleanValue GetBooleanValue(bool value, bool defaultValue) + { + return value == defaultValue ? null : new BooleanValue(value); + } + + private static void CollapseColumns(Columns columns, Dictionary sheetColumns) + { + UInt32 lastMin = 1; + var count = sheetColumns.Count; + var arr = sheetColumns.OrderBy(kp => kp.Key).ToArray(); + // sheetColumns[kp.Key + 1] + //Int32 i = 0; + //foreach (KeyValuePair kp in arr + // //.Where(kp => !(kp.Key < count && ColumnsAreEqual(kp.Value, ))) + // ) + for (var i = 0; i < count; i++) + { + var kp = arr[i]; + if (i + 1 != count && ColumnsAreEqual(kp.Value, arr[i + 1].Value)) continue; + + var newColumn = (Column)kp.Value.CloneNode(true); + newColumn.Min = lastMin; + var newColumnMax = newColumn.Max.Value; + var columnsToRemove = + columns.Elements().Where(co => co.Min >= lastMin && co.Max <= newColumnMax). + Select(co => co).ToList(); + columnsToRemove.ForEach(c => columns.RemoveChild(c)); + + columns.AppendChild(newColumn); + lastMin = kp.Key + 1; + //i++; + } + } + + private static double GetColumnWidth(double columnWidth) + { + return Math.Min(255.0, Math.Max(0.0, columnWidth + ColumnWidthOffset)); + } + + private static void UpdateColumn(Column column, Columns columns, Dictionary sheetColumnsByMin) + { + var co = column.Min.Value; + Column newColumn; + if (!sheetColumnsByMin.ContainsKey(co)) + { + newColumn = (Column)column.CloneNode(true); + columns.AppendChild(newColumn); + sheetColumnsByMin.Add(co, newColumn); + } + else + { + var existingColumn = sheetColumnsByMin[column.Min.Value]; + newColumn = (Column)existingColumn.CloneNode(true); + newColumn.Min = column.Min; + newColumn.Max = column.Max; + newColumn.Style = column.Style; + newColumn.Width = column.Width.SaveRound(); + newColumn.CustomWidth = column.CustomWidth; + + if (column.Hidden != null) + newColumn.Hidden = true; + else + newColumn.Hidden = null; + + if (column.Collapsed != null) + newColumn.Collapsed = true; + else + newColumn.Collapsed = null; + + if (column.OutlineLevel != null && column.OutlineLevel > 0) + newColumn.OutlineLevel = (byte)column.OutlineLevel; + else + newColumn.OutlineLevel = null; + + sheetColumnsByMin.Remove(column.Min.Value); + if (existingColumn.Min + 1 > existingColumn.Max) + { + //existingColumn.Min = existingColumn.Min + 1; + //columns.InsertBefore(existingColumn, newColumn); + //existingColumn.Remove(); + columns.RemoveChild(existingColumn); + columns.AppendChild(newColumn); + sheetColumnsByMin.Add(newColumn.Min.Value, newColumn); + } + else + { + //columns.InsertBefore(existingColumn, newColumn); + columns.AppendChild(newColumn); + sheetColumnsByMin.Add(newColumn.Min.Value, newColumn); + existingColumn.Min = existingColumn.Min + 1; + sheetColumnsByMin.Add(existingColumn.Min.Value, existingColumn); + } + } + } + + private static bool ColumnsAreEqual(Column left, Column right) + { + return + ((left.Style == null && right.Style == null) + || (left.Style != null && right.Style != null && left.Style.Value == right.Style.Value)) + && ((left.Width == null && right.Width == null) + || (left.Width != null && right.Width != null && left.Width.Value == right.Width.Value)) + && ((left.Hidden == null && right.Hidden == null) + || (left.Hidden != null && right.Hidden != null && left.Hidden.Value == right.Hidden.Value)) + && ((left.Collapsed == null && right.Collapsed == null) + || + (left.Collapsed != null && right.Collapsed != null && left.Collapsed.Value == right.Collapsed.Value)) + && ((left.OutlineLevel == null && right.OutlineLevel == null) + || + (left.OutlineLevel != null && right.OutlineLevel != null && + left.OutlineLevel.Value == right.OutlineLevel.Value)); + } + + #endregion GenerateWorksheetPartContent + } } \ No newline at end of file diff --git a/ClosedXML_Tests/Examples/MiscTests.cs b/ClosedXML_Tests/Examples/MiscTests.cs index 910d717..4f14453 100644 --- a/ClosedXML_Tests/Examples/MiscTests.cs +++ b/ClosedXML_Tests/Examples/MiscTests.cs @@ -1,214 +1,214 @@ -using ClosedXML_Examples; -using ClosedXML_Examples.Misc; -using NUnit.Framework; - -namespace ClosedXML_Tests.Examples -{ - [TestFixture] - public class MiscTests - { - [Test] - public void AddingDataSet() - { - TestHelper.RunTestExample(@"Misc\AddingDataSet.xlsx"); - } - - [Test] - public void AddingDataTableAsWorksheet() - { - TestHelper.RunTestExample(@"Misc\AddingDataTableAsWorksheet.xlsx"); - } - - [Test] - public void AdjustToContents() - { - TestHelper.RunTestExample(@"Misc\AdjustToContents.xlsx"); - } - - [Test] - public void AdjustToContentsWithAutoFilter() - { - TestHelper.RunTestExample(@"Misc\AdjustToContentsWithAutoFilter.xlsx"); - } - - [Test] - public void AutoFilter() - { - TestHelper.RunTestExample(@"Misc\AutoFilter.xlsx"); - } - - [Test] - public void BasicTable() - { - TestHelper.RunTestExample(@"Misc\BasicTable.xlsx"); - } - - [Test] - public void BlankCells() - { - TestHelper.RunTestExample(@"Misc\BlankCells.xlsx"); - } - - [Test] - public void CellValues() - { - TestHelper.RunTestExample(@"Misc\CellValues.xlsx"); - } - - [Test] - public void Collections() - { - TestHelper.RunTestExample(@"Misc\Collections.xlsx"); - } - - [Test] - public void CopyingRowsAndColumns() - { - TestHelper.RunTestExample(@"Misc\CopyingRowsAndColumns.xlsx"); - } - - [Test] - public void CopyingWorksheets() - { - TestHelper.RunTestExample(@"Misc\CopyingWorksheets.xlsx"); - } - - [Test] - public void DataTypes() - { - TestHelper.RunTestExample(@"Misc\DataTypes.xlsx"); - } - - [Test] - public void DataTypesUnderDifferentCulture() - { - TestHelper.RunTestExample(@"Misc\DataTypesUnderDifferentCulture.xlsx"); - } - - [Test] - public void DataValidation() - { - TestHelper.RunTestExample(@"Misc\DataValidation.xlsx"); - } - - [Test] - public void Formulas() - { - TestHelper.RunTestExample(@"Misc\Formulas.xlsx"); - } - - [Test] - public void FormulasWithEvaluation() - { - TestHelper.RunTestExample(@"Misc\FormulasWithEvaluation.xlsx", true); - } - - [Test] - public void FreezePanes() - { - TestHelper.RunTestExample(@"Misc\FreezePanes.xlsx"); - } - - [Test] - public void HideSheets() - { - TestHelper.RunTestExample(@"Misc\HideSheets.xlsx"); - } - - [Test] - public void HideUnhide() - { - TestHelper.RunTestExample(@"Misc\HideUnhide.xlsx"); - } - - [Test] - public void Hyperlinks() - { - TestHelper.RunTestExample(@"Misc\Hyperlinks.xlsx"); - } - - [Test] - public void InsertingData() - { - TestHelper.RunTestExample(@"Misc\InsertingData.xlsx"); - } - - [Test] - public void InsertingTables() - { - TestHelper.RunTestExample(@"Misc\InsertingTables.xlsx"); - } - - [Test] - public void LambdaExpressions() - { - TestHelper.RunTestExample(@"Misc\LambdaExpressions.xlsx"); - } - - [Test] - public void MergeCells() - { - TestHelper.RunTestExample(@"Misc\MergeCells.xlsx"); - } - - [Test] - public void MergeMoves() - { - TestHelper.RunTestExample(@"Misc\MergeMoves.xlsx"); - } - - [Test] - public void Outline() - { - TestHelper.RunTestExample(@"Misc\Outline.xlsx"); - } - - [Test] - public void RightToLeft() - { - TestHelper.RunTestExample(@"Misc\RightToLeft.xlsx"); - } - - [Test] - public void SheetProtection() - { - TestHelper.RunTestExample(@"Misc\SheetProtection.xlsx"); - } - - [Test] - public void SheetViews() - { - TestHelper.RunTestExample(@"Misc\SheetViews.xlsx"); - } - - [Test] - public void ShiftingFormulas() - { - TestHelper.RunTestExample(@"Misc\ShiftingFormulas.xlsx"); - } - - [Test] - public void ShowCase() - { - TestHelper.RunTestExample(@"Misc\ShowCase.xlsx"); - } - - [Test] - public void TabColors() - { - TestHelper.RunTestExample(@"Misc\TabColors.xlsx"); - } - - [Test] - public void WorkbookProperties() - { - TestHelper.RunTestExample(@"Misc\WorkbookProperties.xlsx"); - } - - [Test] - public void WorkbookProtection() - { - TestHelper.RunTestExample(@"Misc\WorkbookProtection.xlsx"); - } - } +using ClosedXML_Examples; +using ClosedXML_Examples.Misc; +using NUnit.Framework; + +namespace ClosedXML_Tests.Examples +{ + [TestFixture] + public class MiscTests + { + [Test] + public void AddingDataSet() + { + TestHelper.RunTestExample(@"Misc\AddingDataSet.xlsx"); + } + + [Test] + public void AddingDataTableAsWorksheet() + { + TestHelper.RunTestExample(@"Misc\AddingDataTableAsWorksheet.xlsx"); + } + + [Test] + public void AdjustToContents() + { + TestHelper.RunTestExample(@"Misc\AdjustToContents.xlsx"); + } + + [Test] + public void AdjustToContentsWithAutoFilter() + { + TestHelper.RunTestExample(@"Misc\AdjustToContentsWithAutoFilter.xlsx"); + } + + [Test] + public void AutoFilter() + { + TestHelper.RunTestExample(@"Misc\AutoFilter.xlsx"); + } + + [Test] + public void BasicTable() + { + TestHelper.RunTestExample(@"Misc\BasicTable.xlsx"); + } + + [Test] + public void BlankCells() + { + TestHelper.RunTestExample(@"Misc\BlankCells.xlsx"); + } + + [Test] + public void CellValues() + { + TestHelper.RunTestExample(@"Misc\CellValues.xlsx"); + } + + [Test] + public void Collections() + { + TestHelper.RunTestExample(@"Misc\Collections.xlsx"); + } + + [Test] + public void CopyingRowsAndColumns() + { + TestHelper.RunTestExample(@"Misc\CopyingRowsAndColumns.xlsx"); + } + + [Test] + public void CopyingWorksheets() + { + TestHelper.RunTestExample(@"Misc\CopyingWorksheets.xlsx"); + } + + [Test] + public void DataTypes() + { + TestHelper.RunTestExample(@"Misc\DataTypes.xlsx"); + } + + [Test] + public void DataTypesUnderDifferentCulture() + { + TestHelper.RunTestExample(@"Misc\DataTypesUnderDifferentCulture.xlsx"); + } + + [Test] + public void DataValidation() + { + TestHelper.RunTestExample(@"Misc\DataValidation.xlsx"); + } + + [Test] + public void Formulas() + { + TestHelper.RunTestExample(@"Misc\Formulas.xlsx"); + } + + [Test] + public void FormulasWithEvaluation() + { + TestHelper.RunTestExample(@"Misc\FormulasWithEvaluation.xlsx", true); + } + + [Test] + public void FreezePanes() + { + TestHelper.RunTestExample(@"Misc\FreezePanes.xlsx"); + } + + [Test] + public void HideSheets() + { + TestHelper.RunTestExample(@"Misc\HideSheets.xlsx"); + } + + [Test] + public void HideUnhide() + { + TestHelper.RunTestExample(@"Misc\HideUnhide.xlsx"); + } + + [Test] + public void Hyperlinks() + { + TestHelper.RunTestExample(@"Misc\Hyperlinks.xlsx"); + } + + [Test] + public void InsertingData() + { + TestHelper.RunTestExample(@"Misc\InsertingData.xlsx"); + } + + [Test] + public void InsertingTables() + { + TestHelper.RunTestExample(@"Misc\InsertingTables.xlsx"); + } + + [Test] + public void LambdaExpressions() + { + TestHelper.RunTestExample(@"Misc\LambdaExpressions.xlsx"); + } + + [Test] + public void MergeCells() + { + TestHelper.RunTestExample(@"Misc\MergeCells.xlsx"); + } + + [Test] + public void MergeMoves() + { + TestHelper.RunTestExample(@"Misc\MergeMoves.xlsx"); + } + + [Test] + public void Outline() + { + TestHelper.RunTestExample(@"Misc\Outline.xlsx"); + } + + [Test] + public void RightToLeft() + { + TestHelper.RunTestExample(@"Misc\RightToLeft.xlsx"); + } + + [Test] + public void SheetProtection() + { + TestHelper.RunTestExample(@"Misc\SheetProtection.xlsx"); + } + + [Test] + public void SheetViews() + { + TestHelper.RunTestExample(@"Misc\SheetViews.xlsx"); + } + + [Test] + public void ShiftingFormulas() + { + TestHelper.RunTestExample(@"Misc\ShiftingFormulas.xlsx"); + } + + [Test] + public void ShowCase() + { + TestHelper.RunTestExample(@"Misc\ShowCase.xlsx"); + } + + [Test] + public void TabColors() + { + TestHelper.RunTestExample(@"Misc\TabColors.xlsx"); + } + + [Test] + public void WorkbookProperties() + { + TestHelper.RunTestExample(@"Misc\WorkbookProperties.xlsx"); + } + + [Test] + public void WorkbookProtection() + { + TestHelper.RunTestExample(@"Misc\WorkbookProtection.xlsx"); + } + } } \ No newline at end of file diff --git a/ClosedXML_Tests/Excel/Misc/XLWorkbookTests.cs b/ClosedXML_Tests/Excel/Misc/XLWorkbookTests.cs index 203201e..55afe19 100644 --- a/ClosedXML_Tests/Excel/Misc/XLWorkbookTests.cs +++ b/ClosedXML_Tests/Excel/Misc/XLWorkbookTests.cs @@ -1,328 +1,328 @@ -using System; -using System.Linq; -using ClosedXML.Excel; -using NUnit.Framework; - -namespace ClosedXML_Tests.Excel -{ - /// - /// Summary description for UnitTest1 - /// - [TestFixture] - public class XLWorkbookTests - { - [Test] - public void Cell1() - { - var wb = new XLWorkbook(); - IXLCell cell = wb.Cell("ABC"); - Assert.IsNull(cell); - } - - [Test] - public void Cell2() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - ws.FirstCell().SetValue(1).AddToNamed("Result", XLScope.Worksheet); - IXLCell cell = wb.Cell("Sheet1!Result"); - Assert.IsNotNull(cell); - Assert.AreEqual(1, cell.GetValue()); - } - - [Test] - public void Cell3() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - ws.FirstCell().SetValue(1).AddToNamed("Result"); - IXLCell cell = wb.Cell("Sheet1!Result"); - Assert.IsNotNull(cell); - Assert.AreEqual(1, cell.GetValue()); - } - - [Test] - public void Cells1() - { - var wb = new XLWorkbook(); - IXLCells cells = wb.Cells("ABC"); - Assert.IsNotNull(cells); - Assert.AreEqual(0, cells.Count()); - } - - [Test] - public void Cells2() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - ws.FirstCell().SetValue(1).AddToNamed("Result", XLScope.Worksheet); - IXLCells cells = wb.Cells("Sheet1!Result, ABC"); - Assert.IsNotNull(cells); - Assert.AreEqual(1, cells.Count()); - Assert.AreEqual(1, cells.First().GetValue()); - } - - [Test] - public void Cells3() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - ws.FirstCell().SetValue(1).AddToNamed("Result"); - IXLCells cells = wb.Cells("Sheet1!Result, ABC"); - Assert.IsNotNull(cells); - Assert.AreEqual(1, cells.Count()); - Assert.AreEqual(1, cells.First().GetValue()); - } - - [Test] - public void NamedRange1() - { - var wb = new XLWorkbook(); - IXLNamedRange range = wb.NamedRange("ABC"); - Assert.IsNull(range); - } - - [Test] - public void NamedRange2() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - ws.FirstCell().SetValue(1).AddToNamed("Result", XLScope.Worksheet); - IXLNamedRange range = wb.NamedRange("Sheet1!Result"); - Assert.IsNotNull(range); - Assert.AreEqual(1, range.Ranges.Count); - Assert.AreEqual(1, range.Ranges.Cells().Count()); - Assert.AreEqual(1, range.Ranges.First().FirstCell().GetValue()); - } - - [Test] - public void NamedRange3() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - IXLNamedRange range = wb.NamedRange("Sheet1!Result"); - Assert.IsNull(range); - } - - [Test] - public void NamedRange4() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - ws.FirstCell().SetValue(1).AddToNamed("Result"); - IXLNamedRange range = wb.NamedRange("Sheet1!Result"); - Assert.IsNotNull(range); - Assert.AreEqual(1, range.Ranges.Count); - Assert.AreEqual(1, range.Ranges.Cells().Count()); - Assert.AreEqual(1, range.Ranges.First().FirstCell().GetValue()); - } - - [Test] - public void Range1() - { - var wb = new XLWorkbook(); - IXLRange range = wb.Range("ABC"); - Assert.IsNull(range); - } - - [Test] - public void Range2() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - ws.FirstCell().SetValue(1).AddToNamed("Result", XLScope.Worksheet); - IXLRange range = wb.Range("Sheet1!Result"); - Assert.IsNotNull(range); - Assert.AreEqual(1, range.Cells().Count()); - Assert.AreEqual(1, range.FirstCell().GetValue()); - } - - [Test] - public void Range3() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - ws.FirstCell().SetValue(1).AddToNamed("Result"); - IXLRange range = wb.Range("Sheet1!Result"); - Assert.IsNotNull(range); - Assert.AreEqual(1, range.Cells().Count()); - Assert.AreEqual(1, range.FirstCell().GetValue()); - } - - [Test] - public void Ranges1() - { - var wb = new XLWorkbook(); - IXLRanges ranges = wb.Ranges("ABC"); - Assert.IsNotNull(ranges); - Assert.AreEqual(0, ranges.Count()); - } - - [Test] - public void Ranges2() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - ws.FirstCell().SetValue(1).AddToNamed("Result", XLScope.Worksheet); - IXLRanges ranges = wb.Ranges("Sheet1!Result, ABC"); - Assert.IsNotNull(ranges); - Assert.AreEqual(1, ranges.Cells().Count()); - Assert.AreEqual(1, ranges.First().FirstCell().GetValue()); - } - - [Test] - public void Ranges3() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.AddWorksheet("Sheet1"); - ws.FirstCell().SetValue(1).AddToNamed("Result"); - IXLRanges ranges = wb.Ranges("Sheet1!Result, ABC"); - Assert.IsNotNull(ranges); - Assert.AreEqual(1, ranges.Cells().Count()); - Assert.AreEqual(1, ranges.First().FirstCell().GetValue()); - } - - [Test] - public void WbNamedCell() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.Worksheets.Add("Sheet1"); - ws.Cell(1, 1).SetValue("Test").AddToNamed("TestCell"); - Assert.AreEqual("Test", wb.Cell("TestCell").GetString()); - Assert.AreEqual("Test", ws.Cell("TestCell").GetString()); - } - - [Test] - public void WbNamedCells() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.Worksheets.Add("Sheet1"); - ws.Cell(1, 1).SetValue("Test").AddToNamed("TestCell"); - ws.Cell(2, 1).SetValue("B").AddToNamed("Test2"); - IXLCells wbCells = wb.Cells("TestCell, Test2"); - Assert.AreEqual("Test", wbCells.First().GetString()); - Assert.AreEqual("B", wbCells.Last().GetString()); - - IXLCells wsCells = ws.Cells("TestCell, Test2"); - Assert.AreEqual("Test", wsCells.First().GetString()); - Assert.AreEqual("B", wsCells.Last().GetString()); - } - - [Test] - public void WbNamedRange() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.Worksheets.Add("Sheet1"); - ws.Cell(1, 1).SetValue("A"); - ws.Cell(2, 1).SetValue("B"); - IXLRange original = ws.Range("A1:A2"); - original.AddToNamed("TestRange"); - Assert.AreEqual(original.RangeAddress.ToStringFixed(), wb.Range("TestRange").RangeAddress.ToString()); - Assert.AreEqual(original.RangeAddress.ToStringFixed(), ws.Range("TestRange").RangeAddress.ToString()); - } - - [Test] - public void WbNamedRanges() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.Worksheets.Add("Sheet1"); - ws.Cell(1, 1).SetValue("A"); - ws.Cell(2, 1).SetValue("B"); - ws.Cell(3, 1).SetValue("C").AddToNamed("Test2"); - IXLRange original = ws.Range("A1:A2"); - original.AddToNamed("TestRange"); - IXLRanges wbRanges = wb.Ranges("TestRange, Test2"); - Assert.AreEqual(original.RangeAddress.ToStringFixed(), wbRanges.First().RangeAddress.ToString()); - Assert.AreEqual("$A$3:$A$3", wbRanges.Last().RangeAddress.ToStringFixed()); - - IXLRanges wsRanges = wb.Ranges("TestRange, Test2"); - Assert.AreEqual(original.RangeAddress.ToStringFixed(), wsRanges.First().RangeAddress.ToString()); - Assert.AreEqual("$A$3:$A$3", wsRanges.Last().RangeAddress.ToStringFixed()); - } - - [Test] - public void WbNamedRangesOneString() - { - var wb = new XLWorkbook(); - IXLWorksheet ws = wb.Worksheets.Add("Sheet1"); - wb.NamedRanges.Add("TestRange", "Sheet1!$A$1,Sheet1!$A$3"); - - IXLRanges wbRanges = ws.Ranges("TestRange"); - Assert.AreEqual("$A$1:$A$1", wbRanges.First().RangeAddress.ToStringFixed()); - Assert.AreEqual("$A$3:$A$3", wbRanges.Last().RangeAddress.ToStringFixed()); - - IXLRanges wsRanges = ws.Ranges("TestRange"); - Assert.AreEqual("$A$1:$A$1", wsRanges.First().RangeAddress.ToStringFixed()); - Assert.AreEqual("$A$3:$A$3", wsRanges.Last().RangeAddress.ToStringFixed()); - } - - [Test] - public void WbProtect1() - { - using (var wb = new XLWorkbook()) - { - var ws = wb.Worksheets.Add("Sheet1"); - wb.Protect(); - Assert.IsTrue(wb.LockStructure); - Assert.IsFalse(wb.LockWindows); - } - } - - [Test] - public void WbProtect2() - { - using (var wb = new XLWorkbook()) - { - var ws = wb.Worksheets.Add("Sheet1"); - wb.Protect(true, false); - Assert.IsTrue(wb.LockStructure); - Assert.IsFalse(wb.LockWindows); - } - } - - [Test] - public void WbProtect3() - { - using (var wb = new XLWorkbook()) - { - var ws = wb.Worksheets.Add("Sheet1"); - wb.Protect("Abc@123"); - Assert.IsTrue(wb.LockStructure); - Assert.IsFalse(wb.LockWindows); - Assert.Throws(typeof(InvalidOperationException), delegate { wb.Protect(); }); - Assert.Throws(typeof(InvalidOperationException), delegate { wb.Unprotect(); }); - Assert.Throws(typeof(ArgumentException), delegate { wb.Unprotect("Cde@345"); }); - } - } - - [Test] - public void WbProtect4() - { - using (var wb = new XLWorkbook()) - { - var ws = wb.Worksheets.Add("Sheet1"); - wb.Protect(); - Assert.IsTrue(wb.LockStructure); - Assert.IsFalse(wb.LockWindows); - wb.Protect("Abc@123"); - Assert.IsTrue(wb.LockStructure); - Assert.IsFalse(wb.LockWindows); - } - } - - [Test] - public void WbProtect5() - { - using (var wb = new XLWorkbook()) - { - var ws = wb.Worksheets.Add("Sheet1"); - wb.Protect(true, false, "Abc@123"); - Assert.IsTrue(wb.LockStructure); - Assert.IsFalse(wb.LockWindows); - wb.Unprotect("Abc@123"); - Assert.IsFalse(wb.LockStructure); - Assert.IsFalse(wb.LockWindows); - } - } - } +using System; +using System.Linq; +using ClosedXML.Excel; +using NUnit.Framework; + +namespace ClosedXML_Tests.Excel +{ + /// + /// Summary description for UnitTest1 + /// + [TestFixture] + public class XLWorkbookTests + { + [Test] + public void Cell1() + { + var wb = new XLWorkbook(); + IXLCell cell = wb.Cell("ABC"); + Assert.IsNull(cell); + } + + [Test] + public void Cell2() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().SetValue(1).AddToNamed("Result", XLScope.Worksheet); + IXLCell cell = wb.Cell("Sheet1!Result"); + Assert.IsNotNull(cell); + Assert.AreEqual(1, cell.GetValue()); + } + + [Test] + public void Cell3() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().SetValue(1).AddToNamed("Result"); + IXLCell cell = wb.Cell("Sheet1!Result"); + Assert.IsNotNull(cell); + Assert.AreEqual(1, cell.GetValue()); + } + + [Test] + public void Cells1() + { + var wb = new XLWorkbook(); + IXLCells cells = wb.Cells("ABC"); + Assert.IsNotNull(cells); + Assert.AreEqual(0, cells.Count()); + } + + [Test] + public void Cells2() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().SetValue(1).AddToNamed("Result", XLScope.Worksheet); + IXLCells cells = wb.Cells("Sheet1!Result, ABC"); + Assert.IsNotNull(cells); + Assert.AreEqual(1, cells.Count()); + Assert.AreEqual(1, cells.First().GetValue()); + } + + [Test] + public void Cells3() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().SetValue(1).AddToNamed("Result"); + IXLCells cells = wb.Cells("Sheet1!Result, ABC"); + Assert.IsNotNull(cells); + Assert.AreEqual(1, cells.Count()); + Assert.AreEqual(1, cells.First().GetValue()); + } + + [Test] + public void NamedRange1() + { + var wb = new XLWorkbook(); + IXLNamedRange range = wb.NamedRange("ABC"); + Assert.IsNull(range); + } + + [Test] + public void NamedRange2() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().SetValue(1).AddToNamed("Result", XLScope.Worksheet); + IXLNamedRange range = wb.NamedRange("Sheet1!Result"); + Assert.IsNotNull(range); + Assert.AreEqual(1, range.Ranges.Count); + Assert.AreEqual(1, range.Ranges.Cells().Count()); + Assert.AreEqual(1, range.Ranges.First().FirstCell().GetValue()); + } + + [Test] + public void NamedRange3() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + IXLNamedRange range = wb.NamedRange("Sheet1!Result"); + Assert.IsNull(range); + } + + [Test] + public void NamedRange4() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().SetValue(1).AddToNamed("Result"); + IXLNamedRange range = wb.NamedRange("Sheet1!Result"); + Assert.IsNotNull(range); + Assert.AreEqual(1, range.Ranges.Count); + Assert.AreEqual(1, range.Ranges.Cells().Count()); + Assert.AreEqual(1, range.Ranges.First().FirstCell().GetValue()); + } + + [Test] + public void Range1() + { + var wb = new XLWorkbook(); + IXLRange range = wb.Range("ABC"); + Assert.IsNull(range); + } + + [Test] + public void Range2() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().SetValue(1).AddToNamed("Result", XLScope.Worksheet); + IXLRange range = wb.Range("Sheet1!Result"); + Assert.IsNotNull(range); + Assert.AreEqual(1, range.Cells().Count()); + Assert.AreEqual(1, range.FirstCell().GetValue()); + } + + [Test] + public void Range3() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().SetValue(1).AddToNamed("Result"); + IXLRange range = wb.Range("Sheet1!Result"); + Assert.IsNotNull(range); + Assert.AreEqual(1, range.Cells().Count()); + Assert.AreEqual(1, range.FirstCell().GetValue()); + } + + [Test] + public void Ranges1() + { + var wb = new XLWorkbook(); + IXLRanges ranges = wb.Ranges("ABC"); + Assert.IsNotNull(ranges); + Assert.AreEqual(0, ranges.Count()); + } + + [Test] + public void Ranges2() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().SetValue(1).AddToNamed("Result", XLScope.Worksheet); + IXLRanges ranges = wb.Ranges("Sheet1!Result, ABC"); + Assert.IsNotNull(ranges); + Assert.AreEqual(1, ranges.Cells().Count()); + Assert.AreEqual(1, ranges.First().FirstCell().GetValue()); + } + + [Test] + public void Ranges3() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().SetValue(1).AddToNamed("Result"); + IXLRanges ranges = wb.Ranges("Sheet1!Result, ABC"); + Assert.IsNotNull(ranges); + Assert.AreEqual(1, ranges.Cells().Count()); + Assert.AreEqual(1, ranges.First().FirstCell().GetValue()); + } + + [Test] + public void WbNamedCell() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.Worksheets.Add("Sheet1"); + ws.Cell(1, 1).SetValue("Test").AddToNamed("TestCell"); + Assert.AreEqual("Test", wb.Cell("TestCell").GetString()); + Assert.AreEqual("Test", ws.Cell("TestCell").GetString()); + } + + [Test] + public void WbNamedCells() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.Worksheets.Add("Sheet1"); + ws.Cell(1, 1).SetValue("Test").AddToNamed("TestCell"); + ws.Cell(2, 1).SetValue("B").AddToNamed("Test2"); + IXLCells wbCells = wb.Cells("TestCell, Test2"); + Assert.AreEqual("Test", wbCells.First().GetString()); + Assert.AreEqual("B", wbCells.Last().GetString()); + + IXLCells wsCells = ws.Cells("TestCell, Test2"); + Assert.AreEqual("Test", wsCells.First().GetString()); + Assert.AreEqual("B", wsCells.Last().GetString()); + } + + [Test] + public void WbNamedRange() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.Worksheets.Add("Sheet1"); + ws.Cell(1, 1).SetValue("A"); + ws.Cell(2, 1).SetValue("B"); + IXLRange original = ws.Range("A1:A2"); + original.AddToNamed("TestRange"); + Assert.AreEqual(original.RangeAddress.ToStringFixed(), wb.Range("TestRange").RangeAddress.ToString()); + Assert.AreEqual(original.RangeAddress.ToStringFixed(), ws.Range("TestRange").RangeAddress.ToString()); + } + + [Test] + public void WbNamedRanges() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.Worksheets.Add("Sheet1"); + ws.Cell(1, 1).SetValue("A"); + ws.Cell(2, 1).SetValue("B"); + ws.Cell(3, 1).SetValue("C").AddToNamed("Test2"); + IXLRange original = ws.Range("A1:A2"); + original.AddToNamed("TestRange"); + IXLRanges wbRanges = wb.Ranges("TestRange, Test2"); + Assert.AreEqual(original.RangeAddress.ToStringFixed(), wbRanges.First().RangeAddress.ToString()); + Assert.AreEqual("$A$3:$A$3", wbRanges.Last().RangeAddress.ToStringFixed()); + + IXLRanges wsRanges = wb.Ranges("TestRange, Test2"); + Assert.AreEqual(original.RangeAddress.ToStringFixed(), wsRanges.First().RangeAddress.ToString()); + Assert.AreEqual("$A$3:$A$3", wsRanges.Last().RangeAddress.ToStringFixed()); + } + + [Test] + public void WbNamedRangesOneString() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.Worksheets.Add("Sheet1"); + wb.NamedRanges.Add("TestRange", "Sheet1!$A$1,Sheet1!$A$3"); + + IXLRanges wbRanges = ws.Ranges("TestRange"); + Assert.AreEqual("$A$1:$A$1", wbRanges.First().RangeAddress.ToStringFixed()); + Assert.AreEqual("$A$3:$A$3", wbRanges.Last().RangeAddress.ToStringFixed()); + + IXLRanges wsRanges = ws.Ranges("TestRange"); + Assert.AreEqual("$A$1:$A$1", wsRanges.First().RangeAddress.ToStringFixed()); + Assert.AreEqual("$A$3:$A$3", wsRanges.Last().RangeAddress.ToStringFixed()); + } + + [Test] + public void WbProtect1() + { + using (var wb = new XLWorkbook()) + { + var ws = wb.Worksheets.Add("Sheet1"); + wb.Protect(); + Assert.IsTrue(wb.LockStructure); + Assert.IsFalse(wb.LockWindows); + } + } + + [Test] + public void WbProtect2() + { + using (var wb = new XLWorkbook()) + { + var ws = wb.Worksheets.Add("Sheet1"); + wb.Protect(true, false); + Assert.IsTrue(wb.LockStructure); + Assert.IsFalse(wb.LockWindows); + } + } + + [Test] + public void WbProtect3() + { + using (var wb = new XLWorkbook()) + { + var ws = wb.Worksheets.Add("Sheet1"); + wb.Protect("Abc@123"); + Assert.IsTrue(wb.LockStructure); + Assert.IsFalse(wb.LockWindows); + Assert.Throws(typeof(InvalidOperationException), delegate { wb.Protect(); }); + Assert.Throws(typeof(InvalidOperationException), delegate { wb.Unprotect(); }); + Assert.Throws(typeof(ArgumentException), delegate { wb.Unprotect("Cde@345"); }); + } + } + + [Test] + public void WbProtect4() + { + using (var wb = new XLWorkbook()) + { + var ws = wb.Worksheets.Add("Sheet1"); + wb.Protect(); + Assert.IsTrue(wb.LockStructure); + Assert.IsFalse(wb.LockWindows); + wb.Protect("Abc@123"); + Assert.IsTrue(wb.LockStructure); + Assert.IsFalse(wb.LockWindows); + } + } + + [Test] + public void WbProtect5() + { + using (var wb = new XLWorkbook()) + { + var ws = wb.Worksheets.Add("Sheet1"); + wb.Protect(true, false, "Abc@123"); + Assert.IsTrue(wb.LockStructure); + Assert.IsFalse(wb.LockWindows); + wb.Unprotect("Abc@123"); + Assert.IsFalse(wb.LockStructure); + Assert.IsFalse(wb.LockWindows); + } + } + } } \ No newline at end of file