Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make use of dynamic columns when generating sheet by IDataReader to change columns names & widths #514

Merged
merged 1 commit into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Make use of dynamic columns when generating sheet by IDataReader to c…
…hange column names & widths
  • Loading branch information
Laxynium committed Jul 18, 2023
commit bc569ee67345373b4037e87375f4dbf1e3698d99
63 changes: 60 additions & 3 deletions src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -609,17 +609,26 @@ private void GenerateSheetByIDataReader(MiniExcelStreamWriter writer, IDataReade
writer.Write(" />"); // end of code will be replaced
}

var props = new List<ExcelColumnInfo>();
for (var i = 0; i < reader.FieldCount; i++)
{
var columnName = reader.GetName(i);
var prop = GetColumnInfosForIDataReader(columnName);
props.Add(prop);
}

WriteColumnsWidths(writer, props);

writer.Write("<x:sheetData>");
int fieldCount = reader.FieldCount;
if (_printHeader)
{
writer.Write($"<x:row r=\"{yIndex}\">");
xIndex = xy.Item1;
for (int i = 0; i < fieldCount; i++)
foreach (var p in props)
{
var r = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
var columnName = reader.GetName(i);
WriteC(writer, r, columnName);
WriteC(writer, r, columnName: p.ExcelColumnName);
xIndex++;
}
writer.Write($"</x:row>");
Expand Down Expand Up @@ -653,6 +662,54 @@ private void GenerateSheetByIDataReader(MiniExcelStreamWriter writer, IDataReade
}
}

private ExcelColumnInfo GetColumnInfosForIDataReader(string columnName)
{
var prop = new ExcelColumnInfo
{
ExcelColumnName = columnName,
Key = columnName
};

if (_configuration.DynamicColumns == null || _configuration.DynamicColumns.Length <= 0)
return prop;

var dynamicColumn = _configuration.DynamicColumns.SingleOrDefault(_ => _.Key == columnName);
if (dynamicColumn == null || dynamicColumn.Ignore)
{
return prop;
}

prop.Nullable = true;
//prop.ExcludeNullableType = item2[key]?.GetType();
if (dynamicColumn.Format != null)
prop.ExcelFormat = dynamicColumn.Format;
if (dynamicColumn.Aliases != null)
prop.ExcelColumnAliases = dynamicColumn.Aliases;
if (dynamicColumn.IndexName != null)
prop.ExcelIndexName = dynamicColumn.IndexName;
prop.ExcelColumnIndex = dynamicColumn.Index;
if (dynamicColumn.Name != null)
prop.ExcelColumnName = dynamicColumn.Name;
prop.ExcelColumnWidth = dynamicColumn.Width;

return prop;
}

private static void WriteColumnsWidths(MiniExcelStreamWriter writer, IEnumerable<ExcelColumnInfo> props)
{
var ecwProps = props.Where(x => x?.ExcelColumnWidth != null).ToList();
if (ecwProps.Count <= 0)
return;
writer.Write($@"<x:cols>");
foreach (var p in ecwProps)
{
writer.Write(
$@"<x:col min=""{p.ExcelColumnIndex + 1}"" max=""{p.ExcelColumnIndex + 1}"" width=""{p.ExcelColumnWidth}"" customWidth=""1"" />");
}

writer.Write($@"</x:cols>");
}

private static void WriteC(MiniExcelStreamWriter writer, string r, string columnName)
{
writer.Write($"<x:c r=\"{r}\" t=\"str\" s=\"1\">");
Expand Down
52 changes: 52 additions & 0 deletions tests/MiniExcelTests/MiniExcelOpenXmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,5 +1197,57 @@ public void SharedStringNoCacheTest()
output.WriteLine("elapsedMilliseconds: " + stopWatch.ElapsedMilliseconds);
stopWatch.Stop();
}

[Fact]
public void DynamicColumnsConfigurationIsUsedWhenCreatingExcelUsingIDataReader()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx");
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);
}

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
}
}
};
var reader = table.CreateDataReader();

MiniExcel.SaveAs(path, reader, configuration: configuration);

using (var stream = File.OpenRead(path))
{
var rows = stream.Query(useHeaderRow: true)
.Select(x => (IDictionary<string,object>)x)
.ToList();

Assert.Contains("Name of something", rows[0]);
Assert.Contains("Its value", rows[0]);
Assert.Contains("Name of something", rows[1]);
Assert.Contains("Its value", rows[1]);

Assert.Equal("MiniExcel", rows[0]["Name of something"]);
Assert.Equal(1D, rows[0]["Its value"]);
Assert.Equal("Github", rows[1]["Name of something"]);
Assert.Equal(2D, rows[1]["Its value"]);
}
}
}
}