2026-06-08 14:31:31 +07:00
|
|
|
|
namespace QWERTYkez.ExcelProcessor;
|
2026-06-05 15:58:03 +07:00
|
|
|
|
|
|
|
|
|
|
/// <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,
|
|
|
|
|
|
}
|