using ClosedXML.Excel; using System; using System.Diagnostics.CodeAnalysis; using System.Text; namespace AsbCloudInfrastructure.Services.DailyReport { #nullable enable internal class CellAddress: IXLAddress { const int excelLettersCount = 'Z' - 'A' + 1; public int RowNumber { get; set; } public int ColumnNumber { get; set; } public string ColumnLetter { get { return CalcColumnLetter(); } } public bool FixedColumn { get; set; } public bool FixedRow { get; set; } public string UniqueId => ToString(XLReferenceStyle.A1, true); public IXLWorksheet? Worksheet { get; set; } public CellAddress(IXLWorksheet? worksheet, int row, int colunm) { Worksheet = worksheet; RowNumber = row; ColumnNumber = colunm; } public static CellAddress operator + (CellAddress a, CellAddress b) => new CellAddress(a.Worksheet, a.RowNumber + b.RowNumber, a.ColumnNumber + b.ColumnNumber); public static CellAddress operator +(CellAddress a, (int row, int column) b) => new CellAddress(a.Worksheet, a.RowNumber + b.row, a.ColumnNumber + b.column); public static CellAddress operator - (CellAddress a, CellAddress b) => new CellAddress(a.Worksheet, a.RowNumber - b.RowNumber, a.ColumnNumber - b.ColumnNumber); public static bool operator == (CellAddress a, CellAddress b) => a.RowNumber == b.RowNumber && a.ColumnNumber == b.ColumnNumber; public static bool operator !=(CellAddress a, CellAddress b) => !(a == b); private string CalcColumnLetter() { string letter = ""; var columnNumber = ColumnNumber; while (columnNumber > 0) { int modulo = (columnNumber - 1) % excelLettersCount; letter = Convert.ToChar('A' + modulo) + letter; columnNumber = (columnNumber - modulo) / excelLettersCount; } return letter; } public CellAddress Copy() => new CellAddress(Worksheet, RowNumber, ColumnNumber) { FixedColumn = this.FixedColumn, FixedRow = this.FixedRow, }; public override string ToString() => ToString(XLReferenceStyle.A1); public string ToString(XLReferenceStyle referenceStyle) => ToString(referenceStyle, false); public string ToString(XLReferenceStyle referenceStyle, bool includeSheet) { if (referenceStyle == XLReferenceStyle.R1C1) throw new NotImplementedException("R1C1 - style doesn't implemented"); var sb = new StringBuilder(); if (includeSheet && Worksheet is not null) sb.Append('$') .Append(Worksheet.Name) .Append('.'); if (FixedColumn) sb.Append('$'); sb.Append(ColumnLetter); if (FixedRow) sb.Append('$'); sb.Append(RowNumber); return sb.ToString(); } public string ToStringFixed() => ToStringFixed(XLReferenceStyle.A1); public string ToStringFixed(XLReferenceStyle referenceStyle) => ToStringFixed(referenceStyle, false); public string ToStringFixed(XLReferenceStyle referenceStyle, bool includeSheet) { if (referenceStyle == XLReferenceStyle.R1C1) throw new NotImplementedException("R1C1 - style doesn't implemented"); var sb = new StringBuilder(); if (includeSheet && Worksheet is not null) sb.Append('$') .Append(Worksheet.Name) .Append('.'); sb.Append('$'); sb.Append(ColumnLetter); sb.Append('$'); sb.Append(RowNumber); return sb.ToString(); } public string ToStringRelative() => ToStringRelative(false); public string ToStringRelative(bool includeSheet) { var sb = new StringBuilder(); if (includeSheet && Worksheet is not null) sb.Append('$') .Append(Worksheet.Name) .Append('.'); sb.Append(ColumnLetter); sb.Append(RowNumber); return sb.ToString(); } public bool Equals(IXLAddress? x, IXLAddress? y) => x?.ColumnNumber == y?.ColumnNumber && x?.RowNumber == y?.RowNumber && x?.FixedColumn == y?.FixedColumn && x?.FixedRow == y?.FixedRow && x?.Worksheet == y?.Worksheet; public override int GetHashCode() => base.GetHashCode(); public int GetHashCode([DisallowNull] IXLAddress obj) => obj.GetHashCode(); public bool Equals(IXLAddress? other) => Equals(this, other); public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } if (obj is null) { return false; } if (obj is CellAddress address) return this == address; return false; } } #nullable disable }