diff --git a/src/MiniExcel/Attributes/ExcelColumnAttribute.cs b/src/MiniExcel/Attributes/ExcelColumnAttribute.cs
index d7337418..965f0579 100644
--- a/src/MiniExcel/Attributes/ExcelColumnAttribute.cs
+++ b/src/MiniExcel/Attributes/ExcelColumnAttribute.cs
@@ -9,6 +9,8 @@ public class ExcelColumnAttribute : Attribute
private int _index = -1;
private string _xName;
+ internal int FormatId { get; set; } = -1;
+
public string Name { get; set; }
public string[] Aliases { get; set; }
@@ -52,6 +54,7 @@ private void Init(int index, string columnName = null)
public class DynamicExcelColumn : ExcelColumnAttribute
{
public string Key { get; set; }
+
public DynamicExcelColumn(string key)
{
Key = key;
diff --git a/src/MiniExcel/OpenXml/Constants/ExcelXml.cs b/src/MiniExcel/OpenXml/Constants/ExcelXml.cs
index a4efba29..b1a0d7a5 100644
--- a/src/MiniExcel/OpenXml/Constants/ExcelXml.cs
+++ b/src/MiniExcel/OpenXml/Constants/ExcelXml.cs
@@ -1,4 +1,9 @@
-using MiniExcelLibs.OpenXml.Models;
+using MiniExcelLibs.Attributes;
+using MiniExcelLibs.OpenXml.Models;
+using MiniExcelLibs.Utils;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
namespace MiniExcelLibs.OpenXml.Constants
{
@@ -52,10 +57,21 @@ static ExcelXml()
";
- internal static readonly string DefaultStylesXml = @"
+ #region StyleSheet
+
+ private const int startUpNumFmts = 1;
+ private const string NumFmtsToken = "{{numFmts}}";
+ private const string NumFmtsCountToken = "{{numFmtCount}}";
+
+ private const int startUpCellXfs = 5;
+ private const string cellXfsToken = "{{cellXfs}}";
+ private const string cellXfsCountToken = "{{cellXfsCount}}";
+
+ internal static readonly string DefaultStylesXml = $@"
-
+
+ {NumFmtsToken}
@@ -133,7 +149,7 @@ static ExcelXml()
-
+
@@ -150,12 +166,15 @@ static ExcelXml()
+ {cellXfsToken}
";
+ #endregion
+
internal static readonly string DefaultWorkbookXml = @"
@@ -231,5 +250,52 @@ internal static string DrawingXml(FileDto file, int fileIndex)
internal static string Sheet(SheetDto sheetDto, int sheetId)
=> $@"";
+
+ internal static string SetupStyleXml(string styleXml, ICollection columns)
+ {
+ const int numFmtIndex = 166;
+
+ var sb = new StringBuilder(styleXml);
+ var columnsToApply = GenerateStyleIds(columns);
+
+ var numFmts = columnsToApply.Select((x, i) =>
+ {
+ return new
+ {
+ numFmt =
+$@"",
+
+ cellXfs =
+$@"
+
+
+"
+ };
+ }).ToArray();
+
+ sb.Replace(NumFmtsToken, string.Join(string.Empty, numFmts.Select(x => x.numFmt)));
+ sb.Replace(NumFmtsCountToken, (startUpNumFmts + numFmts.Length).ToString());
+
+ sb.Replace(cellXfsToken, string.Join(string.Empty, numFmts.Select(x => x.cellXfs)));
+ sb.Replace(cellXfsCountToken, (5 + numFmts.Length).ToString());
+ return sb.ToString();
+ }
+
+ private static IEnumerable GenerateStyleIds(ICollection dynamicColumns)
+ {
+ if (dynamicColumns == null)
+ yield break;
+
+ int index = 0;
+ foreach (var g in dynamicColumns?.Where(x => !string.IsNullOrWhiteSpace(x.Format) && new ExcelNumberFormat(x.Format).IsValid).GroupBy(x => x.Format))
+ {
+ foreach (var col in g)
+ col.FormatId = startUpCellXfs + index;
+
+ yield return g.First();
+ index++;
+ }
+ }
+
}
}
diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs
index edd0117e..80e85e38 100644
--- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs
+++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs
@@ -36,6 +36,7 @@ internal async Task GenerateDefaultOpenXmlAsync(CancellationToken cancellationTo
{
await CreateZipEntryAsync(ExcelFileNames.Rels, ExcelContentTypes.Relationships, ExcelXml.DefaultRels, cancellationToken);
await CreateZipEntryAsync(ExcelFileNames.SharedStrings, ExcelContentTypes.SharedStrings, ExcelXml.DefaultSharedString, cancellationToken);
+ await GenerateStylesXmlAsync(cancellationToken);
}
private async Task CreateSheetXmlAsync(object value, string sheetPath, CancellationToken cancellationToken)
@@ -47,27 +48,27 @@ private async Task CreateSheetXmlAsync(object value, string sheetPath, Cancellat
if (value == null)
{
await WriteEmptySheetAsync(writer);
- goto End; //for re-using code
}
-
- //DapperRow
-
- switch (value)
+ else
{
- case IDataReader dataReader:
- await GenerateSheetByIDataReaderAsync(writer, dataReader);
- break;
- case IEnumerable enumerable:
- await GenerateSheetByEnumerableAsync(writer, enumerable);
- break;
- case DataTable dataTable:
- await GenerateSheetByDataTableAsync(writer, dataTable);
- break;
- default:
- throw new NotImplementedException($"Type {value.GetType().FullName} is not implemented. Please open an issue.");
+ //DapperRow
+
+ switch (value)
+ {
+ case IDataReader dataReader:
+ await GenerateSheetByIDataReaderAsync(writer, dataReader);
+ break;
+ case IEnumerable enumerable:
+ await GenerateSheetByEnumerableAsync(writer, enumerable);
+ break;
+ case DataTable dataTable:
+ await GenerateSheetByDataTableAsync(writer, dataTable);
+ break;
+ default:
+ throw new NotImplementedException($"Type {value.GetType().FullName} is not implemented. Please open an issue.");
+ }
}
}
- End: //for re-using code
_zipDictionary.Add(sheetPath, new ZipPackageInfo(entry, ExcelContentTypes.Worksheet));
}
@@ -455,8 +456,6 @@ private async Task GenerateEndXmlAsync(CancellationToken cancellationToken)
{
await AddFilesToZipAsync(cancellationToken);
- await GenerateStylesXmlAsync(cancellationToken);
-
await GenerateDrawinRelXmlAsync(cancellationToken);
await GenerateDrawingXmlAsync(cancellationToken);
@@ -479,7 +478,7 @@ private async Task AddFilesToZipAsync(CancellationToken cancellationToken)
///
private async Task GenerateStylesXmlAsync(CancellationToken cancellationToken)
{
- var styleXml = GetStylesXml();
+ var styleXml = GetStylesXml(_configuration.DynamicColumns);
await CreateZipEntryAsync(
ExcelFileNames.Styles,
diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.DefaultOpenXml.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.DefaultOpenXml.cs
index 16ead3ae..3ec3283f 100644
--- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.DefaultOpenXml.cs
+++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.DefaultOpenXml.cs
@@ -1,4 +1,5 @@
-using MiniExcelLibs.OpenXml.Constants;
+using MiniExcelLibs.Attributes;
+using MiniExcelLibs.OpenXml.Constants;
using MiniExcelLibs.OpenXml.Models;
using MiniExcelLibs.Utils;
using MiniExcelLibs.Zip;
@@ -108,6 +109,7 @@ private ExcelColumnInfo GetColumnInfosFromDynamicConfiguration(string columnName
if (dynamicColumn.Format != null)
{
prop.ExcelFormat = dynamicColumn.Format;
+ prop.ExcelFormatId = dynamicColumn.FormatId;
}
if (dynamicColumn.Aliases != null)
@@ -158,14 +160,26 @@ private Tuple GetCellValue(int rowIndex, int cellIndex,
return Tuple.Create("2", "str", ExcelOpenXmlUtils.EncodeXML(str));
}
- if (columnInfo?.ExcelFormat != null && value is IFormattable formattableValue)
+ var type = GetValueType(value, columnInfo);
+
+
+ if (columnInfo?.ExcelFormat != null && columnInfo?.ExcelFormatId == -1 && value is IFormattable formattableValue)
{
var formattedStr = formattableValue.ToString(columnInfo.ExcelFormat, _configuration.Culture);
return Tuple.Create("2", "str", ExcelOpenXmlUtils.EncodeXML(formattedStr));
}
- var type = GetValueType(value, columnInfo);
+ if (type == typeof(DateTime))
+ {
+ return GetDateTimeValue((DateTime)value, columnInfo);
+ }
+#if NET6_0_OR_GREATER
+ if (type == typeof(DateOnly))
+ {
+ return GetDateTimeValue(((DateOnly)value).ToDateTime(new TimeOnly()), columnInfo);
+ }
+#endif
if (type.IsEnum)
{
var description = CustomPropertyHelper.DescriptionAttr(type, value);
@@ -193,33 +207,6 @@ private Tuple GetCellValue(int rowIndex, int cellIndex,
return Tuple.Create("4", "str", ExcelOpenXmlUtils.EncodeXML(base64));
}
- if (type == typeof(DateTime))
- {
- return GetDateTimeValue(value, columnInfo);
- }
-
-#if NET6_0_OR_GREATER
- if (type == typeof(DateOnly))
- {
- if (_configuration.Culture != CultureInfo.InvariantCulture)
- {
- var cellValue = ((DateOnly)value).ToString(_configuration.Culture);
- return Tuple.Create("2", "str", cellValue);
- }
-
- if (columnInfo == null || columnInfo.ExcelFormat == null)
- {
- var oaDate = CorrectDateTimeValue((DateTime)value);
- var cellValue = oaDate.ToString(CultureInfo.InvariantCulture);
- return Tuple.Create("3", null, cellValue);
- }
-
- // TODO: now it'll lose date type information
- var formattedCellValue = ((DateOnly)value).ToString(columnInfo.ExcelFormat, _configuration.Culture);
- return Tuple.Create("2", "str", formattedCellValue);
- }
-#endif
-
return Tuple.Create("2", "str", ExcelOpenXmlUtils.EncodeXML(value.ToString()));
}
@@ -325,24 +312,21 @@ private string GetFileValue(int rowIndex, int cellIndex, object value)
return base64;
}
- private Tuple GetDateTimeValue(object value, ExcelColumnInfo columnInfo)
+ private Tuple GetDateTimeValue(DateTime value, ExcelColumnInfo columnInfo)
{
+ string cellValue = null;
if (_configuration.Culture != CultureInfo.InvariantCulture)
{
- var cellValue = ((DateTime)value).ToString(_configuration.Culture);
+ cellValue = (value).ToString(_configuration.Culture);
return Tuple.Create("2", "str", cellValue);
}
+ var oaDate = CorrectDateTimeValue(value);
+ cellValue = oaDate.ToString(CultureInfo.InvariantCulture);
if (columnInfo == null || columnInfo.ExcelFormat == null)
- {
- var oaDate = CorrectDateTimeValue((DateTime)value);
- var cellValue = oaDate.ToString(CultureInfo.InvariantCulture);
return Tuple.Create("3", null, cellValue);
- }
-
- // TODO: now it'll lose date type information
- var formattedCellValue = ((DateTime)value).ToString(columnInfo.ExcelFormat, _configuration.Culture);
- return Tuple.Create("2", "str", formattedCellValue);
+ else
+ return Tuple.Create(columnInfo.ExcelFormatId.ToString(), (string)null, cellValue);
}
private static double CorrectDateTimeValue(DateTime value)
@@ -375,14 +359,14 @@ private string GetDimensionRef(int maxRowIndex, int maxColumnIndex)
return dimensionRef;
}
- private string GetStylesXml()
+ private string GetStylesXml(ICollection columns)
{
switch (_configuration.TableStyles)
{
case TableStyles.None:
- return ExcelXml.NoneStylesXml;
+ return ExcelXml.SetupStyleXml(ExcelXml.NoneStylesXml, columns);
case TableStyles.Default:
- return ExcelXml.DefaultStylesXml;
+ return ExcelXml.SetupStyleXml(ExcelXml.DefaultStylesXml, columns);
default:
return string.Empty;
}
diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs
index 07a7e267..79e211d6 100644
--- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs
+++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs
@@ -1,4 +1,5 @@
-using MiniExcelLibs.OpenXml.Constants;
+using MiniExcelLibs.Attributes;
+using MiniExcelLibs.OpenXml.Constants;
using MiniExcelLibs.OpenXml.Models;
using MiniExcelLibs.Utils;
using MiniExcelLibs.Zip;
@@ -68,6 +69,7 @@ internal void GenerateDefaultOpenXml()
{
CreateZipEntry(ExcelFileNames.Rels, ExcelContentTypes.Relationships, ExcelXml.DefaultRels);
CreateZipEntry(ExcelFileNames.SharedStrings, ExcelContentTypes.SharedStrings, ExcelXml.DefaultSharedString);
+ GenerateStylesXml();
}
private void CreateSheetXml(object value, string sheetPath)
@@ -79,29 +81,29 @@ private void CreateSheetXml(object value, string sheetPath)
if (value == null)
{
WriteEmptySheet(writer);
- goto End; //for re-using code
- }
-
- //DapperRow
-
- if (value is IDataReader)
- {
- GenerateSheetByIDataReader(writer, value as IDataReader);
- }
- else if (value is IEnumerable)
- {
- GenerateSheetByEnumerable(writer, value as IEnumerable);
- }
- else if (value is DataTable)
- {
- GenerateSheetByDataTable(writer, value as DataTable);
}
else
{
- throw new NotImplementedException($"Type {value.GetType().FullName} is not implemented. Please open an issue.");
+ //DapperRow
+
+ if (value is IDataReader)
+ {
+ GenerateSheetByIDataReader(writer, value as IDataReader);
+ }
+ else if (value is IEnumerable)
+ {
+ GenerateSheetByEnumerable(writer, value as IEnumerable);
+ }
+ else if (value is DataTable)
+ {
+ GenerateSheetByDataTable(writer, value as DataTable);
+ }
+ else
+ {
+ throw new NotImplementedException($"Type {value.GetType().FullName} is not implemented. Please open an issue.");
+ }
}
}
- End: //for re-using code
_zipDictionary.Add(sheetPath, new ZipPackageInfo(entry, ExcelContentTypes.Worksheet));
}
@@ -151,7 +153,7 @@ private void GenerateSheetByIDataReader(MiniExcelStreamWriter writer, IDataReade
for (int i = 0; i < fieldCount; i++)
{
var cellValue = reader.GetValue(i);
- WriteCell(writer, yIndex, xIndex, cellValue, columnInfo: null);
+ WriteCell(writer, yIndex, xIndex, cellValue, columnInfo: props?.FirstOrDefault(x => x?.ExcelColumnIndex == xIndex - 1));
xIndex++;
}
writer.Write(WorksheetXml.EndRow);
@@ -356,7 +358,7 @@ private void GenerateSheetByDataTable(MiniExcelStreamWriter writer, DataTable va
for (int j = 0; j < value.Columns.Count; j++)
{
var cellValue = value.Rows[i][j];
- WriteCell(writer, yIndex, xIndex, cellValue, columnInfo: null);
+ WriteCell(writer, yIndex, xIndex, cellValue, columnInfo: props?.FirstOrDefault(x => x?.ExcelColumnIndex == xIndex - 1));
xIndex++;
}
writer.Write(WorksheetXml.EndRow);
@@ -454,7 +456,7 @@ private int GenerateSheetByColumnInfo(MiniExcelStreamWriter writer, IEnumerat
return yIndex - 1;
}
-
+
private void WriteCell(MiniExcelStreamWriter writer, int rowIndex, int cellIndex, object value, ExcelColumnInfo columnInfo)
{
var columnReference = ExcelOpenXmlUtils.ConvertXyToCell(cellIndex, rowIndex);
@@ -484,8 +486,6 @@ private void GenerateEndXml()
{
AddFilesToZip();
- GenerateStylesXml();
-
GenerateDrawinRelXml();
GenerateDrawingXml();
@@ -508,7 +508,7 @@ private void AddFilesToZip()
///
private void GenerateStylesXml()
{
- var styleXml = GetStylesXml();
+ var styleXml = GetStylesXml(_configuration.DynamicColumns);
CreateZipEntry(ExcelFileNames.Styles, ExcelContentTypes.Styles, styleXml);
}
@@ -600,4 +600,4 @@ private void CreateZipEntry(string path, byte[] content)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/MiniExcel/Utils/CustomPropertyHelper.cs b/src/MiniExcel/Utils/CustomPropertyHelper.cs
index 7fa06114..fa7f164f 100644
--- a/src/MiniExcel/Utils/CustomPropertyHelper.cs
+++ b/src/MiniExcel/Utils/CustomPropertyHelper.cs
@@ -23,6 +23,7 @@ internal class ExcelColumnInfo
public double? ExcelColumnWidth { get; internal set; }
public string ExcelIndexName { get; internal set; }
public bool ExcelIgnore { get; internal set; }
+ public int ExcelFormatId { get; internal set; }
}
internal class ExcellSheetInfo
@@ -205,6 +206,7 @@ private static IEnumerable ConvertToExcelCustomPropertyInfo(Pro
ExcelIndexName = p.GetAttribute()?.ExcelXName ?? excelColumn?.IndexName,
ExcelColumnWidth = p.GetAttribute()?.ExcelColumnWidth ?? excelColumn?.Width,
ExcelFormat = excelFormat ?? excelColumn?.Format,
+ ExcelFormatId = excelColumn?.FormatId ?? -1
};
}).Where(_ => _ != null);
}
@@ -292,7 +294,10 @@ internal static void SetDictionaryColumnInfo(List _props, objec
p.Nullable = true;
//p.ExcludeNullableType = item2[key]?.GetType();
if (dynamicColumn.Format != null)
+ {
p.ExcelFormat = dynamicColumn.Format;
+ p.ExcelFormatId = dynamicColumn.FormatId;
+ }
if (dynamicColumn.Aliases != null)
p.ExcelColumnAliases = dynamicColumn.Aliases;
if (dynamicColumn.IndexName != null)
diff --git a/tests/MiniExcelTests/MiniExcelIssueTests.cs b/tests/MiniExcelTests/MiniExcelIssueTests.cs
index 220d538f..498fa29f 100644
--- a/tests/MiniExcelTests/MiniExcelIssueTests.cs
+++ b/tests/MiniExcelTests/MiniExcelIssueTests.cs
@@ -309,7 +309,7 @@ public void TestIssue370()
var rows = MiniExcel.Query(path, false).ToList();
Assert.Equal("createdate", rows[0].A);
- Assert.Equal("2022-04-12", rows[1].A);
+ Assert.Equal(new DateTime(2022, 04, 12), rows[1].A);
Assert.Equal("name", rows[0].B);
Assert.Equal("Jack", rows[1].B);
Assert.Equal("Account Point", rows[0].C);
@@ -334,7 +334,7 @@ public void TestIssue369()
var rows = MiniExcel.Query(path, false).ToList();
Assert.Equal("createdate", rows[0].A);
- Assert.Equal("2022-04-12", rows[1].A);
+ Assert.Equal(new DateTime(2022, 04, 12), rows[1].A);
Assert.Equal("name", rows[0].B);
Assert.Equal("Jack", rows[1].B);
Assert.Equal("Account Point", rows[0].C);
diff --git a/tests/MiniExcelTests/MiniExcelOpenXmlAsyncTests.cs b/tests/MiniExcelTests/MiniExcelOpenXmlAsyncTests.cs
index d2cae10e..ecf4fd06 100644
--- a/tests/MiniExcelTests/MiniExcelOpenXmlAsyncTests.cs
+++ b/tests/MiniExcelTests/MiniExcelOpenXmlAsyncTests.cs
@@ -1281,5 +1281,150 @@ await Assert.ThrowsAsync(async () =>
}
});
}
+
+ [Fact]
+ public async Task DynamicColumnsConfigurationIsUsedWhenCreatingExcelUsingIDataReader()
+ {
+ var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx");
+ var dateTime = DateTime.Now;
+ var onlyDate = DateOnly.FromDateTime(dateTime);
+ var table = new DataTable();
+ {
+ table.Columns.Add("Column1", typeof(string));
+ table.Columns.Add("Column2", typeof(int));
+ table.Columns.Add("Column3", typeof(DateTime));
+ table.Columns.Add("Column4", typeof(DateOnly));
+ table.Rows.Add("MiniExcel", 1, dateTime, onlyDate);
+ table.Rows.Add("Github", 2, dateTime, onlyDate);
+ }
+
+ var configuration = new OpenXmlConfiguration
+ {
+ DynamicColumns = new[]
+ {
+ new DynamicExcelColumn("Column1")
+ {
+ Name = "Name of something",
+ Index = 0,
+ Width = 150
+ },
+ new DynamicExcelColumn("Column2")
+ {
+ Name = "Its value",
+ Index = 1,
+ Width = 150
+ },
+ new DynamicExcelColumn("Column3")
+ {
+ Name = "Its Date",
+ Index = 2,
+ Width = 150,
+ Format = "dd.mm.yyyy hh:mm:ss",
+ }
+
+ }
+ };
+ var reader = table.CreateDataReader();
+
+ await MiniExcel.SaveAsAsync(path, reader, configuration: configuration);
+
+ using (var stream = File.OpenRead(path))
+ {
+ var rows = stream.Query(useHeaderRow: true)
+ .Select(x => (IDictionary)x)
+ .ToList();
+
+ Assert.Contains("Name of something", rows[0]);
+ Assert.Contains("Its value", rows[0]);
+ Assert.Contains("Its Date", rows[0]);
+ Assert.Contains("Column4", rows[0]);
+ Assert.Contains("Name of something", rows[1]);
+ Assert.Contains("Its value", rows[1]);
+ Assert.Contains("Its Date", rows[1]);
+ Assert.Contains("Column4", rows[1]);
+
+ Assert.Equal("MiniExcel", rows[0]["Name of something"]);
+ Assert.Equal(1D, rows[0]["Its value"]);
+ Assert.Equal(dateTime, (DateTime)rows[0]["Its Date"], TimeSpan.FromMilliseconds(10d));
+ Assert.Equal(onlyDate.ToDateTime(TimeOnly.MinValue), (DateTime)rows[0]["Column4"]);
+ Assert.Equal("Github", rows[1]["Name of something"]);
+ Assert.Equal(2D, rows[1]["Its value"]);
+ Assert.Equal(dateTime, (DateTime)rows[1]["Its Date"], TimeSpan.FromMilliseconds(10d));
+ Assert.Equal(onlyDate.ToDateTime(TimeOnly.MinValue), (DateTime)rows[1]["Column4"]);
+ }
+ }
+
+ [Fact]
+ public async Task DynamicColumnsConfigurationIsUsedWhenCreatingExcelUsingDataTable()
+ {
+ var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx");
+ var dateTime = DateTime.Now;
+ var onlyDate = DateOnly.FromDateTime(dateTime);
+ var table = new DataTable();
+ {
+ table.Columns.Add("Column1", typeof(string));
+ table.Columns.Add("Column2", typeof(int));
+ table.Columns.Add("Column3", typeof(DateTime));
+ table.Columns.Add("Column4", typeof(DateOnly));
+ table.Rows.Add("MiniExcel", 1, dateTime, onlyDate);
+ table.Rows.Add("Github", 2, dateTime, onlyDate);
+ }
+
+ var configuration = new OpenXmlConfiguration
+ {
+ DynamicColumns = new[]
+ {
+ new DynamicExcelColumn("Column1")
+ {
+ Name = "Name of something",
+ Index = 0,
+ Width = 150
+ },
+ new DynamicExcelColumn("Column2")
+ {
+ Name = "Its value",
+ Index = 1,
+ Width = 150
+ },
+ new DynamicExcelColumn("Column3")
+ {
+ Name = "Its Date",
+ Index = 2,
+ Width = 150,
+ Format = "dd.mm.yyyy hh:mm:ss"
+ }
+ }
+ };
+
+ await MiniExcel.SaveAsAsync(path, table, configuration: configuration);
+
+ using (var stream = File.OpenRead(path))
+ {
+ var rows = stream.Query(useHeaderRow: true)
+ .Select(x => (IDictionary)x)
+ .Select(x => (IDictionary)x)
+ .ToList();
+
+ Assert.Contains("Name of something", rows[0]);
+ Assert.Contains("Its value", rows[0]);
+ Assert.Contains("Its Date", rows[0]);
+ Assert.Contains("Column4", rows[0]);
+ Assert.Contains("Name of something", rows[1]);
+ Assert.Contains("Its value", rows[1]);
+ Assert.Contains("Its Date", rows[1]);
+ Assert.Contains("Column4", rows[1]);
+
+
+ Assert.Equal("MiniExcel", rows[0]["Name of something"]);
+ Assert.Equal(1D, rows[0]["Its value"]);
+ Assert.Equal(dateTime, (DateTime)rows[0]["Its Date"], TimeSpan.FromMilliseconds(10d));
+ Assert.Equal(onlyDate.ToDateTime(TimeOnly.MinValue), (DateTime)rows[0]["Column4"]);
+ Assert.Equal("Github", rows[1]["Name of something"]);
+ Assert.Equal(2D, rows[1]["Its value"]);
+ Assert.Equal(dateTime, (DateTime)rows[1]["Its Date"], TimeSpan.FromMilliseconds(10d));
+ Assert.Equal(onlyDate.ToDateTime(TimeOnly.MinValue), (DateTime)rows[1]["Column4"]);
+ }
+ }
+
}
}
\ No newline at end of file
diff --git a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs
index 1aa967e2..5af73bb3 100644
--- a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs
+++ b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs
@@ -1217,12 +1217,16 @@ public void SharedStringNoCacheTest()
public void DynamicColumnsConfigurationIsUsedWhenCreatingExcelUsingIDataReader()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx");
+ var dateTime = DateTime.Now;
+ var onlyDate = DateOnly.FromDateTime(dateTime);
var table = new DataTable();
{
table.Columns.Add("Column1", typeof(string));
table.Columns.Add("Column2", typeof(int));
- table.Rows.Add("MiniExcel", 1);
- table.Rows.Add("Github", 2);
+ table.Columns.Add("Column3", typeof(DateTime));
+ table.Columns.Add("Column4", typeof(DateOnly));
+ table.Rows.Add("MiniExcel", 1, dateTime, onlyDate);
+ table.Rows.Add("Github", 2, dateTime, onlyDate);
}
var configuration = new OpenXmlConfiguration
@@ -1240,7 +1244,15 @@ public void DynamicColumnsConfigurationIsUsedWhenCreatingExcelUsingIDataReader()
Name = "Its value",
Index = 1,
Width = 150
+ },
+ new DynamicExcelColumn("Column3")
+ {
+ Name = "Its Date",
+ Index = 2,
+ Width = 150,
+ Format = "dd.mm.yyyy hh:mm:ss",
}
+
}
};
var reader = table.CreateDataReader();
@@ -1255,13 +1267,21 @@ public void DynamicColumnsConfigurationIsUsedWhenCreatingExcelUsingIDataReader()
Assert.Contains("Name of something", rows[0]);
Assert.Contains("Its value", rows[0]);
+ Assert.Contains("Its Date", rows[0]);
+ Assert.Contains("Column4", rows[0]);
Assert.Contains("Name of something", rows[1]);
Assert.Contains("Its value", rows[1]);
+ Assert.Contains("Its Date", rows[1]);
+ Assert.Contains("Column4", rows[1]);
Assert.Equal("MiniExcel", rows[0]["Name of something"]);
Assert.Equal(1D, rows[0]["Its value"]);
+ Assert.Equal(dateTime, (DateTime)rows[0]["Its Date"], TimeSpan.FromMilliseconds(10d));
+ Assert.Equal(onlyDate.ToDateTime(TimeOnly.MinValue), (DateTime)rows[0]["Column4"]);
Assert.Equal("Github", rows[1]["Name of something"]);
Assert.Equal(2D, rows[1]["Its value"]);
+ Assert.Equal(dateTime, (DateTime)rows[1]["Its Date"], TimeSpan.FromMilliseconds(10d));
+ Assert.Equal(onlyDate.ToDateTime(TimeOnly.MinValue), (DateTime)rows[1]["Column4"]);
}
}
@@ -1269,12 +1289,16 @@ public void DynamicColumnsConfigurationIsUsedWhenCreatingExcelUsingIDataReader()
public void DynamicColumnsConfigurationIsUsedWhenCreatingExcelUsingDataTable()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx");
+ var dateTime = DateTime.Now;
+ var onlyDate = DateOnly.FromDateTime(dateTime);
var table = new DataTable();
{
table.Columns.Add("Column1", typeof(string));
table.Columns.Add("Column2", typeof(int));
- table.Rows.Add("MiniExcel", 1);
- table.Rows.Add("Github", 2);
+ table.Columns.Add("Column3", typeof(DateTime));
+ table.Columns.Add("Column4", typeof(DateOnly));
+ table.Rows.Add("MiniExcel", 1, dateTime, onlyDate);
+ table.Rows.Add("Github", 2, dateTime, onlyDate);
}
var configuration = new OpenXmlConfiguration
@@ -1292,6 +1316,13 @@ public void DynamicColumnsConfigurationIsUsedWhenCreatingExcelUsingDataTable()
Name = "Its value",
Index = 1,
Width = 150
+ },
+ new DynamicExcelColumn("Column3")
+ {
+ Name = "Its Date",
+ Index = 2,
+ Width = 150,
+ Format = "dd.mm.yyyy hh:mm:ss"
}
}
};
@@ -1307,14 +1338,22 @@ public void DynamicColumnsConfigurationIsUsedWhenCreatingExcelUsingDataTable()
Assert.Contains("Name of something", rows[0]);
Assert.Contains("Its value", rows[0]);
+ Assert.Contains("Its Date", rows[0]);
+ Assert.Contains("Column4", rows[0]);
Assert.Contains("Name of something", rows[1]);
Assert.Contains("Its value", rows[1]);
+ Assert.Contains("Its Date", rows[1]);
+ Assert.Contains("Column4", rows[1]);
Assert.Equal("MiniExcel", rows[0]["Name of something"]);
Assert.Equal(1D, rows[0]["Its value"]);
+ Assert.Equal(dateTime, (DateTime)rows[0]["Its Date"], TimeSpan.FromMilliseconds(10d));
+ Assert.Equal(onlyDate.ToDateTime(TimeOnly.MinValue), (DateTime)rows[0]["Column4"]);
Assert.Equal("Github", rows[1]["Name of something"]);
Assert.Equal(2D, rows[1]["Its value"]);
+ Assert.Equal(dateTime, (DateTime)rows[1]["Its Date"], TimeSpan.FromMilliseconds(10d));
+ Assert.Equal(onlyDate.ToDateTime(TimeOnly.MinValue), (DateTime)rows[1]["Column4"]);
}
}
}