namespace QWERTYkez.ExcelProcessor.Editors; /// /// Определяет выравнивание содержимого ячейки: горизонтальное, вертикальное, перенос текста и уменьшение по размеру. /// Все свойства опциональны. Если свойство не задано, соответствующий аспект не изменяется. /// public readonly struct CellAlign : IEquatable { /// Горизонтальное выравнивание. public CellAlignHorizontal? Horizontal { get; init; } /// Вертикальное выравнивание. public CellAlignVertical? Vertical { get; init; } /// Переносить ли текст по словам (многострочный режим). public bool? WrapText { get; init; } /// Уменьшать размер шрифта, чтобы текст поместился в ячейку. public bool? ShrinkToFit { get; init; } /// Преобразует горизонтальное выравнивание в тип Open XML. public bool TryGetExcelHorizontalAlignment(out HorizontalAlignmentValues value) { if (Horizontal.HasValue) { value = Horizontal.Value switch { CellAlignHorizontal.Left => HorizontalAlignmentValues.Left, CellAlignHorizontal.Center => HorizontalAlignmentValues.Center, CellAlignHorizontal.Right => HorizontalAlignmentValues.Right, CellAlignHorizontal.Fill => HorizontalAlignmentValues.Fill, CellAlignHorizontal.Justify => HorizontalAlignmentValues.Justify, CellAlignHorizontal.CenterContinuous => HorizontalAlignmentValues.CenterContinuous, CellAlignHorizontal.Distributed => HorizontalAlignmentValues.Distributed, _ => throw new NotSupportedException($"Unsupported horizontal alignment: {Horizontal.Value}") }; return true; } value = default; return false; } /// Преобразует вертикальное выравнивание в тип Open XML. public bool TryGetExcelVerticalAlignment(out VerticalAlignmentValues value) { if (Vertical.HasValue) { value = Vertical.Value switch { CellAlignVertical.Top => VerticalAlignmentValues.Top, CellAlignVertical.Center => VerticalAlignmentValues.Center, CellAlignVertical.Bottom => VerticalAlignmentValues.Bottom, CellAlignVertical.Justify => VerticalAlignmentValues.Justify, CellAlignVertical.Distributed => VerticalAlignmentValues.Distributed, _ => throw new NotSupportedException($"Unsupported vertical alignment: {Vertical.Value}") }; return true; } value = default; return false; } /// Создаёт элемент Alignment для Open XML. public Alignment? ToAlignment() { if (!Horizontal.HasValue && !Vertical.HasValue && !WrapText.HasValue && !ShrinkToFit.HasValue) return null; var align = new Alignment(); if (TryGetExcelHorizontalAlignment(out var hAlign)) align.Horizontal = hAlign; if (TryGetExcelVerticalAlignment(out var vAlign)) align.Vertical = vAlign; if (WrapText.HasValue) align.WrapText = WrapText.Value; if (ShrinkToFit.HasValue) align.ShrinkToFit = ShrinkToFit.Value; return align; } /// Создаёт CellAlign из элемента Alignment Open XML. public static CellAlign FromAlignment(Alignment? alignment) { if (alignment == null) return default; var result = new CellAlign(); if (alignment.Horizontal?.Value is { } horizontal) { result = result with { Horizontal = MapHorizontalFromExcel(horizontal) }; } if (alignment.Vertical?.Value is { } vertical) { result = result with { Vertical = MapVerticalFromExcel(vertical) }; } if (alignment.WrapText?.Value is { } wrapText) { result = result with { WrapText = wrapText }; } if (alignment.ShrinkToFit?.Value is { } shrinkToFit) { result = result with { ShrinkToFit = shrinkToFit }; } return result; } private static CellAlignHorizontal MapHorizontalFromExcel(HorizontalAlignmentValues value) { if (value == HorizontalAlignmentValues.Left) { return CellAlignHorizontal.Left; } else if (value == HorizontalAlignmentValues.Center) { return CellAlignHorizontal.Center; } else if (value == HorizontalAlignmentValues.Right) { return CellAlignHorizontal.Right; } else if (value == HorizontalAlignmentValues.Fill) { return CellAlignHorizontal.Fill; } else if (value == HorizontalAlignmentValues.Justify) { return CellAlignHorizontal.Justify; } else if (value == HorizontalAlignmentValues.CenterContinuous) { return CellAlignHorizontal.CenterContinuous; } else if (value == HorizontalAlignmentValues.Distributed) { return CellAlignHorizontal.Distributed; } else throw new NotSupportedException($"Unsupported horizontal alignment: {value}"); } private static CellAlignVertical MapVerticalFromExcel(VerticalAlignmentValues value) { if (value == VerticalAlignmentValues.Top) { return CellAlignVertical.Top; } else if (value == VerticalAlignmentValues.Center) { return CellAlignVertical.Center; } else if (value == VerticalAlignmentValues.Bottom) { return CellAlignVertical.Bottom; } else if (value == VerticalAlignmentValues.Justify) { return CellAlignVertical.Justify; } else if (value == VerticalAlignmentValues.Distributed) { return CellAlignVertical.Distributed; } else throw new NotSupportedException($"Unsupported vertical alignment: {value}"); } public override bool Equals(object? obj) => obj is CellAlign other && Equals(other); public bool Equals(CellAlign other) => this == other; public static bool operator ==(CellAlign left, CellAlign right) => left.Horizontal == right.Horizontal && left.Vertical == right.Vertical && left.WrapText == right.WrapText && left.ShrinkToFit == right.ShrinkToFit; public static bool operator !=(CellAlign left, CellAlign right) => !(left == right); public override int GetHashCode() { unchecked { int hash = 17; hash = hash * 31 + (Horizontal?.GetHashCode() ?? 0); hash = hash * 31 + (Vertical?.GetHashCode() ?? 0); hash = hash * 31 + (WrapText?.GetHashCode() ?? 0); hash = hash * 31 + (ShrinkToFit?.GetHashCode() ?? 0); return hash; } } } /// Горизонтальное выравнивание содержимого ячейки. public enum CellAlignHorizontal { /// По левому краю. Left, /// По центру. Center, /// По правому краю. Right, /// Заполнение (повтор содержимого для заполнения ширины). Fill, /// По ширине (для многострочного текста). Justify, /// Центрирование по выделенным ячейкам (визуально, без объединения). CenterContinuous, /// Распределённый (выравнивание по ширине с пробелами). Distributed, } /// Вертикальное выравнивание содержимого ячейки. public enum CellAlignVertical { /// По верхнему краю. Top, /// По центру. Center, /// По нижнему краю (значение по умолчанию). Bottom, /// По высоте (для многострочного текста). Justify, /// Распределённый по вертикали. Distributed, }