NanoXLSX.Core 3.1.0
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;
17using NanoXLSX.Styles;
18using NanoXLSX.Utils;
20
21namespace NanoXLSX
22{
26 public class Worksheet
27 {
28 static Worksheet()
29 {
31 }
32
33 #region constants
37 public static readonly int MaxWorksheetNameLength = 31;
41 public static readonly float DefaultWorksheetColumnWidth = 10f;
45 public static readonly float DefaultWorksheetRowHeight = 15f;
49 public static readonly int MaxColumnNumber = 16383;
53#pragma warning disable CA1805 // Do not initialize unnecessarily
54 public static readonly int MinColumnNumber = 0;
55#pragma warning restore CA1805
59#pragma warning disable CA1805 // Do not initialize unnecessarily
60 public static readonly float MinColumnWidth = 0f;
61#pragma warning restore CA1805
65#pragma warning disable CA1805 // Do not initialize unnecessarily
66 public static readonly float MinRowHeight = 0f;
67#pragma warning restore CA1805
71 public static readonly float MaxColumnWidth = 255f;
75 public static readonly int MaxRowNumber = 1048575;
79#pragma warning disable CA1805 // Do not initialize unnecessarily
80 public static readonly int MinRowNumber = 0;
81#pragma warning restore CA1805
85 public static readonly float MaxRowHeight = 409.5f;
89#pragma warning disable CA1805 // Do not initialize unnecessarily
90 public const int AutoZoomFactor = 0;
91#pragma warning restore CA1805
95 public const int MinZoomFactor = 10;
99 public const int maxZoomFactor = 400;
100 #endregion
101
102 #region enums
115
153
168
181 #endregion
182
183 #region privateFields
184 private Style activeStyle;
185 private Range? autoFilterRange;
186 private readonly Dictionary<CellKey, Cell> cells;
187 private readonly StringKeyedCellView cellsStringView;
188 private readonly Dictionary<int, Column> columns;
189 private string sheetName;
190 private int currentRowNumber;
191 private int currentColumnNumber;
192 private float defaultRowHeight;
193 private float defaultColumnWidth;
194 private readonly Dictionary<int, float> rowHeights;
195 private readonly Dictionary<int, bool> hiddenRows;
196 private readonly Dictionary<string, Range> mergedCells;
197 private readonly List<SheetProtectionValue> sheetProtectionValues;
198 private bool useActiveStyle;
199 private bool hidden;
200 private Workbook workbookReference;
201 private IPassword sheetProtectionPassword;
202 private List<Range> selectedCells;
203 private bool? freezeSplitPanes;
204 private float? paneSplitLeftWidth;
205 private float? paneSplitTopHeight;
206 private Address? paneSplitTopLeftCell;
207 private Address? paneSplitAddress;
208 private WorksheetPane? activePane;
209 private int sheetID;
210 private SheetViewType viewType;
211 private Dictionary<SheetViewType, int> zoomFactor;
212 #endregion
213
214 #region properties
219 {
220 get { return autoFilterRange; }
221 }
222
227 public IReadOnlyDictionary<string, Cell> Cells
228 {
229 get { return cellsStringView; }
230 }
231
236 public IEnumerable<Cell> CellValues
237 {
238 get { return cells.Values; }
239 }
240
244 public Dictionary<int, Column> Columns
245 {
246 get { return columns; }
247 }
248
253
259 {
260 get { return defaultColumnWidth; }
261 set
262 {
263 if (value < MinColumnWidth || value > MaxColumnWidth)
264 {
265 throw new RangeException("The passed default column width is out of range (" + MinColumnWidth + " to " + MaxColumnWidth + ")");
266 }
267 defaultColumnWidth = value;
268 }
269 }
270
275 public float DefaultRowHeight
276 {
277 get { return defaultRowHeight; }
278 set
279 {
280 if (value < MinRowHeight || value > MaxRowHeight)
281 {
282 throw new RangeException("The passed default row height is out of range (" + MinRowHeight + " to " + MaxRowHeight + ")");
283 }
284 defaultRowHeight = value;
285 }
286 }
287
292 public Dictionary<int, bool> HiddenRows
293 {
294 get { return hiddenRows; }
295 }
296
300 public Dictionary<int, float> RowHeights
301 {
302 get { return rowHeights; }
303 }
304
308 public Dictionary<string, Range> MergedCells
309 {
310 get { return mergedCells; }
311 }
312
316 public List<Range> SelectedCells
317 {
318 get { return selectedCells; }
319 }
320
324 public int SheetID
325 {
326 get => sheetID;
327 set
328 {
329 if (value < 1)
330 {
331 throw new FormatException("The ID " + value + " is invalid. Worksheet IDs must be >0");
332 }
333 sheetID = value;
334 }
335 }
336
340 public string SheetName
341 {
342 get { return sheetName; }
343 set { SetSheetName(value); }
344 }
345
351 {
352 get { return sheetProtectionPassword; }
353 internal set { sheetProtectionPassword = value; }
354 }
355
359 public List<SheetProtectionValue> SheetProtectionValues
360 {
361 get { return sheetProtectionValues; }
362 }
363
367 public bool UseSheetProtection { get; set; }
368
373 {
374 get { return workbookReference; }
375 set
376 {
377 workbookReference = value;
378 if (value != null)
379 {
380 workbookReference.ValidateWorksheets();
381 }
382 }
383 }
384
390 public bool Hidden
391 {
392 get { return hidden; }
393 set
394 {
395 hidden = value;
396 if (value && workbookReference != null)
397 {
398 workbookReference.ValidateWorksheets();
399 }
400 }
401 }
402
411 public float? PaneSplitTopHeight
412 {
413 get { return paneSplitTopHeight; }
414 }
415
424 public float? PaneSplitLeftWidth
425 {
426 get { return paneSplitLeftWidth; }
427 }
428
433 public bool? FreezeSplitPanes
434 {
435 get { return freezeSplitPanes; }
436 }
437
444 {
445 get { return paneSplitTopLeftCell; }
446 }
447
456 {
457 get { return paneSplitAddress; }
458 }
459
460
466 {
467 get { return activePane; }
468 }
469
474 {
475 get { return activeStyle; }
476 }
477
481 public bool ShowGridLines { get; set; }
482
486 public bool ShowRowColumnHeaders { get; set; }
487
491 public bool ShowRuler { get; set; }
492
497 {
498 get
499 {
500 return viewType;
501 }
502 set
503 {
504 viewType = value;
505 SetZoomFactor(value, 100);
506 }
507 }
508
514 public int ZoomFactor
515 {
516 set
517 {
518 SetZoomFactor(viewType, value);
519 }
520 get
521 {
522 return zoomFactor[viewType];
523 }
524 }
525
529 public Dictionary<SheetViewType, int> ZoomFactors
530 {
531 get
532 {
533 return zoomFactor;
534 }
535 }
536
537
538 #endregion
539
540
541 #region constructors
545 public Worksheet()
546 {
547 CurrentCellDirection = CellDirection.ColumnToColumn;
548 cells = new Dictionary<CellKey, Cell>(1000); // Let's assume a default of 1000 cells per worksheet, which is a good starting point for most use cases. This can be adjusted if needed, but it will save some resizing operations on the dictionary in the average case
549 cellsStringView = new StringKeyedCellView(cells);
550 currentRowNumber = 0;
551 currentColumnNumber = 0;
552 defaultColumnWidth = DefaultWorksheetColumnWidth;
553 defaultRowHeight = DefaultWorksheetRowHeight;
554 rowHeights = new Dictionary<int, float>();
555 mergedCells = new Dictionary<string, Range>();
556 selectedCells = new List<Range>();
557 sheetProtectionValues = new List<SheetProtectionValue>();
558 hiddenRows = new Dictionary<int, bool>();
559 columns = new Dictionary<int, Column>();
560 activeStyle = null;
561 workbookReference = null;
562 viewType = SheetViewType.Normal;
563 zoomFactor = new Dictionary<SheetViewType, int>
564 {
565 { viewType, 100 }
566 };
567 ShowGridLines = true;
569 ShowRuler = true;
570 sheetProtectionPassword = new LegacyPassword(LegacyPassword.PasswordType.WorksheetProtection);
571 }
572
577 public Worksheet(string name)
578 : this()
579 {
580 SetSheetName(name);
581 }
582
589 public Worksheet(string name, int id, Workbook reference)
590 : this()
591 {
592 SetSheetName(name);
593 SheetID = id;
594 workbookReference = reference;
595 }
596
597 #endregion
598
599 #region methods_AddNextCell
600
609 public void AddNextCell(object value)
610 {
611 AddNextCell(CastValue(value, currentColumnNumber, currentRowNumber), true, null);
612 }
613
614
625 public void AddNextCell(object value, Style style)
626 {
627 AddNextCell(CastValue(value, currentColumnNumber, currentRowNumber), true, style);
628 }
629
630
640 private void AddNextCell(Cell cell, bool incremental, Style style)
641 {
642 // date and time styles are already defined by the passed cell object
643 if (style != null || (activeStyle != null && useActiveStyle))
644 {
645 if (cell.CellStyle == null && useActiveStyle)
646 {
647 cell.SetStyle(activeStyle);
648 }
649 else if (cell.CellStyle == null && style != null)
650 {
651 cell.SetStyle(style);
652 }
653 else if (cell.CellStyle != null && useActiveStyle)
654 {
655 Style mixedStyle = (Style)cell.CellStyle.Copy();
656 mixedStyle.Append(activeStyle);
657 cell.SetStyle(mixedStyle);
658 }
659 else if (cell.CellStyle != null && style != null)
660 {
661 Style mixedStyle = (Style)cell.CellStyle.Copy();
662 mixedStyle.Append(style);
663 cell.SetStyle(mixedStyle);
664 }
665 }
666 cells[new CellKey(cell.ColumnNumber, cell.RowNumber)] = cell;
667 if (incremental)
668 {
669 if (CurrentCellDirection == CellDirection.ColumnToColumn)
670 {
671 currentColumnNumber++;
672 }
673 else if (CurrentCellDirection == CellDirection.RowToRow)
674 {
675 currentRowNumber++;
676 }
677 else
678 {
679 // disabled / no-op
680 }
681 }
682 else
683 {
684 if (CurrentCellDirection == CellDirection.ColumnToColumn)
685 {
686 currentColumnNumber = cell.ColumnNumber + 1;
687 currentRowNumber = cell.RowNumber;
688 }
689 else if (CurrentCellDirection == CellDirection.RowToRow)
690 {
691 currentColumnNumber = cell.ColumnNumber;
692 currentRowNumber = cell.RowNumber + 1;
693 }
694 else
695 {
696 // disabled / no-op
697 }
698 }
699 }
700
708 private static Cell CastValue(object value, int column, int row)
709 {
710 Cell c;
711 if (value != null && value.GetType() == typeof(Cell))
712 {
713 c = (Cell)value;
714 c.CellAddress2 = new Address(column, row);
715 }
716 else
717 {
718 c = new Cell(value, Cell.CellType.Default, column, row);
719 }
720 return c;
721 }
722
723
724 #endregion
725
726 #region methods_AddCell
727
738 public void AddCell(object value, int columnNumber, int rowNumber)
739 {
740 AddNextCell(CastValue(value, columnNumber, rowNumber), false, null);
741 }
742
755 public void AddCell(object value, int columnNumber, int rowNumber, Style style)
756 {
757 AddNextCell(CastValue(value, columnNumber, rowNumber), false, style);
758 }
759
760
771 public void AddCell(object value, string address)
772 {
773 int column;
774 int row;
775 Cell.ResolveCellCoordinate(address, out column, out row);
776 AddCell(value, column, row);
777 }
778
791 public void AddCell(object value, string address, Style style)
792 {
793 int column;
794 int row;
795 Cell.ResolveCellCoordinate(address, out column, out row);
796 AddCell(value, column, row, style);
797 }
798
799 #endregion
800
801 #region methods_AddCellFormula
802
810 public void AddCellFormula(string formula, string address)
811 {
812 int column;
813 int row;
814 Cell.ResolveCellCoordinate(address, out column, out row);
815 Cell c = new Cell(formula, Cell.CellType.Formula, column, row);
816 AddNextCell(c, false, null);
817 }
818
828 public void AddCellFormula(string formula, string address, Style style)
829 {
830 int column;
831 int row;
832 Cell.ResolveCellCoordinate(address, out column, out row);
833 Cell c = new Cell(formula, Cell.CellType.Formula, column, row);
834 AddNextCell(c, false, style);
835 }
836
844 public void AddCellFormula(string formula, int columnNumber, int rowNumber)
845 {
846 Cell c = new Cell(formula, Cell.CellType.Formula, columnNumber, rowNumber);
847 AddNextCell(c, false, null);
848 }
849
858 public void AddCellFormula(string formula, int columnNumber, int rowNumber, Style style)
859 {
860 Cell c = new Cell(formula, Cell.CellType.Formula, columnNumber, rowNumber);
861 AddNextCell(c, false, style);
862 }
863
869 public void AddNextCellFormula(string formula)
870 {
871 Cell c = new Cell(formula, Cell.CellType.Formula, currentColumnNumber, currentRowNumber);
872 AddNextCell(c, true, null);
873 }
874
881 public void AddNextCellFormula(string formula, Style style)
882 {
883 Cell c = new Cell(formula, Cell.CellType.Formula, currentColumnNumber, currentRowNumber);
884 AddNextCell(c, true, style);
885 }
886
887 #endregion
888
889 #region methods_AddCellRange
890
901 public void AddCellRange(IReadOnlyList<object> values, Address startAddress, Address endAddress)
902 {
903 AddCellRangeInternal(values, startAddress, endAddress, null);
904 }
905
918 public void AddCellRange(IReadOnlyList<object> values, Address startAddress, Address endAddress, Style style)
919 {
920 AddCellRangeInternal(values, startAddress, endAddress, style);
921 }
922
933 public void AddCellRange(IReadOnlyList<object> values, string cellRange)
934 {
935 Range range = Cell.ResolveCellRange(cellRange);
936 AddCellRangeInternal(values, range.StartAddress, range.EndAddress, null);
937 }
938
951 public void AddCellRange(IReadOnlyList<object> values, string cellRange, Style style)
952 {
953 Range range = Cell.ResolveCellRange(cellRange);
954 AddCellRangeInternal(values, range.StartAddress, range.EndAddress, style);
955 }
956
966 public void AddCellRange(IReadOnlyList<object> values, Range cellRange)
967 {
968 AddCellRangeInternal(values, cellRange.StartAddress, cellRange.EndAddress, null);
969 }
970
982 public void AddCellRange(IReadOnlyList<object> values, Range cellRange, Style style)
983 {
984 AddCellRangeInternal(values, cellRange.StartAddress, cellRange.EndAddress, style);
985 }
986
998 private void AddCellRangeInternal<T>(IReadOnlyList<T> values, Address startAddress, Address endAddress, Style style)
999 {
1000 if (values == null)
1001 {
1002 throw new RangeException("The passed value list cannot be null");
1003 }
1004 List<Address> addresses = Cell.GetCellRange(startAddress, endAddress) as List<Address>;
1005 if (values.Count != addresses.Count)
1006 {
1007 throw new RangeException("The number of passed values (" + values.Count + ") differs from the number of cells within the range (" + addresses.Count + ")");
1008 }
1009 List<Cell> list = Cell.ConvertArray(values) as List<Cell>;
1010 int len = values.Count;
1011 for (int i = 0; i < len; i++)
1012 {
1013 list[i].RowNumber = addresses[i].Row;
1014 list[i].ColumnNumber = addresses[i].Column;
1015 AddNextCell(list[i], false, style);
1016 }
1017 }
1018 #endregion
1019
1020 #region methods_RemoveCell
1028 public bool RemoveCell(int columnNumber, int rowNumber)
1029 {
1030 return cells.Remove(new CellKey(columnNumber, rowNumber));
1031 }
1032
1040 public bool RemoveCell(string address)
1041 {
1042 int row;
1043 int column;
1044 Cell.ResolveCellCoordinate(address, out column, out row);
1045 return RemoveCell(column, row);
1046 }
1047 #endregion
1048
1049 #region methods_setStyle
1050
1058 public void SetStyle(Range cellRange, Style style)
1059 {
1060 IReadOnlyList<Address> addresses = cellRange.ResolveEnclosedAddresses();
1061 foreach (Address address in addresses)
1062 {
1063 if (cells.TryGetValue(new CellKey(address.Column, address.Row), out Cell existing))
1064 {
1065 if (style == null)
1066 {
1067 existing.RemoveStyle();
1068 }
1069 else
1070 {
1071 existing.SetStyle(style);
1072 }
1073 }
1074 else
1075 {
1076 if (style != null)
1077 {
1078 AddCell(null, address.Column, address.Row, style);
1079 }
1080 }
1081 }
1082 }
1083
1092 public void SetStyle(Address startAddress, Address endAddress, Style style)
1093 {
1094 SetStyle(new Range(startAddress, endAddress), style);
1095 }
1096
1104 public void SetStyle(Address address, Style style)
1105 {
1106 SetStyle(address, address, style);
1107 }
1108
1117 public void SetStyle(string addressExpression, Style style)
1118 {
1119 Cell.AddressScope scope = Cell.GetAddressScope(addressExpression);
1120 if (scope == Cell.AddressScope.SingleAddress)
1121 {
1122 Address address = new Address(addressExpression);
1123 SetStyle(address, style);
1124 }
1125 else if (scope == Cell.AddressScope.Range)
1126 {
1127 Range range = new Range(addressExpression);
1128 SetStyle(range, style);
1129 }
1130 else
1131 {
1132 throw new FormatException("The passed address'" + addressExpression + "' is neither a cell address, nor a range");
1133 }
1134 }
1135
1136 #endregion
1137
1138 #region boundaryFunctions
1146 {
1147 return GetBoundaryNumber(false, true);
1148 }
1149
1157 {
1158 return GetBoundaryDataNumber(false, true, true);
1159 }
1160
1168 {
1169 return GetBoundaryNumber(true, true);
1170 }
1171
1179 {
1180 return GetBoundaryDataNumber(true, true, true);
1181 }
1182
1191 {
1192 return GetBoundaryNumber(false, false);
1193 }
1194
1202 {
1203 return GetBoundaryDataNumber(false, false, true);
1204 }
1205
1213 public int GetLastRowNumber()
1214 {
1215 return GetBoundaryNumber(true, false);
1216 }
1217
1218
1226 {
1227 return GetBoundaryDataNumber(true, false, true);
1228 }
1229
1237
1239 {
1240 int lastRow = GetLastRowNumber();
1241 int lastColumn = GetLastColumnNumber();
1242 if (lastRow < 0 || lastColumn < 0)
1243 {
1244 return null;
1245 }
1246 return new Address(lastColumn, lastRow);
1247 }
1248
1255
1257 {
1258 int lastRow = GetLastDataRowNumber();
1259 int lastColumn = GetLastDataColumnNumber();
1260 if (lastRow < 0 || lastColumn < 0)
1261 {
1262 return null;
1263 }
1264 return new Address(lastColumn, lastRow);
1265 }
1266
1274 {
1275 int firstRow = GetFirstRowNumber();
1276 int firstColumn = GetFirstColumnNumber();
1277 if (firstRow < 0 || firstColumn < 0)
1278 {
1279 return null;
1280 }
1281 return new Address(firstColumn, firstRow);
1282 }
1283
1291 {
1292 int firstRow = GetFirstDataRowNumber();
1293 int firstColumn = GetFirstDataColumnNumber();
1294 if (firstRow < 0 || firstColumn < 0)
1295 {
1296 return null;
1297 }
1298 return new Address(firstColumn, firstRow);
1299 }
1300
1308 private int GetBoundaryDataNumber(bool row, bool min, bool ignoreEmpty)
1309 {
1310 if (cells.Count == 0)
1311 {
1312 return -1;
1313 }
1314 if (!ignoreEmpty)
1315 {
1316 if (row && min)
1317 {
1318 return cells.Values.Min(x => x.RowNumber);
1319 }
1320 else if (row)
1321 {
1322 return cells.Values.Max(x => x.RowNumber);
1323 }
1324 else if (min)
1325 {
1326 return cells.Values.Min(x => x.ColumnNumber);
1327 }
1328 else
1329 {
1330 return cells.Values.Max(x => x.ColumnNumber);
1331 }
1332 }
1333 List<Cell> nonEmptyCells = cells.Values.Where(x => x.Value != null && x.Value.ToString() != string.Empty).ToList();
1334 if (nonEmptyCells.Count == 0)
1335 {
1336 return -1;
1337 }
1338 if (row && min)
1339 {
1340 return nonEmptyCells.Min(x => x.RowNumber);
1341 }
1342 else if (row)
1343 {
1344 return nonEmptyCells.Max(x => x.RowNumber);
1345 }
1346 else if (min)
1347 {
1348 return nonEmptyCells.Min(x => x.ColumnNumber);
1349 }
1350 else
1351 {
1352 return nonEmptyCells.Max(x => x.ColumnNumber);
1353 }
1354 }
1355
1362 private int GetBoundaryNumber(bool row, bool min)
1363 {
1364 int cellBoundary = GetBoundaryDataNumber(row, min, false);
1365 if (row)
1366 {
1367 int heightBoundary = -1;
1368 if (rowHeights.Count > 0)
1369 {
1370 heightBoundary = min ? RowHeights.Min(x => x.Key) : RowHeights.Max(x => x.Key);
1371 }
1372 int hiddenBoundary = -1;
1373 if (hiddenRows.Count > 0)
1374 {
1375 hiddenBoundary = min ? HiddenRows.Min(x => x.Key) : HiddenRows.Max(x => x.Key);
1376 }
1377 return min ? GetMinRow(cellBoundary, heightBoundary, hiddenBoundary) : GetMaxRow(cellBoundary, heightBoundary, hiddenBoundary);
1378 }
1379 else
1380 {
1381 int columnDefBoundary = -1;
1382 if (columns.Count > 0)
1383 {
1384 columnDefBoundary = min ? Columns.Min(x => x.Key) : Columns.Max(x => x.Key);
1385 }
1386 if (min)
1387 {
1388 return cellBoundary >= 0 && cellBoundary < columnDefBoundary ? cellBoundary : columnDefBoundary;
1389 }
1390 else
1391 {
1392 return cellBoundary >= 0 && cellBoundary > columnDefBoundary ? cellBoundary : columnDefBoundary;
1393 }
1394 }
1395 }
1396
1404 private static int GetMaxRow(int cellBoundary, int heightBoundary, int hiddenBoundary)
1405 {
1406 int highest = -1;
1407 if (cellBoundary >= 0)
1408 {
1409 highest = cellBoundary;
1410 }
1411 if (heightBoundary >= 0 && heightBoundary > highest)
1412 {
1413 highest = heightBoundary;
1414 }
1415 if (hiddenBoundary >= 0 && hiddenBoundary > highest)
1416 {
1417 highest = hiddenBoundary;
1418 }
1419 return highest;
1420 }
1421
1429 private static int GetMinRow(int cellBoundary, int heightBoundary, int hiddenBoundary)
1430 {
1431 int lowest = int.MaxValue;
1432 if (cellBoundary >= 0)
1433 {
1434 lowest = cellBoundary;
1435 }
1436 if (heightBoundary >= 0 && heightBoundary < lowest)
1437 {
1438 lowest = heightBoundary;
1439 }
1440 if (hiddenBoundary >= 0 && hiddenBoundary < lowest)
1441 {
1442 lowest = hiddenBoundary;
1443 }
1444 return lowest == int.MaxValue ? -1 : lowest;
1445 }
1446 #endregion
1447
1448 #region Insert-Search-Replace
1449
1458 public void InsertRow(int rowNumber, int numberOfNewRows)
1459 {
1460 // All cells below the first row must receive a new address (row + count);
1461 var upperRow = this.GetRow(rowNumber);
1462
1463 // Identify all cells below the insertion point to adjust their addresses
1464 var cellsToChange = cells.Values.Where(c => c.CellAddress2.Row > rowNumber).ToList();
1465
1466 // Make a copy of the cells to be moved and then delete the original cells;
1467 List<Cell> newCells = new List<Cell>();
1468 foreach (Cell cell in cellsToChange)
1469 {
1470 int row = cell.CellAddress2.Row;
1471 int col = cell.CellAddress2.Column;
1472 Address newAddress = new Address(col, row + numberOfNewRows);
1473 Cell newCell = new Cell(cell.Value, cell.DataType, newAddress);
1474 if (cell.CellStyle != null)
1475 {
1476 newCell.SetStyle(cell.CellStyle);
1477 }
1478 newCells.Add(newCell);
1479 cells.Remove(new CellKey(col, row));
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 {
1491 newCell.SetStyle(cell.CellStyle);
1492 }
1493 cells[new CellKey(newAddress.Column, newAddress.Row)] = newCell;
1494 }
1495 }
1496
1497 // Re-add the displaced cells with their new addresses.
1498 foreach (Cell newCell in newCells)
1499 {
1500 cells[new CellKey(newCell.ColumnNumber, newCell.RowNumber)] = newCell;
1501 }
1502 }
1503
1512 public void InsertColumn(int columnNumber, int numberOfNewColumns)
1513 {
1514 var leftColumn = this.GetColumn(columnNumber);
1515 var cellsToChange = cells.Values.Where(c => c.CellAddress2.Column > columnNumber).ToList();
1516
1517 List<Cell> newCells = new List<Cell>();
1518 foreach (Cell cell in cellsToChange)
1519 {
1520 int row = cell.CellAddress2.Row;
1521 int col = cell.CellAddress2.Column;
1522 Address newAddress = new Address(col + numberOfNewColumns, row);
1523 Cell newCell = new Cell(cell.Value, cell.DataType, newAddress);
1524 if (cell.CellStyle != null)
1525 {
1526 newCell.SetStyle(cell.CellStyle);
1527 }
1528 newCells.Add(newCell);
1529 cells.Remove(new CellKey(col, row));
1530 }
1531
1532 // Fill the gap with new cells, using the same style as the left column.
1533 foreach (Cell cell in leftColumn)
1534 {
1535 for (int i = 0; i < numberOfNewColumns; i++)
1536 {
1537 Address newAddress = new Address(cell.CellAddress2.Column + 1 + i, cell.CellAddress2.Row);
1538 Cell newCell = new Cell(null, Cell.CellType.Empty, newAddress);
1539 if (cell.CellStyle != null)
1540 {
1541 newCell.SetStyle(cell.CellStyle);
1542 }
1543 cells[new CellKey(newAddress.Column, newAddress.Row)] = newCell;
1544 }
1545 }
1546
1547 // Re-add the displaced cells with their new addresses.
1548 foreach (Cell newCell in newCells)
1549 {
1550 cells[new CellKey(newCell.ColumnNumber, newCell.RowNumber)] = newCell;
1551 }
1552 }
1553
1559 public Cell FirstCellByValue(object searchValue)
1560 {
1561 return cells.Values.FirstOrDefault(c => Equals(c.Value, searchValue));
1562 }
1563
1570 public Cell FirstOrDefaultCell(Func<Cell, bool> predicate)
1571 {
1572 return cells.Values.FirstOrDefault(c => c != null && (c.Value == null || predicate(c)));
1573 }
1574
1580 public List<Cell> CellsByValue(object searchValue)
1581 {
1582 return cells.Values.Where(c => Equals(c.Value, searchValue)).ToList();
1583 }
1584
1591 public int ReplaceCellValue(object oldValue, object newValue)
1592 {
1593 int count = 0;
1594 List<Cell> foundCells = this.CellsByValue(oldValue);
1595 foreach (var cell in foundCells)
1596 {
1597 cell.Value = newValue;
1598 count++;
1599 }
1600 return count;
1601 }
1602 #endregion
1603
1604 #region common_methods
1605
1612 {
1613 if (!sheetProtectionValues.Contains(typeOfProtection))
1614 {
1615 if (typeOfProtection == SheetProtectionValue.SelectLockedCells && !sheetProtectionValues.Contains(SheetProtectionValue.SelectUnlockedCells))
1616 {
1617 sheetProtectionValues.Add(SheetProtectionValue.SelectUnlockedCells);
1618 }
1619 sheetProtectionValues.Add(typeOfProtection);
1620 UseSheetProtection = true;
1621 }
1622 }
1623
1629 public void AddHiddenColumn(int columnNumber)
1630 {
1631 SetColumnHiddenState(columnNumber, true);
1632 }
1633
1639 public void AddHiddenColumn(string columnAddress)
1640 {
1641 int columnNumber = Cell.ResolveColumn(columnAddress);
1642 SetColumnHiddenState(columnNumber, true);
1643 }
1644
1650 public void AddHiddenRow(int rowNumber)
1651 {
1652 SetRowHiddenState(rowNumber, true);
1653 }
1654
1658 public void ClearActiveStyle()
1659 {
1660 useActiveStyle = false;
1661 activeStyle = null;
1662 }
1663
1670 public Cell GetCell(Address address)
1671 {
1672 if (!cells.TryGetValue(new CellKey(address.Column, address.Row), out Cell cell))
1673 {
1674 throw new WorksheetException("The cell with the address " + address.GetAddress() + " does not exist in this worksheet");
1675 }
1676 return cell;
1677 }
1678
1686 public Cell GetCell(int columnNumber, int rowNumber)
1687 {
1688 return GetCell(new Address(columnNumber, rowNumber));
1689 }
1690
1698 public bool HasCell(Address address)
1699 {
1700 return cells.ContainsKey(new CellKey(address.Column, address.Row));
1701 }
1702
1712 public bool HasCell(int columnNumber, int rowNumber)
1713 {
1714 return HasCell(new Address(columnNumber, rowNumber));
1715 }
1716
1722 public void ResetColumn(int columnNumber)
1723 {
1724 if (columns.TryGetValue(columnNumber, out var value) && !value.HasAutoFilter) // AutoFilters cannot have gaps
1725 {
1726 columns.Remove(columnNumber);
1727 }
1728 else if (columns.TryGetValue(columnNumber, out var value2))
1729 {
1730 value2.IsHidden = false;
1731 value2.Width = DefaultWorksheetColumnWidth;
1732 }
1733 }
1734
1740 public IReadOnlyList<Cell> GetRow(int rowNumber)
1741 {
1742 List<Cell> list = new List<Cell>();
1743 foreach (Cell cell in cells.Values)
1744 {
1745 if (cell.RowNumber == rowNumber)
1746 {
1747 list.Add(cell);
1748 }
1749 }
1750 list.Sort((c1, c2) => (c1.ColumnNumber.CompareTo(c2.ColumnNumber))); // Lambda sort
1751 return list;
1752 }
1753
1760 public IReadOnlyList<Cell> GetColumn(string columnAddress)
1761 {
1762 int column = Cell.ResolveColumn(columnAddress);
1763 return GetColumn(column);
1764 }
1765
1771 public IReadOnlyList<Cell> GetColumn(int columnNumber)
1772 {
1773 List<Cell> list = new List<Cell>();
1774 foreach (Cell cell in cells.Values)
1775 {
1776 if (cell.ColumnNumber == columnNumber)
1777 {
1778 list.Add(cell);
1779 }
1780 }
1781 list.Sort((c1, c2) => (c1.RowNumber.CompareTo(c2.RowNumber))); // Lambda sort
1782 return list;
1783 }
1784
1790 {
1791 return currentColumnNumber;
1792 }
1793
1799 {
1800 return currentRowNumber;
1801 }
1802
1806 public void GoToNextColumn()
1807 {
1808 currentColumnNumber++;
1809 currentRowNumber = 0;
1810 Cell.ValidateColumnNumber(currentColumnNumber);
1811 }
1812
1819 public void GoToNextColumn(int numberOfColumns, bool keepRowPosition = false)
1820 {
1821 currentColumnNumber += numberOfColumns;
1822 if (!keepRowPosition)
1823 {
1824 currentRowNumber = 0;
1825 }
1826 Cell.ValidateColumnNumber(currentColumnNumber);
1827 }
1828
1832 public void GoToNextRow()
1833 {
1834 currentRowNumber++;
1835 currentColumnNumber = 0;
1836 Cell.ValidateRowNumber(currentRowNumber);
1837 }
1838
1845 public void GoToNextRow(int numberOfRows, bool keepColumnPosition = false)
1846 {
1847 currentRowNumber += numberOfRows;
1848 if (!keepColumnPosition)
1849 {
1850 currentColumnNumber = 0;
1851 }
1852 Cell.ValidateRowNumber(currentRowNumber);
1853 }
1854
1861 public string MergeCells(Range cellRange)
1862 {
1863 return MergeCells(cellRange.StartAddress, cellRange.EndAddress);
1864 }
1865
1873 public string MergeCells(string cellRange)
1874 {
1875 Range range = Cell.ResolveCellRange(cellRange);
1876 return MergeCells(range.StartAddress, range.EndAddress);
1877 }
1878
1886 public string MergeCells(Address startAddress, Address endAddress)
1887 {
1888 string key = startAddress + ":" + endAddress;
1889 Range value = new Range(startAddress, endAddress);
1890 IReadOnlyList<Address> result = value.ResolveEnclosedAddresses();
1891 foreach (KeyValuePair<string, Range> item in mergedCells)
1892 {
1893 if (item.Value.ResolveEnclosedAddresses().Intersect(result).Any())
1894 {
1895 throw new RangeException("The passed range: " + value.ToString() + " contains cells that are already in the defined merge range: " + item.Key);
1896 }
1897 }
1898 mergedCells.Add(key, value);
1899 return key;
1900 }
1901
1905 internal void RecalculateAutoFilter()
1906 {
1907 if (autoFilterRange == null)
1908 { return; }
1909 int start = autoFilterRange.Value.StartAddress.Column;
1910 int end = autoFilterRange.Value.EndAddress.Column;
1911 int endRow = 0;
1912 foreach (Cell item in CellValues)
1913 {
1914 if (item.ColumnNumber < start || item.ColumnNumber > end)
1915 { continue; }
1916 if (item.RowNumber > endRow)
1917 { endRow = item.RowNumber; }
1918 }
1919 Column c;
1920 for (int i = start; i <= end; i++)
1921 {
1922 if (!columns.TryGetValue(i, out var value))
1923 {
1924 c = new Column(i)
1925 {
1926 HasAutoFilter = true
1927 };
1928 columns.Add(i, c);
1929 }
1930 else
1931 {
1932 value.HasAutoFilter = true;
1933 }
1934 }
1935 autoFilterRange = new Range(start, 0, end, endRow);
1936 }
1937
1941 internal void RecalculateColumns()
1942 {
1943 List<int> columnsToDelete = new List<int>();
1944 foreach (KeyValuePair<int, Column> col in columns)
1945 {
1946 if (!col.Value.HasAutoFilter && !col.Value.IsHidden && Comparators.CompareDimensions(col.Value.Width, DefaultWorksheetColumnWidth) == 0 && col.Value.DefaultColumnStyle == null)
1947 {
1948 columnsToDelete.Add(col.Key);
1949 }
1950 }
1951 foreach (int index in columnsToDelete)
1952 {
1953 columns.Remove(index);
1954 }
1955 }
1956
1962 internal void ResolveMergedCells()
1963 {
1964 Style mergeStyle = BasicStyles.MergeCellStyle;
1965 Cell cell;
1966 foreach (KeyValuePair<string, Range> range in MergedCells)
1967 {
1968 int pos = 0;
1969 List<Address> addresses = Cell.GetCellRange(range.Value.StartAddress, range.Value.EndAddress) as List<Address>;
1970 foreach (Address address in addresses)
1971 {
1972 if (!cells.TryGetValue(new CellKey(address.Column, address.Row), out cell))
1973 {
1974 cell = new Cell
1975 {
1976 DataType = Cell.CellType.Empty,
1977 RowNumber = address.Row,
1978 ColumnNumber = address.Column
1979 };
1980 AddCell(cell, cell.ColumnNumber, cell.RowNumber);
1981 }
1982 if (pos != 0)
1983 {
1984 cell.DataType = Cell.CellType.Empty;
1985 if (cell.CellStyle == null)
1986 {
1987 cell.SetStyle(mergeStyle);
1988 }
1989 else
1990 {
1991 Style mixedMergeStyle = cell.CellStyle;
1992 // TODO: There should be a better possibility to identify particular style elements that deviates
1993 mixedMergeStyle.CurrentCellXf.ForceApplyAlignment = mergeStyle.CurrentCellXf.ForceApplyAlignment;
1994 cell.SetStyle(mixedMergeStyle);
1995 }
1996 }
1997 pos++;
1998 }
1999 }
2000 }
2001
2005 public void RemoveAutoFilter()
2006 {
2007 autoFilterRange = null;
2008 }
2009
2015 public void RemoveHiddenColumn(int columnNumber)
2016 {
2017 SetColumnHiddenState(columnNumber, false);
2018 }
2019
2025 public void RemoveHiddenColumn(string columnAddress)
2026 {
2027 int columnNumber = Cell.ResolveColumn(columnAddress);
2028 SetColumnHiddenState(columnNumber, false);
2029 }
2030
2036 public void RemoveHiddenRow(int rowNumber)
2037 {
2038 SetRowHiddenState(rowNumber, false);
2039 }
2040
2046 public void RemoveMergedCells(string range)
2047 {
2048 range = ParserUtils.ToUpper(range);
2049 if (range == null || !mergedCells.ContainsKey(range))
2050 {
2051 throw new RangeException("The cell range " + range + " was not found in the list of merged cell ranges");
2052 }
2053
2054 List<Address> addresses = Cell.GetCellRange(range) as List<Address>;
2055 foreach (Address address in addresses)
2056 {
2057 if (cells.TryGetValue(new CellKey(address.Column, address.Row), out Cell cell))
2058 {
2059 if (BasicStyles.MergeCellStyle.Equals(cell.CellStyle))
2060 {
2061 cell.RemoveStyle();
2062 }
2063 cell.ResolveCellType(); // resets the type
2064 }
2065 }
2066 mergedCells.Remove(range);
2067 }
2068
2073 public void RemoveRowHeight(int rowNumber)
2074 {
2075 if (rowHeights.ContainsKey(rowNumber))
2076 {
2077 rowHeights.Remove(rowNumber);
2078 }
2079 }
2080
2086 {
2087 if (sheetProtectionValues.Contains(value))
2088 {
2089 sheetProtectionValues.Remove(value);
2090 }
2091 }
2092
2097 public void SetActiveStyle(Style style)
2098 {
2099 if (style == null)
2100 {
2101 useActiveStyle = false;
2102 }
2103 else
2104 {
2105 useActiveStyle = true;
2106 }
2107 activeStyle = style;
2108 }
2109
2116 public void SetAutoFilter(int startColumn, int endColumn)
2117 {
2118 string start = Cell.ResolveCellAddress(startColumn, 0);
2119 string end = Cell.ResolveCellAddress(endColumn, 0);
2120 if (endColumn < startColumn)
2121 {
2122 SetAutoFilter(end + ":" + start);
2123 }
2124 else
2125 {
2126 SetAutoFilter(start + ":" + end);
2127 }
2128 }
2129
2136 public void SetAutoFilter(string range)
2137 {
2138 autoFilterRange = Cell.ResolveCellRange(range);
2139 RecalculateAutoFilter();
2140 RecalculateColumns();
2141 }
2142
2149 private void SetColumnHiddenState(int columnNumber, bool state)
2150 {
2151 Cell.ValidateColumnNumber(columnNumber);
2152 if (columns.TryGetValue(columnNumber, out var value))
2153 {
2154 value.IsHidden = state;
2155 }
2156 else if (state)
2157 {
2158 Column c = new Column(columnNumber)
2159 {
2160 IsHidden = true
2161 };
2162 columns.Add(columnNumber, c);
2163 }
2164 if (!columns[columnNumber].IsHidden && Comparators.CompareDimensions(columns[columnNumber].Width, DefaultWorksheetColumnWidth) == 0 && !columns[columnNumber].HasAutoFilter)
2165 {
2166 columns.Remove(columnNumber);
2167 }
2168 }
2169
2176 public void SetColumnWidth(string columnAddress, float width)
2177 {
2178 int columnNumber = Cell.ResolveColumn(columnAddress);
2179 SetColumnWidth(columnNumber, width);
2180 }
2181
2188 public void SetColumnWidth(int columnNumber, float width)
2189 {
2190 Cell.ValidateColumnNumber(columnNumber);
2191 if (width < MinColumnWidth || width > MaxColumnWidth)
2192 {
2193 throw new RangeException("The column width (" + width + ") is out of range. Range is from " + MinColumnWidth + " to " + MaxColumnWidth + " (chars).");
2194 }
2195 if (columns.TryGetValue(columnNumber, out var value))
2196 {
2197 value.Width = width;
2198 }
2199 else
2200 {
2201 Column c = new Column(columnNumber)
2202 {
2203 Width = width
2204 };
2205 columns.Add(columnNumber, c);
2206 }
2207 }
2208
2216 public Style SetColumnDefaultStyle(string columnAddress, Style style)
2217 {
2218 int columnNumber = Cell.ResolveColumn(columnAddress);
2219 return SetColumnDefaultStyle(columnNumber, style);
2220 }
2221
2228 public Style SetColumnDefaultStyle(int columnNumber, Style style)
2229 {
2230 Cell.ValidateColumnNumber(columnNumber);
2231 if (this.columns.TryGetValue(columnNumber, out var value))
2232 {
2233 return value.SetDefaultColumnStyle(style);
2234 }
2235 else
2236 {
2237 Column c = new Column(columnNumber);
2238 Style returnStyle = c.SetDefaultColumnStyle(style);
2239 this.columns.Add(columnNumber, c);
2240 return returnStyle;
2241 }
2242 }
2243
2250 public void SetCurrentCellAddress(int columnNumber, int rowNumber)
2251 {
2252 SetCurrentColumnNumber(columnNumber);
2253 SetCurrentRowNumber(rowNumber);
2254 }
2255
2262 public void SetCurrentCellAddress(string address)
2263 {
2264 int row;
2265 int column;
2266 Cell.ResolveCellCoordinate(address, out column, out row);
2267 SetCurrentCellAddress(column, row);
2268 }
2269
2275 public void SetCurrentColumnNumber(int columnNumber)
2276 {
2277 Cell.ValidateColumnNumber(columnNumber);
2278 currentColumnNumber = columnNumber;
2279 }
2280
2286 public void SetCurrentRowNumber(int rowNumber)
2287 {
2288 Cell.ValidateRowNumber(rowNumber);
2289 currentRowNumber = rowNumber;
2290 }
2291
2296 public void AddSelectedCells(Range range)
2297 {
2298 selectedCells = DataUtils.MergeRange(selectedCells, range).ToList();
2299 }
2300
2306 public void AddSelectedCells(Address startAddress, Address endAddress)
2307 {
2308 AddSelectedCells(new Range(startAddress, endAddress));
2309 }
2310
2315 public void AddSelectedCells(string rangeOrAddress)
2316 {
2317 Range? resolved = ParseRange(rangeOrAddress);
2318 if (resolved != null)
2319 {
2320 AddSelectedCells(resolved.Value);
2321 }
2322 }
2323
2328 public void AddSelectedCells(Address address)
2329 {
2330 AddSelectedCells(new Range(address, address));
2331 }
2332
2337 {
2338 selectedCells.Clear();
2339 }
2340
2346 public void RemoveSelectedCells(Range range)
2347 {
2348 selectedCells = DataUtils.SubtractRange(selectedCells, range).ToList();
2349 }
2350
2355 public void RemoveSelectedCells(String rangeOrAddress)
2356 {
2357 Range? resolved = ParseRange(rangeOrAddress);
2358 if (resolved != null)
2359 {
2360 RemoveSelectedCells(resolved.Value);
2361 }
2362 }
2363
2369 public void RemoveSelectedCells(Address startAddress, Address endAddress)
2370 {
2371 RemoveSelectedCells(new Range(startAddress, endAddress));
2372 }
2373
2378 public void RemoveSelectedCells(Address address)
2379 {
2380 RemoveSelectedCells(new Range(address, address));
2381 }
2382
2387 public void SetSheetProtectionPassword(string password)
2388 {
2389 if (string.IsNullOrEmpty(password))
2390 {
2391 sheetProtectionPassword.UnsetPassword();
2392 UseSheetProtection = false;
2393 }
2394 else
2395 {
2396 sheetProtectionPassword.SetPassword(password);
2397 UseSheetProtection = true;
2398 }
2399 }
2400
2407 public void SetRowHeight(int rowNumber, float height)
2408 {
2409 Cell.ValidateRowNumber(rowNumber);
2410 if (height < MinRowHeight || height > MaxRowHeight)
2411 {
2412 throw new RangeException("The row height (" + height + ") is out of range. Range is from " + MinRowHeight + " to " + MaxRowHeight + " (equals 546px).");
2413 }
2414 if (rowHeights.ContainsKey(rowNumber))
2415 {
2416 rowHeights[rowNumber] = height;
2417 }
2418 else
2419 {
2420 rowHeights.Add(rowNumber, height);
2421 }
2422 }
2423
2430 private void SetRowHiddenState(int rowNumber, bool state)
2431 {
2432 Cell.ValidateRowNumber(rowNumber);
2433 if (hiddenRows.ContainsKey(rowNumber))
2434 {
2435 if (state)
2436 {
2437 hiddenRows[rowNumber] = true;
2438 }
2439 else
2440 {
2441 hiddenRows.Remove(rowNumber);
2442 }
2443 }
2444 else if (state)
2445 {
2446 hiddenRows.Add(rowNumber, true);
2447 }
2448 }
2449
2455 public void SetSheetName(string name)
2456 {
2457 if (string.IsNullOrEmpty(name))
2458 {
2459 throw new FormatException("the worksheet name must be between 1 and " + MaxWorksheetNameLength + " characters");
2460 }
2461 if (name.Length > MaxWorksheetNameLength)
2462 {
2463 throw new FormatException("the worksheet name must be between 1 and " + MaxWorksheetNameLength + " characters");
2464 }
2465 Regex regex = new Regex(@"[\‍[\‍]\*\?/\\‍]");
2466 Match match = regex.Match(name);
2467 if (match.Captures.Count > 0)
2468 {
2469 throw new FormatException(@"the worksheet name must not contain the characters [ ] * ? / \ ");
2470 }
2471 sheetName = name;
2472 }
2473
2480 public void SetSheetName(string name, bool sanitize)
2481 {
2482 if (sanitize)
2483 {
2484 sheetName = ""; // Empty name (temporary) to prevent conflicts during sanitizing
2485 sheetName = SanitizeWorksheetName(name, workbookReference);
2486 }
2487 else
2488 {
2489 SetSheetName(name);
2490 }
2491 }
2492
2499 public void SetHorizontalSplit(float topPaneHeight, Address topLeftCell, WorksheetPane? activePane)
2500 {
2501 SetSplit(null, topPaneHeight, topLeftCell, activePane);
2502 }
2503
2512 public void SetHorizontalSplit(int numberOfRowsFromTop, bool freeze, Address topLeftCell, WorksheetPane? activePane)
2513 {
2514 SetSplit(null, numberOfRowsFromTop, freeze, topLeftCell, activePane);
2515 }
2516
2523 public void SetVerticalSplit(float leftPaneWidth, Address topLeftCell, WorksheetPane? activePane)
2524 {
2525 SetSplit(leftPaneWidth, null, topLeftCell, activePane);
2526 }
2527
2537 public void SetVerticalSplit(int numberOfColumnsFromLeft, bool freeze, Address topLeftCell, WorksheetPane? activePane)
2538 {
2539 SetSplit(numberOfColumnsFromLeft, null, freeze, topLeftCell, activePane);
2540 }
2541
2553 public void SetSplit(int? numberOfColumnsFromLeft, int? numberOfRowsFromTop, bool freeze, Address topLeftCell, WorksheetPane? activePane)
2554 {
2555 if (freeze)
2556 {
2557 if (numberOfColumnsFromLeft != null && topLeftCell.Column < numberOfColumnsFromLeft.Value)
2558 {
2559 throw new WorksheetException("The column number " + topLeftCell.Column +
2560 " is not valid for a frozen, vertical split with the split pane column number " + numberOfColumnsFromLeft.Value);
2561 }
2562 if (numberOfRowsFromTop != null && topLeftCell.Row < numberOfRowsFromTop.Value)
2563 {
2564 throw new WorksheetException("The row number " + topLeftCell.Row +
2565 " is not valid for a frozen, horizontal split height the split pane row number " + numberOfRowsFromTop.Value);
2566 }
2567 }
2568 this.paneSplitLeftWidth = null;
2569 this.paneSplitTopHeight = null;
2570 this.freezeSplitPanes = freeze;
2571 int row = numberOfRowsFromTop != null ? numberOfRowsFromTop.Value : 0;
2572 int column = numberOfColumnsFromLeft != null ? numberOfColumnsFromLeft.Value : 0;
2573 this.paneSplitAddress = new Address(column, row);
2574 this.paneSplitTopLeftCell = topLeftCell;
2575 this.activePane = activePane;
2576 }
2577
2587 public void SetSplit(float? leftPaneWidth, float? topPaneHeight, Address topLeftCell, WorksheetPane? activePane)
2588 {
2589 this.paneSplitLeftWidth = leftPaneWidth;
2590 this.paneSplitTopHeight = topPaneHeight;
2591 this.freezeSplitPanes = null;
2592 this.paneSplitAddress = null;
2593 this.paneSplitTopLeftCell = topLeftCell;
2594 this.activePane = activePane;
2595 }
2596
2600 public void ResetSplit()
2601 {
2602 this.paneSplitLeftWidth = null;
2603 this.paneSplitTopHeight = null;
2604 this.freezeSplitPanes = null;
2605 this.paneSplitAddress = null;
2606 this.paneSplitTopLeftCell = null;
2607 this.activePane = null;
2608 }
2609
2619 public Worksheet Copy()
2620 {
2621 Worksheet copy = new Worksheet();
2622 foreach (Cell cell in this.cells.Values)
2623 {
2624 copy.AddCell(cell.Copy(), cell.ColumnNumber, cell.RowNumber);
2625 }
2626 copy.activePane = this.activePane;
2627 copy.activeStyle = this.activeStyle;
2628 if (this.autoFilterRange.HasValue)
2629 {
2630 copy.autoFilterRange = this.autoFilterRange.Value.Copy();
2631 }
2632 foreach (KeyValuePair<int, Column> column in this.columns)
2633 {
2634 copy.columns.Add(column.Key, column.Value.Copy());
2635 }
2636 copy.CurrentCellDirection = this.CurrentCellDirection;
2637 copy.currentColumnNumber = this.currentColumnNumber;
2638 copy.currentRowNumber = this.currentRowNumber;
2639 copy.defaultColumnWidth = this.defaultColumnWidth;
2640 copy.defaultRowHeight = this.defaultRowHeight;
2641 copy.freezeSplitPanes = this.freezeSplitPanes;
2642 copy.hidden = this.hidden;
2643 foreach (KeyValuePair<int, bool> row in this.hiddenRows)
2644 {
2645 copy.hiddenRows.Add(row.Key, row.Value);
2646 }
2647 foreach (KeyValuePair<string, Range> cell in this.mergedCells)
2648 {
2649 copy.mergedCells.Add(cell.Key, cell.Value.Copy());
2650 }
2651 if (this.paneSplitAddress.HasValue)
2652 {
2653 copy.paneSplitAddress = this.paneSplitAddress.Value.Copy();
2654 }
2655 copy.paneSplitLeftWidth = this.paneSplitLeftWidth;
2656 copy.paneSplitTopHeight = this.paneSplitTopHeight;
2657 if (this.paneSplitTopLeftCell.HasValue)
2658 {
2659 copy.paneSplitTopLeftCell = this.paneSplitTopLeftCell.Value.Copy();
2660 }
2661 foreach (KeyValuePair<int, float> row in this.rowHeights)
2662 {
2663 copy.rowHeights.Add(row.Key, row.Value);
2664 }
2665 foreach (Range range in selectedCells)
2666 {
2667 copy.AddSelectedCells(range);
2668 }
2669 copy.sheetProtectionPassword.CopyFrom(this.sheetProtectionPassword);
2670 foreach (SheetProtectionValue value in this.sheetProtectionValues)
2671 {
2672 copy.sheetProtectionValues.Add(value);
2673 }
2674 copy.useActiveStyle = this.useActiveStyle;
2675 copy.UseSheetProtection = this.UseSheetProtection;
2676 copy.ShowGridLines = this.ShowGridLines;
2677 copy.ShowRowColumnHeaders = this.ShowRowColumnHeaders;
2678 copy.ShowRuler = this.ShowRuler;
2679 copy.ViewType = this.ViewType;
2680 copy.zoomFactor.Clear();
2681 foreach (KeyValuePair<SheetViewType, int> zoomFactor in this.zoomFactor)
2682 {
2683 copy.SetZoomFactor(zoomFactor.Key, zoomFactor.Value);
2684 }
2685 return copy;
2686 }
2687
2695 public void SetZoomFactor(SheetViewType sheetViewType, int zoomFactor)
2696 {
2697 if (zoomFactor != AutoZoomFactor && (zoomFactor < MinZoomFactor || zoomFactor > maxZoomFactor))
2698 {
2699 throw new WorksheetException("The zoom factor " + zoomFactor + " is not valid. Valid are values between " + MinZoomFactor + " and " + maxZoomFactor + ", or " + AutoZoomFactor + " (automatic)");
2700 }
2701 if (this.zoomFactor.ContainsKey(sheetViewType))
2702 {
2703 this.zoomFactor[sheetViewType] = zoomFactor;
2704 }
2705 else
2706 {
2707 this.zoomFactor.Add(sheetViewType, zoomFactor);
2708 }
2709 }
2710
2711
2712
2713 #region static_methods
2721 public static string SanitizeWorksheetName(string input, Workbook workbook)
2722 {
2723 if (string.IsNullOrEmpty(input))
2724 {
2725 input = "Sheet1";
2726 }
2727 int len;
2728 if (input.Length > MaxWorksheetNameLength)
2729 {
2731 }
2732 else
2733 {
2734 len = input.Length;
2735 }
2736 StringBuilder sb = new StringBuilder(MaxWorksheetNameLength);
2737 char c;
2738 for (int i = 0; i < len; i++)
2739 {
2740 c = input[i];
2741 if (c == '[' || c == ']' || c == '*' || c == '?' || c == '\\' || c == '/')
2742 { sb.Append('_'); }
2743 else
2744 { sb.Append(c); }
2745 }
2746 return GetUnusedWorksheetName(sb.ToString(), workbook);
2747 }
2748
2754 private static Range? ParseRange(string rangeOrAddress)
2755 {
2756 if (string.IsNullOrEmpty(rangeOrAddress))
2757 {
2758 return null;
2759 }
2760 Range range;
2761 if (rangeOrAddress.Contains(":"))
2762 {
2763 range = Cell.ResolveCellRange(rangeOrAddress);
2764 }
2765 else
2766 {
2767 Address address = Cell.ResolveCellCoordinate(rangeOrAddress);
2768 range = new Range(address, address);
2769 }
2770 return range;
2771 }
2772
2782 private static string GetUnusedWorksheetName(string name, Workbook workbook)
2783 {
2784 if (workbook == null)
2785 {
2786 throw new WorksheetException("The workbook reference is null");
2787 }
2788 if (!WorksheetExists(name, workbook))
2789 { return name; }
2790 Regex regex = new Regex(@"^(.*?)(\d{1,31})$");
2791 Match match = regex.Match(name);
2792 string prefix = name;
2793 int number = 1;
2794 if (match.Groups.Count > 1)
2795 {
2796 prefix = match.Groups[1].Value;
2797 _ = int.TryParse(match.Groups[2].Value, out number);
2798 // if this failed, the start number is 0 (parsed number was >max. int32)
2799 }
2800 while (true)
2801 {
2802 string numberString = ParserUtils.ToString(number);
2803 if (numberString.Length + prefix.Length > MaxWorksheetNameLength)
2804 {
2805 int endIndex = prefix.Length - (numberString.Length + prefix.Length - MaxWorksheetNameLength);
2806 prefix = prefix.Substring(0, endIndex);
2807 }
2808 string newName = prefix + numberString;
2809 if (!WorksheetExists(newName, workbook))
2810 { return newName; }
2811 number++;
2812 }
2813 }
2814
2821 private static bool WorksheetExists(string name, Workbook workbook)
2822 {
2823 int len = workbook.Worksheets.Count;
2824 for (int i = 0; i < len; i++)
2825 {
2826 if (workbook.Worksheets[i].SheetName == name)
2827 {
2828 return true;
2829 }
2830 }
2831 return false;
2832 }
2833
2837 internal static string GetSheetProtectionName(SheetProtectionValue protection)
2838 {
2839 string output = "";
2840 switch (protection)
2841 {
2842 case SheetProtectionValue.Objects: output = "objects"; break;
2843 case SheetProtectionValue.Scenarios: output = "scenarios"; break;
2844 case SheetProtectionValue.FormatCells: output = "formatCells"; break;
2845 case SheetProtectionValue.FormatColumns: output = "formatColumns"; break;
2846 case SheetProtectionValue.FormatRows: output = "formatRows"; break;
2847 case SheetProtectionValue.InsertColumns: output = "insertColumns"; break;
2848 case SheetProtectionValue.InsertRows: output = "insertRows"; break;
2849 case SheetProtectionValue.InsertHyperlinks: output = "insertHyperlinks"; break;
2850 case SheetProtectionValue.DeleteColumns: output = "deleteColumns"; break;
2851 case SheetProtectionValue.DeleteRows: output = "deleteRows"; break;
2852 case SheetProtectionValue.SelectLockedCells: output = "selectLockedCells"; break;
2853 case SheetProtectionValue.Sort: output = "sort"; break;
2854 case SheetProtectionValue.AutoFilter: output = "autoFilter"; break;
2855 case SheetProtectionValue.PivotTables: output = "pivotTables"; break;
2856 case SheetProtectionValue.SelectUnlockedCells: output = "selectUnlockedCells"; break;
2857 }
2858 return output;
2859 }
2860
2866 internal static WorksheetPane? GetWorksheetPaneEnum(string pane)
2867 {
2868 WorksheetPane? output = null;
2869 switch (pane)
2870 {
2871 case "topLeft": output = WorksheetPane.TopLeft; break;
2872 case "topRight": output = WorksheetPane.TopRight; break;
2873 case "bottomLeft": output = WorksheetPane.BottomLeft; break;
2874 case "bottomRight": output = WorksheetPane.BottomRight; break;
2875 }
2876 return output;
2877 }
2878
2884 internal static SheetViewType GetSheetViewTypeEnum(string viewType)
2885 {
2886 SheetViewType output = SheetViewType.Normal;
2887 switch (viewType)
2888 {
2889 case "pageBreakPreview": output = SheetViewType.PageBreakPreview; break;
2890 case "pageLayout": output = SheetViewType.PageLayout; break;
2891 }
2892 return output;
2893 }
2894 #endregion
2895 #endregion
2896
2897 }
2898}
Class representing a cell of a worksheet.
Definition Cell.cs:23
static Address ResolveCellCoordinate(string address)
Gets the column and row number (zero based) of a cell by the address.
Definition Cell.cs:740
CellType
Enum defines the basic data types of a cell.
Definition Cell.cs:33
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:943
Address CellAddress2
Gets or sets the combined cell Address as Address object.
Definition Cell.cs:109
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:716
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:902
Style CellStyle
Gets the assigned style of the cell.
Definition Cell.cs:123
static Range ResolveCellRange(string range)
Resolves a cell range from the format like A1:B3 or AAD556:AAD1000.
Definition Cell.cs:831
int RowNumber
Gets or sets the number of the row (zero-based).
Definition Cell.cs:146
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:929
static int ResolveColumn(string columnAddress)
Gets the column number from the column address (A - XFD).
Definition Cell.cs:855
CellType DataType
Gets or sets the type of the cell.
Definition Cell.cs:140
AddressScope
Enum to define the scope of a passed address string (used in static context).
Definition Cell.cs:73
int ColumnNumber
Gets or sets the number of the column (zero-based).
Definition Cell.cs:130
Style SetStyle(Style style, bool unmanaged=false)
Sets the style of the cell.
Definition Cell.cs:412
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:626
object Value
Gets or sets the value of the cell (generic object type). When setting a value, the DataType is autom...
Definition Cell.cs:163
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:293
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:37
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:259
void AddCellFormula(string formula, string address, Style style)
Adds a cell formula as string to the defined cell address.
Definition Worksheet.cs:828
WorksheetPane
Enum to define the pane position or active pane in a slip worksheet.
Definition Worksheet.cs:158
@ TopRight
The pane is located in the top right of the split worksheet.
Definition Worksheet.cs:162
@ BottomRight
The pane is located in the bottom right of the split worksheet.
Definition Worksheet.cs:160
@ BottomLeft
The pane is located in the bottom left of the split worksheet.
Definition Worksheet.cs:164
@ TopLeft
The pane is located in the top left of the split worksheet.
Definition Worksheet.cs:166
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:276
int ZoomFactor
Gets or sets the zoom factor of the ViewType of the current worksheet. If AutoZoomFactor,...
Definition Worksheet.cs:515
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:325
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:107
@ RowToRow
The next cell will be on the same column (A1,A2,A3...).
Definition Worksheet.cs:111
@ ColumnToColumn
The next cell will be on the same row (A1,B1,C1...).
Definition Worksheet.cs:109
@ Disabled
The address of the next cell will be not changed when adding a cell (for manual definition of cell ad...
Definition Worksheet.cs:113
int GetLastColumnNumber()
Gets the last existing column number in the current worksheet (zero-based).
WorksheetPane? ActivePane
Gets the active Pane is splitting is applied. The value is nullable. If null, no splitting was defin...
Definition Worksheet.cs:466
bool ShowRuler
Gets or sets whether a ruler is displayed over the column headers. This value only applies if ViewTyp...
Definition Worksheet.cs:491
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:367
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:530
SheetViewType
Enum to define how a worksheet is displayed in the spreadsheet application (Excel).
Definition Worksheet.cs:173
@ PageBreakPreview
The worksheet is displayed with indicators where the page would break if it were printed.
Definition Worksheet.cs:177
@ PageLayout
The worksheet is displayed like it would be printed.
Definition Worksheet.cs:179
@ Normal
The worksheet is displayed without pagination (default).
Definition Worksheet.cs:175
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:881
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:577
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:252
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:54
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:481
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:120
@ PivotTables
If selected, the user can use pivot tables if the worksheets is protected.
Definition Worksheet.cs:149
@ FormatCells
If selected, the user can format cells if the worksheets is protected.
Definition Worksheet.cs:127
@ InsertHyperlinks
If selected, the user can insert hyper links if the worksheets is protected.
Definition Worksheet.cs:137
@ InsertColumns
If selected, the user can insert columns if the worksheets is protected.
Definition Worksheet.cs:133
@ Sort
If selected, the user can sort cells if the worksheets is protected.
Definition Worksheet.cs:145
@ DeleteColumns
If selected, the user can delete columns if the worksheets is protected.
Definition Worksheet.cs:139
@ Scenarios
If selected, the user can edit scenarios if the worksheets is protected.
Definition Worksheet.cs:125
@ DeleteRows
If selected, the user can delete rows if the worksheets is protected.
Definition Worksheet.cs:141
@ FormatColumns
If selected, the user can format columns if the worksheets is protected.
Definition Worksheet.cs:129
@ InsertRows
If selected, the user can insert rows if the worksheets is protected.
Definition Worksheet.cs:135
@ FormatRows
If selected, the user can format rows if the worksheets is protected.
Definition Worksheet.cs:131
@ AutoFilter
If selected, the user can use auto filters if the worksheets is protected.
Definition Worksheet.cs:147
@ Objects
If selected, the user can edit objects if the worksheets is protected.
Definition Worksheet.cs:123
@ SelectUnlockedCells
If selected, the user can select unlocked cells if the worksheets is protected.
Definition Worksheet.cs:151
@ SelectLockedCells
If selected, the user can select locked cells if the worksheets is protected.
Definition Worksheet.cs:143
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:589
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:982
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:41
static readonly float DefaultWorksheetRowHeight
Default row height as constant.
Definition Worksheet.cs:45
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:75
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:444
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,...
IEnumerable< Cell > CellValues
Gets all cells of the worksheet as an enumerable sequence. Preferred over Cells in performance-critic...
Definition Worksheet.cs:237
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:966
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:49
void AddCellFormula(string formula, string address)
Adds a cell formula as string to the defined cell address.
Definition Worksheet.cs:810
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:738
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:497
string SheetName
Gets or sets the name of the worksheet.
Definition Worksheet.cs:341
void AddCellFormula(string formula, int columnNumber, int rowNumber)
Adds a cell formula as string to the defined cell address.
Definition Worksheet.cs:844
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:373
const int AutoZoomFactor
Automatic zoom factor of a worksheet.
Definition Worksheet.cs:90
float? PaneSplitTopHeight
Gets the height of the upper, horizontal split pane, measured from the top of the window....
Definition Worksheet.cs:412
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:456
Cell FirstOrDefaultCell(Func< Cell, bool > predicate)
Searches for the first occurrence of the expression. Example: var cell = worksheet....
Worksheet()
Default Constructor.
Definition Worksheet.cs:545
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:317
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:918
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:360
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:771
static readonly float MinColumnWidth
Minimum column width as constant.
Definition Worksheet.cs:60
void RemoveMergedCells(string range)
Removes the defined merged cell range.
static readonly int MinRowNumber
Minimum row number (zero-based) as constant.
Definition Worksheet.cs:80
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:625
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:301
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:791
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:901
bool ShowRowColumnHeaders
Gets or sets whether the column and row headers are visible on the current worksheet....
Definition Worksheet.cs:486
virtual IPassword SheetProtectionPassword
Password instance of the worksheet protection. If a password was set, the pain text representation an...
Definition Worksheet.cs:351
const int maxZoomFactor
Maximum zoom factor of a worksheet.
Definition Worksheet.cs:99
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:71
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:309
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:434
void AddSelectedCells(Range range)
Adds a range to the selected cells on this worksheet.
IReadOnlyDictionary< string, Cell > Cells
Gets the cells of the worksheet as read-only dictionary with the cell address string as key and the c...
Definition Worksheet.cs:228
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:951
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:933
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:609
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:219
const int MinZoomFactor
Minimum zoom factor of a worksheet. If set to this value, the zoom is set to automatic.
Definition Worksheet.cs:95
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:755
void AddNextCellFormula(string formula)
Adds a formula as string to the next cell position.
Definition Worksheet.cs:869
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:66
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:474
static readonly float MaxRowHeight
Maximum row height as constant.
Definition Worksheet.cs:85
void AddCellFormula(string formula, int columnNumber, int rowNumber, Style style)
Adds a cell formula as string to the defined cell address.
Definition Worksheet.cs:858
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:391
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:245
float? PaneSplitLeftWidth
Gets the width of the left, vertical split pane, measured from the left of the window....
Definition Worksheet.cs:425
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