Skip to content

Commit

Permalink
Add async support (#131)
Browse files Browse the repository at this point in the history
* Add async for ExcelDataReader

* Add ExcelDataWriter.CreateAsync
  • Loading branch information
MarkPflug authored Sep 8, 2023
1 parent ff487e4 commit 634355c
Show file tree
Hide file tree
Showing 18 changed files with 837 additions and 151 deletions.
32 changes: 32 additions & 0 deletions docs/Async.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Async Support

ExcelDataReader and ExcelDataWriter both support "async" operations.
In order to ensure proper async behavior, you must use the `CreateAsync`
method to create instances. In this mode, the entire file must be
buffered in memory, and all IO will be handled asynchronously.

The CreateAsync methods are only supported on .NET Core versions.

Reading:
```
// this line will buffer the entire file into memory.
await using var edr = ExcelDataReader.CreateAsync("jumbo.xlsx");
while(await edr.ReadAsync())
{
// ...
}
```

Writing:
```
// must use async disposal
await using var edw = ExcelDataWriter.CreateAsync("jumbo.xlsx");
edw.WriteAsync(myDataReader, "MyData");
edw.WriteAsync(myOtherDataReader, "MoreData");
// when the ExcelDataWriter is asynchronously disposed
// the buffered file is asynchronously written to the output.
```
3 changes: 2 additions & 1 deletion docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

_0.4.16_
- Adds ExcelFileType class that exposes constants about supported Excel formats: extensions and content types.
- Add `Obsolete` to `TryOpenWorksheetAsync`, use `TryOpenWorksheet` instead. Information about future Async strategy will be forthcoming.
- Add `Obsolete` to `TryOpenWorksheetAsync`, use `TryOpenWorksheet` instead.
- Add `CreateAsync` to `ExcelDataReader` and `ExcelDataWriter` to enable async operation (not supported on .NET Framework versions).

_0.4.15_
- Fix a bug that prevented .xlsx reader from working on .NET Framework versions.
Expand Down
60 changes: 60 additions & 0 deletions source/Sylvan.Data.Excel.Tests/ExcelDataReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace Sylvan.Data.Excel;
Expand Down Expand Up @@ -1253,6 +1254,65 @@ public void Date1900()
Assert.Equal(45678d, edr.GetDouble(0));
Assert.Equal(new DateTime(2025, 1, 21), edr.GetDateTime(0));
}

#if ASYNC

[Fact]
public async Task BasicAsync()
{
var name = GetFile("Big");
await using var edr = await ExcelDataReader.CreateAsync(name);
while (await edr.ReadAsync())
{
for (int i = 0; i < edr.RowFieldCount; i++)
{
edr.GetValue(i);
}
}
}

[Fact]
public async Task StreamAsync()
{
var name = GetFile("Big");
var stream = File.OpenRead(name);

var testStream = new TestStream(stream);

await using var edr = await ExcelDataReader.CreateAsync(testStream, this.WorkbookType);
while (await edr.ReadAsync())
{
for (int i = 0; i < edr.RowFieldCount; i++)
{
edr.GetValue(i);
}
}

// The stream should still be open, because we own it.
Assert.False(testStream.IsClosed);
}

[Fact]
public async Task OwnedStreamAsync()
{
var name = GetFile("Big");
var stream = File.OpenRead(name);

var testStream = new TestStream(stream);
var opts = new ExcelDataReaderOptions { OwnsStream = true };
await using var edr = await ExcelDataReader.CreateAsync(testStream, this.WorkbookType, opts);
while (await edr.ReadAsync())
{
for (int i = 0; i < edr.RowFieldCount; i++)
{
edr.GetValue(i);
}
}
// The stream should have been closed for us, due to OwnsStream = true.
Assert.True(testStream.IsClosed);
}

#endif
}

public sealed class XlsTests : XlsxTests
Expand Down
Loading

0 comments on commit 634355c

Please sign in to comment.