9using System.Collections.Generic;
12using System.Text.RegularExpressions;
25 public class Worksheet
52#pragma warning disable CA1805
54#pragma warning restore CA1805
58#pragma warning disable CA1805
60#pragma warning restore CA1805
64#pragma warning disable CA1805
66#pragma warning restore CA1805
78#pragma warning disable CA1805
80#pragma warning restore CA1805
88#pragma warning disable CA1805
90#pragma warning restore CA1805
182 #region privateFields
183 private Style activeStyle;
184 private Range? autoFilterRange;
185 private readonly Dictionary<string, Cell> cells;
186 private readonly Dictionary<int, Column> columns;
187 private string sheetName;
188 private int currentRowNumber;
189 private int currentColumnNumber;
190 private float defaultRowHeight;
191 private float defaultColumnWidth;
192 private readonly Dictionary<int, float> rowHeights;
193 private readonly Dictionary<int, bool> hiddenRows;
194 private readonly Dictionary<string, Range> mergedCells;
195 private readonly List<SheetProtectionValue> sheetProtectionValues;
196 private bool useActiveStyle;
199 private IPassword sheetProtectionPassword;
200 private List<Range> selectedCells;
201 private bool? freezeSplitPanes;
202 private float? paneSplitLeftWidth;
203 private float? paneSplitTopHeight;
204 private Address? paneSplitTopLeftCell;
205 private Address? paneSplitAddress;
209 private Dictionary<SheetViewType, int> zoomFactor;
218 get {
return autoFilterRange; }
224 public Dictionary<string, Cell>
Cells
226 get {
return cells; }
234 get {
return columns; }
248 get {
return defaultColumnWidth; }
255 defaultColumnWidth = value;
265 get {
return defaultRowHeight; }
272 defaultRowHeight = value;
282 get {
return hiddenRows; }
290 get {
return rowHeights; }
298 get {
return mergedCells; }
306 get {
return selectedCells; }
319 throw new FormatException(
"The ID " + value +
" is invalid. Worksheet IDs must be >0");
330 get {
return sheetName; }
340 get {
return sheetProtectionPassword; }
341 internal set { sheetProtectionPassword = value; }
349 get {
return sheetProtectionValues; }
362 get {
return workbookReference; }
365 workbookReference = value;
368 workbookReference.ValidateWorksheets();
380 get {
return hidden; }
384 if (value && workbookReference !=
null)
386 workbookReference.ValidateWorksheets();
401 get {
return paneSplitTopHeight; }
414 get {
return paneSplitLeftWidth; }
423 get {
return freezeSplitPanes; }
433 get {
return paneSplitTopLeftCell; }
445 get {
return paneSplitAddress; }
455 get {
return activePane; }
463 get {
return activeStyle; }
510 return zoomFactor[viewType];
536 cells =
new Dictionary<string, Cell>();
537 currentRowNumber = 0;
538 currentColumnNumber = 0;
541 rowHeights =
new Dictionary<int, float>();
542 mergedCells =
new Dictionary<string, Range>();
543 selectedCells =
new List<Range>();
544 sheetProtectionValues =
new List<SheetProtectionValue>();
545 hiddenRows =
new Dictionary<int, bool>();
546 columns =
new Dictionary<int, Column>();
548 workbookReference =
null;
550 zoomFactor =
new Dictionary<SheetViewType, int>
581 workbookReference = reference;
586 #region methods_AddNextCell
598 AddNextCell(CastValue(value, currentColumnNumber, currentRowNumber),
true,
null);
614 AddNextCell(CastValue(value, currentColumnNumber, currentRowNumber),
true, style);
630 if (style !=
null || (activeStyle !=
null && useActiveStyle))
632 if (cell.
CellStyle ==
null && useActiveStyle)
636 else if (cell.
CellStyle ==
null && style !=
null)
640 else if (cell.
CellStyle !=
null && useActiveStyle)
643 mixedStyle.
Append(activeStyle);
646 else if (cell.
CellStyle !=
null && style !=
null)
654 if (cells.ContainsKey(address))
656 cells[address] = cell;
660 cells.Add(address, cell);
666 currentColumnNumber++;
681 currentColumnNumber = cell.ColumnNumber + 1;
687 currentRowNumber = cell.RowNumber + 1;
703 private static Cell CastValue(
object value,
int column,
int row)
706 if (value !=
null && value.GetType() == typeof(Cell))
709 c.CellAddress2 =
new Address(column, row);
713 c =
new Cell(value, Cell.CellType.Default, column, row);
721 #region methods_AddCell
733 public void AddCell(
object value,
int columnNumber,
int rowNumber)
735 AddNextCell(CastValue(value, columnNumber, rowNumber),
false,
null);
750 public void AddCell(
object value,
int columnNumber,
int rowNumber,
Style style)
752 AddNextCell(CastValue(value, columnNumber, rowNumber),
false, style);
766 public void AddCell(
object value,
string address)
791 AddCell(value, column, row, style);
796 #region methods_AddCellFormula
884 #region methods_AddCellRange
898 AddCellRangeInternal(values, startAddress, endAddress,
null);
915 AddCellRangeInternal(values, startAddress, endAddress, style);
928 public void AddCellRange(IReadOnlyList<object> values,
string cellRange)
993 private void AddCellRangeInternal<T>(IReadOnlyList<T> values,
Address startAddress,
Address endAddress,
Style style)
999 List<Address> addresses =
Cell.
GetCellRange(startAddress, endAddress) as List<Address>;
1000 if (values.Count != addresses.Count)
1002 throw new RangeException(
"The number of passed values (" + values.Count +
") differs from the number of cells within the range (" + addresses.Count +
")");
1004 List<Cell> list = Cell.ConvertArray(values) as List<Cell>;
1005 int len = values.Count;
1006 for (
int i = 0; i < len; i++)
1008 list[i].RowNumber = addresses[i].Row;
1009 list[i].ColumnNumber = addresses[i].Column;
1015 #region methods_RemoveCell
1026 return cells.Remove(address);
1045 #region methods_setStyle
1057 foreach (
Address address
in addresses)
1060 if (this.cells.ContainsKey(key))
1064 cells[key].RemoveStyle();
1068 cells[key].SetStyle(style);
1129 throw new FormatException(
"The passed address'" + addressExpression +
"' is neither a cell address, nor a range");
1135 #region boundaryFunctions
1144 return GetBoundaryNumber(
false,
true);
1155 return GetBoundaryDataNumber(
false,
true,
true);
1166 return GetBoundaryNumber(
true,
true);
1177 return GetBoundaryDataNumber(
true,
true,
true);
1189 return GetBoundaryNumber(
false,
false);
1200 return GetBoundaryDataNumber(
false,
false,
true);
1212 return GetBoundaryNumber(
true,
false);
1224 return GetBoundaryDataNumber(
true,
false,
true);
1239 if (lastRow < 0 || lastColumn < 0)
1243 return new Address(lastColumn, lastRow);
1257 if (lastRow < 0 || lastColumn < 0)
1261 return new Address(lastColumn, lastRow);
1274 if (firstRow < 0 || firstColumn < 0)
1278 return new Address(firstColumn, firstRow);
1291 if (firstRow < 0 || firstColumn < 0)
1295 return new Address(firstColumn, firstRow);
1305 private int GetBoundaryDataNumber(
bool row,
bool min,
bool ignoreEmpty)
1307 if (cells.Count == 0)
1315 return cells.Min(x => x.Value.RowNumber);
1319 return cells.Max(x => x.Value.RowNumber);
1323 return cells.Min(x => x.Value.ColumnNumber);
1327 return cells.Max(x => x.Value.ColumnNumber);
1330 List<Cell> nonEmptyCells = cells.Values.Where(x => x.Value !=
null && x.Value.ToString() !=
string.Empty).ToList();
1331 if (nonEmptyCells.Count == 0)
1337 return nonEmptyCells.Min(x => x.RowNumber);
1341 return nonEmptyCells.Max(x => x.RowNumber);
1345 return nonEmptyCells.Min(x => x.ColumnNumber);
1349 return nonEmptyCells.Max(x => x.ColumnNumber);
1359 private int GetBoundaryNumber(
bool row,
bool min)
1361 int cellBoundary = GetBoundaryDataNumber(row, min,
false);
1364 int heightBoundary = -1;
1365 if (rowHeights.Count > 0)
1369 int hiddenBoundary = -1;
1370 if (hiddenRows.Count > 0)
1374 return min ? GetMinRow(cellBoundary, heightBoundary, hiddenBoundary) : GetMaxRow(cellBoundary, heightBoundary, hiddenBoundary);
1378 int columnDefBoundary = -1;
1379 if (columns.Count > 0)
1381 columnDefBoundary = min ?
Columns.Min(x => x.Key) :
Columns.Max(x => x.Key);
1385 return cellBoundary >= 0 && cellBoundary < columnDefBoundary ? cellBoundary : columnDefBoundary;
1389 return cellBoundary >= 0 && cellBoundary > columnDefBoundary ? cellBoundary : columnDefBoundary;
1401 private static int GetMaxRow(
int cellBoundary,
int heightBoundary,
int hiddenBoundary)
1404 if (cellBoundary >= 0)
1406 highest = cellBoundary;
1408 if (heightBoundary >= 0 && heightBoundary > highest)
1410 highest = heightBoundary;
1412 if (hiddenBoundary >= 0 && hiddenBoundary > highest)
1414 highest = hiddenBoundary;
1426 private static int GetMinRow(
int cellBoundary,
int heightBoundary,
int hiddenBoundary)
1428 int lowest =
int.MaxValue;
1429 if (cellBoundary >= 0)
1431 lowest = cellBoundary;
1433 if (heightBoundary >= 0 && heightBoundary < lowest)
1435 lowest = heightBoundary;
1437 if (hiddenBoundary >= 0 && hiddenBoundary < lowest)
1439 lowest = hiddenBoundary;
1441 return lowest == int.MaxValue ? -1 : lowest;
1445 #region Insert-Search-Replace
1458 var upperRow = this.
GetRow(rowNumber);
1461 var cellsToChange = this.Cells.Where(c => c.
Value.CellAddress2.Row > rowNumber).ToList();
1464 Dictionary<string, Cell> newCells =
new Dictionary<string, Cell>();
1465 foreach (var cell
in cellsToChange)
1467 var row = cell.Value.CellAddress2.Row;
1468 var col = cell.Value.CellAddress2.Column;
1471 Cell newCell =
new Cell(cell.Value.Value, cell.Value.DataType, newAddress);
1472 if (cell.Value.CellStyle !=
null)
1474 newCell.
SetStyle(cell.Value.CellStyle);
1476 newCells.Add(newAddress.
GetAddress(), newCell);
1479 this.Cells.Remove(cell.Key);
1483 foreach (
Cell cell
in upperRow)
1485 for (
int i = 0; i < numberOfNewRows; i++)
1487 Address newAddress =
new Address(cell.CellAddress2.Column, cell.CellAddress2.Row + 1 + i);
1489 if (cell.CellStyle !=
null)
1491 this.Cells.Add(newAddress.
GetAddress(), newCell);
1496 foreach (KeyValuePair<string, Cell> cellKeyValue
in newCells)
1498 this.Cells.Add(cellKeyValue.Key, cellKeyValue.Value);
1512 var leftColumn = this.
GetColumn(columnNumber);
1513 var cellsToChange = this.Cells.Where(c => c.
Value.CellAddress2.Column > columnNumber).ToList();
1515 Dictionary<string, Cell> newCells =
new Dictionary<string, Cell>();
1516 foreach (var cell
in cellsToChange)
1518 var row = cell.Value.CellAddress2.Row;
1519 var col = cell.Value.CellAddress2.Column;
1522 Cell newCell =
new Cell(cell.Value.Value, cell.Value.DataType, newAddress);
1523 if (cell.Value.CellStyle !=
null)
1525 newCell.
SetStyle(cell.Value.CellStyle);
1527 newCells.Add(newAddress.
GetAddress(), newCell);
1530 this.Cells.Remove(cell.Key);
1534 foreach (
Cell cell
in leftColumn)
1536 for (
int i = 0; i < numberOfNewColumns; i++)
1538 Address newAddress =
new Address(cell.CellAddress2.Column + 1 + i, cell.CellAddress2.Row);
1540 if (cell.CellStyle !=
null)
1542 this.Cells.Add(newAddress.
GetAddress(), newCell);
1547 foreach (KeyValuePair<string, Cell> cellKeyValue
in newCells)
1549 this.Cells.Add(cellKeyValue.Key, cellKeyValue.Value);
1560 var cell = this.Cells.FirstOrDefault(c =>
1561 Equals(c.
Value.Value, searchValue))
1574 return this.Cells.Values
1575 .FirstOrDefault(c => c !=
null && (c.
Value ==
null || predicate(c)));
1585 return this.Cells.Where(c =>
1586 Equals(c.
Value.Value, searchValue))
1587 .Select(c => c.
Value)
1601 foreach (var cell
in foundCells)
1603 cell.Value = newValue;
1610 #region common_methods
1619 if (!sheetProtectionValues.Contains(typeOfProtection))
1625 sheetProtectionValues.Add(typeOfProtection);
1637 SetColumnHiddenState(columnNumber,
true);
1648 SetColumnHiddenState(columnNumber,
true);
1658 SetRowHiddenState(rowNumber,
true);
1666 useActiveStyle =
false;
1678 if (!cells.ContainsKey(address.
GetAddress()))
1706 return cells.ContainsKey(address.
GetAddress());
1718 public bool HasCell(
int columnNumber,
int rowNumber)
1730 if (columns.TryGetValue(columnNumber, out var value) && !value.HasAutoFilter)
1732 columns.Remove(columnNumber);
1734 else if (columns.TryGetValue(columnNumber, out var value2))
1736 value2.IsHidden =
false;
1746 public IReadOnlyList<Cell>
GetRow(
int rowNumber)
1748 List<Cell> list =
new List<Cell>();
1749 foreach (KeyValuePair<string, Cell> cell
in cells)
1751 if (cell.Value.RowNumber == rowNumber)
1753 list.Add(cell.Value);
1756 list.Sort((c1, c2) => (c1.ColumnNumber.CompareTo(c2.ColumnNumber)));
1779 List<Cell> list =
new List<Cell>();
1780 foreach (KeyValuePair<string, Cell> cell
in cells)
1782 if (cell.Value.ColumnNumber == columnNumber)
1784 list.Add(cell.Value);
1787 list.Sort((c1, c2) => (c1.RowNumber.CompareTo(c2.RowNumber)));
1797 return currentColumnNumber;
1806 return currentRowNumber;
1814 currentColumnNumber++;
1815 currentRowNumber = 0;
1827 currentColumnNumber += numberOfColumns;
1828 if (!keepRowPosition)
1830 currentRowNumber = 0;
1841 currentColumnNumber = 0;
1851 public void GoToNextRow(
int numberOfRows,
bool keepColumnPosition =
false)
1853 currentRowNumber += numberOfRows;
1854 if (!keepColumnPosition)
1856 currentColumnNumber = 0;
1894 string key = startAddress +
":" + endAddress;
1895 Range value =
new Range(startAddress, endAddress);
1897 foreach (KeyValuePair<string, Range> item
in mergedCells)
1899 if (item.Value.ResolveEnclosedAddresses().Intersect(result).Any())
1901 throw new RangeException(
"The passed range: " + value.ToString() +
" contains cells that are already in the defined merge range: " + item.Key);
1904 mergedCells.Add(key, value);
1911 internal void RecalculateAutoFilter()
1913 if (autoFilterRange ==
null)
1918 foreach (KeyValuePair<string, Cell> item
in Cells)
1920 if (item.Value.ColumnNumber < start || item.Value.ColumnNumber > end)
1922 if (item.Value.RowNumber > endRow)
1923 { endRow = item.Value.RowNumber; }
1926 for (
int i = start; i <= end; i++)
1928 if (!columns.TryGetValue(i, out var value))
1932 HasAutoFilter =
true
1938 value.HasAutoFilter =
true;
1941 autoFilterRange =
new Range(start, 0, end, endRow);
1947 internal void RecalculateColumns()
1949 List<int> columnsToDelete =
new List<int>();
1950 foreach (KeyValuePair<int, Column> col
in columns)
1952 if (!col.Value.HasAutoFilter && !col.Value.IsHidden && Comparators.CompareDimensions(col.Value.Width,
DefaultWorksheetColumnWidth) == 0 && col.Value.DefaultColumnStyle ==
null)
1954 columnsToDelete.Add(col.Key);
1957 foreach (
int index
in columnsToDelete)
1959 columns.Remove(index);
1968 internal void ResolveMergedCells()
1970 Style mergeStyle = BasicStyles.MergeCellStyle;
1972 foreach (KeyValuePair<string, Range> range
in MergedCells)
1975 List<Address> addresses = Cell.GetCellRange(range.Value.StartAddress, range.Value.EndAddress) as List<Address>;
1976 foreach (Address address
in addresses)
1982 DataType = Cell.CellType.Empty,
1983 RowNumber = address.
Row,
1984 ColumnNumber = address.Column
1994 cell.DataType = Cell.CellType.Empty;
2017 autoFilterRange =
null;
2027 SetColumnHiddenState(columnNumber,
false);
2038 SetColumnHiddenState(columnNumber,
false);
2048 SetRowHiddenState(rowNumber,
false);
2059 if (range ==
null || !mergedCells.ContainsKey(range))
2061 throw new RangeException(
"The cell range " + range +
" was not found in the list of merged cell ranges");
2065 foreach (
Address address
in addresses)
2077 mergedCells.Remove(range);
2086 if (rowHeights.ContainsKey(rowNumber))
2088 rowHeights.Remove(rowNumber);
2098 if (sheetProtectionValues.Contains(value))
2100 sheetProtectionValues.Remove(value);
2112 useActiveStyle =
false;
2116 useActiveStyle =
true;
2118 activeStyle = style;
2131 if (endColumn < startColumn)
2150 RecalculateAutoFilter();
2151 RecalculateColumns();
2160 private void SetColumnHiddenState(
int columnNumber,
bool state)
2163 if (columns.TryGetValue(columnNumber, out var value))
2165 value.IsHidden = state;
2173 columns.Add(columnNumber, c);
2175 if (!columns[columnNumber].IsHidden && Comparators.CompareDimensions(columns[columnNumber].Width,
DefaultWorksheetColumnWidth) == 0 && !columns[columnNumber].HasAutoFilter)
2177 columns.Remove(columnNumber);
2206 if (columns.TryGetValue(columnNumber, out var value))
2208 value.Width = width;
2216 columns.Add(columnNumber, c);
2242 if (this.columns.TryGetValue(columnNumber, out var value))
2244 return value.SetDefaultColumnStyle(style);
2250 this.columns.Add(columnNumber, c);
2289 currentColumnNumber = columnNumber;
2300 currentRowNumber = rowNumber;
2328 Range? resolved = ParseRange(rangeOrAddress);
2329 if (resolved !=
null)
2349 selectedCells.Clear();
2368 Range? resolved = ParseRange(rangeOrAddress);
2369 if (resolved !=
null)
2400 if (
string.IsNullOrEmpty(password))
2402 sheetProtectionPassword.UnsetPassword();
2407 sheetProtectionPassword.SetPassword(password);
2425 if (rowHeights.ContainsKey(rowNumber))
2427 rowHeights[rowNumber] = height;
2431 rowHeights.Add(rowNumber, height);
2441 private void SetRowHiddenState(
int rowNumber,
bool state)
2444 if (hiddenRows.ContainsKey(rowNumber))
2448 hiddenRows[rowNumber] =
true;
2452 hiddenRows.Remove(rowNumber);
2457 hiddenRows.Add(rowNumber,
true);
2468 if (
string.IsNullOrEmpty(name))
2476 Regex regex =
new Regex(
@"[\[\]\*\?/\\]");
2477 Match match = regex.Match(name);
2478 if (match.Captures.Count > 0)
2480 throw new FormatException(
@"the worksheet name must not contain the characters [ ] * ? / \ ");
2512 SetSplit(
null, topPaneHeight, topLeftCell, activePane);
2525 SetSplit(
null, numberOfRowsFromTop, freeze, topLeftCell, activePane);
2536 SetSplit(leftPaneWidth,
null, topLeftCell, activePane);
2550 SetSplit(numberOfColumnsFromLeft,
null, freeze, topLeftCell, activePane);
2568 if (numberOfColumnsFromLeft !=
null && topLeftCell.
Column < numberOfColumnsFromLeft.Value)
2571 " is not valid for a frozen, vertical split with the split pane column number " + numberOfColumnsFromLeft.Value);
2573 if (numberOfRowsFromTop !=
null && topLeftCell.
Row < numberOfRowsFromTop.Value)
2576 " is not valid for a frozen, horizontal split height the split pane row number " + numberOfRowsFromTop.Value);
2579 this.paneSplitLeftWidth =
null;
2580 this.paneSplitTopHeight =
null;
2581 this.freezeSplitPanes = freeze;
2582 int row = numberOfRowsFromTop !=
null ? numberOfRowsFromTop.Value : 0;
2583 int column = numberOfColumnsFromLeft !=
null ? numberOfColumnsFromLeft.Value : 0;
2584 this.paneSplitAddress =
new Address(column, row);
2585 this.paneSplitTopLeftCell = topLeftCell;
2586 this.activePane = activePane;
2600 this.paneSplitLeftWidth = leftPaneWidth;
2601 this.paneSplitTopHeight = topPaneHeight;
2602 this.freezeSplitPanes =
null;
2603 this.paneSplitAddress =
null;
2604 this.paneSplitTopLeftCell = topLeftCell;
2605 this.activePane = activePane;
2613 this.paneSplitLeftWidth =
null;
2614 this.paneSplitTopHeight =
null;
2615 this.freezeSplitPanes =
null;
2616 this.paneSplitAddress =
null;
2617 this.paneSplitTopLeftCell =
null;
2618 this.activePane =
null;
2633 foreach (KeyValuePair<string, Cell> cell
in this.cells)
2635 copy.AddCell(cell.Value.Copy(), cell.Key);
2637 copy.activePane = this.activePane;
2638 copy.activeStyle = this.activeStyle;
2639 if (this.autoFilterRange.HasValue)
2641 copy.autoFilterRange = this.autoFilterRange.Value.Copy();
2643 foreach (KeyValuePair<int, Column> column
in this.columns)
2645 copy.columns.Add(column.Key, column.Value.Copy());
2647 copy.CurrentCellDirection = this.CurrentCellDirection;
2648 copy.currentColumnNumber = this.currentColumnNumber;
2649 copy.currentRowNumber = this.currentRowNumber;
2650 copy.defaultColumnWidth = this.defaultColumnWidth;
2651 copy.defaultRowHeight = this.defaultRowHeight;
2652 copy.freezeSplitPanes = this.freezeSplitPanes;
2653 copy.hidden = this.hidden;
2654 foreach (KeyValuePair<int, bool> row
in this.hiddenRows)
2656 copy.hiddenRows.Add(row.Key, row.Value);
2658 foreach (KeyValuePair<string, Range> cell
in this.mergedCells)
2660 copy.mergedCells.Add(cell.Key, cell.Value.Copy());
2662 if (this.paneSplitAddress.HasValue)
2664 copy.paneSplitAddress = this.paneSplitAddress.Value.Copy();
2666 copy.paneSplitLeftWidth = this.paneSplitLeftWidth;
2667 copy.paneSplitTopHeight = this.paneSplitTopHeight;
2668 if (this.paneSplitTopLeftCell.HasValue)
2670 copy.paneSplitTopLeftCell = this.paneSplitTopLeftCell.Value.Copy();
2672 foreach (KeyValuePair<int, float> row
in this.rowHeights)
2674 copy.rowHeights.Add(row.Key, row.Value);
2676 foreach (
Range range
in selectedCells)
2678 copy.AddSelectedCells(range);
2680 copy.sheetProtectionPassword.CopyFrom(this.sheetProtectionPassword);
2683 copy.sheetProtectionValues.Add(value);
2685 copy.useActiveStyle = this.useActiveStyle;
2686 copy.UseSheetProtection = this.UseSheetProtection;
2687 copy.ShowGridLines = this.ShowGridLines;
2688 copy.ShowRowColumnHeaders = this.ShowRowColumnHeaders;
2689 copy.ShowRuler = this.ShowRuler;
2690 copy.ViewType = this.ViewType;
2691 copy.zoomFactor.Clear();
2692 foreach (KeyValuePair<SheetViewType, int> zoomFactor
in this.zoomFactor)
2694 copy.SetZoomFactor(zoomFactor.Key, zoomFactor.Value);
2712 if (this.zoomFactor.ContainsKey(sheetViewType))
2714 this.zoomFactor[sheetViewType] = zoomFactor;
2718 this.zoomFactor.Add(sheetViewType, zoomFactor);
2724 #region static_methods
2734 if (
string.IsNullOrEmpty(input))
2749 for (
int i = 0; i < len; i++)
2752 if (c ==
'[' || c ==
']' || c ==
'*' || c ==
'?' || c ==
'\\' || c ==
'/')
2757 return GetUnusedWorksheetName(sb.ToString(), workbook);
2765 private static Range? ParseRange(
string rangeOrAddress)
2767 if (
string.IsNullOrEmpty(rangeOrAddress))
2772 if (rangeOrAddress.Contains(
":"))
2778 Address address = Cell.ResolveCellCoordinate(rangeOrAddress);
2779 range =
new Range(address, address);
2793 private static string GetUnusedWorksheetName(
string name, Workbook workbook)
2795 if (workbook ==
null)
2797 throw new WorksheetException(
"The workbook reference is null");
2799 if (!WorksheetExists(name, workbook))
2801 Regex regex =
new Regex(
@"^(.*?)(\d{1,31})$");
2802 Match match = regex.Match(name);
2803 string prefix = name;
2805 if (match.Groups.Count > 1)
2807 prefix = match.Groups[1].Value;
2808 _ =
int.TryParse(match.Groups[2].Value, out number);
2813 string numberString = ParserUtils.ToString(number);
2817 prefix = prefix.Substring(0, endIndex);
2819 string newName = prefix + numberString;
2820 if (!WorksheetExists(newName, workbook))
2832 private static bool WorksheetExists(
string name, Workbook workbook)
2835 for (
int i = 0; i < len; i++)
2837 if (workbook.
Worksheets[i].SheetName == name)
2877 internal static WorksheetPane? GetWorksheetPaneEnum(
string pane)
2884 case "bottomLeft": output =
WorksheetPane.BottomLeft;
break;
2885 case "bottomRight": output =
WorksheetPane.BottomRight;
break;
2895 internal static SheetViewType GetSheetViewTypeEnum(
string viewType)
2900 case "pageBreakPreview": output =
SheetViewType.PageBreakPreview;
break;
2901 case "pageLayout": output =
SheetViewType.PageLayout;
break;
Class representing a cell of a worksheet.
static Address ResolveCellCoordinate(string address)
Gets the column and row number (zero based) of a cell by the address.
CellType
Enum defines the basic data types of a cell.
static void ValidateRowNumber(int row)
Validates the passed (zero-based) row number. An exception will be thrown if the row is invalid.
static string ResolveCellAddress(int column, int row, AddressType type=AddressType.Default)
Gets the address of a cell by the column and row number (zero based).
static AddressScope GetAddressScope(string addressExpression)
Gets the scope of the passed address (string expression). Scope means either single cell address or r...
Style CellStyle
Gets the assigned style of the cell.
static Range ResolveCellRange(string range)
Resolves a cell range from the format like A1:B3 or AAD556:AAD1000.
int RowNumber
Gets or sets the number of the row (zero-based).
static void ValidateColumnNumber(int column)
Validates the passed (zero-based) column number. An exception will be thrown if the column is invalid...
static int ResolveColumn(string columnAddress)
Gets the column number from the column address (A - XFD).
string CellAddress
Gets or sets the combined cell Address as string in the format A1 - XFD1048576. The address may conta...
AddressScope
Enum to define the scope of a passed address string (used in static context).
int ColumnNumber
Gets or sets the number of the column (zero-based).
Style SetStyle(Style style, bool unmanaged=false)
Sets the style of the cell.
static IEnumerable< Address > GetCellRange(string range)
Gets a list of cell addresses from a cell range (format A1:B3 or AAD556:AAD1000).
void ResolveCellType()
Method resets the Cell type and tries to find the actual type. This is used if a Cell was created wit...
object Value
Gets or sets the value of the cell (generic object type). When setting a value, the DataType is autom...
void RemoveStyle()
Removes the assigned style from the cell.
Class representing a column of a worksheet.
Style SetDefaultColumnStyle(Style defaultColumnStyle, bool unmanaged=false)
Sets the default style of the column.
Class for exceptions regarding range incidents (e.g. out-of-range).
Class for exceptions regarding worksheet incidents.
Class implementing a legacy password, based on the proprietary hashing algorithm of Excel.
PasswordType
Target type of the password.
Class to register plug-in classes that extends the functionality of NanoXLSX (Core or any other packa...
static bool Initialize()
Initializes the plug-in loader process. If already initialized, the method returns without action.
bool Equals(AbstractStyle other)
Method to compare two objects for sorting purpose.
Factory class with the most important predefined styles.
static Style MergeCellStyle
Gets the style used when merging cells.
bool ForceApplyAlignment
Gets or sets whether the applyAlignment property (used to merge cells) will be defined in the XF entr...
Class representing a Style with sub classes within a style sheet. An instance of this class is only a...
override AbstractStyle Copy()
Method to copy the current object to a new one without casting.
CellXf CurrentCellXf
Gets or sets the current CellXf object of the style.
Style Append(AbstractStyle styleToAppend)
Appends the specified style parts to the current one. The parts can be instances of sub-classes like ...
General data utils class with static methods.
static IReadOnlyList< Range > MergeRange(List< Range > givenRanges, Range newRange, RangeMergeStrategy strategy=RangeMergeStrategy.MergeColumns)
Merges a range with a list of given ranges. If there is no intersection between the list and the new ...
static IReadOnlyList< Range > SubtractRange(List< Range > givenRanges, Range rangeToRemove, RangeMergeStrategy strategy=RangeMergeStrategy.MergeColumns)
Subtracts a range form a list of given ranges. If the range to be removed does not intersect any of t...
Class providing static methods to parse string values to specific types or to print object as languag...
static string ToUpper(string input)
Transforms a string to upper case with null check and invariant culture.
Class representing a workbook.
List< Worksheet > Worksheets
Gets the list of worksheets in the workbook.
Dictionary< int, bool > HiddenRows
Gets the hidden rows as dictionary with the zero-based row number as key and a boolean as value....
Cell FirstCellByValue(object searchValue)
Searches for the first occurrence of the value.
int GetFirstDataRowNumber()
Gets the first existing row number with data in the current worksheet (zero-based).
static readonly int MaxWorksheetNameLength
Maximum number of characters a worksheet name can have.
void SetStyle(Range cellRange, Style style)
Sets the passed style on the passed cell range. If cells are already existing, the style will be adde...
float DefaultColumnWidth
Gets or sets the default column width.
void AddCellFormula(string formula, string address, Style style)
Adds a cell formula as string to the defined cell address.
WorksheetPane
Enum to define the pane position or active pane in a slip worksheet.
@ TopRight
The pane is located in the top right of the split worksheet.
@ BottomRight
The pane is located in the bottom right of the split worksheet.
@ BottomLeft
The pane is located in the bottom left of the split worksheet.
@ TopLeft
The pane is located in the top left of the split worksheet.
void SetHorizontalSplit(float topPaneHeight, Address topLeftCell, WorksheetPane? activePane)
Sets the horizontal split of the worksheet into two panes. The measurement in characters cannot be us...
float DefaultRowHeight
Gets or sets the default Row height.
int ZoomFactor
Gets or sets the zoom factor of the ViewType of the current worksheet. If AutoZoomFactor,...
void GoToNextRow()
Moves the current position to the next row (use for a new line).
int SheetID
Gets or sets the internal ID of the worksheet.
void RemoveHiddenRow(int rowNumber)
Sets a previously defined, hidden row as visible again.
CellDirection
Enum to define the direction when using AddNextCell method.
@ RowToRow
The next cell will be on the same column (A1,A2,A3...).
@ ColumnToColumn
The next cell will be on the same row (A1,B1,C1...).
@ Disabled
The address of the next cell will be not changed when adding a cell (for manual definition of cell ad...
int GetLastColumnNumber()
Gets the last existing column number in the current worksheet (zero-based).
Dictionary< string, Cell > Cells
Gets the cells of the worksheet as dictionary with the cell address as key and the cell object as val...
WorksheetPane? ActivePane
Gets the active Pane is splitting is applied. The value is nullable. If null, no splitting was defin...
bool ShowRuler
Gets or sets whether a ruler is displayed over the column headers. This value only applies if ViewTyp...
int GetCurrentColumnNumber()
Gets the current column number (zero based).
void ClearSelectedCells()
Removes all cell selections of this worksheet.
bool UseSheetProtection
Gets or sets whether the worksheet is protected. If true, protection is enabled.
void InsertRow(int rowNumber, int numberOfNewRows)
Inserts 'count' rows below the specified 'rowNumber'. Existing cells are moved down by the number of ...
void SetSheetProtectionPassword(string password)
Sets or removes the password for worksheet protection. If set, UseSheetProtection will be also set to...
Dictionary< SheetViewType, int > ZoomFactors
Gets all defined zoom factors per SheetViewType of the current worksheet. Use SetZoomFactor(SheetView...
SheetViewType
Enum to define how a worksheet is displayed in the spreadsheet application (Excel).
@ PageBreakPreview
The worksheet is displayed with indicators where the page would break if it were printed.
@ PageLayout
The worksheet is displayed like it would be printed.
@ Normal
The worksheet is displayed without pagination (default).
void GoToNextColumn()
Moves the current position to the next column.
void AddNextCellFormula(string formula, Style style)
Adds a formula as string to the next cell position.
void SetRowHeight(int rowNumber, float height)
Sets the height of the passed row number (zero-based).
Worksheet(string name)
Constructor with worksheet name.
int GetFirstColumnNumber()
Gets the first existing column number in the current worksheet (zero-based).
void AddHiddenColumn(int columnNumber)
Sets the defined column as hidden.
CellDirection CurrentCellDirection
Gets or sets the direction when using AddNextCell method.
Cell GetCell(Address address)
Gets the cell of the specified address.
IReadOnlyList< Cell > GetRow(int rowNumber)
Gets a row as list of cell objects.
int ReplaceCellValue(object oldValue, object newValue)
Replaces all occurrences of 'oldValue' with 'newValue' and returns the number of replacements.
static readonly int MinColumnNumber
Minimum column number (zero-based) as constant.
void AddSelectedCells(string rangeOrAddress)
Adds a range or cell address to the selected cells on this worksheet.
Worksheet Copy()
Creates a (dereferenced) deep copy of this worksheet.
void SetCurrentCellAddress(int columnNumber, int rowNumber)
Set the current cell address.
string MergeCells(string cellRange)
Merges the defined cell range.
bool ShowGridLines
Gets or sets whether grid lines are visible on the current worksheet. Default is true.
IReadOnlyList< Cell > GetColumn(int columnNumber)
Gets a column as list of cell objects.
Address? GetLastDataCellAddress()
Gets the last existing cell with data in the current worksheet (bottom right).
void AddSelectedCells(Address startAddress, Address endAddress)
Adds a range to the selected cells on this worksheet.
void InsertColumn(int columnNumber, int numberOfNewColumns)
Inserts 'count' columns right of the specified 'columnNumber'. Existing cells are moved to the right ...
SheetProtectionValue
Enum to define the possible protection types when protecting a worksheet.
@ PivotTables
If selected, the user can use pivot tables if the worksheets is protected.
@ FormatCells
If selected, the user can format cells if the worksheets is protected.
@ InsertHyperlinks
If selected, the user can insert hyper links if the worksheets is protected.
@ InsertColumns
If selected, the user can insert columns if the worksheets is protected.
@ Sort
If selected, the user can sort cells if the worksheets is protected.
@ DeleteColumns
If selected, the user can delete columns if the worksheets is protected.
@ Scenarios
If selected, the user can edit scenarios if the worksheets is protected.
@ DeleteRows
If selected, the user can delete rows if the worksheets is protected.
@ FormatColumns
If selected, the user can format columns if the worksheets is protected.
@ InsertRows
If selected, the user can insert rows if the worksheets is protected.
@ FormatRows
If selected, the user can format rows if the worksheets is protected.
@ AutoFilter
If selected, the user can use auto filters if the worksheets is protected.
@ Objects
If selected, the user can edit objects if the worksheets is protected.
@ SelectUnlockedCells
If selected, the user can select unlocked cells if the worksheets is protected.
@ SelectLockedCells
If selected, the user can select locked cells if the worksheets is protected.
Style SetColumnDefaultStyle(int columnNumber, Style style)
Sets the default column style of the passed column number (zero-based).
Worksheet(string name, int id, Workbook reference)
Constructor with name and sheet ID.
void SetColumnWidth(string columnAddress, float width)
Sets the width of the passed column address.
void SetSplit(float? leftPaneWidth, float? topPaneHeight, Address topLeftCell, WorksheetPane? activePane)
Sets the horizontal and vertical split of the worksheet into four panes. The measurement in character...
Address? GetFirstCellAddress()
Gets the first existing cell in the current worksheet (bottom right).
void AddCellRange(IReadOnlyList< object > values, Range cellRange, Style style)
Adds a list of object values to a defined cell range. If the type of the particular value does not ma...
void AddHiddenColumn(string columnAddress)
Sets the defined column as hidden.
IReadOnlyList< Cell > GetColumn(string columnAddress)
Gets a column as list of cell objects.
void SetStyle(string addressExpression, Style style)
Sets the passed style on the passed address expression. Such an expression may be a single cell or a ...
static readonly float DefaultWorksheetColumnWidth
Default column width as constant.
static readonly float DefaultWorksheetRowHeight
Default row height as constant.
Address? GetLastCellAddress()
Gets the last existing cell in the current worksheet (bottom right).
bool HasCell(int columnNumber, int rowNumber)
Gets whether the specified address exists in the worksheet. Existing means that a value was stored at...
static readonly int MaxRowNumber
Maximum row number (zero-based) as constant.
int GetLastDataRowNumber()
Gets the last existing row number with data in the current worksheet (zero-based).
void ResetSplit()
Resets splitting of the worksheet into panes, as well as their freezing.
void SetCurrentCellAddress(string address)
Set the current cell address.
void RemoveSelectedCells(Address address)
Removes the given address from the selected cell ranges of this worksheet, if existing.
Address? PaneSplitTopLeftCell
Gets the Top Left cell address of the bottom right pane if applicable and splitting is applied....
void ClearActiveStyle()
Clears the active style of the worksheet. All later added calls will contain no style unless another ...
void SetHorizontalSplit(int numberOfRowsFromTop, bool freeze, Address topLeftCell, WorksheetPane? activePane)
Sets the horizontal split of the worksheet into two panes. The measurement in rows can be used to spl...
void RemoveAutoFilter()
Removes auto filters from the worksheet.
void GoToNextRow(int numberOfRows, bool keepColumnPosition=false)
Moves the current position to the next row with the number of cells to move (use for a new line).
string MergeCells(Range cellRange)
Merges the defined cell range.
bool RemoveCell(int columnNumber, int rowNumber)
Removes a previous inserted cell at the defined address.
void AddSelectedCells(Address address)
Adds a single cell address to the selected cells on this worksheet.
void SetSplit(int? numberOfColumnsFromLeft, int? numberOfRowsFromTop, bool freeze, Address topLeftCell, WorksheetPane? activePane)
Sets the horizontal and vertical split of the worksheet into four panes. The measurement in rows and ...
Style SetColumnDefaultStyle(string columnAddress, Style style)
Sets the default column style of the passed column address.
void RemoveSelectedCells(String rangeOrAddress)
Removes the given range or cell address from the selected cell ranges of this worksheet,...
void AddCellRange(IReadOnlyList< object > values, Range cellRange)
Adds a list of object values to a defined cell range. If the type of the particular value does not ma...
void AddAllowedActionOnSheetProtection(SheetProtectionValue typeOfProtection)
Method to add allowed actions if the worksheet is protected. If one or more values are added,...
void SetAutoFilter(string range)
Sets the column auto filter within the defined column range.
static readonly int MaxColumnNumber
Maximum column number (zero-based) as constant.
void AddCellFormula(string formula, string address)
Adds a cell formula as string to the defined cell address.
void SetVerticalSplit(float leftPaneWidth, Address topLeftCell, WorksheetPane? activePane)
Sets the vertical split of the worksheet into two panes. The measurement in characters cannot be used...
void AddCell(object value, int columnNumber, int rowNumber)
Adds an object to the defined cell address. If the type of the value does not match with one of the s...
void SetCurrentColumnNumber(int columnNumber)
Sets the current column number (zero based).
Address? GetFirstDataCellAddress()
Gets the first existing cell with data in the current worksheet (bottom right).
void SetVerticalSplit(int numberOfColumnsFromLeft, bool freeze, Address topLeftCell, WorksheetPane? activePane)
Sets the vertical split of the worksheet into two panes. The measurement in columns can be used to sp...
SheetViewType ViewType
Gets or sets how the current worksheet is displayed in the spreadsheet application (Excel).
string SheetName
Gets or sets the name of the worksheet.
void AddCellFormula(string formula, int columnNumber, int rowNumber)
Adds a cell formula as string to the defined cell address.
bool HasCell(Address address)
Gets whether the specified address exists in the worksheet. Existing means that a value was stored at...
Workbook WorkbookReference
Gets or sets the Reference to the parent Workbook.
const int AutoZoomFactor
Automatic zoom factor of a worksheet.
float? PaneSplitTopHeight
Gets the height of the upper, horizontal split pane, measured from the top of the window....
Address? PaneSplitAddress
Gets the split address for frozen panes or if pane split was defined in number of columns and / or ro...
Cell FirstOrDefaultCell(Func< Cell, bool > predicate)
Searches for the first occurrence of the expression. Example: var cell = worksheet....
Worksheet()
Default Constructor.
void RemoveSelectedCells(Range range)
Removes the given range from the selected cell ranges of this worksheet, if existing....
List< Range > SelectedCells
Gets the cell ranges of selected cells of this worksheet. Returns ans empty list if no cells are sele...
void SetSheetName(string name)
Validates and sets the worksheet name.
int GetLastDataColumnNumber()
Gets the last existing column number with data in the current worksheet (zero-based).
string MergeCells(Address startAddress, Address endAddress)
Merges the defined cell range.
void AddCellRange(IReadOnlyList< object > values, Address startAddress, Address endAddress, Style style)
Adds a list of object values to a defined cell range. If the type of the particular value does not ma...
int GetFirstRowNumber()
Gets the first existing row number in the current worksheet (zero-based).
void SetActiveStyle(Style style)
Sets the active style of the worksheet. This style will be assigned to all later added cells.
int GetFirstDataColumnNumber()
Gets the first existing column number with data in the current worksheet (zero-based).
List< SheetProtectionValue > SheetProtectionValues
Gets the list of SheetProtectionValues. These values define the allowed actions if the worksheet is p...
void SetZoomFactor(SheetViewType sheetViewType, int zoomFactor)
Sets a zoom factor for a given SheetViewType. If AutoZoomFactor, the zoom factor is set to automatic.
static string SanitizeWorksheetName(string input, Workbook workbook)
Sanitizes a worksheet name.
void SetStyle(Address address, Style style)
Sets the passed style on the passed (singular) cell address. If the cell is already existing,...
void AddHiddenRow(int rowNumber)
Sets the defined row as hidden.
void AddCell(object value, string address)
Adds an object to the defined cell address. If the type of the value does not match with one of the s...
static readonly float MinColumnWidth
Minimum column width as constant.
void RemoveMergedCells(string range)
Removes the defined merged cell range.
static readonly int MinRowNumber
Minimum row number (zero-based) as constant.
void AddNextCell(object value, Style style)
Adds an object to the next cell position. If the type of the value does not match with one of the sup...
Dictionary< int, float > RowHeights
Gets defined row heights as dictionary with the zero-based row number as key and the height (float fr...
void AddCell(object value, string address, Style style)
Adds an object to the defined cell address. If the type of the value does not match with one of the s...
void AddCellRange(IReadOnlyList< object > values, Address startAddress, Address endAddress)
Adds a list of object values to a defined cell range. If the type of the particular value does not ma...
bool ShowRowColumnHeaders
Gets or sets whether the column and row headers are visible on the current worksheet....
virtual IPassword SheetProtectionPassword
Password instance of the worksheet protection. If a password was set, the pain text representation an...
const int maxZoomFactor
Maximum zoom factor of a worksheet.
void SetColumnWidth(int columnNumber, float width)
Sets the width of the passed column number (zero-based).
static readonly float MaxColumnWidth
Maximum column width as constant.
Dictionary< string, Range > MergedCells
Gets the merged cells (only references) as dictionary with the cell address as key and the range obje...
void SetSheetName(string name, bool sanitize)
Sets the name of the worksheet.
bool? FreezeSplitPanes
Gets whether split panes are frozen. The value is nullable. If null, no freezing is applied....
void AddSelectedCells(Range range)
Adds a range to the selected cells on this worksheet.
void AddCellRange(IReadOnlyList< object > values, string cellRange, Style style)
Adds a list of object values to a defined cell range. If the type of the particular value does not ma...
void AddCellRange(IReadOnlyList< object > values, string cellRange)
Adds a list of object values to a defined cell range. If the type of the particular value does not ma...
void AddNextCell(object value)
Adds an object to the next cell position. If the type of the value does not match with one of the sup...
void RemoveHiddenColumn(int columnNumber)
Sets a previously defined, hidden column as visible again.
void RemoveHiddenColumn(string columnAddress)
Sets a previously defined, hidden column as visible again.
Range? AutoFilterRange
Gets the range of the auto-filter. Wrapped to Nullable to provide null as value. If null,...
const int MinZoomFactor
Minimum zoom factor of a worksheet. If set to this value, the zoom is set to automatic.
bool RemoveCell(string address)
Removes a previous inserted cell at the defined address.
int GetLastRowNumber()
Gets the last existing row number in the current worksheet (zero-based).
void ResetColumn(int columnNumber)
Resets the defined column, if existing. The corresponding instance will be removed from Columns.
void SetCurrentRowNumber(int rowNumber)
Sets the current row number (zero based).
void AddCell(object value, int columnNumber, int rowNumber, Style style)
Adds an object to the defined cell address. If the type of the value does not match with one of the s...
void AddNextCellFormula(string formula)
Adds a formula as string to the next cell position.
void RemoveAllowedActionOnSheetProtection(SheetProtectionValue value)
Removes an allowed action on the current worksheet or its cells.
int GetCurrentRowNumber()
Gets the current row number (zero based).
static readonly float MinRowHeight
Minimum row height as constant.
List< Cell > CellsByValue(object searchValue)
Searches for cells that contain the specified value and returns a list of these cells.
Style ActiveStyle
Gets the active Style of the worksheet. If null, no style is defined as active.
static readonly float MaxRowHeight
Maximum row height as constant.
void AddCellFormula(string formula, int columnNumber, int rowNumber, Style style)
Adds a cell formula as string to the defined cell address.
void RemoveRowHeight(int rowNumber)
Removes the defined, non-standard row height.
void SetStyle(Address startAddress, Address endAddress, Style style)
Sets the passed style on the passed cell range, derived from a start and end address....
void SetAutoFilter(int startColumn, int endColumn)
Sets the column auto filter within the defined column range.
void GoToNextColumn(int numberOfColumns, bool keepRowPosition=false)
Moves the current position to the next column with the number of cells to move.
bool Hidden
gets or sets whether the worksheet is hidden. If true, the worksheet is not listed in the worksheet t...
void RemoveSelectedCells(Address startAddress, Address endAddress)
Removes the given range from the selected cell ranges of this worksheet, if existing.
Dictionary< int, Column > Columns
Gets all columns with non-standard properties, like auto filter applied or a special width as diction...
float? PaneSplitLeftWidth
Gets the width of the left, vertical split pane, measured from the left of the window....
Cell GetCell(int columnNumber, int rowNumber)
Gets the cell of the specified column and row number (zero-based).
Interface to represent a protection password, either for workbooks or worksheets. The implementations...
Struct representing the cell address as column and row (zero based).
int Row
Row number (zero based).
string GetAddress()
Returns the combined Address.
int Column
Column number (zero based).
Struct representing a cell range with a start and end address.
IReadOnlyList< Address > ResolveEnclosedAddresses()
Gets a list of all addresses between the start and end address.
Address StartAddress
Start address of the range.
Address EndAddress
End address of the range.