NanoXLSX.Core 3.0.0-rc.5
Loading...
Searching...
No Matches
Worksheet.cs
1/*
2 * NanoXLSX is a small .NET library to generate and read XLSX (Microsoft Excel 2007 or newer) files in an easy and native way
3 * Copyright Raphael Stoeckli © 2026
4 * This library is licensed under the MIT License.
5 * You find a copy of the license in project folder or on: http://opensource.org/licenses/MIT
6 */
7
8using System;
9using System.Collections.Generic;
10using System.Linq;
11using System.Text;
12using System.Text.RegularExpressions;
16using NanoXLSX.Styles;
17using NanoXLSX.Utils;
19
20namespace NanoXLSX
21{
25 public class Worksheet
26 {
27 static Worksheet()
28 {
30 }
31
32 #region constants
36 public static readonly int MaxWorksheetNameLength = 31;
40 public static readonly float DefaultWorksheetColumnWidth = 10f;
44 public static readonly float DefaultWorksheetRowHeight = 15f;
48 public static readonly int MaxColumnNumber = 16383;
52#pragma warning disable CA1805 // Do not initialize unnecessarily
53 public static readonly int MinColumnNumber = 0;
54#pragma warning restore CA1805
58#pragma warning disable CA1805 // Do not initialize unnecessarily
59 public static readonly float MinColumnWidth = 0f;
60#pragma warning restore CA1805
64#pragma warning disable CA1805 // Do not initialize unnecessarily
65 public static readonly float MinRowHeight = 0f;
66#pragma warning restore CA1805
70 public static readonly float MaxColumnWidth = 255f;
74 public static readonly int MaxRowNumber = 1048575;
78#pragma warning disable CA1805 // Do not initialize unnecessarily
79 public static readonly int MinRowNumber = 0;
80#pragma warning restore CA1805
84 public static readonly float MaxRowHeight = 409.5f;
88#pragma warning disable CA1805 // Do not initialize unnecessarily
89 public const int AutoZoomFactor = 0;
90#pragma warning restore CA1805
94 public const int MinZoomFactor = 10;
98 public const int maxZoomFactor = 400;
99 #endregion
100
101 #region enums
114
152
167
180 #endregion
181
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;
197 private bool hidden;
198 private Workbook workbookReference;
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;
206 private WorksheetPane? activePane;
207 private int sheetID;
208 private SheetViewType viewType;
209 private Dictionary<SheetViewType, int> zoomFactor;
210 #endregion
211
212 #region properties
217 {
218 get { return autoFilterRange; }
219 }
220
224 public Dictionary<string, Cell> Cells
225 {
226 get { return cells; }
227 }
228
232 public Dictionary<int, Column> Columns
233 {
234 get { return columns; }
235 }
236
241
247 {
248 get { return defaultColumnWidth; }
249 set
250 {
251 if (value < MinColumnWidth || value > MaxColumnWidth)
252 {
253 throw new RangeException("The passed default column width is out of range (" + MinColumnWidth + " to " + MaxColumnWidth + ")");
254 }
255 defaultColumnWidth = value;
256 }
257 }
258
263 public float DefaultRowHeight
264 {
265 get { return defaultRowHeight; }
266 set
267 {
268 if (value < MinRowHeight || value > MaxRowHeight)
269 {
270 throw new RangeException("The passed default row height is out of range (" + MinRowHeight + " to " + MaxRowHeight + ")");
271 }
272 defaultRowHeight = value;
273 }
274 }
275
280 public Dictionary<int, bool> HiddenRows
281 {
282 get { return hiddenRows; }
283 }
284
288 public Dictionary<int, float> RowHeights
289 {
290 get { return rowHeights; }
291 }
292
296 public Dictionary<string, Range> MergedCells
297 {
298 get { return mergedCells; }
299 }
300
304 public List<Range> SelectedCells
305 {
306 get { return selectedCells; }
307 }
308
312 public int SheetID
313 {
314 get => sheetID;
315 set
316 {
317 if (value < 1)
318 {
319 throw new FormatException("The ID " + value + " is invalid. Worksheet IDs must be >0");
320 }
321 sheetID = value;
322 }
323 }
324
328 public string SheetName
329 {
330 get { return sheetName; }
331 set { SetSheetName(value); }
332 }
333
339 {
340 get { return sheetProtectionPassword; }
341 internal set { sheetProtectionPassword = value; }
342 }
343
347 public List<SheetProtectionValue> SheetProtectionValues
348 {
349 get { return sheetProtectionValues; }
350 }
351
355 public bool UseSheetProtection { get; set; }
356
361 {
362 get { return workbookReference; }
363 set
364 {
365 workbookReference = value;
366 if (value != null)
367 {
368 workbookReference.ValidateWorksheets();
369 }
370 }
371 }
372
378 public bool Hidden
379 {
380 get { return hidden; }
381 set
382 {
383 hidden = value;
384 if (value && workbookReference != null)
385 {
386 workbookReference.ValidateWorksheets();
387 }
388 }
389 }
390
399 public float? PaneSplitTopHeight
400 {
401 get { return paneSplitTopHeight; }
402 }
403
412 public float? PaneSplitLeftWidth
413 {
414 get { return paneSplitLeftWidth; }
415 }
416
421 public bool? FreezeSplitPanes
422 {
423 get { return freezeSplitPanes; }
424 }
425
432 {
433 get { return paneSplitTopLeftCell; }
434 }
435
444 {
445 get { return paneSplitAddress; }
446 }
447
448
454 {
455 get { return activePane; }
456 }
457
462 {
463 get { return activeStyle; }
464 }
465
469 public bool ShowGridLines { get; set; }
470
474 public bool ShowRowColumnHeaders { get; set; }
475
479 public bool ShowRuler { get; set; }
480
485 {
486 get
487 {
488 return viewType;
489 }
490 set
491 {
492 viewType = value;
493 SetZoomFactor(value, 100);
494 }
495 }
496
502 public int ZoomFactor
503 {
504 set
505 {
506 SetZoomFactor(viewType, value);
507 }
508 get
509 {
510 return zoomFactor[viewType];
511 }
512 }
513
517 public Dictionary<SheetViewType, int> ZoomFactors
518 {
519 get
520 {
521 return zoomFactor;
522 }
523 }
524
525
526 #endregion
527
528
529 #region constructors
533 public Worksheet()
534 {
535 CurrentCellDirection = CellDirection.ColumnToColumn;
536 cells = new Dictionary<string, Cell>();
537 currentRowNumber = 0;
538 currentColumnNumber = 0;
539 defaultColumnWidth = DefaultWorksheetColumnWidth;
540 defaultRowHeight = DefaultWorksheetRowHeight;
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>();
547 activeStyle = null;
548 workbookReference = null;
549 viewType = SheetViewType.Normal;
550 zoomFactor = new Dictionary<SheetViewType, int>
551 {
552 { viewType, 100 }
553 };
554 ShowGridLines = true;
556 ShowRuler = true;
557 sheetProtectionPassword = new LegacyPassword(LegacyPassword.PasswordType.WorksheetProtection);
558 }
559
564 public Worksheet(string name)
565 : this()
566 {
567 SetSheetName(name);
568 }
569
576 public Worksheet(string name, int id, Workbook reference)
577 : this()
578 {
579 SetSheetName(name);
580 SheetID = id;
581 workbookReference = reference;
582 }
583
584 #endregion
585
586 #region methods_AddNextCell
587
596 public void AddNextCell(object value)
597 {
598 AddNextCell(CastValue(value, currentColumnNumber, currentRowNumber), true, null);
599 }
600
601
612 public void AddNextCell(object value, Style style)
613 {
614 AddNextCell(CastValue(value, currentColumnNumber, currentRowNumber), true, style);
615 }
616
617
627 private void AddNextCell(Cell cell, bool incremental, Style style)
628 {
629 // date and time styles are already defined by the passed cell object
630 if (style != null || (activeStyle != null && useActiveStyle))
631 {
632 if (cell.CellStyle == null && useActiveStyle)
633 {
634 cell.SetStyle(activeStyle);
635 }
636 else if (cell.CellStyle == null && style != null)
637 {
638 cell.SetStyle(style);
639 }
640 else if (cell.CellStyle != null && useActiveStyle)
641 {
642 Style mixedStyle = (Style)cell.CellStyle.Copy();
643 mixedStyle.Append(activeStyle);
644 cell.SetStyle(mixedStyle);
645 }
646 else if (cell.CellStyle != null && style != null)
647 {
648 Style mixedStyle = (Style)cell.CellStyle.Copy();
649 mixedStyle.Append(style);
650 cell.SetStyle(mixedStyle);
651 }
652 }
653 string address = cell.CellAddress;
654 if (cells.ContainsKey(address))
655 {
656 cells[address] = cell;
657 }
658 else
659 {
660 cells.Add(address, cell);
661 }
662 if (incremental)
663 {
664 if (CurrentCellDirection == CellDirection.ColumnToColumn)
665 {
666 currentColumnNumber++;
667 }
668 else if (CurrentCellDirection == CellDirection.RowToRow)
669 {
670 currentRowNumber++;
671 }
672 else
673 {
674 // disabled / no-op
675 }
676 }
677 else
678 {
679 if (CurrentCellDirection == CellDirection.ColumnToColumn)
680 {
681 currentColumnNumber = cell.ColumnNumber + 1;
682 currentRowNumber = cell.RowNumber;
683 }
684 else if (CurrentCellDirection == CellDirection.RowToRow)
685 {
686 currentColumnNumber = cell.ColumnNumber;
687 currentRowNumber = cell.RowNumber + 1;
688 }
689 else
690 {
691 // disabled / no-op
692 }
693 }
694 }
695
703 private static Cell CastValue(object value, int column, int row)
704 {
705 Cell c;
706 if (value != null && value.GetType() == typeof(Cell))
707 {
708 c = (Cell)value;
709 c.CellAddress2 = new Address(column, row);
710 }
711 else
712 {
713 c = new Cell(value, Cell.CellType.Default, column, row);
714 }
715 return c;
716 }
717
718
719 #endregion
720
721 #region methods_AddCell
722
733 public void AddCell(object value, int columnNumber, int rowNumber)
734 {
735 AddNextCell(CastValue(value, columnNumber, rowNumber), false, null);
736 }
737
750 public void AddCell(object value, int columnNumber, int rowNumber, Style style)
751 {
752 AddNextCell(CastValue(value, columnNumber, rowNumber), false, style);
753 }
754
755
766 public void AddCell(object value, string address)
767 {
768 int column;
769 int row;
770 Cell.ResolveCellCoordinate(address, out column, out row);
771 AddCell(value, column, row);
772 }
773
786 public void AddCell(object value, string address, Style style)
787 {
788 int column;
789 int row;
790 Cell.ResolveCellCoordinate(address, out column, out row);
791 AddCell(value, column, row, style);
792 }
793
794 #endregion
795
796 #region methods_AddCellFormula
797
805 public void AddCellFormula(string formula, string address)
806 {
807 int column;
808 int row;
809 Cell.ResolveCellCoordinate(address, out column, out row);
810 Cell c = new Cell(formula, Cell.CellType.Formula, column, row);
811 AddNextCell(c, false, null);
812 }
813
823 public void AddCellFormula(string formula, string address, Style style)
824 {
825 int column;
826 int row;
827 Cell.ResolveCellCoordinate(address, out column, out row);
828 Cell c = new Cell(formula, Cell.CellType.Formula, column, row);
829 AddNextCell(c, false, style);
830 }
831
839 public void AddCellFormula(string formula, int columnNumber, int rowNumber)
840 {
841 Cell c = new Cell(formula, Cell.CellType.Formula, columnNumber, rowNumber);
842 AddNextCell(c, false, null);
843 }
844
853 public void AddCellFormula(string formula, int columnNumber, int rowNumber, Style style)
854 {
855 Cell c = new Cell(formula, Cell.CellType.Formula, columnNumber, rowNumber);
856 AddNextCell(c, false, style);
857 }
858
864 public void AddNextCellFormula(string formula)
865 {
866 Cell c = new Cell(formula, Cell.CellType.Formula, currentColumnNumber, currentRowNumber);
867 AddNextCell(c, true, null);
868 }
869
876 public void AddNextCellFormula(string formula, Style style)
877 {
878 Cell c = new Cell(formula, Cell.CellType.Formula, currentColumnNumber, currentRowNumber);
879 AddNextCell(c, true, style);
880 }
881
882 #endregion
883
884 #region methods_AddCellRange
885
896 public void AddCellRange(IReadOnlyList<object> values, Address startAddress, Address endAddress)
897 {
898 AddCellRangeInternal(values, startAddress, endAddress, null);
899 }
900
913 public void AddCellRange(IReadOnlyList<object> values, Address startAddress, Address endAddress, Style style)
914 {
915 AddCellRangeInternal(values, startAddress, endAddress, style);
916 }
917
928 public void AddCellRange(IReadOnlyList<object> values, string cellRange)
929 {
930 Range range = Cell.ResolveCellRange(cellRange);
931 AddCellRangeInternal(values, range.StartAddress, range.EndAddress, null);
932 }
933
946 public void AddCellRange(IReadOnlyList<object> values, string cellRange, Style style)
947 {
948 Range range = Cell.ResolveCellRange(cellRange);
949 AddCellRangeInternal(values, range.StartAddress, range.EndAddress, style);
950 }
951
961 public void AddCellRange(IReadOnlyList<object> values, Range cellRange)
962 {
963 AddCellRangeInternal(values, cellRange.StartAddress, cellRange.EndAddress, null);
964 }
965
977 public void AddCellRange(IReadOnlyList<object> values, Range cellRange, Style style)
978 {
979 AddCellRangeInternal(values, cellRange.StartAddress, cellRange.EndAddress, style);
980 }
981
993 private void AddCellRangeInternal<T>(IReadOnlyList<T> values, Address startAddress, Address endAddress, Style style)
994 {
995 if (values == null)
996 {
997 throw new RangeException("The passed value list cannot be null");
998 }
999 List<Address> addresses = Cell.GetCellRange(startAddress, endAddress) as List<Address>;
1000 if (values.Count != addresses.Count)
1001 {
1002 throw new RangeException("The number of passed values (" + values.Count + ") differs from the number of cells within the range (" + addresses.Count + ")");
1003 }
1004 List<Cell> list = Cell.ConvertArray(values) as List<Cell>;
1005 int len = values.Count;
1006 for (int i = 0; i < len; i++)
1007 {
1008 list[i].RowNumber = addresses[i].Row;
1009 list[i].ColumnNumber = addresses[i].Column;
1010 AddNextCell(list[i], false, style);
1011 }
1012 }
1013 #endregion
1014
1015 #region methods_RemoveCell
1023 public bool RemoveCell(int columnNumber, int rowNumber)
1024 {
1025 string address = Cell.ResolveCellAddress(columnNumber, rowNumber);
1026 return cells.Remove(address);
1027 }
1028
1036 public bool RemoveCell(string address)
1037 {
1038 int row;
1039 int column;
1040 Cell.ResolveCellCoordinate(address, out column, out row);
1041 return RemoveCell(column, row);
1042 }
1043 #endregion
1044
1045 #region methods_setStyle
1046
1054 public void SetStyle(Range cellRange, Style style)
1055 {
1056 IReadOnlyList<Address> addresses = cellRange.ResolveEnclosedAddresses();
1057 foreach (Address address in addresses)
1058 {
1059 string key = address.GetAddress();
1060 if (this.cells.ContainsKey(key))
1061 {
1062 if (style == null)
1063 {
1064 cells[key].RemoveStyle();
1065 }
1066 else
1067 {
1068 cells[key].SetStyle(style);
1069 }
1070 }
1071 else
1072 {
1073 if (style != null)
1074 {
1075 AddCell(null, address.Column, address.Row, style);
1076 }
1077 }
1078 }
1079 }
1080
1089 public void SetStyle(Address startAddress, Address endAddress, Style style)
1090 {
1091 SetStyle(new Range(startAddress, endAddress), style);
1092 }
1093
1101 public void SetStyle(Address address, Style style)
1102 {
1103 SetStyle(address, address, style);
1104 }
1105
1114 public void SetStyle(string addressExpression, Style style)
1115 {
1116 Cell.AddressScope scope = Cell.GetAddressScope(addressExpression);
1117 if (scope == Cell.AddressScope.SingleAddress)
1118 {
1119 Address address = new Address(addressExpression);
1120 SetStyle(address, style);
1121 }
1122 else if (scope == Cell.AddressScope.Range)
1123 {
1124 Range range = new Range(addressExpression);
1125 SetStyle(range, style);
1126 }
1127 else
1128 {
1129 throw new FormatException("The passed address'" + addressExpression + "' is neither a cell address, nor a range");
1130 }
1131 }
1132
1133 #endregion
1134
1135 #region boundaryFunctions
1143 {
1144 return GetBoundaryNumber(false, true);
1145 }
1146
1154 {
1155 return GetBoundaryDataNumber(false, true, true);
1156 }
1157
1165 {
1166 return GetBoundaryNumber(true, true);
1167 }
1168
1176 {
1177 return GetBoundaryDataNumber(true, true, true);
1178 }
1179
1188 {
1189 return GetBoundaryNumber(false, false);
1190 }
1191
1199 {
1200 return GetBoundaryDataNumber(false, false, true);
1201 }
1202
1210 public int GetLastRowNumber()
1211 {
1212 return GetBoundaryNumber(true, false);
1213 }
1214
1215
1223 {
1224 return GetBoundaryDataNumber(true, false, true);
1225 }
1226
1234
1236 {
1237 int lastRow = GetLastRowNumber();
1238 int lastColumn = GetLastColumnNumber();
1239 if (lastRow < 0 || lastColumn < 0)
1240 {
1241 return null;
1242 }
1243 return new Address(lastColumn, lastRow);
1244 }
1245
1252
1254 {
1255 int lastRow = GetLastDataRowNumber();
1256 int lastColumn = GetLastDataColumnNumber();
1257 if (lastRow < 0 || lastColumn < 0)
1258 {
1259 return null;
1260 }
1261 return new Address(lastColumn, lastRow);
1262 }
1263
1271 {
1272 int firstRow = GetFirstRowNumber();
1273 int firstColumn = GetFirstColumnNumber();
1274 if (firstRow < 0 || firstColumn < 0)
1275 {
1276 return null;
1277 }
1278 return new Address(firstColumn, firstRow);
1279 }
1280
1288 {
1289 int firstRow = GetFirstDataRowNumber();
1290 int firstColumn = GetFirstDataColumnNumber();
1291 if (firstRow < 0 || firstColumn < 0)
1292 {
1293 return null;
1294 }
1295 return new Address(firstColumn, firstRow);
1296 }
1297
1305 private int GetBoundaryDataNumber(bool row, bool min, bool ignoreEmpty)
1306 {
1307 if (cells.Count == 0)
1308 {
1309 return -1;
1310 }
1311 if (!ignoreEmpty)
1312 {
1313 if (row && min)
1314 {
1315 return cells.Min(x => x.Value.RowNumber);
1316 }
1317 else if (row)
1318 {
1319 return cells.Max(x => x.Value.RowNumber);
1320 }
1321 else if (min)
1322 {
1323 return cells.Min(x => x.Value.ColumnNumber);
1324 }
1325 else
1326 {
1327 return cells.Max(x => x.Value.ColumnNumber);
1328 }
1329 }
1330 List<Cell> nonEmptyCells = cells.Values.Where(x => x.Value != null && x.Value.ToString() != string.Empty).ToList();
1331 if (nonEmptyCells.Count == 0)
1332 {
1333 return -1;
1334 }
1335 if (row && min)
1336 {
1337 return nonEmptyCells.Min(x => x.RowNumber);
1338 }
1339 else if (row)
1340 {
1341 return nonEmptyCells.Max(x => x.RowNumber);
1342 }
1343 else if (min)
1344 {
1345 return nonEmptyCells.Min(x => x.ColumnNumber);
1346 }
1347 else
1348 {
1349 return nonEmptyCells.Max(x => x.ColumnNumber);
1350 }
1351 }
1352
1359 private int GetBoundaryNumber(bool row, bool min)
1360 {
1361 int cellBoundary = GetBoundaryDataNumber(row, min, false);
1362 if (row)
1363 {
1364 int heightBoundary = -1;
1365 if (rowHeights.Count > 0)
1366 {
1367 heightBoundary = min ? RowHeights.Min(x => x.Key) : RowHeights.Max(x => x.Key);
1368 }
1369 int hiddenBoundary = -1;
1370 if (hiddenRows.Count > 0)
1371 {
1372 hiddenBoundary = min ? HiddenRows.Min(x => x.Key) : HiddenRows.Max(x => x.Key);
1373 }
1374 return min ? GetMinRow(cellBoundary, heightBoundary, hiddenBoundary) : GetMaxRow(cellBoundary, heightBoundary, hiddenBoundary);
1375 }
1376 else
1377 {
1378 int columnDefBoundary = -1;
1379 if (columns.Count > 0)
1380 {
1381 columnDefBoundary = min ? Columns.Min(x => x.Key) : Columns.Max(x => x.Key);
1382 }
1383 if (min)
1384 {
1385 return cellBoundary >= 0 && cellBoundary < columnDefBoundary ? cellBoundary : columnDefBoundary;
1386 }
1387 else
1388 {
1389 return cellBoundary >= 0 && cellBoundary > columnDefBoundary ? cellBoundary : columnDefBoundary;
1390 }
1391 }
1392 }
1393
1401 private static int GetMaxRow(int cellBoundary, int heightBoundary, int hiddenBoundary)
1402 {
1403 int highest = -1;
1404 if (cellBoundary >= 0)
1405 {
1406 highest = cellBoundary;
1407 }
1408 if (heightBoundary >= 0 && heightBoundary > highest)
1409 {
1410 highest = heightBoundary;
1411 }
1412 if (hiddenBoundary >= 0 && hiddenBoundary > highest)
1413 {
1414 highest = hiddenBoundary;
1415 }
1416 return highest;
1417 }
1418
1426 private static int GetMinRow(int cellBoundary, int heightBoundary, int hiddenBoundary)
1427 {
1428 int lowest = int.MaxValue;
1429 if (cellBoundary >= 0)
1430 {
1431 lowest = cellBoundary;
1432 }
1433 if (heightBoundary >= 0 && heightBoundary < lowest)
1434 {
1435 lowest = heightBoundary;
1436 }
1437 if (hiddenBoundary >= 0 && hiddenBoundary < lowest)
1438 {
1439 lowest = hiddenBoundary;
1440 }
1441 return lowest == int.MaxValue ? -1 : lowest;
1442 }
1443 #endregion
1444
1445 #region Insert-Search-Replace
1446
1455 public void InsertRow(int rowNumber, int numberOfNewRows)
1456 {
1457 // All cells below the first row must receive a new address (row + count);
1458 var upperRow = this.GetRow(rowNumber);
1459
1460 // Identify all cells below the insertion point to adjust their addresses
1461 var cellsToChange = this.Cells.Where(c => c.Value.CellAddress2.Row > rowNumber).ToList();
1462
1463 // Make a copy of the cells to be moved and then delete the original cells;
1464 Dictionary<string, Cell> newCells = new Dictionary<string, Cell>();
1465 foreach (var cell in cellsToChange)
1466 {
1467 var row = cell.Value.CellAddress2.Row;
1468 var col = cell.Value.CellAddress2.Column;
1469 Address newAddress = new Address(col, row + numberOfNewRows);
1470
1471 Cell newCell = new Cell(cell.Value.Value, cell.Value.DataType, newAddress);
1472 if (cell.Value.CellStyle != null)
1473 {
1474 newCell.SetStyle(cell.Value.CellStyle); // Apply the style from the "old" cell.
1475 }
1476 newCells.Add(newAddress.GetAddress(), newCell);
1477
1478 // Delete the original cells since the key cannot be changed.
1479 this.Cells.Remove(cell.Key);
1480 }
1481
1482 // Fill the gap with new cells, using the same style as the first row.
1483 foreach (Cell cell in upperRow)
1484 {
1485 for (int i = 0; i < numberOfNewRows; i++)
1486 {
1487 Address newAddress = new Address(cell.CellAddress2.Column, cell.CellAddress2.Row + 1 + i);
1488 Cell newCell = new Cell(null, Cell.CellType.Empty, newAddress);
1489 if (cell.CellStyle != null)
1490 newCell.SetStyle(cell.CellStyle);
1491 this.Cells.Add(newAddress.GetAddress(), newCell);
1492 }
1493 }
1494
1495 // Re-add the previous cells from the copy back with a new key.
1496 foreach (KeyValuePair<string, Cell> cellKeyValue in newCells)
1497 {
1498 this.Cells.Add(cellKeyValue.Key, cellKeyValue.Value); //cell.Value is the cell incl. Style etc.
1499 }
1500 }
1501
1510 public void InsertColumn(int columnNumber, int numberOfNewColumns)
1511 {
1512 var leftColumn = this.GetColumn(columnNumber);
1513 var cellsToChange = this.Cells.Where(c => c.Value.CellAddress2.Column > columnNumber).ToList();
1514
1515 Dictionary<string, Cell> newCells = new Dictionary<string, Cell>();
1516 foreach (var cell in cellsToChange)
1517 {
1518 var row = cell.Value.CellAddress2.Row;
1519 var col = cell.Value.CellAddress2.Column;
1520 Address newAddress = new Address(col + numberOfNewColumns, row);
1521
1522 Cell newCell = new Cell(cell.Value.Value, cell.Value.DataType, newAddress);
1523 if (cell.Value.CellStyle != null)
1524 {
1525 newCell.SetStyle(cell.Value.CellStyle); // Apply the style from the "old" cell.
1526 }
1527 newCells.Add(newAddress.GetAddress(), newCell);
1528
1529 // Delete the original cells since the key cannot be changed.
1530 this.Cells.Remove(cell.Key);
1531 }
1532
1533 // Fill the gap with new cells, using the same style as the first row.
1534 foreach (Cell cell in leftColumn)
1535 {
1536 for (int i = 0; i < numberOfNewColumns; i++)
1537 {
1538 Address newAddress = new Address(cell.CellAddress2.Column + 1 + i, cell.CellAddress2.Row);
1539 Cell newCell = new Cell(null, Cell.CellType.Empty, newAddress);
1540 if (cell.CellStyle != null)
1541 newCell.SetStyle(cell.CellStyle);
1542 this.Cells.Add(newAddress.GetAddress(), newCell);
1543 }
1544 }
1545
1546 // Re-add the previous cells from the copy back with a new key.
1547 foreach (KeyValuePair<string, Cell> cellKeyValue in newCells)
1548 {
1549 this.Cells.Add(cellKeyValue.Key, cellKeyValue.Value); //cell.Value is the cell incl. Style etc.
1550 }
1551 }
1552
1558 public Cell FirstCellByValue(object searchValue)
1559 {
1560 var cell = this.Cells.FirstOrDefault(c =>
1561 Equals(c.Value.Value, searchValue))
1562 .Value;
1563 return cell;
1564 }
1565
1572 public Cell FirstOrDefaultCell(Func<Cell, bool> predicate)
1573 {
1574 return this.Cells.Values
1575 .FirstOrDefault(c => c != null && (c.Value == null || predicate(c)));
1576 }
1577
1583 public List<Cell> CellsByValue(object searchValue)
1584 {
1585 return this.Cells.Where(c =>
1586 Equals(c.Value.Value, searchValue))
1587 .Select(c => c.Value)
1588 .ToList();
1589 }
1590
1597 public int ReplaceCellValue(object oldValue, object newValue)
1598 {
1599 int count = 0;
1600 List<Cell> foundCells = this.CellsByValue(oldValue);
1601 foreach (var cell in foundCells)
1602 {
1603 cell.Value = newValue;
1604 count++;
1605 }
1606 return count;
1607 }
1608 #endregion
1609
1610 #region common_methods
1611
1618 {
1619 if (!sheetProtectionValues.Contains(typeOfProtection))
1620 {
1621 if (typeOfProtection == SheetProtectionValue.SelectLockedCells && !sheetProtectionValues.Contains(SheetProtectionValue.SelectUnlockedCells))
1622 {
1623 sheetProtectionValues.Add(SheetProtectionValue.SelectUnlockedCells);
1624 }
1625 sheetProtectionValues.Add(typeOfProtection);
1626 UseSheetProtection = true;
1627 }
1628 }
1629
1635 public void AddHiddenColumn(int columnNumber)
1636 {
1637 SetColumnHiddenState(columnNumber, true);
1638 }
1639
1645 public void AddHiddenColumn(string columnAddress)
1646 {
1647 int columnNumber = Cell.ResolveColumn(columnAddress);
1648 SetColumnHiddenState(columnNumber, true);
1649 }
1650
1656 public void AddHiddenRow(int rowNumber)
1657 {
1658 SetRowHiddenState(rowNumber, true);
1659 }
1660
1664 public void ClearActiveStyle()
1665 {
1666 useActiveStyle = false;
1667 activeStyle = null;
1668 }
1669
1676 public Cell GetCell(Address address)
1677 {
1678 if (!cells.ContainsKey(address.GetAddress()))
1679 {
1680 throw new WorksheetException("The cell with the address " + address.GetAddress() + " does not exist in this worksheet");
1681 }
1682 return cells[address.GetAddress()];
1683 }
1684
1692 public Cell GetCell(int columnNumber, int rowNumber)
1693 {
1694 return GetCell(new Address(columnNumber, rowNumber));
1695 }
1696
1704 public bool HasCell(Address address)
1705 {
1706 return cells.ContainsKey(address.GetAddress());
1707 }
1708
1718 public bool HasCell(int columnNumber, int rowNumber)
1719 {
1720 return HasCell(new Address(columnNumber, rowNumber));
1721 }
1722
1728 public void ResetColumn(int columnNumber)
1729 {
1730 if (columns.TryGetValue(columnNumber, out var value) && !value.HasAutoFilter) // AutoFilters cannot have gaps
1731 {
1732 columns.Remove(columnNumber);
1733 }
1734 else if (columns.TryGetValue(columnNumber, out var value2))
1735 {
1736 value2.IsHidden = false;
1737 value2.Width = DefaultWorksheetColumnWidth;
1738 }
1739 }
1740
1746 public IReadOnlyList<Cell> GetRow(int rowNumber)
1747 {
1748 List<Cell> list = new List<Cell>();
1749 foreach (KeyValuePair<string, Cell> cell in cells)
1750 {
1751 if (cell.Value.RowNumber == rowNumber)
1752 {
1753 list.Add(cell.Value);
1754 }
1755 }
1756 list.Sort((c1, c2) => (c1.ColumnNumber.CompareTo(c2.ColumnNumber))); // Lambda sort
1757 return list;
1758 }
1759
1766 public IReadOnlyList<Cell> GetColumn(string columnAddress)
1767 {
1768 int column = Cell.ResolveColumn(columnAddress);
1769 return GetColumn(column);
1770 }
1771
1777 public IReadOnlyList<Cell> GetColumn(int columnNumber)
1778 {
1779 List<Cell> list = new List<Cell>();
1780 foreach (KeyValuePair<string, Cell> cell in cells)
1781 {
1782 if (cell.Value.ColumnNumber == columnNumber)
1783 {
1784 list.Add(cell.Value);
1785 }
1786 }
1787 list.Sort((c1, c2) => (c1.RowNumber.CompareTo(c2.RowNumber))); // Lambda sort
1788 return list;
1789 }
1790
1796 {
1797 return currentColumnNumber;
1798 }
1799
1805 {
1806 return currentRowNumber;
1807 }
1808
1812 public void GoToNextColumn()
1813 {
1814 currentColumnNumber++;
1815 currentRowNumber = 0;
1816 Cell.ValidateColumnNumber(currentColumnNumber);
1817 }
1818
1825 public void GoToNextColumn(int numberOfColumns, bool keepRowPosition = false)
1826 {
1827 currentColumnNumber += numberOfColumns;
1828 if (!keepRowPosition)
1829 {
1830 currentRowNumber = 0;
1831 }
1832 Cell.ValidateColumnNumber(currentColumnNumber);
1833 }
1834
1838 public void GoToNextRow()
1839 {
1840 currentRowNumber++;
1841 currentColumnNumber = 0;
1842 Cell.ValidateRowNumber(currentRowNumber);
1843 }
1844
1851 public void GoToNextRow(int numberOfRows, bool keepColumnPosition = false)
1852 {
1853 currentRowNumber += numberOfRows;
1854 if (!keepColumnPosition)
1855 {
1856 currentColumnNumber = 0;
1857 }
1858 Cell.ValidateRowNumber(currentRowNumber);
1859 }
1860
1867 public string MergeCells(Range cellRange)
1868 {
1869 return MergeCells(cellRange.StartAddress, cellRange.EndAddress);
1870 }
1871
1879 public string MergeCells(string cellRange)
1880 {
1881 Range range = Cell.ResolveCellRange(cellRange);
1882 return MergeCells(range.StartAddress, range.EndAddress);
1883 }
1884
1892 public string MergeCells(Address startAddress, Address endAddress)
1893 {
1894 string key = startAddress + ":" + endAddress;
1895 Range value = new Range(startAddress, endAddress);
1896 IReadOnlyList<Address> result = value.ResolveEnclosedAddresses();
1897 foreach (KeyValuePair<string, Range> item in mergedCells)
1898 {
1899 if (item.Value.ResolveEnclosedAddresses().Intersect(result).Any())
1900 {
1901 throw new RangeException("The passed range: " + value.ToString() + " contains cells that are already in the defined merge range: " + item.Key);
1902 }
1903 }
1904 mergedCells.Add(key, value);
1905 return key;
1906 }
1907
1911 internal void RecalculateAutoFilter()
1912 {
1913 if (autoFilterRange == null)
1914 { return; }
1915 int start = autoFilterRange.Value.StartAddress.Column;
1916 int end = autoFilterRange.Value.EndAddress.Column;
1917 int endRow = 0;
1918 foreach (KeyValuePair<string, Cell> item in Cells)
1919 {
1920 if (item.Value.ColumnNumber < start || item.Value.ColumnNumber > end)
1921 { continue; }
1922 if (item.Value.RowNumber > endRow)
1923 { endRow = item.Value.RowNumber; }
1924 }
1925 Column c;
1926 for (int i = start; i <= end; i++)
1927 {
1928 if (!columns.TryGetValue(i, out var value))
1929 {
1930 c = new Column(i)
1931 {
1932 HasAutoFilter = true
1933 };
1934 columns.Add(i, c);
1935 }
1936 else
1937 {
1938 value.HasAutoFilter = true;
1939 }
1940 }
1941 autoFilterRange = new Range(start, 0, end, endRow);
1942 }
1943
1947 internal void RecalculateColumns()
1948 {
1949 List<int> columnsToDelete = new List<int>();
1950 foreach (KeyValuePair<int, Column> col in columns)
1951 {
1952 if (!col.Value.HasAutoFilter && !col.Value.IsHidden && Comparators.CompareDimensions(col.Value.Width, DefaultWorksheetColumnWidth) == 0 && col.Value.DefaultColumnStyle == null)
1953 {
1954 columnsToDelete.Add(col.Key);
1955 }
1956 }
1957 foreach (int index in columnsToDelete)
1958 {
1959 columns.Remove(index);
1960 }
1961 }
1962
1968 internal void ResolveMergedCells()
1969 {
1970 Style mergeStyle = BasicStyles.MergeCellStyle;
1971 Cell cell;
1972 foreach (KeyValuePair<string, Range> range in MergedCells)
1973 {
1974 int pos = 0;
1975 List<Address> addresses = Cell.GetCellRange(range.Value.StartAddress, range.Value.EndAddress) as List<Address>;
1976 foreach (Address address in addresses)
1977 {
1978 if (!Cells.ContainsKey(address.GetAddress()))
1979 {
1980 cell = new Cell
1981 {
1982 DataType = Cell.CellType.Empty,
1983 RowNumber = address.Row,
1984 ColumnNumber = address.Column
1985 };
1986 AddCell(cell, cell.ColumnNumber, cell.RowNumber);
1987 }
1988 else
1989 {
1990 cell = Cells[address.GetAddress()];
1991 }
1992 if (pos != 0)
1993 {
1994 cell.DataType = Cell.CellType.Empty;
1995 if (cell.CellStyle == null)
1996 {
1997 cell.SetStyle(mergeStyle);
1998 }
1999 else
2000 {
2001 Style mixedMergeStyle = cell.CellStyle;
2002 // TODO: There should be a better possibility to identify particular style elements that deviates
2003 mixedMergeStyle.CurrentCellXf.ForceApplyAlignment = mergeStyle.CurrentCellXf.ForceApplyAlignment;
2004 cell.SetStyle(mixedMergeStyle);
2005 }
2006 }
2007 pos++;
2008 }
2009 }
2010 }
2011
2015 public void RemoveAutoFilter()
2016 {
2017 autoFilterRange = null;
2018 }
2019
2025 public void RemoveHiddenColumn(int columnNumber)
2026 {
2027 SetColumnHiddenState(columnNumber, false);
2028 }
2029
2035 public void RemoveHiddenColumn(string columnAddress)
2036 {
2037 int columnNumber = Cell.ResolveColumn(columnAddress);
2038 SetColumnHiddenState(columnNumber, false);
2039 }
2040
2046 public void RemoveHiddenRow(int rowNumber)
2047 {
2048 SetRowHiddenState(rowNumber, false);
2049 }
2050
2056 public void RemoveMergedCells(string range)
2057 {
2058 range = ParserUtils.ToUpper(range);
2059 if (range == null || !mergedCells.ContainsKey(range))
2060 {
2061 throw new RangeException("The cell range " + range + " was not found in the list of merged cell ranges");
2062 }
2063
2064 List<Address> addresses = Cell.GetCellRange(range) as List<Address>;
2065 foreach (Address address in addresses)
2066 {
2067 if (cells.ContainsKey(address.GetAddress()))
2068 {
2069 Cell cell = cells[address.GetAddress()];
2071 {
2072 cell.RemoveStyle();
2073 }
2074 cell.ResolveCellType(); // resets the type
2075 }
2076 }
2077 mergedCells.Remove(range);
2078 }
2079
2084 public void RemoveRowHeight(int rowNumber)
2085 {
2086 if (rowHeights.ContainsKey(rowNumber))
2087 {
2088 rowHeights.Remove(rowNumber);
2089 }
2090 }
2091
2097 {
2098 if (sheetProtectionValues.Contains(value))
2099 {
2100 sheetProtectionValues.Remove(value);
2101 }
2102 }
2103
2108 public void SetActiveStyle(Style style)
2109 {
2110 if (style == null)
2111 {
2112 useActiveStyle = false;
2113 }
2114 else
2115 {
2116 useActiveStyle = true;
2117 }
2118 activeStyle = style;
2119 }
2120
2127 public void SetAutoFilter(int startColumn, int endColumn)
2128 {
2129 string start = Cell.ResolveCellAddress(startColumn, 0);
2130 string end = Cell.ResolveCellAddress(endColumn, 0);
2131 if (endColumn < startColumn)
2132 {
2133 SetAutoFilter(end + ":" + start);
2134 }
2135 else
2136 {
2137 SetAutoFilter(start + ":" + end);
2138 }
2139 }
2140
2147 public void SetAutoFilter(string range)
2148 {
2149 autoFilterRange = Cell.ResolveCellRange(range);
2150 RecalculateAutoFilter();
2151 RecalculateColumns();
2152 }
2153
2160 private void SetColumnHiddenState(int columnNumber, bool state)
2161 {
2162 Cell.ValidateColumnNumber(columnNumber);
2163 if (columns.TryGetValue(columnNumber, out var value))
2164 {
2165 value.IsHidden = state;
2166 }
2167 else if (state)
2168 {
2169 Column c = new Column(columnNumber)
2170 {
2171 IsHidden = true
2172 };
2173 columns.Add(columnNumber, c);
2174 }
2175 if (!columns[columnNumber].IsHidden && Comparators.CompareDimensions(columns[columnNumber].Width, DefaultWorksheetColumnWidth) == 0 && !columns[columnNumber].HasAutoFilter)
2176 {
2177 columns.Remove(columnNumber);
2178 }
2179 }
2180
2187 public void SetColumnWidth(string columnAddress, float width)
2188 {
2189 int columnNumber = Cell.ResolveColumn(columnAddress);
2190 SetColumnWidth(columnNumber, width);
2191 }
2192
2199 public void SetColumnWidth(int columnNumber, float width)
2200 {
2201 Cell.ValidateColumnNumber(columnNumber);
2202 if (width < MinColumnWidth || width > MaxColumnWidth)
2203 {
2204 throw new RangeException("The column width (" + width + ") is out of range. Range is from " + MinColumnWidth + " to " + MaxColumnWidth + " (chars).");
2205 }
2206 if (columns.TryGetValue(columnNumber, out var value))
2207 {
2208 value.Width = width;
2209 }
2210 else
2211 {
2212 Column c = new Column(columnNumber)
2213 {
2214 Width = width
2215 };
2216 columns.Add(columnNumber, c);
2217 }
2218 }
2219
2227 public Style SetColumnDefaultStyle(string columnAddress, Style style)
2228 {
2229 int columnNumber = Cell.ResolveColumn(columnAddress);
2230 return SetColumnDefaultStyle(columnNumber, style);
2231 }
2232
2239 public Style SetColumnDefaultStyle(int columnNumber, Style style)
2240 {
2241 Cell.ValidateColumnNumber(columnNumber);
2242 if (this.columns.TryGetValue(columnNumber, out var value))
2243 {
2244 return value.SetDefaultColumnStyle(style);
2245 }
2246 else
2247 {
2248 Column c = new Column(columnNumber);
2249 Style returnStyle = c.SetDefaultColumnStyle(style);
2250 this.columns.Add(columnNumber, c);
2251 return returnStyle;
2252 }
2253 }
2254
2261 public void SetCurrentCellAddress(int columnNumber, int rowNumber)
2262 {
2263 SetCurrentColumnNumber(columnNumber);
2264 SetCurrentRowNumber(rowNumber);
2265 }
2266
2273 public void SetCurrentCellAddress(string address)
2274 {
2275 int row;
2276 int column;
2277 Cell.ResolveCellCoordinate(address, out column, out row);
2278 SetCurrentCellAddress(column, row);
2279 }
2280
2286 public void SetCurrentColumnNumber(int columnNumber)
2287 {
2288 Cell.ValidateColumnNumber(columnNumber);
2289 currentColumnNumber = columnNumber;
2290 }
2291
2297 public void SetCurrentRowNumber(int rowNumber)
2298 {
2299 Cell.ValidateRowNumber(rowNumber);
2300 currentRowNumber = rowNumber;
2301 }
2302
2307 public void AddSelectedCells(Range range)
2308 {
2309 selectedCells = DataUtils.MergeRange(selectedCells, range).ToList();
2310 }
2311
2317 public void AddSelectedCells(Address startAddress, Address endAddress)
2318 {
2319 AddSelectedCells(new Range(startAddress, endAddress));
2320 }
2321
2326 public void AddSelectedCells(string rangeOrAddress)
2327 {
2328 Range? resolved = ParseRange(rangeOrAddress);
2329 if (resolved != null)
2330 {
2331 AddSelectedCells(resolved.Value);
2332 }
2333 }
2334
2339 public void AddSelectedCells(Address address)
2340 {
2341 AddSelectedCells(new Range(address, address));
2342 }
2343
2348 {
2349 selectedCells.Clear();
2350 }
2351
2357 public void RemoveSelectedCells(Range range)
2358 {
2359 selectedCells = DataUtils.SubtractRange(selectedCells, range).ToList();
2360 }
2361
2366 public void RemoveSelectedCells(String rangeOrAddress)
2367 {
2368 Range? resolved = ParseRange(rangeOrAddress);
2369 if (resolved != null)
2370 {
2371 RemoveSelectedCells(resolved.Value);
2372 }
2373 }
2374
2380 public void RemoveSelectedCells(Address startAddress, Address endAddress)
2381 {
2382 RemoveSelectedCells(new Range(startAddress, endAddress));
2383 }
2384
2389 public void RemoveSelectedCells(Address address)
2390 {
2391 RemoveSelectedCells(new Range(address, address));
2392 }
2393
2398 public void SetSheetProtectionPassword(string password)
2399 {
2400 if (string.IsNullOrEmpty(password))
2401 {
2402 sheetProtectionPassword.UnsetPassword();
2403 UseSheetProtection = false;
2404 }
2405 else
2406 {
2407 sheetProtectionPassword.SetPassword(password);
2408 UseSheetProtection = true;
2409 }
2410 }
2411
2418 public void SetRowHeight(int rowNumber, float height)
2419 {
2420 Cell.ValidateRowNumber(rowNumber);
2421 if (height < MinRowHeight || height > MaxRowHeight)
2422 {
2423 throw new RangeException("The row height (" + height + ") is out of range. Range is from " + MinRowHeight + " to " + MaxRowHeight + " (equals 546px).");
2424 }
2425 if (rowHeights.ContainsKey(rowNumber))
2426 {
2427 rowHeights[rowNumber] = height;
2428 }
2429 else
2430 {
2431 rowHeights.Add(rowNumber, height);
2432 }
2433 }
2434
2441 private void SetRowHiddenState(int rowNumber, bool state)
2442 {
2443 Cell.ValidateRowNumber(rowNumber);
2444 if (hiddenRows.ContainsKey(rowNumber))
2445 {
2446 if (state)
2447 {
2448 hiddenRows[rowNumber] = true;
2449 }
2450 else
2451 {
2452 hiddenRows.Remove(rowNumber);
2453 }
2454 }
2455 else if (state)
2456 {
2457 hiddenRows.Add(rowNumber, true);
2458 }
2459 }
2460
2466 public void SetSheetName(string name)
2467 {
2468 if (string.IsNullOrEmpty(name))
2469 {
2470 throw new FormatException("the worksheet name must be between 1 and " + MaxWorksheetNameLength + " characters");
2471 }
2472 if (name.Length > MaxWorksheetNameLength)
2473 {
2474 throw new FormatException("the worksheet name must be between 1 and " + MaxWorksheetNameLength + " characters");
2475 }
2476 Regex regex = new Regex(@"[\‍[\‍]\*\?/\\‍]");
2477 Match match = regex.Match(name);
2478 if (match.Captures.Count > 0)
2479 {
2480 throw new FormatException(@"the worksheet name must not contain the characters [ ] * ? / \ ");
2481 }
2482 sheetName = name;
2483 }
2484
2491 public void SetSheetName(string name, bool sanitize)
2492 {
2493 if (sanitize)
2494 {
2495 sheetName = ""; // Empty name (temporary) to prevent conflicts during sanitizing
2496 sheetName = SanitizeWorksheetName(name, workbookReference);
2497 }
2498 else
2499 {
2500 SetSheetName(name);
2501 }
2502 }
2503
2510 public void SetHorizontalSplit(float topPaneHeight, Address topLeftCell, WorksheetPane? activePane)
2511 {
2512 SetSplit(null, topPaneHeight, topLeftCell, activePane);
2513 }
2514
2523 public void SetHorizontalSplit(int numberOfRowsFromTop, bool freeze, Address topLeftCell, WorksheetPane? activePane)
2524 {
2525 SetSplit(null, numberOfRowsFromTop, freeze, topLeftCell, activePane);
2526 }
2527
2534 public void SetVerticalSplit(float leftPaneWidth, Address topLeftCell, WorksheetPane? activePane)
2535 {
2536 SetSplit(leftPaneWidth, null, topLeftCell, activePane);
2537 }
2538
2548 public void SetVerticalSplit(int numberOfColumnsFromLeft, bool freeze, Address topLeftCell, WorksheetPane? activePane)
2549 {
2550 SetSplit(numberOfColumnsFromLeft, null, freeze, topLeftCell, activePane);
2551 }
2552
2564 public void SetSplit(int? numberOfColumnsFromLeft, int? numberOfRowsFromTop, bool freeze, Address topLeftCell, WorksheetPane? activePane)
2565 {
2566 if (freeze)
2567 {
2568 if (numberOfColumnsFromLeft != null && topLeftCell.Column < numberOfColumnsFromLeft.Value)
2569 {
2570 throw new WorksheetException("The column number " + topLeftCell.Column +
2571 " is not valid for a frozen, vertical split with the split pane column number " + numberOfColumnsFromLeft.Value);
2572 }
2573 if (numberOfRowsFromTop != null && topLeftCell.Row < numberOfRowsFromTop.Value)
2574 {
2575 throw new WorksheetException("The row number " + topLeftCell.Row +
2576 " is not valid for a frozen, horizontal split height the split pane row number " + numberOfRowsFromTop.Value);
2577 }
2578 }
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;
2587 }
2588
2598 public void SetSplit(float? leftPaneWidth, float? topPaneHeight, Address topLeftCell, WorksheetPane? activePane)
2599 {
2600 this.paneSplitLeftWidth = leftPaneWidth;
2601 this.paneSplitTopHeight = topPaneHeight;
2602 this.freezeSplitPanes = null;
2603 this.paneSplitAddress = null;
2604 this.paneSplitTopLeftCell = topLeftCell;
2605 this.activePane = activePane;
2606 }
2607
2611 public void ResetSplit()
2612 {
2613 this.paneSplitLeftWidth = null;
2614 this.paneSplitTopHeight = null;
2615 this.freezeSplitPanes = null;
2616 this.paneSplitAddress = null;
2617 this.paneSplitTopLeftCell = null;
2618 this.activePane = null;
2619 }
2620
2630 public Worksheet Copy()
2631 {
2632 Worksheet copy = new Worksheet();
2633 foreach (KeyValuePair<string, Cell> cell in this.cells)
2634 {
2635 copy.AddCell(cell.Value.Copy(), cell.Key);
2636 }
2637 copy.activePane = this.activePane;
2638 copy.activeStyle = this.activeStyle;
2639 if (this.autoFilterRange.HasValue)
2640 {
2641 copy.autoFilterRange = this.autoFilterRange.Value.Copy();
2642 }
2643 foreach (KeyValuePair<int, Column> column in this.columns)
2644 {
2645 copy.columns.Add(column.Key, column.Value.Copy());
2646 }
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)
2655 {
2656 copy.hiddenRows.Add(row.Key, row.Value);
2657 }
2658 foreach (KeyValuePair<string, Range> cell in this.mergedCells)
2659 {
2660 copy.mergedCells.Add(cell.Key, cell.Value.Copy());
2661 }
2662 if (this.paneSplitAddress.HasValue)
2663 {
2664 copy.paneSplitAddress = this.paneSplitAddress.Value.Copy();
2665 }
2666 copy.paneSplitLeftWidth = this.paneSplitLeftWidth;
2667 copy.paneSplitTopHeight = this.paneSplitTopHeight;
2668 if (this.paneSplitTopLeftCell.HasValue)
2669 {
2670 copy.paneSplitTopLeftCell = this.paneSplitTopLeftCell.Value.Copy();
2671 }
2672 foreach (KeyValuePair<int, float> row in this.rowHeights)
2673 {
2674 copy.rowHeights.Add(row.Key, row.Value);
2675 }
2676 foreach (Range range in selectedCells)
2677 {
2678 copy.AddSelectedCells(range);
2679 }
2680 copy.sheetProtectionPassword.CopyFrom(this.sheetProtectionPassword);
2681 foreach (SheetProtectionValue value in this.sheetProtectionValues)
2682 {
2683 copy.sheetProtectionValues.Add(value);
2684 }
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)
2693 {
2694 copy.SetZoomFactor(zoomFactor.Key, zoomFactor.Value);
2695 }
2696 return copy;
2697 }
2698
2706 public void SetZoomFactor(SheetViewType sheetViewType, int zoomFactor)
2707 {
2708 if (zoomFactor != AutoZoomFactor && (zoomFactor < MinZoomFactor || zoomFactor > maxZoomFactor))
2709 {
2710 throw new WorksheetException("The zoom factor " + zoomFactor + " is not valid. Valid are values between " + MinZoomFactor + " and " + maxZoomFactor + ", or " + AutoZoomFactor + " (automatic)");
2711 }
2712 if (this.zoomFactor.ContainsKey(sheetViewType))
2713 {
2714 this.zoomFactor[sheetViewType] = zoomFactor;
2715 }
2716 else
2717 {
2718 this.zoomFactor.Add(sheetViewType, zoomFactor);
2719 }
2720 }
2721
2722
2723
2724 #region static_methods
2732 public static string SanitizeWorksheetName(string input, Workbook workbook)
2733 {
2734 if (string.IsNullOrEmpty(input))
2735 {
2736 input = "Sheet1";
2737 }
2738 int len;
2739 if (input.Length > MaxWorksheetNameLength)
2740 {
2742 }
2743 else
2744 {
2745 len = input.Length;
2746 }
2747 StringBuilder sb = new StringBuilder(MaxWorksheetNameLength);
2748 char c;
2749 for (int i = 0; i < len; i++)
2750 {
2751 c = input[i];
2752 if (c == '[' || c == ']' || c == '*' || c == '?' || c == '\\' || c == '/')
2753 { sb.Append('_'); }
2754 else
2755 { sb.Append(c); }
2756 }
2757 return GetUnusedWorksheetName(sb.ToString(), workbook);
2758 }
2759
2765 private static Range? ParseRange(string rangeOrAddress)
2766 {
2767 if (string.IsNullOrEmpty(rangeOrAddress))
2768 {
2769 return null;
2770 }
2771 Range range;
2772 if (rangeOrAddress.Contains(":"))
2773 {
2774 range = Cell.ResolveCellRange(rangeOrAddress);
2775 }
2776 else
2777 {
2778 Address address = Cell.ResolveCellCoordinate(rangeOrAddress);
2779 range = new Range(address, address);
2780 }
2781 return range;
2782 }
2783
2793 private static string GetUnusedWorksheetName(string name, Workbook workbook)
2794 {
2795 if (workbook == null)
2796 {
2797 throw new WorksheetException("The workbook reference is null");
2798 }
2799 if (!WorksheetExists(name, workbook))
2800 { return name; }
2801 Regex regex = new Regex(@"^(.*?)(\d{1,31})$");
2802 Match match = regex.Match(name);
2803 string prefix = name;
2804 int number = 1;
2805 if (match.Groups.Count > 1)
2806 {
2807 prefix = match.Groups[1].Value;
2808 _ = int.TryParse(match.Groups[2].Value, out number);
2809 // if this failed, the start number is 0 (parsed number was >max. int32)
2810 }
2811 while (true)
2812 {
2813 string numberString = ParserUtils.ToString(number);
2814 if (numberString.Length + prefix.Length > MaxWorksheetNameLength)
2815 {
2816 int endIndex = prefix.Length - (numberString.Length + prefix.Length - MaxWorksheetNameLength);
2817 prefix = prefix.Substring(0, endIndex);
2818 }
2819 string newName = prefix + numberString;
2820 if (!WorksheetExists(newName, workbook))
2821 { return newName; }
2822 number++;
2823 }
2824 }
2825
2832 private static bool WorksheetExists(string name, Workbook workbook)
2833 {
2834 int len = workbook.Worksheets.Count;
2835 for (int i = 0; i < len; i++)
2836 {
2837 if (workbook.Worksheets[i].SheetName == name)
2838 {
2839 return true;
2840 }
2841 }
2842 return false;
2843 }
2844
2848 internal static string GetSheetProtectionName(SheetProtectionValue protection)
2849 {
2850 string output = "";
2851 switch (protection)
2852 {
2853 case SheetProtectionValue.Objects: output = "objects"; break;
2854 case SheetProtectionValue.Scenarios: output = "scenarios"; break;
2855 case SheetProtectionValue.FormatCells: output = "formatCells"; break;
2856 case SheetProtectionValue.FormatColumns: output = "formatColumns"; break;
2857 case SheetProtectionValue.FormatRows: output = "formatRows"; break;
2858 case SheetProtectionValue.InsertColumns: output = "insertColumns"; break;
2859 case SheetProtectionValue.InsertRows: output = "insertRows"; break;
2860 case SheetProtectionValue.InsertHyperlinks: output = "insertHyperlinks"; break;
2861 case SheetProtectionValue.DeleteColumns: output = "deleteColumns"; break;
2862 case SheetProtectionValue.DeleteRows: output = "deleteRows"; break;
2863 case SheetProtectionValue.SelectLockedCells: output = "selectLockedCells"; break;
2864 case SheetProtectionValue.Sort: output = "sort"; break;
2865 case SheetProtectionValue.AutoFilter: output = "autoFilter"; break;
2866 case SheetProtectionValue.PivotTables: output = "pivotTables"; break;
2867 case SheetProtectionValue.SelectUnlockedCells: output = "selectUnlockedCells"; break;
2868 }
2869 return output;
2870 }
2871
2877 internal static WorksheetPane? GetWorksheetPaneEnum(string pane)
2878 {
2879 WorksheetPane? output = null;
2880 switch (pane)
2881 {
2882 case "topLeft": output = WorksheetPane.TopLeft; break;
2883 case "topRight": output = WorksheetPane.TopRight; break;
2884 case "bottomLeft": output = WorksheetPane.BottomLeft; break;
2885 case "bottomRight": output = WorksheetPane.BottomRight; break;
2886 }
2887 return output;
2888 }
2889
2895 internal static SheetViewType GetSheetViewTypeEnum(string viewType)
2896 {
2897 SheetViewType output = SheetViewType.Normal;
2898 switch (viewType)
2899 {
2900 case "pageBreakPreview": output = SheetViewType.PageBreakPreview; break;
2901 case "pageLayout": output = SheetViewType.PageLayout; break;
2902 }
2903 return output;
2904 }
2905 #endregion
2906 #endregion
2907
2908 }
2909}
Class representing a cell of a worksheet.
Definition Cell.cs:24
static Address ResolveCellCoordinate(string address)
Gets the column and row number (zero based) of a cell by the address.
Definition Cell.cs:742
CellType
Enum defines the basic data types of a cell.
Definition Cell.cs:35
static void ValidateRowNumber(int row)
Validates the passed (zero-based) row number. An exception will be thrown if the row is invalid.
Definition Cell.cs:928
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).
Definition Cell.cs:718
static AddressScope GetAddressScope(string addressExpression)
Gets the scope of the passed address (string expression). Scope means either single cell address or r...
Definition Cell.cs:887
Style CellStyle
Gets the assigned style of the cell.
Definition Cell.cs:125
static Range ResolveCellRange(string range)
Resolves a cell range from the format like A1:B3 or AAD556:AAD1000.
Definition Cell.cs:816
int RowNumber
Gets or sets the number of the row (zero-based).
Definition Cell.cs:148
static void ValidateColumnNumber(int column)
Validates the passed (zero-based) column number. An exception will be thrown if the column is invalid...
Definition Cell.cs:914
static int ResolveColumn(string columnAddress)
Gets the column number from the column address (A - XFD).
Definition Cell.cs:840
string CellAddress
Gets or sets the combined cell Address as string in the format A1 - XFD1048576. The address may conta...
Definition Cell.cs:99
AddressScope
Enum to define the scope of a passed address string (used in static context).
Definition Cell.cs:75
int ColumnNumber
Gets or sets the number of the column (zero-based).
Definition Cell.cs:132
Style SetStyle(Style style, bool unmanaged=false)
Sets the style of the cell.
Definition Cell.cs:414
static IEnumerable< Address > GetCellRange(string range)
Gets a list of cell addresses from a cell range (format A1:B3 or AAD556:AAD1000).
Definition Cell.cs:628
void ResolveCellType()
Method resets the Cell type and tries to find the actual type. This is used if a Cell was created wit...
Definition Cell.cs:344
object Value
Gets or sets the value of the cell (generic object type). When setting a value, the DataType is autom...
Definition Cell.cs:165
void RemoveStyle()
Removes the assigned style from the cell.
Definition Cell.cs:335
Class representing a column of a worksheet.
Definition Column.cs:18
Style SetDefaultColumnStyle(Style defaultColumnStyle, bool unmanaged=false)
Sets the default style of the column.
Definition Column.cs:93
Class for exceptions regarding format error incidents.
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...
Definition CellXf.cs:120
Class representing a Style with sub classes within a style sheet. An instance of this class is only a...
Definition Style.cs:18
override AbstractStyle Copy()
Method to copy the current object to a new one without casting.
Definition Style.cs:206
CellXf CurrentCellXf
Gets or sets the current CellXf object of the style.
Definition Style.cs:33
Style Append(AbstractStyle styleToAppend)
Appends the specified style parts to the current one. The parts can be instances of sub-classes like ...
Definition Style.cs:121
General data utils class with static methods.
Definition DataUtils.cs:21
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 ...
Definition DataUtils.cs:345
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...
Definition DataUtils.cs:429
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.
Definition Workbook.cs:24
List< Worksheet > Worksheets
Gets the list of worksheets in the workbook.
Definition Workbook.cs:130
Dictionary< int, bool > HiddenRows
Gets the hidden rows as dictionary with the zero-based row number as key and a boolean as value....
Definition Worksheet.cs:281
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.
Definition Worksheet.cs:36
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.
Definition Worksheet.cs:247
void AddCellFormula(string formula, string address, Style style)
Adds a cell formula as string to the defined cell address.
Definition Worksheet.cs:823
WorksheetPane
Enum to define the pane position or active pane in a slip worksheet.
Definition Worksheet.cs:157
@ TopRight
The pane is located in the top right of the split worksheet.
Definition Worksheet.cs:161
@ BottomRight
The pane is located in the bottom right of the split worksheet.
Definition Worksheet.cs:159
@ BottomLeft
The pane is located in the bottom left of the split worksheet.
Definition Worksheet.cs:163
@ TopLeft
The pane is located in the top left of the split worksheet.
Definition Worksheet.cs:165
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.
Definition Worksheet.cs:264
int ZoomFactor
Gets or sets the zoom factor of the ViewType of the current worksheet. If AutoZoomFactor,...
Definition Worksheet.cs:503
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.
Definition Worksheet.cs:313
void RemoveHiddenRow(int rowNumber)
Sets a previously defined, hidden row as visible again.
CellDirection
Enum to define the direction when using AddNextCell method.
Definition Worksheet.cs:106
@ RowToRow
The next cell will be on the same column (A1,A2,A3...).
Definition Worksheet.cs:110
@ ColumnToColumn
The next cell will be on the same row (A1,B1,C1...).
Definition Worksheet.cs:108
@ Disabled
The address of the next cell will be not changed when adding a cell (for manual definition of cell ad...
Definition Worksheet.cs:112
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...
Definition Worksheet.cs:225
WorksheetPane? ActivePane
Gets the active Pane is splitting is applied. The value is nullable. If null, no splitting was defin...
Definition Worksheet.cs:454
bool ShowRuler
Gets or sets whether a ruler is displayed over the column headers. This value only applies if ViewTyp...
Definition Worksheet.cs:479
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.
Definition Worksheet.cs:355
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...
Definition Worksheet.cs:518
SheetViewType
Enum to define how a worksheet is displayed in the spreadsheet application (Excel).
Definition Worksheet.cs:172
@ PageBreakPreview
The worksheet is displayed with indicators where the page would break if it were printed.
Definition Worksheet.cs:176
@ PageLayout
The worksheet is displayed like it would be printed.
Definition Worksheet.cs:178
@ Normal
The worksheet is displayed without pagination (default).
Definition Worksheet.cs:174
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.
Definition Worksheet.cs:876
void SetRowHeight(int rowNumber, float height)
Sets the height of the passed row number (zero-based).
Worksheet(string name)
Constructor with worksheet name.
Definition Worksheet.cs:564
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.
Definition Worksheet.cs:240
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.
Definition Worksheet.cs:53
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.
Definition Worksheet.cs:469
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.
Definition Worksheet.cs:119
@ PivotTables
If selected, the user can use pivot tables if the worksheets is protected.
Definition Worksheet.cs:148
@ FormatCells
If selected, the user can format cells if the worksheets is protected.
Definition Worksheet.cs:126
@ InsertHyperlinks
If selected, the user can insert hyper links if the worksheets is protected.
Definition Worksheet.cs:136
@ InsertColumns
If selected, the user can insert columns if the worksheets is protected.
Definition Worksheet.cs:132
@ Sort
If selected, the user can sort cells if the worksheets is protected.
Definition Worksheet.cs:144
@ DeleteColumns
If selected, the user can delete columns if the worksheets is protected.
Definition Worksheet.cs:138
@ Scenarios
If selected, the user can edit scenarios if the worksheets is protected.
Definition Worksheet.cs:124
@ DeleteRows
If selected, the user can delete rows if the worksheets is protected.
Definition Worksheet.cs:140
@ FormatColumns
If selected, the user can format columns if the worksheets is protected.
Definition Worksheet.cs:128
@ InsertRows
If selected, the user can insert rows if the worksheets is protected.
Definition Worksheet.cs:134
@ FormatRows
If selected, the user can format rows if the worksheets is protected.
Definition Worksheet.cs:130
@ AutoFilter
If selected, the user can use auto filters if the worksheets is protected.
Definition Worksheet.cs:146
@ Objects
If selected, the user can edit objects if the worksheets is protected.
Definition Worksheet.cs:122
@ SelectUnlockedCells
If selected, the user can select unlocked cells if the worksheets is protected.
Definition Worksheet.cs:150
@ SelectLockedCells
If selected, the user can select locked cells if the worksheets is protected.
Definition Worksheet.cs:142
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.
Definition Worksheet.cs:576
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...
Definition Worksheet.cs:977
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.
Definition Worksheet.cs:40
static readonly float DefaultWorksheetRowHeight
Default row height as constant.
Definition Worksheet.cs:44
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.
Definition Worksheet.cs:74
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....
Definition Worksheet.cs:432
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...
Definition Worksheet.cs:961
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.
Definition Worksheet.cs:48
void AddCellFormula(string formula, string address)
Adds a cell formula as string to the defined cell address.
Definition Worksheet.cs:805
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...
Definition Worksheet.cs:733
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).
Definition Worksheet.cs:485
string SheetName
Gets or sets the name of the worksheet.
Definition Worksheet.cs:329
void AddCellFormula(string formula, int columnNumber, int rowNumber)
Adds a cell formula as string to the defined cell address.
Definition Worksheet.cs:839
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.
Definition Worksheet.cs:361
const int AutoZoomFactor
Automatic zoom factor of a worksheet.
Definition Worksheet.cs:89
float? PaneSplitTopHeight
Gets the height of the upper, horizontal split pane, measured from the top of the window....
Definition Worksheet.cs:400
Address? PaneSplitAddress
Gets the split address for frozen panes or if pane split was defined in number of columns and / or ro...
Definition Worksheet.cs:444
Cell FirstOrDefaultCell(Func< Cell, bool > predicate)
Searches for the first occurrence of the expression. Example: var cell = worksheet....
Worksheet()
Default Constructor.
Definition Worksheet.cs:533
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...
Definition Worksheet.cs:305
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...
Definition Worksheet.cs:913
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...
Definition Worksheet.cs:348
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...
Definition Worksheet.cs:766
static readonly float MinColumnWidth
Minimum column width as constant.
Definition Worksheet.cs:59
void RemoveMergedCells(string range)
Removes the defined merged cell range.
static readonly int MinRowNumber
Minimum row number (zero-based) as constant.
Definition Worksheet.cs:79
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...
Definition Worksheet.cs:612
Dictionary< int, float > RowHeights
Gets defined row heights as dictionary with the zero-based row number as key and the height (float fr...
Definition Worksheet.cs:289
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...
Definition Worksheet.cs:786
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...
Definition Worksheet.cs:896
bool ShowRowColumnHeaders
Gets or sets whether the column and row headers are visible on the current worksheet....
Definition Worksheet.cs:474
virtual IPassword SheetProtectionPassword
Password instance of the worksheet protection. If a password was set, the pain text representation an...
Definition Worksheet.cs:339
const int maxZoomFactor
Maximum zoom factor of a worksheet.
Definition Worksheet.cs:98
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.
Definition Worksheet.cs:70
Dictionary< string, Range > MergedCells
Gets the merged cells (only references) as dictionary with the cell address as key and the range obje...
Definition Worksheet.cs:297
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....
Definition Worksheet.cs:422
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...
Definition Worksheet.cs:946
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...
Definition Worksheet.cs:928
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...
Definition Worksheet.cs:596
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,...
Definition Worksheet.cs:217
const int MinZoomFactor
Minimum zoom factor of a worksheet. If set to this value, the zoom is set to automatic.
Definition Worksheet.cs:94
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...
Definition Worksheet.cs:750
void AddNextCellFormula(string formula)
Adds a formula as string to the next cell position.
Definition Worksheet.cs:864
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.
Definition Worksheet.cs:65
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.
Definition Worksheet.cs:462
static readonly float MaxRowHeight
Maximum row height as constant.
Definition Worksheet.cs:84
void AddCellFormula(string formula, int columnNumber, int rowNumber, Style style)
Adds a cell formula as string to the defined cell address.
Definition Worksheet.cs:853
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...
Definition Worksheet.cs:379
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...
Definition Worksheet.cs:233
float? PaneSplitLeftWidth
Gets the width of the left, vertical split pane, measured from the left of the window....
Definition Worksheet.cs:413
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...
Definition IPassword.cs:14
Struct representing the cell address as column and row (zero based).
Definition Address.cs:16
int Row
Row number (zero based).
Definition Address.cs:28
string GetAddress()
Returns the combined Address.
Definition Address.cs:84
int Column
Column number (zero based).
Definition Address.cs:24
Struct representing a cell range with a start and end address.
Definition Range.cs:16
IReadOnlyList< Address > ResolveEnclosedAddresses()
Gets a list of all addresses between the start and end address.
Definition Range.cs:125
Address StartAddress
Start address of the range.
Definition Range.cs:27
Address EndAddress
End address of the range.
Definition Range.cs:23