Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x
- name: Restore dependencies
run: dotnet restore
Expand Down
27 changes: 27 additions & 0 deletions .runsettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage">
<Configuration>
<CodeCoverage>
<ModulePaths>
<Exclude>
<ModulePath>.*MiniExcel.Tests.Common.dll</ModulePath>
<ModulePath>.*MiniExcel.Csv.Tests.dll</ModulePath>
<ModulePath>.*MiniExcel.OpenXml.Tests.dll</ModulePath>
<ModulePath>.*Dapper.dll</ModulePath>
</Exclude>
</ModulePaths>

<Functions>
<Exclude>
<Function>System.Text.RegularExpressions.Generated</Function>
</Exclude>
</Functions>
</CodeCoverage>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
3 changes: 2 additions & 1 deletion MiniExcel.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<File Path=".gitattributes" />
<File Path=".gitignore" />
<File Path=".github\workflows\dotnet.yml" />
<File Path=".runsettings" />
<File Path="LICENSE" />
<File Path="README.md" />
<File Path="README.zh-CN.md" />
Expand All @@ -26,9 +27,9 @@
<File Path="src/.editorconfig" />
<File Path="src\Directory.Build.props" />
<File Path="src\Directory.Packages.props" />
<Project Path="src\MiniExcel.OpenXml/MiniExcel.OpenXml.csproj" />
<Project Path="src\MiniExcel.Core\MiniExcel.Core.csproj" />
<Project Path="src\MiniExcel.Csv\MiniExcel.Csv.csproj" />
<Project Path="src\MiniExcel.OpenXml/MiniExcel.OpenXml.csproj" />
<Project Path="src\MiniExcel\MiniExcel.csproj" />
</Folder>
<Folder Name="/tests/">
Expand Down
8 changes: 3 additions & 5 deletions src/MiniExcel.Core/MiniExcelDataReaderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,10 @@ public DataTable GetSchemaTable()

return Schema;
}

public virtual bool NextResult()
=> throw new NotImplementedException();

