This commit is contained in:
@@ -16,7 +16,161 @@ internal sealed class ExcelColumn : IColumn
|
||||
_colIndex = colIndex;
|
||||
}
|
||||
|
||||
public uint Index => _colIndex;
|
||||
|
||||
private CellStyle? GetColumnStyle(Column columnElement)
|
||||
{
|
||||
if (columnElement.Style?.Value is not uint styleIndex)
|
||||
return null;
|
||||
return _writer.GetCellStyle(styleIndex);
|
||||
}
|
||||
|
||||
private void ApplyStyleToColumn(CellStyle style)
|
||||
{
|
||||
var columnElement = GetOrCreateColumnElement();
|
||||
int styleIndex = _writer.GetOrCreateStyleId(style);
|
||||
columnElement.Style = (uint)styleIndex;
|
||||
// Принудительно устанавливаем customStyle через атрибут
|
||||
if (!columnElement.ExtendedAttributes.Any(attr => attr.LocalName == "customStyle" && attr.Value == "1"))
|
||||
columnElement.SetAttribute(new OpenXmlAttribute("customStyle", "", "1"));
|
||||
}
|
||||
|
||||
internal static Column? GetColumnElementInternal(ExcelSheet sheet, uint colIndex)
|
||||
{
|
||||
var cols = sheet.Worksheet.GetFirstChild<Columns>();
|
||||
if (cols == null) return null;
|
||||
foreach (Column col in cols.Elements<Column>())
|
||||
{
|
||||
if (col.Min?.Value is { } min && col.Max?.Value is { } max && min <= colIndex && max >= colIndex)
|
||||
return col;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public IColumn Set(NumberFormatPattern format)
|
||||
{
|
||||
if (format == null) return this;
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
{
|
||||
var columnElement = GetOrCreateColumnElement();
|
||||
var currentStyle = GetColumnStyle(columnElement) ?? new CellStyle();
|
||||
if (currentStyle.TryMerge(format, out var newStyle))
|
||||
{
|
||||
ApplyStyleToColumn(newStyle);
|
||||
ApplyStyleToColumnCells(newStyle);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IColumn Set(CellAlign align)
|
||||
{
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
{
|
||||
var columnElement = GetOrCreateColumnElement();
|
||||
var currentStyle = GetColumnStyle(columnElement) ?? new CellStyle();
|
||||
if (currentStyle.TryMerge(align, out var newStyle))
|
||||
{
|
||||
ApplyStyleToColumn(newStyle);
|
||||
ApplyStyleToColumnCells(newStyle);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IColumn Set(CellBorder border)
|
||||
{
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
{
|
||||
var columnElement = GetOrCreateColumnElement();
|
||||
var currentStyle = GetColumnStyle(columnElement) ?? new CellStyle();
|
||||
if (currentStyle.TryMerge(border, out var newStyle))
|
||||
{
|
||||
ApplyStyleToColumn(newStyle);
|
||||
ApplyStyleToColumnCells(newStyle);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IColumn Set(CellFill fill)
|
||||
{
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
{
|
||||
var columnElement = GetOrCreateColumnElement();
|
||||
var currentStyle = GetColumnStyle(columnElement) ?? new CellStyle();
|
||||
if (currentStyle.TryMerge(fill, out var newStyle))
|
||||
{
|
||||
ApplyStyleToColumn(newStyle);
|
||||
ApplyStyleToColumnCells(newStyle);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IColumn Set(CellFont font)
|
||||
{
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
{
|
||||
var columnElement = GetOrCreateColumnElement();
|
||||
var currentStyle = GetColumnStyle(columnElement) ?? new CellStyle();
|
||||
if (currentStyle.TryMerge(font, out var newStyle))
|
||||
{
|
||||
ApplyStyleToColumn(newStyle);
|
||||
ApplyStyleToColumnCells(newStyle);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IColumn Set(CellStyle style)
|
||||
{
|
||||
if (style == null) return this;
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
{
|
||||
var columnElement = GetOrCreateColumnElement();
|
||||
var currentStyle = GetColumnStyle(columnElement) ?? new CellStyle();
|
||||
if (currentStyle.TryMerge(style, out var newStyle))
|
||||
{
|
||||
ApplyStyleToColumn(newStyle);
|
||||
ApplyStyleToColumnCells(newStyle);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void ApplyStyleToColumnCells(CellStyle style)
|
||||
{
|
||||
var sheetData = _sheet.GetSheetData();
|
||||
foreach (var rowElement in sheetData.Elements<Row>())
|
||||
{
|
||||
var cellElement = FindCellInRow(rowElement, _colIndex);
|
||||
if (cellElement != null)
|
||||
{
|
||||
var cell = new ExcelCell(_writer, _sheet, rowElement.RowIndex!.Value, _colIndex);
|
||||
cell.Set(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public uint Index => _colIndex;
|
||||
public string IndexLetter => NumberToColumnLetter(_colIndex);
|
||||
|
||||
|
||||
@@ -64,23 +218,7 @@ internal sealed class ExcelColumn : IColumn
|
||||
}
|
||||
}
|
||||
|
||||
// Вспомогательные внутренние методы (перенести существующую логику)
|
||||
private static Column? GetColumnElementInternal(ExcelSheet sheet, uint colIndex)
|
||||
{
|
||||
var cols = sheet.Worksheet.GetFirstChild<Columns>();
|
||||
if (cols == null) return null;
|
||||
foreach (Column col in cols.Elements<Column>())
|
||||
{
|
||||
if (col?.Min?.Value is { } min
|
||||
&& col?.Max?.Value is { } max
|
||||
&& min <= colIndex
|
||||
&& max >= colIndex)
|
||||
return col;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Column GetOrCreateColumnElementInternal(ExcelSheet sheet, uint colIndex)
|
||||
static Column GetOrCreateColumnElementInternal(ExcelSheet sheet, uint colIndex)
|
||||
{
|
||||
var existing = GetColumnElementInternal(sheet, colIndex);
|
||||
if (existing != null) return existing;
|
||||
@@ -127,62 +265,46 @@ internal sealed class ExcelColumn : IColumn
|
||||
}
|
||||
|
||||
public ColumnWidth Width
|
||||
{
|
||||
get
|
||||
{
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
get
|
||||
{
|
||||
var column = GetColumnElement();
|
||||
if (column is Column col && col.Width?.Value is { } val && col.CustomWidth?.Value == true)
|
||||
return ColumnWidth.FromCharacters(val);
|
||||
return ColumnWidth.FromCharacters(8.43); // стандартная ширина
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
{
|
||||
var col = GetOrCreateColumnElement();
|
||||
double widthInChars;
|
||||
|
||||
if (value.IsCharacterUnit)
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
{
|
||||
// Если ширина задана в символах, используем напрямую
|
||||
widthInChars = value.CharacterValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
double targetCm = value.GetTargetCentimeters();
|
||||
widthInChars = _writer.TryGetCalibrateCoeff(targetCm, out var closestCw)
|
||||
? closestCw : targetCm * (ColumnWidth.DefaultPointsPerChar / 28.3464566929);
|
||||
}
|
||||
|
||||
col.Width = widthInChars;
|
||||
col.CustomWidth = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IColumn SetNumberFormat(NumberFormatPattern format)
|
||||
{
|
||||
if (format == null) return this;
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
{
|
||||
int fmtId = GetOrCreateNumberFormatId(format);
|
||||
// Применяем ко всем ячейкам столбца
|
||||
var sheetData = _sheet.GetSheetData();
|
||||
foreach (var row in sheetData.Elements<Row>())
|
||||
{
|
||||
var cell = FindCellInRow(row, _colIndex);
|
||||
cell?.StyleIndex = (uint)fmtId;
|
||||
var column = GetColumnElement();
|
||||
if (column is Column col && col.Width?.Value is { } val && col.CustomWidth?.Value == true)
|
||||
return ColumnWidth.FromCharacters(val);
|
||||
return ColumnWidth.FromCharacters(8.43); // стандартная ширина
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
_writer.ThrowIfDisposed();
|
||||
lock (_writer._syncLock)
|
||||
{
|
||||
var col = GetOrCreateColumnElement();
|
||||
double widthInChars;
|
||||
|
||||
if (value.IsCharacterUnit)
|
||||
{
|
||||
// Если ширина задана в символах, используем напрямую
|
||||
widthInChars = value.CharacterValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
double targetCm = value.GetTargetCentimeters();
|
||||
widthInChars = _writer.TryGetCalibrateCoeff(targetCm, out var closestCw)
|
||||
? closestCw : targetCm * (ColumnWidth.DefaultPointsPerChar / 28.3464566929);
|
||||
}
|
||||
|
||||
col.Width = widthInChars;
|
||||
col.CustomWidth = true;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ICell Cell(uint row)
|
||||
{
|
||||
return new ExcelCell(_writer, _sheet, row, _colIndex);
|
||||
@@ -207,7 +329,7 @@ internal sealed class ExcelColumn : IColumn
|
||||
|
||||
public IColumn Cell(uint row, string value, NumberFormatPattern? format = null)
|
||||
{
|
||||
Cell(row).Set(value, format); return this;
|
||||
Cell(row).SetFormula(value, format); return this;
|
||||
}
|
||||
|
||||
public IColumn Cell(uint row, DateTime value, NumberFormatPattern? format = null)
|
||||
@@ -305,7 +427,7 @@ internal sealed class ExcelColumn : IColumn
|
||||
|
||||
// Вспомогательные методы
|
||||
|
||||
private Column? GetColumnElement()
|
||||
Column? GetColumnElement()
|
||||
{
|
||||
var cols = _sheet.Worksheet.GetFirstChild<Columns>();
|
||||
if (cols == null) return null;
|
||||
@@ -320,7 +442,7 @@ internal sealed class ExcelColumn : IColumn
|
||||
return null;
|
||||
}
|
||||
|
||||
private Column GetOrCreateColumnElement()
|
||||
Column GetOrCreateColumnElement()
|
||||
{
|
||||
var existing = GetColumnElement();
|
||||
if (existing != null) return existing;
|
||||
@@ -344,13 +466,13 @@ internal sealed class ExcelColumn : IColumn
|
||||
return newCol;
|
||||
}
|
||||
|
||||
private void DeleteColumnElement()
|
||||
void DeleteColumnElement()
|
||||
{
|
||||
var col = GetColumnElement();
|
||||
col?.Remove();
|
||||
}
|
||||
|
||||
private void CopyColumnData(uint sourceCol, uint targetCol)
|
||||
void CopyColumnData(uint sourceCol, uint targetCol)
|
||||
{
|
||||
if (sourceCol == targetCol) return;
|
||||
var sheetData = _sheet.GetSheetData();
|
||||
@@ -389,7 +511,7 @@ internal sealed class ExcelColumn : IColumn
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearColumnData(uint col)
|
||||
void ClearColumnData(uint col)
|
||||
{
|
||||
var sheetData = _sheet.GetSheetData();
|
||||
foreach (var row in sheetData.Elements<Row>().ToList())
|
||||
@@ -399,7 +521,7 @@ internal sealed class ExcelColumn : IColumn
|
||||
}
|
||||
}
|
||||
|
||||
private Cell? FindCellInRow(Row row, uint colIndex)
|
||||
Cell? FindCellInRow(Row row, uint colIndex)
|
||||
{
|
||||
foreach (var cell in row.Elements<Cell>())
|
||||
{
|
||||
@@ -410,7 +532,7 @@ internal sealed class ExcelColumn : IColumn
|
||||
return null;
|
||||
}
|
||||
|
||||
private void InsertCellInRow(Row row, Cell cell, uint colIndex)
|
||||
void InsertCellInRow(Row row, Cell cell, uint colIndex)
|
||||
{
|
||||
string newRef = NumberToColumnLetter(colIndex) + (row.RowIndex?.Value ?? 1).ToString();
|
||||
cell.CellReference = newRef;
|
||||
@@ -430,7 +552,7 @@ internal sealed class ExcelColumn : IColumn
|
||||
row.Append(cell);
|
||||
}
|
||||
|
||||
private Column? GetColumnElementForIndex(uint col)
|
||||
Column? GetColumnElementForIndex(uint col)
|
||||
{
|
||||
var cols = _sheet.Worksheet.GetFirstChild<Columns>();
|
||||
if (cols == null) return null;
|
||||
@@ -445,7 +567,7 @@ internal sealed class ExcelColumn : IColumn
|
||||
return null;
|
||||
}
|
||||
|
||||
private Column GetOrCreateColumnElementForIndex(uint col)
|
||||
Column GetOrCreateColumnElementForIndex(uint col)
|
||||
{
|
||||
var existing = GetColumnElementForIndex(col);
|
||||
if (existing != null) return existing;
|
||||
@@ -468,12 +590,12 @@ internal sealed class ExcelColumn : IColumn
|
||||
return newCol;
|
||||
}
|
||||
|
||||
private int GetOrCreateNumberFormatId(NumberFormatPattern format)
|
||||
int GetOrCreateNumberFormatId(NumberFormatPattern format)
|
||||
{
|
||||
return _writer.GetOrCreateCellFormatId(numberFormat: format);
|
||||
}
|
||||
|
||||
private static bool TryParseCellReference(string reference, out uint row, out uint col)
|
||||
static bool TryParseCellReference(string reference, out uint row, out uint col)
|
||||
{
|
||||
row = 0; col = 0;
|
||||
if (string.IsNullOrEmpty(reference)) return false;
|
||||
@@ -487,7 +609,7 @@ internal sealed class ExcelColumn : IColumn
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string NumberToColumnLetter(uint col)
|
||||
static string NumberToColumnLetter(uint col)
|
||||
{
|
||||
if (col == 0) throw new ArgumentException("Column number must be > 0");
|
||||
string result = "";
|
||||
|
||||
Reference in New Issue
Block a user