Skip to content

Commit

Permalink
feat: Enhance IDataReader export with DynamicColumnFirst and Custom F…
Browse files Browse the repository at this point in the history
…ormatting Delegate (#700)

* Add DynamicColumnFirst in config;

* Handle DynamicColumnFirst value assign;
Modify DynamicColumns ignore case;

* Handle CustomFormatter logic;
  • Loading branch information
IcedMango authored Nov 29, 2024
1 parent d72312e commit da9b517
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 5 deletions.
2 changes: 2 additions & 0 deletions src/MiniExcel/Attributes/ExcelColumnAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public enum ColumnType { Value, Formula }
public class DynamicExcelColumn : ExcelColumnAttribute
{
public string Key { get; set; }

public Func<object, string> CustomFormatter { get; set; }

public DynamicExcelColumn(string key)
{
Expand Down
5 changes: 5 additions & 0 deletions src/MiniExcel/IConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ public abstract class Configuration : IConfiguration
public DynamicExcelColumn[] DynamicColumns { get; set; }
public int BufferSize { get; set; } = 1024 * 512;
public bool FastMode { get; set; } = false;

/// <summary>
/// When exporting using DataReader, the data not in DynamicColumn will be filtered.
/// </summary>
public bool DynamicColumnFirst { get; set; } = false;
}
}
50 changes: 46 additions & 4 deletions src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,25 @@ private async Task GenerateSheetByIDataReaderAsync(MiniExcelAsyncStreamWriter wr
for (var i = 0; i < reader.FieldCount; i++)
{
var columnName = reader.GetName(i);
var prop = GetColumnInfosFromDynamicConfiguration(columnName);
props.Add(prop);

if (!_configuration.DynamicColumnFirst)
{
var prop = GetColumnInfosFromDynamicConfiguration(columnName);
props.Add(prop);
continue;
}

if (_configuration
.DynamicColumns
.Any(a => string.Equals(
a.Key,
columnName,
StringComparison.OrdinalIgnoreCase)))

{
var prop = GetColumnInfosFromDynamicConfiguration(columnName);
props.Add(prop);
}
}
maxColumnIndex = props.Count;

Expand Down Expand Up @@ -149,7 +166,18 @@ private async Task GenerateSheetByIDataReaderAsync(MiniExcelAsyncStreamWriter wr
var xIndex = 1;
for (int i = 0; i < fieldCount; i++)
{
var cellValue = reader.GetValue(i);
object cellValue;

if (_configuration.DynamicColumnFirst)
{
var columnIndex = reader.GetOrdinal(props[i].Key.ToString());
cellValue = reader.GetValue(columnIndex);
}
else
{
cellValue = reader.GetValue(i);
}

await WriteCellAsync(writer, yIndex, xIndex, cellValue, props[i], widths);
xIndex++;
}
Expand Down Expand Up @@ -534,7 +562,21 @@ private async Task WriteCellAsync(MiniExcelAsyncStreamWriter writer, int rowInde
var columnType = p.ExcelColumnType;

/*Prefix and suffix blank space will lost after SaveAs #294*/
var preserveSpace = cellValue != null && (cellValue.StartsWith(" ", StringComparison.Ordinal) || cellValue.EndsWith(" ", StringComparison.Ordinal));
var preserveSpace = cellValue != null && (cellValue.StartsWith(" ", StringComparison.Ordinal) ||
cellValue.EndsWith(" ", StringComparison.Ordinal));

if (p.CustomFormatter != null)
{
try
{
cellValue = p.CustomFormatter(cellValue);
}
catch (Exception e)

Check warning on line 574 in src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs

View workflow job for this annotation

GitHub Actions / build

The variable 'e' is declared but never used

Check warning on line 574 in src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs

View workflow job for this annotation

GitHub Actions / build

The variable 'e' is declared but never used

Check warning on line 574 in src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs

View workflow job for this annotation

GitHub Actions / build

The variable 'e' is declared but never used
{
//ignored
}
}

await writer.WriteAsync(WorksheetXml.Cell(columnReference, dataType, styleIndex, cellValue, preserveSpace: preserveSpace, columnType: columnType));
widthCollection?.AdjustWidth(cellIndex, cellValue);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ private ExcelColumnInfo GetColumnInfosFromDynamicConfiguration(string columnName
if (_configuration.DynamicColumns == null || _configuration.DynamicColumns.Length <= 0)
return prop;

var dynamicColumn = _configuration.DynamicColumns.SingleOrDefault(_ => _.Key == columnName);
var dynamicColumn = _configuration.DynamicColumns.SingleOrDefault(_ => string.Equals(_.Key , columnName,StringComparison.OrdinalIgnoreCase));
if (dynamicColumn == null || dynamicColumn.Ignore)
{
return prop;
Expand All @@ -203,6 +203,7 @@ private ExcelColumnInfo GetColumnInfosFromDynamicConfiguration(string columnName
prop.ExcelColumnType = dynamicColumn.Type;
prop.ExcelColumnIndex = dynamicColumn.Index;
prop.ExcelColumnWidth = dynamicColumn.Width;
prop.CustomFormatter = dynamicColumn.CustomFormatter;
//prop.ExcludeNullableType = item2[key]?.GetType();

if (dynamicColumn.Format != null)
Expand Down
13 changes: 13 additions & 0 deletions src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,19 @@ private void WriteCell(MiniExcelStreamWriter writer, int rowIndex, int cellIndex
var styleIndex = tuple.Item1; // https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.cell?view=openxml-3.0.1
var dataType = tuple.Item2; // https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.cellvalues?view=openxml-3.0.1
var cellValue = tuple.Item3;

if (columnInfo?.CustomFormatter != null)
{
try
{
cellValue = columnInfo.CustomFormatter(cellValue);
}
catch (Exception e)

Check warning on line 580 in src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs

View workflow job for this annotation

GitHub Actions / build

The variable 'e' is declared but never used

Check warning on line 580 in src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs

View workflow job for this annotation

GitHub Actions / build

The variable 'e' is declared but never used

Check warning on line 580 in src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs

View workflow job for this annotation

GitHub Actions / build

The variable 'e' is declared but never used
{
//ignored
}
}

var columnType = columnInfo?.ExcelColumnType ?? ColumnType.Value;

/*Prefix and suffix blank space will lost after SaveAs #294*/
Expand Down
2 changes: 2 additions & 0 deletions src/MiniExcel/Utils/CustomPropertyHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ internal class ExcelColumnInfo
public bool ExcelIgnore { get; internal set; }
public int ExcelFormatId { get; internal set; }
public ColumnType ExcelColumnType { get; internal set; }
public Func<object, string> CustomFormatter { get; set; }
}

internal class ExcellSheetInfo
Expand Down Expand Up @@ -310,6 +311,7 @@ internal static void SetDictionaryColumnInfo(List<ExcelColumnInfo> _props, objec
isIgnore = dynamicColumn.Ignore;
p.ExcelColumnWidth = dynamicColumn.Width;
p.ExcelColumnType = dynamicColumn.Type;
p.CustomFormatter = dynamicColumn.CustomFormatter;
}
}
if (!isIgnore)
Expand Down

0 comments on commit da9b517

Please sign in to comment.