diff --git a/QWERTYkez.ExcelProcessor/Editors/ExcelSheet.cs b/QWERTYkez.ExcelProcessor/Editors/ExcelSheet.cs index d4cdcad..8e4cd11 100644 --- a/QWERTYkez.ExcelProcessor/Editors/ExcelSheet.cs +++ b/QWERTYkez.ExcelProcessor/Editors/ExcelSheet.cs @@ -212,20 +212,63 @@ internal sealed class ExcelSheet : ISheet /// public IRange RangeByIndexes(uint startRow, uint startCol, uint endRow, uint endCol) { - return new ExcelRange(Book, this, startRow, startCol, endRow, endCol); + if (startRow == 0) throw new ArgumentException("startRow must be >= 1", nameof(startRow)); + if (startCol == 0) throw new ArgumentException("startCol must be >= 1", nameof(startCol)); + if (endRow == 0) throw new ArgumentException("endRow must be >= 1", nameof(endRow)); + if (endCol == 0) throw new ArgumentException("endCol must be >= 1", nameof(endCol)); + + // Приводим к корректному порядку (пользователь мог передать start > end) + uint rowStart = Math.Min(startRow, endRow); + uint rowEnd = Math.Max(startRow, endRow); + uint colStart = Math.Min(startCol, endCol); + uint colEnd = Math.Max(startCol, endCol); + + return new ExcelRange(Book, this, rowStart, colStart, rowEnd, colEnd); } /// public IRange RangeByIndexes(uint startRow, string startCol, uint endRow, string endCol) { + if (string.IsNullOrEmpty(startCol)) throw new ArgumentException("startCol cannot be null or empty", nameof(startCol)); + if (string.IsNullOrEmpty(endCol)) throw new ArgumentException("endCol cannot be null or empty", nameof(endCol)); + uint startColIdx = CellAddressHelper.ColumnLetterToIndex(startCol); uint endColIdx = CellAddressHelper.ColumnLetterToIndex(endCol); - return new ExcelRange(Book, this, startRow, startColIdx, endRow, endColIdx); + if (startColIdx == 0) throw new ArgumentException($"Invalid column letter: '{startCol}'", nameof(startCol)); + if (endColIdx == 0) throw new ArgumentException($"Invalid column letter: '{endCol}'", nameof(endCol)); + + return RangeByIndexes(startRow, startColIdx, endRow, endColIdx); + } + + /// + public IRange RangeByLength(uint startRow, uint startCol, uint rows, uint cols) + { + if (startRow == 0) throw new ArgumentException("startRow must be >= 1", nameof(startRow)); + if (startCol == 0) throw new ArgumentException("startCol must be >= 1", nameof(startCol)); + if (rows == 0) throw new ArgumentException("rows must be > 0", nameof(rows)); + if (cols == 0) throw new ArgumentException("cols must be > 0", nameof(cols)); + + checked + { + uint endRow = startRow + rows - 1; + uint endCol = startCol + cols - 1; + return new ExcelRange(Book, this, startRow, startCol, endRow, endCol); + } + } + + /// + public IRange RangeByLength(uint startRow, string startCol, uint rows, uint cols) + { + if (string.IsNullOrEmpty(startCol)) throw new ArgumentException("startCol cannot be null or empty", nameof(startCol)); + uint startColIdx = CellAddressHelper.ColumnLetterToIndex(startCol); + if (startColIdx == 0) throw new ArgumentException($"Invalid column letter: '{startCol}'", nameof(startCol)); + return RangeByLength(startRow, startColIdx, rows, cols); } /// public ISheet RangeByIndexes(uint startRow, uint startCol, uint endRow, uint endCol, Action edit) { + if (edit is null) throw new ArgumentNullException(nameof(edit)); var range = RangeByIndexes(startRow, startCol, endRow, endCol); edit(range); return this; @@ -234,31 +277,16 @@ internal sealed class ExcelSheet : ISheet /// public ISheet RangeByIndexes(uint startRow, string startCol, uint endRow, string endCol, Action edit) { + if (edit is null) throw new ArgumentNullException(nameof(edit)); var range = RangeByIndexes(startRow, startCol, endRow, endCol); edit(range); return this; } - /// - public IRange RangeByLength(uint startRow, uint startCol, uint rows, uint cols) - { - if (rows == 0 || cols == 0) - throw new ArgumentException("Rows and columns must be greater than 0"); - uint endRow = startRow + rows - 1; - uint endCol = startCol + cols - 1; - return new ExcelRange(Book, this, startRow, startCol, endRow, endCol); - } - - /// - public IRange RangeByLength(uint startRow, string startCol, uint rows, uint cols) - { - uint startColIdx = CellAddressHelper.ColumnLetterToIndex(startCol); - return RangeByLength(startRow, startColIdx, rows, cols); - } - /// public ISheet RangeByLength(uint startRow, uint startCol, uint rows, uint cols, Action edit) { + if (edit is null) throw new ArgumentNullException(nameof(edit)); var range = RangeByLength(startRow, startCol, rows, cols); edit(range); return this; @@ -267,6 +295,7 @@ internal sealed class ExcelSheet : ISheet /// public ISheet RangeByLength(uint startRow, string startCol, uint rows, uint cols, Action edit) { + if (edit is null) throw new ArgumentNullException(nameof(edit)); var range = RangeByLength(startRow, startCol, rows, cols); edit(range); return this; @@ -274,4 +303,27 @@ internal sealed class ExcelSheet : ISheet #endregion + + + + #region Merge Operations + + /// + public bool TryMergeByIndexes(uint startRow, uint startCol, uint endRow, uint endCol) => + RangeByIndexes(startRow, startCol, endRow, endCol).TryMerge(); + + /// + public bool TryMergeByIndexes(uint startRow, string startCol, uint endRow, string endCol) => + RangeByIndexes(startRow, startCol, endRow, endCol).TryMerge(); + + /// + public bool TryMergeByLength(uint startRow, uint startCol, uint rows, uint cols) => + RangeByLength(startRow, startCol, rows, cols).TryMerge(); + + /// + public bool TryMergeByLength(uint startRow, string startCol, uint rows, uint cols) => + RangeByLength(startRow, startCol, rows, cols).TryMerge(); + + #endregion + } \ No newline at end of file diff --git a/QWERTYkez.ExcelProcessor/Editors/Interfaces.cs b/QWERTYkez.ExcelProcessor/Editors/Interfaces.cs index 7d0abd0..4c403cd 100644 --- a/QWERTYkez.ExcelProcessor/Editors/Interfaces.cs +++ b/QWERTYkez.ExcelProcessor/Editors/Interfaces.cs @@ -99,6 +99,18 @@ public interface ISheet /// Редактирует диапазон, заданный начальной ячейкой и размером (буква столбца). ISheet RangeByLength(uint startRow, string startCol, uint rows, uint cols, Action edit); + /// Возвращает диапазон ячеек по начальным и конечным индексам строк и столбцов. + bool TryMergeByIndexes(uint startRow, uint startCol, uint endRow, uint endCol); + + /// Возвращает диапазон ячеек по начальным и конечным координатам с буквенным обозначением столбцов. + bool TryMergeByIndexes(uint startRow, string startCol, uint endRow, string endCol); + + /// Возвращает диапазон, начиная с указанной ячейки, заданной размером (строки x столбцы). + bool TryMergeByLength(uint startRow, uint startCol, uint rows, uint cols); + + /// Возвращает диапазон по начальной ячейке и размеру с буквенным обозначением столбца. + bool TryMergeByLength(uint startRow, string startCol, uint rows, uint cols); + /// Возвращает ячейку по номеру строки и столбца (оба начиная с 1). ICell Cell(uint row, uint col);