NanoXLSX.Core 3.0.0-rc.3
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 © 2025
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
963 private void AddCellRangeInternal<T>(IReadOnlyList<T> values, Address startAddress, Address endAddress, Style style)
964 {
965 List<Address> addresses = Cell.GetCellRange(startAddress, endAddress) as List<Address>;
966 if (values.Count != addresses.Count)
967 {
968 throw new RangeException("The number of passed values (" + values.Count + ") differs from the number of cells within the range (" + addresses.Count + ")");
969 }
970 List<Cell> list = Cell.ConvertArray(values) as List<Cell>;
971 int len = values.Count;
972 for (int i = 0; i < len; i++)
973 {
974 list[i].RowNumber = addresses[i].Row;
975 list[i].ColumnNumber = addresses[i].Column;
976 AddNextCell(list[i], false, style);
977 }
978 }
979 #endregion
980
981 #region methods_RemoveCell
989 public bool RemoveCell(int columnNumber, int rowNumber)
990 {
991 string address = Cell.ResolveCellAddress(columnNumber, rowNumber);
992 return cells.Remove(address);
993 }
994
1002 public bool RemoveCell(string address)
1003 {
1004 int row;
1005 int column;
1006 Cell.ResolveCellCoordinate(address, out column, out row);
1007 return RemoveCell(column, row);
1008 }
1009 #endregion
1010
1011 #region methods_setStyle
1012
1020 public void SetStyle(Range cellRange, Style style)
1021 {
1022 IReadOnlyList<Address> addresses = cellRange.ResolveEnclosedAddresses();
1023 foreach (Address address in addresses)
1024 {
1025 string key = address.GetAddress();
1026 if (this.cells.ContainsKey(key))
1027 {
1028 if (style == null)
1029 {
1030 cells[key].RemoveStyle();
1031 }
1032 else
1033 {
1034 cells[key].SetStyle(style);
1035 }
1036 }
1037 else
1038 {
1039 if (style != null)
1040 {
1041 AddCell(null, address.Column, address.Row, style);
1042 }
1043 }
1044 }
1045 }
1046
1055 public void SetStyle(Address startAddress, Address endAddress, Style style)
1056 {
1057 SetStyle(new Range(startAddress, endAddress), style);
1058 }
1059
1067 public void SetStyle(Address address, Style style)
1068 {
1069 SetStyle(address, address, style);
1070 }
1071
1080 public void SetStyle(string addressExpression, Style style)
1081 {
1082 Cell.AddressScope scope = Cell.GetAddressScope(addressExpression);
1083 if (scope == Cell.AddressScope.SingleAddress)
1084 {
1085 Address address = new Address(addressExpression);
1086 SetStyle(address, style);
1087 }
1088 else if (scope == Cell.AddressScope.Range)
1089 {
1090 Range range = new Range(addressExpression);
1091 SetStyle(range, style);
1092 }
1093 else
1094 {
1095 throw new FormatException("The passed address'" + addressExpression + "' is neither a cell address, nor a range");
1096 }
1097 }
1098
1099 #endregion
1100
1101 #region boundaryFunctions
1109 {
1110 return GetBoundaryNumber(false, true);
1111 }
1112
1120 {
1121 return GetBoundaryDataNumber(false, true, true);
1122 }
1123
1131 {
1132 return GetBoundaryNumber(true, true);
1133 }
1134
1142 {
1143 return GetBoundaryDataNumber(true, true, true);
1144 }
1145
1154 {
1155 return GetBoundaryNumber(false, false);
1156 }
1157
1165 {
1166 return GetBoundaryDataNumber(false, false, true);
1167 }
1168
1176 public int GetLastRowNumber()
1177 {
1178 return GetBoundaryNumber(true, false);
1179 }
1180
1181
1189 {
1190 return GetBoundaryDataNumber(true, false, true);
1191 }
1192
1200
1202 {
1203 int lastRow = GetLastRowNumber();
1204 int lastColumn = GetLastColumnNumber();
1205 if (lastRow < 0 || lastColumn < 0)
1206 {
1207 return null;
1208 }
1209 return new Address(lastColumn, lastRow);
1210 }
1211
1218
1220 {
1221 int lastRow = GetLastDataRowNumber();
1222 int lastColumn = GetLastDataColumnNumber();
1223 if (lastRow < 0 || lastColumn < 0)
1224 {
1225 return null;
1226 }
1227 return new Address(lastColumn, lastRow);
1228 }
1229
1237 {
1238 int firstRow = GetFirstRowNumber();
1239 int firstColumn = GetFirstColumnNumber();
1240 if (firstRow < 0 || firstColumn < 0)
1241 {
1242 return null;
1243 }
1244 return new Address(firstColumn, firstRow);
1245 }
1246
1254 {
1255 int firstRow = GetFirstDataRowNumber();
1256 int firstColumn = GetFirstDataColumnNumber();
1257 if (firstRow < 0 || firstColumn < 0)
1258 {
1259 return null;
1260 }
1261 return new Address(firstColumn, firstRow);
1262 }
1263
1271 private int GetBoundaryDataNumber(bool row, bool min, bool ignoreEmpty)
1272 {
1273 if (cells.Count == 0)
1274 {
1275 return -1;
1276 }
1277 if (!ignoreEmpty)
1278 {
1279 if (row && min)
1280 {
1281 return cells.Min(x => x.Value.RowNumber);
1282 }
1283 else if (row)
1284 {
1285 return cells.Max(x => x.Value.RowNumber);
1286 }
1287 else if (min)
1288 {
1289 return cells.Min(x => x.Value.ColumnNumber);
1290 }
1291 else
1292 {
1293 return cells.Max(x => x.Value.ColumnNumber);
1294 }
1295 }
1296 List<Cell> nonEmptyCells = cells.Values.Where(x => x.Value != null && x.Value.ToString() != string.Empty).ToList();
1297 if (nonEmptyCells.Count == 0)
1298 {
1299 return -1;
1300 }
1301 if (row && min)
1302 {
1303 return nonEmptyCells.Min(x => x.RowNumber);
1304 }
1305 else if (row)
1306 {
1307 return nonEmptyCells.Max(x => x.RowNumber);
1308 }
1309 else if (min)
1310 {
1311 return nonEmptyCells.Min(x => x.ColumnNumber);
1312 }
1313 else
1314 {
1315 return nonEmptyCells.Max(x => x.ColumnNumber);
1316 }
1317 }
1318
1325 private int GetBoundaryNumber(bool row, bool min)
1326 {
1327 int cellBoundary = GetBoundaryDataNumber(row, min, false);
1328 if (row)
1329 {
1330 int heightBoundary = -1;
1331 if (rowHeights.Count > 0)
1332 {
1333 heightBoundary = min ? RowHeights.Min(x => x.Key) : RowHeights.Max(x => x.Key);
1334 }
1335 int hiddenBoundary = -1;
1336 if (hiddenRows.Count > 0)
1337 {
1338 hiddenBoundary = min ? HiddenRows.Min(x => x.Key) : HiddenRows.Max(x => x.Key);
1339 }
1340 return min ? GetMinRow(cellBoundary, heightBoundary, hiddenBoundary) : GetMaxRow(cellBoundary, heightBoundary, hiddenBoundary);
1341 }
1342 else
1343 {
1344 int columnDefBoundary = -1;
1345 if (columns.Count > 0)
1346 {
1347 columnDefBoundary = min ? Columns.Min(x => x.Key) : Columns.Max(x => x.Key);
1348 }
1349 if (min)
1350 {
1351 return cellBoundary >= 0 && cellBoundary < columnDefBoundary ? cellBoundary : columnDefBoundary;
1352 }
1353 else
1354 {
1355 return cellBoundary >= 0 && cellBoundary > columnDefBoundary ? cellBoundary : columnDefBoundary;
1356 }
1357 }
1358 }
1359
1367 private static int GetMaxRow(int cellBoundary, int heightBoundary, int hiddenBoundary)
1368 {
1369 int highest = -1;
1370 if (cellBoundary >= 0)
1371 {
1372 highest = cellBoundary;
1373 }
1374 if (heightBoundary >= 0 && heightBoundary > highest)
1375 {
1376 highest = heightBoundary;
1377 }
1378 if (hiddenBoundary >= 0 && hiddenBoundary > highest)
1379 {
1380 highest = hiddenBoundary;
1381 }
1382 return highest;
1383 }
1384
1392 private static int GetMinRow(int cellBoundary, int heightBoundary, int hiddenBoundary)
1393 {
1394 int lowest = int.MaxValue;
1395 if (cellBoundary >= 0)
1396 {
1397 lowest = cellBoundary;
1398 }
1399 if (heightBoundary >= 0 && heightBoundary < lowest)
1400 {
1401 lowest = heightBoundary;
1402 }
1403 if (hiddenBoundary >= 0 && hiddenBoundary < lowest)
1404 {
1405 lowest = hiddenBoundary;
1406 }
1407 return lowest == int.MaxValue ? -1 : lowest;
1408 }
1409 #endregion
1410
1411 #region Insert-Search-Replace
1412
1421 public void InsertRow(int rowNumber, int numberOfNewRows)
1422 {
1423 // All cells below the first row must receive a new address (row + count);
1424 var upperRow = this.GetRow(rowNumber);
1425
1426 // Identify all cells below the insertion point to adjust their addresses
1427 var cellsToChange = this.Cells.Where(c => c.Value.CellAddress2.Row > rowNumber).ToList();
1428
1429 // Make a copy of the cells to be moved and then delete the original cells;
1430 Dictionary<string, Cell> newCells = new Dictionary<string, Cell>();
1431 foreach (var cell in cellsToChange)
1432 {
1433 var row = cell.Value.CellAddress2.Row;
1434 var col = cell.Value.CellAddress2.Column;
1435 Address newAddress = new Address(col, row + numberOfNewRows);
1436
1437 Cell newCell = new Cell(cell.Value.Value, cell.Value.DataType, newAddress);
1438 if (cell.Value.CellStyle != null)
1439 {
1440 newCell.SetStyle(cell.Value.CellStyle); // Apply the style from the "old" cell.
1441 }
1442 newCells.Add(newAddress.GetAddress(), newCell);
1443
1444 // Delete the original cells since the key cannot be changed.
1445 this.Cells.Remove(cell.Key);
1446 }
1447
1448 // Fill the gap with new cells, using the same style as the first row.
1449 foreach (Cell cell in upperRow)
1450 {
1451 for (int i = 0; i < numberOfNewRows; i++)
1452 {
1453 Address newAddress = new Address(cell.CellAddress2.Column, cell.CellAddress2.Row + 1 + i);
1454 Cell newCell = new Cell(null, Cell.CellType.Empty, newAddress);
1455 if (cell.CellStyle != null)
1456 newCell.SetStyle(cell.CellStyle);
1457 this.Cells.Add(newAddress.GetAddress(), newCell);
1458 }
1459 }
1460
1461 // Re-add the previous cells from the copy back with a new key.
1462 foreach (KeyValuePair<string, Cell> cellKeyValue in newCells)
1463 {
1464 this.Cells.Add(cellKeyValue.Key, cellKeyValue.Value); //cell.Value is the cell incl. Style etc.
1465 }
1466 }
1467
1476 public void InsertColumn(int columnNumber, int numberOfNewColumns)
1477 {
1478 var leftColumn = this.GetColumn(columnNumber);
1479 var cellsToChange = this.Cells.Where(c => c.Value.CellAddress2.Column > columnNumber).ToList();
1480
1481 Dictionary<string, Cell> newCells = new Dictionary<string, Cell>();
1482 foreach (var cell in cellsToChange)
1483 {
1484 var row = cell.Value.CellAddress2.Row;
1485 var col = cell.Value.CellAddress2.Column;
1486 Address newAddress = new Address(col + numberOfNewColumns, row);
1487
1488 Cell newCell = new Cell(cell.Value.Value, cell.Value.DataType, newAddress);
1489 if (cell.Value.CellStyle != null)
1490 {
1491 newCell.SetStyle(cell.Value.CellStyle); // Apply the style from the "old" cell.
1492 }
1493 newCells.Add(newAddress.GetAddress(), newCell);
1494
1495 // Delete the original cells since the key cannot be changed.
1496 this.Cells.Remove(cell.Key);
1497 }
1498
1499 // Fill the gap with new cells, using the same style as the first row.
1500 foreach (Cell cell in leftColumn)
1501 {
1502 for (int i = 0; i < numberOfNewColumns; i++)
1503 {
1504 Address newAddress = new Address(cell.CellAddress2.Column + 1 + i, cell.CellAddress2.Row);
1505 Cell newCell = new Cell(null, Cell.CellType.Empty, newAddress);
1506 if (cell.CellStyle != null)
1507 newCell.SetStyle(cell.CellStyle);
1508 this.Cells.Add(newAddress.GetAddress(), newCell);
1509 }
1510 }
1511
1512 // Re-add the previous cells from the copy back with a new key.
1513 foreach (KeyValuePair<string, Cell> cellKeyValue in newCells)
1514 {
1515 this.Cells.Add(cellKeyValue.Key, cellKeyValue.Value); //cell.Value is the cell incl. Style etc.
1516 }
1517 }
1518
1524 public Cell FirstCellByValue(object searchValue)
1525 {
1526 var cell = this.Cells.FirstOrDefault(c =>
1527 Equals(c.Value.Value, searchValue))
1528 .Value;
1529 return cell;
1530 }
1531
1538 public Cell FirstOrDefaultCell(Func<Cell, bool> predicate)
1539 {
1540 return this.Cells.Values
1541 .FirstOrDefault(c => c != null && (c.Value == null || predicate(c)));
1542 }
1543
1549 public List<Cell> CellsByValue(object searchValue)
1550 {
1551 return this.Cells.Where(c =>
1552 Equals(c.Value.Value, searchValue))
1553 .Select(c => c.Value)
1554 .ToList();
1555 }
1556
1563 public int ReplaceCellValue(object oldValue, object newValue)
1564 {
1565 int count = 0;
1566 List<Cell> foundCells = this.CellsByValue(oldValue);
1567 foreach (var cell in foundCells)
1568 {
1569 cell.Value = newValue;
1570 count++;
1571 }
1572 return count;
1573 }
1574 #endregion
1575
1576 #region common_methods
1577
1584 {
1585 if (!sheetProtectionValues.Contains(typeOfProtection))
1586 {
1587 if (typeOfProtection == SheetProtectionValue.SelectLockedCells && !sheetProtectionValues.Contains(SheetProtectionValue.SelectUnlockedCells))
1588 {
1589 sheetProtectionValues.Add(SheetProtectionValue.SelectUnlockedCells);
1590 }
1591 sheetProtectionValues.Add(typeOfProtection);
1592 UseSheetProtection = true;
1593 }
1594 }
1595
1601 public void AddHiddenColumn(int columnNumber)
1602 {
1603 SetColumnHiddenState(columnNumber, true);
1604 }
1605
1611 public void AddHiddenColumn(string columnAddress)
1612 {
1613 int columnNumber = Cell.ResolveColumn(columnAddress);
1614 SetColumnHiddenState(columnNumber, true);
1615 }
1616
1622 public void AddHiddenRow(int rowNumber)
1623 {
1624 SetRowHiddenState(rowNumber, true);
1625 }
1626
1630 public void ClearActiveStyle()
1631 {
1632 useActiveStyle = false;
1633 activeStyle = null;
1634 }
1635
1642 public Cell GetCell(Address address)
1643 {
1644 if (!cells.ContainsKey(address.GetAddress()))
1645 {
1646 throw new WorksheetException("The cell with the address " + address.GetAddress() + " does not exist in this worksheet");
1647 }
1648 return cells[address.GetAddress()];
1649 }
1650
1658 public Cell GetCell(int columnNumber, int rowNumber)
1659 {
1660 return GetCell(new Address(columnNumber, rowNumber));
1661 }
1662
1670 public bool HasCell(Address address)
1671 {
1672 return cells.ContainsKey(address.GetAddress());
1673 }
1674
1684 public bool HasCell(int columnNumber, int rowNumber)
1685 {
1686 return HasCell(new Address(columnNumber, rowNumber));
1687 }
1688
1694 public void ResetColumn(int columnNumber)
1695 {
1696 if (columns.ContainsKey(columnNumber) && !columns[columnNumber].HasAutoFilter) // AutoFilters cannot have gaps
1697 {
1698 columns.Remove(columnNumber);
1699 }
1700 else if (columns.ContainsKey(columnNumber))
1701 {
1702 columns[columnNumber].IsHidden = false;
1703 columns[columnNumber].Width = DefaultWorksheetColumnWidth;
1704 }
1705 }
1706
1712 public IReadOnlyList<Cell> GetRow(int rowNumber)
1713 {
1714 List<Cell> list = new List<Cell>();
1715 foreach (KeyValuePair<string, Cell> cell in cells)
1716 {
1717 if (cell.Value.RowNumber == rowNumber)
1718 {
1719 list.Add(cell.Value);
1720 }
1721 }
1722 list.Sort((c1, c2) => (c1.ColumnNumber.CompareTo(c2.ColumnNumber))); // Lambda sort
1723 return list;
1724 }
1725
1732 public IReadOnlyList<Cell> GetColumn(string columnAddress)
1733 {
1734 int column = Cell.ResolveColumn(columnAddress);
1735 return GetColumn(column);
1736 }
1737
1743 public IReadOnlyList<Cell> GetColumn(int columnNumber)
1744 {
1745 List<Cell> list = new List<Cell>();
1746 foreach (KeyValuePair<string, Cell> cell in cells)
1747 {
1748 if (cell.Value.ColumnNumber == columnNumber)
1749 {
1750 list.Add(cell.Value);
1751 }
1752 }
1753 list.Sort((c1, c2) => (c1.RowNumber.CompareTo(c2.RowNumber))); // Lambda sort
1754 return list;
1755 }
1756
1762 {
1763 return currentColumnNumber;
1764 }
1765
1771 {
1772 return currentRowNumber;
1773 }
1774
1778 public void GoToNextColumn()
1779 {
1780 currentColumnNumber++;
1781 currentRowNumber = 0;
1782 Cell.ValidateColumnNumber(currentColumnNumber);
1783 }
1784
1791 public void GoToNextColumn(int numberOfColumns, bool keepRowPosition = false)
1792 {
1793 currentColumnNumber += numberOfColumns;
1794 if (!keepRowPosition)
1795 {
1796 currentRowNumber = 0;
1797 }
1798 Cell.ValidateColumnNumber(currentColumnNumber);
1799 }
1800
1804 public void GoToNextRow()
1805 {
1806 currentRowNumber++;
1807 currentColumnNumber = 0;
1808 Cell.ValidateRowNumber(currentRowNumber);
1809 }
1810
1817 public void GoToNextRow(int numberOfRows, bool keepColumnPosition = false)
1818 {
1819 currentRowNumber += numberOfRows;
1820 if (!keepColumnPosition)
1821 {
1822 currentColumnNumber = 0;
1823 }
1824 Cell.ValidateRowNumber(currentRowNumber);
1825 }
1826
1833 public string MergeCells(Range cellRange)
1834 {
1835 return MergeCells(cellRange.StartAddress, cellRange.EndAddress);
1836 }
1837
1845 public string MergeCells(string cellRange)
1846 {
1847 Range range = Cell.ResolveCellRange(cellRange);
1848 return MergeCells(range.StartAddress, range.EndAddress);
1849 }
1850
1858 public string MergeCells(Address startAddress, Address endAddress)
1859 {
1860 string key = startAddress + ":" + endAddress;
1861 Range value = new Range(startAddress, endAddress);
1862 IReadOnlyList<Address> result = value.ResolveEnclosedAddresses();
1863 foreach (KeyValuePair<string, Range> item in mergedCells)
1864 {
1865 if (item.Value.ResolveEnclosedAddresses().Intersect(result).Any())
1866 {
1867 throw new RangeException("The passed range: " + value.ToString() + " contains cells that are already in the defined merge range: " + item.Key);
1868 }
1869 }
1870 mergedCells.Add(key, value);
1871 return key;
1872 }
1873
1877 internal void RecalculateAutoFilter()
1878 {
1879 if (autoFilterRange == null)
1880 { return; }
1881 int start = autoFilterRange.Value.StartAddress.Column;
1882 int end = autoFilterRange.Value.EndAddress.Column;
1883 int endRow = 0;
1884 foreach (KeyValuePair<string, Cell> item in Cells)
1885 {
1886 if (item.Value.ColumnNumber < start || item.Value.ColumnNumber > end)
1887 { continue; }
1888 if (item.Value.RowNumber > endRow)
1889 { endRow = item.Value.RowNumber; }
1890 }
1891 Column c;
1892 for (int i = start; i <= end; i++)
1893 {
1894 if (!columns.ContainsKey(i))
1895 {
1896 c = new Column(i)
1897 {
1898 HasAutoFilter = true
1899 };
1900 columns.Add(i, c);
1901 }
1902 else
1903 {
1904 columns[i].HasAutoFilter = true;
1905 }
1906 }
1907 autoFilterRange = new Range(start, 0, end, endRow);
1908 }
1909
1913 internal void RecalculateColumns()
1914 {
1915 List<int> columnsToDelete = new List<int>();
1916 foreach (KeyValuePair<int, Column> col in columns)
1917 {
1918 if (!col.Value.HasAutoFilter && !col.Value.IsHidden && Comparators.CompareDimensions(col.Value.Width, DefaultWorksheetColumnWidth) == 0 && col.Value.DefaultColumnStyle == null)
1919 {
1920 columnsToDelete.Add(col.Key);
1921 }
1922 }
1923 foreach (int index in columnsToDelete)
1924 {
1925 columns.Remove(index);
1926 }
1927 }
1928
1934 internal void ResolveMergedCells()
1935 {
1936 Style mergeStyle = BasicStyles.MergeCellStyle;
1937 Cell cell;
1938 foreach (KeyValuePair<string, Range> range in MergedCells)
1939 {
1940 int pos = 0;
1941 List<Address> addresses = Cell.GetCellRange(range.Value.StartAddress, range.Value.EndAddress) as List<Address>;
1942 foreach (Address address in addresses)
1943 {
1944 if (!Cells.ContainsKey(address.GetAddress()))
1945 {
1946 cell = new Cell
1947 {
1948 DataType = Cell.CellType.Empty,
1949 RowNumber = address.Row,
1950 ColumnNumber = address.Column
1951 };
1952 AddCell(cell, cell.ColumnNumber, cell.RowNumber);
1953 }
1954 else
1955 {
1956 cell = Cells[address.GetAddress()];
1957 }
1958 if (pos != 0)
1959 {
1960 cell.DataType = Cell.CellType.Empty;
1961 if (cell.CellStyle == null)
1962 {
1963 cell.SetStyle(mergeStyle);
1964 }
1965 else
1966 {
1967 Style mixedMergeStyle = cell.CellStyle;
1968 // TODO: There should be a better possibility to identify particular style elements that deviates
1969 mixedMergeStyle.CurrentCellXf.ForceApplyAlignment = mergeStyle.CurrentCellXf.ForceApplyAlignment;
1970 cell.SetStyle(mixedMergeStyle);
1971 }
1972 }
1973 pos++;
1974 }
1975 }
1976 }
1977
1981 public void RemoveAutoFilter()
1982 {
1983 autoFilterRange = null;
1984 }
1985
1991 public void RemoveHiddenColumn(int columnNumber)
1992 {
1993 SetColumnHiddenState(columnNumber, false);
1994 }
1995
2001 public void RemoveHiddenColumn(string columnAddress)
2002 {
2003 int columnNumber = Cell.ResolveColumn(columnAddress);
2004 SetColumnHiddenState(columnNumber, false);
2005 }
2006
2012 public void RemoveHiddenRow(int rowNumber)
2013 {
2014 SetRowHiddenState(rowNumber, false);
2015 }
2016
2022 public void RemoveMergedCells(string range)
2023 {
2024 range = ParserUtils.ToUpper(range);
2025 if (range == null || !mergedCells.ContainsKey(range))
2026 {
2027 throw new RangeException("The cell range " + range + " was not found in the list of merged cell ranges");
2028 }
2029
2030 List<Address> addresses = Cell.GetCellRange(range) as List<Address>;
2031 foreach (Address address in addresses)
2032 {
2033 if (cells.ContainsKey(address.GetAddress()))
2034 {
2035 Cell cell = cells[address.GetAddress()];
2037 {
2038 cell.RemoveStyle();
2039 }
2040 cell.ResolveCellType(); // resets the type
2041 }
2042 }
2043 mergedCells.Remove(range);
2044 }
2045
2050 public void RemoveRowHeight(int rowNumber)
2051 {
2052 if (rowHeights.ContainsKey(rowNumber))
2053 {
2054 rowHeights.Remove(rowNumber);
2055 }
2056 }
2057
2063 {
2064 if (sheetProtectionValues.Contains(value))
2065 {
2066 sheetProtectionValues.Remove(value);
2067 }
2068 }
2069
2074 public void SetActiveStyle(Style style)
2075 {
2076 if (style == null)
2077 {
2078 useActiveStyle = false;
2079 }
2080 else
2081 {
2082 useActiveStyle = true;
2083 }
2084 activeStyle = style;
2085 }
2086
2093 public void SetAutoFilter(int startColumn, int endColumn)
2094 {
2095 string start = Cell.ResolveCellAddress(startColumn, 0);
2096 string end = Cell.ResolveCellAddress(endColumn, 0);
2097 if (endColumn < startColumn)
2098 {
2099 SetAutoFilter(end + ":" + start);
2100 }
2101 else
2102 {
2103 SetAutoFilter(start + ":" + end);
2104 }
2105 }
2106
2113 public void SetAutoFilter(string range)
2114 {
2115 autoFilterRange = Cell.ResolveCellRange(range);
2116 RecalculateAutoFilter();
2117 RecalculateColumns();
2118 }
2119
2126 private void SetColumnHiddenState(int columnNumber, bool state)
2127 {
2128 Cell.ValidateColumnNumber(columnNumber);
2129 if (columns.ContainsKey(columnNumber))
2130 {
2131 columns[columnNumber].IsHidden = state;
2132 }
2133 else if (state)
2134 {
2135 Column c = new Column(columnNumber)
2136 {
2137 IsHidden = true
2138 };
2139 columns.Add(columnNumber, c);
2140 }
2141 if (!columns[columnNumber].IsHidden && Comparators.CompareDimensions(columns[columnNumber].Width, DefaultWorksheetColumnWidth) == 0 && !columns[columnNumber].HasAutoFilter)
2142 {
2143 columns.Remove(columnNumber);
2144 }
2145 }
2146
2153 public void SetColumnWidth(string columnAddress, float width)
2154 {
2155 int columnNumber = Cell.ResolveColumn(columnAddress);
2156 SetColumnWidth(columnNumber, width);
2157 }
2158
2165 public void SetColumnWidth(int columnNumber, float width)
2166 {
2167 Cell.ValidateColumnNumber(columnNumber);
2168 if (width < MinColumnWidth || width > MaxColumnWidth)
2169 {
2170 throw new RangeException("The column width (" + width + ") is out of range. Range is from " + MinColumnWidth + " to " + MaxColumnWidth + " (chars).");
2171 }
2172 if (columns.ContainsKey(columnNumber))
2173 {
2174 columns[columnNumber].Width = width;
2175 }
2176 else
2177 {
2178 Column c = new Column(columnNumber)
2179 {
2180 Width = width
2181 };
2182 columns.Add(columnNumber, c);
2183 }
2184 }
2185
2193 public Style SetColumnDefaultStyle(string columnAddress, Style style)
2194 {
2195 int columnNumber = Cell.ResolveColumn(columnAddress);
2196 return SetColumnDefaultStyle(columnNumber, style);
2197 }
2198
2205 public Style SetColumnDefaultStyle(int columnNumber, Style style)
2206 {
2207 Cell.ValidateColumnNumber(columnNumber);
2208 if (this.columns.ContainsKey(columnNumber))
2209 {
2210 return this.columns[columnNumber].SetDefaultColumnStyle(style);
2211 }
2212 else
2213 {
2214 Column c = new Column(columnNumber);
2215 Style returnStyle = c.SetDefaultColumnStyle(style);
2216 this.columns.Add(columnNumber, c);
2217 return returnStyle;
2218 }
2219 }
2220
2227 public void SetCurrentCellAddress(int columnNumber, int rowNumber)
2228 {
2229 SetCurrentColumnNumber(columnNumber);
2230 SetCurrentRowNumber(rowNumber);
2231 }
2232
2239 public void SetCurrentCellAddress(string address)
2240 {
2241 int row;
2242 int column;
2243 Cell.ResolveCellCoordinate(address, out column, out row);
2244 SetCurrentCellAddress(column, row);
2245 }
2246
2252 public void SetCurrentColumnNumber(int columnNumber)
2253 {
2254 Cell.ValidateColumnNumber(columnNumber);
2255 currentColumnNumber = columnNumber;
2256 }
2257
2263 public void SetCurrentRowNumber(int rowNumber)
2264 {
2265 Cell.ValidateRowNumber(rowNumber);
2266 currentRowNumber = rowNumber;
2267 }
2268
2273 public void AddSelectedCells(Range range)
2274 {
2275 selectedCells = DataUtils.MergeRange(selectedCells, range).ToList();
2276 }
2277
2283 public void AddSelectedCells(Address startAddress, Address endAddress)
2284 {
2285 AddSelectedCells(new Range(startAddress, endAddress));
2286 }
2287
2292 public void AddSelectedCells(string rangeOrAddress)
2293 {
2294 Range? resolved = ParseRange(rangeOrAddress);
2295 if (resolved != null)
2296 {
2297 AddSelectedCells(resolved.Value);
2298 }
2299 }
2300
2305 public void AddSelectedCells(Address address)
2306 {
2307 AddSelectedCells(new Range(address, address));
2308 }
2309
2314 {
2315 selectedCells.Clear();
2316 }
2317
2323 public void RemoveSelectedCells(Range range)
2324 {
2325 selectedCells = DataUtils.SubtractRange(selectedCells, range).ToList();
2326 }
2327
2332 public void RemoveSelectedCells(String rangeOrAddress)
2333 {
2334 Range? resolved = ParseRange(rangeOrAddress);
2335 if (resolved != null)
2336 {
2337 RemoveSelectedCells(resolved.Value);
2338 }
2339 }
2340
2346 public void RemoveSelectedCells(Address startAddress, Address endAddress)
2347 {
2348 RemoveSelectedCells(new Range(startAddress, endAddress));
2349 }
2350
2355 public void RemoveSelectedCells(Address address)
2356 {
2357 RemoveSelectedCells(new Range(address, address));
2358 }
2359
2364 public void SetSheetProtectionPassword(string password)
2365 {
2366 if (string.IsNullOrEmpty(password))
2367 {
2368 sheetProtectionPassword.UnsetPassword();
2369 UseSheetProtection = false;
2370 }
2371 else
2372 {
2373 sheetProtectionPassword.SetPassword(password);
2374 UseSheetProtection = true;
2375 }
2376 }
2377
2384 public void SetRowHeight(int rowNumber, float height)
2385 {
2386 Cell.ValidateRowNumber(rowNumber);
2387 if (height < MinRowHeight || height > MaxRowHeight)
2388 {
2389 throw new RangeException("The row height (" + height + ") is out of range. Range is from " + MinRowHeight + " to " + MaxRowHeight + " (equals 546px).");
2390 }
2391 if (rowHeights.ContainsKey(rowNumber))
2392 {
2393 rowHeights[rowNumber] = height;
2394 }
2395 else
2396 {
2397 rowHeights.Add(rowNumber, height);
2398 }
2399 }
2400
2407 private void SetRowHiddenState(int rowNumber, bool state)
2408 {
2409 Cell.ValidateRowNumber(rowNumber);
2410 if (hiddenRows.ContainsKey(rowNumber))
2411 {
2412 if (state)
2413 {
2414 hiddenRows[rowNumber] = true;
2415 }
2416 else
2417 {
2418 hiddenRows.Remove(rowNumber);
2419 }
2420 }
2421 else if (state)
2422 {
2423 hiddenRows.Add(rowNumber, true);
2424 }
2425 }
2426
2432 public void SetSheetName(string name)
2433 {
2434 if (string.IsNullOrEmpty(name))
2435 {
2436 throw new FormatException("the worksheet name must be between 1 and " + MaxWorksheetNameLength + " characters");
2437 }
2438 if (name.Length > MaxWorksheetNameLength)
2439 {
2440 throw new FormatException("the worksheet name must be between 1 and " + MaxWorksheetNameLength + " characters");
2441 }
2442 Regex regex = new Regex(@"[\‍[\‍]\*\?/\\‍]");
2443 Match match = regex.Match(name);
2444 if (match.Captures.Count > 0)
2445 {
2446 throw new FormatException(@"the worksheet name must not contain the characters [ ] * ? / \ ");
2447 }
2448 sheetName = name;
2449 }
2450
2457 public void SetSheetName(string name, bool sanitize)
2458 {
2459 if (sanitize)
2460 {
2461 sheetName = ""; // Empty name (temporary) to prevent conflicts during sanitizing
2462 sheetName = SanitizeWorksheetName(name, workbookReference);
2463 }
2464 else
2465 {
2466 SetSheetName(name);
2467 }
2468 }
2469
2476 public void SetHorizontalSplit(float topPaneHeight, Address topLeftCell, WorksheetPane? activePane)
2477 {
2478 SetSplit(null, topPaneHeight, topLeftCell, activePane);
2479 }
2480
2489 public void SetHorizontalSplit(int numberOfRowsFromTop, bool freeze, Address topLeftCell, WorksheetPane? activePane)
2490 {
2491 SetSplit(null, numberOfRowsFromTop, freeze, topLeftCell, activePane);
2492 }
2493
2500 public void SetVerticalSplit(float leftPaneWidth, Address topLeftCell, WorksheetPane? activePane)
2501 {
2502 SetSplit(leftPaneWidth, null, topLeftCell, activePane);
2503 }
2504
2514 public void SetVerticalSplit(int numberOfColumnsFromLeft, bool freeze, Address topLeftCell, WorksheetPane? activePane)
2515 {
2516 SetSplit(numberOfColumnsFromLeft, null, freeze, topLeftCell, activePane);
2517 }
2518
2530 public void SetSplit(int? numberOfColumnsFromLeft, int? numberOfRowsFromTop, bool freeze, Address topLeftCell, WorksheetPane? activePane)
2531 {
2532 if (freeze)
2533 {
2534 if (numberOfColumnsFromLeft != null && topLeftCell.Column < numberOfColumnsFromLeft.Value)
2535 {
2536 throw new WorksheetException("The column number " + topLeftCell.Column +
2537 " is not valid for a frozen, vertical split with the split pane column number " + numberOfColumnsFromLeft.Value);
2538 }
2539 if (numberOfRowsFromTop != null && topLeftCell.Row < numberOfRowsFromTop.Value)
2540 {
2541 throw new WorksheetException("The row number " + topLeftCell.Row +
2542 " is not valid for a frozen, horizontal split height the split pane row number " + numberOfRowsFromTop.Value);
2543 }
2544 }
2545 this.paneSplitLeftWidth = null;
2546 this.paneSplitTopHeight = null;
2547 this.freezeSplitPanes = freeze;
2548 int row = numberOfRowsFromTop != null ? numberOfRowsFromTop.Value : 0;
2549 int column = numberOfColumnsFromLeft != null ? numberOfColumnsFromLeft.Value : 0;
2550 this.paneSplitAddress = new Address(column, row);
2551 this.paneSplitTopLeftCell = topLeftCell;
2552 this.activePane = activePane;
2553 }
2554
2564 public void SetSplit(float? leftPaneWidth, float? topPaneHeight, Address topLeftCell, WorksheetPane? activePane)
2565 {
2566 this.paneSplitLeftWidth = leftPaneWidth;
2567 this.paneSplitTopHeight = topPaneHeight;
2568 this.freezeSplitPanes = null;
2569 this.paneSplitAddress = null;
2570 this.paneSplitTopLeftCell = topLeftCell;
2571 this.activePane = activePane;
2572 }
2573
2577 public void ResetSplit()
2578 {
2579 this.paneSplitLeftWidth = null;
2580 this.paneSplitTopHeight = null;
2581 this.freezeSplitPanes = null;
2582 this.paneSplitAddress = null;
2583 this.paneSplitTopLeftCell = null;
2584 this.activePane = null;
2585 }
2586
2596 public Worksheet Copy()
2597 {
2598 Worksheet copy = new Worksheet();
2599 foreach (KeyValuePair<string, Cell> cell in this.cells)
2600 {
2601 copy.AddCell(cell.Value.Copy(), cell.Key);
2602 }
2603 copy.activePane = this.activePane;
2604 copy.activeStyle = this.activeStyle;
2605 if (this.autoFilterRange.HasValue)
2606 {
2607 copy.autoFilterRange = this.autoFilterRange.Value.Copy();
2608 }
2609 foreach (KeyValuePair<int, Column> column in this.columns)
2610 {
2611 copy.columns.Add(column.Key, column.Value.Copy());
2612 }
2613 copy.CurrentCellDirection = this.CurrentCellDirection;
2614 copy.currentColumnNumber = this.currentColumnNumber;
2615 copy.currentRowNumber = this.currentRowNumber;
2616 copy.defaultColumnWidth = this.defaultColumnWidth;
2617 copy.defaultRowHeight = this.defaultRowHeight;
2618 copy.freezeSplitPanes = this.freezeSplitPanes;
2619 copy.hidden = this.hidden;
2620 foreach (KeyValuePair<int, bool> row in this.hiddenRows)
2621 {
2622 copy.hiddenRows.Add(row.Key, row.Value);
2623 }
2624 foreach (KeyValuePair<string, Range> cell in this.mergedCells)
2625 {
2626 copy.mergedCells.Add(cell.Key, cell.Value.Copy());
2627 }
2628 if (this.paneSplitAddress.HasValue)
2629 {
2630 copy.paneSplitAddress = this.paneSplitAddress.Value.Copy();
2631 }
2632 copy.paneSplitLeftWidth = this.paneSplitLeftWidth;
2633 copy.paneSplitTopHeight = this.paneSplitTopHeight;
2634 if (this.paneSplitTopLeftCell.HasValue)
2635 {
2636 copy.paneSplitTopLeftCell = this.paneSplitTopLeftCell.Value.Copy();
2637 }
2638 foreach (KeyValuePair<int, float> row in this.rowHeights)
2639 {
2640 copy.rowHeights.Add(row.Key, row.Value);
2641 }
2642 foreach (Range range in selectedCells)
2643 {
2644 copy.AddSelectedCells(range);
2645 }
2646 copy.sheetProtectionPassword.CopyFrom(this.sheetProtectionPassword);
2647 foreach (SheetProtectionValue value in this.sheetProtectionValues)
2648 {
2649 copy.sheetProtectionValues.Add(value);
2650 }
2651 copy.useActiveStyle = this.useActiveStyle;
2652 copy.UseSheetProtection = this.UseSheetProtection;
2653 copy.ShowGridLines = this.ShowGridLines;
2654 copy.ShowRowColumnHeaders = this.ShowRowColumnHeaders;
2655 copy.ShowRuler = this.ShowRuler;
2656 copy.ViewType = this.ViewType;
2657 copy.zoomFactor.Clear();
2658 foreach (KeyValuePair<SheetViewType, int> zoomFactor in this.zoomFactor)
2659 {
2660 copy.SetZoomFactor(zoomFactor.Key, zoomFactor.Value);
2661 }
2662 return copy;
2663 }
2664
2672 public void SetZoomFactor(SheetViewType sheetViewType, int zoomFactor)
2673 {
2674 if (zoomFactor != AutoZoomFactor && (zoomFactor < MinZoomFactor || zoomFactor > maxZoomFactor))
2675 {
2676 throw new WorksheetException("The zoom factor " + zoomFactor + " is not valid. Valid are values between " + MinZoomFactor + " and " + maxZoomFactor + ", or " + AutoZoomFactor + " (automatic)");
2677 }
2678 if (this.zoomFactor.ContainsKey(sheetViewType))
2679 {
2680 this.zoomFactor[sheetViewType] = zoomFactor;
2681 }
2682 else
2683 {
2684 this.zoomFactor.Add(sheetViewType, zoomFactor);
2685 }
2686 }
2687
2688
2689
2690 #region static_methods
2698 public static string SanitizeWorksheetName(string input, Workbook workbook)
2699 {
2700 if (string.IsNullOrEmpty(input))
2701 {
2702 input = "Sheet1";
2703 }
2704 int len;
2705 if (input.Length > MaxWorksheetNameLength)
2706 {
2708 }
2709 else
2710 {
2711 len = input.Length;
2712 }
2713 StringBuilder sb = new StringBuilder(MaxWorksheetNameLength);
2714 char c;
2715 for (int i = 0; i < len; i++)
2716 {
2717 c = input[i];
2718 if (c == '[' || c == ']' || c == '*' || c == '?' || c == '\\' || c == '/')
2719 { sb.Append('_'); }
2720 else
2721 { sb.Append(c); }
2722 }
2723 return GetUnusedWorksheetName(sb.ToString(), workbook);
2724 }
2725
2731 private static Range? ParseRange(string rangeOrAddress)
2732 {
2733 if (string.IsNullOrEmpty(rangeOrAddress))
2734 {
2735 return null;
2736 }
2737 Range range;
2738 if (rangeOrAddress.Contains(":"))
2739 {
2740 range = Cell.ResolveCellRange(rangeOrAddress);
2741 }
2742 else
2743 {
2744 Address address = Cell.ResolveCellCoordinate(rangeOrAddress);
2745 range = new Range(address, address);
2746 }
2747 return range;
2748 }
2749
2759 private static string GetUnusedWorksheetName(string name, Workbook workbook)
2760 {
2761 if (workbook == null)
2762 {
2763 throw new WorksheetException("The workbook reference is null");
2764 }
2765 if (!WorksheetExists(name, workbook))
2766 { return name; }
2767 Regex regex = new Regex(@"^(.*?)(\d{1,31})$");
2768 Match match = regex.Match(name);
2769 string prefix = name;
2770 int number = 1;
2771 if (match.Groups.Count > 1)
2772 {
2773 prefix = match.Groups[1].Value;
2774 _ = int.TryParse(match.Groups[2].Value, out number);
2775 // if this failed, the start number is 0 (parsed number was >max. int32)
2776 }
2777 while (true)
2778 {
2779 string numberString = ParserUtils.ToString(number);
2780 if (numberString.Length + prefix.Length > MaxWorksheetNameLength)
2781 {
2782 int endIndex = prefix.Length - (numberString.Length + prefix.Length - MaxWorksheetNameLength);
2783 prefix = prefix.Substring(0, endIndex);
2784 }
2785 string newName = prefix + numberString;
2786 if (!WorksheetExists(newName, workbook))
2787 { return newName; }
2788 number++;
2789 }
2790 }
2791
2798 private static bool WorksheetExists(string name, Workbook workbook)
2799 {
2800 int len = workbook.Worksheets.Count;
2801 for (int i = 0; i < len; i++)
2802 {
2803 if (workbook.Worksheets[i].SheetName == name)
2804 {
2805 return true;
2806 }
2807 }
2808 return false;
2809 }
2810
2814 internal static string GetSheetProtectionName(SheetProtectionValue protection)
2815 {
2816 string output = "";
2817 switch (protection)
2818 {
2819 case SheetProtectionValue.Objects: output = "objects"; break;
2820 case SheetProtectionValue.Scenarios: output = "scenarios"; break;
2821 case SheetProtectionValue.FormatCells: output = "formatCells"; break;
2822 case SheetProtectionValue.FormatColumns: output = "formatColumns"; break;
2823 case SheetProtectionValue.FormatRows: output = "formatRows"; break;
2824 case SheetProtectionValue.InsertColumns: output = "insertColumns"; break;
2825 case SheetProtectionValue.InsertRows: output = "insertRows"; break;
2826 case SheetProtectionValue.InsertHyperlinks: output = "insertHyperlinks"; break;
2827 case SheetProtectionValue.DeleteColumns: output = "deleteColumns"; break;
2828 case SheetProtectionValue.DeleteRows: output = "deleteRows"; break;
2829 case SheetProtectionValue.SelectLockedCells: output = "selectLockedCells"; break;
2830 case SheetProtectionValue.Sort: output = "sort"; break;
2831 case SheetProtectionValue.AutoFilter: output = "autoFilter"; break;
2832 case SheetProtectionValue.PivotTables: output = "pivotTables"; break;
2833 case SheetProtectionValue.SelectUnlockedCells: output = "selectUnlockedCells"; break;
2834 }
2835 return output;
2836 }
2837
2843 internal static WorksheetPane? GetWorksheetPaneEnum(string pane)
2844 {
2845 WorksheetPane? output = null;
2846 switch (pane)
2847 {
2848 case "topLeft": output = WorksheetPane.TopLeft; break;
2849 case "topRight": output = WorksheetPane.TopRight; break;
2850 case "bottomLeft": output = WorksheetPane.BottomLeft; break;
2851 case "bottomRight": output = WorksheetPane.BottomRight; break;
2852 }
2853 return output;
2854 }
2855
2861 internal static SheetViewType GetSheetViewTypeEnum(string viewType)
2862 {
2863 SheetViewType output = SheetViewType.Normal;
2864 switch (viewType)
2865 {
2866 case "pageBreakPreview": output = SheetViewType.PageBreakPreview; break;
2867 case "pageLayout": output = SheetViewType.PageLayout; break;
2868 }
2869 return output;
2870 }
2871 #endregion
2872 #endregion
2873
2874 }
2875}
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:23
List< Worksheet > Worksheets
Gets the list of worksheets in the workbook.
Definition Workbook.cs:129
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 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.
Definition Worksheet.cs:989
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 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