diff --git a/ClosedXML/ClosedXML/ClosedXML/ClosedXML.csproj b/ClosedXML/ClosedXML/ClosedXML/ClosedXML.csproj index d6d0784..94f3964 100644 --- a/ClosedXML/ClosedXML/ClosedXML/ClosedXML.csproj +++ b/ClosedXML/ClosedXML/ClosedXML/ClosedXML.csproj @@ -132,6 +132,8 @@ + + diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Columns/XLColumn.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Columns/XLColumn.cs index 2a909b4..e75111a 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Columns/XLColumn.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Columns/XLColumn.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Drawing; + namespace ClosedXML.Excel { internal class XLColumn : XLRangeBase, IXLColumn @@ -29,7 +30,7 @@ IsReference = xlColumnParameters.IsReference; if (IsReference) - SubscribeToShiftedColumns(WorksheetRangeShiftedColumns); + SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); else { SetStyle(xlColumnParameters.DefaultStyleId); @@ -46,8 +47,8 @@ _width = column._width; IsReference = column.IsReference; if (IsReference) - SubscribeToShiftedColumns(WorksheetRangeShiftedColumns); - _collapsed = column._collapsed; + SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); + _collapsed = column._collapsed; _isHidden = column._isHidden; _outlineLevel = column._outlineLevel; SetStyle(column.GetStyleId()); @@ -215,7 +216,7 @@ { using (var asRange = column.AsRange()) { - asRange.InsertColumnsAfter(true, numberOfColumns).Dispose(); + asRange.InsertColumnsAfterVoid(true, numberOfColumns); } } @@ -241,7 +242,7 @@ { using (var asRange = column.AsRange()) { - asRange.InsertColumnsBefore(true, numberOfColumns).Dispose(); + asRange.InsertColumnsBeforeVoid(true, numberOfColumns); } } diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Misc/XLCallbackAction.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Misc/XLCallbackAction.cs new file mode 100644 index 0000000..9238200 --- /dev/null +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Misc/XLCallbackAction.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ClosedXML.Excel.Misc +{ + internal class XLCallbackAction + { + public XLCallbackAction(Action action) + { + this.Action = action; + } + + public Action Action { get; set; } + } +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Misc/XLReentrantEnumerableSet.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Misc/XLReentrantEnumerableSet.cs new file mode 100644 index 0000000..c902733 --- /dev/null +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Misc/XLReentrantEnumerableSet.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; + +namespace ClosedXML.Excel.Misc +{ + /// + /// This is most definitely NOT thread-safe, but it is reentrant (e.g. you can insert and remove + /// items during enumeration) + /// + /// + internal class XLReentrantEnumerableSet : IEnumerable + { + private HashSet _hashSet; + private List _list; + + private int _activeEnumerators; + + public XLReentrantEnumerableSet() + { + _list = new List(); + _hashSet = new HashSet(); + } + + public void Add(T item) + { + if(!_hashSet.Contains(item)) + { + // Add item to end of list + _list.Add(item); + + // Store the item in the hashset too. + _hashSet.Add(item); + } + } + + public void Remove(T item) + { + _hashSet.Remove(item); + + fixup(); + } + + private void fixup() + { + // Only fixup the list if there are no active enumerators + if(_activeEnumerators > 0) + return; + + // Only fixup the list if there are more than a certain number of items to deal with + // This saves fixing up the list continually. + if(_list.Count < 1000 || (_list.Count < _hashSet.Count * 1.5)) + return; + + // Rebuild the list skipping out omitted items + _list = _list.Where(item => _hashSet.Contains(item)).ToList(); + } + + public IEnumerator GetEnumerator() + { + // Mark that we are enumerating + _activeEnumerators++; + try + { + int idx = 0; + + // Important, store count here, as more items may be added while we are enumerating + // and we only want to enumerate items that were already there. + int count = _list.Count; + while(idx < count) + { + var item = _list[idx]; + + // Skip over items in the list which aren't in the hashset; they could have been + // removed while we were enumerating or previously removed. + if(_hashSet.Contains(item)) + { + yield return item; + } + + idx++; + } + + } + finally + { + // Finished enumerating, can now fixup + _activeEnumerators--; + fixup(); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs index 73bd719..6ffdff1 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; + namespace ClosedXML.Excel { internal class XLRange : XLRangeBase, IXLRange @@ -15,8 +16,8 @@ if (!xlRangeParameters.IgnoreEvents) { - SubscribeToShiftedRows(WorksheetRangeShiftedRows); - SubscribeToShiftedColumns(WorksheetRangeShiftedColumns); + SubscribeToShiftedRows((range, rowShifted) => this.WorksheetRangeShiftedRows(range, rowShifted)); + SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); //xlRangeParameters.IgnoreEvents = true; } SetStyle(xlRangeParameters.DefaultStyle); @@ -806,4 +807,4 @@ return this; } } -} \ No newline at end of file +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs index 914e55b..f9ab78d 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs @@ -1,8 +1,10 @@ -using System; +using ClosedXML.Excel.Misc; +using System; using System.Collections.Generic; using System.Linq; + namespace ClosedXML.Excel { internal abstract class XLRangeBase : IXLRangeBase, IXLStylized @@ -55,25 +57,26 @@ } #endregion - - private Boolean _subscribedToShiftedRows; - protected void SubscribeToShiftedRows(RangeShiftedRowsDelegate worksheetRangeShiftedRows) + + private XLCallbackAction _shiftedRowsAction; + + protected void SubscribeToShiftedRows(Action action) { if (Worksheet == null || !Worksheet.EventTrackingEnabled) return; - WorksheetRangeShiftedRows = worksheetRangeShiftedRows; - RangeAddress.Worksheet.RangeShiftedRows += WorksheetRangeShiftedRows; - _subscribedToShiftedRows = true; + _shiftedRowsAction = new XLCallbackAction(action); + + RangeAddress.Worksheet.RangeShiftedRows.Add(_shiftedRowsAction); } - private Boolean _subscribedToShiftedColumns; - protected void SubscribeToShiftedColumns(RangeShiftedColumnsDelegate worksheetRangeShiftedColumns) + private XLCallbackAction _shiftedColumnsAction; + protected void SubscribeToShiftedColumns(Action action) { if (Worksheet == null || !Worksheet.EventTrackingEnabled) return; - WorksheetRangeShiftedColumns = worksheetRangeShiftedColumns; - RangeAddress.Worksheet.RangeShiftedColumns += WorksheetRangeShiftedColumns; - _subscribedToShiftedColumns = true; + _shiftedColumnsAction = new XLCallbackAction(action); + + RangeAddress.Worksheet.RangeShiftedColumns.Add(_shiftedColumnsAction); } #region Public properties @@ -947,6 +950,16 @@ } public IXLRangeColumns InsertColumnsAfter(Boolean onlyUsedCells, Int32 numberOfColumns, Boolean formatFromLeft = true) + { + return InsertColumnsAfterInternal(onlyUsedCells, numberOfColumns, formatFromLeft); + } + + public void InsertColumnsAfterVoid(Boolean onlyUsedCells, Int32 numberOfColumns, Boolean formatFromLeft = true) + { + InsertColumnsAfterInternal(onlyUsedCells, numberOfColumns, formatFromLeft, nullReturn: true); + } + + private IXLRangeColumns InsertColumnsAfterInternal(Boolean onlyUsedCells, Int32 numberOfColumns, Boolean formatFromLeft = true, Boolean nullReturn = false) { int columnCount = ColumnCount(); int firstColumn = RangeAddress.FirstAddress.ColumnNumber + columnCount; @@ -962,7 +975,7 @@ lastRow = XLHelper.MaxRowNumber; var newRange = Worksheet.Range(firstRow, firstColumn, lastRow, lastColumn); - return newRange.InsertColumnsBefore(onlyUsedCells, numberOfColumns, formatFromLeft); + return newRange.InsertColumnsBeforeInternal(onlyUsedCells, numberOfColumns, formatFromLeft, nullReturn); } public IXLRangeColumns InsertColumnsBefore(Int32 numberOfColumns) @@ -991,7 +1004,17 @@ return retVal; } - public IXLRangeColumns InsertColumnsBefore(Boolean onlyUsedCells, Int32 numberOfColumns, Boolean formatFromLeft = true) + public IXLRangeColumns InsertColumnsBefore(Boolean onlyUsedCells, Int32 numberOfColumns, Boolean formatFromLeft = true) + { + return InsertColumnsBeforeInternal(onlyUsedCells, numberOfColumns, formatFromLeft); + } + + public void InsertColumnsBeforeVoid(Boolean onlyUsedCells, Int32 numberOfColumns, Boolean formatFromLeft = true) + { + InsertColumnsBeforeInternal(onlyUsedCells, numberOfColumns, formatFromLeft, nullReturn: true); + } + + private IXLRangeColumns InsertColumnsBeforeInternal(Boolean onlyUsedCells, Int32 numberOfColumns, Boolean formatFromLeft = true, Boolean nullReturn = false) { foreach (XLWorksheet ws in Worksheet.Workbook.WorksheetsInternal) { @@ -1120,6 +1143,8 @@ } } + if(nullReturn) + return null; return rangeToReturn.Columns(); } @@ -1150,8 +1175,18 @@ return retVal; } - public IXLRangeRows InsertRowsBelow(Boolean onlyUsedCells, Int32 numberOfRows, Boolean formatFromAbove = true) - { + public IXLRangeRows InsertRowsBelow(Boolean onlyUsedCells, Int32 numberOfRows, Boolean formatFromAbove = true) + { + return InsertRowsBelowInternal(onlyUsedCells, numberOfRows, formatFromAbove, nullReturn: false); + } + + public void InsertRowsBelowVoid(Boolean onlyUsedCells, Int32 numberOfRows, Boolean formatFromAbove = true) + { + InsertRowsBelowInternal(onlyUsedCells, numberOfRows, formatFromAbove, nullReturn: true); + } + + private IXLRangeRows InsertRowsBelowInternal(Boolean onlyUsedCells, Int32 numberOfRows, Boolean formatFromAbove, Boolean nullReturn) + { int rowCount = RowCount(); int firstRow = RangeAddress.FirstAddress.RowNumber + rowCount; if (firstRow > XLHelper.MaxRowNumber) @@ -1166,7 +1201,7 @@ lastColumn = XLHelper.MaxColumnNumber; var newRange = Worksheet.Range(firstRow, firstColumn, lastRow, lastColumn); - return newRange.InsertRowsAbove(onlyUsedCells, numberOfRows, formatFromAbove); + return newRange.InsertRowsAboveInternal(onlyUsedCells, numberOfRows, formatFromAbove, nullReturn); } public IXLRangeRows InsertRowsAbove(Int32 numberOfRows) @@ -1200,8 +1235,17 @@ public XLAddress SourceAddress; public XLDataValidation DataValidation; } - public IXLRangeRows InsertRowsAbove(Boolean onlyUsedCells, Int32 numberOfRows, Boolean formatFromAbove = true) - { + public void InsertRowsAboveVoid(Boolean onlyUsedCells, Int32 numberOfRows, Boolean formatFromAbove = true) + { + InsertRowsAboveInternal(onlyUsedCells, numberOfRows, formatFromAbove, nullReturn: true); + } + public IXLRangeRows InsertRowsAbove(Boolean onlyUsedCells, Int32 numberOfRows, Boolean formatFromAbove = true) + { + return InsertRowsAboveInternal(onlyUsedCells, numberOfRows, formatFromAbove, nullReturn: false); + } + + private IXLRangeRows InsertRowsAboveInternal(Boolean onlyUsedCells, Int32 numberOfRows, Boolean formatFromAbove, Boolean nullReturn) + { using (var asRange = AsRange()) foreach (XLWorksheet ws in Worksheet.Workbook.WorksheetsInternal) { @@ -1330,6 +1374,10 @@ } } + // Skip calling .Rows() for performance reasons if required. + if(nullReturn) + return null; + return rangeToReturn.Rows(); } @@ -1882,23 +1930,19 @@ new XLRangeParameters(new XLRangeAddress(firstCellAddress, lastCellAddress), Worksheet.Style), true); } - private RangeShiftedRowsDelegate WorksheetRangeShiftedRows; - - private RangeShiftedColumnsDelegate WorksheetRangeShiftedColumns; - - public void Dispose() { - if (_subscribedToShiftedRows) + if(_shiftedRowsAction != null) { - RangeAddress.Worksheet.RangeShiftedRows -= WorksheetRangeShiftedRows; - _subscribedToShiftedRows = false; + RangeAddress.Worksheet.RangeShiftedRows.Remove(_shiftedRowsAction); + _shiftedRowsAction = null; } - if (!_subscribedToShiftedColumns) return; - - RangeAddress.Worksheet.RangeShiftedColumns -= WorksheetRangeShiftedColumns; - _subscribedToShiftedColumns = false; + if(_shiftedColumnsAction != null) + { + RangeAddress.Worksheet.RangeShiftedColumns.Remove(_shiftedColumnsAction); + _shiftedColumnsAction = null; + } } public IXLDataValidation SetDataValidation() @@ -1933,4 +1977,4 @@ Worksheet.SelectedRanges.Add(AsRange()); } } -} \ No newline at end of file +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeColumn.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeColumn.cs index 3ecd2fe..77fc1ba 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeColumn.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeColumn.cs @@ -2,6 +2,7 @@ { using System; using System.Linq; + internal class XLRangeColumn : XLRangeBase, IXLRangeColumn { @@ -12,8 +13,8 @@ { if (quickLoad) return; - SubscribeToShiftedRows((range, rowsShifted) => WorksheetRangeShiftedRows(range, rowsShifted)); - SubscribeToShiftedColumns((range, columnsShifted) => WorksheetRangeShiftedColumns(range, columnsShifted)); + SubscribeToShiftedRows((range, rowsShifted) => this.WorksheetRangeShiftedRows(range, rowsShifted)); + SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); SetStyle(rangeParameters.DefaultStyle); } @@ -351,4 +352,4 @@ } } -} \ No newline at end of file +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeRow.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeRow.cs index 7aab510..802342f 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeRow.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeRow.cs @@ -2,6 +2,7 @@ { using System; using System.Linq; + internal class XLRangeRow : XLRangeBase, IXLRangeRow { @@ -14,8 +15,8 @@ if (quickLoad) return; if (!RangeParameters.IgnoreEvents) { - SubscribeToShiftedRows((range, rowsShifted) => WorksheetRangeShiftedRows(range, rowsShifted)); - SubscribeToShiftedColumns((range, columnsShifted) => WorksheetRangeShiftedColumns(range, columnsShifted)); + SubscribeToShiftedRows((range, rowsShifted) => this.WorksheetRangeShiftedRows(range, rowsShifted)); + SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); } SetStyle(rangeParameters.DefaultStyle); } @@ -273,11 +274,17 @@ private XLRangeRow RowShift(Int32 rowsToShift) { Int32 rowNum = RowNumber() + rowsToShift; - return Worksheet.Range( + + var range = Worksheet.Range( rowNum, RangeAddress.FirstAddress.ColumnNumber, rowNum, - RangeAddress.LastAddress.ColumnNumber).FirstRow(); + RangeAddress.LastAddress.ColumnNumber); + + var result = range.FirstRow(); + range.Dispose(); + + return result; } #region XLRangeRow Above diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/XLRow.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/XLRow.cs index 806a23c..f9772e6 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/XLRow.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/XLRow.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Drawing; + namespace ClosedXML.Excel { internal class XLRow : XLRangeBase, IXLRow @@ -27,7 +28,7 @@ IsReference = xlRowParameters.IsReference; if (IsReference) - SubscribeToShiftedRows(WorksheetRangeShiftedRows); + SubscribeToShiftedRows((range, rowShifted) => this.WorksheetRangeShiftedRows(range, rowShifted)); else { SetStyle(xlRowParameters.DefaultStyleId); @@ -43,7 +44,7 @@ _height = row._height; IsReference = row.IsReference; if (IsReference) - SubscribeToShiftedRows(WorksheetRangeShiftedRows); + SubscribeToShiftedRows((range, rowShifted) => this.WorksheetRangeShiftedRows(range, rowShifted)); _collapsed = row._collapsed; _isHidden = row._isHidden; @@ -159,7 +160,7 @@ { using (var asRange = row.AsRange()) { - asRange.InsertRowsBelow(true, numberOfRows).Dispose(); + asRange.InsertRowsBelowVoid(true, numberOfRows); } } var newRows = Worksheet.Rows(rowNum + 1, rowNum + numberOfRows); @@ -198,7 +199,7 @@ { using (var asRange = row.AsRange()) { - asRange.InsertRowsAbove(true, numberOfRows).Dispose(); + asRange.InsertRowsAboveVoid(true, numberOfRows); } } @@ -703,4 +704,4 @@ } -} \ No newline at end of file +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs index 0a7be5c..8b447b2 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs @@ -4,13 +4,11 @@ using System.Text; using System.Text.RegularExpressions; using ClosedXML.Excel.CalcEngine; +using ClosedXML.Excel.Misc; + namespace ClosedXML.Excel { - internal delegate void RangeShiftedRowsDelegate(XLRange range, Int32 rowsShifted); - - internal delegate void RangeShiftedColumnsDelegate(XLRange range, Int32 columnsShifted); - internal class XLWorksheet : XLRangeBase, IXLWorksheet { #region Constants @@ -19,8 +17,8 @@ #region Events - public event RangeShiftedRowsDelegate RangeShiftedRows; - public event RangeShiftedColumnsDelegate RangeShiftedColumns; + public XLReentrantEnumerableSet RangeShiftedRows; + public XLReentrantEnumerableSet RangeShiftedColumns; #endregion @@ -46,6 +44,10 @@ new XLAddress(null, XLHelper.MaxRowNumber, XLHelper.MaxColumnNumber, false, false))) { EventTrackingEnabled = workbook.EventTracking == XLEventTracking.Enabled; + + RangeShiftedRows = new XLReentrantEnumerableSet(); + RangeShiftedColumns = new XLReentrantEnumerableSet(); + RangeAddress.Worksheet = this; RangeAddress.FirstAddress.Worksheet = this; RangeAddress.LastAddress.Worksheet = this; @@ -68,9 +70,9 @@ _columnWidth = workbook.ColumnWidth; _rowHeight = workbook.RowHeight; RowHeightChanged = Math.Abs(workbook.RowHeight - XLWorkbook.DefaultRowHeight) > XLHelper.Epsilon; - Name = sheetName; - SubscribeToShiftedRows(WorksheetRangeShiftedRows); - SubscribeToShiftedColumns(WorksheetRangeShiftedColumns); + Name = sheetName; + SubscribeToShiftedRows((range, rowsShifted) => this.WorksheetRangeShiftedRows(range, rowsShifted)); + SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); Charts = new XLCharts(); ShowFormulas = workbook.ShowFormulas; ShowGridLines = workbook.ShowGridLines; @@ -1318,13 +1320,23 @@ public void NotifyRangeShiftedRows(XLRange range, Int32 rowsShifted) { if (RangeShiftedRows != null) - RangeShiftedRows(range, rowsShifted); + { + foreach(var item in RangeShiftedRows) + { + item.Action(range, rowsShifted); + } + } } public void NotifyRangeShiftedColumns(XLRange range, Int32 columnsShifted) { if (RangeShiftedColumns != null) - RangeShiftedColumns(range, columnsShifted); + { + foreach(var item in RangeShiftedColumns) + { + item.Action(range, columnsShifted); + } + } } public XLRow Row(Int32 row, Boolean pingCells) diff --git a/ClosedXML/ClosedXML/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj b/ClosedXML/ClosedXML/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj index 8da1ad5..4fbd00f 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj +++ b/ClosedXML/ClosedXML/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj @@ -510,6 +510,9 @@ Excel\IXLWorksheets.cs + + Excel\Misc\XLCallbackAction.cs + Excel\Misc\XLDictionary.cs @@ -519,6 +522,9 @@ Excel\Misc\XLIdManager.cs + + Excel\Misc\XLReentrantEnumerableSet.cs + Excel\NamedRanges\IXLNamedRange.cs diff --git a/ClosedXML/ClosedXML/ClosedXML_Sandbox/Program.cs b/ClosedXML/ClosedXML/ClosedXML_Sandbox/Program.cs index 9e2bb7b..46b1c77 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Sandbox/Program.cs +++ b/ClosedXML/ClosedXML/ClosedXML_Sandbox/Program.cs @@ -12,7 +12,19 @@ { static void Main(string[] args) { + var wb = new XLWorkbook(); + + foreach (var wsNum in Enumerable.Range(1, 5)) + { + var ws = wb.AddWorksheet(wsNum.ToString()); + var rowNum = Math.Pow(10, wsNum); + var start = DateTime.Now; + ws.FirstRow().InsertRowsBelow((int)rowNum); + var end = DateTime.Now; + Console.WriteLine(rowNum + " rows in " + (end - start).TotalSeconds + " seconds."); + } + Console.ReadKey(); } } diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/WorkbookProperties.xlsx b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/WorkbookProperties.xlsx index 6007842..da39cda 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/WorkbookProperties.xlsx +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/WorkbookProperties.xlsx Binary files differ diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Styles/UsingRichText.xlsx b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Styles/UsingRichText.xlsx index 18fff6e..cfc3637 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Styles/UsingRichText.xlsx +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Styles/UsingRichText.xlsx Binary files differ diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/TestHelper.cs b/ClosedXML/ClosedXML/ClosedXML_Tests/TestHelper.cs index 50fddbf..35fde24 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/TestHelper.cs +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/TestHelper.cs @@ -19,7 +19,13 @@ //Note: Run example tests parameters public static string TestsOutputDirectory { - get { return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); } + get { + var preferredPath = "C:\\ClosedXML_Tests"; + if (Directory.Exists(preferredPath)) + return preferredPath; + + return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + } }