diff --git a/docs/README.zh-Hant.md b/docs/README.zh-Hant.md
index b019e584..cf2cdcec 100644
--- a/docs/README.zh-Hant.md
+++ b/docs/README.zh-Hant.md
@@ -4,7 +4,6 @@
-
diff --git a/src/README.md b/src/README.md
index d9cb2979..cbfe70bf 100644
--- a/src/README.md
+++ b/src/README.md
@@ -7,9 +7,6 @@
-
-
-
diff --git a/tests/MiniExcel.Csv.Tests/Issues/GiteeIssuesTests.cs b/tests/MiniExcel.Csv.Tests/Issues/GiteeIssuesTests.cs
new file mode 100644
index 00000000..ce071a15
--- /dev/null
+++ b/tests/MiniExcel.Csv.Tests/Issues/GiteeIssuesTests.cs
@@ -0,0 +1,103 @@
+namespace MiniExcelLib.Csv.Tests.Issues;
+
+public class GiteeIssuesTests
+{
+ private readonly CsvExporter _csvExporter = MiniExcel.Exporters.GetCsvExporter();
+
+ // https://gitee.com/dotnetchina/MiniExcel/issues/I4X92G
+ [Fact]
+ public void TestIssueI4X92G()
+ {
+ using var file = AutoDeletingPath.Create(ExcelType.Csv);
+ var path = file.ToString();
+
+ {
+ var value = new[]
+ {
+ new { ID = 1, Name = "Jack", InDate = new DateTime(2021,01,03)},
+ new { ID = 2, Name = "Henry", InDate = new DateTime(2020,05,03)}
+ };
+ _csvExporter.Export(path, value);
+ var content = File.ReadAllText(path);
+ Assert.Equal(
+ """
+ ID,Name,InDate
+ 1,Jack,"2021-01-03 00:00:00"
+ 2,Henry,"2020-05-03 00:00:00"
+
+ """,
+ content);
+ }
+ {
+ var value = new { ID = 3, Name = "Mike", InDate = new DateTime(2021, 04, 23) };
+ var rowsWritten = _csvExporter.Append(path, value);
+ Assert.Equal(1, rowsWritten);
+
+ var content = File.ReadAllText(path);
+ Assert.Equal(
+ """
+ ID,Name,InDate
+ 1,Jack,"2021-01-03 00:00:00"
+ 2,Henry,"2020-05-03 00:00:00"
+ 3,Mike,"2021-04-23 00:00:00"
+
+ """,
+ content);
+ }
+ {
+ var value = new[]
+ {
+ new { ID=4,Name ="Frank",InDate=new DateTime(2021,06,07)},
+ new { ID=5,Name ="Gloria",InDate=new DateTime(2022,05,03)},
+ };
+ var rowsWritten = _csvExporter.Append(path, value);
+ Assert.Equal(2, rowsWritten);
+
+ var content = File.ReadAllText(path);
+ Assert.Equal(
+ """
+ ID,Name,InDate
+ 1,Jack,"2021-01-03 00:00:00"
+ 2,Henry,"2020-05-03 00:00:00"
+ 3,Mike,"2021-04-23 00:00:00"
+ 4,Frank,"2021-06-07 00:00:00"
+ 5,Gloria,"2022-05-03 00:00:00"
+
+ """,
+ content);
+ }
+ }
+
+ [Fact]
+ public void TestIssueI4Wda9()
+ {
+ using var path = AutoDeletingPath.Create(ExcelType.Csv);
+ var value = new DataTable();
+ {
+ value.Columns.Add("\"name\"");
+ value.Rows.Add("\"Jack\"");
+ }
+
+ _csvExporter.Export(path.ToString(), value);
+ Assert.Equal("\"\"\"name\"\"\"\r\n\"\"\"Jack\"\"\"\r\n", File.ReadAllText(path.ToString()));
+ }
+
+ // Using stream.SaveAs will close the Stream automatically when Specifying excelType
+ // https://gitee.com/dotnetchina/MiniExcel/issues/I57WMM
+ [Fact]
+ public void TestIssueGiteeI57()
+ {
+ Dictionary
[] sheets = [new() { ["ID"] = "0001", ["Name"] = "Jack" }];
+ using var stream = new MemoryStream();
+
+ var config = new CsvConfiguration { StreamWriterFunc = x => new StreamWriter(x, Encoding.Default, leaveOpen: true) };
+ _csvExporter.Export(stream, sheets, configuration: config);
+ stream.Seek(0, SeekOrigin.Begin);
+
+ // convert stream to string
+ using var reader = new StreamReader(stream);
+ var text = reader.ReadToEnd();
+
+ Assert.Equal("ID,Name\r\n0001,Jack\r\n", text);
+ }
+}
\ No newline at end of file
diff --git a/tests/MiniExcel.Csv.Tests/AsyncIssueTests.cs b/tests/MiniExcel.Csv.Tests/Issues/GithubIssuesAsyncTests.cs
similarity index 72%
rename from tests/MiniExcel.Csv.Tests/AsyncIssueTests.cs
rename to tests/MiniExcel.Csv.Tests/Issues/GithubIssuesAsyncTests.cs
index 72252161..b9ab20f7 100644
--- a/tests/MiniExcel.Csv.Tests/AsyncIssueTests.cs
+++ b/tests/MiniExcel.Csv.Tests/Issues/GithubIssuesAsyncTests.cs
@@ -1,110 +1,11 @@
-namespace MiniExcelLib.Csv.Tests;
+namespace MiniExcelLib.Csv.Tests.Issues;
-public class AsyncIssueTests
+public class GithubIssuesAsyncTests
{
private readonly CsvExporter _csvExporter = MiniExcel.Exporters.GetCsvExporter();
private readonly CsvImporter _csvImporter = MiniExcel.Importers.GetCsvImporter();
- ///
- /// Csv SaveAs by datareader with encoding default show messy code #253
- ///
- [Fact]
- public async Task Issue253()
- {
- {
- var value = new[] { new { col1 = "世界你好" } };
- using var path = AutoDeletingPath.Create(ExcelType.Csv);
-
- await _csvExporter.ExportAsync(path.ToString(), value);
- const string expected =
- """
- col1
- 世界你好
-
- """;
-
- Assert.Equal(expected, await File.ReadAllTextAsync(path.ToString()));
- }
-
- {
- Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
- var value = new[] { new { col1 = "世界你好" } };
- using var path = AutoDeletingPath.Create(ExcelType.Csv);
-
- var config = new CsvConfiguration
- {
- StreamWriterFunc = stream => new StreamWriter(stream, Encoding.GetEncoding("gb2312"))
- };
-
- await _csvExporter.ExportAsync(path.ToString(), value, configuration: config);
- const string expected =
- """
- col1
- �������
-
- """;
-
- Assert.Equal(expected, await File.ReadAllTextAsync(path.ToString()));
- }
-
- await using var cn = Db.GetConnection();
-
- {
- var value = await cn.ExecuteReaderAsync("select '世界你好' col1");
- using var path = AutoDeletingPath.Create(ExcelType.Csv);
- await _csvExporter.ExportAsync(path.ToString(), value);
- const string expected =
- """
- col1
- 世界你好
-
- """;
-
- Assert.Equal(expected, await File.ReadAllTextAsync(path.ToString()));
- }
- }
-
- ///
- /// [CSV SaveAs support datareader · Issue #251 · mini-software/MiniExcel](https://github.com/mini-software/MiniExcel/issues/251)
- ///
- [Fact]
- public async Task Issue251()
- {
- await using var cn = Db.GetConnection();
- var reader = await cn.ExecuteReaderAsync(@"select '""<>+-*//}{\\n' a,1234567890 b union all select 'Hello World',-1234567890");
-
- using var path = AutoDeletingPath.Create(ExcelType.Csv);
- var rowsWritten = await _csvExporter.ExportAsync(path.ToString(), reader);
-
- Assert.Equal(2, rowsWritten);
-
- const string expected =
- """"
- a,b
- """<>+-*//}{\\n",1234567890
- "Hello World",-1234567890
-
- """";
-
- Assert.Equal(expected, await File.ReadAllTextAsync(path.ToString()));
- }
-
- private class Issue89Dto
- {
- public WorkState State { get; set; }
-
- public enum WorkState
- {
- OnDuty,
- Leave,
- Fired
- }
- }
-
- ///
- /// Support Enum Mapping
- /// https://github.com/mini-software/MiniExcel/issues/89
- ///
+ // Support Enum Mapping
[Fact]
public async Task Issue89()
{
@@ -140,20 +41,6 @@ public async Task Issue89()
Assert.Equal(Issue89Dto.WorkState.Leave, rows2[2].State);
}
- private class Issue142VoDuplicateColumnName
- {
- [MiniExcelColumnIndex("A")]
- public int MyProperty1 { get; set; }
-
- [MiniExcelColumnIndex("A")]
- public int MyProperty2 { get; set; }
-
- public int MyProperty3 { get; set; }
- [MiniExcelColumnIndex("B")]
-
- public int MyProperty4 { get; set; }
- }
-
[Fact]
public async Task Issue142()
{
@@ -180,10 +67,7 @@ public async Task Issue142()
Assert.Equal("MyProperty3", rows[0].MyProperty3);
}
- ///
- /// DataTable recommended to use Caption for column name first, then use columname
- /// https://github.com/mini-software/MiniExcel/issues/217
- ///
+ // DataTable recommended to use Caption for column name first, then use columname
[Fact]
public async Task Issue217()
{
@@ -203,10 +87,7 @@ public async Task Issue217()
}
- ///
- /// Csv QueryAsync split comma not correct #237
- /// https://github.com/mini-software/MiniExcel/issues/237
- ///
+ // Csv QueryAsync split comma not correct
[Fact]
public async Task Issue237()
{
@@ -223,10 +104,7 @@ public async Task Issue237()
Assert.Equal("1,2,3", rows[1].id);
}
-
- ///
- /// Support Custom Datetime format #241
- ///
+ // Support Custom Datetime format
[Fact]
public async Task Issue241()
{
@@ -252,9 +130,7 @@ public async Task Issue241()
}
- ///
- /// Csv type mapping QueryAsync error "cannot be converted to xxx type" #243
- ///
+ // Csv type mapping QueryAsync error "cannot be converted to xxx type"
[Fact]
public async Task Issue243()
{
@@ -279,36 +155,83 @@ public async Task Issue243()
Assert.Equal(new DateTime(2020, 05, 03), rows[1].InDate);
}
- #region Duplicated
- private class Issue142Dto
- {
- [MiniExcelColumnName("CustomColumnName")]
- public string? MyProperty1 { get; set; } //index = 1
- [MiniExcelIgnore]
- public string? MyProperty7 { get; set; } //index = null
- public string? MyProperty2 { get; set; } //index = 3
- [MiniExcelColumnIndex(6)]
- public string? MyProperty3 { get; set; } //index = 6
- [MiniExcelColumnIndex("A")] // equal column index 0
- public string? MyProperty4 { get; set; }
- [MiniExcelColumnIndex(2)]
- public string? MyProperty5 { get; set; } //index = 2
- public string? MyProperty6 { get; set; } //index = 4
- }
-
- private class Issue241Dto
+ // CSV support export from datareader
+ [Fact]
+ public async Task Issue251()
{
- public string? Name { get; set; }
+ await using var cn = Db.GetConnection();
+ var reader = await cn.ExecuteReaderAsync(@"select '""<>+-*//}{\\n' a,1234567890 b union all select 'Hello World',-1234567890");
+
+ using var path = AutoDeletingPath.Create(ExcelType.Csv);
+ var rowsWritten = await _csvExporter.ExportAsync(path.ToString(), reader);
+
+ Assert.Equal(2, rowsWritten);
+
+ const string expected =
+ """"
+ a,b
+ """<>+-*//}{\\n",1234567890
+ "Hello World",-1234567890
- [MiniExcelFormat("MM dd, yyyy")]
- public DateTime InDate { get; set; }
+ """";
+
+ Assert.Equal(expected, await File.ReadAllTextAsync(path.ToString()));
}
-
- private class Issue243Dto
+
+ // Csv export from datareader with default encoding shows incorrect result
+ [Fact]
+ public async Task Issue253()
{
- public string? Name { get; set; }
- public int Age { get; set; }
- public DateTime InDate { get; set; }
+ {
+ var value = new[] { new { col1 = "世界你好" } };
+ using var path = AutoDeletingPath.Create(ExcelType.Csv);
+
+ await _csvExporter.ExportAsync(path.ToString(), value);
+ const string expected =
+ """
+ col1
+ 世界你好
+
+ """;
+
+ Assert.Equal(expected, await File.ReadAllTextAsync(path.ToString()));
+ }
+
+ {
+ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+ var value = new[] { new { col1 = "世界你好" } };
+ using var path = AutoDeletingPath.Create(ExcelType.Csv);
+
+ var config = new CsvConfiguration
+ {
+ StreamWriterFunc = stream => new StreamWriter(stream, Encoding.GetEncoding("gb2312"))
+ };
+
+ await _csvExporter.ExportAsync(path.ToString(), value, configuration: config);
+ const string expected =
+ """
+ col1
+ �������
+
+ """;
+
+ Assert.Equal(expected, await File.ReadAllTextAsync(path.ToString()));
+ }
+
+ await using var cn = Db.GetConnection();
+
+ {
+ var value = await cn.ExecuteReaderAsync("select '世界你好' col1");
+ using var path = AutoDeletingPath.Create(ExcelType.Csv);
+ await _csvExporter.ExportAsync(path.ToString(), value);
+ const string expected =
+ """
+ col1
+ 世界你好
+
+ """;
+
+ Assert.Equal(expected, await File.ReadAllTextAsync(path.ToString()));
+ }
}
- #endregion
}
diff --git a/tests/MiniExcel.Csv.Tests/IssueTests.cs b/tests/MiniExcel.Csv.Tests/Issues/GithubIssuesTests.cs
similarity index 66%
rename from tests/MiniExcel.Csv.Tests/IssueTests.cs
rename to tests/MiniExcel.Csv.Tests/Issues/GithubIssuesTests.cs
index 1a43a316..90f2dc0f 100644
--- a/tests/MiniExcel.Csv.Tests/IssueTests.cs
+++ b/tests/MiniExcel.Csv.Tests/Issues/GithubIssuesTests.cs
@@ -1,8 +1,6 @@
-using MiniExcelLib.OpenXml;
+namespace MiniExcelLib.Csv.Tests.Issues;
-namespace MiniExcelLib.Csv.Tests;
-
-public class IssueTests
+public class GithubIssuesTests
{
private readonly CsvExporter _csvExporter = MiniExcel.Exporters.GetCsvExporter();
private readonly CsvImporter _csvImporter = MiniExcel.Importers.GetCsvImporter();
@@ -10,138 +8,165 @@ public class IssueTests
private readonly OpenXmlExporter _openXmlExporter = MiniExcel.Exporters.GetOpenXmlExporter();
private readonly OpenXmlImporter _openXmlImporter = MiniExcel.Importers.GetOpenXmlImporter();
+ // Support for Enum Mapping
[Fact]
- public void TestPullRequest10()
+ public void Issue89()
{
- var path = PathHelper.GetFile("csv/TestIssue142.csv");
- var config = new CsvConfiguration
- {
- SplitFn = row => Regex.Split(row, "[\t,](?=(?:[^\"]|\"[^\"]*\")*$)")
- .Select(s => Regex.Replace(s.Replace("\"\"", "\""), "^\"|\"$", ""))
- .ToArray()
- };
-
- var rows = _csvImporter.Query(path, configuration: config).ToList();
- Assert.Equal(2, rows.Count);
- Assert.Equal(15, ((IDictionary)rows[0]).Count);
- }
+ const string text =
+ """
+ State
+ OnDuty
+ Fired
+ Leave
+ """;
+
+ using var stream = new MemoryStream();
+ using var writer = new StreamWriter(stream);
+
+ writer.Write(text);
+ writer.Flush();
+ stream.Position = 0;
+ var rows = _csvImporter.Query(stream, hasHeaderRow: true).ToList();
+
+ Assert.Equal(nameof(Issue89Dto.WorkState.OnDuty), rows[0].State);
+ Assert.Equal(nameof(Issue89Dto.WorkState.Fired), rows[1].State);
+ Assert.Equal(nameof(Issue89Dto.WorkState.Leave), rows[2].State);
- ///
- /// https://gitee.com/dotnetchina/MiniExcel/issues/I49RZH
- /// https://github.com/mini-software/MiniExcel/issues/305
- ///
- [Fact]
- public void TestIssue305()
- {
using var path = AutoDeletingPath.Create(ExcelType.Csv);
- var value = new[]
- {
- new TestIssue305Dto{ Dt = DateTimeOffset.Parse("2022-01-22")},
- new TestIssue305Dto{ Dt = null}
- };
- _csvExporter.Export(path.ToString(), value);
+ _csvExporter.Export(path.ToString(), rows);
+ var rows2 = _csvImporter.Query(path.ToString()).ToList();
- var rows = _csvImporter.Query(path.ToString()).ToList();
- Assert.Equal("2022-01-22", rows[1].A);
+ Assert.Equal(Issue89Dto.WorkState.OnDuty, rows2[0].State);
+ Assert.Equal(Issue89Dto.WorkState.Fired, rows2[1].State);
+ Assert.Equal(Issue89Dto.WorkState.Leave, rows2[2].State);
}
- private class TestIssue305Dto
- {
- [MiniExcelFormat("yyyy-MM-dd")]
- public DateTimeOffset? Dt { get; set; }
- }
-
- ///
- /// https://gitee.com/dotnetchina/MiniExcel/issues/I4X92G
- ///
[Fact]
- public void TestIssueI4X92G()
+ public void Issue142()
{
- using var file = AutoDeletingPath.Create(ExcelType.Csv);
- var path = file.ToString();
-
{
- var value = new[]
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
+ Issue142Dto[] values =
+ [
+ new()
+ {
+ MyProperty1 = "MyProperty1", MyProperty2 = "MyProperty2", MyProperty3 = "MyProperty3",
+ MyProperty4 = "MyProperty4", MyProperty5 = "MyProperty5", MyProperty6 = "MyProperty6",
+ MyProperty7 = "MyProperty7"
+ }
+ ];
+ var rowsWritten = _openXmlExporter.Export(path, values);
+ Assert.Single(rowsWritten);
+ Assert.Equal(1, rowsWritten[0]);
+
{
- new { ID = 1, Name = "Jack", InDate = new DateTime(2021,01,03)},
- new { ID = 2, Name = "Henry", InDate = new DateTime(2020,05,03)}
- };
- _csvExporter.Export(path, value);
- var content = File.ReadAllText(path);
- Assert.Equal(
- """
- ID,Name,InDate
- 1,Jack,"2021-01-03 00:00:00"
- 2,Henry,"2020-05-03 00:00:00"
+ var rows = _openXmlImporter.Query(path).ToList();
+
+ Assert.Equal("MyProperty4", rows[0].A);
+ Assert.Equal("CustomColumnName", rows[0].B);
+ Assert.Equal("MyProperty5", rows[0].C);
+ Assert.Equal("MyProperty2", rows[0].D);
+ Assert.Equal("MyProperty6", rows[0].E);
+ Assert.Null(rows[0].F);
+ Assert.Equal("MyProperty3", rows[0].G);
+
+ Assert.Equal("MyProperty4", rows[0].A);
+ Assert.Equal("CustomColumnName", rows[0].B);
+ Assert.Equal("MyProperty5", rows[0].C);
+ Assert.Equal("MyProperty2", rows[0].D);
+ Assert.Equal("MyProperty6", rows[0].E);
+ Assert.Null(rows[0].F);
+ Assert.Equal("MyProperty3", rows[0].G);
+ }
- """,
- content);
+ {
+ var rows = _openXmlImporter.Query(path).ToList();
+
+ Assert.Equal("MyProperty4", rows[0].MyProperty4);
+ Assert.Equal("MyProperty1", rows[0].MyProperty1);
+ Assert.Equal("MyProperty5", rows[0].MyProperty5);
+ Assert.Equal("MyProperty2", rows[0].MyProperty2);
+ Assert.Equal("MyProperty6", rows[0].MyProperty6);
+ Assert.Null(rows[0].MyProperty7);
+ Assert.Equal("MyProperty3", rows[0].MyProperty3);
+ }
}
+
{
- var value = new { ID = 3, Name = "Mike", InDate = new DateTime(2021, 04, 23) };
- var rowsWritten = _csvExporter.Append(path, value);
+ using var file = AutoDeletingPath.Create(ExcelType.Csv);
+ var path = file.ToString();
+ Issue142Dto[] values =
+ [
+ new()
+ {
+ MyProperty1 = "MyProperty1", MyProperty2 = "MyProperty2", MyProperty3 = "MyProperty3",
+ MyProperty4 = "MyProperty4", MyProperty5 = "MyProperty5", MyProperty6 = "MyProperty6",
+ MyProperty7 = "MyProperty7"
+ }
+ ];
+ var rowsWritten = _csvExporter.Export(path, values);
Assert.Equal(1, rowsWritten);
- var content = File.ReadAllText(path);
- Assert.Equal(
+ const string expected =
"""
- ID,Name,InDate
- 1,Jack,"2021-01-03 00:00:00"
- 2,Henry,"2020-05-03 00:00:00"
- 3,Mike,"2021-04-23 00:00:00"
+ MyProperty4,CustomColumnName,MyProperty5,MyProperty2,MyProperty6,,MyProperty3
+ MyProperty4,MyProperty1,MyProperty5,MyProperty2,MyProperty6,,MyProperty3
+
+ """;
+
+ Assert.Equal(expected, File.ReadAllText(path));
- """,
- content);
- }
- {
- var value = new[]
{
- new { ID=4,Name ="Frank",InDate=new DateTime(2021,06,07)},
- new { ID=5,Name ="Gloria",InDate=new DateTime(2022,05,03)},
- };
- var rowsWritten = _csvExporter.Append(path, value);
- Assert.Equal(2, rowsWritten);
+ var rows = _csvImporter.Query(path).ToList();
- var content = File.ReadAllText(path);
- Assert.Equal(
- """
- ID,Name,InDate
- 1,Jack,"2021-01-03 00:00:00"
- 2,Henry,"2020-05-03 00:00:00"
- 3,Mike,"2021-04-23 00:00:00"
- 4,Frank,"2021-06-07 00:00:00"
- 5,Gloria,"2022-05-03 00:00:00"
-
- """,
- content);
+ Assert.Equal("MyProperty4", rows[0].MyProperty4);
+ Assert.Equal("MyProperty1", rows[0].MyProperty1);
+ Assert.Equal("MyProperty5", rows[0].MyProperty5);
+ Assert.Equal("MyProperty2", rows[0].MyProperty2);
+ Assert.Equal("MyProperty6", rows[0].MyProperty6);
+ Assert.Null(rows[0].MyProperty7);
+ Assert.Equal("MyProperty3", rows[0].MyProperty3);
+ }
}
- }
- private class TestIssue316Dto
- {
- public decimal Amount { get; set; }
- public DateTime CreateTime { get; set; }
+ {
+ using var path = AutoDeletingPath.Create(ExcelType.Csv);
+ Issue142DuplicateColumnNameDto[] input =
+ [
+ new() { MyProperty1 = 0, MyProperty2 = 0, MyProperty3 = 0, MyProperty4 = 0 }
+ ];
+ Assert.Throws(() => _csvExporter.Export(path.ToString(), input));
+ }
}
- ///
- /// Using stream.SaveAs will close the Stream automatically when Specifying excelType
- /// https://gitee.com/dotnetchina/MiniExcel/issues/I57WMM
- ///
[Fact]
- public void TestIssueGiteeI57Dto()
+ public void Issue142_Query()
{
- Dictionary[] sheets = [new() { ["ID"] = "0001", ["Name"] = "Jack" }];
- using var stream = new MemoryStream();
-
- var config = new CsvConfiguration { StreamWriterFunc = x => new StreamWriter(x, Encoding.Default, leaveOpen: true) };
- _csvExporter.Export(stream, sheets, configuration: config);
- stream.Seek(0, SeekOrigin.Begin);
+ var path = PathHelper.GetFile("xlsx/TestIssue142.xlsx");
+ var csvPath = PathHelper.GetFile("csv/TestIssue142.csv");
+
+ var rows = _openXmlImporter.Query(path).ToList();
+ Assert.Equal(0, rows[0].MyProperty1);
+ Assert.Throws(() => _openXmlImporter.Query(path).ToList());
- // convert stream to string
- using var reader = new StreamReader(stream);
- var text = reader.ReadToEnd();
+ var rowsXlsx = _openXmlImporter.Query(path).ToList();
+ Assert.Equal("CustomColumnName", rowsXlsx[0].MyProperty1);
+ Assert.Null(rowsXlsx[0].MyProperty7);
+ Assert.Equal("MyProperty2", rowsXlsx[0].MyProperty2);
+ Assert.Equal("MyProperty103", rowsXlsx[0].MyProperty3);
+ Assert.Equal("MyProperty100", rowsXlsx[0].MyProperty4);
+ Assert.Equal("MyProperty102", rowsXlsx[0].MyProperty5);
+ Assert.Equal("MyProperty6", rowsXlsx[0].MyProperty6);
- Assert.Equal("ID,Name\r\n0001,Jack\r\n", text);
+ var rowsCsv = _csvImporter.Query(csvPath).ToList();
+ Assert.Equal("CustomColumnName", rowsCsv[0].MyProperty1);
+ Assert.Null(rowsCsv[0].MyProperty7);
+ Assert.Equal("MyProperty2", rowsCsv[0].MyProperty2);
+ Assert.Equal("MyProperty103", rowsCsv[0].MyProperty3);
+ Assert.Equal("MyProperty100", rowsCsv[0].MyProperty4);
+ Assert.Equal("MyProperty102", rowsCsv[0].MyProperty5);
+ Assert.Equal("MyProperty6", rowsCsv[0].MyProperty6);
}
[Fact]
@@ -153,8 +178,6 @@ public void Issue217()
table.Columns.Add("CreditLimit").Caption = "Limit";
table.Rows.Add(1, "Jonathan", 23.44);
table.Rows.Add(2, "Bill", 56.87);
-
-
using var path = AutoDeletingPath.Create(ExcelType.Csv);
_csvExporter.Export(path.ToString(), table);
@@ -164,10 +187,7 @@ public void Issue217()
Assert.Equal("Limit", rows[0].C);
}
- ///
- /// Csv Query split comma not correct #237
- /// https://github.com/mini-software/MiniExcel/issues/237
- ///
+ /// Csv Query split comma not correct
[Fact]
public void Issue237()
{
@@ -186,9 +206,7 @@ public void Issue237()
Assert.Equal("1,2,3", rows[1].id);
}
- ///
- /// Support Custom Datetime format #241
- ///
+ /// Support Custom Datetime format
[Fact]
public void Issue241()
{
@@ -209,19 +227,8 @@ public void Issue241()
Assert.Equal(rows2[0].InDate, new DateTime(2021, 01, 04));
Assert.Equal(rows2[1].InDate, new DateTime(2020, 04, 05));
}
-
- private class Issue241Dto
- {
- public string? Name { get; set; }
- [MiniExcelFormat("MM dd, yyyy")]
- public DateTime InDate { get; set; }
- }
-
-
- ///
- /// Csv type mapping Query error "cannot be converted to xxx type" #243
- ///
+ // Csv type mapping Query error
[Fact]
public void Issue243()
{
@@ -243,181 +250,112 @@ public void Issue243()
Assert.Equal(new DateTime(2020, 05, 03), rows[1].InDate);
}
- private class Issue243Dto
- {
- public string? Name { get; set; }
- public int Age { get; set; }
- public DateTime InDate { get; set; }
- }
-
-
- ///
- /// https://github.com/mini-software/MiniExcel/issues/312
- ///
+ // CSV support export from datareader
[Fact]
- public void TestIssue312()
+ public void Issue251()
{
+ using var cn = Db.GetConnection();
+ using var reader = cn.ExecuteReader(@"select '""<>+-*//}{\\n' a,1234567890 b union all select 'Hello World',-1234567890");
using var path = AutoDeletingPath.Create(ExcelType.Csv);
- TestIssue312Dto[] value =
- [
- new() { Value = 12345.6789},
- new() { Value = null}
- ];
- _csvExporter.Export(path.ToString(), value);
+ _csvExporter.Export(path.ToString(), reader);
+ const string expected =
+ """"
+ a,b
+ """<>+-*//}{\\n",1234567890
+ "Hello World",-1234567890
- var rows = _csvImporter.Query(path.ToString()).ToList();
- Assert.Equal("12,345.68", rows[1].A);
- }
+ """";
- private class TestIssue312Dto
- {
- [MiniExcelFormat("0,0.00")]
- public double? Value { get; set; }
+ Assert.Equal(expected, File.ReadAllText(path.ToString()));
}
-
+
+ // Csv SaveAs by datareader with default encoding default shows incorrect characters
[Fact]
- public async Task TestIssue338()
+ public void Issue253()
{
- Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
{
- var path = PathHelper.GetFile("csv/TestIssue338.csv");
- var row = _csvImporter.QueryAsync(path).ToBlockingEnumerable().FirstOrDefault();
- Assert.Equal("���IJ�������", row!.A);
+ var value = new[] { new { col1 = "世界你好" } };
+ using var path = AutoDeletingPath.Create(ExcelType.Csv);
+ _csvExporter.Export(path.ToString(), value);
+ const string expected =
+ """
+ col1
+ 世界你好
+
+ """;
+ Assert.Equal(expected, File.ReadAllText(path.ToString()));
}
+
{
- var path = PathHelper.GetFile("csv/TestIssue338.csv");
+ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+ var value = new[] { new { col1 = "世界你好" } };
+ using var path = AutoDeletingPath.Create(ExcelType.Csv);
var config = new CsvConfiguration
{
- StreamReaderFunc = stream => new StreamReader(stream, Encoding.GetEncoding("gb2312"))
+ StreamWriterFunc = stream => new StreamWriter(stream, Encoding.GetEncoding("gb2312"))
};
- var row = _csvImporter.QueryAsync(path, configuration: config).ToBlockingEnumerable().FirstOrDefault();
- Assert.Equal("中文测试内容", row!.A);
+ _csvExporter.Export(path.ToString(), value, configuration: config);
+ const string expected =
+ """
+ col1
+ �������
+
+ """;
+ Assert.Equal(expected, File.ReadAllText(path.ToString()));
}
+
+ using var cn = Db.GetConnection();
+
{
- var path = PathHelper.GetFile("csv/TestIssue338.csv");
- var config = new CsvConfiguration
- {
- StreamReaderFunc = stream => new StreamReader(stream, Encoding.GetEncoding("gb2312"))
- };
- await using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
- {
- var row = _csvImporter.QueryAsync(stream, configuration: config).ToBlockingEnumerable().FirstOrDefault();
- Assert.Equal("中文测试内容", row!.A);
- }
+ var value = cn.ExecuteReader("select '世界你好' col1");
+ using var path = AutoDeletingPath.Create(ExcelType.Csv);
+ _csvExporter.Export(path.ToString(), value);
+ const string expected =
+ """
+ col1
+ 世界你好
+
+ """;
+ Assert.Equal(expected, File.ReadAllText(path.ToString()));
}
}
[Fact]
- public void TestIssueI4Wda9()
+ public void TestIssue261()
{
- using var path = AutoDeletingPath.Create(ExcelType.Csv);
- var value = new DataTable();
- {
- value.Columns.Add("\"name\"");
- value.Rows.Add("\"Jack\"");
- }
+ var csvPath = PathHelper.GetFile("csv/TestCsvToXlsx.csv");
+ using var path = AutoDeletingPath.Create();
- _csvExporter.Export(path.ToString(), value);
- Assert.Equal("\"\"\"name\"\"\"\r\n\"\"\"Jack\"\"\"\r\n", File.ReadAllText(path.ToString()));
- }
+ MiniExcelConverter.ConvertCsvToXlsx(csvPath, path.FilePath);
+ var rows = _openXmlImporter.Query(path.ToString()).ToList();
- [Fact]
- public void TestIssue316()
- {
- // CSV
- {
- using var file = AutoDeletingPath.Create(ExcelType.Csv);
- var path = file.ToString();
- var value = new[]
- {
- new { Amount = 123_456.789M, CreateTime = new DateTime(2018, 1, 31) }
- };
-
- var config = new CsvConfiguration
- {
- Culture = new CultureInfo("fr-FR"),
- };
- _csvExporter.Export(path, value, configuration: config);
-
- //Datetime error
- Assert.Throws(() =>
- {
- var conf = new CsvConfiguration
- {
- Culture = new CultureInfo("en-US")
- };
- _ = _csvImporter.Query(path, configuration: conf).ToList();
- });
-
- // dynamic
- var rows = _csvImporter.Query(path, true).ToList();
- Assert.Equal("123456,789", rows[0].Amount);
- Assert.Equal("31/01/2018 00:00:00", rows[0].CreateTime);
- }
-
- // type
- {
- using var file = AutoDeletingPath.Create(ExcelType.Csv);
- var path = file.ToString();
-
- var value = new[]
- {
- new{ Amount=123_456.789M, CreateTime=DateTime.Parse("2018-05-12", CultureInfo.InvariantCulture)}
- };
- {
- var config = new CsvConfiguration
- {
- Culture = new CultureInfo("fr-FR"),
- };
- _csvExporter.Export(path, value, configuration: config);
- }
-
- {
- var rows = _csvImporter.Query(path, true).ToList();
- Assert.Equal("123456,789", rows[0].Amount);
- Assert.Equal("12/05/2018 00:00:00", rows[0].CreateTime);
- }
-
- {
- var config = new CsvConfiguration
- {
- Culture = new CultureInfo("en-US"),
- };
- var rows = _csvImporter.Query(path, configuration: config).ToList();
-
- Assert.Equal("2018-12-05 00:00:00", rows[0].CreateTime.ToString("yyyy-MM-dd HH:mm:ss"));
- Assert.Equal(123456789m, rows[0].Amount);
- }
-
- {
- var config = new CsvConfiguration
- {
- Culture = new CultureInfo("fr-FR"),
- };
- var rows = _csvImporter.Query(path, configuration: config).ToList();
-
- Assert.Equal("2018-05-12 00:00:00", rows[0].CreateTime.ToString("yyyy-MM-dd HH:mm:ss"));
- Assert.Equal(123456.789m, rows[0].Amount);
- }
- }
+ Assert.Equal("Name", rows[0].A);
+ Assert.Equal("Jack", rows[1].A);
+ Assert.Equal("Neo", rows[2].A);
+ Assert.Null(rows[3].A);
+ Assert.Null(rows[4].A);
+ Assert.Equal("Age", rows[0].B);
+ Assert.Equal("34", rows[1].B);
+ Assert.Equal("26", rows[2].B);
+ Assert.Null(rows[3].B);
+ Assert.Null(rows[4].B);
}
- ///
- /// Column '' does not belong to table when csv convert to datatable #298
- /// https://github.com/mini-software/MiniExcel/issues/298
- ///
+ // Csv support for QueryAsDataTable
[Fact]
- public void TestIssue298()
+ public void TestIssue279()
{
- var path = PathHelper.GetFile("/csv/TestIssue298.csv");
+ var path = PathHelper.GetFile("/csv/TestHeader.csv");
#pragma warning disable CS0618 // Type or member is obsolete
- var dt = _csvImporter.QueryAsDataTable(path);
+ using var dt = _csvImporter.QueryAsDataTable(path);
#pragma warning restore CS0618
- Assert.Equal(["ID", "Name", "Age"], dt.Columns.Cast().Select(x => x.ColumnName));
+ Assert.Equal("A1", dt.Rows[0]["Column1"]);
+ Assert.Equal("A2", dt.Rows[1]["Column1"]);
+ Assert.Equal("B1", dt.Rows[0]["Column2"]);
+ Assert.Equal("B2", dt.Rows[1]["Column2"]);
}
- ///
- /// [According to the XLSX to CSV example, there will be data loss if there is no header. · Issue #292 · mini-software/MiniExcel](https://github.com/mini-software/MiniExcel/issues/292)
- ///
+
+ // According to the XLSX to CSV example, there will be data loss if there is no header.
[Fact]
public void TestIssue292()
{
@@ -455,9 +393,7 @@ public void TestIssue292()
}
}
- ///
- /// [Csv Query then SaveAs will throw "Stream was not readable." exception · Issue #293 · mini-software/MiniExcel](https://github.com/mini-software/MiniExcel/issues/293)
- ///
+ // Csv Query then SaveAs will throw exception "Stream was not readable."
[Fact]
public void TestIssue293()
{
@@ -468,353 +404,166 @@ public void TestIssue293()
_openXmlExporter.Export(tempPath.ToString(), value, printHeader: false);
}
- ///
- /// Csv not support QueryAsDataTable #279 https://github.com/mini-software/MiniExcel/issues/279
- ///
+ // Column '' does not belong to table when csv is converted to datatable
[Fact]
- public void TestIssue279()
+ public void TestIssue298()
{
- var path = PathHelper.GetFile("/csv/TestHeader.csv");
+ var path = PathHelper.GetFile("/csv/TestIssue298.csv");
#pragma warning disable CS0618 // Type or member is obsolete
using var dt = _csvImporter.QueryAsDataTable(path);
#pragma warning restore CS0618
- Assert.Equal("A1", dt.Rows[0]["Column1"]);
- Assert.Equal("A2", dt.Rows[1]["Column1"]);
- Assert.Equal("B1", dt.Rows[0]["Column2"]);
- Assert.Equal("B2", dt.Rows[1]["Column2"]);
- }
-
- ///
- /// [Convert csv to xlsx · Issue #261 · mini-software/MiniExcel](https://github.com/mini-software/MiniExcel/issues/261)
- ///
- [Fact]
- public void TestIssue261()
- {
- var csvPath = PathHelper.GetFile("csv/TestCsvToXlsx.csv");
- using var path = AutoDeletingPath.Create();
-
- MiniExcelConverter.ConvertCsvToXlsx(csvPath, path.FilePath);
- var rows = _openXmlImporter.Query(path.ToString()).ToList();
-
- Assert.Equal("Name", rows[0].A);
- Assert.Equal("Jack", rows[1].A);
- Assert.Equal("Neo", rows[2].A);
- Assert.Null(rows[3].A);
- Assert.Null(rows[4].A);
- Assert.Equal("Age", rows[0].B);
- Assert.Equal("34", rows[1].B);
- Assert.Equal("26", rows[2].B);
- Assert.Null(rows[3].B);
- Assert.Null(rows[4].B);
- }
-
- ///
- /// Csv SaveAs by datareader with encoding default show messy code #253
- ///
- [Fact]
- public void Issue253()
- {
- {
- var value = new[] { new { col1 = "世界你好" } };
- using var path = AutoDeletingPath.Create(ExcelType.Csv);
- _csvExporter.Export(path.ToString(), value);
- const string expected =
- """
- col1
- 世界你好
-
- """;
- Assert.Equal(expected, File.ReadAllText(path.ToString()));
- }
-
- {
- Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
- var value = new[] { new { col1 = "世界你好" } };
- using var path = AutoDeletingPath.Create(ExcelType.Csv);
- var config = new CsvConfiguration
- {
- StreamWriterFunc = stream => new StreamWriter(stream, Encoding.GetEncoding("gb2312"))
- };
- _csvExporter.Export(path.ToString(), value, configuration: config);
- const string expected =
- """
- col1
- �������
-
- """;
- Assert.Equal(expected, File.ReadAllText(path.ToString()));
- }
-
- using var cn = Db.GetConnection();
-
- {
- var value = cn.ExecuteReader("select '世界你好' col1");
- using var path = AutoDeletingPath.Create(ExcelType.Csv);
- _csvExporter.Export(path.ToString(), value);
- const string expected =
- """
- col1
- 世界你好
-
- """;
- Assert.Equal(expected, File.ReadAllText(path.ToString()));
- }
+ Assert.Equal(["ID", "Name", "Age"], dt.Columns.Cast().Select(x => x.ColumnName));
}
- ///
- /// [CSV SaveAs support datareader · Issue #251 · mini-software/MiniExcel](https://github.com/mini-software/MiniExcel/issues/251)
- ///
[Fact]
- public void Issue251()
+ public void TestIssue305()
{
- using var cn = Db.GetConnection();
- using var reader = cn.ExecuteReader(@"select '""<>+-*//}{\\n' a,1234567890 b union all select 'Hello World',-1234567890");
using var path = AutoDeletingPath.Create(ExcelType.Csv);
- _csvExporter.Export(path.ToString(), reader);
- const string expected =
- """"
- a,b
- """<>+-*//}{\\n",1234567890
- "Hello World",-1234567890
-
- """";
-
- Assert.Equal(expected, File.ReadAllText(path.ToString()));
- }
-
- public class Issue89Model
- {
- public WorkState State { get; set; }
-
- public enum WorkState
+ var value = new[]
{
- OnDuty,
- Leave,
- Fired
- }
+ new TestIssue305Dto{ Dt = DateTimeOffset.Parse("2022-01-22")},
+ new TestIssue305Dto{ Dt = null}
+ };
+ _csvExporter.Export(path.ToString(), value);
+
+ var rows = _csvImporter.Query(path.ToString()).ToList();
+ Assert.Equal("2022-01-22", rows[1].A);
}
- ///
- /// Support Enum Mapping
- /// https://github.com/mini-software/MiniExcel/issues/89
- ///
[Fact]
- public void Issue89()
+ public void TestIssue312()
{
- //csv
- const string text =
- """
- State
- OnDuty
- Fired
- Leave
- """;
-
- using var stream = new MemoryStream();
- using var writer = new StreamWriter(stream);
-
- writer.Write(text);
- writer.Flush();
- stream.Position = 0;
- var rows = _csvImporter.Query(stream, hasHeaderRow: true).ToList();
-
- Assert.Equal(nameof(Issue89Model.WorkState.OnDuty), rows[0].State);
- Assert.Equal(nameof(Issue89Model.WorkState.Fired), rows[1].State);
- Assert.Equal(nameof(Issue89Model.WorkState.Leave), rows[2].State);
-
using var path = AutoDeletingPath.Create(ExcelType.Csv);
- _csvExporter.Export(path.ToString(), rows);
- var rows2 = _csvImporter.Query(path.ToString()).ToList();
-
- Assert.Equal(Issue89Model.WorkState.OnDuty, rows2[0].State);
- Assert.Equal(Issue89Model.WorkState.Fired, rows2[1].State);
- Assert.Equal(Issue89Model.WorkState.Leave, rows2[2].State);
- }
-
- private class Issue142VoDuplicateColumnName
- {
- [MiniExcelColumnIndex("A")]
- public int MyProperty1 { get; set; }
- [MiniExcelColumnIndex("A")]
- public int MyProperty2 { get; set; }
-
- public int MyProperty3 { get; set; }
- [MiniExcelColumnIndex("B")]
- public int MyProperty4 { get; set; }
- }
+ TestIssue312Dto[] value =
+ [
+ new() { Value = 12345.6789},
+ new() { Value = null}
+ ];
+ _csvExporter.Export(path.ToString(), value);
- private class Issue142Model
- {
- [MiniExcelColumnName("CustomColumnName")]
- public string? MyProperty1 { get; set; } //index = 1
- [MiniExcelIgnore]
- public string? MyProperty7 { get; set; } //index = null
- public string? MyProperty2 { get; set; } //index = 3
- [MiniExcelColumnIndex(6)]
- public string? MyProperty3 { get; set; } //index = 6
- [MiniExcelColumnIndex("A")] // equal column index 0
- public string? MyProperty4 { get; set; }
- [MiniExcelColumnIndex(2)]
- public string? MyProperty5 { get; set; } //index = 2
- public string? MyProperty6 { get; set; } //index = 4
+ var rows = _csvImporter.Query(path.ToString()).ToList();
+ Assert.Equal("12,345.68", rows[1].A);
}
[Fact]
- public void Issue142()
+ public void TestIssue316()
{
{
- using var file = AutoDeletingPath.Create();
+ using var file = AutoDeletingPath.Create(ExcelType.Csv);
var path = file.ToString();
- Issue142Model[] values =
- [
- new()
- {
- MyProperty1 = "MyProperty1", MyProperty2 = "MyProperty2", MyProperty3 = "MyProperty3",
- MyProperty4 = "MyProperty4", MyProperty5 = "MyProperty5", MyProperty6 = "MyProperty6",
- MyProperty7 = "MyProperty7"
- }
- ];
- var rowsWritten = _openXmlExporter.Export(path, values);
- Assert.Single(rowsWritten);
- Assert.Equal(1, rowsWritten[0]);
-
+ var value = new[]
{
- var rows = _openXmlImporter.Query(path).ToList();
-
- Assert.Equal("MyProperty4", rows[0].A);
- Assert.Equal("CustomColumnName", rows[0].B);
- Assert.Equal("MyProperty5", rows[0].C);
- Assert.Equal("MyProperty2", rows[0].D);
- Assert.Equal("MyProperty6", rows[0].E);
- Assert.Null(rows[0].F);
- Assert.Equal("MyProperty3", rows[0].G);
+ new { Amount = 123_456.789M, CreateTime = new DateTime(2018, 1, 31) }
+ };
- Assert.Equal("MyProperty4", rows[0].A);
- Assert.Equal("CustomColumnName", rows[0].B);
- Assert.Equal("MyProperty5", rows[0].C);
- Assert.Equal("MyProperty2", rows[0].D);
- Assert.Equal("MyProperty6", rows[0].E);
- Assert.Null(rows[0].F);
- Assert.Equal("MyProperty3", rows[0].G);
- }
+ var config = new CsvConfiguration
+ {
+ Culture = new CultureInfo("fr-FR"),
+ };
+ _csvExporter.Export(path, value, configuration: config);
+ //Datetime error
+ Assert.Throws(() =>
{
- var rows = _openXmlImporter.Query(path).ToList();
+ var conf = new CsvConfiguration
+ {
+ Culture = new CultureInfo("en-US")
+ };
+ _ = _csvImporter.Query(path, configuration: conf).ToList();
+ });
- Assert.Equal("MyProperty4", rows[0].MyProperty4);
- Assert.Equal("MyProperty1", rows[0].MyProperty1);
- Assert.Equal("MyProperty5", rows[0].MyProperty5);
- Assert.Equal("MyProperty2", rows[0].MyProperty2);
- Assert.Equal("MyProperty6", rows[0].MyProperty6);
- Assert.Null(rows[0].MyProperty7);
- Assert.Equal("MyProperty3", rows[0].MyProperty3);
- }
+ // dynamic
+ var rows = _csvImporter.Query(path, true).ToList();
+ Assert.Equal("123456,789", rows[0].Amount);
+ Assert.Equal("31/01/2018 00:00:00", rows[0].CreateTime);
}
+ // type
{
using var file = AutoDeletingPath.Create(ExcelType.Csv);
var path = file.ToString();
- Issue142Model[] values =
- [
- new()
+
+ var value = new[]
+ {
+ new{ Amount=123_456.789M, CreateTime=DateTime.Parse("2018-05-12", CultureInfo.InvariantCulture)}
+ };
+ {
+ var config = new CsvConfiguration
{
- MyProperty1 = "MyProperty1", MyProperty2 = "MyProperty2", MyProperty3 = "MyProperty3",
- MyProperty4 = "MyProperty4", MyProperty5 = "MyProperty5", MyProperty6 = "MyProperty6",
- MyProperty7 = "MyProperty7"
- }
- ];
- var rowsWritten = _csvExporter.Export(path, values);
- Assert.Equal(1, rowsWritten);
+ Culture = new CultureInfo("fr-FR"),
+ };
+ _csvExporter.Export(path, value, configuration: config);
+ }
- const string expected =
- """
- MyProperty4,CustomColumnName,MyProperty5,MyProperty2,MyProperty6,,MyProperty3
- MyProperty4,MyProperty1,MyProperty5,MyProperty2,MyProperty6,,MyProperty3
+ {
+ var rows = _csvImporter.Query(path, true).ToList();
+ Assert.Equal("123456,789", rows[0].Amount);
+ Assert.Equal("12/05/2018 00:00:00", rows[0].CreateTime);
+ }
- """;
+ {
+ var config = new CsvConfiguration
+ {
+ Culture = new CultureInfo("en-US"),
+ };
+ var rows = _csvImporter.Query(path, configuration: config).ToList();
- Assert.Equal(expected, File.ReadAllText(path));
+ Assert.Equal("2018-12-05 00:00:00", rows[0].CreateTime.ToString("yyyy-MM-dd HH:mm:ss"));
+ Assert.Equal(123456789m, rows[0].Amount);
+ }
{
- var rows = _csvImporter.Query(path).ToList();
+ var config = new CsvConfiguration
+ {
+ Culture = new CultureInfo("fr-FR"),
+ };
+ var rows = _csvImporter.Query(path, configuration: config).ToList();
- Assert.Equal("MyProperty4", rows[0].MyProperty4);
- Assert.Equal("MyProperty1", rows[0].MyProperty1);
- Assert.Equal("MyProperty5", rows[0].MyProperty5);
- Assert.Equal("MyProperty2", rows[0].MyProperty2);
- Assert.Equal("MyProperty6", rows[0].MyProperty6);
- Assert.Null(rows[0].MyProperty7);
- Assert.Equal("MyProperty3", rows[0].MyProperty3);
+ Assert.Equal("2018-05-12 00:00:00", rows[0].CreateTime.ToString("yyyy-MM-dd HH:mm:ss"));
+ Assert.Equal(123456.789m, rows[0].Amount);
}
}
-
- {
- using var path = AutoDeletingPath.Create(ExcelType.Csv);
- Issue142VoDuplicateColumnName[] input =
- [
- new() { MyProperty1 = 0, MyProperty2 = 0, MyProperty3 = 0, MyProperty4 = 0 }
- ];
- Assert.Throws(() => _csvExporter.Export(path.ToString(), input));
- }
}
-
+
[Fact]
- public void Issue142_Query()
- {
- var path = PathHelper.GetFile("xlsx/TestIssue142.xlsx");
- var csvPath = PathHelper.GetFile("csv/TestIssue142.csv");
-
- var rows = _openXmlImporter.Query(path).ToList();
- Assert.Equal(0, rows[0].MyProperty1);
- Assert.Throws(() => _openXmlImporter.Query(path).ToList());
-
- var rowsXlsx = _openXmlImporter.Query(path).ToList();
- Assert.Equal("CustomColumnName", rowsXlsx[0].MyProperty1);
- Assert.Null(rowsXlsx[0].MyProperty7);
- Assert.Equal("MyProperty2", rowsXlsx[0].MyProperty2);
- Assert.Equal("MyProperty103", rowsXlsx[0].MyProperty3);
- Assert.Equal("MyProperty100", rowsXlsx[0].MyProperty4);
- Assert.Equal("MyProperty102", rowsXlsx[0].MyProperty5);
- Assert.Equal("MyProperty6", rowsXlsx[0].MyProperty6);
-
- var rowsCsv = _csvImporter.Query(csvPath).ToList();
- Assert.Equal("CustomColumnName", rowsCsv[0].MyProperty1);
- Assert.Null(rowsCsv[0].MyProperty7);
- Assert.Equal("MyProperty2", rowsCsv[0].MyProperty2);
- Assert.Equal("MyProperty103", rowsCsv[0].MyProperty3);
- Assert.Equal("MyProperty100", rowsCsv[0].MyProperty4);
- Assert.Equal("MyProperty102", rowsCsv[0].MyProperty5);
- Assert.Equal("MyProperty6", rowsCsv[0].MyProperty6);
- }
-
- private class Issue142VoOverIndex
- {
- [MiniExcelColumnIndex("Z")]
- public int MyProperty1 { get; set; }
- }
-
- private class Issue142VoExcelColumnNameNotFound
- {
- [MiniExcelColumnIndex("B")]
- public int MyProperty1 { get; set; }
- }
-
- private class Issue507V01
+ public async Task TestIssue338()
{
- public string? A { get; set; }
- public DateTime B { get; set; }
- public string? C { get; set; }
- public int D { get; set; }
+ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+ {
+ var path = PathHelper.GetFile("csv/TestIssue338.csv");
+ var row = _csvImporter.QueryAsync(path).ToBlockingEnumerable().FirstOrDefault();
+ Assert.Equal("���IJ�������", row!.A);
+ }
+ {
+ var path = PathHelper.GetFile("csv/TestIssue338.csv");
+ var config = new CsvConfiguration
+ {
+ StreamReaderFunc = stream => new StreamReader(stream, Encoding.GetEncoding("gb2312"))
+ };
+ var row = _csvImporter.QueryAsync(path, configuration: config).ToBlockingEnumerable().FirstOrDefault();
+ Assert.Equal("中文测试内容", row!.A);
+ }
+ {
+ var path = PathHelper.GetFile("csv/TestIssue338.csv");
+ var config = new CsvConfiguration
+ {
+ StreamReaderFunc = stream => new StreamReader(stream, Encoding.GetEncoding("gb2312"))
+ };
+ await using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
+ {
+ var row = _csvImporter.QueryAsync(stream, configuration: config).ToBlockingEnumerable().FirstOrDefault();
+ Assert.Equal("中文测试内容", row!.A);
+ }
+ }
}
-
[Fact]
public void Issue507_1()
{
//Problem with multi-line when using Query func
//https://github.com/mini-software/MiniExcel/issues/507
- var path = Path.Combine(Path.GetTempPath(), string.Concat(nameof(IssueTests), "_", nameof(Issue507_1), ".csv"));
+ var path = Path.Combine(Path.GetTempPath(), string.Concat(nameof(GithubIssuesTests), "_", nameof(Issue507_1), ".csv"));
var values = new Issue507V01[]
{
new() { A = "Github", B = DateTime.Parse("2021-01-01"), C = "abcd", D = 123 },
@@ -826,7 +575,7 @@ public void Issue507_1()
var config = new CsvConfiguration
{
//AlwaysQuote = true,
- ReadLineBreaksWithinQuotes = true,
+ ReadLineBreaksWithinQuotes = true
};
// create
@@ -855,19 +604,10 @@ public void Issue507_1()
File.Delete(path);
}
- private class Issue507V02
- {
- public DateTime B { get; set; }
- public int D { get; set; }
- }
-
[Fact]
public void Issue507_2()
{
- //Problem with multi-line when using Query func
- //https://github.com/mini-software/MiniExcel/issues/507
-
- var path = Path.Combine(Path.GetTempPath(), string.Concat(nameof(IssueTests), "_", nameof(Issue507_2), ".csv"));
+ var path = Path.Combine(Path.GetTempPath(), string.Concat(nameof(GithubIssuesTests), "_", nameof(Issue507_2), ".csv"));
var values = new Issue507V02[]
{
new() { B = DateTime.Parse("2021-01-01"), D = 123 },
@@ -895,12 +635,10 @@ public void Issue507_2()
File.Delete(path);
}
+ //Problem with multi-line when using Query func
[Fact]
public void Issue507_3_MismatchedQuoteCsv()
{
- //Problem with multi-line when using Query func
- //https://github.com/mini-software/MiniExcel/issues/507
-
var config = new CsvConfiguration
{
//AlwaysQuote = true,
@@ -914,12 +652,6 @@ public void Issue507_3_MismatchedQuoteCsv()
var getRowsInfo = _csvImporter.Query(stream, configuration: config).ToArray();
Assert.Equal(2, getRowsInfo.Length);
}
-
- class NameAgeTuple
- {
- public string? Name { get; set; }
- public int Age { get; set; }
- }
[Fact]
public void Issue914()
@@ -937,10 +669,10 @@ public void Issue914()
"""u8;
using var ms = new MemoryStream([..csv]);
- var result = _csvImporter.Query(ms).ToList();
+ var result = _csvImporter.Query(ms, hasHeaderRow: true).ToList();
Assert.Equal(3, result.Count);
Assert.Equal("Sam", result[1].Name);
- Assert.Equal(44, result[2].Age);
+ Assert.Equal("44", result[2].Age);
}
}
diff --git a/tests/MiniExcel.Csv.Tests/Issues/Models.cs b/tests/MiniExcel.Csv.Tests/Issues/Models.cs
new file mode 100644
index 00000000..3cfc1ea4
--- /dev/null
+++ b/tests/MiniExcel.Csv.Tests/Issues/Models.cs
@@ -0,0 +1,100 @@
+namespace MiniExcelLib.Csv.Tests.Issues;
+
+internal class Issue89Dto
+{
+ public WorkState State { get; set; }
+
+ public enum WorkState
+ {
+ OnDuty,
+ Leave,
+ Fired
+ }
+}
+
+internal class Issue142Dto
+{
+ [MiniExcelColumnName("CustomColumnName")]
+ public string? MyProperty1 { get; set; } //index = 1
+ [MiniExcelIgnore]
+ public string? MyProperty7 { get; set; } //index = null
+ public string? MyProperty2 { get; set; } //index = 3
+ [MiniExcelColumnIndex(6)]
+ public string? MyProperty3 { get; set; } //index = 6
+ [MiniExcelColumnIndex("A")] // equal column index 0
+ public string? MyProperty4 { get; set; }
+ [MiniExcelColumnIndex(2)]
+ public string? MyProperty5 { get; set; } //index = 2
+ public string? MyProperty6 { get; set; } //index = 4
+}
+
+internal class Issue142DuplicateColumnNameDto
+{
+ [MiniExcelColumnIndex("A")]
+ public int MyProperty1 { get; set; }
+ [MiniExcelColumnIndex("A")]
+ public int MyProperty2 { get; set; }
+
+ public int MyProperty3 { get; set; }
+ [MiniExcelColumnIndex("B")]
+ public int MyProperty4 { get; set; }
+}
+
+internal class Issue142OverIndexDto
+{
+ [MiniExcelColumnIndex("Z")]
+ public int MyProperty1 { get; set; }
+}
+
+internal class Issue142ExcelColumnNameNotFoundDto
+{
+ [MiniExcelColumnIndex("B")]
+ public int MyProperty1 { get; set; }
+}
+
+internal class Issue241Dto
+{
+ public string? Name { get; set; }
+
+ [MiniExcelFormat("MM dd, yyyy")]
+ public DateTime InDate { get; set; }
+}
+
+internal class Issue243Dto
+{
+ public string? Name { get; set; }
+ public int Age { get; set; }
+ public DateTime InDate { get; set; }
+}
+
+internal class TestIssue305Dto
+{
+ [MiniExcelFormat("yyyy-MM-dd")]
+ public DateTimeOffset? Dt { get; set; }
+}
+
+internal class TestIssue312Dto
+{
+ [MiniExcelFormat("0,0.00")]
+ public double? Value { get; set; }
+}
+
+internal class TestIssue316Dto
+{
+ public decimal Amount { get; set; }
+ public DateTime CreateTime { get; set; }
+}
+
+internal class Issue507V01
+{
+ public string? A { get; set; }
+ public DateTime B { get; set; }
+ public string? C { get; set; }
+ public int D { get; set; }
+}
+
+internal class Issue507V02
+{
+ public DateTime B { get; set; }
+ public int D { get; set; }
+}
diff --git a/tests/MiniExcel.Csv.Tests/MiniExcelCsvAsyncTests.cs b/tests/MiniExcel.Csv.Tests/Main/MiniExcelCsvAsyncTests.cs
similarity index 97%
rename from tests/MiniExcel.Csv.Tests/MiniExcelCsvAsyncTests.cs
rename to tests/MiniExcel.Csv.Tests/Main/MiniExcelCsvAsyncTests.cs
index 0c5b7b57..e4d90c2d 100644
--- a/tests/MiniExcel.Csv.Tests/MiniExcelCsvAsyncTests.cs
+++ b/tests/MiniExcel.Csv.Tests/Main/MiniExcelCsvAsyncTests.cs
@@ -1,4 +1,4 @@
-namespace MiniExcelLib.Csv.Tests;
+namespace MiniExcelLib.Csv.Tests.Main;
public class MiniExcelCsvAsyncTests
{
diff --git a/tests/MiniExcel.Csv.Tests/MiniExcelCsvTests.cs b/tests/MiniExcel.Csv.Tests/Main/MiniExcelCsvTests.cs
similarity index 96%
rename from tests/MiniExcel.Csv.Tests/MiniExcelCsvTests.cs
rename to tests/MiniExcel.Csv.Tests/Main/MiniExcelCsvTests.cs
index c9467d58..1d017a98 100644
--- a/tests/MiniExcel.Csv.Tests/MiniExcelCsvTests.cs
+++ b/tests/MiniExcel.Csv.Tests/Main/MiniExcelCsvTests.cs
@@ -1,4 +1,4 @@
-namespace MiniExcelLib.Csv.Tests;
+namespace MiniExcelLib.Csv.Tests.Main;
public class MiniExcelCsvTests
{
diff --git a/tests/MiniExcel.OpenXml.Tests/MiniExcelAutoAdjustWidthTests.cs b/tests/MiniExcel.OpenXml.Tests/Configuration/MiniExcelAutoAdjustWidthTests.cs
similarity index 80%
rename from tests/MiniExcel.OpenXml.Tests/MiniExcelAutoAdjustWidthTests.cs
rename to tests/MiniExcel.OpenXml.Tests/Configuration/MiniExcelAutoAdjustWidthTests.cs
index 7c201925..12449313 100644
--- a/tests/MiniExcel.OpenXml.Tests/MiniExcelAutoAdjustWidthTests.cs
+++ b/tests/MiniExcel.OpenXml.Tests/Configuration/MiniExcelAutoAdjustWidthTests.cs
@@ -3,7 +3,7 @@
using MiniExcelLib.OpenXml.Models;
using MiniExcelLib.Tests.Common.Utils;
-namespace MiniExcelLib.OpenXml.Tests;
+namespace MiniExcelLib.OpenXml.Tests.Configuration;
public class MiniExcelAutoAdjustWidthTests
{
@@ -17,7 +17,7 @@ public async Task AutoAdjustWidthThrowsExceptionWithoutFastMode_Async()
await Assert.ThrowsAsync(() => _excelExporter.ExportAsync(path, AutoAdjustTestParameters.GetDictionaryTestData(), configuration: new OpenXmlConfiguration
{
- EnableAutoWidth = true,
+ EnableAutoWidth = true
}));
}
@@ -164,39 +164,4 @@ private static void AssertExpectedWidth(string path, OpenXmlConfiguration config
Assert.Equal(ExcelColumnWidth.GetWidthFromTextLength(expectedWidth), Math.Round(column.Width!.Value, 8));
}
}
-
- private static class AutoAdjustTestParameters
- {
- internal const int Column1MaLen = 32;
- internal const int Column2MaxLen = 16;
- private const int Column3MaxLen = 2;
- private const int Column4MaxLen = 100;
-
- public static List GetTestData() => [
- [
- new('1', Column1MaLen),
- new('2', Column2MaxLen / 2),
- new('3', Column3MaxLen / 2),
- new('4', Column4MaxLen)
- ],
- [
- new('1', Column1MaLen / 2),
- new('2', Column2MaxLen),
- new('3', Column3MaxLen),
- new('4', Column4MaxLen)
- ] ];
-
- public static List> GetDictionaryTestData() => GetTestData()
- .Select(row => row
- .Select((value, i) => (value, i))
- .ToDictionary(x => $"Column{x.i}", object (x) => x.value))
- .ToList();
-
- public static OpenXmlConfiguration GetConfiguration() => new()
- {
- EnableAutoWidth = true,
- FastMode = true,
- MaxWidth = 50
- };
- }
}
diff --git a/tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlConfigurationTest.cs b/tests/MiniExcel.OpenXml.Tests/Configuration/MiniExcelOpenXmlConfigurationTests.cs
similarity index 81%
rename from tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlConfigurationTest.cs
rename to tests/MiniExcel.OpenXml.Tests/Configuration/MiniExcelOpenXmlConfigurationTests.cs
index ca540042..321986a0 100644
--- a/tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlConfigurationTest.cs
+++ b/tests/MiniExcel.OpenXml.Tests/Configuration/MiniExcelOpenXmlConfigurationTests.cs
@@ -1,7 +1,6 @@
-using MiniExcelLib.Core.Helpers;
using MiniExcelLib.Tests.Common.Utils;
-namespace MiniExcelLib.OpenXml.Tests;
+namespace MiniExcelLib.OpenXml.Tests.Configuration;
public class MiniExcelOpenXmlConfigurationTest
{
@@ -26,12 +25,4 @@ public async Task DisableWriteFilePathTest()
var rows = await _excelImporter.QueryAsync(path).ToListAsync();
Assert.True(rows.All(x => x.Img is null or []));
}
-
- private class ImgExportTestDto
- {
- public string? Name { get; set; }
-
- [MiniExcelColumn(Name = "图片", Width = 100)]
- public byte[]? Img { get; set; }
- }
}
diff --git a/tests/MiniExcel.OpenXml.Tests/Configuration/Models.cs b/tests/MiniExcel.OpenXml.Tests/Configuration/Models.cs
new file mode 100644
index 00000000..7e032ae2
--- /dev/null
+++ b/tests/MiniExcel.OpenXml.Tests/Configuration/Models.cs
@@ -0,0 +1,44 @@
+namespace MiniExcelLib.OpenXml.Tests.Configuration;
+
+internal static class AutoAdjustTestParameters
+{
+ internal const int Column1MaLen = 32;
+ internal const int Column2MaxLen = 16;
+ private const int Column3MaxLen = 2;
+ private const int Column4MaxLen = 100;
+
+ public static List GetTestData() => [
+ [
+ new('1', Column1MaLen),
+ new('2', Column2MaxLen / 2),
+ new('3', Column3MaxLen / 2),
+ new('4', Column4MaxLen)
+ ],
+ [
+ new('1', Column1MaLen / 2),
+ new('2', Column2MaxLen),
+ new('3', Column3MaxLen),
+ new('4', Column4MaxLen)
+ ] ];
+
+ public static List> GetDictionaryTestData() => GetTestData()
+ .Select(row => row
+ .Select((value, i) => (value, i))
+ .ToDictionary(x => $"Column{x.i}", object (x) => x.value))
+ .ToList();
+
+ public static OpenXmlConfiguration GetConfiguration() => new()
+ {
+ EnableAutoWidth = true,
+ FastMode = true,
+ MaxWidth = 50
+ };
+}
+
+internal class ImgExportTestDto
+{
+ public string? Name { get; set; }
+
+ [MiniExcelColumn(Name = "图片", Width = 100)]
+ public byte[]? Img { get; set; }
+}
diff --git a/tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGiteeIssuesAsyncTests.cs b/tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGiteeIssuesAsyncTests.cs
new file mode 100644
index 00000000..40aeb229
--- /dev/null
+++ b/tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGiteeIssuesAsyncTests.cs
@@ -0,0 +1,29 @@
+using MiniExcelLib.Tests.Common.Utils;
+
+namespace MiniExcelLib.OpenXml.Tests.Issues;
+
+public class MiniExcelGiteeIssuesAsyncTests
+{
+ private readonly OpenXmlImporter _excelImporter = MiniExcel.Importers.GetOpenXmlImporter();
+ private readonly OpenXmlExporter _excelExporter = MiniExcel.Exporters.GetOpenXmlExporter();
+
+ // https://gitee.com/dotnetchina/MiniExcel/issues/I3OSKV
+ // When exporting, the pure numeric string will be forcibly converted to a numeric type, resulting in the loss of the end data
+ [Fact]
+ public async Task IssueI3OSKV()
+ {
+ using var path1 = AutoDeletingPath.Create();
+ var value1 = new[] { new { Test = "12345678901234567890" } };
+ await _excelExporter.ExportAsync(path1.ToString(), value1);
+
+ var result1 = await _excelImporter.QueryAsync(path1.ToString(), true).FirstAsync();
+ Assert.Equal("12345678901234567890", result1.Test);
+
+ using var path2 = AutoDeletingPath.Create();
+ var value2 = new[] { new { Test = 123456.789 } };
+ await _excelExporter.ExportAsync(path2.ToString(), value2);
+
+ var result2 = await _excelImporter.QueryAsync(path2.ToString(), true).FirstAsync();
+ Assert.Equal(123456.789, result2.Test);
+ }
+}
diff --git a/tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGiteeIssuesTests.cs b/tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGiteeIssuesTests.cs
new file mode 100644
index 00000000..fdbd8dcb
--- /dev/null
+++ b/tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGiteeIssuesTests.cs
@@ -0,0 +1,329 @@
+using MiniExcelLib.OpenXml.Tests.Utils;
+using MiniExcelLib.Tests.Common.Utils;
+
+namespace MiniExcelLib.OpenXml.Tests.Issues;
+
+public class MiniExcelGiteeIssuesTests
+{
+ private readonly OpenXmlImporter _excelImporter = MiniExcel.Importers.GetOpenXmlImporter();
+ private readonly OpenXmlExporter _excelExporter = MiniExcel.Exporters.GetOpenXmlExporter();
+ private readonly OpenXmlTemplater _excelTemplater = MiniExcel.Templaters.GetOpenXmlTemplater();
+
+ [Fact]
+ public void TestIssueI4ZYUU()
+ {
+ using var path = AutoDeletingPath.Create();
+
+ var dt = new DateTime(2022, 10, 15);
+ TestIssueI4ZYUUDto[] value = [new() { MyProperty = "1", MyProperty2 = dt }];
+ _excelExporter.Export(path.ToString(), value);
+
+ using var workbook = new ClosedXML.Excel.XLWorkbook(path.ToString());
+ var ws = workbook.Worksheet(1);
+
+ Assert.Equal(dt, ws.Cell(2, "B").Value.GetDateTime());
+ Assert.Equal("2022-10", ws.Cell(2, "B").GetFormattedString());
+ Assert.True(ws.Column("A").Width > 0);
+ Assert.True(ws.Column("B").Width > 0);
+ }
+
+ [Fact]
+ public void TestIssueI4YCLQ_2()
+ {
+ var path = PathHelper.GetFile("xlsx/TestIssueI4YCLQ_2.xlsx");
+ var rows = _excelImporter.Query(path, startCell: "B2").ToList();
+
+ Assert.Null(rows[0].站点编码);
+ Assert.Equal("N1", rows[0].站址名称);
+ Assert.Equal("a", rows[0].值1);
+ Assert.Equal("b", rows[0].值2);
+ Assert.Equal("c", rows[0].值3);
+ Assert.Equal("A1", rows[0].资源ID);
+ Assert.Equal("A", rows[0].值4);
+ Assert.Equal("B", rows[0].值5);
+ Assert.Equal("C", rows[0].值6);
+ Assert.Null(rows[0].值7);
+ Assert.Null(rows[0].值8);
+ }
+
+ [Fact]
+ public void TestIssueI4WM67()
+ {
+ using var path = AutoDeletingPath.Create();
+ var templatePath = PathHelper.GetFile("xlsx/TestIssueI4WM67.xlsx");
+ var value = new Dictionary
+ {
+ ["users"] = Array.Empty()
+ };
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
+ var rows = _excelImporter.Query(path.ToString()).ToList();
+ Assert.Single(rows);
+ }
+
+ [Fact]
+ public void TestIssueI4WXFB()
+ {
+ {
+ using var path = AutoDeletingPath.Create();
+ var templatePath = PathHelper.GetFile("xlsx/TestIssueI4WXFB.xlsx");
+ var value = new Dictionary
+ {
+ ["Name"] = "Jack",
+ ["Amount"] = 1000,
+ ["Department"] = "HR"
+ };
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
+ }
+
+ {
+ var config = new OpenXmlConfiguration
+ {
+ IgnoreTemplateParameterMissing = false
+ };
+ using var path = AutoDeletingPath.Create();
+ var templatePath = PathHelper.GetFile("xlsx/TestIssueI4WXFB.xlsx");
+ var value = new Dictionary
+ {
+ ["Name"] = "Jack",
+ ["Amount"] = 1000,
+ ["Department"] = "HR"
+ };
+ Assert.Throws(() => _excelTemplater.FillTemplate(path.ToString(), templatePath, value, configuration: config));
+ }
+ }
+
+ [Fact]
+ public void TestIssueI4TXGT()
+ {
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
+ var value = new[] { new TestIssueI4TXGTDto { ID = 1, Name = "Apple", Spc = "X", Up = 6999 } };
+
+ _excelExporter.Export(path, value);
+ var rows1 = _excelImporter.Query(path).ToList();
+ Assert.Equal("ID", rows1[0].A);
+ Assert.Equal("Name", rows1[0].B);
+ Assert.Equal("Specification", rows1[0].C);
+ Assert.Equal("Unit Price", rows1[0].D);
+
+ var rows2 = _excelImporter.Query(path).ToList();
+ Assert.Equal(1, rows2[0].ID);
+ Assert.Equal("Apple", rows2[0].Name);
+ Assert.Equal("X", rows2[0].Spc);
+ Assert.Equal(6999, rows2[0].Up);
+ }
+
+ // https://gitee.com/dotnetchina/MiniExcel/issues/I4HL54
+ [Fact]
+ public void TestIssueI4HL54()
+ {
+ using var cn = Db.GetConnection();
+
+ using var reader = cn.ExecuteReader(@"select 'Hello World1' Text union all select 'Hello World2'");
+ var templatePath = PathHelper.GetFile("xlsx/TestIssueI4HL54_Template.xlsx");
+ using var path = AutoDeletingPath.Create();
+ var value = new Dictionary
+ {
+ { "Texts",reader}
+ };
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
+
+ var rows = _excelImporter.Query(path.ToString(), true).ToList();
+ Assert.Equal("Hello World1", rows[0].Text);
+ Assert.Equal("Hello World2", rows[1].Text);
+ }
+
+ // SaveAsByTemplate if there is & in the cell value, it will be &
+ // https://gitee.com/dotnetchina/MiniExcel/issues/I4DQUN
+ [Fact]
+ public void TestIssueI4DQUN()
+ {
+ var templatePath = PathHelper.GetFile("xlsx/TestIssueI4DQUN.xlsx");
+ using var path = AutoDeletingPath.Create();
+ var value = new Dictionary
+ {
+ { "Title", "Hello & World < , > , \" , '" },
+ { "Details", new[] { new { Value = "Hello & Value < , > , \" , '" } } },
+ };
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
+
+ var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ // Template now uses inlineStr format (...) instead of SharedStrings (...)
+ Assert.Contains("Hello & World < , > , \" , '", sheetXml);
+ Assert.Contains("Hello & Value < , > , \" , '", sheetXml);
+ }
+
+ [Fact]
+ public void TestIssueI49RYZ()
+ {
+ DescriptionEnumDto[] values =
+ [
+ new() { Name = "Jack", UserType = DescriptionEnum.V1 },
+ new() { Name = "Leo", UserType = DescriptionEnum.V2 },
+ new() { Name = "Henry", UserType = DescriptionEnum.V3 },
+ new() { Name = "Lisa", UserType = null }
+ ];
+
+ using var path = AutoDeletingPath.Create();
+ _excelExporter.Export(path.ToString(), values);
+ var rows = _excelImporter.Query(path.ToString(), true).ToList();
+ Assert.Equal("General User", rows[0].UserType);
+ Assert.Equal("General Administrator", rows[1].UserType);
+ Assert.Equal("Super Administrator", rows[2].UserType);
+ Assert.Null(rows[3].UserType);
+ }
+
+ // https://gitee.com/dotnetchina/MiniExcel/issues/I40QA5
+ [Fact]
+ public void TestIssueI40QA5()
+ {
+ {
+ var path = PathHelper.GetFile("/xlsx/TestIssueI40QA5_1.xlsx");
+ var rows = _excelImporter.Query(path).ToList();
+ Assert.Equal("E001", rows[0].Empno);
+ Assert.Equal("E002", rows[1].Empno);
+ }
+ {
+ var path = PathHelper.GetFile("/xlsx/TestIssueI40QA5_2.xlsx");
+ var rows = _excelImporter.Query(path).ToList();
+ Assert.Equal("E001", rows[0].Empno);
+ Assert.Equal("E002", rows[1].Empno);
+ }
+ {
+ var path = PathHelper.GetFile("/xlsx/TestIssueI40QA5_3.xlsx");
+ var rows = _excelImporter.Query(path).ToList();
+ Assert.Equal("E001", rows[0].Empno);
+ Assert.Equal("E002", rows[1].Empno);
+ }
+ {
+ var path = PathHelper.GetFile("/xlsx/TestIssueI40QA5_4.xlsx");
+ var rows = _excelImporter.Query(path).ToList();
+ Assert.Null(rows[0].Empno);
+ Assert.Null(rows[1].Empno);
+ }
+ }
+
+ // Semicolon expected
+ [Fact]
+ public void TestIssueI45TF5_2()
+ {
+ var value = new[] { new Dictionary { { "Col1&Col2", "V1&V2" } } };
+
+ using var path1 = AutoDeletingPath.Create();
+ _excelExporter.Export(path1.ToString(), value);
+ //System.Xml.XmlException : '<' is an unexpected token. The expected token is ';'.
+ SheetHelper.GetZipFileContent(path1.ToString(), "xl/worksheets/sheet1.xml"); //check illegal format or not
+
+ using var dt = new DataTable();
+ dt.Columns.Add("Col1&Col2");
+ dt.Rows.Add("V1&V2");
+
+ using var path2 = AutoDeletingPath.Create();
+ _excelExporter.Export(path2.FilePath, dt);
+ //System.Xml.XmlException : '<' is an unexpected token. The expected token is ';'.
+ SheetHelper.GetZipFileContent(path2.FilePath, "xl/worksheets/sheet1.xml"); //check illegal format or not
+ }
+
+ [Fact]
+ public void TestIssueI45TF5()
+ {
+ using var path = AutoDeletingPath.Create();
+ _excelExporter.Export(path.ToString(), new[] { new { C1 = "1&2;3,4", C2 = "1&2;3,4" } });
+ var sheet1Xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ Assert.DoesNotContain("", sheet1Xml);
+ }
+
+ [Fact]
+ public void TestIssueI3X2ZL()
+ {
+ try
+ {
+ var path = PathHelper.GetFile("xlsx/TestIssueI3X2ZL_datetime_error.xlsx");
+ var rows = _excelImporter.Query(path, startCell: "B3").ToList();
+ }
+ catch (InvalidCastException ex)
+ {
+ Assert.Equal(
+ "The value error cannot be assigned to type DateTime.",
+ ex.Message
+ );
+ }
+
+ try
+ {
+ var path = PathHelper.GetFile("xlsx/TestIssueI3X2ZL_int_error.xlsx");
+ var rows = _excelImporter.Query(path).ToList();
+ }
+ catch (InvalidCastException ex)
+ {
+ Assert.Equal(
+ "The value error cannot be assigned to type Int32.",
+ ex.Message
+ );
+ }
+ }
+
+ // https://gitee.com/dotnetchina/MiniExcel/issues/I3OSKV
+ // When exporting, the pure numeric string will be forcibly converted to a numeric type, resulting in the loss of the end data
+ [Fact]
+ public void IssueI3OSKV()
+ {
+ using var path1 = AutoDeletingPath.Create();
+ var value1 = new[] { new { Test = "12345678901234567890" } };
+ _excelExporter.Export(path1.ToString(), value1);
+
+ var result1 = _excelImporter.Query(path1.ToString(), true).First();
+ Assert.Equal("12345678901234567890", result1.Test);
+
+ using var path2 = AutoDeletingPath.Create();
+ var value2 = new[] { new { Test = 123456.789 } };
+ _excelExporter.Export(path2.ToString(), value2);
+
+ var result2 = _excelImporter.Query(path2.ToString(), true).First();
+ Assert.Equal(123456.789, result2.Test);
+ }
+
+ // https://gitee.com/dotnetchina/MiniExcel/issues/I50VD5
+ [Fact]
+ public void IssueI50VD5()
+ {
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
+
+ List list1 =
+ [
+ new { Name = "github", Image = File.ReadAllBytes(PathHelper.GetFile("images/github_logo.png")) },
+ new { Name = "google", Image = File.ReadAllBytes(PathHelper.GetFile("images/google_logo.png")) },
+ new { Name = "microsoft", Image = File.ReadAllBytes(PathHelper.GetFile("images/microsoft_logo.png")) },
+ new { Name = "reddit", Image = File.ReadAllBytes(PathHelper.GetFile("images/reddit_logo.png")) },
+ new { Name = "stackoverflow", Image = File.ReadAllBytes(PathHelper.GetFile("images/stackoverflow_logo.png")) }
+ ];
+
+ List list2 =
+ [
+ new { Id = 1, Name = "github", Image = File.ReadAllBytes(PathHelper.GetFile("images/github_logo.png")) },
+ new { Id = 2, Name = "google", Image = File.ReadAllBytes(PathHelper.GetFile("images/google_logo.png")) }
+ ];
+
+ var sheets = new Dictionary
+ {
+ ["A"] = list1,
+ ["B"] = list2,
+ };
+ _excelExporter.Export(path, sheets);
+
+ {
+ Assert.Contains("/xl/media/", SheetHelper.GetZipFileContent(path, "xl/drawings/_rels/drawing1.xml.rels"));
+ Assert.Contains("ext cx=\"609600\" cy=\"190500\"", SheetHelper.GetZipFileContent(path, "xl/drawings/drawing1.xml"));
+ Assert.Contains("/xl/drawings/drawing1.xml", SheetHelper.GetZipFileContent(path, "[Content_Types].xml"));
+ Assert.Contains("drawing r:id=\"drawing1\"", SheetHelper.GetZipFileContent(path, "xl/worksheets/sheet1.xml"));
+ Assert.Contains("../drawings/drawing1.xml", SheetHelper.GetZipFileContent(path, "xl/worksheets/_rels/sheet1.xml.rels"));
+
+ Assert.Contains("/xl/media/", SheetHelper.GetZipFileContent(path, "xl/drawings/_rels/drawing2.xml.rels"));
+ Assert.Contains("ext cx=\"609600\" cy=\"190500\"", SheetHelper.GetZipFileContent(path, "xl/drawings/drawing2.xml"));
+ Assert.Contains("/xl/drawings/drawing1.xml", SheetHelper.GetZipFileContent(path, "[Content_Types].xml"));
+ Assert.Contains("drawing r:id=\"drawing2\"", SheetHelper.GetZipFileContent(path, "xl/worksheets/sheet2.xml"));
+ Assert.Contains("../drawings/drawing2.xml", SheetHelper.GetZipFileContent(path, "xl/worksheets/_rels/sheet2.xml.rels"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/MiniExcel.OpenXml.Tests/MiniExcelIssueAsyncTests.cs b/tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGithubIssuesAsyncTests.cs
similarity index 57%
rename from tests/MiniExcel.OpenXml.Tests/MiniExcelIssueAsyncTests.cs
rename to tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGithubIssuesAsyncTests.cs
index be0bad0c..abeda8d8 100644
--- a/tests/MiniExcel.OpenXml.Tests/MiniExcelIssueAsyncTests.cs
+++ b/tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGithubIssuesAsyncTests.cs
@@ -2,9 +2,9 @@
using MiniExcelLib.OpenXml.Tests.Utils;
using MiniExcelLib.Tests.Common.Utils;
-namespace MiniExcelLib.OpenXml.Tests;
+namespace MiniExcelLib.OpenXml.Tests.Issues;
-public class MiniExcelIssueAsyncTests(ITestOutputHelper output)
+public class MiniExcelGithubIssuesAsyncTests(ITestOutputHelper output)
{
private readonly ITestOutputHelper _output = output;
@@ -12,142 +12,80 @@ public class MiniExcelIssueAsyncTests(ITestOutputHelper output)
private readonly OpenXmlExporter _excelExporter = MiniExcel.Exporters.GetOpenXmlExporter();
private readonly OpenXmlTemplater _excelTemplater = MiniExcel.Templaters.GetOpenXmlTemplater();
- static MiniExcelIssueAsyncTests()
+ static MiniExcelGithubIssuesAsyncTests()
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
}
- ///
- /// [SaveAsByTemplate support DateTime custom format · Issue #255 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/255)
- ///
[Fact]
- public async Task Issue255()
+ public async Task EmptyDataReaderIssue()
{
- var dt1 = new DateTime(2021, 01, 01);
- var dt2 = new DateTime(2022, 01, 01);
-
- //template
- {
- var templatePath = PathHelper.GetFile("xlsx/TestsIssue255_Template.xlsx");
- await using var ms = new MemoryStream();
- var value = new
- {
- Issue255DTO = new[] { new Issue255DTO { Time = dt1, Time2 = dt2 } }
- };
-
- await _excelTemplater.FillTemplateAsync(ms, templatePath, value);
-
- ms.Seek(0, SeekOrigin.Begin);
- using var package = new ExcelPackage(ms);
- var cells = package.Workbook.Worksheets[0].Cells;
+ using var path = AutoDeletingPath.Create();
+ using var tempSqlitePath = AutoDeletingPath.Create(Path.GetTempPath(), $"{Guid.NewGuid()}.db");
+ var connectionString = $"Data Source={tempSqlitePath};Version=3;";
- Assert.Equal("2021", cells["A2"].Text);
- Assert.Equal("2022", cells["B2"].Text);
- }
- //export
+ await using (var connection1 = new SQLiteConnection(connectionString))
{
- await using var ms = new MemoryStream();
- Issue255DTO[] value =
- [
- new() { Time = dt1, Time2 = dt2 }
- ];
-
- var rowsWritten = await _excelExporter.ExportAsync(ms, value);
- Assert.Single(rowsWritten);
- Assert.Equal(1, rowsWritten[0]);
-
- ms.Seek(0, SeekOrigin.Begin);
- using var package = new ExcelPackage(ms);
-
- var cells = package.Workbook.Worksheets[0].Cells;
- Assert.Equal(dt1, DateTime.FromOADate((double)cells["A2"].Value));
- Assert.Equal("2021", cells["A2"].Text);
- Assert.Equal(dt2, DateTime.FromOADate((double)cells["B2"].Value));
- Assert.Equal("2022", cells["B2"].Text);
+ await connection1.ExecuteAsync("CREATE TABLE test (id int PRIMARY KEY, name TEXT)");
}
- }
- private class Issue255DTO
- {
- [MiniExcelFormat("yyyy")]
- public DateTime Time { get; set; }
+ await using var connection2 = new SQLiteConnection(connectionString);
+ await using var reader = await connection2.ExecuteReaderAsync("SELECT * FROM test");
- [MiniExcelColumn(Format = "yyyy")]
- public DateTime Time2 { get; set; }
- }
+ var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), reader);
+ Assert.Single(rowsWritten);
+ Assert.Equal(0, rowsWritten[0]);
- ///
- /// [Dynamic QueryAsync custom format not using mapping format · Issue #256]
- /// (https://github.com/mini-software/MiniExcel/issues/256)
- ///
- [Fact]
- public async Task Issue256()
- {
- var path = PathHelper.GetFile("xlsx/TestIssue256.xlsx");
- var q = await _excelImporter.QueryAsync(path).ToListAsync();
- var rows = q.ToList();
-
- Assert.Equal(new DateTime(2003, 4, 16), rows[1].A);
- Assert.Equal(new DateTime(2004, 4, 16), rows[1].B);
+ var rows = await _excelImporter.QueryAsync(path.ToString(), true).ToListAsync();
+ Assert.Empty(rows);
}
-
- ///
- /// No error exception throw when reading xls file #242
- ///
[Fact]
- public async Task Issue242()
+ public async Task Issue87()
{
- var path = PathHelper.GetFile("xls/TestIssue242.xls");
- Assert.Throws(() => _ = _excelImporter.QueryAsync(path).ToBlockingEnumerable().ToList());
+ var templatePath = PathHelper.GetFile("xlsx/TestTemplateCenterEmpty.xlsx");
+ using var path = AutoDeletingPath.Create();
+ var value = new
+ {
+ Tests = Enumerable.Range(1, 5).Select((_, i) => new { test1 = i, test2 = i })
+ };
- await using var stream = File.OpenRead(path);
- Assert.Throws(() => _ = _excelImporter.QueryAsync(stream).ToBlockingEnumerable().ToList());
+ await using var stream = File.OpenRead(templatePath);
+ _ = await _excelImporter.QueryAsync(templatePath).ToListAsync();
+ await _excelTemplater.FillTemplateAsync(path.ToString(), templatePath, value);
}
- ///
- /// Support Custom Datetime format #241
- ///
+ // QueryAsync Merge cells data
[Fact]
- public async Task Issue241()
+ public async Task Issue122()
{
- var date1 = new DateTime(2021, 01, 04);
- var date2 = new DateTime(2020, 04, 05);
-
- Issue241Dto[] value =
- [
- new() { Name = "Jack", InDate = date1 },
- new() { Name = "Henry", InDate = date2 }
- ];
-
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
- var rowsWritten = await _excelExporter.ExportAsync(path, value);
+ var config = new OpenXmlConfiguration
+ {
+ FillMergedCells = true
+ };
- Assert.Single(rowsWritten);
- Assert.Equal(2, rowsWritten[0]);
-
- using var package = new ExcelPackage(path);
- var cells = package.Workbook.Worksheets[0].Cells;
-
- Assert.Equal(date1, DateTime.FromOADate((double)cells["B2"].Value));
- Assert.Equal("01 04, 2021", cells["B2"].Text);
- Assert.Equal(date2, DateTime.FromOADate((double)cells["B3"].Value));
- Assert.Equal("04 05, 2020", cells["B3"].Text);
- }
+ var path1 = PathHelper.GetFile("xlsx/TestIssue122.xlsx");
+ var rows1 = await _excelImporter.QueryAsync(path1, hasHeaderRow: true, configuration: config).ToListAsync();
+
+ Assert.Equal("HR", rows1[0].Department);
+ Assert.Equal("HR", rows1[1].Department);
+ Assert.Equal("HR", rows1[2].Department);
+ Assert.Equal("IT", rows1[3].Department);
+ Assert.Equal("IT", rows1[4].Department);
+ Assert.Equal("IT", rows1[5].Department);
- private class Issue241Dto
- {
- public string Name { get; set; }
+ var path2 = PathHelper.GetFile("xlsx/TestIssue122_2.xlsx");
+ var rows2 = await _excelImporter.QueryAsync(path2, hasHeaderRow: true, configuration: config).ToListAsync();
- [MiniExcelFormat("MM dd, yyyy")]
- public DateTime InDate { get; set; }
+ Assert.Equal("V1", rows2[2].Test1);
+ Assert.Equal("V2", rows2[5].Test2);
+ Assert.Equal("V3", rows2[1].Test3);
+ Assert.Equal("V4", rows2[2].Test4);
+ Assert.Equal("V5", rows2[3].Test5);
+ Assert.Equal("V6", rows2[5].Test5);
}
- ///
- /// SaveAs Default Template #132
- ///
+ // SaveAs Default Template
[Fact]
public async Task Issue132()
{
@@ -195,276 +133,365 @@ public async Task Issue132()
Assert.Single(rowsWritten);
Assert.Equal(2, rowsWritten[0]);
}
- }
+ }
- ///
- /// Support SaveAs by DataSet #235
- ///
[Fact]
- public async Task Issue235()
+ public async Task Issue137()
{
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
+ var path = PathHelper.GetFile("xlsx/TestIssue137.xlsx");
+ {
+ var rows = await _excelImporter.QueryAsync(path).Cast>().ToListAsync();
+ Assert.Equal(["A", "B", "C", "D", "E", "F", "G", "H"], rows[0].Keys.ToArray());
+ Assert.Equal(11, rows.Count);
- var users = new DataTable { TableName = "users" };
- users.Columns.Add("Name", typeof(string));
- users.Columns.Add("Age", typeof(int));
- users.Rows.Add("Jack", 25);
- users.Rows.Add("Mike", 44);
+ var row1 = rows[0];
+ Assert.Equal("比例", row1["A"]);
+ Assert.Equal("商品", row1["B"]);
+ Assert.Equal("滿倉口數", row1["C"]);
+ Assert.Equal(" ", row1["D"]);
+ Assert.Equal(" ", row1["E"]);
+ Assert.Equal(" ", row1["F"]);
+ Assert.Equal(0.0, row1["G"]);
+ Assert.Equal("1為港幣 0為台幣", row1["H"]);
+
+ var row2 = rows[1];
+ Assert.Equal(1.0, row2["A"]);
+ Assert.Equal("MTX", row2["B"]);
+ Assert.Equal(10.0, row2["C"]);
+ Assert.Null(row2["D"]);
+ Assert.Null(row2["E"]);
+ Assert.Null(row2["F"]);
+ Assert.Null(row2["G"]);
+ Assert.Null(row2["H"]);
+
+ var row3 = rows[2];
+ Assert.Equal(0.95, row3["A"]);
+ }
- var departments = new DataTable { TableName = "departments" };
- departments.Columns.Add("ID");
- departments.Columns.Add("Name");
- departments.Rows.Add("01", "HR");
- departments.Rows.Add("02", "IT");
+ // dynamic query with head
+ {
+ var rows = await _excelImporter.QueryAsync(path, true).Cast>().ToListAsync();
+ var first = rows[0]; // https://user-images.githubusercontent.com/12729184/113266322-ba06e400-9307-11eb-9521-d36abfda75cc.png
+ Assert.Equal(["比例", "商品", "滿倉口數", "0", "1為港幣 0為台幣"], first.Keys.ToArray());
+ Assert.Equal(10, rows.Count);
+
+ var row1 = rows[0];
+ Assert.Equal(1.0, row1["比例"]);
+ Assert.Equal("MTX", row1["商品"]);
+ Assert.Equal(10.0, row1["滿倉口數"]);
+ Assert.Null(row1["0"]);
+ Assert.Null(row1["1為港幣 0為台幣"]);
+
+ var row2 = rows[1];
+ Assert.Equal(0.95, row2["比例"]);
+ }
- DataSet sheets = new();
- sheets.Tables.Add(users);
- sheets.Tables.Add(departments);
+ {
+ var rows = await _excelImporter.QueryAsync(path).ToListAsync();
+ Assert.Equal(10, rows.Count);
+
+ var row1 = rows[0];
+ Assert.Equal(1, row1.比例);
+ Assert.Equal("MTX", row1.商品);
+ Assert.Equal(10, row1.滿倉口數);
- var rowsWritten = await _excelExporter.ExportAsync(path, sheets);
- Assert.Equal(2, rowsWritten.Length);
- Assert.Equal(2, rowsWritten[0]);
+ var row2 = rows[1];
+ Assert.Equal(0.95, row2.比例);
+ }
+ }
- var sheetNames = await _excelImporter.GetSheetNamesAsync(path);
- Assert.Equal("users", sheetNames[0]);
- Assert.Equal("departments", sheetNames[1]);
+ [Fact]
+ public async Task Issue138()
+ {
+ var path = PathHelper.GetFile("xlsx/TestIssue138.xlsx");
+ {
+ var rows = await _excelImporter.QueryAsync(path, true).ToListAsync();
+ Assert.Equal(6, rows.Count);
- var rows1 = await _excelImporter.QueryAsync(path, true, sheetName: "users").ToListAsync();
- Assert.Equal("Jack", rows1[0].Name);
- Assert.Equal(25, rows1[0].Age);
- Assert.Equal("Mike", rows1[1].Name);
- Assert.Equal(44, rows1[1].Age);
+ foreach (var index in new[] { 0, 2, 5 })
+ {
+ Assert.Equal(1, rows[index].實單每日損益);
+ Assert.Equal(2, rows[index].程式每日損益);
+ Assert.Equal("測試商品1", rows[index].商品);
+ Assert.Equal(111.11, rows[index].滿倉口數);
+ Assert.Equal(111.11, rows[index].波段);
+ Assert.Equal(111.11, rows[index].當沖);
+ }
- var rows2 = await _excelImporter.QueryAsync(path, true, sheetName: "departments").ToListAsync();
- Assert.Equal("01", rows2[0].ID);
- Assert.Equal("HR", rows2[0].Name);
- Assert.Equal("02", rows2[1].ID);
- Assert.Equal("IT", rows2[1].Name);
+ foreach (var index in new[] { 1, 3, 4 })
+ {
+ Assert.Null(rows[index].實單每日損益);
+ Assert.Null(rows[index].程式每日損益);
+ Assert.Null(rows[index].商品);
+ Assert.Null(rows[index].滿倉口數);
+ Assert.Null(rows[index].波段);
+ Assert.Null(rows[index].當沖);
+ }
+ }
+ {
+
+ var rows = await _excelImporter.QueryAsync(path).ToListAsync();
+ Assert.Equal(6, rows.Count);
+ Assert.Equal(new DateTime(2021, 3, 1), rows[0].Date);
+
+ foreach (var index in new[] { 0, 2, 5 })
+ {
+ Assert.Equal(1, rows[index].實單每日損益);
+ Assert.Equal(2, rows[index].程式每日損益);
+ Assert.Equal("測試商品1", rows[index].商品);
+ Assert.Equal(111.11, rows[index].滿倉口數);
+ Assert.Equal(111.11, rows[index].波段);
+ Assert.Equal(111.11, rows[index].當沖);
+ }
+
+ foreach (var index in new[] { 1, 3, 4 })
+ {
+ Assert.Null(rows[index].實單每日損益);
+ Assert.Null(rows[index].程式每日損益);
+ Assert.Null(rows[index].商品);
+ Assert.Null(rows[index].滿倉口數);
+ Assert.Null(rows[index].波段);
+ Assert.Null(rows[index].當沖);
+ }
+ }
}
- ///
- /// QueryAsDataTable A2=5.5 , A3=0.55/1.1 will case double type check error #233
- ///
[Fact]
- public async Task Issue233()
+ public async Task Issue142()
{
- var path = PathHelper.GetFile("xlsx/TestIssue233.xlsx");
+ var path = PathHelper.GetFile("xlsx/TestIssue142.xlsx");
+ var rows = await _excelImporter.QueryAsync(path).ToListAsync();
- var dt = await _excelImporter.QueryAsDataTableAsync(path);
- var rows = dt.Rows;
-
- Assert.Equal(0.55, rows[0]["Size"]);
- Assert.Equal("0.55/1.1", rows[1]["Size"]);
+ Assert.Equal(0, rows[0].MyProperty1);
+ await Assert.ThrowsAsync(async () =>
+ {
+ _ = await _excelImporter.QueryAsync(path).ToListAsync();
+ });
+
+ var rows1 = await _excelImporter.QueryAsync(path).ToListAsync();
+ Assert.Equal("CustomColumnName", rows1[0].MyProperty1);
+ Assert.Null(rows1[0].MyProperty7);
+ Assert.Equal("MyProperty2", rows1[0].MyProperty2);
+ Assert.Equal("MyProperty103", rows1[0].MyProperty3);
+ Assert.Equal("MyProperty100", rows1[0].MyProperty4);
+ Assert.Equal("MyProperty102", rows1[0].MyProperty5);
+ Assert.Equal("MyProperty6", rows1[0].MyProperty6);
+
+ var rows2 = await _excelImporter.QueryAsync(path).ToListAsync();
+ Assert.Equal("CustomColumnName", rows2[0].MyProperty1);
+ Assert.Null(rows2[0].MyProperty7);
+ Assert.Equal("MyProperty2", rows2[0].MyProperty2);
+ Assert.Equal("MyProperty103", rows2[0].MyProperty3);
+ Assert.Equal("MyProperty100", rows2[0].MyProperty4);
+ Assert.Equal("MyProperty102", rows2[0].MyProperty5);
+ Assert.Equal("MyProperty6", rows2[0].MyProperty6);
}
- ///
- /// SaveAs support multiple sheets #234
- ///
+ // QueryAsync Support StartCell
[Fact]
- public async Task Issue234()
+ public async Task Issue147()
{
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
-
- var users = new[]
- {
- new { Name = "Jack", Age = 25 },
- new { Name = "Mike", Age = 44 }
- };
- var department = new[]
- {
- new { ID = "01", Name = "HR" },
- new { ID = "02", Name = "IT" }
- };
- var sheets = new Dictionary
+ var path1 = PathHelper.GetFile("xlsx/TestIssue147.xlsx");
+ var rows1 = await _excelImporter.QueryAsync(path1, hasHeaderRow: false, startCell: "C3", sheetName: "Sheet1").ToListAsync();
+
+ Assert.Equal(["C", "D", "E"], (rows1[0] as IDictionary)?.Keys);
+ Assert.Equal(new[]{ "Column1", "Column2", "Column3" }, new[] { rows1[0].C as string, rows1[0].D as string, rows1[0].E as string });
+ Assert.Equal(new[]{ "C4", "D4", "E4" }, new[] { rows1[1].C as string, rows1[1].D as string, rows1[1].E as string });
+ Assert.Equal(new[]{ "C9", "D9", "E9" }, new[] { rows1[6].C as string, rows1[6].D as string, rows1[6].E as string });
+ Assert.Equal(new[]{ "C12", "D12", "E12" }, new[] { rows1[9].C as string, rows1[9].D as string, rows1[9].E as string });
+ Assert.Equal(new[]{ "C13", "D13", "E13" }, new[] { rows1[10].C as string, rows1[10].D as string, rows1[10].E as string });
+
+ foreach (var i in new[] { 4, 5, 7, 8 })
{
- ["users"] = users,
- ["department"] = department
- };
- var rowsWritten = await _excelExporter.ExportAsync(path, sheets);
-
- Assert.Equal(2, rowsWritten.Length);
- Assert.Equal(2, rowsWritten[0]);
-
+ Assert.Equal(new string?[]{null, null, null}, new[] { rows1[i].C as string, rows1[i].D as string, rows1[i].E as string });
+ }
+ Assert.Equal(11, rows1.Count);
- var sheetNames = _excelImporter.GetSheetNames(path);
- Assert.Equal("users", sheetNames[0]);
- Assert.Equal("department", sheetNames[1]);
+ var columns1 = await _excelImporter.GetColumnNamesAsync(path1, startCell: "C3");
+ Assert.Equal(["C", "D", "E"], columns1);
- {
- var q = _excelImporter.QueryAsync(path, true, sheetName: "users").ToBlockingEnumerable();
- var rows = q.ToList();
+
+ var path2 = PathHelper.GetFile("xlsx/TestIssue147.xlsx");
+ var rows2 = await _excelImporter.QueryAsync(path2, hasHeaderRow: true, startCell: "C3", sheetName: "Sheet1").ToListAsync();
- Assert.Equal("Jack", rows[0].Name);
- Assert.Equal(25, rows[0].Age);
- Assert.Equal("Mike", rows[1].Name);
- Assert.Equal(44, rows[1].Age);
- }
- {
- var q = _excelImporter.QueryAsync(path, true, sheetName: "department").ToBlockingEnumerable();
- var rows = q.ToList();
+ Assert.Equal(["Column1", "Column2", "Column3"], (rows2[0] as IDictionary)?.Keys);
+ Assert.Equal(new[]{"C4", "D4", "E4"}, new[] { rows2[0].Column1 as string, rows2[0].Column2 as string, rows2[0].Column3 as string });
+ Assert.Equal(new[]{"C9", "D9", "E9"}, new[] { rows2[5].Column1 as string, rows2[5].Column2 as string, rows2[5].Column3 as string });
+ Assert.Equal(new[]{"C12", "D12", "E12"}, new[] { rows2[8].Column1 as string, rows2[8].Column2 as string, rows2[8].Column3 as string });
+ Assert.Equal(new[]{"C13", "D13", "E13"}, new[] { rows2[9].Column1 as string, rows2[9].Column2 as string, rows2[9].Column3 as string });
- Assert.Equal("01", rows[0].ID);
- Assert.Equal("HR", rows[0].Name);
- Assert.Equal("02", rows[1].ID);
- Assert.Equal("IT", rows[1].Name);
+ foreach (var i in new[] { 3, 4, 6, 7 })
+ {
+ Assert.Equal(new string?[]{null, null, null}, new[] { rows2[i].Column1 as string, rows2[i].Column2 as string, rows2[i].Column3 as string });
}
+ Assert.Equal(10, rows2.Count);
+
+ var columns2 = await _excelImporter.GetColumnNamesAsync(path2, hasHeaderRow: true, startCell: "C3");
+ Assert.Equal(["Column1", "Column2", "Column3"], columns2);
}
- ///
- /// SaveAs By Reader Closed error : 'Error! Invalid attempt to call FieldCount when reader is closed' #230
- /// https://github.com/mini-software/MiniExcel/issues/230
- ///
[Fact]
- public async Task Issue230()
+ public async Task Issue149()
{
- await using var conn = Db.GetConnection("Data Source=:memory:");
- await conn.OpenAsync();
- await using var cmd = conn.CreateCommand();
- cmd.CommandText = "select 1 id union all select 2";
+ char[] chars =
+ [
+ '\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007', '\u0008',
+ '\u0009', //
+ '\u000A', //
+ '\u000B', '\u000C',
+ '\u000D', //
+ '\u000E', '\u000F', '\u0010', '\u0011', '\u0012', '\u0013', '\u0014', '\u0015', '\u0016',
+ '\u0017', '\u0018', '\u0019', '\u001A', '\u001B', '\u001C', '\u001D', '\u001E', '\u001F', '\u007F'
+ ];
+ var strings = chars.Select(s => s.ToString()).ToArray();
- await using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection))
+ var path1 = PathHelper.GetFile("xlsx/TestIssue149.xlsx");
+ var rows1 = await _excelImporter.QueryAsync(path1).Select(s => (string)s.A).ToListAsync();
+
+ for (int i = 0; i < chars.Length; i++)
{
- while (await reader.ReadAsync())
- {
- for (int i = 0; i < reader.FieldCount; i++)
- {
- var result = $"{reader.GetName(i)} , {reader.GetValue(i)}";
- _output.WriteLine(result);
- }
- }
+ if (i != 13)
+ Assert.Equal(strings[i], rows1[i]);
}
- await using var conn2 = Db.GetConnection("Data Source=:memory:");
- await conn2.OpenAsync();
- await using var cmd2 = conn2.CreateCommand();
- cmd2.CommandText = "select 1 id union all select 2";
-
- await using (var reader = await cmd2.ExecuteReaderAsync(CommandBehavior.CloseConnection))
+ using var file1 = AutoDeletingPath.Create();
+ var path2 = file1.ToString();
+
+ var input1 = chars.Select(s => new { Test = s.ToString() });
+ await _excelExporter.ExportAsync(path2, input1);
+
+ var rows2 = await _excelImporter.QueryAsync(path2, true).Select(s => (string)s.Test).ToListAsync();
+ for (int i = 0; i < chars.Length; i++)
{
- while (await reader.ReadAsync())
- {
- for (int i = 0; i < reader.FieldCount; i++)
- {
- var result = $"{reader.GetName(i)} , {reader.GetValue(i)}";
- _output.WriteLine(result);
- }
- }
+ _output.WriteLine($"{i}, {chars[i]}, {rows2[i]}");
+ if (i is not (9 or 10 or 13))
+ Assert.Equal(strings[i], rows2[i]);
}
- await using var conn3 = Db.GetConnection("Data Source=:memory:");
- await conn3.OpenAsync();
- await using var cmd3 = conn3.CreateCommand();
- cmd3.CommandText = "select 1 id union all select 2";
-
- await using (var reader = await cmd3.ExecuteReaderAsync(CommandBehavior.CloseConnection))
+ using var file2 = AutoDeletingPath.Create();
+ var path3 = file2.ToString();
+
+ var input2 = chars.Select(s => new { Test = s.ToString() });
+ await _excelExporter.ExportAsync(path3, input2);
+
+ var rows = await _excelImporter.QueryAsync(path3).Select(s => s.Test).ToListAsync();
+ for (int i = 0; i < chars.Length; i++)
{
- using var path = AutoDeletingPath.Create();
- var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), reader, printHeader: true);
-
- Assert.Single(rowsWritten);
- Assert.Equal(2, rowsWritten[0]);
-
- var q = _excelImporter.QueryAsync(path.ToString(), true).ToBlockingEnumerable();
- var rows = q.ToList();
-
- Assert.Equal(1, rows[0].id);
- Assert.Equal(2, rows[1].id);
+ _output.WriteLine($"{i}, {chars[i]}, {rows[i]}");
+ if (i is not (13 or 9 or 10))
+ Assert.Equal(strings[i], rows[i]);
}
}
- ///
- /// v0.14.3 QueryAsDataTable error "Cannot set Column to be null" #229
- /// https://github.com/mini-software/MiniExcel/issues/229
- ///
[Fact]
- public async Task Issue229()
+ public async Task Issue150()
{
- var path = PathHelper.GetFile("xlsx/TestIssue229.xlsx");
-
- var dt = await _excelImporter.QueryAsDataTableAsync(path);
-
- foreach (DataColumn column in dt.Columns)
- {
- var v = dt.Rows[3][column];
- Assert.Equal(DBNull.Value, v);
- }
+ using var filePath = AutoDeletingPath.Create();
+ var path = filePath.ToString();
+
+ await Assert.ThrowsAnyAsync(async () => await _excelExporter.ExportAsync(path, new[] { 1, 2 }, overwriteFile: true));
+ await Assert.ThrowsAnyAsync(async () => await _excelExporter.ExportAsync(path, new[] { "1", "2" }, overwriteFile: true));
+ await Assert.ThrowsAnyAsync(async () => await _excelExporter.ExportAsync(path, new[] { '1', '2' }, overwriteFile: true));
+ await Assert.ThrowsAnyAsync(async () => await _excelExporter.ExportAsync(path, new[] { DateTime.Now }, overwriteFile: true));
+ await Assert.ThrowsAnyAsync(async () => await _excelExporter.ExportAsync(path, new[] { Guid.NewGuid() }, overwriteFile: true));
}
- ///
- /// [QueryAsync Merge cells data · Issue #122 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/122)
- ///
[Fact]
- public Task Issue122()
+ public async Task Issue153()
{
- var config = new OpenXmlConfiguration
- {
- FillMergedCells = true
- };
-
- var path1 = PathHelper.GetFile("xlsx/TestIssue122.xlsx");
- var rows1 = _excelImporter.QueryAsync(path1, hasHeaderRow: true, configuration: config).ToBlockingEnumerable().ToList();
-
- Assert.Equal("HR", rows1[0].Department);
- Assert.Equal("HR", rows1[1].Department);
- Assert.Equal("HR", rows1[2].Department);
- Assert.Equal("IT", rows1[3].Department);
- Assert.Equal("IT", rows1[4].Department);
- Assert.Equal("IT", rows1[5].Department);
-
- var path2 = PathHelper.GetFile("xlsx/TestIssue122_2.xlsx");
- var rows2 = _excelImporter.QueryAsync(path2, hasHeaderRow: true, configuration: config).ToBlockingEnumerable().ToList();
+ var path = PathHelper.GetFile("xlsx/TestIssue153.xlsx");
+ var row = (IDictionary)await _excelImporter.QueryAsync(path, true).FirstAsync();
- Assert.Equal("V1", rows2[2].Test1);
- Assert.Equal("V2", rows2[5].Test2);
- Assert.Equal("V3", rows2[1].Test3);
- Assert.Equal("V4", rows2[2].Test4);
- Assert.Equal("V5", rows2[3].Test5);
- Assert.Equal("V6", rows2[5].Test5);
-
- return Task.CompletedTask;
+ Assert.Equal(
+ [
+ "序号", "代号", "新代号", "名称", "XXX", "部门名称", "单位", "ERP工时 (小时)A", "工时(秒) A/3600", "标准人工工时(秒)",
+ "生产标准机器工时(秒)", "财务、标准机器工时(秒)", "更新日期", "产品机种", "备注", "最近一次修改前的标准工时(秒)", "最近一次修改前的标准机时(秒)", "备注1"
+ ], row.Keys);
}
- ///
- /// [Support Xlsm AutoCheck · Issue #227 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/227)
- ///
[Fact]
- public async Task Issue227()
+ public async Task Issue157()
{
{
- var path = PathHelper.GetTempPath("xlsm");
- Assert.Throws(() => _excelExporter.Export(path, new[] { new { V = "A1" }, new { V = "A2" } }));
- File.Delete(path);
- }
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
+
+ List data =
+ [
+ new()
+ {
+ ID = new Guid("78de23d2-dcb6-bd3d-ec67-c112bbc322a2"),
+ Name = "Wade",
+ BoD = new DateTime(2020, 9, 27),
+ Points = 5019.12m
+ },
+ new()
+ {
+ ID = new Guid("20d3bfce-27c3-ad3e-4f70-35c81c7e8e45"),
+ Name = "Felix",
+ BoD = new DateTime(2020, 10, 25),
+ Points = 7028.46m
+ },
+ new()
+ {
+ ID = new Guid("52013bf0-9aeb-48e6-e5f5-e9500afb034f"),
+ Name = "Phelan",
+ BoD = new DateTime(2020, 10, 25),
+ Points = 3835.7m,
+ VIP = true
+ },
+ new()
+ {
+ ID = new Guid("3b97b87c-7afe-664f-1af5-6914d313ae25"),
+ Name = "Samuel",
+ BoD = new DateTime(2020, 6, 21),
+ Points = 9351.71m
+ },
+ new()
+ {
+ ID = new Guid("9a989c43-d55f-5306-0d2f-0fbafae135bb"),
+ Name = "Raymond",
+ BoD = new DateTime(2021, 7, 12),
+ Points = 8209.76m,
+ VIP = true
+ }
+ ];
+
+ var rowsWritten = await _excelExporter.ExportAsync(path, data);
+ Assert.Single(rowsWritten);
+ Assert.Equal(5, rowsWritten[0]);
+
+ var q = await _excelImporter.QueryAsync(path, sheetName: "Sheet1").ToListAsync();
+ var rows = q.ToList();
+ Assert.Equal(6, rows.Count);
+ Assert.Equal("Sheet1", (await _excelImporter.GetSheetNamesAsync(path))[0]);
+ using var p = new ExcelPackage(new FileInfo(path));
+ var ws = p.Workbook.Worksheets[0];
+ Assert.Equal("Sheet1", ws.Name);
+ Assert.Equal("Sheet1", p.Workbook.Worksheets["Sheet1"].Name);
+ }
{
- var path = PathHelper.GetFile("xlsx/TestIssue227.xlsm");
+ var path = PathHelper.GetFile("xlsx/TestIssue157.xlsx");
{
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal(100, rows.Count);
-
- Assert.Equal(Guid.Parse("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows[0].ID);
- Assert.Equal("Wade", rows[0].Name);
- Assert.Equal(DateTime.ParseExact("27/09/2020", "dd/MM/yyyy", CultureInfo.InvariantCulture), rows[0].BoD);
- Assert.Equal(36, rows[0].Age);
- Assert.False(rows[0].VIP);
- Assert.Equal(5019.12m, rows[0].Points);
- Assert.Equal(1, rows[0].IgnoredProperty);
+ var rows = await _excelImporter.QueryAsync(path, sheetName: "Sheet1").ToListAsync();
+ Assert.Equal(6, rows.Count);
+ Assert.Equal("Sheet1", (await _excelImporter.GetSheetNamesAsync(path))[0]);
+ }
+ using (var p = new ExcelPackage(new FileInfo(path)))
+ {
+ var ws = p.Workbook.Worksheets.First();
+ Assert.Equal("Sheet1", ws.Name);
+ Assert.Equal("Sheet1", p.Workbook.Worksheets["Sheet1"].Name);
}
+
{
- await using var stream = File.OpenRead(path);
- var q = _excelImporter.QueryAsync(stream).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal(100, rows.Count);
+ var rows = await _excelImporter.QueryAsync(path, sheetName: "Sheet1").ToListAsync();
+ Assert.Equal(5, rows.Count);
Assert.Equal(Guid.Parse("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows[0].ID);
Assert.Equal("Wade", rows[0].Name);
Assert.Equal(DateTime.ParseExact("27/09/2020", "dd/MM/yyyy", CultureInfo.InvariantCulture), rows[0].BoD);
- Assert.Equal(36, rows[0].Age);
Assert.False(rows[0].VIP);
Assert.Equal(5019.12m, rows[0].Points);
Assert.Equal(1, rows[0].IgnoredProperty);
@@ -472,311 +499,148 @@ public async Task Issue227()
}
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/226
- /// Fix SaveAsByTemplate single column demension index error #226
- ///
[Fact]
- public async Task Issue226()
+ public async Task Issue193()
{
- using var path = AutoDeletingPath.Create();
- var templatePath = PathHelper.GetFile("xlsx/TestIssue226.xlsx");
- await _excelTemplater.FillTemplateAsync(path.ToString(), templatePath, new { employees = new[] { new { name = "123" }, new { name = "123" } } });
- Assert.Equal("A1:A3", SheetHelper.GetFirstSheetDimensionRefValue(path.ToString()));
- }
+ {
+ var templatePath = PathHelper.GetFile("xlsx/TestTemplateComplexWithNamespacePrefix.xlsx");
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
- ///
- /// ASP.NET Webform gridview datasource can't use miniexcel queryasdatatable · Issue #223]
- /// (https://github.com/mini-software/MiniExcel/issues/223)
- ///
- [Fact]
- public async Task Issue223()
- {
- List> value =
- [
- new() { { "A", null }, { "B", null } },
- new() { { "A", 123 }, { "B", new DateTime(2021, 1, 1) } },
- new() { { "A", Guid.NewGuid() }, { "B", "HelloWorld" } }
- ];
- using var path = AutoDeletingPath.Create();
- var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), value);
- Assert.Single(rowsWritten);
- Assert.Equal(3, rowsWritten[0]);
+ // 1. By Class
+ var value = new
+ {
+ title = "FooCompany",
+ managers = new[]
+ {
+ new {name="Jack",department="HR"},
+ new {name="Loan",department="IT"}
+ },
+ employees = new[]
+ {
+ new {name="Wade",department="HR"},
+ new {name="Felix",department="HR"},
+ new {name="Eric",department="IT"},
+ new {name="Keaton",department="IT"}
+ }
+ };
+ await _excelTemplater.FillTemplateAsync(path, templatePath, value);
+ foreach (var sheetName in await _excelImporter.GetSheetNamesAsync(path))
+ {
+ var rows = await _excelImporter.QueryAsync(path, sheetName: sheetName).ToListAsync();
+ Assert.Equal(9, rows.Count);
- var dt = await _excelImporter.QueryAsDataTableAsync(path.ToString());
-#pragma warning restore CS0618
- var columns = dt.Columns;
- Assert.Equal(typeof(object), columns[0].DataType);
- Assert.Equal(typeof(object), columns[1].DataType);
+ Assert.Equal("FooCompany", rows[0].A);
+ Assert.Equal("Jack", rows[2].B);
+ Assert.Equal("HR", rows[2].C);
+ Assert.Equal("Loan", rows[3].B);
+ Assert.Equal("IT", rows[3].C);
- Assert.Equal(123.0, dt.Rows[1]["A"]);
- Assert.Equal("HelloWorld", dt.Rows[2]["B"]);
- }
+ Assert.Equal("Wade", rows[5].B);
+ Assert.Equal("HR", rows[5].C);
+ Assert.Equal("Felix", rows[6].B);
+ Assert.Equal("HR", rows[6].C);
- ///
- /// [Custom yyyy-MM-dd format not convert datetime · Issue #222]
- /// (https://github.com/mini-software/MiniExcel/issues/222)
- ///
- [Fact]
- public async Task Issue222()
- {
- var path = PathHelper.GetFile("xlsx/TestIssue222.xlsx");
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal(typeof(DateTime), rows[1].A.GetType());
- Assert.Equal(new DateTime(2021, 4, 29), rows[1].A);
- }
-
- ///
- /// QueryAsync Support StartCell #147
- /// https://github.com/mini-software/MiniExcel/issues/147
- ///
- [Fact]
- public async Task Issue147()
- {
- {
- var path = PathHelper.GetFile("xlsx/TestIssue147.xlsx");
- var q = _excelImporter.QueryAsync(path, hasHeaderRow: false, startCell: "C3", sheetName: "Sheet1").ToBlockingEnumerable();
- var rows = q.ToList();
-
- Assert.Equal(["C", "D", "E"], (rows[0] as IDictionary)?.Keys);
- Assert.Equal(["Column1", "Column2", "Column3"], new[] { rows[0].C as string, rows[0].D as string, rows[0].E as string });
- Assert.Equal(["C4", "D4", "E4"], new[] { rows[1].C as string, rows[1].D as string, rows[1].E as string });
- Assert.Equal(["C9", "D9", "E9"], new[] { rows[6].C as string, rows[6].D as string, rows[6].E as string });
- Assert.Equal(["C12", "D12", "E12"], new[] { rows[9].C as string, rows[9].D as string, rows[9].E as string });
- Assert.Equal(["C13", "D13", "E13"], new[] { rows[10].C as string, rows[10].D as string, rows[10].E as string });
-
- foreach (var i in new[] { 4, 5, 7, 8 })
- {
- Assert.Equal([null, null, null], new[] { rows[i].C as string, rows[i].D as string, rows[i].E as string });
- }
- Assert.Equal(11, rows.Count);
+ Assert.Equal("Eric", rows[7].B);
+ Assert.Equal("IT", rows[7].C);
+ Assert.Equal("Keaton", rows[8].B);
+ Assert.Equal("IT", rows[8].C);
- var columns = await _excelImporter.GetColumnNamesAsync(path, startCell: "C3");
- Assert.Equal(["C", "D", "E"], columns);
- }
+ var demension = SheetHelper.GetFirstSheetDimensionRefValue(path);
+ Assert.Equal("A1:C9", demension);
- {
- var path = PathHelper.GetFile("xlsx/TestIssue147.xlsx");
- var q = _excelImporter.QueryAsync(path, hasHeaderRow: true, startCell: "C3", sheetName: "Sheet1").ToBlockingEnumerable();
- var rows = q.ToList();
-
- Assert.Equal(["Column1", "Column2", "Column3"], (rows[0] as IDictionary)?.Keys);
- Assert.Equal(["C4", "D4", "E4"], new[] { rows[0].Column1 as string, rows[0].Column2 as string, rows[0].Column3 as string });
- Assert.Equal(["C9", "D9", "E9"], new[] { rows[5].Column1 as string, rows[5].Column2 as string, rows[5].Column3 as string });
- Assert.Equal(["C12", "D12", "E12"], new[] { rows[8].Column1 as string, rows[8].Column2 as string, rows[8].Column3 as string });
- Assert.Equal(["C13", "D13", "E13"], new[] { rows[9].Column1 as string, rows[9].Column2 as string, rows[9].Column3 as string });
-
- foreach (var i in new[] { 3, 4, 6, 7 })
- {
- Assert.Equal([null, null, null], new[] { rows[i].Column1 as string, rows[i].Column2 as string, rows[i].Column3 as string });
+ //TODO:row can't contain xmlns
+ //
}
- Assert.Equal(10, rows.Count);
-
- var columns = await _excelImporter.GetColumnNamesAsync(path, hasHeaderRow: true, startCell: "C3");
- Assert.Equal(["Column1", "Column2", "Column3"], columns);
}
- }
-
- ///
- /// [Can SaveAs support iDataReader export to avoid the dataTable consuming too much memory · Issue #211 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/211)
- ///
- [Fact]
- public async Task Issue211()
- {
- using var path = AutoDeletingPath.Create();
- using var tempSqlitePath = AutoDeletingPath.Create(Path.GetTempPath(), $"{Guid.NewGuid()}.db");
- var connectionString = $"Data Source={tempSqlitePath};Version=3;";
-
- await using var connection = new SQLiteConnection(connectionString);
- using var reader = await connection.ExecuteReaderAsync("select 1 Test1,2 Test2 union all select 3 , 4 union all select 5 ,6");
-
- var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), reader);
- Assert.Single(rowsWritten);
- Assert.Equal(3, rowsWritten[0]);
-
- var q = _excelImporter.QueryAsync(path.ToString(), true).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal(1.0, rows[0].Test1);
- Assert.Equal(2.0, rows[0].Test2);
- Assert.Equal(3.0, rows[1].Test1);
- Assert.Equal(4.0, rows[1].Test2);
- }
-
- [Fact]
- public async Task EmptyDataReaderIssue()
- {
- using var path = AutoDeletingPath.Create();
- using var tempSqlitePath = AutoDeletingPath.Create(Path.GetTempPath(), $"{Guid.NewGuid()}.db");
- var connectionString = $"Data Source={tempSqlitePath};Version=3;";
-
- await using (var connection1 = new SQLiteConnection(connectionString))
{
- await connection1.ExecuteAsync("CREATE TABLE test (id int PRIMARY KEY, name TEXT)");
- }
-
- await using var connection2 = new SQLiteConnection(connectionString);
- using var reader = await connection2.ExecuteReaderAsync("SELECT * FROM test");
+ var templatePath = PathHelper.GetFile("xlsx/TestTemplateComplex.xlsx");
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
- var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), reader);
- Assert.Single(rowsWritten);
- Assert.Equal(0, rowsWritten[0]);
+ // 2. By Dictionary
+ var value = new Dictionary
+ {
+ ["title"] = "FooCompany",
+ ["managers"] = new[]
+ {
+ new {name="Jack",department="HR"},
+ new {name="Loan",department="IT"}
+ },
+ ["employees"] = new[]
+ {
+ new {name="Wade",department="HR"},
+ new {name="Felix",department="HR"},
+ new {name="Eric",department="IT"},
+ new {name="Keaton",department="IT"}
+ }
+ };
+ await _excelTemplater.FillTemplateAsync(path, templatePath, value);
- var q = _excelImporter.QueryAsync(path.ToString(), true).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Empty(rows);
- }
+ var rows = await _excelImporter.QueryAsync(path).ToListAsync();
+ Assert.Equal("FooCompany", rows[0].A);
+ Assert.Equal("Jack", rows[2].B);
+ Assert.Equal("HR", rows[2].C);
+ Assert.Equal("Loan", rows[3].B);
+ Assert.Equal("IT", rows[3].C);
- ///
- /// [When reading Excel, can return IDataReader and DataTable to facilitate the import of database. Like ExcelDataReader provide reader.AsDataSet() · Issue #216 · mini-software/MiniExcel](https://github.com/mini-software/MiniExcel/issues/216)
- ///
- [Fact]
- public async Task Issue216()
- {
- using var path = AutoDeletingPath.Create();
- var value = new[] { new { Test1 = "1", Test2 = 2 }, new { Test1 = "3", Test2 = 4 } };
- var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), value);
- Assert.Single(rowsWritten);
- Assert.Equal(2, rowsWritten[0]);
+ Assert.Equal("Wade", rows[5].B);
+ Assert.Equal("HR", rows[5].C);
+ Assert.Equal("Felix", rows[6].B);
+ Assert.Equal("HR", rows[6].C);
- {
- var table = await _excelImporter.QueryAsDataTableAsync(path.ToString());
- Assert.Equal("Test1", table.Columns[0].ColumnName);
- Assert.Equal("Test2", table.Columns[1].ColumnName);
- Assert.Equal("1", table.Rows[0]["Test1"]);
- Assert.Equal(2.0, table.Rows[0]["Test2"]);
- Assert.Equal("3", table.Rows[1]["Test1"]);
- Assert.Equal(4.0, table.Rows[1]["Test2"]);
- }
+ Assert.Equal("Eric", rows[7].B);
+ Assert.Equal("IT", rows[7].C);
+ Assert.Equal("Keaton", rows[8].B);
+ Assert.Equal("IT", rows[8].C);
- {
- var dt = await _excelImporter.QueryAsDataTableAsync(path.ToString(), false);
- Assert.Equal("Test1", dt.Rows[0]["A"]);
- Assert.Equal("Test2", dt.Rows[0]["B"]);
- Assert.Equal("1", dt.Rows[1]["A"]);
- Assert.Equal(2.0, dt.Rows[1]["B"]);
- Assert.Equal("3", dt.Rows[2]["A"]);
- Assert.Equal(4.0, dt.Rows[2]["B"]);
+ var demension = SheetHelper.GetFirstSheetDimensionRefValue(path);
+ Assert.Equal("A1:C9", demension);
}
}
- ///
- /// https://gitee.com/dotnetchina/MiniExcel/issues/I3OSKV
- /// When exporting, the pure numeric string will be forcibly converted to a numeric type, resulting in the loss of the end data
- ///
[Fact]
- public async Task IssueI3OSKV()
+ public async Task Issue206()
{
+ var templatePath = PathHelper.GetFile("xlsx/TestTemplateBasicIEmumerableFill.xlsx");
{
using var path = AutoDeletingPath.Create();
- var value = new[] { new { Test = "12345678901234567890" } };
- await _excelExporter.ExportAsync(path.ToString(), value);
- var q = _excelImporter.QueryAsync(path.ToString(), true).ToBlockingEnumerable();
- var A2 = q.First().Test;
- Assert.Equal("12345678901234567890", A2);
+ var dt = new DataTable();
+ {
+ dt.Columns.Add("name");
+ dt.Columns.Add("department");
+ }
+ var value = new Dictionary
+ {
+ ["employees"] = dt
+ };
+ await _excelTemplater.FillTemplateAsync(path.ToString(), templatePath, value);
+
+ var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path.ToString());
+ Assert.Equal("A1:B2", dimension);
}
{
using var path = AutoDeletingPath.Create();
- var value = new[] { new { Test = 123456.789 } };
- await _excelExporter.ExportAsync(path.ToString(), value);
-
- var q = _excelImporter.QueryAsync(path.ToString(), true).ToBlockingEnumerable();
- var A2 = q.First().Test;
- Assert.Equal(123456.789, A2);
- }
- }
- ///
- /// [Dynamic QueryAsync can't summary numeric cell value default, need to cast · Issue #220 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/220)
- ///
- [Fact]
- public async Task Issue220()
- {
- var path = PathHelper.GetFile("xlsx/TestIssue220.xlsx");
- var rows = _excelImporter.QueryAsync(path, hasHeaderRow: true).ToBlockingEnumerable();
- var result = rows
- .GroupBy(s => s.PRT_ID)
- .Select(g => new
+ var dt = new DataTable();
{
- PRT_ID = g.Key,
- Apr = g.Sum(d => (double?)d.Apr),
- May = g.Sum(d => (double?)d.May),
- Jun = g.Sum(d => (double?)d.Jun),
- })
- .ToList();
-
- Assert.Equal(91843.25, result[0].Jun);
- Assert.Equal(50000.99, result[1].Jun);
- }
-
- ///
- /// Optimize stream excel type check
- /// https://github.com/mini-software/MiniExcel/issues/215
- ///
- [Fact]
- public async Task Issue215()
- {
- await using var stream = new MemoryStream();
- await _excelExporter.ExportAsync(stream, new[] { new { V = "test1" }, new { V = "test2" } });
-
- var q = _excelImporter.QueryAsync(stream, true).ToBlockingEnumerable().Cast>();
- var rows = q.ToList();
-
- Assert.Equal("test1", rows[0]["V"]);
- Assert.Equal("test2", rows[1]["V"]);
- }
-
- ///
- /// DataTable recommended to use Caption for column name first, then use columname
- /// https://github.com/mini-software/MiniExcel/issues/217
- ///
- [Fact]
- public async Task Issue217()
- {
- using var table = new DataTable();
- table.Columns.Add("CustomerID");
- table.Columns.Add("CustomerName").Caption = "Name";
- table.Columns.Add("CreditLimit").Caption = "Limit";
- table.Rows.Add(1, "Jonathan", 23.44);
- table.Rows.Add(2, "Bill", 56.87);
-
- using var path = AutoDeletingPath.Create();
- var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), table);
- Assert.Single(rowsWritten);
- Assert.Equal(2, rowsWritten[0]);
-
- var q = _excelImporter.QueryAsync(path.ToString()).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal("Name", rows[0].B);
- Assert.Equal("Limit", rows[0].C);
- }
-
- ///
- /// _ _exporter.ExportXlsx(path, table,sheetName:“Name”) ,the actual sheetName is Sheet1
- /// https://github.com/mini-software/MiniExcel/issues/212
- ///
- [Fact]
- public async Task Issue212()
- {
- const string sheetName = "Demo";
-
- using var path = AutoDeletingPath.Create();
- await _excelExporter.ExportAsync(path.ToString(), new[] { new { x = 1, y = 2 } }, sheetName: sheetName);
+ dt.Columns.Add("name");
+ dt.Columns.Add("department");
+ dt.Rows.Add("Jack", "HR");
+ }
+ var value = new Dictionary { ["employees"] = dt };
+ await _excelTemplater.FillTemplateAsync(path.ToString(), templatePath, value);
- var actualSheetName = _excelImporter.GetSheetNames(path.ToString()).ToList()[0];
- Assert.Equal(sheetName, actualSheetName);
+ var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path.ToString());
+ Assert.Equal("A1:B2", dimension);
+ }
}
- ///
- /// Version <= v0.13.1 Template merge row list rendering has no merge
- /// https://github.com/mini-software/MiniExcel/issues/207
- ///
+ // Template merge row list rendering has no merge
[Fact]
public async Task Issue207()
{
@@ -797,8 +661,7 @@ public async Task Issue207()
};
await _excelTemplater.FillTemplateAsync(path, templatePath, value);
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.ToList();
+ var rows = await _excelImporter.QueryAsync(path).ToListAsync();
Assert.Equal("項目1", rows[0].A);
Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[0].B);
@@ -844,8 +707,7 @@ public async Task Issue207()
await _excelTemplater.FillTemplateAsync(path, templatePath, value);
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.ToList();
+ var rows = await _excelImporter.QueryAsync(path).ToListAsync();
Assert.Equal("項目1", rows[0].A);
Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[0].C);
Assert.Equal("項目2", rows[3].A);
@@ -860,621 +722,465 @@ public async Task Issue207()
}
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/87
- ///
+ // SaveAs support for IDataReader
[Fact]
- public async Task Issue87()
+ public async Task Issue211()
{
- var templatePath = PathHelper.GetFile("xlsx/TestTemplateCenterEmpty.xlsx");
using var path = AutoDeletingPath.Create();
- var value = new
- {
- Tests = Enumerable.Range(1, 5).Select((s, i) => new { test1 = i, test2 = i })
- };
+ using var tempSqlitePath = AutoDeletingPath.Create(Path.GetTempPath(), $"{Guid.NewGuid()}.db");
+ var connectionString = $"Data Source={tempSqlitePath};Version=3;";
- await using var stream = File.OpenRead(templatePath);
- var q = _excelImporter.QueryAsync(templatePath).ToBlockingEnumerable();
- var rows = q.ToList();
+ await using var connection = new SQLiteConnection(connectionString);
+ await using var reader = await connection.ExecuteReaderAsync("select 1 Test1,2 Test2 union all select 3 , 4 union all select 5 ,6");
+
+ var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), reader);
+ Assert.Single(rowsWritten);
+ Assert.Equal(3, rowsWritten[0]);
- await _excelTemplater.FillTemplateAsync(path.ToString(), templatePath, value);
+ var rows = await _excelImporter.QueryAsync(path.ToString(), true).ToListAsync();
+ Assert.Equal(1.0, rows[0].Test1);
+ Assert.Equal(2.0, rows[0].Test2);
+ Assert.Equal(3.0, rows[1].Test1);
+ Assert.Equal(4.0, rows[1].Test2);
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/206
- ///
+ // _exporter.ExportXlsx(path, table,sheetName:“Name”) ,final sheetName is incorrectly Sheet1
[Fact]
- public async Task Issue206()
+ public async Task Issue212()
{
- var templatePath = PathHelper.GetFile("xlsx/TestTemplateBasicIEmumerableFill.xlsx");
- {
- using var path = AutoDeletingPath.Create();
+ const string sheetName = "Demo";
+
+ using var path = AutoDeletingPath.Create();
+ await _excelExporter.ExportAsync(path.ToString(), new[] { new { x = 1, y = 2 } }, sheetName: sheetName);
- var dt = new DataTable();
- {
- dt.Columns.Add("name");
- dt.Columns.Add("department");
- }
- var value = new Dictionary
- {
- ["employees"] = dt
- };
- await _excelTemplater.FillTemplateAsync(path.ToString(), templatePath, value);
+ var actualSheetName = (await _excelImporter.GetSheetNamesAsync(path.ToString()))[0];
+ Assert.Equal(sheetName, actualSheetName);
+ }
- var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path.ToString());
- Assert.Equal("A1:B2", dimension);
- }
+ // When reading Excel, can return IDataReader and DataTable to facilitate the import of database. Like ExcelDataReader provide reader.AsDataSet()
+ [Fact]
+ public async Task Issue216()
+ {
+ using var path = AutoDeletingPath.Create();
- {
- using var path = AutoDeletingPath.Create();
+ var value = new[] { new { Test1 = "1", Test2 = 2 }, new { Test1 = "3", Test2 = 4 } };
+ var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), value);
+ Assert.Single(rowsWritten);
+ Assert.Equal(2, rowsWritten[0]);
- var dt = new DataTable();
- {
- dt.Columns.Add("name");
- dt.Columns.Add("department");
- dt.Rows.Add("Jack", "HR");
- }
- var value = new Dictionary { ["employees"] = dt };
- await _excelTemplater.FillTemplateAsync(path.ToString(), templatePath, value);
-
- var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path.ToString());
- Assert.Equal("A1:B2", dimension);
- }
+ using var table = await _excelImporter.QueryAsDataTableAsync(path.ToString());
+ Assert.Equal("Test1", table.Columns[0].ColumnName);
+ Assert.Equal("Test2", table.Columns[1].ColumnName);
+ Assert.Equal("1", table.Rows[0]["Test1"]);
+ Assert.Equal(2.0, table.Rows[0]["Test2"]);
+ Assert.Equal("3", table.Rows[1]["Test1"]);
+ Assert.Equal(4.0, table.Rows[1]["Test2"]);
+
+ using var dt = await _excelImporter.QueryAsDataTableAsync(path.ToString(), false);
+ Assert.Equal("Test1", dt.Rows[0]["A"]);
+ Assert.Equal("Test2", dt.Rows[0]["B"]);
+ Assert.Equal("1", dt.Rows[1]["A"]);
+ Assert.Equal(2.0, dt.Rows[1]["B"]);
+ Assert.Equal("3", dt.Rows[2]["A"]);
+ Assert.Equal(4.0, dt.Rows[2]["B"]);
}
-
- ///
- /// https://github.com/mini-software/MiniExcel/issues/193
- ///
+ // DataTable recommended to use Caption for column name first, then use columname
[Fact]
- public async Task Issue193()
+ public async Task Issue217()
{
- {
- var templatePath = PathHelper.GetFile("xlsx/TestTemplateComplexWithNamespacePrefix.xlsx");
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
-
- // 1. By Class
- var value = new
- {
- title = "FooCompany",
- managers = new[]
- {
- new {name="Jack",department="HR"},
- new {name="Loan",department="IT"}
- },
- employees = new[]
- {
- new {name="Wade",department="HR"},
- new {name="Felix",department="HR"},
- new {name="Eric",department="IT"},
- new {name="Keaton",department="IT"}
- }
- };
- await _excelTemplater.FillTemplateAsync(path, templatePath, value);
-
- foreach (var sheetName in await _excelImporter.GetSheetNamesAsync(path))
- {
- var rows = await _excelImporter.QueryAsync(path, sheetName: sheetName).ToListAsync();
- Assert.Equal(9, rows.Count);
-
- Assert.Equal("FooCompany", rows[0].A);
- Assert.Equal("Jack", rows[2].B);
- Assert.Equal("HR", rows[2].C);
- Assert.Equal("Loan", rows[3].B);
- Assert.Equal("IT", rows[3].C);
-
- Assert.Equal("Wade", rows[5].B);
- Assert.Equal("HR", rows[5].C);
- Assert.Equal("Felix", rows[6].B);
- Assert.Equal("HR", rows[6].C);
-
- Assert.Equal("Eric", rows[7].B);
- Assert.Equal("IT", rows[7].C);
- Assert.Equal("Keaton", rows[8].B);
- Assert.Equal("IT", rows[8].C);
-
- var demension = SheetHelper.GetFirstSheetDimensionRefValue(path);
- Assert.Equal("A1:C9", demension);
-
- //TODO:row can't contain xmlns
- //
- }
- }
+ using var table = new DataTable();
+ table.Columns.Add("CustomerID");
+ table.Columns.Add("CustomerName").Caption = "Name";
+ table.Columns.Add("CreditLimit").Caption = "Limit";
+ table.Rows.Add(1, "Jonathan", 23.44);
+ table.Rows.Add(2, "Bill", 56.87);
- {
- var templatePath = PathHelper.GetFile("xlsx/TestTemplateComplex.xlsx");
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
+ using var path = AutoDeletingPath.Create();
+ var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), table);
+ Assert.Single(rowsWritten);
+ Assert.Equal(2, rowsWritten[0]);
+
+ var rows = await _excelImporter.QueryAsync(path.ToString()).ToListAsync();
+ Assert.Equal("Name", rows[0].B);
+ Assert.Equal("Limit", rows[0].C);
+ }
- // 2. By Dictionary
- var value = new Dictionary
+ // Dynamic QueryAsync can't summary numeric cell value default, need to cast
+ [Fact]
+ public async Task Issue220()
+ {
+ var path = PathHelper.GetFile("xlsx/TestIssue220.xlsx");
+ var rows = _excelImporter.QueryAsync(path, hasHeaderRow: true);
+ var result = await rows
+ .GroupBy(s => s.PRT_ID)
+ .Select(g => new
{
- ["title"] = "FooCompany",
- ["managers"] = new[]
- {
- new {name="Jack",department="HR"},
- new {name="Loan",department="IT"}
- },
- ["employees"] = new[]
- {
- new {name="Wade",department="HR"},
- new {name="Felix",department="HR"},
- new {name="Eric",department="IT"},
- new {name="Keaton",department="IT"}
- }
- };
- await _excelTemplater.FillTemplateAsync(path, templatePath, value);
-
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal("FooCompany", rows[0].A);
- Assert.Equal("Jack", rows[2].B);
- Assert.Equal("HR", rows[2].C);
- Assert.Equal("Loan", rows[3].B);
- Assert.Equal("IT", rows[3].C);
-
- Assert.Equal("Wade", rows[5].B);
- Assert.Equal("HR", rows[5].C);
- Assert.Equal("Felix", rows[6].B);
- Assert.Equal("HR", rows[6].C);
-
- Assert.Equal("Eric", rows[7].B);
- Assert.Equal("IT", rows[7].C);
- Assert.Equal("Keaton", rows[8].B);
- Assert.Equal("IT", rows[8].C);
+ PRT_ID = g.Key,
+ Apr = g.Sum(d => (double?)d.Apr),
+ May = g.Sum(d => (double?)d.May),
+ Jun = g.Sum(d => (double?)d.Jun),
+ })
+ .ToListAsync();
+
+ Assert.Equal(91843.25, result[0].Jun);
+ Assert.Equal(50000.99, result[1].Jun);
+ }
- var demension = SheetHelper.GetFirstSheetDimensionRefValue(path);
- Assert.Equal("A1:C9", demension);
- }
+ // Custom yyyy-MM-dd format is not converted to datetime
+ [Fact]
+ public async Task Issue222()
+ {
+ var path = PathHelper.GetFile("xlsx/TestIssue222.xlsx");
+ var rows = await _excelImporter.QueryAsync(path).ToListAsync();
+ Assert.Equal(typeof(DateTime), rows[1].A.GetType());
+ Assert.Equal(new DateTime(2021, 4, 29), rows[1].A);
}
+ // ASP.NET Webform gridview datasource can't use miniexcel queryasdatatable
[Fact]
- public async Task Issue142_Query()
+ public async Task Issue223()
{
- var path = PathHelper.GetFile("xlsx/TestIssue142.xlsx");
- var pathCsv = PathHelper.GetFile("xlsx/TestIssue142.csv");
- {
- var rows = _excelImporter.QueryAsync(path).ToBlockingEnumerable().ToList();
- Assert.Equal(0, rows[0].MyProperty1);
- }
+ List> value =
+ [
+ new() { { "A", null }, { "B", null } },
+ new() { { "A", 123 }, { "B", new DateTime(2021, 1, 1) } },
+ new() { { "A", Guid.NewGuid() }, { "B", "HelloWorld" } }
+ ];
+ using var path = AutoDeletingPath.Create();
+ var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), value);
+ Assert.Single(rowsWritten);
+ Assert.Equal(3, rowsWritten[0]);
- {
- await Assert.ThrowsAsync(async () =>
- {
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable().ToList();
- });
- }
- {
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal("CustomColumnName", rows[0].MyProperty1);
- Assert.Null(rows[0].MyProperty7);
- Assert.Equal("MyProperty2", rows[0].MyProperty2);
- Assert.Equal("MyProperty103", rows[0].MyProperty3);
- Assert.Equal("MyProperty100", rows[0].MyProperty4);
- Assert.Equal("MyProperty102", rows[0].MyProperty5);
- Assert.Equal("MyProperty6", rows[0].MyProperty6);
- }
+ using var dt = await _excelImporter.QueryAsDataTableAsync(path.ToString());
+#pragma warning restore CS0618
+ var columns = dt.Columns;
+ Assert.Equal(typeof(object), columns[0].DataType);
+ Assert.Equal(typeof(object), columns[1].DataType);
- {
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal("CustomColumnName", rows[0].MyProperty1);
- Assert.Null(rows[0].MyProperty7);
- Assert.Equal("MyProperty2", rows[0].MyProperty2);
- Assert.Equal("MyProperty103", rows[0].MyProperty3);
- Assert.Equal("MyProperty100", rows[0].MyProperty4);
- Assert.Equal("MyProperty102", rows[0].MyProperty5);
- Assert.Equal("MyProperty6", rows[0].MyProperty6);
- }
+ Assert.Equal(123.0, dt.Rows[1]["A"]);
+ Assert.Equal("HelloWorld", dt.Rows[2]["B"]);
}
- private class Issue142VO
+ /// SaveAsByTemplate single column demension index error
+ [Fact]
+ public async Task Issue226()
{
- [MiniExcelColumnName("CustomColumnName")]
- public string MyProperty1 { get; set; } //index = 1
- [MiniExcelIgnore]
- public string MyProperty7 { get; set; } //index = null
- public string MyProperty2 { get; set; } //index = 3
- [MiniExcelColumnIndex(6)]
- public string MyProperty3 { get; set; } //index = 6
- [MiniExcelColumnIndex("A")] // equal column index 0
- public string MyProperty4 { get; set; }
- [MiniExcelColumnIndex(2)]
- public string MyProperty5 { get; set; } //index = 2
- public string MyProperty6 { get; set; } //index = 4
+ using var path = AutoDeletingPath.Create();
+ var templatePath = PathHelper.GetFile("xlsx/TestIssue226.xlsx");
+ await _excelTemplater.FillTemplateAsync(path.ToString(), templatePath, new { employees = new[] { new { name = "123" }, new { name = "123" } } });
+ Assert.Equal("A1:A3", SheetHelper.GetFirstSheetDimensionRefValue(path.ToString()));
}
- private class Issue142VoOverIndex
+ // Support Xlsm AutoCheck
+ [Fact]
+ public async Task Issue227()
{
- [MiniExcelColumnIndex("Z")]
- public int MyProperty1 { get; set; }
- }
+ var xlsmPath = AutoDeletingPath.Create(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsm");
+ Assert.Throws(() => _excelExporter.Export(xlsmPath.FilePath, new[] { new { V = "A1" }, new { V = "A2" } }));
- private class Issue142VoExcelColumnNameNotFound
- {
- [MiniExcelColumnIndex("B")]
- public int MyProperty1 { get; set; }
+ var path = PathHelper.GetFile("xlsx/TestIssue227.xlsm");
+ var rows1 = await _excelImporter.QueryAsync(path).ToListAsync();
+ Assert.Equal(100, rows1.Count);
+
+ Assert.Equal(Guid.Parse("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows1[0].ID);
+ Assert.Equal("Wade", rows1[0].Name);
+ Assert.Equal(DateTime.ParseExact("27/09/2020", "dd/MM/yyyy", CultureInfo.InvariantCulture), rows1[0].BoD);
+ Assert.Equal(36, rows1[0].Age);
+ Assert.False(rows1[0].VIP);
+ Assert.Equal(5019.12m, rows1[0].Points);
+ Assert.Equal(1, rows1[0].IgnoredProperty);
+
+
+ await using var stream = File.OpenRead(path);
+ var rows2 = await _excelImporter.QueryAsync(stream).ToListAsync();
+ Assert.Equal(100, rows2.Count);
+
+ Assert.Equal(Guid.Parse("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows2[0].ID);
+ Assert.Equal("Wade", rows2[0].Name);
+ Assert.Equal(DateTime.ParseExact("27/09/2020", "dd/MM/yyyy", CultureInfo.InvariantCulture), rows2[0].BoD);
+ Assert.Equal(36, rows2[0].Age);
+ Assert.False(rows2[0].VIP);
+ Assert.Equal(5019.12m, rows2[0].Points);
+ Assert.Equal(1, rows2[0].IgnoredProperty);
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/150
- ///
+ // QueryAsDataTable error "Cannot set Column to be null"
[Fact]
- public async Task Issue150()
+ public async Task Issue229()
{
- var path = PathHelper.GetTempFilePath();
-
- await Assert.ThrowsAnyAsync(async () => await _excelExporter.ExportAsync(path, new[] { 1, 2 }));
- File.Delete(path);
-
- await Assert.ThrowsAnyAsync(async () => await _excelExporter.ExportAsync(path, new[] { "1", "2" }));
- File.Delete(path);
-
- await Assert.ThrowsAnyAsync(async () => await _excelExporter.ExportAsync(path, new[] { '1', '2' }));
- File.Delete(path);
-
- await Assert.ThrowsAnyAsync(async () => await _excelExporter.ExportAsync(path, new[] { DateTime.Now }));
- File.Delete(path);
-
- await Assert.ThrowsAnyAsync(async () => await _excelExporter.ExportAsync(path, new[] { Guid.NewGuid() }));
- File.Delete(path);
+ var path = PathHelper.GetFile("xlsx/TestIssue229.xlsx");
+
+ using var dt = await _excelImporter.QueryAsDataTableAsync(path);
+
+ foreach (DataColumn column in dt.Columns)
+ {
+ var v = dt.Rows[3][column];
+ Assert.Equal(DBNull.Value, v);
+ }
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/157
- ///
+ // SaveAs By data reader error : 'Invalid attempt to call FieldCount when reader is closed'
[Fact]
- public async Task Issue157()
+ public async Task Issue230()
{
+ await using var conn = Db.GetConnection("Data Source=:memory:");
+ await conn.OpenAsync();
+ await using var cmd = conn.CreateCommand();
+ cmd.CommandText = "select 1 id union all select 2";
+
+ await using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection))
{
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
-
- List data =
- [
- new()
- {
- ID = new Guid("78de23d2-dcb6-bd3d-ec67-c112bbc322a2"),
- Name = "Wade",
- BoD = new DateTime(2020, 9, 27),
- Points = 5019.12m
- },
- new()
- {
- ID = new Guid("20d3bfce-27c3-ad3e-4f70-35c81c7e8e45"),
- Name = "Felix",
- BoD = new DateTime(2020, 10, 25),
- Points = 7028.46m
- },
- new()
- {
- ID = new Guid("52013bf0-9aeb-48e6-e5f5-e9500afb034f"),
- Name = "Phelan",
- BoD = new DateTime(2020, 10, 25),
- Points = 3835.7m,
- VIP = true
- },
- new()
- {
- ID = new Guid("3b97b87c-7afe-664f-1af5-6914d313ae25"),
- Name = "Samuel",
- BoD = new DateTime(2020, 6, 21),
- Points = 9351.71m
- },
- new()
+ while (await reader.ReadAsync())
+ {
+ for (int i = 0; i < reader.FieldCount; i++)
{
- ID = new Guid("9a989c43-d55f-5306-0d2f-0fbafae135bb"),
- Name = "Raymond",
- BoD = new DateTime(2021, 7, 12),
- Points = 8209.76m,
- VIP = true
+ var result = $"{reader.GetName(i)} , {reader.GetValue(i)}";
+ _output.WriteLine(result);
}
- ];
-
- var rowsWritten = await _excelExporter.ExportAsync(path, data);
- Assert.Single(rowsWritten);
- Assert.Equal(5, rowsWritten[0]);
-
- var q = await _excelImporter.QueryAsync(path, sheetName: "Sheet1").ToListAsync();
- var rows = q.ToList();
- Assert.Equal(6, rows.Count);
- Assert.Equal("Sheet1", (await _excelImporter.GetSheetNamesAsync(path))[0]);
-
- using var p = new ExcelPackage(new FileInfo(path));
- var ws = p.Workbook.Worksheets[0];
- Assert.Equal("Sheet1", ws.Name);
- Assert.Equal("Sheet1", p.Workbook.Worksheets["Sheet1"].Name);
+ }
}
+
+ await using var conn2 = Db.GetConnection("Data Source=:memory:");
+ await conn2.OpenAsync();
+ await using var cmd2 = conn2.CreateCommand();
+ cmd2.CommandText = "select 1 id union all select 2";
+
+ await using (var reader = await cmd2.ExecuteReaderAsync(CommandBehavior.CloseConnection))
{
- var path = PathHelper.GetFile("xlsx/TestIssue157.xlsx");
- {
- var q = _excelImporter.QueryAsync(path, sheetName: "Sheet1").ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal(6, rows.Count);
- Assert.Equal("Sheet1", (await _excelImporter.GetSheetNamesAsync(path))[0]);
- }
- using (var p = new ExcelPackage(new FileInfo(path)))
+ while (await reader.ReadAsync())
{
- var ws = p.Workbook.Worksheets.First();
- Assert.Equal("Sheet1", ws.Name);
- Assert.Equal("Sheet1", p.Workbook.Worksheets["Sheet1"].Name);
+ for (int i = 0; i < reader.FieldCount; i++)
+ {
+ var result = $"{reader.GetName(i)} , {reader.GetValue(i)}";
+ _output.WriteLine(result);
+ }
}
+ }
- {
- var q = _excelImporter.QueryAsync(path, sheetName: "Sheet1").ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal(5, rows.Count);
+ await using var conn3 = Db.GetConnection("Data Source=:memory:");
+ await conn3.OpenAsync();
+ await using var cmd3 = conn3.CreateCommand();
+ cmd3.CommandText = "select 1 id union all select 2";
+
+ await using (var reader = await cmd3.ExecuteReaderAsync(CommandBehavior.CloseConnection))
+ {
+ using var path = AutoDeletingPath.Create();
- Assert.Equal(Guid.Parse("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows[0].ID);
- Assert.Equal("Wade", rows[0].Name);
- Assert.Equal(DateTime.ParseExact("27/09/2020", "dd/MM/yyyy", CultureInfo.InvariantCulture), rows[0].BoD);
- Assert.False(rows[0].VIP);
- Assert.Equal(5019.12m, rows[0].Points);
- Assert.Equal(1, rows[0].IgnoredProperty);
- }
+ var rowsWritten = await _excelExporter.ExportAsync(path.ToString(), reader, printHeader: true);
+ Assert.Single(rowsWritten);
+ Assert.Equal(2, rowsWritten[0]);
+
+ var rows = await _excelImporter.QueryAsync(path.ToString(), true).ToListAsync();
+ Assert.Equal(1, rows[0].id);
+ Assert.Equal(2, rows[1].id);
}
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/149
- ///
+ // QueryAsDataTable A2=5.5 , A3=0.55/1.1 will case double type check error
[Fact]
- public async Task Issue149()
+ public async Task Issue233()
{
- char[] chars =
- [
- '\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007', '\u0008',
- '\u0009', //
- '\u000A', //
- '\u000B', '\u000C',
- '\u000D', //
- '\u000E', '\u000F', '\u0010', '\u0011', '\u0012', '\u0013', '\u0014', '\u0015', '\u0016',
- '\u0017', '\u0018', '\u0019', '\u001A', '\u001B', '\u001C', '\u001D', '\u001E', '\u001F', '\u007F'
- ];
- var strings = chars.Select(s => s.ToString()).ToArray();
+ var path = PathHelper.GetFile("xlsx/TestIssue233.xlsx");
+
+ using var dt = await _excelImporter.QueryAsDataTableAsync(path);
+ var rows = dt.Rows;
+
+ Assert.Equal(0.55, rows[0]["Size"]);
+ Assert.Equal("0.55/1.1", rows[1]["Size"]);
+ }
+
+ // SaveAs support multiple sheets
+ [Fact]
+ public async Task Issue234()
+ {
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
+ var users = new[]
{
- var path = PathHelper.GetFile("xlsx/TestIssue149.xlsx");
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.Select(s => (string)s.A).ToList();
-
- for (int i = 0; i < chars.Length; i++)
- {
- if (i == 13)
- continue;
-
- Assert.Equal(strings[i], rows[i]);
- }
- }
-
+ new { Name = "Jack", Age = 25 },
+ new { Name = "Mike", Age = 44 }
+ };
+ var department = new[]
{
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
+ new { ID = "01", Name = "HR" },
+ new { ID = "02", Name = "IT" }
+ };
+ var sheets = new Dictionary
+ {
+ ["users"] = users,
+ ["department"] = department
+ };
+ var rowsWritten = await _excelExporter.ExportAsync(path, sheets);
+
+ Assert.Equal(2, rowsWritten.Length);
+ Assert.Equal(2, rowsWritten[0]);
- var input = chars.Select(s => new { Test = s.ToString() });
- await _excelExporter.ExportAsync(path, input);
- var q = _excelImporter.QueryAsync(path, true).ToBlockingEnumerable();
+ var sheetNames = await _excelImporter.GetSheetNamesAsync(path);
+ Assert.Equal("users", sheetNames[0]);
+ Assert.Equal("department", sheetNames[1]);
- var rows = q.Select(s => (string)s.Test).ToList();
- for (int i = 0; i < chars.Length; i++)
- {
- _output.WriteLine($"{i}, {chars[i]}, {rows[i]}");
- if (i is 13 or 9 or 10)
- continue;
-
- Assert.Equal(strings[i], rows[i]);
- }
+ {
+ var rows = await _excelImporter.QueryAsync(path, true, sheetName: "users").ToListAsync();
+ Assert.Equal("Jack", rows[0].Name);
+ Assert.Equal(25, rows[0].Age);
+ Assert.Equal("Mike", rows[1].Name);
+ Assert.Equal(44, rows[1].Age);
}
-
{
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
-
- var input = chars.Select(s => new { Test = s.ToString() });
- await _excelExporter.ExportAsync(path, input);
-
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.Select(s => s.Test).ToList();
-
- for (int i = 0; i < chars.Length; i++)
- {
- _output.WriteLine($"{i}, {chars[i]}, {rows[i]}");
- if (i is 13 or 9 or 10)
- continue;
-
- Assert.Equal(strings[i], rows[i]);
- }
+ var rows = await _excelImporter.QueryAsync(path, true, sheetName: "department").ToListAsync();
+ Assert.Equal("01", rows[0].ID);
+ Assert.Equal("HR", rows[0].Name);
+ Assert.Equal("02", rows[1].ID);
+ Assert.Equal("IT", rows[1].Name);
}
}
- private class Issue149VO
- {
- public string Test { get; set; }
- }
-
- ///
- /// https://github.com/mini-software/MiniExcel/issues/153
- ///
+ /// Support SaveAs by DataSet
[Fact]
- public async Task Issue153()
+ public async Task Issue235()
{
- var path = PathHelper.GetFile("xlsx/TestIssue153.xlsx");
- var q = _excelImporter.QueryAsync(path, true).ToBlockingEnumerable();
- var rows = q.First() as IDictionary;
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
- Assert.Equal(
- [
- "序号", "代号", "新代号", "名称", "XXX", "部门名称", "单位", "ERP工时 (小时)A", "工时(秒) A/3600", "标准人工工时(秒)",
- "生产标准机器工时(秒)", "财务、标准机器工时(秒)", "更新日期", "产品机种", "备注", "最近一次修改前的标准工时(秒)", "最近一次修改前的标准机时(秒)", "备注1"
- ], rows?.Keys);
+ var users = new DataTable { TableName = "users" };
+ users.Columns.Add("Name", typeof(string));
+ users.Columns.Add("Age", typeof(int));
+ users.Rows.Add("Jack", 25);
+ users.Rows.Add("Mike", 44);
+
+ var departments = new DataTable { TableName = "departments" };
+ departments.Columns.Add("ID");
+ departments.Columns.Add("Name");
+ departments.Rows.Add("01", "HR");
+ departments.Rows.Add("02", "IT");
+
+ DataSet sheets = new();
+ sheets.Tables.Add(users);
+ sheets.Tables.Add(departments);
+
+ var rowsWritten = await _excelExporter.ExportAsync(path, sheets);
+ Assert.Equal(2, rowsWritten.Length);
+ Assert.Equal(2, rowsWritten[0]);
+
+ var sheetNames = await _excelImporter.GetSheetNamesAsync(path);
+ Assert.Equal("users", sheetNames[0]);
+ Assert.Equal("departments", sheetNames[1]);
+
+ var rows1 = await _excelImporter.QueryAsync(path, true, sheetName: "users").ToListAsync();
+ Assert.Equal("Jack", rows1[0].Name);
+ Assert.Equal(25, rows1[0].Age);
+ Assert.Equal("Mike", rows1[1].Name);
+ Assert.Equal(44, rows1[1].Age);
+
+ var rows2 = await _excelImporter.QueryAsync(path, true, sheetName: "departments").ToListAsync();
+ Assert.Equal("01", rows2[0].ID);
+ Assert.Equal("HR", rows2[0].Name);
+ Assert.Equal("02", rows2[1].ID);
+ Assert.Equal("IT", rows2[1].Name);
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/137
- ///
+ /// Support Custom Datetime format
[Fact]
- public void Issue137()
+ public async Task Issue241()
{
- var path = PathHelper.GetFile("xlsx/TestIssue137.xlsx");
- {
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.ToList();
- var first = rows[0] as IDictionary; // https://user-images.githubusercontent.com/12729184/113266322-ba06e400-9307-11eb-9521-d36abfda75cc.png
- Assert.Equal(["A", "B", "C", "D", "E", "F", "G", "H"], first?.Keys.ToArray());
- Assert.Equal(11, rows.Count);
+ var date1 = new DateTime(2021, 01, 04);
+ var date2 = new DateTime(2020, 04, 05);
- {
- var row = rows[0] as IDictionary;
- Assert.Equal("比例", row!["A"]);
- Assert.Equal("商品", row["B"]);
- Assert.Equal("滿倉口數", row["C"]);
- Assert.Equal(" ", row["D"]);
- Assert.Equal(" ", row["E"]);
- Assert.Equal(" ", row["F"]);
- Assert.Equal(0.0, row["G"]);
- Assert.Equal("1為港幣 0為台幣", row["H"]);
- }
- {
- var row = rows[1] as IDictionary;
- Assert.Equal(1.0, row!["A"]);
- Assert.Equal("MTX", row["B"]);
- Assert.Equal(10.0, row["C"]);
- Assert.Null(row["D"]);
- Assert.Null(row["E"]);
- Assert.Null(row["F"]);
- Assert.Null(row["G"]);
- Assert.Null(row["H"]);
- }
- {
- var row = rows[2] as IDictionary;
- Assert.Equal(0.95, row!["A"]);
- }
- }
+ Issue241Dto[] value =
+ [
+ new() { Name = "Jack", InDate = date1 },
+ new() { Name = "Henry", InDate = date2 }
+ ];
- // dynamic query with head
- {
- var q = _excelImporter.QueryAsync(path, true).ToBlockingEnumerable();
- var rows = q.ToList();
- var first = rows[0] as IDictionary; // https://user-images.githubusercontent.com/12729184/113266322-ba06e400-9307-11eb-9521-d36abfda75cc.png
- Assert.Equal(["比例", "商品", "滿倉口數", "0", "1為港幣 0為台幣"], first?.Keys.ToArray());
- Assert.Equal(10, rows.Count);
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
+ var rowsWritten = await _excelExporter.ExportAsync(path, value);
- {
- var row = rows[0] as IDictionary;
- Assert.Equal(1.0, row!["比例"]);
- Assert.Equal("MTX", row["商品"]);
- Assert.Equal(10.0, row["滿倉口數"]);
- Assert.Null(row["0"]);
- Assert.Null(row["1為港幣 0為台幣"]);
- }
-
- {
- var row = rows[1] as IDictionary;
- Assert.Equal(0.95, row!["比例"]);
- }
- }
+ Assert.Single(rowsWritten);
+ Assert.Equal(2, rowsWritten[0]);
- {
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal(10, rows.Count);
-
- {
- var row = rows[0];
- Assert.Equal(1, row.比例);
- Assert.Equal("MTX", row.商品);
- Assert.Equal(10, row.滿倉口數);
- }
+ using var package = new ExcelPackage(path);
+ var cells = package.Workbook.Worksheets[0].Cells;
- {
- var row = rows[1];
- Assert.Equal(0.95, row.比例);
- }
- }
+ Assert.Equal(date1, DateTime.FromOADate((double)cells["B2"].Value));
+ Assert.Equal("01 04, 2021", cells["B2"].Text);
+ Assert.Equal(date2, DateTime.FromOADate((double)cells["B3"].Value));
+ Assert.Equal("04 05, 2020", cells["B3"].Text);
}
- private class Issue137ExcelRow
+ /// No error exception throw when reading xls file
+ [Fact]
+ public async Task Issue242()
{
- public double? 比例 { get; set; }
- public string 商品 { get; set; }
- public int? 滿倉口數 { get; set; }
- }
+ var path = PathHelper.GetFile("xls/TestIssue242.xls");
+ await Assert.ThrowsAsync(async () => _ = await _excelImporter.QueryAsync(path).ToListAsync());
+ await using var stream = File.OpenRead(path);
+ await Assert.ThrowsAsync(async () => _ = await _excelImporter.QueryAsync(stream).ToListAsync());
+ }
- ///
- /// https://github.com/mini-software/MiniExcel/issues/138
- ///
+ // SaveAsByTemplate support DateTime custom format
[Fact]
- public void Issue138()
+ public async Task Issue255()
{
- var path = PathHelper.GetFile("xlsx/TestIssue138.xlsx");
+ var dt1 = new DateTime(2021, 01, 01);
+ var dt2 = new DateTime(2022, 01, 01);
+
+ //template
{
- var q = _excelImporter.QueryAsync(path, true).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal(6, rows.Count);
-
- foreach (var index in new[] { 0, 2, 5 })
+ var templatePath = PathHelper.GetFile("xlsx/TestsIssue255_Template.xlsx");
+ await using var ms = new MemoryStream();
+ var value = new
{
- Assert.Equal(1, rows[index].實單每日損益);
- Assert.Equal(2, rows[index].程式每日損益);
- Assert.Equal("測試商品1", rows[index].商品);
- Assert.Equal(111.11, rows[index].滿倉口數);
- Assert.Equal(111.11, rows[index].波段);
- Assert.Equal(111.11, rows[index].當沖);
- }
+ Issue255DTO = new[] { new Issue255DTO { Time = dt1, Time2 = dt2 } }
+ };
+
+ await _excelTemplater.FillTemplateAsync(ms, templatePath, value);
- foreach (var index in new[] { 1, 3, 4 })
- {
- Assert.Null(rows[index].實單每日損益);
- Assert.Null(rows[index].程式每日損益);
- Assert.Null(rows[index].商品);
- Assert.Null(rows[index].滿倉口數);
- Assert.Null(rows[index].波段);
- Assert.Null(rows[index].當沖);
- }
+ ms.Seek(0, SeekOrigin.Begin);
+ using var package = new ExcelPackage(ms);
+ var cells = package.Workbook.Worksheets[0].Cells;
+
+ Assert.Equal("2021", cells["A2"].Text);
+ Assert.Equal("2022", cells["B2"].Text);
}
+ //export
{
+ await using var ms = new MemoryStream();
+ Issue255DTO[] value =
+ [
+ new() { Time = dt1, Time2 = dt2 }
+ ];
- var q = _excelImporter.QueryAsync(path).ToBlockingEnumerable();
- var rows = q.ToList();
- Assert.Equal(6, rows.Count);
- Assert.Equal(new DateTime(2021, 3, 1), rows[0].Date);
+ var rowsWritten = await _excelExporter.ExportAsync(ms, value);
+ Assert.Single(rowsWritten);
+ Assert.Equal(1, rowsWritten[0]);
- foreach (var index in new[] { 0, 2, 5 })
- {
- Assert.Equal(1, rows[index].實單每日損益);
- Assert.Equal(2, rows[index].程式每日損益);
- Assert.Equal("測試商品1", rows[index].商品);
- Assert.Equal(111.11, rows[index].滿倉口數);
- Assert.Equal(111.11, rows[index].波段);
- Assert.Equal(111.11, rows[index].當沖);
- }
+ ms.Seek(0, SeekOrigin.Begin);
+ using var package = new ExcelPackage(ms);
- foreach (var index in new[] { 1, 3, 4 })
- {
- Assert.Null(rows[index].實單每日損益);
- Assert.Null(rows[index].程式每日損益);
- Assert.Null(rows[index].商品);
- Assert.Null(rows[index].滿倉口數);
- Assert.Null(rows[index].波段);
- Assert.Null(rows[index].當沖);
- }
+ var cells = package.Workbook.Worksheets[0].Cells;
+ Assert.Equal(dt1, DateTime.FromOADate((double)cells["A2"].Value));
+ Assert.Equal("2021", cells["A2"].Text);
+ Assert.Equal(dt2, DateTime.FromOADate((double)cells["B2"].Value));
+ Assert.Equal("2022", cells["B2"].Text);
}
}
- private class Issue138ExcelRow
+ // Dynamic QueryAsync custom format not using mapping format
+ [Fact]
+ public async Task Issue256()
{
- public DateTime? Date { get; set; }
- public int? 實單每日損益 { get; set; }
- public int? 程式每日損益 { get; set; }
- public string 商品 { get; set; }
- public double? 滿倉口數 { get; set; }
- public double? 波段 { get; set; }
- public double? 當沖 { get; set; }
+ var path = PathHelper.GetFile("xlsx/TestIssue256.xlsx");
+ var q = await _excelImporter.QueryAsync(path).ToListAsync();
+ var rows = q.ToList();
+
+ Assert.Equal(new DateTime(2003, 4, 16), rows[1].A);
+ Assert.Equal(new DateTime(2004, 4, 16), rows[1].B);
}
[Fact]
@@ -1495,18 +1201,6 @@ public async Task Issue520()
Assert.Equal(300.0, cells["C2"].Value);
}
- class Issue520Dto(long l1, DateTime dt, long l2)
- {
- [MiniExcelColumn(Format = "R$ #,##0.00", Width = 15)]
- public long PaymentValue { get; set; } = l1;
-
- [MiniExcelColumn(Format = "dd/MM/yyyy", Width = 15)]
- public DateTime PaymentDate { get; set; } = dt;
-
- [MiniExcelColumn(Format = "R$ #,##0.00", Width = 15)]
- public long ValueToSettle { get; set; } = l2;
- }
-
[Fact]
public async Task TestIssue627()
{
@@ -1531,13 +1225,43 @@ public async Task TestIssue627()
Assert.Equal("@", cell.Style.Numberformat.Format);
}
+ [Fact]
+ public async Task TestIssue658()
+ {
+ static IEnumerable GetTestData()
+ {
+ yield return new() { FirstName = "Unit", LastName = "Test" };
+ yield return new() { FirstName = "Unit1", LastName = "Test1" };
+ yield return new() { FirstName = "Unit2", LastName = "Test2" };
+ }
+
+ using var memoryStream = new MemoryStream();
+ var testData = GetTestData().ToList();
+ await _excelExporter.ExportAsync(memoryStream, testData, configuration: new OpenXmlConfiguration
+ {
+ FastMode = true,
+ });
+
+ memoryStream.Position = 0;
+ var queryData = await _excelImporter.QueryAsync(memoryStream).ToListAsync();
+ Assert.Equal(testData.Count, queryData.Count);
+
+ var i = 0;
+ foreach (var data in testData)
+ {
+ Assert.Equal(data.FirstName, queryData[i].FirstName);
+ Assert.Equal(data.LastName, queryData[i].LastName);
+ i++;
+ }
+ }
+
[Fact]
public async Task TestIssue951()
{
var templatePath = PathHelper.GetFile("xlsx/TestTemplateEasyFill.xlsx");
using var path = AutoDeletingPath.Create();
- var value = new Issue951
+ var value = new Issue951Dto
{
Name = "Jack",
CreateDate = new DateTime(2021, 01, 01),
@@ -1548,14 +1272,4 @@ public async Task TestIssue951()
// must not throw because of indexer
await _excelTemplater.FillTemplateAsync(path.ToString(), templatePath, value);
}
-
- class Issue951
- {
- public string? Name { get; set; }
- public DateTime CreateDate { get; set; }
- public bool VIP { get; set; }
- public double Points { get; set; }
-
- public object this[string test] => new();
- }
}
diff --git a/tests/MiniExcel.OpenXml.Tests/MiniExcelIssueTests.cs b/tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGithubIssuesTests.cs
similarity index 66%
rename from tests/MiniExcel.OpenXml.Tests/MiniExcelIssueTests.cs
rename to tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGithubIssuesTests.cs
index ecb99e1f..529531ab 100644
--- a/tests/MiniExcel.OpenXml.Tests/MiniExcelIssueTests.cs
+++ b/tests/MiniExcel.OpenXml.Tests/Issues/MiniExcelGithubIssuesTests.cs
@@ -1,5 +1,4 @@
-using System.ComponentModel;
-using System.Text.RegularExpressions;
+using System.Text.RegularExpressions;
using MiniExcelLib.Core.Enums;
using MiniExcelLib.Core.Exceptions;
using MiniExcelLib.OpenXml.Picture;
@@ -8,9 +7,9 @@
using NPOI.XSSF.UserModel;
using LicenseContext = OfficeOpenXml.LicenseContext;
-namespace MiniExcelLib.OpenXml.Tests;
+namespace MiniExcelLib.OpenXml.Tests.Issues;
-public class MiniExcelIssueTests(ITestOutputHelper output)
+public class MiniExcelGithubIssuesTests(ITestOutputHelper output)
{
private readonly ITestOutputHelper _output = output;
@@ -18,134 +17,12 @@ public class MiniExcelIssueTests(ITestOutputHelper output)
private readonly OpenXmlExporter _excelExporter = MiniExcel.Exporters.GetOpenXmlExporter();
private readonly OpenXmlTemplater _excelTemplater = MiniExcel.Templaters.GetOpenXmlTemplater();
- static MiniExcelIssueTests()
+ static MiniExcelGithubIssuesTests()
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/549
- ///
- [Fact]
- public void TestIssue549()
- {
- var data = new[]
- {
- new{ id = 1, name = "jack" },
- new{ id = 2, name = "mike" }
- };
-
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
-
- _excelExporter.Export(path, data);
- var rows = _excelImporter.Query(path, true).ToList();
- {
- using var stream = new FileStream(path, FileMode.Open, FileAccess.Read);
- using var workbook = new XSSFWorkbook(stream);
-
- var sheet = workbook.GetSheetAt(0);
- var a2 = sheet.GetRow(1).GetCell(0);
- var b2 = sheet.GetRow(1).GetCell(1);
- Assert.Equal((string)rows[0].id.ToString(), a2.NumericCellValue.ToString(CultureInfo.InvariantCulture));
- Assert.Equal((string)rows[0].name.ToString(), b2.StringCellValue);
- }
- }
-
- [Fact]
- public void TestIssue24020201()
- {
- using var path = AutoDeletingPath.Create();
- var templatePath = PathHelper.GetFile("xlsx/TestIssue24020201.xlsx");
- var data = new Dictionary
- {
- ["title"] = "This's title",
- ["B"] = new List>
- {
- new() { { "specialMark", 1 } },
- new() { { "specialMark", 2 } },
- new() { { "specialMark", 3 } },
- }
- };
- _excelTemplater.FillTemplate(path.ToString(), templatePath, data);
- }
-
- [Fact]
- public void TestIssue553()
- {
- using var path = AutoDeletingPath.Create();
- var templatePath = PathHelper.GetFile("xlsx/TestIssue553.xlsx");
- var data = new
- {
- B = new[]
- {
- new{ ITM=1 },
- new{ ITM=2 },
- new{ ITM=3 }
- }
- };
- _excelTemplater.FillTemplate(path.ToString(), templatePath, data);
-
- var rows = _excelImporter.Query(path.ToString()).ToList();
- Assert.Equal(rows[2].A, 1);
- Assert.Equal(rows[3].A, 2);
- Assert.Equal(rows[4].A, 3);
- }
-
- [Fact]
- public void TestIssue289()
- {
- using var path = AutoDeletingPath.Create();
- DescriptionEnumDto[] value =
- [
- new() { Name="0001", UserType=DescriptionEnum.V1 },
- new() { Name="0002", UserType=DescriptionEnum.V2 },
- new() { Name="0003", UserType=DescriptionEnum.V3 }
- ];
- _excelExporter.Export(path.ToString(), value);
-
- var rows = _excelImporter.Query(path.ToString()).ToList();
-
- Assert.Equal(DescriptionEnum.V1, rows[0].UserType);
- Assert.Equal(DescriptionEnum.V2, rows[1].UserType);
- Assert.Equal(DescriptionEnum.V3, rows[2].UserType);
- }
-
- private class DescriptionEnumDto
- {
- public string Name { get; set; }
- public DescriptionEnum UserType { get; set; }
- }
-
- private enum DescriptionEnum
- {
- [Description("General User")] V1,
- [Description("General Administrator")] V2,
- [Description("Super Administrator")] V3
- }
-
- ///
- /// Exception : MiniExcelLibs.Core.Exceptions.ExcelInvalidCastException: 'ColumnName : Date, CellRow : 2, Value : 2021-01-31 10:03:00 +08:00, it can't cast to DateTimeOffset type.'
- ///
- [Fact]
- public void TestIssue430()
- {
- using var path = AutoDeletingPath.Create();
- TestIssue430Dto[] value =
- [
- new() { Date = new DateTimeOffset(2021, 1, 31, 10, 3, 0, TimeSpan.FromHours(5)) }
- ];
- _excelExporter.Export(path.ToString(), value);
-
- var testValue = _excelImporter.Query(path.ToString(), hasHeaderRow: true).First();
- Assert.Equal("2021-01-31 10:03:00", testValue.Date.ToString("yyyy-MM-dd HH:mm:ss"));
- }
-
- private class TestIssue430Dto
- {
- [MiniExcelFormat("yyyy-MM-dd HH:mm:ss")]
- public DateTimeOffset Date { get; set; }
- }
+ private static bool IsDateFormatString(string formatCode) => DateTimeHelper.IsDateTimeFormat(formatCode);
[Fact]
public void TestIssue_DataReaderSupportDimension()
@@ -167,1247 +44,1201 @@ public void TestIssue_DataReaderSupportDimension()
Assert.Contains("", xml);
}
- ///
- /// [ · Issue #413 · MiniExcel/MiniExcel]
- /// (https://github.com/MiniExcel/MiniExcel/issues/413)
- ///
[Fact]
- public void TestIssue413()
+ public void Issue87()
{
+ var templatePath = PathHelper.GetFile("xlsx/TestTemplateCenterEmpty.xlsx");
using var path = AutoDeletingPath.Create();
var value = new
{
- list = new List>
- {
- new() { { "id","001"},{ "time",new DateTime(2022,12,25)} },
- new() { { "id","002"},{ "time",new DateTime(2022,9,23)} },
- }
+ Tests = Enumerable.Range(1, 5).Select((_, i) => new { test1 = i, test2 = i })
};
- var templatePath = PathHelper.GetFile("xlsx/TestIssue413.xlsx");
- _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
- var rows = _excelImporter.Query(path.ToString()).ToList();
- Assert.Equal("2022-12-25 00:00:00", rows[1].B);
- Assert.Equal("2022-09-23 00:00:00", rows[2].B);
+ var rows = _excelImporter.Query(templatePath).ToList();
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
}
- ///
- /// [SaveAs Support empty sharedstring · Issue #405 · MiniExcel/MiniExcel]
- /// (https://github.com/MiniExcel/MiniExcel/issues/405)
- ///
[Fact]
- public void TestIssue405()
+ public void TestIssue117()
{
- using var path = AutoDeletingPath.Create();
- var value = new[] { new { id = 1, name = "test" } };
- _excelExporter.Export(path.ToString(), value);
+ var cacheFull = new SharedStringsDiskCache(Path.GetTempPath());
+ for (int i = 0; i < 100; i++)
+ {
+ cacheFull[i] = i.ToString();
+ }
+ for (int i = 0; i < 100; i++)
+ {
+ Assert.Equal(i.ToString(), cacheFull[i]);
+ }
+ Assert.Equal(100, cacheFull.Count);
- var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/sharedStrings.xml");
- Assert.StartsWith("> value =
- [
- new()
- {
- ["Id"] = 1,
- ["Name"] = "Jack",
- ["Date"] = new DateTime(2022, 04, 12),
- ["Point"] = 123.456
- }
- ];
- _excelExporter.Export(path.ToString(), value, configuration: config);
- var rows = _excelImporter.Query(path.ToString()).ToList();
- Assert.Equal("Date", rows[0].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);
- Assert.Equal(123.456, rows[1].C);
+ var path1 = PathHelper.GetFile("xlsx/TestIssue122.xlsx");
+ var rows1 = _excelImporter.Query(path1, hasHeaderRow: true, configuration: config).ToList();
+ Assert.Equal("HR", rows1[0].Department);
+ Assert.Equal("HR", rows1[1].Department);
+ Assert.Equal("HR", rows1[2].Department);
+ Assert.Equal("IT", rows1[3].Department);
+ Assert.Equal("IT", rows1[4].Department);
+ Assert.Equal("IT", rows1[5].Department);
+
+ var path2 = PathHelper.GetFile("xlsx/TestIssue122_2.xlsx");
+ var rows2 = _excelImporter.Query(path2, hasHeaderRow: true, configuration: config).ToList();
+ Assert.Equal("V1", rows2[2].Test1);
+ Assert.Equal("V2", rows2[5].Test2);
+ Assert.Equal("V3", rows2[1].Test3);
+ Assert.Equal("V4", rows2[2].Test4);
+ Assert.Equal("V5", rows2[3].Test5);
+ Assert.Equal("V6", rows2[5].Test5);
}
[Fact]
- public void TestIssue369()
+ public void Issue132()
{
- var config = new OpenXmlConfiguration
{
- DynamicColumns =
- [
- new DynamicExcelColumn("id") { Ignore=true },
- new DynamicExcelColumn("name") { Index=1, Width=10 },
- new DynamicExcelColumn("createdate") { Index=0, Format="yyyy-MM-dd", Width=15 },
- new DynamicExcelColumn("point") { Index=2, Name="Account Point" }
- ]
- };
- using var path = AutoDeletingPath.Create();
- var value = new[] { new { id = 1, name = "Jack", createdate = new DateTime(2022, 04, 12), point = 123.456 } };
- _excelExporter.Export(path.ToString(), value, configuration: config);
+ using var path = AutoDeletingPath.Create();
+ var value = new[] {
+ new { name = "Jack", Age = 25, InDate = new DateTime(2021,01,03)},
+ new { name = "Henry", Age = 36, InDate = new DateTime(2020,05,03)},
+ };
- var rows = _excelImporter.Query(path.ToString()).ToList();
- Assert.Equal("createdate", rows[0].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);
- Assert.Equal(123.456, rows[1].C);
- }
+ _excelExporter.Export(path.ToString(), value);
+ }
- [Fact]
- public void TestIssueI4ZYUU()
- {
- using var path = AutoDeletingPath.Create();
-
- var dt = new DateTime(2022, 10, 15);
- TestIssueI4ZYUUDto[] value = [new() { MyProperty = "1", MyProperty2 = dt }];
- _excelExporter.Export(path.ToString(), value);
+ {
+ using var path = AutoDeletingPath.Create();
+ var value = new[]
+ {
+ new { name = "Jack", Age = 25, InDate = new DateTime(2021,01,03)},
+ new { name = "Henry", Age = 36, InDate = new DateTime(2020,05,03)},
+ };
+ var config = new OpenXmlConfiguration
+ {
+ TableStyles = TableStyles.None
+ };
+ _excelExporter.Export(path.ToString(), value, configuration: config);
+ }
- using var workbook = new ClosedXML.Excel.XLWorkbook(path.ToString());
- var ws = workbook.Worksheet(1);
+ {
+ using var path = AutoDeletingPath.Create();
- Assert.Equal(dt, ws.Cell(2, "B").Value.GetDateTime());
- Assert.Equal("2022-10", ws.Cell(2, "B").GetFormattedString());
- Assert.True(ws.Column("A").Width > 0);
- Assert.True(ws.Column("B").Width > 0);
- }
+ var dt = new DataTable();
+ dt.Columns.Add("Name");
+ dt.Columns.Add("Age");
+ dt.Columns.Add("Date");
- private class TestIssueI4ZYUUDto
- {
- [MiniExcelColumn(Name = "ID", Index = 0)]
- public string MyProperty { get; set; }
- [MiniExcelColumn(Name = "CreateDate", Index = 1, Format = "yyyy-MM", Width = 100)]
- public DateTime MyProperty2 { get; set; }
- }
+ dt.Rows.Add("Jack", 25, new DateTime(2021, 01, 03));
+ dt.Rows.Add("Henry", 36, new DateTime(2021, 01, 03));
- [Fact]
- public void TestIssue360()
- {
- var path = PathHelper.GetFile("xlsx/NotDuplicateSharedStrings_10x100.xlsx");
- var config = new OpenXmlConfiguration { SharedStringCacheSize = 1 };
- var sheets = _excelImporter.GetSheetNames(path);
- foreach (var sheetName in sheets)
- {
- var dt = _excelImporter.QueryAsDataTable(path, hasHeaderRow: true, sheetName: sheetName, configuration: config);
+ _excelExporter.Export(path.ToString(), dt);
}
}
[Fact]
- public void TestIssue117()
+ public void TestIssues133()
{
- var cacheFull = new SharedStringsDiskCache(Path.GetTempPath());
- for (int i = 0; i < 100; i++)
- {
- cacheFull[i] = i.ToString();
- }
- for (int i = 0; i < 100; i++)
{
- Assert.Equal(i.ToString(), cacheFull[i]);
- }
- Assert.Equal(100, cacheFull.Count);
+ using var path = AutoDeletingPath.Create();
- var cacheEmpty = new SharedStringsDiskCache(Path.GetTempPath());
- Assert.Empty(cacheEmpty);
- }
-
- [Fact]
- public void TestIssue352()
- {
- {
- using var table = new DataTable();
- table.Columns.Add("id", typeof(int));
- table.Columns.Add("name", typeof(string));
- table.Rows.Add(1, "Jack");
- table.Rows.Add(2, "Mike");
+ var value = new DataTable();
+ value.Columns.Add("Id");
+ value.Columns.Add("Name");
+ _excelExporter.Export(path.ToString(), value);
+ var rows = _excelImporter.Query(path.ToString()).ToList();
- using var path = AutoDeletingPath.Create();
- var reader = table.CreateDataReader();
- _excelExporter.Export(path.ToString(), reader);
- var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- var cnt = Regex.Matches(xml, "").Count;
+ Assert.Equal("Id", rows[0].A);
+ Assert.Equal("Name", rows[0].B);
+ Assert.Single(rows);
+ Assert.Equal("A1:B1", SheetHelper.GetFirstSheetDimensionRefValue(path.ToString()));
}
- {
- using var table = new DataTable();
- table.Columns.Add("id", typeof(int));
- table.Columns.Add("name", typeof(string));
- table.Rows.Add(1, "Jack");
- table.Rows.Add(2, "Mike");
- using var path = AutoDeletingPath.Create();
- var reader = table.CreateDataReader();
- _excelExporter.Export(path.ToString(), reader, false);
- var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- var cnt = Regex.Matches(xml, "").Count;
- }
{
- using var table = new DataTable();
- table.Columns.Add("id", typeof(int));
- table.Columns.Add("name", typeof(string));
-
using var path = AutoDeletingPath.Create();
- var reader = table.CreateDataReader();
- _excelExporter.Export(path.ToString(), reader);
- var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- var cnt = Regex.Matches(xml, "").Count;
+
+ var value = Array.Empty();
+ _excelExporter.Export(path.ToString(), value);
+ var rows = _excelImporter.Query(path.ToString()).ToList();
+
+ Assert.Equal("Id", rows[0].A);
+ Assert.Equal("Name", rows[0].B);
+ Assert.Single(rows);
+ Assert.Equal("A1:B1", SheetHelper.GetFirstSheetDimensionRefValue(path.ToString()));
}
}
- [Theory]
- [InlineData(true, 1)]
- [InlineData(false, 0)]
- public void TestIssue401(bool autoFilter, int count)
+ [Fact]
+ public void Issue137()
{
- // Test for DataTable
+ var path = PathHelper.GetFile("xlsx/TestIssue137.xlsx");
{
- var table = new DataTable();
+ var rows = _excelImporter.Query(path).ToList();
+ var first = (IDictionary)rows[0]; // https://user-images.githubusercontent.com/12729184/113266322-ba06e400-9307-11eb-9521-d36abfda75cc.png
+ Assert.Equal(["A", "B", "C", "D", "E", "F", "G", "H"], first.Keys.ToArray());
+ Assert.Equal(11, rows.Count);
{
- table.Columns.Add("id", typeof(int));
- table.Columns.Add("name", typeof(string));
- table.Rows.Add(1, "Jack");
- table.Rows.Add(2, "Mike");
+ var row = rows[0] as IDictionary;
+ Assert.Equal("比例", row!["A"]);
+ Assert.Equal("商品", row["B"]);
+ Assert.Equal("滿倉口數", row["C"]);
+ Assert.Equal(" ", row["D"]);
+ Assert.Equal(" ", row["E"]);
+ Assert.Equal(" ", row["F"]);
+ Assert.Equal(0.0, row["G"]);
+ Assert.Equal("1為港幣 0為台幣", row["H"]);
}
-
- var reader = table.CreateDataReader();
- using var path = AutoDeletingPath.Create();
- var config = new OpenXmlConfiguration { AutoFilter = autoFilter };
- _excelExporter.Export(path.ToString(), reader, configuration: config);
-
- var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- var cnt = Regex.Matches(xml, "").Count;
- Assert.Equal(count, cnt);
- }
- {
- var table = new DataTable();
{
- table.Columns.Add("id", typeof(int));
- table.Columns.Add("name", typeof(string));
- table.Rows.Add(1, "Jack");
- table.Rows.Add(2, "Mike");
+ var row = rows[1] as IDictionary;
+ Assert.Equal(1.0, row!["A"]);
+ Assert.Equal("MTX", row["B"]);
+ Assert.Equal(10.0, row["C"]);
+ Assert.Null(row["D"]);
+ Assert.Null(row["E"]);
+ Assert.Null(row["F"]);
+ Assert.Null(row["G"]);
+ Assert.Null(row["H"]);
}
- var reader = table.CreateDataReader();
- using var path = AutoDeletingPath.Create();
- var config = new OpenXmlConfiguration { AutoFilter = autoFilter };
- _excelExporter.Export(path.ToString(), reader, false, configuration: config);
-
- var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- var cnt = Regex.Matches(xml, "").Count;
- Assert.Equal(count, cnt);
- }
- {
- var table = new DataTable();
{
- table.Columns.Add("id", typeof(int));
- table.Columns.Add("name", typeof(string));
+ var row = rows[2] as IDictionary;
+ Assert.Equal(0.95, row!["A"]);
}
- var reader = table.CreateDataReader();
- using var path = AutoDeletingPath.Create();
- var config = new OpenXmlConfiguration { AutoFilter = autoFilter };
- _excelExporter.Export(path.ToString(), reader, configuration: config);
-
- var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- var cnt = Regex.Matches(xml, "").Count;
- Assert.Equal(count, cnt);
}
- // Test for DataReader
+ // dynamic query with head
{
- using var path = AutoDeletingPath.Create();
- var config = new OpenXmlConfiguration { AutoFilter = autoFilter };
- using (var connection = Db.GetConnection("Data Source=:memory:"))
+ var rows = _excelImporter.Query(path, true).ToList();
+ var first = (IDictionary)rows[0]; //
+ Assert.Equal(["比例", "商品", "滿倉口數", "0", "1為港幣 0為台幣"], first.Keys.ToArray());
+ Assert.Equal(10, rows.Count);
{
- connection.Open();
-
- using var command = connection.CreateCommand();
- command.CommandText =
- """
- SELECT
- 'MiniExcel' as Column1,
- 1 as Column2
-
- UNION ALL
- SELECT 'Github', 2
- """;
-
- using var reader = command.ExecuteReader();
- _excelExporter.Export(path.ToString(), reader, configuration: config);
+ var row = rows[0] as IDictionary;
+ Assert.Equal(1.0, row!["比例"]);
+ Assert.Equal("MTX", row["商品"]);
+ Assert.Equal(10.0, row["滿倉口數"]);
+ Assert.Null(row["0"]);
+ Assert.Null(row["1為港幣 0為台幣"]);
}
- var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- var cnt = Regex.Matches(xml, "autoFilter").Count;
- Assert.Equal(count, cnt);
- }
-
- {
- var xlsxPath = PathHelper.GetFile("xlsx/Test5x2.xlsx");
- using var tempSqlitePath = AutoDeletingPath.Create(Path.GetTempPath(), $"{Guid.NewGuid()}.db");
- var connectionString = $"Data Source={tempSqlitePath};Version=3;";
-
- using (var connection = new SQLiteConnection(connectionString))
{
- connection.Execute("create table T (A varchar(20),B varchar(20));");
+ var row = rows[1] as IDictionary;
+ Assert.Equal(0.95, row!["比例"]);
}
+ }
- using (var connection = new SQLiteConnection(connectionString))
+ {
+ var rows = _excelImporter.Query(path).ToList();
+ Assert.Equal(10, rows.Count);
{
- connection.Open();
- using (var transaction = connection.BeginTransaction())
- using (var stream = File.OpenRead(xlsxPath))
- {
- var rows = _excelImporter.Query(stream);
- foreach (var row in rows)
- connection.Execute(
- "insert into T (A,B) values (@A,@B)",
- new { row.A, row.B },
- transaction: transaction);
-
- transaction.Commit();
- }
+ var row = rows[0];
+ Assert.Equal(1, row.比例);
+ Assert.Equal("MTX", row.商品);
+ Assert.Equal(10, row.滿倉口數);
}
- using var path = AutoDeletingPath.Create();
- var config = new OpenXmlConfiguration { AutoFilter = autoFilter };
- using (var connection = new SQLiteConnection(connectionString))
{
- using var command = new SQLiteCommand("select * from T", connection);
- connection.Open();
- using var reader = command.ExecuteReader();
- _excelExporter.Export(path.ToString(), reader, configuration: config);
+ var row = rows[1];
+ Assert.Equal(0.95, row.比例);
}
-
- var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- var cnt = Regex.Matches(xml, "autoFilter").Count;
- Assert.Equal(count, cnt);
}
}
[Fact]
- public async Task TestIssue307()
+ public void Issue138()
{
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
- var value = new[] { new { id = 1, name = "Jack" } };
+ var path = PathHelper.GetFile("xlsx/TestIssue138.xlsx");
+ var rows1 = _excelImporter.Query(path, true).ToList();
+ Assert.Equal(6, rows1.Count);
- await _excelExporter.ExportAsync(path, value);
- Assert.Throws(() => _excelExporter.Export(path, value));
+ foreach (var index in new[] { 0, 2, 5 })
+ {
+ Assert.Equal(1, rows1[index].實單每日損益);
+ Assert.Equal(2, rows1[index].程式每日損益);
+ Assert.Equal("測試商品1", rows1[index].商品);
+ Assert.Equal(111.11, rows1[index].滿倉口數);
+ Assert.Equal(111.11, rows1[index].波段);
+ Assert.Equal(111.11, rows1[index].當沖);
+ }
- await _excelExporter.ExportAsync(path, value, overwriteFile: true);
- await Assert.ThrowsAsync(async () => await _excelExporter.ExportAsync(path, value));
- await _excelExporter.ExportAsync(path, value, overwriteFile: true);
- }
+ foreach (var index in new[] { 1, 3, 4 })
+ {
+ Assert.Null(rows1[index].實單每日損益);
+ Assert.Null(rows1[index].程式每日損益);
+ Assert.Null(rows1[index].商品);
+ Assert.Null(rows1[index].滿倉口數);
+ Assert.Null(rows1[index].波段);
+ Assert.Null(rows1[index].當沖);
+ }
- [Fact]
- public void TestIssue310()
- {
- using var path = AutoDeletingPath.Create();
- var value = new[] { new TestIssue310Dto { V1 = null }, new TestIssue310Dto { V1 = 2 } };
- _excelExporter.Export(path.ToString(), value);
- var rows = _excelImporter.Query(path.ToString()).ToList();
- }
+ var rows2 = _excelImporter.Query(path).ToList();
+ Assert.Equal(6, rows2.Count);
+ Assert.Equal(new DateTime(2021, 3, 1), rows2[0].Date);
- [Fact]
- public void TestIssue310Fix497()
- {
- using var path = AutoDeletingPath.Create();
- var value = new[]
+ foreach (var index in new[] { 0, 2, 5 })
{
- new TestIssue310Dto { V1 = null },
- new TestIssue310Dto { V1 = 2 }
- };
- _excelExporter.Export(path.ToString(), value, configuration: new OpenXmlConfiguration { EnableWriteNullValueCell = false });
- var rows = _excelImporter.Query(path.ToString()).ToList();
- }
+ Assert.Equal(1, rows2[index].實單每日損益);
+ Assert.Equal(2, rows2[index].程式每日損益);
+ Assert.Equal("測試商品1", rows2[index].商品);
+ Assert.Equal(111.11, rows2[index].滿倉口數);
+ Assert.Equal(111.11, rows2[index].波段);
+ Assert.Equal(111.11, rows2[index].當沖);
+ }
- private class TestIssue310Dto
- {
- public int? V1 { get; set; }
+ foreach (var index in new[] { 1, 3, 4 })
+ {
+ Assert.Null(rows2[index].實單每日損益);
+ Assert.Null(rows2[index].程式每日損益);
+ Assert.Null(rows2[index].商品);
+ Assert.Null(rows2[index].滿倉口數);
+ Assert.Null(rows2[index].波段);
+ Assert.Null(rows2[index].當沖);
+ }
}
- ///
- /// Excel was unable to open the file https://github.com/mini-software/MiniExcel/issues/343
- ///
[Fact]
- public void TestIssue343()
+ public void Issue149()
{
- var date = DateTime.Parse("2022-03-17 09:32:06.111", CultureInfo.InvariantCulture);
- using var path = AutoDeletingPath.Create();
+ char[] chars =
+ [
+ '\u0000','\u0001','\u0002','\u0003','\u0004','\u0005','\u0006','\u0007','\u0008',
+ '\u0009', //
+ '\u000A', //
+ '\u000B','\u000C',
+ '\u000D', //
+ '\u000E','\u000F','\u0010','\u0011','\u0012','\u0013','\u0014','\u0015','\u0016',
+ '\u0017','\u0018','\u0019','\u001A','\u001B','\u001C','\u001D','\u001E','\u001F','\u007F'
+ ];
+ var strings = chars.Select(s => s.ToString()).ToArray();
- CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("ff-Latn");
- var table = new DataTable();
{
- table.Columns.Add("time1", typeof(DateTime));
- table.Columns.Add("time2", typeof(DateTime));
- table.Rows.Add(date, date);
- table.Rows.Add(date, date);
+ var path = PathHelper.GetFile("xlsx/TestIssue149.xlsx");
+ var rows = _excelImporter.Query(path).Select(s => (string)s.A).ToList();
+ for (int i = 0; i < chars.Length; i++)
+ {
+ //output.WriteLine($"{i} , {chars[i]} , {rows[i]}");
+ if (i == 13)
+ continue;
+
+ Assert.Equal(strings[i], rows[i]);
+ }
}
- var reader = table.CreateDataReader();
- _excelExporter.Export(path.ToString(), reader);
- var rows = _excelImporter.Query(path.ToString(), true).ToArray();
- Assert.Equal(date, rows[0].time1);
- Assert.Equal(date, rows[0].time2);
+ {
+ using var path = AutoDeletingPath.Create();
+ var input = chars.Select(s => new { Test = s.ToString() });
+ _excelExporter.Export(path.ToString(), input);
+
+ var rows = _excelImporter.Query(path.ToString(), true).Select(s => (string)s.Test).ToList();
+ for (int i = 0; i < chars.Length; i++)
+ {
+ _output.WriteLine($"{i}, {chars[i]}, {rows[i]}");
+ if (i is 13 or 9 or 10)
+ continue;
+
+ Assert.Equal(strings[i], rows[i]);
+ }
+ }
+
+ {
+ using var path = AutoDeletingPath.Create();
+ var input = chars.Select(s => new { Test = s.ToString() });
+ _excelExporter.Export(path.ToString(), input);
+
+ var rows = _excelImporter.Query(path.ToString()).Select(s => s.Test).ToList();
+ for (int i = 0; i < chars.Length; i++)
+ {
+ _output.WriteLine($"{i}, {chars[i]}, {rows[i]}");
+ if (i is 13 or 9 or 10)
+ continue;
+
+ Assert.Equal(strings[i], rows[i]);
+ }
+ }
}
[Fact]
- public void TestIssueI4YCLQ_2()
+ public void Issue150()
{
- var path = PathHelper.GetFile("xlsx/TestIssueI4YCLQ_2.xlsx");
- var rows = _excelImporter.Query(path, startCell: "B2").ToList();
+ var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx");
- Assert.Null(rows[0].站点编码);
- Assert.Equal("N1", rows[0].站址名称);
- Assert.Equal("a", rows[0].值1);
- Assert.Equal("b", rows[0].值2);
- Assert.Equal("c", rows[0].值3);
- Assert.Equal("A1", rows[0].资源ID);
- Assert.Equal("A", rows[0].值4);
- Assert.Equal("B", rows[0].值5);
- Assert.Equal("C", rows[0].值6);
- Assert.Null(rows[0].值7);
- Assert.Null(rows[0].值8);
- }
+ Assert.Throws(() => _excelExporter.Export(path, new[] { 1, 2 }));
+ File.Delete(path);
- private class TestIssueI4YCLQ_2Dto
- {
- [MiniExcelColumnIndex("A")]
- public string 站点编码 { get; set; }
- [MiniExcelColumnIndex("B")]
- public string 站址名称 { get; set; }
- [MiniExcelColumnIndex("C")]
- public string 值1 { get; set; }
- [MiniExcelColumnIndex("D")]
- public string 值2 { get; set; }
- [MiniExcelColumnIndex("E")]
- public string 值3 { get; set; }
- [MiniExcelColumnIndex("F")]
- public string 资源ID { get; set; }
- [MiniExcelColumnIndex("G")]
- public string 值4 { get; set; }
- [MiniExcelColumnIndex("H")]
- public string 值5 { get; set; }
- [MiniExcelColumnIndex("I")]
- public string 值6 { get; set; }
- public string 值7 { get; set; }
- [MiniExcelColumnName("NotExist")]
- public string 值8 { get; set; }
- }
+ Assert.Throws(() => _excelExporter.Export(path, new[] { "1", "2" }));
+ File.Delete(path);
+ Assert.Throws(() => _excelExporter.Export(path, new[] { '1', '2' }));
+ File.Delete(path);
- [Fact]
- public void TestIssueI4WM67()
- {
- using var path = AutoDeletingPath.Create();
- var templatePath = PathHelper.GetFile("xlsx/TestIssueI4WM67.xlsx");
- var value = new Dictionary
- {
- ["users"] = Array.Empty()
- };
- _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
- var rows = _excelImporter.Query(path.ToString()).ToList();
- Assert.Single(rows);
+ Assert.Throws(() => _excelExporter.Export(path, new[] { DateTime.Now }));
+ File.Delete(path);
+
+ Assert.Throws(() => _excelExporter.Export(path, new[] { Guid.NewGuid() }));
+ File.Delete(path);
}
- private class TestIssueI4WM67Dto
+ [Fact]
+ public void Issue153()
{
- public int ID { get; set; }
- public string Name { get; set; }
+ var path = PathHelper.GetFile("xlsx/TestIssue153.xlsx");
+ var rows = _excelImporter.Query(path, true).First() as IDictionary;
+ Assert.Equal(
+ [
+ "序号", "代号", "新代号", "名称", "XXX", "部门名称", "单位", "ERP工时 (小时)A", "工时(秒) A/3600", "标准人工工时(秒)",
+ "生产标准机器工时(秒)", "财务、标准机器工时(秒)", "更新日期", "产品机种", "备注", "最近一次修改前的标准工时(秒)", "最近一次修改前的标准机时(秒)", "备注1"
+ ], rows?.Keys);
}
[Fact]
- public void TestIssueI4WXFB()
+ public void Issue157()
{
{
- using var path = AutoDeletingPath.Create();
- var templatePath = PathHelper.GetFile("xlsx/TestIssueI4WXFB.xlsx");
- var value = new Dictionary
- {
- ["Name"] = "Jack",
- ["Amount"] = 1000,
- ["Department"] = "HR"
- };
- _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
- }
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
+
+ List data =
+ [
+ new()
+ {
+ ID = new Guid("78de23d2-dcb6-bd3d-ec67-c112bbc322a2"),
+ Name = "Wade",
+ BoD = new DateTime(2020, 9, 27),
+ Points = 5019.12m
+ },
+ new()
+ {
+ ID = new Guid("20d3bfce-27c3-ad3e-4f70-35c81c7e8e45"),
+ Name = "Felix",
+ BoD = new DateTime(2020, 10, 25),
+ Points = 7028.46m
+ },
+ new()
+ {
+ ID = new Guid("52013bf0-9aeb-48e6-e5f5-e9500afb034f"),
+ Name = "Phelan",
+ BoD = new DateTime(2020, 10, 25),
+ Points = 3835.7m,
+ VIP = true
+ },
+ new()
+ {
+ ID = new Guid("3b97b87c-7afe-664f-1af5-6914d313ae25"),
+ Name = "Samuel",
+ BoD = new DateTime(2020, 6, 21),
+ Points = 9351.71m
+ },
+ new()
+ {
+ ID = new Guid("9a989c43-d55f-5306-0d2f-0fbafae135bb"),
+ Name = "Raymond",
+ BoD = new DateTime(2021, 7, 12),
+ Points = 8209.76m,
+ VIP = true
+ }
+ ];
+
+ _excelExporter.Export(path, data);
+
+ var rows = _excelImporter.Query(path, sheetName: "Sheet1").ToList();
+ Assert.Equal(6, rows.Count);
+ Assert.Equal("Sheet1", _excelImporter.GetSheetNames(path).First());
+ using var p = new ExcelPackage(new FileInfo(path));
+ var ws = p.Workbook.Worksheets.First();
+ Assert.Equal("Sheet1", ws.Name);
+ Assert.Equal("Sheet1", p.Workbook.Worksheets["Sheet1"].Name);
+ }
{
- var config = new OpenXmlConfiguration
+ var path = PathHelper.GetFile("xlsx/TestIssue157.xlsx");
+
{
- IgnoreTemplateParameterMissing = false
- };
- using var path = AutoDeletingPath.Create();
- var templatePath = PathHelper.GetFile("xlsx/TestIssueI4WXFB.xlsx");
- var value = new Dictionary
+ var rows = _excelImporter.Query(path, sheetName: "Sheet1").ToList();
+ Assert.Equal(6, rows.Count);
+ Assert.Equal("Sheet1", _excelImporter.GetSheetNames(path).First());
+ }
+ using (var p = new ExcelPackage(new FileInfo(path)))
{
- ["Name"] = "Jack",
- ["Amount"] = 1000,
- ["Department"] = "HR"
- };
- Assert.Throws(() => _excelTemplater.FillTemplate(path.ToString(), templatePath, value, configuration: config));
+ var ws = p.Workbook.Worksheets.First();
+ Assert.Equal("Sheet1", ws.Name);
+ Assert.Equal("Sheet1", p.Workbook.Worksheets["Sheet1"].Name);
+ }
+
+ {
+ var rows = _excelImporter.Query(path, sheetName: "Sheet1").ToList();
+ Assert.Equal(5, rows.Count);
+
+ Assert.Equal(new Guid("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows[0].ID);
+ Assert.Equal("Wade", rows[0].Name);
+ Assert.Equal(new DateTime(2020,9,27), rows[0].BoD);
+ Assert.False(rows[0].VIP);
+ Assert.Equal(5019.12m, rows[0].Points);
+ Assert.Equal(1, rows[0].IgnoredProperty);
+ }
}
}
+ // Query Support StartCell
[Fact]
- public void TestIssue331_2()
+ public void Issue147()
{
- var cln = CultureInfo.CurrentCulture.Name;
- CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("cs-CZ");
-
- var config = new OpenXmlConfiguration
- {
- Culture = CultureInfo.GetCultureInfo("cs-CZ")
- };
+ var path1 = PathHelper.GetFile("xlsx/TestIssue147.xlsx");
+ var rows1 = _excelImporter.Query(path1, hasHeaderRow: false, startCell: "C3", sheetName: "Sheet1").ToList();
- var rnd = new Random();
- var data = Enumerable.Range(1, 100).Select(x => new TestIssue331Dto
- {
- Number = x,
- Text = $"Number {x}",
- DecimalNumber = (decimal)rnd.NextDouble(),
- DoubleNumber = rnd.NextDouble()
- });
+ Assert.Equal(["C", "D", "E"], (rows1[0] as IDictionary)?.Keys);
+ Assert.Equal(new[]{"Column1", "Column2", "Column3"}, new[] { rows1[0].C as string, rows1[0].D as string, rows1[0].E as string });
+ Assert.Equal(new[]{"C4", "D4", "E4"}, new[] { rows1[1].C as string, rows1[1].D as string, rows1[1].E as string });
+ Assert.Equal(new[]{"C9", "D9", "E9"}, new[] { rows1[6].C as string, rows1[6].D as string, rows1[6].E as string });
+ Assert.Equal(new[]{"C12", "D12", "E12"}, new[] { rows1[9].C as string, rows1[9].D as string, rows1[9].E as string });
+ Assert.Equal(new[]{"C13", "D13", "E13"}, new[] { rows1[10].C as string, rows1[10].D as string, rows1[10].E as string });
+ foreach (var i in new[] { 4, 5, 7, 8 })
+ Assert.Equal(expected: [null, null, null], new[] { rows1[i].C as string, rows1[i].D as string, rows1[i].E as string });
- using var path = AutoDeletingPath.Create();
- _excelExporter.Export(path.ToString(), data, configuration: config);
- CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(cln);
- }
+ Assert.Equal(11, rows1.Count);
- [Fact]
- public void TestIssue331()
- {
- var cln = CultureInfo.CurrentCulture.Name;
- CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("cs-CZ");
- var data = Enumerable.Range(1, 10).Select(x => new TestIssue331Dto
- {
- Number = x,
- Text = $"Number {x}",
- DecimalNumber = x / 2m,
- DoubleNumber = x / 2d
- });
+ var columns1 = _excelImporter.GetColumnNames(path1, startCell: "C3");
+ Assert.Equal(["C", "D", "E"], columns1);
- using var path = AutoDeletingPath.Create();
- _excelExporter.Export(path.ToString(), data);
+ var path2 = PathHelper.GetFile("xlsx/TestIssue147.xlsx");
+ var rows2 = _excelImporter.Query(path2, hasHeaderRow: true, startCell: "C3", sheetName: "Sheet1").ToList();
- var rows = _excelImporter.Query(path.ToString(), startCell: "A2").ToArray();
- Assert.Equal(1.5, rows[2].B);
- Assert.Equal(1.5, rows[2].C);
+ Assert.Equal(["Column1", "Column2", "Column3"], (rows2[0] as IDictionary)?.Keys);
+ Assert.Equal(new[]{"C4", "D4", "E4"}, new[] { rows2[0].Column1 as string, rows2[0].Column2 as string, rows2[0].Column3 as string });
+ Assert.Equal(new[]{"C9", "D9", "E9"}, new[] { rows2[5].Column1 as string, rows2[5].Column2 as string, rows2[5].Column3 as string });
+ Assert.Equal(new[]{"C12", "D12", "E12"}, new[] { rows2[8].Column1 as string, rows2[8].Column2 as string, rows2[8].Column3 as string });
+ Assert.Equal(new[]{"C13", "D13", "E13"}, new[] { rows2[9].Column1 as string, rows2[9].Column2 as string, rows2[9].Column3 as string });
+
+ foreach (var i in new[] { 3, 4, 6, 7 })
+ {
+ Assert.Equal(new string?[]{null, null, null}, new[] { rows2[i].Column1 as string, rows2[i].Column2 as string, rows2[i].Column3 as string });
+ }
- CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(cln);
- }
+ Assert.Equal(10, rows2.Count);
- private class TestIssue331Dto
- {
- public int Number { get; set; }
- public decimal DecimalNumber { get; set; }
- public double DoubleNumber { get; set; }
- public string Text { get; set; }
+ var columns2 = _excelImporter.GetColumnNames(path2, hasHeaderRow: true, startCell: "C3");
+ Assert.Equal(["Column1", "Column2", "Column3"], columns2);
}
[Fact]
- public void TestIssueI4TXGT()
+ public void TestIssue186()
{
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
- var value = new[] { new TestIssueI4TXGTDto { ID = 1, Name = "Apple", Spc = "X", Up = 6999 } };
+ var originPath = PathHelper.GetFile("xlsx/TestIssue186_Template.xlsx");
+ using var path = AutoDeletingPath.Create();
+ File.Copy(originPath, path.FilePath);
- _excelExporter.Export(path, value);
- {
- var rows = _excelImporter.Query(path).ToList();
- Assert.Equal("ID", rows[0].A);
- Assert.Equal("Name", rows[0].B);
- Assert.Equal("Specification", rows[0].C);
- Assert.Equal("Unit Price", rows[0].D);
- }
- {
- var rows = _excelImporter.Query(path).ToList();
- Assert.Equal(1, rows[0].ID);
- Assert.Equal("Apple", rows[0].Name);
- Assert.Equal("X", rows[0].Spc);
- Assert.Equal(6999, rows[0].Up);
- }
- }
+ MiniExcelPicture[] images =
+ [
+ new()
+ {
+ ImageBytes = File.ReadAllBytes(PathHelper.GetFile("images/github_logo.png")),
+ SheetName = null, // default null is first sheet
+ CellAddress = "C3", // required
+ },
+ new()
+ {
+ ImageBytes = File.ReadAllBytes(PathHelper.GetFile("images/google_logo.png")),
+ PictureType = "image/png", // default PictureType = image/png
+ SheetName = "Demo",
+ CellAddress = "C9", // required
+ WidthPx = 100,
+ HeightPx = 100
+ }
+ ];
- private class TestIssueI4TXGTDto
- {
- public int ID { get; set; }
- public string Name { get; set; }
- [DisplayName("Specification")]
- public string Spc { get; set; }
- [DisplayName("Unit Price")]
- public decimal Up { get; set; }
+ _excelTemplater.AddPicture(path.FilePath, images);
}
+ // SaveAs default theme support filter mode - https://github.com/mini-software/MiniExcel/issues/190
[Fact]
- public void TestIssue328()
+ public void TestIssue190()
{
- using var path = AutoDeletingPath.Create();
- var value = new[]
{
- new
- {
- id=1,
- name="Jack",
- indate=new DateTime(2022,5,13),
- file = File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.png"))
- },
- new
- {
- id=2,
- name="Henry",
- indate=new DateTime(2022,4,10),
- file = File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.txt"))
- },
- };
- _excelExporter.Export(path.ToString(), value);
-
- var rowIndx = 0;
- using var reader = _excelImporter.GetDataReader(path.ToString(), true);
-
- Assert.Equal("id", reader.GetName(0));
- Assert.Equal("name", reader.GetName(1));
- Assert.Equal("indate", reader.GetName(2));
- Assert.Equal("file", reader.GetName(3));
+ using var path = AutoDeletingPath.Create();
+ var value = new TestIssue190Dto[] { };
+ _excelExporter.Export(path.ToString(), value, configuration: new OpenXmlConfiguration { AutoFilter = false });
- while (reader.Read())
+ var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ Assert.DoesNotContain("", sheetXml);
+ }
{
- for (int i = 0; i < reader.FieldCount; i++)
- {
- var v = reader.GetValue(i);
- if (rowIndx == 0 && i == 0) Assert.Equal(1.0, v);
- if (rowIndx == 0 && i == 1) Assert.Equal("Jack", v);
- if (rowIndx == 0 && i == 2) Assert.Equal(new DateTime(2022, 5, 13), v);
- if (rowIndx == 0 && i == 3) Assert.Equal(File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.png")), v);
- if (rowIndx == 1 && i == 0) Assert.Equal(2.0, v);
- if (rowIndx == 1 && i == 1) Assert.Equal("Henry", v);
- if (rowIndx == 1 && i == 2) Assert.Equal(new DateTime(2022, 4, 10), v);
- if (rowIndx == 1 && i == 3) Assert.Equal(File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.txt")), v);
- }
- rowIndx++;
+ using var path = AutoDeletingPath.Create();
+ var value = new TestIssue190Dto[] { };
+ _excelExporter.Export(path.ToString(), value);
+
+ var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ Assert.Contains("", sheetXml);
}
+ {
+ using var path = AutoDeletingPath.Create();
+ TestIssue190Dto[] value =
+ [
+ new() { ID = 1, Name = "Jack", Age = 32 },
+ new() { ID = 2, Name = "Lisa", Age = 45 }
+ ];
+ _excelExporter.Export(path.ToString(), value);
- //TODO:How to resolve empty body sheet?
+ var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ Assert.Contains("", sheetXml);
+ }
}
[Fact]
- public void TestIssue327()
+ public void Issue193()
{
- using var path = AutoDeletingPath.Create();
- var value = new[]
{
- new { id = 1, file = File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.png")) },
- new { id = 2, file = File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.txt")) },
- new { id = 3, file = File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.html")) },
- };
- _excelExporter.Export(path.ToString(), value);
- var rows = _excelImporter.Query(path.ToString(), true).ToList();
+ var templatePath = PathHelper.GetFile("xlsx/TestTemplateComplexWithNamespacePrefix.xlsx");
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
- Assert.Equal(value[0].file, rows[0].file);
- Assert.Equal(value[1].file, rows[1].file);
- Assert.Equal(value[2].file, rows[2].file);
- Assert.Equal("Hello MiniExcel", Encoding.UTF8.GetString(rows[1].file));
- Assert.Equal("Hello MiniExcel", Encoding.UTF8.GetString(rows[2].file));
- }
+ // 1. By Class
+ var value = new
+ {
+ title = "FooCompany",
+ managers = new[]
+ {
+ new { name = "Jack", department = "HR" },
+ new { name = "Loan", department = "IT" }
+ },
+ employees = new[]
+ {
+ new { name = "Wade", department = "HR" },
+ new { name = "Felix", department = "HR" },
+ new { name = "Eric", department = "IT" },
+ new { name = "Keaton", department = "IT" }
+ }
+ };
+ _excelTemplater.FillTemplate(path, templatePath, value);
- ///
- /// https://github.com/mini-software/MiniExcel/issues/325
- ///
- [Fact]
- public void TestIssue325()
- {
- using var path = AutoDeletingPath.Create();
- var value = new Dictionary
- {
- { "sheet1",new[]{ new { id = 1, date = DateTime.Parse("2022-01-01") } }},
- { "sheet2",new[]{ new { id = 2, date = DateTime.Parse("2022-01-01") } }},
- };
- _excelExporter.Export(path.ToString(), value);
+ foreach (var sheetName in _excelImporter.GetSheetNames(path))
+ {
+ var rows = _excelImporter.Query(path, sheetName: sheetName).ToList();
+ Assert.Equal(9, rows.Count);
- var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/_rels/sheet2.xml.rels");
- var cnt = Regex.Matches(xml, "Id=\"drawing2\"").Count;
- Assert.True(cnt == 1);
- }
+ Assert.Equal("FooCompany", rows[0].A);
+ Assert.Equal("Jack", rows[2].B);
+ Assert.Equal("HR", rows[2].C);
+ Assert.Equal("Loan", rows[3].B);
+ Assert.Equal("IT", rows[3].C);
- ///
- /// https://gitee.com/dotnetchina/MiniExcel/issues/I49RZH
- /// https://github.com/mini-software/MiniExcel/issues/305
- ///
- [Fact]
- public async Task TestIssueI49RZH()
- {
- var dt = new DateTime(2022, 01, 22);
+ Assert.Equal("Wade", rows[5].B);
+ Assert.Equal("HR", rows[5].C);
+ Assert.Equal("Felix", rows[6].B);
+ Assert.Equal("HR", rows[6].C);
- using var path = AutoDeletingPath.Create();
- TestIssueI49RZHDto[] value =
- [
- new() { dd = dt },
- new() { dd = null }
- ];
- await _excelExporter.ExportAsync(path.FilePath, value, overwriteFile: true);
+ Assert.Equal("Eric", rows[7].B);
+ Assert.Equal("IT", rows[7].C);
+ Assert.Equal("Keaton", rows[8].B);
+ Assert.Equal("IT", rows[8].C);
- using var package = new ExcelPackage(path.ToString());
- var cells = package.Workbook.Worksheets[0].Cells;
-
- Assert.Equal(dt, DateTime.FromOADate((double)cells["A2"].Value));
- Assert.Equal("22-01-2022", cells["A2"].Text);
- }
+ var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path);
+ Assert.Equal("A1:C9", dimension);
- private class TestIssueI49RZHDto
- {
- [MiniExcelFormat("dd-MM-yyyy")]
- public DateTime? dd { get; set; }
- }
+ /*TODO:row can't contain xmlns*/
+ // https://user-images.githubusercontent.com/12729184/114998840-ead44500-9ed3-11eb-8611-58afb98faed9.png
- ///
- /// https://github.com/mini-software/MiniExcel/issues/312
- ///
- [Fact]
- public void TestIssue312()
- {
- using var path = AutoDeletingPath.Create();
- TestIssue312Dto[] value =
- [
- new() { Value = 12_345.6789 },
- new() { Value = null }
- ];
- _excelExporter.Export(path.ToString(), value);
+ }
+ }
- using var package = new ExcelPackage(path.ToString());
- var cells = package.Workbook.Worksheets[0].Cells;
+ {
+ var templatePath = PathHelper.GetFile("xlsx/TestTemplateComplex.xlsx");
+ using var path = AutoDeletingPath.Create();
- var fmt = cells["A2"].Style.Numberformat.Format;
- Assert.Equal(12_345.68.ToString(fmt), cells["A2"].Text);
- Assert.Equal(12_345.6789, (double)cells["A2"].Value);
- }
+ // 2. By Dictionary
+ var value = new Dictionary
+ {
+ ["title"] = "FooCompany",
+ ["managers"] = new[] {
+ new {name="Jack",department="HR"},
+ new {name="Loan",department="IT"}
+ },
+ ["employees"] = new[] {
+ new {name="Wade",department="HR"},
+ new {name="Felix",department="HR"},
+ new {name="Eric",department="IT"},
+ new {name="Keaton",department="IT"}
+ }
+ };
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
+ var rows = _excelImporter.Query(path.ToString()).ToList();
- private class TestIssue312Dto
- {
- [MiniExcelFormat("0,0.00")]
- public double? Value { get; set; }
- }
+ Assert.Equal("FooCompany", rows[0].A);
+ Assert.Equal("Jack", rows[2].B);
+ Assert.Equal("HR", rows[2].C);
+ Assert.Equal("Loan", rows[3].B);
+ Assert.Equal("IT", rows[3].C);
- ///
- /// Query type conversion error
- /// https://github.com/mini-software/MiniExcel/issues/309
- ///
- [Fact]
- public void TestIssue209()
- {
- try
- {
- var path = PathHelper.GetFile("xlsx/TestIssue309.xlsx");
- var rows = _excelImporter.Query(path).ToList();
- }
- catch (ValueNotAssignableException ex)
- {
- Assert.Equal("SEQ", ex.ColumnName);
- Assert.Equal(4, ex.Row);
- Assert.Equal("Error", ex.Value);
- Assert.Equal(typeof(int), ex.ColumnType);
- Assert.Equal("The value Error cannot be assigned to type Int32.", ex.Message);
- }
- }
+ Assert.Equal("Wade", rows[5].B);
+ Assert.Equal("HR", rows[5].C);
+ Assert.Equal("Felix", rows[6].B);
+ Assert.Equal("HR", rows[6].C);
- private class TestIssue209Dto
- {
- public int ID { get; set; }
- public string Name { get; set; }
- public int SEQ { get; set; }
+ Assert.Equal("Eric", rows[7].B);
+ Assert.Equal("IT", rows[7].C);
+ Assert.Equal("Keaton", rows[8].B);
+ Assert.Equal("IT", rows[8].C);
+
+ var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path.ToString());
+ Assert.Equal("A1:C9", dimension);
+ }
}
- ///
- /// [SaveAs and Query support btye[] base64 converter · Issue #318 · mini-software/MiniExcel](https://github.com/mini-software/MiniExcel/issues/318)
- ///
[Fact]
- public void TestIssue318()
+ public void Issue206()
{
- var imageByte = File.ReadAllBytes(PathHelper.GetFile("images/github_logo.png"));
- using var path = AutoDeletingPath.Create();
- var value = new[]
{
- new { Name="github", Image=imageByte},
- };
- _excelExporter.Export(path.ToString(), value);
+ var templatePath = PathHelper.GetFile("xlsx/TestTemplateBasicIEmumerableFill.xlsx");
+ using var path = AutoDeletingPath.Create();
+ var dt = new DataTable();
+ {
+ dt.Columns.Add("name");
+ dt.Columns.Add("department");
+ }
+ var value = new Dictionary
+ {
+ ["employees"] = dt
+ };
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
- // import to byte[]
- {
- const string expectedBase64 = "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAEXRFWHRTb2Z0d2FyZQBTbmlwYXN0ZV0Xzt0AAALNSURBVEiJ7ZVLTBNBGMdndrfdIofy0ERbCgcFeYRuCy2JGOPNRA9qeIZS6YEEogQj0YMmGOqDSATxQaLRxKtRID4SgjGelUBpaQvGZ7kpII8aWtjd2dkdDxsJoS1pIh6M/k+z8833m/3+8+0OJISArRa15cT/0D8CZTYPe32+Zy+GxjzjMzOzAACDYafdZquqOG7hzJtkwUQthRC6cavv0eN+QRTBujUQQp1OV1dbffZMq1arTRaqKIok4eZTrSNjHqIo6gIIIQBgbQwpal+Z/f7dPo2GoaiNHtJut3vjPhBe7+kdfvW61Mq1nGyaX1xYjkRzsk2Z6Rm8IOTvzWs73SLwwqjHK4jCgf3lcV6VxGgiECji7AXm0gvtHYQQnue/zy8ghCRJWlxaWuV5Qsilq9cKzLYiiz04ORVLiHP6A4NPRQlhjLWsVpZlnU63Y3umRqNhGCYjPV3HsrIsMwyDsYQQejIwGEuIA/WMT1AAaDSahnoHTdPKL1vXPKVp2umoZVkWAOj1+ZOCzs7NKYTo9XqjYRcAgKIo9ZRUu9VxltGYZTQAAL5+m0kKijEmAPCrqyJCcRuOECKI4lL4ByEEYykpaE62iQIgurLi9wchhLIsry8fYwwh9PomwuEwACDbZEoKauHMgKJSU1PbOy6Hpqdpml5fPsMwn7+EOru6IYQAghKrJSloTVUFURSX02G3lRw+WulqbA4EJ9XQh4+f2s6dr65zhkLTEEIKwtqaylhCnG/fauFO1Nfde/Bw6Hm/0WiYevc+LU2vhlK2pQwNvwQAsCwrYexyOrji4lhCnOaXZRljXONoOHTk2Ju3I/5AcC3EC0JZ+cE9Bea8IqursUkUker4BsWBqpIk6aL7Sm4htzvfvByJqJORaDS3kMsvLuns6kYIJcpNCFU17pvouXlHEET1URDEnt7bo2OezbMS/vp+R3/PdfKPQ38Ccg0E/CDcpY8AAAAASUVORK5CYII=";
- var rows = _excelImporter.Query(path.ToString(), true).ToList();
- var actulBase64 = Convert.ToBase64String((byte[])rows[0].Image);
- Assert.Equal(expectedBase64, actulBase64);
+ var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path.ToString());
+ Assert.Equal("A1:B2", dimension);
}
- // import to base64 string
{
- var config = new OpenXmlConfiguration { EnableConvertByteArray = false };
- var rows = _excelImporter.Query(path.ToString(), true, configuration: config).ToList();
- var image = (string)rows[0].Image;
- Assert.StartsWith("@@@fileid@@@,xl/media/", image);
- }
+ var templatePath = PathHelper.GetFile("xlsx/TestTemplateBasicIEmumerableFill.xlsx");
+ using var path = AutoDeletingPath.Create();
- }
+ using var dt = new DataTable();
+ dt.Columns.Add("name");
+ dt.Columns.Add("department");
+ dt.Rows.Add("Jack", "HR");
+ var value = new Dictionary { ["employees"] = dt };
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
- ///
- /// SaveAs support Image type · Issue #304 https://github.com/mini-software/MiniExcel/issues/304
- ///
+ var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path.ToString());
+ Assert.Equal("A1:B2", dimension);
+ }
+ }
+
+ // Template merge row list rendering has no merge
[Fact]
- public void TestIssue304()
+ public void Issue207()
{
- var path = PathHelper.GetTempFilePath();
- var value = new[]
{
- new { Name="github", Image=File.ReadAllBytes(PathHelper.GetFile("images/github_logo.png"))},
- new { Name="google", Image=File.ReadAllBytes(PathHelper.GetFile("images/google_logo.png"))},
- new { Name="microsoft", Image=File.ReadAllBytes(PathHelper.GetFile("images/microsoft_logo.png"))},
- new { Name="reddit", Image=File.ReadAllBytes(PathHelper.GetFile("images/reddit_logo.png"))},
- new { Name="stackoverflow", Image=File.ReadAllBytes(PathHelper.GetFile("images/stackoverflow_logo.png"))},
- };
- _excelExporter.Export(path, value);
+ var tempaltePath = PathHelper.GetFile("xlsx/TestIssue207_2.xlsx");
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
- Assert.Contains("/xl/media/", SheetHelper.GetZipFileContent(path, "xl/drawings/_rels/drawing1.xml.rels"));
- Assert.Contains("ext cx=\"609600\" cy=\"190500\"", SheetHelper.GetZipFileContent(path, "xl/drawings/drawing1.xml"));
- Assert.Contains("/xl/drawings/drawing1.xml", SheetHelper.GetZipFileContent(path, "[Content_Types].xml"));
- Assert.Contains("drawing r:id=", SheetHelper.GetZipFileContent(path, "xl/worksheets/sheet1.xml"));
- Assert.Contains("../drawings/drawing1.xml", SheetHelper.GetZipFileContent(path, "xl/worksheets/_rels/sheet1.xml.rels"));
- }
+ var value = new
+ {
+ project = new[] {
+ new {name = "項目1",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
+ new {name = "項目2",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
+ new {name = "項目3",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
+ new {name = "項目4",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
+ }
+ };
- ///
- /// https://gitee.com/dotnetchina/MiniExcel/issues/I4HL54
- ///
- [Fact]
- public void TestIssueI4HL54()
- {
- using var cn = Db.GetConnection();
+ _excelTemplater.FillTemplate(path, tempaltePath, value);
+ var rows = _excelImporter.Query(path).ToList();
- using var reader = cn.ExecuteReader(@"select 'Hello World1' Text union all select 'Hello World2'");
- var templatePath = PathHelper.GetFile("xlsx/TestIssueI4HL54_Template.xlsx");
- using var path = AutoDeletingPath.Create();
- var value = new Dictionary
- {
- { "Texts",reader}
- };
- _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
+ Assert.Equal("項目1", rows[0].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[0].B);
+ Assert.Equal("項目2", rows[2].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[2].B);
+ Assert.Equal("項目3", rows[4].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[4].B);
+ Assert.Equal("項目4", rows[6].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[6].B);
- var rows = _excelImporter.Query(path.ToString(), true).ToList();
- Assert.Equal("Hello World1", rows[0].Text);
- Assert.Equal("Hello World2", rows[1].Text);
- }
+ Assert.Equal("Test1", rows[8].A);
+ Assert.Equal("Test2", rows[8].B);
+ Assert.Equal("Test3", rows[8].C);
- ///
- /// [Prefix and suffix blank space will lost after SaveAs · Issue #294 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/294)
- ///
- [Fact]
- public void TestIssue294()
- {
- {
- using var path = AutoDeletingPath.Create();
- var value = new[] { new { Name = " Jack" } };
- _excelExporter.Export(path.ToString(), value);
- var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- Assert.Contains("xml:space=\"preserve\"", sheetXml);
- }
- {
- using var path = AutoDeletingPath.Create();
- var value = new[] { new { Name = "Ja ck" } };
- _excelExporter.Export(path.ToString(), value);
- var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- Assert.DoesNotContain("xml:space=\"preserve\"", sheetXml);
+ Assert.Equal("項目1", rows[12].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[12].B);
+ Assert.Equal("項目2", rows[13].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[13].B);
+ Assert.Equal("項目3", rows[14].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[14].B);
+ Assert.Equal("項目4", rows[15].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[15].B);
+
+ var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path);
+ Assert.Equal("A1:C16", dimension);
}
+
{
- using var path = AutoDeletingPath.Create();
- var value = new[] { new { Name = "Jack " } };
- _excelExporter.Export(path.ToString(), value);
- var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- Assert.Contains("xml:space=\"preserve\"", sheetXml);
+ var tempaltePath = PathHelper.GetFile("xlsx/TestIssue207_Template_Merge_row_list_rendering_without_merge/template.xlsx");
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
+
+ var value = new
+ {
+ project = new[] {
+ new {name = "項目1",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
+ new {name = "項目2",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
+ new {name = "項目3",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
+ new {name = "項目4",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
+ }
+ };
+
+ _excelTemplater.FillTemplate(path, tempaltePath, value);
+ var rows = _excelImporter.Query(path).ToList();
+
+ Assert.Equal("項目1", rows[0].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[0].C);
+ Assert.Equal("項目2", rows[3].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[3].C);
+ Assert.Equal("項目3", rows[6].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[6].C);
+ Assert.Equal("項目4", rows[9].A);
+ Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[9].C);
+ var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path);
+ Assert.Equal("A1:E15", dimension);
}
}
-
- ///
- /// SaveAsByTemplate if there is & in the cell value, it will be &
- /// https://gitee.com/dotnetchina/MiniExcel/issues/I4DQUN
- ///
[Fact]
- public void TestIssueI4DQUN()
+ public void Issue208()
{
- var templatePath = PathHelper.GetFile("xlsx/TestIssueI4DQUN.xlsx");
- using var path = AutoDeletingPath.Create();
- var value = new Dictionary
- {
- { "Title", "Hello & World < , > , \" , '" },
- { "Details", new[] { new { Value = "Hello & Value < , > , \" , '" } } },
- };
- _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
-
- var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- // Template now uses inlineStr format (...) instead of SharedStrings (...)
- Assert.Contains("Hello & World < , > , \" , '", sheetXml);
- Assert.Contains("Hello & Value < , > , \" , '", sheetXml);
+ var path = PathHelper.GetFile("xlsx/TestIssue208.xlsx");
+ var columns = _excelImporter.GetColumnNames(path).ToList();
+ Assert.Equal(16384, columns.Count);
+ Assert.Equal("XFD", columns[16383]);
}
- ///
- /// [SaveAs default theme support filter mode · Issue #190 · mini-software/MiniExcel](https://github.com/mini-software/MiniExcel/issues/190)
- ///
+ // Query type conversion error - https://github.com/mini-software/MiniExcel/issues/309
[Fact]
- public void TestIssue190()
+ public void TestIssue209()
{
+ try
{
- using var path = AutoDeletingPath.Create();
- var value = new TestIssue190Dto[] { };
- _excelExporter.Export(path.ToString(), value, configuration: new OpenXmlConfiguration { AutoFilter = false });
-
- var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- Assert.DoesNotContain("", sheetXml);
- }
- {
- using var path = AutoDeletingPath.Create();
- var value = new TestIssue190Dto[] { };
- _excelExporter.Export(path.ToString(), value);
-
- var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- Assert.Contains("", sheetXml);
+ var path = PathHelper.GetFile("xlsx/TestIssue309.xlsx");
+ _ = _excelImporter.Query(path).ToList();
}
+ catch (ValueNotAssignableException ex)
{
- using var path = AutoDeletingPath.Create();
- TestIssue190Dto[] value =
- [
- new() { ID = 1, Name = "Jack", Age = 32 },
- new() { ID = 2, Name = "Lisa", Age = 45 }
- ];
- _excelExporter.Export(path.ToString(), value);
-
- var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- Assert.Contains("", sheetXml);
+ Assert.Equal("SEQ", ex.ColumnName);
+ Assert.Equal(4, ex.Row);
+ Assert.Equal("Error", ex.Value);
+ Assert.Equal(typeof(int), ex.ColumnType);
+ Assert.Equal("The value Error cannot be assigned to type Int32.", ex.Message);
}
}
- private class TestIssue190Dto
- {
- public int ID { get; set; }
- public string Name { get; set; }
- public int Age { get; set; }
- }
-
-
+ // SaveAs support for IDataReader based export
[Fact]
- public void TestIssueI49RYZ()
+ public void Issue211()
{
- I49RYZDto[] values =
- [
- new() { Name="Jack", UserType=I49RYZUserType.V1 },
- new() { Name="Leo", UserType=I49RYZUserType.V2 },
- new() { Name="Henry", UserType=I49RYZUserType.V3 },
- new() { Name="Lisa", UserType=null }
- ];
using var path = AutoDeletingPath.Create();
- _excelExporter.Export(path.ToString(), values);
+ var tempSqlitePath = AutoDeletingPath.Create(Path.GetTempPath(), $"{Guid.NewGuid()}.db");
+ var connectionString = $"Data Source={tempSqlitePath};Version=3;";
+
+ using var connection = new SQLiteConnection(connectionString);
+ var reader = connection.ExecuteReader(@"select 1 Test1,2 Test2 union all select 3 , 4 union all select 5 ,6");
+ _excelExporter.Export(path.ToString(), reader);
var rows = _excelImporter.Query(path.ToString(), true).ToList();
- Assert.Equal("GeneralUser", rows[0].UserType);
- Assert.Equal("SuperAdministrator", rows[1].UserType);
- Assert.Equal("GeneralAdministrator", rows[2].UserType);
- Assert.Null(rows[3].UserType);
+
+ Assert.Equal(1.0, rows[0].Test1);
+ Assert.Equal(2.0, rows[0].Test2);
+ Assert.Equal(3.0, rows[1].Test1);
+ Assert.Equal(4.0, rows[1].Test2);
}
+ // _exporter.Export(path, table,sheetName:“Name”) sheetName is incorrectly Sheet1
[Fact]
- public void TestIssue286()
+ public void Issue212()
{
- TestIssue286Dto[] values =
- [
- new() { E = TestIssue286Enum.VIP1 },
- new() { E = TestIssue286Enum.VIP2 }
- ];
using var path = AutoDeletingPath.Create();
- _excelExporter.Export(path.ToString(), values);
- var rows = _excelImporter.Query(path.ToString(), true).ToList();
+ _excelExporter.Export(path.ToString(), new[] { new { x = 1, y = 2 } }, sheetName: "Demo");
- Assert.Equal("VIP1", rows[0].E);
- Assert.Equal("VIP2", rows[1].E);
+ var actualSheetName = _excelImporter.GetSheetNames(path.ToString()).ToList()[0];
+ Assert.Equal("Demo", actualSheetName);
}
- private class TestIssue286Dto
+ // Support reading Excel by IDataReader and returning DataTable
+ [Fact]
+ public void Issue216()
{
- public TestIssue286Enum E { get; set; }
- }
+ using var path = AutoDeletingPath.Create();
+ var value = new[]
+ {
+ new { Test1 = "1", Test2 = 2 },
+ new { Test1 = "3", Test2 = 4 }
+ };
+ _excelExporter.Export(path.ToString(), value);
- private enum TestIssue286Enum { VIP1, VIP2 }
+ using var table = _excelImporter.QueryAsDataTable(path.ToString());
+ Assert.Equal("Test1", table.Columns[0].ColumnName);
+ Assert.Equal("Test2", table.Columns[1].ColumnName);
+ Assert.Equal("1", table.Rows[0]["Test1"]);
+ Assert.Equal(2.0, table.Rows[0]["Test2"]);
+ Assert.Equal("3", table.Rows[1]["Test1"]);
+ Assert.Equal(4.0, table.Rows[1]["Test2"]);
- private enum I49RYZUserType
- {
- [Description("GeneralUser")] V1 = 0,
- [Description("SuperAdministrator")] V2 = 1,
- [Description("GeneralAdministrator")] V3 = 2
+
+ using var dt = _excelImporter.QueryAsDataTable(path.ToString(), false);
+ Assert.Equal("Test1", dt.Rows[0]["A"]);
+ Assert.Equal("Test2", dt.Rows[0]["B"]);
+ Assert.Equal("1", dt.Rows[1]["A"]);
+ Assert.Equal(2.0, dt.Rows[1]["B"]);
+ Assert.Equal("3", dt.Rows[2]["A"]);
+ Assert.Equal(4.0, dt.Rows[2]["B"]);
}
- private class I49RYZDto
+ // DataTable recommended to use Caption for column name first, then use columname
+ [Fact]
+ public void Issue217()
{
- public string Name { get; set; }
- public I49RYZUserType? UserType { get; set; }
- }
+ using var table = new DataTable();
+ table.Columns.Add("CustomerID");
+ table.Columns.Add("CustomerName").Caption = "Name";
+ table.Columns.Add("CreditLimit").Caption = "Limit";
+ table.Rows.Add(1, "Jonathan", 23.44);
+ table.Rows.Add(2, "Bill", 56.87);
+ using var path = AutoDeletingPath.Create();
+ _excelExporter.Export(path.ToString(), table);
- ///
- /// Create Multiple Sheets from IDataReader have Bug #283
- ///
+ var rows = _excelImporter.Query(path.ToString()).ToList();
+ Assert.Equal("Name", rows[0].B);
+ Assert.Equal("Limit", rows[0].C);
+ }
+
+ // Dynamic Query can't summary numeric cell value default, need to cast
[Fact]
- public void TestIssue283()
+ public void Issue220()
{
- using var path = AutoDeletingPath.Create();
- using (var cn = Db.GetConnection())
- {
- var sheets = new Dictionary
+ var path = PathHelper.GetFile("xlsx/TestIssue220.xlsx");
+ var rows = _excelImporter.Query(path, hasHeaderRow: true);
+ var result = rows
+ .GroupBy(s => s.PRT_ID)
+ .Select(g => new
{
- { "sheet01", cn.ExecuteReader("select 'v1' col1") },
- { "sheet02", cn.ExecuteReader("select 'v2' col1") }
- };
- var rows = _excelExporter.Export(path.ToString(), sheets);
- Assert.Equal(2, rows.Length);
- }
+ PRT_ID = g.Key,
+ Apr = g.Sum(x => (double?)x.Apr),
+ May = g.Sum(x => (double?)x.May),
+ Jun = g.Sum(x => (double?)x.Jun)
+ })
+ .ToList();
- var sheetNames = _excelImporter.GetSheetNames(path.ToString());
- Assert.Equal(["sheet01", "sheet02"], sheetNames);
+ Assert.Equal(91843.25, result[0].Jun);
+ Assert.Equal(50000.99, result[1].Jun);
}
- ///
- /// https://gitee.com/dotnetchina/MiniExcel/issues/I40QA5
- ///
+ // Custom yyyy-MM-dd format not converted to datetime
[Fact]
- public void TestIssueI40QA5()
+ public void Issue222()
{
- {
- var path = PathHelper.GetFile("/xlsx/TestIssueI40QA5_1.xlsx");
- var rows = _excelImporter.Query(path).ToList();
- Assert.Equal("E001", rows[0].Empno);
- Assert.Equal("E002", rows[1].Empno);
- }
- {
- var path = PathHelper.GetFile("/xlsx/TestIssueI40QA5_2.xlsx");
- var rows = _excelImporter.Query(path).ToList();
- Assert.Equal("E001", rows[0].Empno);
- Assert.Equal("E002", rows[1].Empno);
- }
- {
- var path = PathHelper.GetFile("/xlsx/TestIssueI40QA5_3.xlsx");
- var rows = _excelImporter.Query(path).ToList();
- Assert.Equal("E001", rows[0].Empno);
- Assert.Equal("E002", rows[1].Empno);
- }
- {
- var path = PathHelper.GetFile("/xlsx/TestIssueI40QA5_4.xlsx");
- var rows = _excelImporter.Query(path).ToList();
- Assert.Null(rows[0].Empno);
- Assert.Null(rows[1].Empno);
- }
+ var path = PathHelper.GetFile("xlsx/TestIssue222.xlsx");
+ var rows = _excelImporter.Query(path).ToList();
+ Assert.Equal(typeof(DateTime), rows[1].A.GetType());
+ Assert.Equal(new DateTime(2021, 4, 29), rows[1].A);
}
- private class TestIssueI40QA5Dto
+ [Fact]
+ public void Issue223()
{
- [MiniExcelColumnName(columnName: "EmployeeNo", aliases: new[] { "EmpNo", "No" })]
- public string Empno { get; set; }
- public string Name { get; set; }
+ List> value =
+ [
+ new() { { "A", null }, { "B", null } },
+ new() { { "A", 123 }, { "B", new DateTime(2021, 1, 1) } },
+ new() { { "A", Guid.NewGuid() }, { "B", "HelloWorld" } }
+ ];
+ using var path = AutoDeletingPath.Create();
+ _excelExporter.Export(path.ToString(), value);
+
+ using var dt = _excelImporter.QueryAsDataTable(path.ToString());
+
+ var columns = dt.Columns;
+ Assert.Equal(typeof(object), columns[0].DataType);
+ Assert.Equal(typeof(object), columns[1].DataType);
+
+ Assert.Equal(123.0, dt.Rows[1]["A"]);
+ Assert.Equal("HelloWorld", dt.Rows[2]["B"]);
}
+ // Fix SaveAsByTemplate single column dimension index error
[Fact]
- public void TestIssues133()
+ public void Issue226()
{
- {
- using var path = AutoDeletingPath.Create();
+ using var path = AutoDeletingPath.Create();
+ var templatePath = PathHelper.GetFile("xlsx/TestIssue226.xlsx");
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, new { employees = new[] { new { name = "123" }, new { name = "123" } } });
+ Assert.Equal("A1:A3", SheetHelper.GetFirstSheetDimensionRefValue(path.ToString()));
+ }
- var value = new DataTable();
- value.Columns.Add("Id");
- value.Columns.Add("Name");
- _excelExporter.Export(path.ToString(), value);
- var rows = _excelImporter.Query(path.ToString()).ToList();
+ // Support Xlsm AutoCheck
+ [Fact]
+ public void Issue227()
+ {
+ var path = PathHelper.GetTempPath("xlsm");
+ Assert.Throws(() => _excelExporter.Export(path, new[] { new { V = "A1" }, new { V = "A2" } }));
+ File.Delete(path);
- Assert.Equal("Id", rows[0].A);
- Assert.Equal("Name", rows[0].B);
- Assert.Single(rows);
- Assert.Equal("A1:B1", SheetHelper.GetFirstSheetDimensionRefValue(path.ToString()));
- }
+ var path1 = PathHelper.GetFile("xlsx/TestIssue227.xlsm");
+ var rows1 = _excelImporter.Query(path1).ToList();
+ Assert.Equal(100, rows1.Count);
- {
- using var path = AutoDeletingPath.Create();
+ Assert.Equal(Guid.Parse("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows1[0].ID);
+ Assert.Equal("Wade", rows1[0].Name);
+ Assert.Equal(DateTime.ParseExact("27/09/2020", "dd/MM/yyyy", CultureInfo.InvariantCulture), rows1[0].BoD);
+ Assert.Equal(36, rows1[0].Age);
+ Assert.False(rows1[0].VIP);
+ Assert.Equal(5019.12m, rows1[0].Points);
+ Assert.Equal(1, rows1[0].IgnoredProperty);
- var value = Array.Empty();
- _excelExporter.Export(path.ToString(), value);
- var rows = _excelImporter.Query(path.ToString()).ToList();
+ using var stream = File.OpenRead(path1);
+ var rows2 = _excelImporter.Query(stream).ToList();
+ Assert.Equal(100, rows2.Count);
- Assert.Equal("Id", rows[0].A);
- Assert.Equal("Name", rows[0].B);
- Assert.Single(rows);
- Assert.Equal("A1:B1", SheetHelper.GetFirstSheetDimensionRefValue(path.ToString()));
- }
+ Assert.Equal(Guid.Parse("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows2[0].ID);
+ Assert.Equal("Wade", rows2[0].Name);
+ Assert.Equal(DateTime.ParseExact("27/09/2020", "dd/MM/yyyy", CultureInfo.InvariantCulture), rows2[0].BoD);
+ Assert.Equal(36, rows2[0].Age);
+ Assert.False(rows2[0].VIP);
+ Assert.Equal(5019.12m, rows2[0].Points);
+ Assert.Equal(1, rows2[0].IgnoredProperty);
}
- private class TestIssues133Dto
+ // QueryAsDataTable error "Cannot set Column to be null"
+ [Fact]
+ public void Issue229()
{
- public string Id { get; set; }
- public string Name { get; set; }
+ var path = PathHelper.GetFile("xlsx/TestIssue229.xlsx");
+
+ using var dt = _excelImporter.QueryAsDataTable(path);
+
+ foreach (DataColumn column in dt.Columns)
+ {
+ var v = dt.Rows[3][column];
+ Assert.Equal(DBNull.Value, v);
+ }
}
- ///
- /// Semicolon expected
- ///
+ // SaveAs By data reader error : 'Invalid attempt to call FieldCount when reader is closed'
[Fact]
- public void TestIssueI45TF5_2()
+ public void Issue230()
{
+ using var conn = Db.GetConnection("Data Source=:memory:");
+ conn.Open();
+ using var cmd = conn.CreateCommand();
+ cmd.CommandText = "select 1 id union all select 2";
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
- var value = new[] { new Dictionary { { "Col1&Col2", "V1&V2" } } };
- var path = PathHelper.GetTempPath();
- _excelExporter.Export(path, value);
- //System.Xml.XmlException : '<' is an unexpected token. The expected token is ';'.
- SheetHelper.GetZipFileContent(path, "xl/worksheets/sheet1.xml"); //check illegal format or not
+ while (reader.Read())
+ {
+ for (int i = 0; i < reader.FieldCount; i++)
+ {
+ var result = $"{reader.GetName(i)} , {reader.GetValue(i)}";
+ _output.WriteLine(result);
+ }
+ }
}
+ using var conn2 = Db.GetConnection("Data Source=:memory:");
+ conn2.Open();
+ using var cmd2 = conn2.CreateCommand();
+ cmd2.CommandText = "select 1 id union all select 2";
+ using (var reader = cmd2.ExecuteReader(CommandBehavior.CloseConnection))
{
- using var dt = new DataTable();
- dt.Columns.Add("Col1&Col2");
- dt.Rows.Add("V1&V2");
- var path = PathHelper.GetTempPath();
- _excelExporter.Export(path, dt);
- //System.Xml.XmlException : '<' is an unexpected token. The expected token is ';'.
- SheetHelper.GetZipFileContent(path, "xl/worksheets/sheet1.xml"); //check illegal format or not
+ while (reader.Read())
+ {
+ for (int i = 0; i < reader.FieldCount; i++)
+ {
+ var result = $"{reader.GetName(i)}, {reader.GetValue(i)}";
+ _output.WriteLine(result);
+ }
+ }
}
- }
- [Fact]
- public void TestIssueI45TF5()
- {
- using var path = AutoDeletingPath.Create();
- _excelExporter.Export(path.ToString(), new[] { new { C1 = "1&2;3,4", C2 = "1&2;3,4" } });
- var sheet1Xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
- Assert.DoesNotContain("", sheet1Xml);
+ using var conn3 = Db.GetConnection("Data Source=:memory:");
+ conn3.Open();
+ using var cmd3 = conn3.CreateCommand();
+ cmd3.CommandText = "select 1 id union all select 2";
+ using (var reader = cmd3.ExecuteReader(CommandBehavior.CloseConnection))
+ {
+ using var path = AutoDeletingPath.Create();
+ _excelExporter.Export(path.ToString(), reader, printHeader: true);
+ var rows = _excelImporter.Query(path.ToString(), true).ToList();
+ Assert.Equal(1, rows[0].id);
+ Assert.Equal(2, rows[1].id);
+ }
}
- ///
- /// [Support column width attribute · Issue #280 · mini-software/MiniExcel](https://github.com/mini-software/MiniExcel/issues/280)
- ///
+ // QueryAsDataTable A2=5.5 , A3=0.55/1.1 will case double type check error
[Fact]
- public void TestIssue280()
+ public void Issue233()
{
- TestIssue280Dto[] value =
- [
- new() { ID = 1, Name = "Jack" },
- new() { ID = 2, Name = "Mike" }
- ];
- using var path = AutoDeletingPath.Create();
- _excelExporter.Export(path.ToString(), value);
- }
+ var path = PathHelper.GetFile("xlsx/TestIssue233.xlsx");
- private class TestIssue280Dto
- {
- [MiniExcelColumnWidth(20)]
- public int ID { get; set; }
- [MiniExcelColumnWidth(15.50)]
- public string Name { get; set; }
- }
+ var dt = _excelImporter.QueryAsDataTable(path);
- ///
- /// Custom excel zip can't read and show Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory. #272
- ///
- [Fact]
- public void TestIssue272()
- {
- var path = PathHelper.GetFile("/xlsx/TestIssue272.xlsx");
- Assert.Throws(() => _excelImporter.Query(path).ToList());
- }
+ var rows = dt.Rows;
- ///
- /// v0.16.0-0.17.1 custom format contains specific format (eg:`#,##0.000_);[Red]\(#,##0.000\)`), automatic converter will convert double to datetime #267
- ///
- [Fact]
- public void TestIssue267()
- {
- var path = PathHelper.GetFile("/xlsx/TestIssue267.xlsx");
- var row = _excelImporter.Query(path).SingleOrDefault();
- Assert.Equal(10618, row!.A);
- Assert.Equal("2021-02-23", row.B);
- Assert.Equal(43.199999999999996, row.C);
- Assert.Equal(1.2, row.D);
- Assert.Equal(new DateTime(2021, 7, 5), row.E);
- Assert.Equal(new DateTime(2021, 7, 5, 15, 2, 46), row.F);
+ Assert.Equal(0.55, rows[0]["Size"]);
+ Assert.Equal("0.55/1.1", rows[1]["Size"]);
}
-
+ /// SaveAs support for multiple sheets
[Fact]
- public void TestIssue268_DateFormat()
+ public void Issue234()
{
- Assert.True(IsDateFormatString("dd/mm/yyyy"));
- Assert.True(IsDateFormatString("dd-mmm-yy"));
- Assert.True(IsDateFormatString("dd-mmmm"));
- Assert.True(IsDateFormatString("mmm-yy"));
- Assert.True(IsDateFormatString("h:mm AM/PM"));
- Assert.True(IsDateFormatString("h:mm:ss AM/PM"));
- Assert.True(IsDateFormatString("hh:mm"));
- Assert.True(IsDateFormatString("hh:mm:ss"));
- Assert.True(IsDateFormatString("dd/mm/yyyy hh:mm"));
- Assert.True(IsDateFormatString("mm:ss"));
- Assert.True(IsDateFormatString("mm:ss.0"));
- Assert.True(IsDateFormatString("[$-809]dd mmmm yyyy"));
- Assert.False(IsDateFormatString("#,##0;[Red]-#,##0"));
- Assert.False(IsDateFormatString(@"#,##0.000_);[Red]\(#,##0.000\)"));
- Assert.False(IsDateFormatString("0_);[Red](0)"));
- Assert.False(IsDateFormatString(@"0\h"));
- Assert.False(IsDateFormatString("0\"h\""));
- Assert.False(IsDateFormatString("0%"));
- Assert.False(IsDateFormatString("General"));
- Assert.False(IsDateFormatString(@"_-* #,##0\ _P_t_s_-;\-* #,##0\ _P_t_s_-;_-* "" - ""??\ _P_t_s_-;_-@_- "));
- }
-
- private static bool IsDateFormatString(string formatCode) => DateTimeHelper.IsDateTimeFormat(formatCode);
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
- [Fact]
- public void TestIssueI3X2ZL()
- {
- try
+ var users = new[]
{
- var path = PathHelper.GetFile("xlsx/TestIssueI3X2ZL_datetime_error.xlsx");
- var rows = _excelImporter.Query(path, startCell: "B3").ToList();
- }
- catch (InvalidCastException ex)
+ new { Name = "Jack", Age = 25 },
+ new { Name = "Mike", Age = 44 }
+ };
+ var department = new[]
{
- Assert.Equal(
- "The value error cannot be assigned to type DateTime.",
- ex.Message
- );
- }
+ new { ID = "01", Name = "HR" },
+ new { ID = "02", Name = "IT" }
+ };
+ var sheets = new Dictionary
+ {
+ ["users"] = users,
+ ["department"] = department
+ };
+ _excelExporter.Export(path, sheets);
+
+ var sheetNames = _excelImporter.GetSheetNames(path);
+ Assert.Equal("users", sheetNames[0]);
+ Assert.Equal("department", sheetNames[1]);
- try
{
- var path = PathHelper.GetFile("xlsx/TestIssueI3X2ZL_int_error.xlsx");
- var rows = _excelImporter.Query(path).ToList();
+ var rows = _excelImporter.Query(path, true, sheetName: "users").ToList();
+ Assert.Equal("Jack", rows[0].Name);
+ Assert.Equal(25, rows[0].Age);
+ Assert.Equal("Mike", rows[1].Name);
+ Assert.Equal(44, rows[1].Age);
}
- catch (InvalidCastException ex)
{
- Assert.Equal(
- "The value error cannot be assigned to type Int32.",
- ex.Message
- );
+ var rows = _excelImporter.Query(path, true, sheetName: "department").ToList();
+ Assert.Equal("01", rows[0].ID);
+ Assert.Equal("HR", rows[0].Name);
+ Assert.Equal("02", rows[1].ID);
+ Assert.Equal("IT", rows[1].Name);
}
}
- private class IssueI3X2ZLDTO
- {
- public int Col1 { get; set; }
- public DateTime Col2 { get; set; }
- }
-
- ///
- /// [SaveAsByTemplate support DateTime custom format · Issue #255 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/255)
- ///
+ // Support SaveAs by DataSet
+ [Fact]
+ public void Issue235()
+ {
+ using var path = AutoDeletingPath.Create();
+
+ var users = new DataTable { TableName = "users" };
+ users.Columns.Add("Name", typeof(string));
+ users.Columns.Add("Age", typeof(int));
+ users.Rows.Add("Jack", 25);
+ users.Rows.Add("Mike", 44);
+
+ var departments = new DataTable { TableName = "departments" };
+ departments.Columns.Add("ID");
+ departments.Columns.Add("Name");
+ departments.Rows.Add("01", "HR");
+ departments.Rows.Add("02", "IT");
+
+ DataSet dataSet = new();
+ dataSet.Tables.Add(users);
+ dataSet.Tables.Add(departments);
+
+ var rowsWritten = _excelExporter.Export(path.ToString(), dataSet);
+ Assert.Equal(2, rowsWritten.Length);
+ Assert.Equal(2, rowsWritten[0]);
+
+ var sheetNames = _excelImporter.GetSheetNames(path.ToString());
+ Assert.Equal("users", sheetNames[0]);
+ Assert.Equal("departments", sheetNames[1]);
+
+ var rows1 = _excelImporter.Query(path.ToString(), true, sheetName: "users").ToList();
+ Assert.Equal("Jack", rows1[0].Name);
+ Assert.Equal(25, rows1[0].Age);
+ Assert.Equal("Mike", rows1[1].Name);
+ Assert.Equal(44, rows1[1].Age);
+
+ var rows2 = _excelImporter.Query(path.ToString(), true, sheetName: "departments").ToList();
+ Assert.Equal("01", rows2[0].ID);
+ Assert.Equal("HR", rows2[0].Name);
+ Assert.Equal("02", rows2[1].ID);
+ Assert.Equal("IT", rows2[1].Name);
+ }
+
+ [Fact]
+ public void TestIssue240()
+ {
+ using var path = AutoDeletingPath.Create();
+ var templatePath = PathHelper.GetFile("xlsx/TestIssue24020201.xlsx");
+ var data = new Dictionary
+ {
+ ["title"] = "This's title",
+ ["B"] = new List>
+ {
+ new() { { "specialMark", 1 } },
+ new() { { "specialMark", 2 } },
+ new() { { "specialMark", 3 } },
+ }
+ };
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, data);
+ }
+
+ // Support Custom Datetime format
+ [Fact]
+ public void Issue241()
+ {
+ var date1 = new DateTime(2021, 01, 04);
+ var date2 = new DateTime(2020, 04, 05);
+
+ Issue241Dto[] value =
+ [
+ new() { Name = "Jack", InDate = date1 },
+ new() { Name = "Henry", InDate = date2 }
+ ];
+
+ using var file = AutoDeletingPath.Create();
+ var path = file.ToString();
+ var rowsWritten = _excelExporter.Export(path, value);
+
+ Assert.Single(rowsWritten);
+ Assert.Equal(2, rowsWritten[0]);
+
+ using var package = new ExcelPackage(path);
+ var cells = package.Workbook.Worksheets.First().Cells;
+
+ Assert.Equal(date1, DateTime.FromOADate((double)cells["B2"].Value));
+ Assert.Equal("01 04, 2021", cells["B2"].Text);
+ Assert.Equal(date2, DateTime.FromOADate((double)cells["B3"].Value));
+ Assert.Equal("04 05, 2020", cells["B3"].Text);
+ }
+
+ // No error exception throw when reading xls file #242
+ [Fact]
+ public void Issue242()
+ {
+ var path = PathHelper.GetFile("xls/TestIssue242.xls");
+ Assert.Throws(() => _excelImporter.Query(path).ToList());
+
+ using var stream = File.OpenRead(path);
+ Assert.Throws(() => _excelImporter.Query(stream).ToList());
+ }
+
+ // SaveAsByTemplate support DateTime custom format
[Fact]
public void Issue255()
{
@@ -1455,19 +1286,7 @@ public void Issue255()
}
}
- private class Issue255DTO
- {
- [MiniExcelFormat("yyyy")]
- public DateTime Time { get; set; }
-
- [MiniExcelColumn(Format = "yyyy")]
- public DateTime Time2 { get; set; }
- }
-
- ///
- /// [Dynamic Query custom format not using mapping format · Issue #256]
- /// (https://github.com/mini-software/MiniExcel/issues/256)
- ///
+ // Dynamic Query custom format not using mapping format
[Fact]
public void Issue256()
{
@@ -1477,1282 +1296,693 @@ public void Issue256()
Assert.Equal(new DateTime(2004, 4, 16), rows[1].B);
}
- ///
- /// No error exception throw when reading xls file #242
- ///
+ // custom format contains specific format (eg:`#,##0.000_);[Red]\(#,##0.000\)`), automatic converter will convert double to datetime
[Fact]
- public void Issue242()
+ public void TestIssue267()
{
- var path = PathHelper.GetFile("xls/TestIssue242.xls");
- Assert.Throws(() => _excelImporter.Query(path).ToList());
+ var path = PathHelper.GetFile("/xlsx/TestIssue267.xlsx");
+ var row = _excelImporter.Query(path).SingleOrDefault();
+ Assert.Equal(10618, row!.A);
+ Assert.Equal("2021-02-23", row.B);
+ Assert.Equal(43.199999999999996, row.C);
+ Assert.Equal(1.2, row.D);
+ Assert.Equal(new DateTime(2021, 7, 5), row.E);
+ Assert.Equal(new DateTime(2021, 7, 5, 15, 2, 46), row.F);
+ }
- using var stream = File.OpenRead(path);
- Assert.Throws(() => _excelImporter.Query(stream).ToList());
+ [Fact]
+ public void TestIssue268_DateFormat()
+ {
+ Assert.True(IsDateFormatString("dd/mm/yyyy"));
+ Assert.True(IsDateFormatString("dd-mmm-yy"));
+ Assert.True(IsDateFormatString("dd-mmmm"));
+ Assert.True(IsDateFormatString("mmm-yy"));
+ Assert.True(IsDateFormatString("h:mm AM/PM"));
+ Assert.True(IsDateFormatString("h:mm:ss AM/PM"));
+ Assert.True(IsDateFormatString("hh:mm"));
+ Assert.True(IsDateFormatString("hh:mm:ss"));
+ Assert.True(IsDateFormatString("dd/mm/yyyy hh:mm"));
+ Assert.True(IsDateFormatString("mm:ss"));
+ Assert.True(IsDateFormatString("mm:ss.0"));
+ Assert.True(IsDateFormatString("[$-809]dd mmmm yyyy"));
+ Assert.False(IsDateFormatString("#,##0;[Red]-#,##0"));
+ Assert.False(IsDateFormatString(@"#,##0.000_);[Red]\(#,##0.000\)"));
+ Assert.False(IsDateFormatString("0_);[Red](0)"));
+ Assert.False(IsDateFormatString(@"0\h"));
+ Assert.False(IsDateFormatString("0\"h\""));
+ Assert.False(IsDateFormatString("0%"));
+ Assert.False(IsDateFormatString("General"));
+ Assert.False(IsDateFormatString(@"_-* #,##0\ _P_t_s_-;\-* #,##0\ _P_t_s_-;_-* "" - ""??\ _P_t_s_-;_-@_- "));
}
///
- /// Support Custom Datetime format #241
+ /// Custom excel zip can't read and show Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory. #272
///
[Fact]
- public void Issue241()
+ public void TestIssue272()
{
- var date1 = new DateTime(2021, 01, 04);
- var date2 = new DateTime(2020, 04, 05);
+ var path = PathHelper.GetFile("/xlsx/TestIssue272.xlsx");
+ Assert.Throws(() => _excelImporter.Query(path).ToList());
+ }
- Issue241Dto[] value =
+ // Support column width attribute - https://github.com/mini-software/MiniExcel/issues/280
+ [Fact]
+ public void TestIssue280()
+ {
+ TestIssue280Dto[] value =
[
- new() { Name = "Jack", InDate = date1 },
- new() { Name = "Henry", InDate = date2 }
+ new() { ID = 1, Name = "Jack" },
+ new() { ID = 2, Name = "Mike" }
];
+ using var path = AutoDeletingPath.Create();
+ _excelExporter.Export(path.ToString(), value);
+ }
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
- var rowsWritten = _excelExporter.Export(path, value);
-
- Assert.Single(rowsWritten);
- Assert.Equal(2, rowsWritten[0]);
+ // Create Multiple Sheets from IDataReader is bugged
+ [Fact]
+ public void TestIssue283()
+ {
+ using var path = AutoDeletingPath.Create();
+ using (var cn = Db.GetConnection())
+ {
+ var sheets = new Dictionary
+ {
+ { "sheet01", cn.ExecuteReader("select 'v1' col1") },
+ { "sheet02", cn.ExecuteReader("select 'v2' col1") }
+ };
+ var rows = _excelExporter.Export(path.ToString(), sheets);
+ Assert.Equal(2, rows.Length);
+ }
- using var package = new ExcelPackage(path);
- var cells = package.Workbook.Worksheets.First().Cells;
+ var sheetNames = _excelImporter.GetSheetNames(path.ToString());
+ Assert.Equal(["sheet01", "sheet02"], sheetNames);
+ }
- Assert.Equal(date1, DateTime.FromOADate((double)cells["B2"].Value));
- Assert.Equal("01 04, 2021", cells["B2"].Text);
- Assert.Equal(date2, DateTime.FromOADate((double)cells["B3"].Value));
- Assert.Equal("04 05, 2020", cells["B3"].Text);
+ [Fact]
+ public void TestIssue286()
+ {
+ TestIssue286Dto[] values =
+ [
+ new() { E = TestIssue286Enum.VIP1 },
+ new() { E = TestIssue286Enum.VIP2 }
+ ];
+ using var path = AutoDeletingPath.Create();
+ _excelExporter.Export(path.ToString(), values);
+ var rows = _excelImporter.Query(path.ToString(), true).ToList();
+
+ Assert.Equal("VIP1", rows[0].E);
+ Assert.Equal("VIP2", rows[1].E);
}
- private class Issue241Dto
+ [Fact]
+ public void TestIssue289()
{
- public string Name { get; set; }
+ using var path = AutoDeletingPath.Create();
+ DescriptionEnumDto[] value =
+ [
+ new() { Name = "0001", UserType = DescriptionEnum.V1 },
+ new() { Name = "0002", UserType = DescriptionEnum.V2 },
+ new() { Name = "0003", UserType = DescriptionEnum.V3 }
+ ];
+ _excelExporter.Export(path.ToString(), value);
+
+ var rows = _excelImporter.Query(path.ToString()).ToList();
- [MiniExcelFormat("MM dd, yyyy")]
- public DateTime InDate { get; set; }
+ Assert.Equal(DescriptionEnum.V1, rows[0].UserType);
+ Assert.Equal(DescriptionEnum.V2, rows[1].UserType);
+ Assert.Equal(DescriptionEnum.V3, rows[2].UserType);
}
- ///
- /// SaveAs Default Template #132
- ///
+ /// Prefix and suffix blank space are lost after SaveAs - https://github.com/mini-software/MiniExcel/issues/294
[Fact]
- public void Issue132()
+ public void TestIssue294()
{
{
using var path = AutoDeletingPath.Create();
- var value = new[] {
- new { name = "Jack", Age = 25, InDate = new DateTime(2021,01,03)},
- new { name = "Henry", Age = 36, InDate = new DateTime(2020,05,03)},
- };
-
+ var value = new[] { new { Name = " Jack" } };
_excelExporter.Export(path.ToString(), value);
+ var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ Assert.Contains("xml:space=\"preserve\"", sheetXml);
}
-
{
using var path = AutoDeletingPath.Create();
- var value = new[]
- {
- new { name = "Jack", Age = 25, InDate = new DateTime(2021,01,03)},
- new { name = "Henry", Age = 36, InDate = new DateTime(2020,05,03)},
- };
- var config = new OpenXmlConfiguration
- {
- TableStyles = TableStyles.None
- };
- _excelExporter.Export(path.ToString(), value, configuration: config);
+ var value = new[] { new { Name = "Ja ck" } };
+ _excelExporter.Export(path.ToString(), value);
+ var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ Assert.DoesNotContain("xml:space=\"preserve\"", sheetXml);
}
-
{
using var path = AutoDeletingPath.Create();
+ var value = new[] { new { Name = "Jack " } };
+ _excelExporter.Export(path.ToString(), value);
+ var sheetXml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ Assert.Contains("xml:space=\"preserve\"", sheetXml);
+ }
+ }
- var dt = new DataTable();
- dt.Columns.Add("Name");
- dt.Columns.Add("Age");
- dt.Columns.Add("Date");
-
- dt.Rows.Add("Jack", 25, new DateTime(2021, 01, 03));
- dt.Rows.Add("Henry", 36, new DateTime(2021, 01, 03));
-
- _excelExporter.Export(path.ToString(), dt);
- }
- }
-
- ///
- /// Support SaveAs by DataSet #235
- ///
+ // SaveAs support Image type - https://github.com/mini-software/MiniExcel/issues/304
[Fact]
- public void Issue235()
+ public void TestIssue304()
{
- using var path = AutoDeletingPath.Create();
-
- var users = new DataTable { TableName = "users" };
- users.Columns.Add("Name", typeof(string));
- users.Columns.Add("Age", typeof(int));
- users.Rows.Add("Jack", 25);
- users.Rows.Add("Mike", 44);
-
- var departments = new DataTable { TableName = "departments" };
- departments.Columns.Add("ID");
- departments.Columns.Add("Name");
- departments.Rows.Add("01", "HR");
- departments.Rows.Add("02", "IT");
-
- DataSet dataSet = new();
- dataSet.Tables.Add(users);
- dataSet.Tables.Add(departments);
-
- var rowsWritten = _excelExporter.Export(path.ToString(), dataSet);
- Assert.Equal(2, rowsWritten.Length);
- Assert.Equal(2, rowsWritten[0]);
-
- var sheetNames = _excelImporter.GetSheetNames(path.ToString());
- Assert.Equal("users", sheetNames[0]);
- Assert.Equal("departments", sheetNames[1]);
-
- var rows1 = _excelImporter.Query(path.ToString(), true, sheetName: "users").ToList();
- Assert.Equal("Jack", rows1[0].Name);
- Assert.Equal(25, rows1[0].Age);
- Assert.Equal("Mike", rows1[1].Name);
- Assert.Equal(44, rows1[1].Age);
+ var path = PathHelper.GetTempFilePath();
+ var value = new[]
+ {
+ new { Name="github", Image=File.ReadAllBytes(PathHelper.GetFile("images/github_logo.png"))},
+ new { Name="google", Image=File.ReadAllBytes(PathHelper.GetFile("images/google_logo.png"))},
+ new { Name="microsoft", Image=File.ReadAllBytes(PathHelper.GetFile("images/microsoft_logo.png"))},
+ new { Name="reddit", Image=File.ReadAllBytes(PathHelper.GetFile("images/reddit_logo.png"))},
+ new { Name="stackoverflow", Image=File.ReadAllBytes(PathHelper.GetFile("images/stackoverflow_logo.png"))},
+ };
+ _excelExporter.Export(path, value);
- var rows2 = _excelImporter.Query(path.ToString(), true, sheetName: "departments").ToList();
- Assert.Equal("01", rows2[0].ID);
- Assert.Equal("HR", rows2[0].Name);
- Assert.Equal("02", rows2[1].ID);
- Assert.Equal("IT", rows2[1].Name);
+ Assert.Contains("/xl/media/", SheetHelper.GetZipFileContent(path, "xl/drawings/_rels/drawing1.xml.rels"));
+ Assert.Contains("ext cx=\"609600\" cy=\"190500\"", SheetHelper.GetZipFileContent(path, "xl/drawings/drawing1.xml"));
+ Assert.Contains("/xl/drawings/drawing1.xml", SheetHelper.GetZipFileContent(path, "[Content_Types].xml"));
+ Assert.Contains("drawing r:id=", SheetHelper.GetZipFileContent(path, "xl/worksheets/sheet1.xml"));
+ Assert.Contains("../drawings/drawing1.xml", SheetHelper.GetZipFileContent(path, "xl/worksheets/_rels/sheet1.xml.rels"));
}
- ///
- /// QueryAsDataTable A2=5.5 , A3=0.55/1.1 will case double type check error #233
- ///
+ // https://github.com/mini-software/MiniExcel/issues/305
[Fact]
- public void Issue233()
+ public async Task TestIssue305()
{
- var path = PathHelper.GetFile("xlsx/TestIssue233.xlsx");
-
- var dt = _excelImporter.QueryAsDataTable(path);
+ var dt = new DateTime(2022, 01, 22);
- var rows = dt.Rows;
+ using var path = AutoDeletingPath.Create();
+ TestIssueI49RZHDto[] value =
+ [
+ new() { dd = dt },
+ new() { dd = null }
+ ];
+ await _excelExporter.ExportAsync(path.FilePath, value, overwriteFile: true);
- Assert.Equal(0.55, rows[0]["Size"]);
- Assert.Equal("0.55/1.1", rows[1]["Size"]);
+ using var package = new ExcelPackage(path.ToString());
+ var cells = package.Workbook.Worksheets[0].Cells;
+
+ Assert.Equal(dt, DateTime.FromOADate((double)cells["A2"].Value));
+ Assert.Equal("22-01-2022", cells["A2"].Text);
}
- ///
- /// SaveAs support multiple sheets #234
- ///
[Fact]
- public void Issue234()
+ public async Task TestIssue307()
{
using var file = AutoDeletingPath.Create();
var path = file.ToString();
+ var value = new[] { new { id = 1, name = "Jack" } };
- var users = new[]
- {
- new { Name = "Jack", Age = 25 },
- new { Name = "Mike", Age = 44 }
- };
- var department = new[]
- {
- new { ID = "01", Name = "HR" },
- new { ID = "02", Name = "IT" }
- };
- var sheets = new Dictionary
- {
- ["users"] = users,
- ["department"] = department
- };
- _excelExporter.Export(path, sheets);
-
- var sheetNames = _excelImporter.GetSheetNames(path);
- Assert.Equal("users", sheetNames[0]);
- Assert.Equal("department", sheetNames[1]);
+ await _excelExporter.ExportAsync(path, value);
+ Assert.Throws(() => _excelExporter.Export(path, value));
- {
- var rows = _excelImporter.Query(path, true, sheetName: "users").ToList();
- Assert.Equal("Jack", rows[0].Name);
- Assert.Equal(25, rows[0].Age);
- Assert.Equal("Mike", rows[1].Name);
- Assert.Equal(44, rows[1].Age);
- }
- {
- var rows = _excelImporter.Query(path, true, sheetName: "department").ToList();
- Assert.Equal("01", rows[0].ID);
- Assert.Equal("HR", rows[0].Name);
- Assert.Equal("02", rows[1].ID);
- Assert.Equal("IT", rows[1].Name);
- }
+ await _excelExporter.ExportAsync(path, value, overwriteFile: true);
+ await Assert.ThrowsAsync(async () => await _excelExporter.ExportAsync(path, value));
+ await _excelExporter.ExportAsync(path, value, overwriteFile: true);
}
- ///
- /// SaveAs By Reader Closed error : 'Error! Invalid attempt to call FieldCount when reader is closed' #230
- /// https://github.com/mini-software/MiniExcel/issues/230
- ///
[Fact]
- public void Issue230()
+ public void TestIssue310()
{
- using var conn = Db.GetConnection("Data Source=:memory:");
- conn.Open();
- using var cmd = conn.CreateCommand();
- cmd.CommandText = "select 1 id union all select 2";
-
- using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
- {
- while (reader.Read())
- {
- for (int i = 0; i < reader.FieldCount; i++)
- {
- var result = $"{reader.GetName(i)} , {reader.GetValue(i)}";
- _output.WriteLine(result);
- }
- }
- }
-
- using var conn2 = Db.GetConnection("Data Source=:memory:");
- conn2.Open();
- using var cmd2 = conn2.CreateCommand();
- cmd2.CommandText = "select 1 id union all select 2";
- using (var reader = cmd2.ExecuteReader(CommandBehavior.CloseConnection))
- {
- while (reader.Read())
- {
- for (int i = 0; i < reader.FieldCount; i++)
- {
- var result = $"{reader.GetName(i)}, {reader.GetValue(i)}";
- _output.WriteLine(result);
- }
- }
- }
+ using var path = AutoDeletingPath.Create();
+ var value = new[] { new TestIssue310Dto { V1 = null }, new TestIssue310Dto { V1 = 2 } };
+ _excelExporter.Export(path.ToString(), value);
+ var rows = _excelImporter.Query(path.ToString()).ToList();
+ }
- using var conn3 = Db.GetConnection("Data Source=:memory:");
- conn3.Open();
- using var cmd3 = conn3.CreateCommand();
- cmd3.CommandText = "select 1 id union all select 2";
- using (var reader = cmd3.ExecuteReader(CommandBehavior.CloseConnection))
+ [Fact]
+ public void TestIssue310_Fix497()
+ {
+ using var path = AutoDeletingPath.Create();
+ var value = new[]
{
- using var path = AutoDeletingPath.Create();
- _excelExporter.Export(path.ToString(), reader, printHeader: true);
- var rows = _excelImporter.Query(path.ToString(), true).ToList();
- Assert.Equal(1, rows[0].id);
- Assert.Equal(2, rows[1].id);
- }
+ new TestIssue310Dto { V1 = null },
+ new TestIssue310Dto { V1 = 2 }
+ };
+ _excelExporter.Export(path.ToString(), value, configuration: new OpenXmlConfiguration { EnableWriteNullValueCell = false });
+ var rows = _excelImporter.Query(path.ToString()).ToList();
}
- ///
- /// v0.14.3 QueryAsDataTable error "Cannot set Column to be null" #229
- /// https://github.com/mini-software/MiniExcel/issues/229
- ///
[Fact]
- public void Issue229()
+ public void TestIssue312()
{
- var path = PathHelper.GetFile("xlsx/TestIssue229.xlsx");
+ using var path = AutoDeletingPath.Create();
+ TestIssue312Dto[] value =
+ [
+ new() { Value = 12_345.6789 },
+ new() { Value = null }
+ ];
+ _excelExporter.Export(path.ToString(), value);
- using var dt = _excelImporter.QueryAsDataTable(path);
+ using var package = new ExcelPackage(path.ToString());
+ var cells = package.Workbook.Worksheets[0].Cells;
- foreach (DataColumn column in dt.Columns)
- {
- var v = dt.Rows[3][column];
- Assert.Equal(DBNull.Value, v);
- }
+ var fmt = cells["A2"].Style.Numberformat.Format;
+ Assert.Equal(12_345.68.ToString(fmt), cells["A2"].Text);
+ Assert.Equal(12_345.6789, (double)cells["A2"].Value);
}
- ///
- /// [Query Merge cells data · Issue #122 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/122)
- ///
+ // SaveAs and Query support btye[] base64 converter - https://github.com/mini-software/MiniExcel/issues/318
[Fact]
- public void Issue122()
+ public void TestIssue318()
{
- var config = new OpenXmlConfiguration
+ var imageByte = File.ReadAllBytes(PathHelper.GetFile("images/github_logo.png"));
+ using var path = AutoDeletingPath.Create();
+ var value = new[]
{
- FillMergedCells = true
+ new { Name="github", Image=imageByte},
};
+ _excelExporter.Export(path.ToString(), value);
+
+
+ // import to byte[]
{
- var path = PathHelper.GetFile("xlsx/TestIssue122.xlsx");
- {
- var rows = _excelImporter.Query(path, hasHeaderRow: true, configuration: config).ToList();
- Assert.Equal("HR", rows[0].Department);
- Assert.Equal("HR", rows[1].Department);
- Assert.Equal("HR", rows[2].Department);
- Assert.Equal("IT", rows[3].Department);
- Assert.Equal("IT", rows[4].Department);
- Assert.Equal("IT", rows[5].Department);
- }
+ const string expectedBase64 = "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAEXRFWHRTb2Z0d2FyZQBTbmlwYXN0ZV0Xzt0AAALNSURBVEiJ7ZVLTBNBGMdndrfdIofy0ERbCgcFeYRuCy2JGOPNRA9qeIZS6YEEogQj0YMmGOqDSATxQaLRxKtRID4SgjGelUBpaQvGZ7kpII8aWtjd2dkdDxsJoS1pIh6M/k+z8833m/3+8+0OJISArRa15cT/0D8CZTYPe32+Zy+GxjzjMzOzAACDYafdZquqOG7hzJtkwUQthRC6cavv0eN+QRTBujUQQp1OV1dbffZMq1arTRaqKIok4eZTrSNjHqIo6gIIIQBgbQwpal+Z/f7dPo2GoaiNHtJut3vjPhBe7+kdfvW61Mq1nGyaX1xYjkRzsk2Z6Rm8IOTvzWs73SLwwqjHK4jCgf3lcV6VxGgiECji7AXm0gvtHYQQnue/zy8ghCRJWlxaWuV5Qsilq9cKzLYiiz04ORVLiHP6A4NPRQlhjLWsVpZlnU63Y3umRqNhGCYjPV3HsrIsMwyDsYQQejIwGEuIA/WMT1AAaDSahnoHTdPKL1vXPKVp2umoZVkWAOj1+ZOCzs7NKYTo9XqjYRcAgKIo9ZRUu9VxltGYZTQAAL5+m0kKijEmAPCrqyJCcRuOECKI4lL4ByEEYykpaE62iQIgurLi9wchhLIsry8fYwwh9PomwuEwACDbZEoKauHMgKJSU1PbOy6Hpqdpml5fPsMwn7+EOru6IYQAghKrJSloTVUFURSX02G3lRw+WulqbA4EJ9XQh4+f2s6dr65zhkLTEEIKwtqaylhCnG/fauFO1Nfde/Bw6Hm/0WiYevc+LU2vhlK2pQwNvwQAsCwrYexyOrji4lhCnOaXZRljXONoOHTk2Ju3I/5AcC3EC0JZ+cE9Bea8IqursUkUker4BsWBqpIk6aL7Sm4htzvfvByJqJORaDS3kMsvLuns6kYIJcpNCFU17pvouXlHEET1URDEnt7bo2OezbMS/vp+R3/PdfKPQ38Ccg0E/CDcpY8AAAAASUVORK5CYII=";
+ var rows = _excelImporter.Query(path.ToString(), true).ToList();
+ var actulBase64 = Convert.ToBase64String((byte[])rows[0].Image);
+ Assert.Equal(expectedBase64, actulBase64);
}
+ // import to base64 string
{
- var path = PathHelper.GetFile("xlsx/TestIssue122_2.xlsx");
- {
- var rows = _excelImporter.Query(path, hasHeaderRow: true, configuration: config).ToList();
- Assert.Equal("V1", rows[2].Test1);
- Assert.Equal("V2", rows[5].Test2);
- Assert.Equal("V3", rows[1].Test3);
- Assert.Equal("V4", rows[2].Test4);
- Assert.Equal("V5", rows[3].Test5);
- Assert.Equal("V6", rows[5].Test5);
- }
+ var config = new OpenXmlConfiguration { EnableConvertByteArray = false };
+ var rows = _excelImporter.Query(path.ToString(), true, configuration: config).ToList();
+ var image = (string)rows[0].Image;
+ Assert.StartsWith("@@@fileid@@@,xl/media/", image);
}
- }
- ///
- /// [Support Xlsm AutoCheck · Issue #227 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/227)
- ///
+ }
+
+ // https://github.com/mini-software/MiniExcel/issues/325
[Fact]
- public void Issue227()
+ public void TestIssue325()
{
+ using var path = AutoDeletingPath.Create();
+ var value = new Dictionary
{
- var path = PathHelper.GetTempPath("xlsm");
- Assert.Throws(() => _excelExporter.Export(path, new[] { new { V = "A1" }, new { V = "A2" } }));
- File.Delete(path);
- }
+ { "sheet1",new[]{ new { id = 1, date = DateTime.Parse("2022-01-01") } }},
+ { "sheet2",new[]{ new { id = 2, date = DateTime.Parse("2022-01-01") } }},
+ };
+ _excelExporter.Export(path.ToString(), value);
- {
- var path = PathHelper.GetFile("xlsx/TestIssue227.xlsm");
- {
- var rows = _excelImporter.Query(path).ToList();
- Assert.Equal(100, rows.Count);
-
- Assert.Equal(Guid.Parse("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows[0].ID);
- Assert.Equal("Wade", rows[0].Name);
- Assert.Equal(DateTime.ParseExact("27/09/2020", "dd/MM/yyyy", CultureInfo.InvariantCulture), rows[0].BoD);
- Assert.Equal(36, rows[0].Age);
- Assert.False(rows[0].VIP);
- Assert.Equal(5019.12m, rows[0].Points);
- Assert.Equal(1, rows[0].IgnoredProperty);
- }
- {
- using var stream = File.OpenRead(path);
- var rows = _excelImporter.Query(stream).ToList();
- Assert.Equal(100, rows.Count);
-
- Assert.Equal(Guid.Parse("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows[0].ID);
- Assert.Equal("Wade", rows[0].Name);
- Assert.Equal(DateTime.ParseExact("27/09/2020", "dd/MM/yyyy", CultureInfo.InvariantCulture), rows[0].BoD);
- Assert.Equal(36, rows[0].Age);
- Assert.False(rows[0].VIP);
- Assert.Equal(5019.12m, rows[0].Points);
- Assert.Equal(1, rows[0].IgnoredProperty);
- }
- }
-
-
- }
-
- ///
- /// https://github.com/mini-software/MiniExcel/issues/226
- /// Fix SaveAsByTemplate single column dimension index error #226
- ///
- [Fact]
- public void Issue226()
- {
- using var path = AutoDeletingPath.Create();
- var templatePath = PathHelper.GetFile("xlsx/TestIssue226.xlsx");
- _excelTemplater.FillTemplate(path.ToString(), templatePath, new { employees = new[] { new { name = "123" }, new { name = "123" } } });
- Assert.Equal("A1:A3", SheetHelper.GetFirstSheetDimensionRefValue(path.ToString()));
- }
-
- ///
- /// ASP.NET Webform gridview datasource can't use miniexcel queryasdatatable · Issue #223]
- /// (https://github.com/mini-software/MiniExcel/issues/223)
- ///
- [Fact]
- public void Issue223()
- {
- List> value =
- [
- new() { { "A", null }, { "B", null } },
- new() { { "A", 123 }, { "B", new DateTime(2021, 1, 1) } },
- new() { { "A", Guid.NewGuid() }, { "B", "HelloWorld" } }
- ];
- using var path = AutoDeletingPath.Create();
- _excelExporter.Export(path.ToString(), value);
-
- using var dt = _excelImporter.QueryAsDataTable(path.ToString());
-
- var columns = dt.Columns;
- Assert.Equal(typeof(object), columns[0].DataType);
- Assert.Equal(typeof(object), columns[1].DataType);
-
- Assert.Equal(123.0, dt.Rows[1]["A"]);
- Assert.Equal("HelloWorld", dt.Rows[2]["B"]);
- }
-
- ///
- /// [Custom yyyy-MM-dd format not convert datetime · Issue #222]
- /// (https://github.com/mini-software/MiniExcel/issues/222)
- ///
- [Fact]
- public void Issue222()
- {
- var path = PathHelper.GetFile("xlsx/TestIssue222.xlsx");
- var rows = _excelImporter.Query(path).ToList();
- Assert.Equal(typeof(DateTime), rows[1].A.GetType());
- Assert.Equal(new DateTime(2021, 4, 29), rows[1].A);
- }
-
- ///
- /// Query Support StartCell #147
- /// https://github.com/mini-software/MiniExcel/issues/147
- ///
- [Fact]
- public void Issue147()
- {
- {
- var path = PathHelper.GetFile("xlsx/TestIssue147.xlsx");
- var rows = _excelImporter.Query(path, hasHeaderRow: false, startCell: "C3", sheetName: "Sheet1").ToList();
-
- Assert.Equal(["C", "D", "E"], (rows[0] as IDictionary)?.Keys);
- Assert.Equal(["Column1", "Column2", "Column3"], new[] { rows[0].C as string, rows[0].D as string, rows[0].E as string });
- Assert.Equal(["C4", "D4", "E4"], new[] { rows[1].C as string, rows[1].D as string, rows[1].E as string });
- Assert.Equal(["C9", "D9", "E9"], new[] { rows[6].C as string, rows[6].D as string, rows[6].E as string });
- Assert.Equal(["C12", "D12", "E12"], new[] { rows[9].C as string, rows[9].D as string, rows[9].E as string });
- Assert.Equal(["C13", "D13", "E13"], new[] { rows[10].C as string, rows[10].D as string, rows[10].E as string });
- foreach (var i in new[] { 4, 5, 7, 8 })
- Assert.Equal(expected: [null, null, null], new[] { rows[i].C as string, rows[i].D as string, rows[i].E as string });
-
- Assert.Equal(11, rows.Count);
-
-
- var columns = _excelImporter.GetColumnNames(path, startCell: "C3");
- Assert.Equal(["C", "D", "E"], columns);
- }
-
- {
- var path = PathHelper.GetFile("xlsx/TestIssue147.xlsx");
- var rows = _excelImporter.Query(path, hasHeaderRow: true, startCell: "C3", sheetName: "Sheet1").ToList();
-
- Assert.Equal(["Column1", "Column2", "Column3"], (rows[0] as IDictionary)?.Keys);
- Assert.Equal(["C4", "D4", "E4"], new[] { rows[0].Column1 as string, rows[0].Column2 as string, rows[0].Column3 as string });
- Assert.Equal(["C9", "D9", "E9"], new[] { rows[5].Column1 as string, rows[5].Column2 as string, rows[5].Column3 as string });
- Assert.Equal(["C12", "D12", "E12"], new[] { rows[8].Column1 as string, rows[8].Column2 as string, rows[8].Column3 as string });
- Assert.Equal(["C13", "D13", "E13"], new[] { rows[9].Column1 as string, rows[9].Column2 as string, rows[9].Column3 as string });
- foreach (var i in new[] { 3, 4, 6, 7 })
- Assert.Equal([null, null, null], new[] { rows[i].Column1 as string, rows[i].Column2 as string, rows[i].Column3 as string });
-
- Assert.Equal(10, rows.Count);
-
- var columns = _excelImporter.GetColumnNames(path, hasHeaderRow: true, startCell: "C3");
- Assert.Equal(["Column1", "Column2", "Column3"], columns);
- }
- }
-
-
- ///
- /// [Can SaveAs support iDataReader export to avoid the dataTable consuming too much memory · Issue #211 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/211)
- ///
- [Fact]
- public void Issue211()
- {
- using var path = AutoDeletingPath.Create();
- var tempSqlitePath = AutoDeletingPath.Create(Path.GetTempPath(), $"{Guid.NewGuid()}.db");
- var connectionString = $"Data Source={tempSqlitePath};Version=3;";
-
- using var connection = new SQLiteConnection(connectionString);
- var reader = connection.ExecuteReader(@"select 1 Test1,2 Test2 union all select 3 , 4 union all select 5 ,6");
- _excelExporter.Export(path.ToString(), reader);
- var rows = _excelImporter.Query(path.ToString(), true).ToList();
-
- Assert.Equal(1.0, rows[0].Test1);
- Assert.Equal(2.0, rows[0].Test2);
- Assert.Equal(3.0, rows[1].Test1);
- Assert.Equal(4.0, rows[1].Test2);
+ var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/_rels/sheet2.xml.rels");
+ var cnt = Regex.Matches(xml, "Id=\"drawing2\"").Count;
+ Assert.True(cnt == 1);
}
- ///
- /// [When reading Excel, can return IDataReader and DataTable to facilitate the import of database. Like ExcelDataReader provide reader.AsDataSet() · Issue #216 · mini-software/MiniExcel](https://github.com/mini-software/MiniExcel/issues/216)
- ///
[Fact]
- public void Issue216()
+ public void TestIssue327()
{
using var path = AutoDeletingPath.Create();
var value = new[]
{
- new { Test1 = "1", Test2 = 2 },
- new { Test1 = "3", Test2 = 4 }
+ new { id = 1, file = File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.png")) },
+ new { id = 2, file = File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.txt")) },
+ new { id = 3, file = File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.html")) },
};
_excelExporter.Export(path.ToString(), value);
+ var rows = _excelImporter.Query(path.ToString(), true).ToList();
- {
- using var table = _excelImporter.QueryAsDataTable(path.ToString());
-
- Assert.Equal("Test1", table.Columns[0].ColumnName);
- Assert.Equal("Test2", table.Columns[1].ColumnName);
- Assert.Equal("1", table.Rows[0]["Test1"]);
- Assert.Equal(2.0, table.Rows[0]["Test2"]);
- Assert.Equal("3", table.Rows[1]["Test1"]);
- Assert.Equal(4.0, table.Rows[1]["Test2"]);
- }
-
- {
- using var dt = _excelImporter.QueryAsDataTable(path.ToString(), false);
-
- Assert.Equal("Test1", dt.Rows[0]["A"]);
- Assert.Equal("Test2", dt.Rows[0]["B"]);
- Assert.Equal("1", dt.Rows[1]["A"]);
- Assert.Equal(2.0, dt.Rows[1]["B"]);
- Assert.Equal("3", dt.Rows[2]["A"]);
- Assert.Equal(4.0, dt.Rows[2]["B"]);
- }
- }
-
- ///
- /// https://gitee.com/dotnetchina/MiniExcel/issues/I3OSKV
- /// When exporting, the pure numeric string will be forcibly converted to a numeric type, resulting in the loss of the end data
- ///
- [Fact]
- public void IssueI3OSKV()
- {
- {
- using var path = AutoDeletingPath.Create();
- var value = new[] { new { Test = "12345678901234567890" } };
- _excelExporter.Export(path.ToString(), value);
-
- var A2 = _excelImporter.Query(path.ToString(), true).First().Test;
- Assert.Equal("12345678901234567890", A2);
- }
-
- {
- using var path = AutoDeletingPath.Create();
- var value = new[] { new { Test = 123456.789 } };
- _excelExporter.Export(path.ToString(), value);
-
- var A2 = _excelImporter.Query(path.ToString(), true).First().Test;
- Assert.Equal(123456.789, A2);
- }
- }
-
-
- ///
- /// [Dynamic Query can't summary numeric cell value default, need to cast · Issue #220 · mini-software/MiniExcel]
- /// (https://github.com/mini-software/MiniExcel/issues/220)
- ///
- [Fact]
- public void Issue220()
- {
- var path = PathHelper.GetFile("xlsx/TestIssue220.xlsx");
- var rows = _excelImporter.Query(path, hasHeaderRow: true);
- var result = rows
- .GroupBy(s => s.PRT_ID)
- .Select(g => new
- {
- PRT_ID = g.Key,
- Apr = g.Sum(x => (double?)x.Apr),
- May = g.Sum(x => (double?)x.May),
- Jun = g.Sum(x => (double?)x.Jun)
- })
- .ToList();
-
- Assert.Equal(91843.25, result[0].Jun);
- Assert.Equal(50000.99, result[1].Jun);
- }
-
- ///
- /// Optimize stream excel type check
- /// https://github.com/mini-software/MiniExcel/issues/215
- ///
- [Fact]
- public void Issue215()
- {
- using var stream = new MemoryStream();
- _excelExporter.Export(stream, new[] { new { V = "test1" }, new { V = "test2" } });
- var rows = _excelImporter.Query(stream, true).ToList();
-
- Assert.Equal("test1", rows[0].V);
- Assert.Equal("test2", rows[1].V);
- }
-
- ///
- /// DataTable recommended to use Caption for column name first, then use columname
- /// https://github.com/mini-software/MiniExcel/issues/217
- ///
- [Fact]
- public void Issue217()
- {
- using var table = new DataTable();
- table.Columns.Add("CustomerID");
- table.Columns.Add("CustomerName").Caption = "Name";
- table.Columns.Add("CreditLimit").Caption = "Limit";
- table.Rows.Add(1, "Jonathan", 23.44);
- table.Rows.Add(2, "Bill", 56.87);
-
- using var path = AutoDeletingPath.Create();
- _excelExporter.Export(path.ToString(), table);
-
- var rows = _excelImporter.Query(path.ToString()).ToList();
- Assert.Equal("Name", rows[0].B);
- Assert.Equal("Limit", rows[0].C);
+ Assert.Equal(value[0].file, rows[0].file);
+ Assert.Equal(value[1].file, rows[1].file);
+ Assert.Equal(value[2].file, rows[2].file);
+ Assert.Equal("Hello MiniExcel", Encoding.UTF8.GetString(rows[1].file));
+ Assert.Equal("Hello MiniExcel", Encoding.UTF8.GetString(rows[2].file));
}
- ///
- /// _ _exporter.Export(path, table,sheetName:“Name”) ,the actual sheetName is Sheet1
- /// https://github.com/mini-software/MiniExcel/issues/212
- ///
[Fact]
- public void Issue212()
+ public void TestIssue328()
{
- const string sheetName = "Demo";
using var path = AutoDeletingPath.Create();
- _excelExporter.Export(path.ToString(), new[] { new { x = 1, y = 2 } }, sheetName: sheetName);
-
- var actualSheetName = _excelImporter.GetSheetNames(path.ToString()).ToList()[0];
- Assert.Equal(sheetName, actualSheetName);
- }
-
- ///
- /// Version <= v0.13.1 Template merge row list rendering has no merge
- /// https://github.com/mini-software/MiniExcel/issues/207
- ///
- [Fact]
- public void Issue207()
- {
+ var value = new[]
{
- var tempaltePath = PathHelper.GetFile("xlsx/TestIssue207_2.xlsx");
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
-
- var value = new
+ new
{
- project = new[] {
- new {name = "項目1",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
- new {name = "項目2",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
- new {name = "項目3",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
- new {name = "項目4",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
- }
- };
-
- _excelTemplater.FillTemplate(path, tempaltePath, value);
- var rows = _excelImporter.Query(path).ToList();
-
- Assert.Equal("項目1", rows[0].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[0].B);
- Assert.Equal("項目2", rows[2].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[2].B);
- Assert.Equal("項目3", rows[4].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[4].B);
- Assert.Equal("項目4", rows[6].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[6].B);
-
- Assert.Equal("Test1", rows[8].A);
- Assert.Equal("Test2", rows[8].B);
- Assert.Equal("Test3", rows[8].C);
-
- Assert.Equal("項目1", rows[12].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[12].B);
- Assert.Equal("項目2", rows[13].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[13].B);
- Assert.Equal("項目3", rows[14].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[14].B);
- Assert.Equal("項目4", rows[15].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[15].B);
-
- var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path);
- Assert.Equal("A1:C16", dimension);
- }
-
- {
- var tempaltePath = PathHelper.GetFile("xlsx/TestIssue207_Template_Merge_row_list_rendering_without_merge/template.xlsx");
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
-
- var value = new
+ id=1,
+ name="Jack",
+ indate=new DateTime(2022,5,13),
+ file = File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.png"))
+ },
+ new
{
- project = new[] {
- new {name = "項目1",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
- new {name = "項目2",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
- new {name = "項目3",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
- new {name = "項目4",content="[]內容1,[]內容2,[]內容3,[]內容4,[]內容5"},
- }
- };
-
- _excelTemplater.FillTemplate(path, tempaltePath, value);
- var rows = _excelImporter.Query(path).ToList();
-
- Assert.Equal("項目1", rows[0].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[0].C);
- Assert.Equal("項目2", rows[3].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[3].C);
- Assert.Equal("項目3", rows[6].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[6].C);
- Assert.Equal("項目4", rows[9].A);
- Assert.Equal("[]內容1,[]內容2,[]內容3,[]內容4,[]內容5", rows[9].C);
- var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path);
- Assert.Equal("A1:E15", dimension);
- }
- }
-
- ///
- /// https://github.com/mini-software/MiniExcel/issues/87
- ///
- [Fact]
- public void Issue87()
- {
- var templatePath = PathHelper.GetFile("xlsx/TestTemplateCenterEmpty.xlsx");
- using var path = AutoDeletingPath.Create();
- var value = new
- {
- Tests = Enumerable.Range(1, 5).Select((_, i) => new { test1 = i, test2 = i })
+ id=2,
+ name="Henry",
+ indate=new DateTime(2022,4,10),
+ file = File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.txt"))
+ },
};
+ _excelExporter.Export(path.ToString(), value);
- var rows = _excelImporter.Query(templatePath).ToList();
- _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
- }
-
- ///
- /// https://github.com/mini-software/MiniExcel/issues/208
- ///
- [Fact]
- public void Issue208()
- {
- var path = PathHelper.GetFile("xlsx/TestIssue208.xlsx");
- var columns = _excelImporter.GetColumnNames(path).ToList();
- Assert.Equal(16384, columns.Count);
- Assert.Equal("XFD", columns[16383]);
- }
-
- ///
- /// https://github.com/mini-software/MiniExcel/issues/206
- ///
- [Fact]
- public void Issue206()
- {
- {
- var templatePath = PathHelper.GetFile("xlsx/TestTemplateBasicIEmumerableFill.xlsx");
- using var path = AutoDeletingPath.Create();
-
- var dt = new DataTable();
- {
- dt.Columns.Add("name");
- dt.Columns.Add("department");
- }
- var value = new Dictionary
- {
- ["employees"] = dt
- };
- _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
-
- var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path.ToString());
- Assert.Equal("A1:B2", dimension);
- }
-
- {
- var templatePath = PathHelper.GetFile("xlsx/TestTemplateBasicIEmumerableFill.xlsx");
- using var path = AutoDeletingPath.Create();
-
- using var dt = new DataTable();
- dt.Columns.Add("name");
- dt.Columns.Add("department");
- dt.Rows.Add("Jack", "HR");
-
- var value = new Dictionary { ["employees"] = dt };
- _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
-
- var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path.ToString());
- Assert.Equal("A1:B2", dimension);
- }
- }
-
-
- ///
- /// https://github.com/mini-software/MiniExcel/issues/193
- ///
- [Fact]
- public void Issue193()
- {
- {
- var templatePath = PathHelper.GetFile("xlsx/TestTemplateComplexWithNamespacePrefix.xlsx");
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
-
- // 1. By Class
- var value = new
- {
- title = "FooCompany",
- managers = new[]
- {
- new { name = "Jack", department = "HR" },
- new { name = "Loan", department = "IT" }
- },
- employees = new[]
- {
- new { name = "Wade", department = "HR" },
- new { name = "Felix", department = "HR" },
- new { name = "Eric", department = "IT" },
- new { name = "Keaton", department = "IT" }
- }
- };
- _excelTemplater.FillTemplate(path, templatePath, value);
-
- foreach (var sheetName in _excelImporter.GetSheetNames(path))
- {
- var rows = _excelImporter.Query(path, sheetName: sheetName).ToList();
- Assert.Equal(9, rows.Count);
-
- Assert.Equal("FooCompany", rows[0].A);
- Assert.Equal("Jack", rows[2].B);
- Assert.Equal("HR", rows[2].C);
- Assert.Equal("Loan", rows[3].B);
- Assert.Equal("IT", rows[3].C);
-
- Assert.Equal("Wade", rows[5].B);
- Assert.Equal("HR", rows[5].C);
- Assert.Equal("Felix", rows[6].B);
- Assert.Equal("HR", rows[6].C);
-
- Assert.Equal("Eric", rows[7].B);
- Assert.Equal("IT", rows[7].C);
- Assert.Equal("Keaton", rows[8].B);
- Assert.Equal("IT", rows[8].C);
-
- var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path);
- Assert.Equal("A1:C9", dimension);
-
- /*TODO:row can't contain xmlns*/
- // https://user-images.githubusercontent.com/12729184/114998840-ead44500-9ed3-11eb-8611-58afb98faed9.png
-
- }
- }
-
- {
- var templatePath = PathHelper.GetFile("xlsx/TestTemplateComplex.xlsx");
- using var path = AutoDeletingPath.Create();
-
- // 2. By Dictionary
- var value = new Dictionary
- {
- ["title"] = "FooCompany",
- ["managers"] = new[] {
- new {name="Jack",department="HR"},
- new {name="Loan",department="IT"}
- },
- ["employees"] = new[] {
- new {name="Wade",department="HR"},
- new {name="Felix",department="HR"},
- new {name="Eric",department="IT"},
- new {name="Keaton",department="IT"}
- }
- };
- _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
- var rows = _excelImporter.Query(path.ToString()).ToList();
-
- Assert.Equal("FooCompany", rows[0].A);
- Assert.Equal("Jack", rows[2].B);
- Assert.Equal("HR", rows[2].C);
- Assert.Equal("Loan", rows[3].B);
- Assert.Equal("IT", rows[3].C);
-
- Assert.Equal("Wade", rows[5].B);
- Assert.Equal("HR", rows[5].C);
- Assert.Equal("Felix", rows[6].B);
- Assert.Equal("HR", rows[6].C);
-
- Assert.Equal("Eric", rows[7].B);
- Assert.Equal("IT", rows[7].C);
- Assert.Equal("Keaton", rows[8].B);
- Assert.Equal("IT", rows[8].C);
-
- var dimension = SheetHelper.GetFirstSheetDimensionRefValue(path.ToString());
- Assert.Equal("A1:C9", dimension);
- }
- }
-
- ///
- /// https://github.com/mini-software/MiniExcel/issues/150
- ///
- [Fact]
- public void Issue150()
- {
- var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx");
-
- Assert.Throws(() => _excelExporter.Export(path, new[] { 1, 2 }));
- File.Delete(path);
-
- Assert.Throws(() => _excelExporter.Export(path, new[] { "1", "2" }));
- File.Delete(path);
-
- Assert.Throws(() => _excelExporter.Export(path, new[] { '1', '2' }));
- File.Delete(path);
-
- Assert.Throws(() => _excelExporter.Export(path, new[] { DateTime.Now }));
- File.Delete(path);
-
- Assert.Throws(() => _excelExporter.Export(path, new[] { Guid.NewGuid() }));
- File.Delete(path);
- }
-
- ///
- /// https://github.com/mini-software/MiniExcel/issues/157
- ///
- [Fact]
- public void Issue157()
- {
- {
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
-
- List data =
- [
- new()
- {
- ID = new Guid("78de23d2-dcb6-bd3d-ec67-c112bbc322a2"),
- Name = "Wade",
- BoD = new DateTime(2020, 9, 27),
- Points = 5019.12m
- },
- new()
- {
- ID = new Guid("20d3bfce-27c3-ad3e-4f70-35c81c7e8e45"),
- Name = "Felix",
- BoD = new DateTime(2020, 10, 25),
- Points = 7028.46m
- },
- new()
- {
- ID = new Guid("52013bf0-9aeb-48e6-e5f5-e9500afb034f"),
- Name = "Phelan",
- BoD = new DateTime(2020, 10, 25),
- Points = 3835.7m,
- VIP = true
- },
- new()
- {
- ID = new Guid("3b97b87c-7afe-664f-1af5-6914d313ae25"),
- Name = "Samuel",
- BoD = new DateTime(2020, 6, 21),
- Points = 9351.71m
- },
- new()
- {
- ID = new Guid("9a989c43-d55f-5306-0d2f-0fbafae135bb"),
- Name = "Raymond",
- BoD = new DateTime(2021, 7, 12),
- Points = 8209.76m,
- VIP = true
- }
- ];
-
- _excelExporter.Export(path, data);
-
- var rows = _excelImporter.Query(path, sheetName: "Sheet1").ToList();
- Assert.Equal(6, rows.Count);
- Assert.Equal("Sheet1", _excelImporter.GetSheetNames(path).First());
-
- using var p = new ExcelPackage(new FileInfo(path));
- var ws = p.Workbook.Worksheets.First();
- Assert.Equal("Sheet1", ws.Name);
- Assert.Equal("Sheet1", p.Workbook.Worksheets["Sheet1"].Name);
- }
- {
- var path = PathHelper.GetFile("xlsx/TestIssue157.xlsx");
+ var rowIndx = 0;
+ using var reader = _excelImporter.GetDataReader(path.ToString(), true);
- {
- var rows = _excelImporter.Query(path, sheetName: "Sheet1").ToList();
- Assert.Equal(6, rows.Count);
- Assert.Equal("Sheet1", _excelImporter.GetSheetNames(path).First());
- }
- using (var p = new ExcelPackage(new FileInfo(path)))
- {
- var ws = p.Workbook.Worksheets.First();
- Assert.Equal("Sheet1", ws.Name);
- Assert.Equal("Sheet1", p.Workbook.Worksheets["Sheet1"].Name);
- }
+ Assert.Equal("id", reader.GetName(0));
+ Assert.Equal("name", reader.GetName(1));
+ Assert.Equal("indate", reader.GetName(2));
+ Assert.Equal("file", reader.GetName(3));
+ while (reader.Read())
+ {
+ for (int i = 0; i < reader.FieldCount; i++)
{
- var rows = _excelImporter.Query(path, sheetName: "Sheet1").ToList();
- Assert.Equal(5, rows.Count);
-
- Assert.Equal(new Guid("78DE23D2-DCB6-BD3D-EC67-C112BBC322A2"), rows[0].ID);
- Assert.Equal("Wade", rows[0].Name);
- Assert.Equal(new DateTime(2020,9,27), rows[0].BoD);
- Assert.False(rows[0].VIP);
- Assert.Equal(5019.12m, rows[0].Points);
- Assert.Equal(1, rows[0].IgnoredProperty);
+ var v = reader.GetValue(i);
+ if (rowIndx == 0 && i == 0) Assert.Equal(1.0, v);
+ if (rowIndx == 0 && i == 1) Assert.Equal("Jack", v);
+ if (rowIndx == 0 && i == 2) Assert.Equal(new DateTime(2022, 5, 13), v);
+ if (rowIndx == 0 && i == 3) Assert.Equal(File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.png")), v);
+ if (rowIndx == 1 && i == 0) Assert.Equal(2.0, v);
+ if (rowIndx == 1 && i == 1) Assert.Equal("Henry", v);
+ if (rowIndx == 1 && i == 2) Assert.Equal(new DateTime(2022, 4, 10), v);
+ if (rowIndx == 1 && i == 3) Assert.Equal(File.ReadAllBytes(PathHelper.GetFile("xlsx/Issue327/TestIssue327.txt")), v);
}
+ rowIndx++;
}
+
+ //TODO:How to resolve empty body sheet?
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/149
- ///
[Fact]
- public void Issue149()
+ public void TestIssue331()
{
- char[] chars =
- [
- '\u0000','\u0001','\u0002','\u0003','\u0004','\u0005','\u0006','\u0007','\u0008',
- '\u0009', //
- '\u000A', //
- '\u000B','\u000C',
- '\u000D', //
- '\u000E','\u000F','\u0010','\u0011','\u0012','\u0013','\u0014','\u0015','\u0016',
- '\u0017','\u0018','\u0019','\u001A','\u001B','\u001C','\u001D','\u001E','\u001F','\u007F'
- ];
- var strings = chars.Select(s => s.ToString()).ToArray();
+ var cln = CultureInfo.CurrentCulture.Name;
+ CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("cs-CZ");
+ var data = Enumerable.Range(1, 10).Select(x => new TestIssue331Dto
{
- var path = PathHelper.GetFile("xlsx/TestIssue149.xlsx");
- var rows = _excelImporter.Query(path).Select(s => (string)s.A).ToList();
- for (int i = 0; i < chars.Length; i++)
- {
- //output.WriteLine($"{i} , {chars[i]} , {rows[i]}");
- if (i == 13)
- continue;
+ Number = x,
+ Text = $"Number {x}",
+ DecimalNumber = x / 2m,
+ DoubleNumber = x / 2d
+ });
- Assert.Equal(strings[i], rows[i]);
- }
- }
+ using var path = AutoDeletingPath.Create();
+ _excelExporter.Export(path.ToString(), data);
+
+ var rows = _excelImporter.Query(path.ToString(), startCell: "A2").ToArray();
+ Assert.Equal(1.5, rows[2].B);
+ Assert.Equal(1.5, rows[2].C);
+
+ CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(cln);
+ }
+ [Fact]
+ public void TestIssue331_2()
+ {
+ var cln = CultureInfo.CurrentCulture.Name;
+ CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("cs-CZ");
+
+ var config = new OpenXmlConfiguration
{
- using var path = AutoDeletingPath.Create();
- var input = chars.Select(s => new { Test = s.ToString() });
- _excelExporter.Export(path.ToString(), input);
+ Culture = CultureInfo.GetCultureInfo("cs-CZ")
+ };
- var rows = _excelImporter.Query(path.ToString(), true).Select(s => (string)s.Test).ToList();
- for (int i = 0; i < chars.Length; i++)
- {
- _output.WriteLine($"{i}, {chars[i]}, {rows[i]}");
- if (i is 13 or 9 or 10)
- continue;
+ var rnd = new Random();
+ var data = Enumerable.Range(1, 100).Select(x => new TestIssue331Dto
+ {
+ Number = x,
+ Text = $"Number {x}",
+ DecimalNumber = (decimal)rnd.NextDouble(),
+ DoubleNumber = rnd.NextDouble()
+ });
- Assert.Equal(strings[i], rows[i]);
- }
+ using var path = AutoDeletingPath.Create();
+ _excelExporter.Export(path.ToString(), data, configuration: config);
+ CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(cln);
+ }
+
+ // Excel was unable to open the file https://github.com/mini-software/MiniExcel/issues/343
+ [Fact]
+ public void TestIssue343()
+ {
+ var date = DateTime.Parse("2022-03-17 09:32:06.111", CultureInfo.InvariantCulture);
+ using var path = AutoDeletingPath.Create();
+
+ CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("ff-Latn");
+ var table = new DataTable();
+ {
+ table.Columns.Add("time1", typeof(DateTime));
+ table.Columns.Add("time2", typeof(DateTime));
+ table.Rows.Add(date, date);
+ table.Rows.Add(date, date);
}
+ var reader = table.CreateDataReader();
+ _excelExporter.Export(path.ToString(), reader);
+ var rows = _excelImporter.Query(path.ToString(), true).ToArray();
+ Assert.Equal(date, rows[0].time1);
+ Assert.Equal(date, rows[0].time2);
+ }
+
+ [Fact]
+ public void TestIssue352()
+ {
{
+ using var table = new DataTable();
+ table.Columns.Add("id", typeof(int));
+ table.Columns.Add("name", typeof(string));
+ table.Rows.Add(1, "Jack");
+ table.Rows.Add(2, "Mike");
+
using var path = AutoDeletingPath.Create();
- var input = chars.Select(s => new { Test = s.ToString() });
- _excelExporter.Export(path.ToString(), input);
+ var reader = table.CreateDataReader();
+ _excelExporter.Export(path.ToString(), reader);
+ var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ var cnt = Regex.Count(xml, "");
+ }
+ {
+ using var table = new DataTable();
+ table.Columns.Add("id", typeof(int));
+ table.Columns.Add("name", typeof(string));
+ table.Rows.Add(1, "Jack");
+ table.Rows.Add(2, "Mike");
- var rows = _excelImporter.Query(path.ToString()).Select(s => s.Test).ToList();
- for (int i = 0; i < chars.Length; i++)
- {
- _output.WriteLine($"{i}, {chars[i]}, {rows[i]}");
- if (i is 13 or 9 or 10)
- continue;
+ using var path = AutoDeletingPath.Create();
+ var reader = table.CreateDataReader();
+ _excelExporter.Export(path.ToString(), reader, false);
+ var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ var cnt = Regex.Count(xml, "");
+ }
+ {
+ using var table = new DataTable();
+ table.Columns.Add("id", typeof(int));
+ table.Columns.Add("name", typeof(string));
- Assert.Equal(strings[i], rows[i]);
- }
+ using var path = AutoDeletingPath.Create();
+ var reader = table.CreateDataReader();
+ _excelExporter.Export(path.ToString(), reader);
+ var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ var cnt = Regex.Count(xml, "");
}
}
- private class Issue149VO
+ [Fact]
+ public void TestIssue360()
{
- public string Test { get; set; }
+ var path = PathHelper.GetFile("xlsx/NotDuplicateSharedStrings_10x100.xlsx");
+ var config = new OpenXmlConfiguration { SharedStringCacheSize = 1 };
+ var sheets = _excelImporter.GetSheetNames(path);
+ foreach (var sheetName in sheets)
+ {
+ _ = _excelImporter.QueryAsDataTable(path, hasHeaderRow: true, sheetName: sheetName, configuration: config);
+ }
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/153
- ///
[Fact]
- public void Issue153()
+ public void TestIssue369()
{
- var path = PathHelper.GetFile("xlsx/TestIssue153.xlsx");
- var rows = _excelImporter.Query(path, true).First() as IDictionary;
- Assert.Equal(
- [
- "序号", "代号", "新代号", "名称", "XXX", "部门名称", "单位", "ERP工时 (小时)A", "工时(秒) A/3600", "标准人工工时(秒)",
- "生产标准机器工时(秒)", "财务、标准机器工时(秒)", "更新日期", "产品机种", "备注", "最近一次修改前的标准工时(秒)", "最近一次修改前的标准机时(秒)", "备注1"
- ], rows?.Keys);
+ var config = new OpenXmlConfiguration
+ {
+ DynamicColumns =
+ [
+ new DynamicExcelColumn("id") { Ignore=true },
+ new DynamicExcelColumn("name") { Index=1, Width=10 },
+ new DynamicExcelColumn("createdate") { Index=0, Format="yyyy-MM-dd", Width=15 },
+ new DynamicExcelColumn("point") { Index=2, Name="Account Point" }
+ ]
+ };
+ using var path = AutoDeletingPath.Create();
+ var value = new[] { new { id = 1, name = "Jack", createdate = new DateTime(2022, 04, 12), point = 123.456 } };
+ _excelExporter.Export(path.ToString(), value, configuration: config);
+
+ var rows = _excelImporter.Query(path.ToString()).ToList();
+ Assert.Equal("createdate", rows[0].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);
+ Assert.Equal(123.456, rows[1].C);
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/137
- ///
[Fact]
- public void Issue137()
+ public void TestIssue370()
{
- var path = PathHelper.GetFile("xlsx/TestIssue137.xlsx");
+ var config = new OpenXmlConfiguration
{
- var rows = _excelImporter.Query(path).ToList();
- var first = rows[0] as IDictionary; // https://user-images.githubusercontent.com/12729184/113266322-ba06e400-9307-11eb-9521-d36abfda75cc.png
- Assert.Equal(["A", "B", "C", "D", "E", "F", "G", "H"], first?.Keys.ToArray());
- Assert.Equal(11, rows.Count);
- {
- var row = rows[0] as IDictionary;
- Assert.Equal("比例", row!["A"]);
- Assert.Equal("商品", row["B"]);
- Assert.Equal("滿倉口數", row["C"]);
- Assert.Equal(" ", row["D"]);
- Assert.Equal(" ", row["E"]);
- Assert.Equal(" ", row["F"]);
- Assert.Equal(0.0, row["G"]);
- Assert.Equal("1為港幣 0為台幣", row["H"]);
- }
- {
- var row = rows[1] as IDictionary;
- Assert.Equal(1.0, row!["A"]);
- Assert.Equal("MTX", row["B"]);
- Assert.Equal(10.0, row["C"]);
- Assert.Null(row["D"]);
- Assert.Null(row["E"]);
- Assert.Null(row["F"]);
- Assert.Null(row["G"]);
- Assert.Null(row["H"]);
- }
+ DynamicColumns =
+ [
+ new DynamicExcelColumn("Id") { Ignore = true },
+ new DynamicExcelColumn("Name") { Index = 1,Width = 10 },
+ new DynamicExcelColumn("Date") { Index = 0, Format="yyyy-MM-dd", Width = 15 },
+ new DynamicExcelColumn("Point") { Index = 2, Name = "Account Point" }
+ ]
+ };
+ using var path = AutoDeletingPath.Create();
+ List> value =
+ [
+ new()
{
- var row = rows[2] as IDictionary;
- Assert.Equal(0.95, row!["A"]);
+ ["Id"] = 1,
+ ["Name"] = "Jack",
+ ["Date"] = new DateTime(2022, 04, 12),
+ ["Point"] = 123.456
}
- }
+ ];
+ _excelExporter.Export(path.ToString(), value, configuration: config);
- // dynamic query with head
+ var rows = _excelImporter.Query(path.ToString()).ToList();
+ Assert.Equal("Date", rows[0].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);
+ Assert.Equal(123.456, rows[1].C);
+ }
+
+ [Theory]
+ [InlineData(true, 1)]
+ [InlineData(false, 0)]
+ public void TestIssue401(bool autoFilter, int count)
+ {
+ // Test for DataTable
{
- var rows = _excelImporter.Query(path, true).ToList();
- var first = rows[0] as IDictionary; //
- Assert.Equal(["比例", "商品", "滿倉口數", "0", "1為港幣 0為台幣"], first?.Keys.ToArray());
- Assert.Equal(10, rows.Count);
+ var table = new DataTable();
{
- var row = rows[0] as IDictionary;
- Assert.Equal(1.0, row!["比例"]);
- Assert.Equal("MTX", row["商品"]);
- Assert.Equal(10.0, row["滿倉口數"]);
- Assert.Null(row["0"]);
- Assert.Null(row["1為港幣 0為台幣"]);
+ table.Columns.Add("id", typeof(int));
+ table.Columns.Add("name", typeof(string));
+ table.Rows.Add(1, "Jack");
+ table.Rows.Add(2, "Mike");
}
- {
- var row = rows[1] as IDictionary;
- Assert.Equal(0.95, row!["比例"]);
- }
- }
+ var reader = table.CreateDataReader();
+ using var path = AutoDeletingPath.Create();
+ var config = new OpenXmlConfiguration { AutoFilter = autoFilter };
+ _excelExporter.Export(path.ToString(), reader, configuration: config);
+ var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ var cnt = Regex.Matches(xml, "").Count;
+ Assert.Equal(count, cnt);
+ }
{
- var rows = _excelImporter.Query(path).ToList();
- Assert.Equal(10, rows.Count);
+ var table = new DataTable();
{
- var row = rows[0];
- Assert.Equal(1, row.比例);
- Assert.Equal("MTX", row.商品);
- Assert.Equal(10, row.滿倉口數);
+ table.Columns.Add("id", typeof(int));
+ table.Columns.Add("name", typeof(string));
+ table.Rows.Add(1, "Jack");
+ table.Rows.Add(2, "Mike");
}
+ var reader = table.CreateDataReader();
+ using var path = AutoDeletingPath.Create();
+ var config = new OpenXmlConfiguration { AutoFilter = autoFilter };
+ _excelExporter.Export(path.ToString(), reader, false, configuration: config);
+ var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ var cnt = Regex.Matches(xml, "").Count;
+ Assert.Equal(count, cnt);
+ }
+ {
+ var table = new DataTable();
{
- var row = rows[1];
- Assert.Equal(0.95, row.比例);
+ table.Columns.Add("id", typeof(int));
+ table.Columns.Add("name", typeof(string));
}
+ var reader = table.CreateDataReader();
+ using var path = AutoDeletingPath.Create();
+ var config = new OpenXmlConfiguration { AutoFilter = autoFilter };
+ _excelExporter.Export(path.ToString(), reader, configuration: config);
+
+ var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ var cnt = Regex.Matches(xml, "").Count;
+ Assert.Equal(count, cnt);
}
- }
- private class Issue137ExcelRow
- {
- public double? 比例 { get; set; }
- public string 商品 { get; set; }
- public int? 滿倉口數 { get; set; }
- }
+ // Test for DataReader
+ {
+ using var path = AutoDeletingPath.Create();
+ var config = new OpenXmlConfiguration { AutoFilter = autoFilter };
+ using (var connection = Db.GetConnection("Data Source=:memory:"))
+ {
+ connection.Open();
+ using var command = connection.CreateCommand();
+ command.CommandText =
+ """
+ SELECT
+ 'MiniExcel' as Column1,
+ 1 as Column2
- ///
- /// https://github.com/mini-software/MiniExcel/issues/138
- ///
- [Fact]
- public void Issue138()
- {
- var path = PathHelper.GetFile("xlsx/TestIssue138.xlsx");
- {
- var rows = _excelImporter.Query(path, true).ToList();
- Assert.Equal(6, rows.Count);
+ UNION ALL
+ SELECT 'Github', 2
+ """;
- foreach (var index in new[] { 0, 2, 5 })
- {
- Assert.Equal(1, rows[index].實單每日損益);
- Assert.Equal(2, rows[index].程式每日損益);
- Assert.Equal("測試商品1", rows[index].商品);
- Assert.Equal(111.11, rows[index].滿倉口數);
- Assert.Equal(111.11, rows[index].波段);
- Assert.Equal(111.11, rows[index].當沖);
+ using var reader = command.ExecuteReader();
+ _excelExporter.Export(path.ToString(), reader, configuration: config);
}
- foreach (var index in new[] { 1, 3, 4 })
- {
- Assert.Null(rows[index].實單每日損益);
- Assert.Null(rows[index].程式每日損益);
- Assert.Null(rows[index].商品);
- Assert.Null(rows[index].滿倉口數);
- Assert.Null(rows[index].波段);
- Assert.Null(rows[index].當沖);
- }
+ var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ var cnt = Regex.Matches(xml, "autoFilter").Count;
+ Assert.Equal(count, cnt);
}
+
{
+ var xlsxPath = PathHelper.GetFile("xlsx/Test5x2.xlsx");
+ using var tempSqlitePath = AutoDeletingPath.Create(Path.GetTempPath(), $"{Guid.NewGuid()}.db");
+ var connectionString = $"Data Source={tempSqlitePath};Version=3;";
- var rows = _excelImporter.Query(path).ToList();
- Assert.Equal(6, rows.Count);
- Assert.Equal(new DateTime(2021, 3, 1), rows[0].Date);
+ using (var connection = new SQLiteConnection(connectionString))
+ {
+ connection.Execute("create table T (A varchar(20),B varchar(20));");
+ }
- foreach (var index in new[] { 0, 2, 5 })
+ using (var connection = new SQLiteConnection(connectionString))
{
- Assert.Equal(1, rows[index].實單每日損益);
- Assert.Equal(2, rows[index].程式每日損益);
- Assert.Equal("測試商品1", rows[index].商品);
- Assert.Equal(111.11, rows[index].滿倉口數);
- Assert.Equal(111.11, rows[index].波段);
- Assert.Equal(111.11, rows[index].當沖);
+ connection.Open();
+ using (var transaction = connection.BeginTransaction())
+ using (var stream = File.OpenRead(xlsxPath))
+ {
+ var rows = _excelImporter.Query(stream);
+ foreach (var row in rows)
+ connection.Execute(
+ "insert into T (A,B) values (@A,@B)",
+ new { row.A, row.B },
+ transaction: transaction);
+
+ transaction.Commit();
+ }
}
- foreach (var index in new[] { 1, 3, 4 })
+ using var path = AutoDeletingPath.Create();
+ var config = new OpenXmlConfiguration { AutoFilter = autoFilter };
+ using (var connection = new SQLiteConnection(connectionString))
{
- Assert.Null(rows[index].實單每日損益);
- Assert.Null(rows[index].程式每日損益);
- Assert.Null(rows[index].商品);
- Assert.Null(rows[index].滿倉口數);
- Assert.Null(rows[index].波段);
- Assert.Null(rows[index].當沖);
+ using var command = new SQLiteCommand("select * from T", connection);
+ connection.Open();
+ using var reader = command.ExecuteReader();
+ _excelExporter.Export(path.ToString(), reader, configuration: config);
}
- }
- }
- private class Issue138ExcelRow
- {
- public DateTime? Date { get; set; }
- public int? 實單每日損益 { get; set; }
- public int? 程式每日損益 { get; set; }
- public string 商品 { get; set; }
- public double? 滿倉口數 { get; set; }
- public double? 波段 { get; set; }
- public double? 當沖 { get; set; }
+ var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/worksheets/sheet1.xml");
+ var cnt = Regex.Matches(xml, "autoFilter").Count;
+ Assert.Equal(count, cnt);
+ }
}
- ///
- /// https://gitee.com/dotnetchina/MiniExcel/issues/I50VD5
- ///
+ // https://github.com/MiniExcel/MiniExcel/issues/405)
[Fact]
- public void IssueI50VD5()
+ public void TestIssue405()
{
- using var file = AutoDeletingPath.Create();
- var path = file.ToString();
-
- List list1 =
- [
- new { Name = "github", Image = File.ReadAllBytes(PathHelper.GetFile("images/github_logo.png")) },
- new { Name = "google", Image = File.ReadAllBytes(PathHelper.GetFile("images/google_logo.png")) },
- new { Name = "microsoft", Image = File.ReadAllBytes(PathHelper.GetFile("images/microsoft_logo.png")) },
- new { Name = "reddit", Image = File.ReadAllBytes(PathHelper.GetFile("images/reddit_logo.png")) },
- new { Name = "stackoverflow", Image = File.ReadAllBytes(PathHelper.GetFile("images/stackoverflow_logo.png")) }
- ];
-
- List list2 =
- [
- new { Id = 1, Name = "github", Image = File.ReadAllBytes(PathHelper.GetFile("images/github_logo.png")) },
- new { Id = 2, Name = "google", Image = File.ReadAllBytes(PathHelper.GetFile("images/google_logo.png")) }
- ];
-
- var sheets = new Dictionary
- {
- ["A"] = list1,
- ["B"] = list2,
- };
- _excelExporter.Export(path, sheets);
-
- {
- Assert.Contains("/xl/media/", SheetHelper.GetZipFileContent(path, "xl/drawings/_rels/drawing1.xml.rels"));
- Assert.Contains("ext cx=\"609600\" cy=\"190500\"", SheetHelper.GetZipFileContent(path, "xl/drawings/drawing1.xml"));
- Assert.Contains("/xl/drawings/drawing1.xml", SheetHelper.GetZipFileContent(path, "[Content_Types].xml"));
- Assert.Contains("drawing r:id=\"drawing1\"", SheetHelper.GetZipFileContent(path, "xl/worksheets/sheet1.xml"));
- Assert.Contains("../drawings/drawing1.xml", SheetHelper.GetZipFileContent(path, "xl/worksheets/_rels/sheet1.xml.rels"));
+ using var path = AutoDeletingPath.Create();
+ var value = new[] { new { id = 1, name = "test" } };
+ _excelExporter.Export(path.ToString(), value);
- Assert.Contains("/xl/media/", SheetHelper.GetZipFileContent(path, "xl/drawings/_rels/drawing2.xml.rels"));
- Assert.Contains("ext cx=\"609600\" cy=\"190500\"", SheetHelper.GetZipFileContent(path, "xl/drawings/drawing2.xml"));
- Assert.Contains("/xl/drawings/drawing1.xml", SheetHelper.GetZipFileContent(path, "[Content_Types].xml"));
- Assert.Contains("drawing r:id=\"drawing2\"", SheetHelper.GetZipFileContent(path, "xl/worksheets/sheet2.xml"));
- Assert.Contains("../drawings/drawing2.xml", SheetHelper.GetZipFileContent(path, "xl/worksheets/_rels/sheet2.xml.rels"));
- }
+ var xml = SheetHelper.GetZipFileContent(path.ToString(), "xl/sharedStrings.xml");
+ Assert.StartsWith("(path, configuration: config).ToList();
+ var config = new OpenXmlConfiguration
+ {
+ Culture = new CultureInfo("ru")
+ {
+ NumberFormat = { NumberDecimalSeparator = "," }
+ }
+ };
+
+ var query = _excelImporter.Query(path, configuration: config).ToList();
Assert.Equal(0.002886, query[0].Quantity);
Assert.Equal(4.1E-05, query[1].Quantity);
@@ -2794,23 +2023,29 @@ public void TestIssue409()
Assert.Equal(17.4024812, query[4].Quantity);
Assert.Equal(1.43E-06, query[5].Quantity);
Assert.Equal(9.9E-06, query[6].Quantity);
- }
+ }
- private class Issue422Enumerable(IEnumerable inner) : IEnumerable
+ // https://github.com/MiniExcel/MiniExcel/issues/413)
+ [Fact]
+ public void TestIssue413()
{
- private readonly IEnumerable _inner = inner;
- public int GetEnumeratorCount { get; private set; }
-
- public IEnumerator GetEnumerator()
+ using var path = AutoDeletingPath.Create();
+ var value = new
{
- GetEnumeratorCount++;
- return _inner.GetEnumerator();
- }
+ list = new List>
+ {
+ new() { { "id","001"},{ "time",new DateTime(2022,12,25)} },
+ new() { { "id","002"},{ "time",new DateTime(2022,9,23)} },
+ }
+ };
+ var templatePath = PathHelper.GetFile("xlsx/TestIssue413.xlsx");
+ _excelTemplater.FillTemplate(path.ToString(), templatePath, value);
+ var rows = _excelImporter.Query(path.ToString()).ToList();
+
+ Assert.Equal("2022-12-25 00:00:00", rows[1].B);
+ Assert.Equal("2022-09-23 00:00:00", rows[2].B);
}
- ///
- /// https://github.com/mini-software/MiniExcel/issues/422
- ///
[Fact]
public void Issue422()
{
@@ -2827,6 +2062,21 @@ public void Issue422()
Assert.Equal(1, enumerableWithCount.GetEnumeratorCount);
}
+ // Exception : MiniExcelLibs.Core.Exceptions.ExcelInvalidCastException: 'ColumnName : Date, CellRow : 2, Value : 2021-01-31 10:03:00 +08:00, it can't cast to DateTimeOffset type.'
+ [Fact]
+ public void TestIssue430()
+ {
+ using var path = AutoDeletingPath.Create();
+ TestIssue430Dto[] value =
+ [
+ new() { Date = new DateTimeOffset(2021, 1, 31, 10, 3, 0, TimeSpan.FromHours(5)) }
+ ];
+ _excelExporter.Export(path.ToString(), value);
+
+ var testValue = _excelImporter.Query(path.ToString(), hasHeaderRow: true).First();
+ Assert.Equal("2021-01-31 10:03:00", testValue.Date.ToString("yyyy-MM-dd HH:mm:ss"));
+ }
+
[Fact]
public void Issue459()
{
@@ -2870,37 +2120,88 @@ public void Issue520()
Assert.Equal(300.0, cells["C2"].Value);
Assert.Equal(300.0.ToString("R$ #,##0.00"), cells["C2"].Text);
}
+
+ [Fact]
+ public void Issue527()
+ {
+ List row =
+ [
+ new() { Name = "Bill", UserType = DescriptionEnum.V1 },
+ new() { Name = "Bob", UserType = DescriptionEnum.V2 }
+ ];
+
+ var value = new { t = row };
+ var template = PathHelper.GetFile("xlsx/Issue527Template.xlsx");
+
+ using var path = AutoDeletingPath.Create();
+ _excelTemplater.FillTemplate(path.FilePath, template, value);
+
+ var rows = _excelImporter.Query(path.FilePath).ToList();
+ Assert.Equal("General User", rows[1].B);
+ Assert.Equal("General Administrator", rows[2].B);
+ }
+
+ [Fact]
+ public void Issue542()
+ {
+ var path = PathHelper.GetFile("xlsx/TestIssue542.xlsx");
- class Issue520Dto(long l1, DateTime dt, long l2)
- {
- [MiniExcelColumn(Format = "R$ #,##0.00", Width = 15)]
- public long PaymentValue { get; set; } = l1;
+ var resultWithoutFirstRow = _excelImporter.Query(path).ToList();
+ var resultWithFirstRow = _excelImporter.Query