18using DocumentFormat.OpenXml.Spreadsheet;
20using System.Collections.Generic;
48 private List<string> _filePaths;
49 private Dictionary<string, XLWorkbook> _workbooks;
50 private string _currentSheetName;
51 private int _currentSheetIndex {
get;
set; }
52 List<ExcelHelper.CellDifference> _differences;
53 private int? _insertPosition;
54 private string _insertSeparator;
55 private string _replaceValue;
56 private string _currentCell;
57 private bool _operationPerformed;
58 private bool _isClosed;
59 private List<(
string Sheet,
string Range, IGPALGrid<string> Data)> _rangesData;
67 _filePaths =
new List<string>();
68 _workbooks =
new Dictionary<string, XLWorkbook>();
69 _rangesData =
new List<(
string Sheet,
string Range, IGPALGrid<string> Data)>();
70 _differences =
new List<ExcelHelper.CellDifference>();
72 _insertSeparator =
" ";
73 _operationPerformed =
false;
83 private void ReopenIfClosed()
91 _currentSheetName =
null;
92 _currentSheetIndex = -1;
94 _insertSeparator =
" ";
102 $
"Reopening already closed file [{_gpalFile?.Filenames?.FirstOrDefault() ?? "unknown
"}]",
104 GPALObjectType.Other);
114 private void LoadFile(
string path)
116 if (!_workbooks.ContainsKey(path))
120 _workbooks[path] =
new XLWorkbook(path);
123 $
"Loaded workbook [{path}]",
125 GPALObjectType.GPALExcel);
131 $
"Failed to load workbook [{path}]",
133 GPALObjectType.GPALExcel, ex);
152 if (gpalFile ==
null)
156 "GPALFile cannot be null",
158 GPALObjectType.GPALExcel);
162 _gpalFile = gpalFile;
166 _differences.Clear();
167 _currentSheetName =
null;
168 _currentSheetIndex = -1;
170 _insertSeparator =
" ";
173 _operationPerformed =
false;
175 foreach (var pattern
in gpalFile.
Filenames)
179 string directory = Path.GetDirectoryName(pattern) ?? Directory.GetCurrentDirectory();
180 string fileName = Path.GetFileName(pattern);
181 var matchingFiles = Directory.GetFiles(directory, fileName, SearchOption.TopDirectoryOnly);
182 _filePaths.AddRange(matchingFiles);
188 $
"Failed to resolve wildcard pattern [{pattern}]",
190 GPALObjectType.GPALExcel, ex);
194 _filePaths = _filePaths.Distinct().ToList();
195 foreach (var path
in _filePaths)
213 if (gpalFile ==
null)
217 "GPALFile cannot be null",
219 GPALObjectType.GPALExcel);
223 string path = gpalFile.Last ?? gpalFile.
Filename;
225 _gpalFile = gpalFile;
226 _filePaths =
new List<string> { path };
229 _differences.Clear();
230 _currentSheetName =
null;
231 _currentSheetIndex = -1;
233 _insertSeparator =
" ";
236 _operationPerformed =
false;
238 XLWorkbook made =
new XLWorkbook();
240 made.Worksheets.Add(
"Sheet1");
242 _workbooks[path] = made;
243 _currentSheetIndex = 1;
247 $
"Started workbook [{path}] with one sheet",
249 GPALObjectType.GPALExcel);
265 if (
true ==
string.IsNullOrWhiteSpace(sheetName))
269 "Sheet name cannot be empty",
271 GPALObjectType.GPALExcel);
273 else if (!_workbooks.Any())
277 "No workbooks loaded",
279 GPALObjectType.GPALExcel);
283 foreach (var kvp
in _workbooks)
284 if (
false == kvp.Value.TryGetWorksheet(sheetName, out IXLWorksheet _))
285 kvp.Value.Worksheets.Add(sheetName);
287 _currentSheetName = sheetName;
288 _currentSheetIndex = -1;
307 _operationPerformed =
true;
309 if (
null == grid || 0 == grid.Rows)
313 "No rows to write into the sheet",
315 GPALObjectType.GPALExcel);
317 else if (!_workbooks.Any())
321 "No workbooks loaded",
323 GPALObjectType.GPALExcel);
327 string startCell = _currentCell ??
"A1";
329 foreach (var kvp
in _workbooks)
331 IXLWorksheet worksheet = GetWorksheet(kvp.Value);
333 if (
null == worksheet)
336 $
"No sheet selected in [{kvp.Key}], so there is nowhere to write the rows",
338 GPALObjectType.GPALExcel);
341 IXLCell anchorCell = worksheet.Cell(startCell);
342 int firstRow = anchorCell.Address.RowNumber;
343 int firstColumn = anchorCell.Address.ColumnNumber;
346 foreach (List<string> row
in grid)
348 for (
int column = 0; column < row.Count; column++)
349 worksheet.Cell(firstRow + rowOffset, firstColumn + column).Value = row[column];
356 $
"Wrote [{grid.Rows}] rows into sheet [{worksheet.Name}] of [{kvp.Key}] from [{startCell}]",
358 GPALObjectType.GPALExcel);
375 if (!_workbooks.Any())
379 "No workbooks loaded",
381 GPALObjectType.GPALExcel);
388 foreach (var kvp
in _workbooks)
389 if (1 > sheetIndex || sheetIndex > kvp.Value.Worksheets.Count)
392 if (indexErrors == _workbooks.Count)
395 $
"Invalid sheet index. No workbook contains sheet [{sheetIndex}]",
397 GPALObjectType.GPALExcel);
400 _currentSheetName =
null;
401 _currentSheetIndex = sheetIndex;
417 if (
string.IsNullOrEmpty(sheetName))
421 "Sheet name cannot be empty",
423 GPALObjectType.GPALExcel);
429 foreach (var kvp
in _workbooks)
431 if (!kvp.Value.Worksheets.Any(ws => ws.Name.Equals(sheetName, StringComparison.OrdinalIgnoreCase)))
435 if (nameErrors == _workbooks.Count)
438 $
"Sheet [{sheetName}] not found in any workbooks",
440 GPALObjectType.GPALExcel);
443 _currentSheetName = sheetName;
444 _currentSheetIndex = -1;
462 if (
string.IsNullOrEmpty(range))
466 "Range cannot be empty",
468 GPALObjectType.Other);
472 if (
true == _operationPerformed)
475 _operationPerformed =
false;
476 _differences.Clear();
479 foreach (var kvp
in _workbooks)
481 var worksheet = GetWorksheet(kvp.Value);
484 if (worksheet !=
null)
486 var rangeData = ExcelHelper.ReadRange(worksheet, range);
487 _rangesData.Add((_currentSheetName ?? _currentSheetIndex.ToString() ??
"Sheet1", range, rangeData));
493 $
"Cannot read range [{range}] from [{worksheet?.Name ?? "unknown
"}]: Invalid sheet",
495 GPALObjectType.Other);
502 $
"Failed to read range [{range}] from [{worksheet?.Name ?? "unknown
"}]",
504 GPALObjectType.Other, ex);
522 _operationPerformed =
true;
524 if (!_rangesData.Any())
528 $
"No data to write for range [{range}]",
530 GPALObjectType.Other);
532 else if (
string.IsNullOrEmpty(range))
536 "Range cannot be empty",
538 GPALObjectType.Other);
542 foreach (var kvp
in _workbooks)
546 var worksheet = GetWorksheet(kvp.Value);
547 if (worksheet !=
null)
549 foreach (var rangeData
in _rangesData)
551 ExcelHelper.WriteRange(worksheet, range, rangeData.Data);
558 $
"Cannot write range [{range}] to [{kvp.Key}]: Invalid sheet",
560 GPALObjectType.Other);
567 $
"Failed to write range [{range}] to [{kvp.Key}]",
569 GPALObjectType.Other, ex);
586 _differences.Clear();
589 "Cleared range data and comparison differences",
591 GPALObjectType.GPALExcel);
606 if (
string.IsNullOrEmpty(cell))
610 "Cell address cannot be empty",
612 GPALObjectType.GPALExcel);
632 if (
string.IsNullOrEmpty(value))
636 "Search value cannot be empty",
638 GPALObjectType.GPALExcel);
641 _replaceValue = value;
658 if (
true == _operationPerformed)
661 _operationPerformed =
false;
662 _differences.Clear();
665 if (
string.IsNullOrEmpty(column))
669 "Column cannot be empty",
671 GPALObjectType.GPALExcel);
675 foreach (var kvp
in _workbooks)
679 var worksheet = GetWorksheet(kvp.Value);
680 if (worksheet !=
null)
682 var values = ExcelHelper.GetColumnValues(worksheet, column);
683 var grid =
GPAL.GridForType<
string>();
684 foreach (var value
in values)
685 grid.AddRow(
new List<string> { value });
686 _rangesData.Add((_currentSheetName ?? _currentSheetIndex.ToString() ??
"Sheet1", column, grid));
691 $
"Cannot read column [{column}] from [{kvp.Key}]: Invalid sheet",
693 GPALObjectType.GPALExcel);
699 $
"Failed to read column [{column}] from [{kvp.Key}]",
701 GPALObjectType.GPALExcel, ex);
720 if (
true == _operationPerformed)
723 _operationPerformed =
false;
724 _differences.Clear();
731 $
"Invalid row number [{rowNumber}]",
733 GPALObjectType.GPALExcel);
737 foreach (var kvp
in _workbooks)
741 var worksheet = GetWorksheet(kvp.Value);
742 if (worksheet !=
null)
744 var values = ExcelHelper.GetRowValues(worksheet, rowNumber);
745 var grid =
GPAL.GridForType<
string>();
746 grid.AddRow(values.ToList());
747 _rangesData.Add((_currentSheetName ?? _currentSheetIndex.ToString() ??
"Sheet1", $
"Row{rowNumber}", grid));
754 $
"Cannot read row [{rowNumber}] from [{kvp.Key}]: Invalid sheet",
756 GPALObjectType.GPALExcel);
763 $
"Failed to read row [{rowNumber}] from [{kvp.Key}]",
765 GPALObjectType.GPALExcel, ex);
782 _operationPerformed =
true;
784 if (!_rangesData.Any())
790 GPALObjectType.GPALExcel);
796 var sum = _rangesData
797 .SelectMany(rd => rd.Data.SelectMany(row => row))
798 .Where(v =>
double.TryParse(v, out _))
799 .Sum(v =>
double.Parse(v));
800 result = sum.ToString();
806 $
"Failed to calculate sum",
808 GPALObjectType.GPALExcel, ex);
824 _operationPerformed =
true;
826 if (!_rangesData.Any())
832 GPALObjectType.GPALExcel);
838 var count = _rangesData
839 .SelectMany(rd => rd.Data.SelectMany(row => row))
840 .Count(v => !
string.IsNullOrEmpty(v));
841 result = count.ToString();
847 $
"Failed to calculate count",
849 GPALObjectType.GPALExcel, ex);
864 _operationPerformed =
true;
866 if (!_rangesData.Any())
870 "No range defined for comparison",
872 GPALObjectType.GPALExcel);
876 foreach (var kvp
in _workbooks)
881 foreach (var rangeData
in _rangesData)
885 var ws1 = GetWorksheet(kvp.Value, rangeData.Sheet);
890 $
"Invalid sheet for comparison in [{kvp.Key}]: [{rangeData.Sheet}]",
892 GPALObjectType.GPALExcel);
895 var data1 = ExcelHelper.ReadRange(ws1, rangeData.Range);
896 var differences = ExcelHelper.CompareRanges(data1, data2);
897 foreach (var diff
in differences)
899 _differences.Add(
new ExcelHelper.CellDifference
901 CellAddress = diff.CellAddress,
902 OldValue = diff.OldValue,
903 NewValue = diff.NewValue,
904 SourceRange = rangeData.Range,
913 $
"Failed to compare range [{rangeData.Range}] in [{kvp.Key}]",
915 GPALObjectType.GPALExcel, ex);
923 $
"Failed to compare with grid in [{kvp.Key}]",
925 GPALObjectType.GPALExcel, ex);
942 _operationPerformed =
true;
944 if (gpalFile ==
null)
948 "Comparison file cannot be null",
950 GPALObjectType.GPALExcel);
952 else if (!_rangesData.Any())
956 "No range defined for comparison",
958 GPALObjectType.GPALExcel);
964 var comparePaths =
new List<string>();
965 foreach (var pattern
in gpalFile.
Filenames)
969 string directory = Path.GetDirectoryName(pattern) ?? Directory.GetCurrentDirectory();
970 string fileName = Path.GetFileName(pattern);
971 var matchingFiles = Directory.GetFiles(directory, fileName, SearchOption.TopDirectoryOnly);
972 comparePaths.AddRange(matchingFiles);
978 $
"Failed to resolve wildcard pattern [{pattern}]",
980 GPALObjectType.GPALExcel, ex);
983 comparePaths = comparePaths.Distinct().ToList();
985 foreach (var kvp
in _workbooks)
987 var worksheet = GetWorksheet(kvp.Value);
988 if (worksheet ==
null)
992 $
"Invalid sheet in [{kvp.Key}]",
994 GPALObjectType.GPALExcel);
997 foreach (var comparePath
in comparePaths)
1001 using var compareWorkbook =
new XLWorkbook(comparePath);
1003 var compareWorksheet =
true ==
string.IsNullOrEmpty(_currentSheetName)
1004 ? GetWorksheet(compareWorkbook, _currentSheetIndex)
1005 : GetWorksheet(compareWorkbook, _currentSheetName) ?? GetWorksheet(compareWorkbook, _currentSheetIndex);
1006 if (compareWorksheet ==
null)
1009 GPALEventType.ERROR,
1010 $
"Sheet [{_currentSheetName ?? _currentSheetIndex.ToString()}] not found in [{comparePath}]",
1012 GPALObjectType.GPALExcel);
1015 foreach (var rangeData
in _rangesData)
1019 var data1 = ExcelHelper.ReadRange(worksheet, rangeData.Range);
1020 var data2 = ExcelHelper.ReadRange(compareWorksheet, rangeData.Range);
1021 var differences = ExcelHelper.CompareRanges(data1, data2);
1022 foreach (var diff
in differences)
1024 _differences.Add(
new ExcelHelper.CellDifference
1026 CellAddress = diff.CellAddress,
1027 OldValue = diff.OldValue,
1028 NewValue = diff.NewValue,
1029 SourceRange = rangeData.Range,
1030 TargetRange = $
"{comparePath}:{rangeData.Range}"
1034 catch (Exception ex)
1037 GPALEventType.ERROR,
1038 $
"Failed to compare range [{rangeData.Range}] in [{kvp.Key}] with [{comparePath}]",
1040 GPALObjectType.GPALExcel, ex);
1044 catch (Exception ex)
1047 GPALEventType.ERROR,
1048 $
"Failed to compare [{kvp.Key}] with [{comparePath}]",
1050 GPALObjectType.GPALExcel, ex);
1055 catch (Exception ex)
1058 GPALEventType.EXCEPTION,
1059 $
"Failed to compare with files [{string.Join(",
", gpalFile.Filenames)}]",
1061 GPALObjectType.GPALExcel, ex);
1076 _operationPerformed =
true;
1078 if (!_rangesData.Any())
1081 GPALEventType.ERROR,
1082 "No initial range defined for comparison",
1084 GPALObjectType.GPALExcel);
1086 else if (
string.IsNullOrEmpty(range))
1089 GPALEventType.ERROR,
1090 "Comparison range cannot be empty",
1092 GPALObjectType.GPALExcel);
1096 foreach (var kvp
in _workbooks)
1100 var ws2 = GetWorksheet(kvp.Value);
1104 GPALEventType.ERROR,
1105 $
"Invalid sheet for comparison in [{kvp.Key}]",
1107 GPALObjectType.GPALExcel);
1110 var data2 = ExcelHelper.ReadRange(ws2, range);
1111 foreach (var rangeData
in _rangesData)
1115 var ws1 = GetWorksheet(kvp.Value, rangeData.Sheet);
1119 GPALEventType.ERROR,
1120 $
"Invalid sheet for comparison in [{kvp.Key}]: [{rangeData.Sheet}]",
1122 GPALObjectType.GPALExcel);
1125 var data1 = ExcelHelper.ReadRange(ws1, rangeData.Range);
1126 var differences = ExcelHelper.CompareRanges(data1, data2);
1127 foreach (var diff
in differences)
1129 _differences.Add(
new ExcelHelper.CellDifference
1131 CellAddress = diff.CellAddress,
1132 OldValue = diff.OldValue,
1133 NewValue = diff.NewValue,
1134 SourceRange = rangeData.Range,
1139 catch (Exception ex)
1142 GPALEventType.ERROR,
1143 $
"Failed to compare range [{rangeData.Range}] in [{kvp.Key}]",
1145 GPALObjectType.GPALExcel, ex);
1149 catch (Exception ex)
1152 GPALEventType.ERROR,
1153 $
"Failed to compare ranges in [{kvp.Key}]",
1155 GPALObjectType.GPALExcel, ex);
1173 results =
GPAL.GridForType<
string>();
1174 results.AddRow(
new List<string> {
"File",
"Sheet",
"Cell",
"SourceRange",
"TargetRange",
"OldValue",
"NewValue" });
1178 if (_differences.Any())
1180 foreach (var diff
in _differences)
1182 results.AddRow(
new List<string>
1184 _filePaths.FirstOrDefault() ??
"unknown",
1185 _currentSheetName ?? _currentSheetIndex.ToString(),
1195 catch (Exception ex)
1198 GPALEventType.ERROR,
1199 $
"Failed to get results",
1201 GPALObjectType.GPALExcel, ex);
1219 GPALEventType.ERROR,
1220 $
"Invalid insert position [{position}]",
1222 GPALObjectType.GPALExcel);
1225 _insertPosition = position;
1240 if (
string.IsNullOrEmpty(separator))
1243 GPALEventType.ERROR,
1244 "Insert separator cannot be empty",
1246 GPALObjectType.GPALExcel);
1249 _insertSeparator = separator;
1267 _operationPerformed =
true;
1269 if (_insertPosition ==
null || _insertSeparator ==
null ||
string.IsNullOrEmpty(_currentCell))
1272 GPALEventType.ERROR,
1273 $
"Missing insert position, separator, or cell for value [{value}]",
1275 GPALObjectType.GPALExcel);
1280 foreach (var kvp
in _workbooks)
1284 var worksheet = GetWorksheet(kvp.Value);
1285 if (worksheet !=
null)
1287 var cell = worksheet.Cell(_currentCell);
1288 var currentValue = cell.GetString();
1289 var newValue = _insertPosition == 0 ? $
"{value}{_insertSeparator}{currentValue}" : $
"{currentValue}{_insertSeparator}{value}";
1290 cell.SetValue(newValue);
1295 GPALEventType.ERROR,
1296 $
"Cannot insert value [{value}] in [{kvp.Key}]: Invalid sheet",
1298 GPALObjectType.GPALExcel);
1301 catch (Exception ex)
1304 GPALEventType.ERROR,
1305 $
"Failed to insert value [{value}] at cell [{_currentCell}] in [{kvp.Key}]",
1307 GPALObjectType.GPALExcel, ex);
1325 _operationPerformed =
true;
1327 if (
string.IsNullOrEmpty(_currentCell))
1330 GPALEventType.ERROR,
1331 $
"No cell specified for setting value [{value}]",
1333 GPALObjectType.GPALExcel);
1337 foreach (var kvp
in _workbooks)
1341 var worksheet = GetWorksheet(kvp.Value);
1342 if (worksheet !=
null)
1344 worksheet.Cell(_currentCell).SetValue(value);
1349 GPALEventType.ERROR,
1350 $
"Cannot set value [{value}] in [{kvp.Key}]: Invalid sheet",
1352 GPALObjectType.GPALExcel);
1355 catch (Exception ex)
1358 GPALEventType.ERROR,
1359 $
"Failed to set value [{value}] at cell [{_currentCell}] in [{kvp.Key}]",
1361 GPALObjectType.GPALExcel, ex);
1379 _operationPerformed =
true;
1381 if (
string.IsNullOrEmpty(_currentCell))
1384 GPALEventType.ERROR,
1385 $
"No cell specified for appending value [{value}]",
1387 GPALObjectType.GPALExcel);
1391 foreach (var kvp
in _workbooks)
1395 var worksheet = GetWorksheet(kvp.Value);
1396 if (worksheet !=
null)
1398 var cell = worksheet.Cell(_currentCell);
1399 var currentValue = cell.GetString();
1400 cell.SetValue(currentValue + value);
1405 GPALEventType.ERROR,
1406 $
"Cannot append value [{value}] in [{kvp.Key}]: Invalid sheet",
1408 GPALObjectType.GPALExcel);
1411 catch (Exception ex)
1414 GPALEventType.ERROR,
1415 $
"Failed to append value [{value}] at cell [{_currentCell}] in [{kvp.Key}]",
1417 GPALObjectType.GPALExcel, ex);
1435 _operationPerformed =
true;
1437 if (
string.IsNullOrEmpty(_currentCell))
1440 GPALEventType.ERROR,
1441 $
"No cell specified for prepending value [{value}]",
1443 GPALObjectType.GPALExcel);
1447 foreach (var kvp
in _workbooks)
1451 var worksheet = GetWorksheet(kvp.Value);
1452 if (worksheet !=
null)
1454 var cell = worksheet.Cell(_currentCell);
1455 var currentValue = cell.GetString();
1456 cell.SetValue(value + currentValue);
1461 GPALEventType.ERROR,
1462 $
"Cannot prepend value [{value}] in [{kvp.Key}]: Invalid sheet",
1464 GPALObjectType.GPALExcel);
1467 catch (Exception ex)
1470 GPALEventType.ERROR,
1471 $
"Failed to prepend value [{value}] at cell [{_currentCell}] in [{kvp.Key}]",
1473 GPALObjectType.GPALExcel, ex);
1490 _operationPerformed =
true;
1492 if (
string.IsNullOrEmpty(_replaceValue))
1495 GPALEventType.ERROR,
1496 $
"No search value for replace with [{value}]",
1498 GPALObjectType.GPALExcel);
1500 else if (!_rangesData.Any())
1503 GPALEventType.ERROR,
1504 $
"No range defined for replace with [{value}]",
1506 GPALObjectType.GPALExcel);
1510 foreach (var kvp
in _workbooks)
1514 var worksheet = GetWorksheet(kvp.Value);
1515 if (worksheet ==
null)
1518 GPALEventType.ERROR,
1519 $
"Cannot replace in [{kvp.Key}]: Invalid sheet",
1521 GPALObjectType.GPALExcel);
1525 foreach (var rangeData
in _rangesData)
1527 ExcelHelper.SearchAndReplaceByValue(worksheet, rangeData.Range, _replaceValue, value);
1531 catch (Exception ex)
1534 GPALEventType.ERROR,
1535 $
"Failed to replace [{_replaceValue}] with [{value}] in [{kvp.Key}]",
1537 GPALObjectType.GPALExcel, ex);
1567 results =
GPAL.GridForType<
string>();
1568 results.AddRow(
new List<string> {
"File",
"Sheet",
"Cell",
"Row",
"Column" });
1570 if (
string.IsNullOrEmpty(_replaceValue))
1571 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"No search value, so there is nothing to find. Call .WithSearchValue first",
this, GPALObjectType.GPALExcel);
1572 else if (!_rangesData.Any())
1573 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"No range defined, so there is nothing to search. Call .WithRange first",
this, GPALObjectType.GPALExcel);
1578 foreach (var kvp
in _workbooks)
1582 var worksheet = GetWorksheet(kvp.Value);
1584 if (
null == worksheet)
1585 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"Cannot search in [{kvp.Key}]: Invalid sheet",
this, GPALObjectType.GPALExcel);
1587 foreach (var rangeData
in _rangesData)
1588 foreach (var hit
in ExcelHelper.SearchValue(worksheet, rangeData.Range, _replaceValue))
1590 results.AddRow(
new List<string>
1593 _currentSheetName ?? _currentSheetIndex.ToString(),
1596 hit.Column.ToString()
1602 catch (Exception ex)
1604 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"Failed searching for [{_replaceValue}] in [{kvp.Key}]",
this, GPALObjectType.GPALExcel, ex);
1608 GPAL.
PublishSimpleEvent(GPALEventType.INFO, $
"Searching for [{_replaceValue}] found [{found}] cell(s)",
this, GPALObjectType.GPALExcel);
1624 _operationPerformed =
true;
1625 gpalFile = gpalFile ?? _gpalFile;
1627 if (gpalFile ==
null)
1629 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"No GPALFile specified for save",
this, GPALObjectType.GPALExcel);
1631 else if (!_workbooks.Any())
1633 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"No workbooks loaded to save",
this, GPALObjectType.GPALExcel);
1639 var targetPaths =
new List<string>();
1640 foreach (var pattern
in gpalFile.
Filenames)
1646 if (
false == pattern.Contains(
"*") &&
false == pattern.Contains(
"?"))
1648 targetPaths.Add(pattern);
1652 string directory = Path.GetDirectoryName(pattern) ?? Directory.GetCurrentDirectory();
1653 string fileName = Path.GetFileName(pattern);
1654 var matchingFiles = Directory.GetFiles(directory, fileName, SearchOption.TopDirectoryOnly);
1655 targetPaths.AddRange(matchingFiles);
1657 catch (Exception ex)
1659 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"Failed to resolve save path [{pattern}]",
this, GPALObjectType.GPALExcel, ex);
1662 targetPaths = targetPaths.Distinct().ToList();
1664 if (!targetPaths.Any())
1666 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"No valid target paths resolved from [{string.Join(",
", gpalFile.Filenames)}]",
this, GPALObjectType.GPALExcel);
1670 foreach (var kvp
in _workbooks)
1674 if (targetPaths.Contains(kvp.Key, StringComparer.OrdinalIgnoreCase))
1678 kvp.Value.SaveAs(kvp.Key);
1679 GPAL.
PublishSimpleEvent(GPALEventType.INFO, $
"Saved workbook [{kvp.Key}] to [{kvp.Key}]",
this, GPALObjectType.GPALExcel);
1681 catch (Exception ex)
1683 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"Failed to save workbook [{kvp.Key}] to [{kvp.Key}]",
this, GPALObjectType.GPALExcel, ex);
1688 foreach (var targetPath
in targetPaths)
1692 using var targetWorkbook =
new XLWorkbook();
1693 foreach (var worksheet
in kvp.Value.Worksheets)
1695 var targetWorksheet = targetWorkbook.Worksheets.Add(worksheet.Name);
1696 ExcelHelper.CopyWorksheet(worksheet, targetWorksheet);
1698 targetWorkbook.SaveAs(targetPath);
1699 GPAL.
PublishSimpleEvent(GPALEventType.INFO, $
"Saved unmatched workbook [{kvp.Key}] to [{targetPath}]",
this, GPALObjectType.GPALExcel);
1701 catch (Exception ex)
1703 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"Failed to save unmatched workbook [{kvp.Key}] to [{targetPath}]",
this, GPALObjectType.GPALExcel, ex);
1708 catch (Exception ex)
1710 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"Failed to process workbook [{kvp.Key}]",
this, GPALObjectType.GPALExcel, ex);
1715 catch (Exception ex)
1717 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"Failed to resolve save paths for [{string.Join(",
", gpalFile.Filenames)}]",
this, GPALObjectType.GPALExcel, ex);
1734 grid =
GPAL.GridForType<
string>();
1737 if (!_workbooks.Any() && _filePaths.Any())
1739 foreach (var path
in _filePaths)
1742 if (!_rangesData.Any())
1745 GPALEventType.ERROR,
1746 "No data to save to grid",
1748 GPALObjectType.GPALExcel);
1752 _operationPerformed =
true;
1756 $
"Saving [{_rangesData.Sum(rangeData => rangeData.Data.Count())}] rows from [{_rangesData.Count}] ranges to grid.",
1758 GPALObjectType.GPALExcel);
1762 foreach (var rangeData
in _rangesData)
1764 foreach (var row
in rangeData.Data)
1768 catch (Exception ex)
1771 GPALEventType.ERROR,
1772 $
"Failed to save to grid",
1774 GPALObjectType.GPALExcel, ex);
1791 if (!_workbooks.Any() && _filePaths.Any())
1793 foreach (var path
in _filePaths)
1796 if (!_rangesData.Any())
1799 GPALEventType.ERROR,
1800 $
"No data to write to sheet [{sheetName}]",
1802 GPALObjectType.GPALExcel);
1804 else if (
string.IsNullOrEmpty(sheetName))
1807 GPALEventType.ERROR,
1808 "Sheet name cannot be empty",
1810 GPALObjectType.GPALExcel);
1814 _operationPerformed =
true;
1818 $
"Saving [{_rangesData.Count}] ranges to sheet [{sheetName}] of [{_workbooks.Count}] workbooks.",
1820 GPALObjectType.GPALExcel);
1822 foreach (var kvp
in _workbooks)
1826 var worksheet = kvp.Value.Worksheets.Any(ws => ws.Name.Equals(sheetName, StringComparison.OrdinalIgnoreCase))
1827 ? kvp.Value.Worksheet(sheetName)
1828 : kvp.Value.Worksheets.Add(sheetName);
1830 if (!
string.IsNullOrEmpty(_currentCell))
1832 target = _currentCell;
1833 worksheet.Cell(target).SetValue(_rangesData.Last().Data.SelectMany(row => row).FirstOrDefault() ??
"");
1837 target = _rangesData.Last().Range;
1838 foreach (var rangeData
in _rangesData)
1840 ExcelHelper.WriteRange(worksheet, rangeData.Range, rangeData.Data);
1844 catch (Exception ex)
1847 GPALEventType.ERROR,
1848 $
"Failed to write to sheet [{sheetName}] in [{kvp.Key}]",
1850 GPALObjectType.GPALExcel, ex);
1867 if (!_workbooks.Any() && _filePaths.Any())
1869 foreach (var path
in _filePaths)
1872 if (!_rangesData.Any())
1875 GPALEventType.ERROR,
1876 $
"No data to write to sheet index [{sheetIndex}]",
1878 GPALObjectType.GPALExcel);
1880 else if (sheetIndex < 1)
1883 GPALEventType.ERROR,
1884 $
"Invalid sheet index [{sheetIndex}]",
1886 GPALObjectType.GPALExcel);
1890 _operationPerformed =
true;
1894 $
"Saving [{_rangesData.Count}] ranges to sheet index [{sheetIndex}] of [{_workbooks.Count}] workbooks.",
1896 GPALObjectType.GPALExcel);
1898 foreach (var kvp
in _workbooks)
1902 var worksheet = kvp.Value.Worksheets.ElementAtOrDefault(sheetIndex - 1) ?? kvp.Value.Worksheets.Add($
"Sheet{sheetIndex}");
1904 if (!
string.IsNullOrEmpty(_currentCell))
1906 target = _currentCell;
1907 worksheet.Cell(target).SetValue(_rangesData.Last().Data.SelectMany(row => row).FirstOrDefault() ??
"");
1911 target = _rangesData.Last().Range;
1912 foreach (var rangeData
in _rangesData)
1914 ExcelHelper.WriteRange(worksheet, rangeData.Range, rangeData.Data);
1918 catch (Exception ex)
1921 GPALEventType.ERROR,
1922 $
"Failed to write to sheet index [{sheetIndex}] in [{kvp.Key}]",
1924 GPALObjectType.GPALExcel, ex);
1943 $
"GPALExcel instance already closed [{_gpalFile?.Filenames?.FirstOrDefault() ?? "unknown
"}]",
1945 GPALObjectType.GPALExcel);
1949 _operationPerformed =
false;
1951 foreach (var kvp
in _workbooks)
1957 kvp.Value.SaveAs(kvp.Key);
1959 kvp.Value.Dispose();
1961 catch (Exception ex)
1964 GPALEventType.ERROR,
1965 $
"Failed to close workbook [{kvp.Key}]",
1967 GPALObjectType.GPALExcel, ex);
1972 _rangesData.Clear();
1973 _currentSheetName =
null;
1974 _currentSheetIndex = -1;
1975 _insertPosition = 0;
1976 _insertSeparator =
" ";
1977 _currentCell =
null;
1989 private IXLWorksheet GetWorksheet(XLWorkbook workbook)
1991 if (!
string.IsNullOrEmpty(_currentSheetName))
1993 return workbook.Worksheets.FirstOrDefault(ws => ws.Name.Equals(_currentSheetName, StringComparison.OrdinalIgnoreCase));
1995 if (-1 != _currentSheetIndex)
1998 return workbook.Worksheets.ElementAtOrDefault(_currentSheetIndex - 1);
2011 internal static IXLWorksheet GetWorksheet(XLWorkbook workbook,
string sheetIdentifier)
2015 if (workbook.TryGetWorksheet(sheetIdentifier, out IXLWorksheet worksheet))
2020 if (
int.TryParse(sheetIdentifier, out
int sheetIndex) && sheetIndex > 0)
2024 worksheet = workbook.Worksheet(sheetIndex);
2032 GPAL.PublishSimpleEvent(Enums.GPALEventType.ERROR, $
"Worksheet [{sheetIdentifier}] not found in workbook and no default name provided.");
2035 catch (Exception ex)
2037 GPAL.PublishSimpleEvent(Enums.GPALEventType.EXCEPTION, $
"Failed to get worksheet [{sheetIdentifier}]",
null, Enums.GPALObjectType.None, ex);
2048 internal static IXLWorksheet GetWorksheet(XLWorkbook workbook,
int sheetIndex)
2052 if (
null != workbook.Worksheet(sheetIndex))
2053 return workbook.Worksheet(sheetIndex);
2055 GPAL.PublishSimpleEvent(Enums.GPALEventType.ERROR, $
"Worksheet [{sheetIndex}] not found in workbook and no default name provided.");
2058 catch (Exception ex)
2060 GPAL.PublishSimpleEvent(Enums.GPALEventType.EXCEPTION, $
"Failed to get worksheet [{sheetIndex}]",
null, Enums.GPALObjectType.None, ex);
IAllowExcelOperations WriteRange(string range)
Writes the range data previously read via WithRange(string) (or another data-producing operation) to ...
IAllowExcelOperations ClearRanges()
Clears any range data read via WithRange(string), WithColumn(string), or WithRowNumber(int),...
IAllowExcelSearchAndReplaceSettings WithSearchValue(string value)
Sets the value to search for in subsequent ReplaceWith(string) operations.
IAllowExcelOperations SaveTo(int sheetIndex)
Writes the previously read range data into the sheet at the given 1-based index of every loaded workb...
IAllowExcelSheetSelection WithFile(GPALFile gpalFile)
Resets this instance and loads the workbook(s) matching gpalFile 's filenames (which may include wild...
IAllowExcelOperations CompareToRange(string range)
Compares each previously read range against range on the currently selected sheet of every loaded wo...
IAllowExcelOperations CalculateCount(out string result)
Counts every non-empty value across all previously read range data.
IAllowExcelOperations CompareToFile(GPALFile gpalFile)
Compares each previously read range against the same range/sheet in the workbook(s) matching gpalFile...
IAllowExcelOperations InsertValue(string value)
Inserts value into the cell selected via WithCell(string) on every loaded workbook,...
IAllowExcelOperations SetValue(string value)
Sets the value of the cell selected via WithCell(string) on every loaded workbook,...
IAllowExcelOperations WithSheet(int sheetIndex)
Selects the sheet at the given 1-based index for subsequent Excel operations on every loaded workbook...
void Close(bool saveOnClose)
Closes every loaded workbook, optionally saving each back to its source path first,...
IAllowExcelOperations SaveTo(GPALFile gpalFile)
Saves the loaded workbook(s) to the file(s) matching gpalFile 's filenames (which may include wildcar...
IGPALExcel ToGPALObject()
Returns this instance as an IGPALExcel, completing the fluent configuration chain.
IAllowExcelOperations GetSearchResults(out IGPALGrid< string > results)
Every cell in the range holding the search value, as a grid shaped the way GetCompareResults shapes i...
IAllowExcelSheetSelection WithNewFile(GPALFile gpalFile)
Starts a workbook of the workflow's own at gpalFile , holding one sheet and nothing else....
IAllowExcelOperations WithRange(string range)
Reads the given cell range from the currently selected sheet of every loaded workbook and stores the ...
IAllowExcelOperations ReplaceWith(string value)
Replaces every occurrence of the value set via WithSearchValue(string) with value ,...
IAllowExcelOperations WithNewSheet(string sheetName)
Adds a sheet named sheetName to every loaded workbook and works on it from here. A workbook already ...
IAllowExcelCellSettings WithInsertSeparator(string separator)
Sets the separator that InsertValue(string) places between the inserted value and the cell's existing...
IAllowExcelOperations GetCompareResults(out IGPALGrid< string > results)
Returns the cell-level differences accumulated by the CompareTo* methods (CompareToGrid(IGPALGrid<str...
IAllowExcelOperations InputFrom(IGPALGrid< string > grid)
Writes grid into the current sheet, starting at the cell WithCell(string) named or A1....
IAllowExcelOperations AppendValue(string value)
Appends value to the end of the existing content of the cell selected via WithCell(string) on every ...
IAllowExcelCellSettings WithInsertPosition(int position)
Sets where InsertValue(string) places its value relative to the current cell content: 0 inserts befor...
IAllowExcelCellSettings WithCell(string cell)
Selects a single cell address (e.g. "B3") on the currently selected sheet as the target for subsequen...
IAllowExcelOperations SaveTo(ref IGPALGrid< string > grid)
Appends every row from the previously read range data into grid . The grid is taken by reference bec...
IAllowExcelOperations WithRowNumber(int rowNumber)
Reads every value in the given row from the currently selected sheet of the first loaded workbook tha...
IAllowExcelOperations CompareToGrid(IGPALGrid< string > grid)
Compares each previously read range against grid , recording any cell-level differences for retrieval...
IAllowExcelOperations WithSheet(string sheetName)
Selects the sheet with the given name (case-insensitive) for subsequent Excel operations on every loa...
IAllowExcelOperations WithColumn(string column)
Reads every value in the given column from the currently selected sheet of the first loaded workbook ...
IAllowExcelOperations SaveTo(string sheetName)
Writes the previously read range data into the sheet named sheetName of every loaded workbook,...
IAllowExcelOperations CalculateSum(out string result)
Sums every numeric value across all previously read range data (non-numeric values are ignored).
IAllowExcelOperations PrependValue(string value)
Prepends value to the beginning of the existing content of the cell selected via WithCell(string) on...
GPAL File object instantied with GPAL.File Used to load tokens into a GPALGrid [rows/columns].
List< string > Filenames
Get the list of filenames.
string Filename
We have only one file, accessing it.
Everything starts here, all the GPAL controls and global settings using fluent syntax are here....
static void PublishSimpleEvent(GPALEventType gPALEventType, string msg, dynamic gPALObject=null, Enums.GPALObjectType gPALObjectType=GPALObjectType.None, Exception ex=null)
Publish a message to either the information channel or exception channel (if exception passed in) Pub...