Files
QWERTYkez.OpenXmlProcessors/QWERTYkez.ExcelProcessor/Editors/CellAlign.cs

223 lines
8.8 KiB
C#
Raw Normal View History

namespace QWERTYkez.ExcelProcessor.Editors;
/// <summary>
/// Определяет выравнивание содержимого ячейки: горизонтальное, вертикальное, перенос текста и уменьшение по размеру.
/// Все свойства опциональны. Если свойство не задано, соответствующий аспект не изменяется.
/// </summary>
public readonly struct CellAlign : IEquatable<CellAlign>
{
/// <summary>Горизонтальное выравнивание.</summary>
public CellAlignHorizontal? Horizontal { get; init; }
/// <summary>Вертикальное выравнивание.</summary>
public CellAlignVertical? Vertical { get; init; }
/// <summary>Переносить ли текст по словам (многострочный режим).</summary>
public bool? WrapText { get; init; }
/// <summary>Уменьшать размер шрифта, чтобы текст поместился в ячейку.</summary>
public bool? ShrinkToFit { get; init; }
/// <summary>Преобразует горизонтальное выравнивание в тип Open XML.</summary>
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;
}
/// <summary>Преобразует вертикальное выравнивание в тип Open XML.</summary>
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;
}
/// <summary>Создаёт элемент Alignment для Open XML.</summary>
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;
}
/// <summary>Создаёт CellAlign из элемента Alignment Open XML.</summary>
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;
}
}
}
/// <summary>Горизонтальное выравнивание содержимого ячейки.</summary>
public enum CellAlignHorizontal
{
/// <summary>По левому краю.</summary>
Left,
/// <summary>По центру.</summary>
Center,
/// <summary>По правому краю.</summary>
Right,
/// <summary>Заполнение (повтор содержимого для заполнения ширины).</summary>
Fill,
/// <summary>По ширине (для многострочного текста).</summary>
Justify,
/// <summary>Центрирование по выделенным ячейкам (визуально, без объединения).</summary>
CenterContinuous,
/// <summary>Распределённый (выравнивание по ширине с пробелами).</summary>
Distributed,
}
/// <summary>Вертикальное выравнивание содержимого ячейки.</summary>
public enum CellAlignVertical
{
/// <summary>По верхнему краю.</summary>
Top,
/// <summary>По центру.</summary>
Center,
/// <summary>По нижнему краю (значение по умолчанию).</summary>
Bottom,
/// <summary>По высоте (для многострочного текста).</summary>
Justify,
/// <summary>Распределённый по вертикали.</summary>
Distributed,
}