public virtual Task<bool> NextResultAsync(CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public abstract bool NextResult();

public abstract Task<bool> NextResultAsync(CancellationToken cancellationToken = default);


public void Close()
Expand Down
3 changes: 3 additions & 0 deletions src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ public async Task<int> CopyAndAddSheetAsync(string inputFile, string outputFile,
if (inputFile.Equals(outputFile, StringComparison.InvariantCultureIgnoreCase))
throw new ArgumentException("The generated file must not have the same path as the original file.");

if (Path.GetExtension(outputFile).Equals(".xlsm", StringComparison.InvariantCultureIgnoreCase))
throw new NotSupportedException("MiniExcel's CopyAndAddSheet does not support the .xlsm format");
Comment thread
michelebastione marked this conversation as resolved.

var inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.RandomAccess);
await using var disposableInputStream = inputStream.ConfigureAwait(false);

Expand Down
6 changes: 3 additions & 3 deletions src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public async IAsyncEnumerable<dynamic> QueryAsync(Stream stream, bool hasHeaderR
#region Query Range

/// <summary>
/// Queries a specific rectangular region within an worksheet using index-based coordinates.
/// Queries a specific rectangular region within an worksheet using cell-based coordinates.
/// </summary>
/// <param name="path">The path to the Excel document.</param>
/// <param name="hasHeaderRow">If true, the first row within the range is used as column headers for dynamic object properties. Default is false.</param>
Expand All @@ -131,7 +131,7 @@ public async IAsyncEnumerable<dynamic> QueryRangeAsync(string path, bool hasHead
}

/// <summary>
/// Queries a specific rectangular region within an worksheet using index-based coordinates.
/// Queries a specific rectangular region within an worksheet using cell-based coordinates.
/// </summary>
/// <param name="stream">The stream containing the Excel file data. The stream position is not reset after reading.</param>
/// <param name="hasHeaderRow">If true, the first row within the range is used as column headers for dynamic object properties. Default is false.</param>
Expand Down Expand Up @@ -375,7 +375,7 @@ public async Task<List<SheetInfo>> GetSheetInformationsAsync(string path, Cancel
[CreateSyncVersion]
public async Task<List<SheetInfo>> GetSheetInformationsAsync(Stream stream, bool leaveOpen = false, CancellationToken cancellationToken = default)
{
var archive = await OpenXmlZip.CreateAsync(stream, cancellationToken: cancellationToken).ConfigureAwait(false);
var archive = await OpenXmlZip.CreateAsync(stream, leaveOpen: leaveOpen, cancellationToken: cancellationToken).ConfigureAwait(false);
await using var disposableArchve = archive.ConfigureAwait(false);

var rels = await OpenXmlReader.GetWorkbookRelsAsync(archive.EntryCollection, cancellationToken).ConfigureAwait(false);
Expand Down
2 changes: 1 addition & 1 deletion src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public async Task AddPictureAsync(string path, CancellationToken cancellationTok
var stream = File.Open(path, FileMode.OpenOrCreate);
await using var disposableStream = stream.ConfigureAwait(false);

await MiniExcelPictureImplement.AddPictureAsync(stream, cancellationToken, images).ConfigureAwait(false);
await AddPictureAsync(stream, cancellationToken, images).ConfigureAwait(false);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ public async Task GetDataReader_GetOrdinal_ReturnsColumnIndex()
public async Task GetDataReader_NextResult_ThrowsNotSupportedException()
{
var path = PathHelper.GetFile("csv/TestDataReaderHeader.csv");
await using var stream = File.OpenRead(path);
await using var reader = await _csvImporter.GetAsyncDataReader(stream, hasHeaderRow: true);
await using var reader = await _csvImporter.GetAsyncDataReader(path, hasHeaderRow: true);

await Assert.ThrowsAsync<NotSupportedException>(async () => await reader.NextResultAsync());
}
Expand Down
5 changes: 2 additions & 3 deletions tests/MiniExcel.Csv.Tests/DataReader/CsvDataReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,10 @@ public void GetDataReader_GetOrdinal_ReturnsColumnIndex()
}

[Fact]
public async Task GetDataReader_NextResult_ThrowsNotSupportedException()
public void GetDataReader_NextResult_ThrowsNotSupportedException()
{
var path = PathHelper.GetFile("csv/TestDataReaderHeader.csv");
await using var stream = File.OpenRead(path);
await using var reader = await _csvImporter.GetAsyncDataReader(stream, hasHeaderRow: true);
using var reader = _csvImporter.GetDataReader(path, hasHeaderRow: true);

Assert.Throws<NotSupportedException>(() => reader.NextResult());
}
Expand Down
92 changes: 88 additions & 4 deletions tests/MiniExcel.Csv.Tests/Main/MiniExcelCsvAsyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ public class MiniExcelCsvAsyncTests
private readonly CsvImporter _csvImporter = MiniExcel.Importers.GetCsvImporter();

[Fact]
public void Gb2312_Encoding_Read_Test()
public async Task Gb2312_Encoding_Read_Test()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var path = PathHelper.GetFile("csv/gb2312_Encoding_Read_Test.csv");
var config = new CsvConfiguration
{
StreamReaderFunc = stream => new StreamReader(stream, encoding: Encoding.GetEncoding("gb2312"))
};
var rows = _csvImporter.QueryAsync(path, true, configuration: config).ToBlockingEnumerable().ToList();
var rows = await _csvImporter.QueryAsync(path, true, configuration: config).ToListAsync();
Assert.Equal("世界你好", rows[0].栏位1);
}

Expand Down Expand Up @@ -57,6 +57,14 @@ public async Task SeperatorTest()
Assert.Equal(expected, await File.ReadAllTextAsync(path));
}

[Fact]
public async Task WriteNullValueTest()
{
using var path = AutoDeletingPath.Create(ExcelType.Csv);
await _csvExporter.ExportAsync(path.FilePath, null!);
Assert.Equal("", File.ReadAllText(path.FilePath));
}

[Fact]
public async Task SaveAsByDictionary()
{
Expand Down Expand Up @@ -361,8 +369,67 @@ static async IAsyncEnumerable<TestDto> GetValues()
Assert.Equal("A2", results[1].C1);
Assert.Equal("B2", results[1].C2);
}

[Fact]

[Fact]
public async Task AppendToCsvTest()
{
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) },
};
await _csvExporter.AppendAsync(path, value);

var content = await File.ReadAllTextAsync(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) };
await _csvExporter.AppendAsync(path, value);

var content = await File.ReadAllTextAsync(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) }
};
await _csvExporter.AppendAsync(path, value);

var content = await File.ReadAllTextAsync(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 async Task ExportDataTableWithProgressTest()
{
var dataTable = new DataTable();
Expand Down Expand Up @@ -409,4 +476,21 @@ public async Task ExportDataTableWithProgressTest()
}
}
}

[Fact]
public async Task GetColumnNamesTest()
{
var path = PathHelper.GetFile(@"csv/TestHeader.csv");
var cols = (await _csvImporter.GetColumnNamesAsync(path, true)).ToArray();
Assert.Equal("Column1", cols[0]);
Assert.Equal("Column2", cols[1]);
}

[Fact]
public async Task GetColumnNamesEmptyTest()
{
await using var ms = new MemoryStream();
var cols = await _csvImporter.GetColumnNamesAsync(ms);
Assert.Empty(cols);
}
}
Loading
Loading