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
81 changes: 41 additions & 40 deletions MiniExcel.slnx
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
<Solution>
<Folder Name="/benchmarks/">
<Project Path="benchmarks\MiniExcel.Benchmarks\MiniExcel.Benchmarks.csproj" />
</Folder>
<Folder Name="/Docs and settings/">
<File Path=".editorconfig" />
<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" />
<File Path=".github\workflows\benchmark.yml" />
<File Path=".github\workflows\codeql-analysis.yml" />
<File Path="README-V2.md" />
<File Path="miniexcel.publickey" />
<File Path="src\icon.png" />
<File Path="V2-Upgrade-Notes.md" />
</Folder>
<Folder Name="/Releases/">
<File Path="docs\README.md" />
<File Path="docs\README.zh-CN.md" />
<File Path="docs\README.zh-Hant.md" />
</Folder>
<Folder Name="/src/">
<File Path="src/.editorconfig" />
<File Path="src\Directory.Build.props" />
<File Path="src\Directory.Packages.props" />
<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/">
<Project Path="tests/MiniExcel.Csv.Tests/MiniExcel.Csv.Tests.csproj" />
<Project Path="tests/MiniExcel.OpenXml.Tests/MiniExcel.OpenXml.Tests.csproj" />
<Project Path="tests/MiniExcel.Tests.Common/MiniExcel.Tests.Common.csproj" />
</Folder>
</Solution>
<Solution>
<Folder Name="/benchmarks/">
<Project Path="benchmarks\MiniExcel.Benchmarks\MiniExcel.Benchmarks.csproj" />
</Folder>
<Folder Name="/Docs and settings/">
<File Path=".editorconfig" />
<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" />
<File Path=".github\workflows\benchmark.yml" />
<File Path=".github\workflows\codeql-analysis.yml" />
<File Path="README-V2.md" />
<File Path="miniexcel.publickey" />
<File Path="src\icon.png" />
<File Path="V2-Upgrade-Notes.md" />
</Folder>
<Folder Name="/Releases/">
<File Path="docs\README.md" />
<File Path="docs\README.zh-CN.md" />
<File Path="docs\README.zh-Hant.md" />
</Folder>
<Folder Name="/src/">
<File Path="src/.editorconfig" />
<File Path="src\Directory.Build.props" />
<File Path="src\Directory.Packages.props" />
<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.OpenXml.FluentMapping/MiniExcel.OpenXml.FluentMapping.csproj" />
<Project Path="src\MiniExcel\MiniExcel.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/MiniExcel.Csv.Tests/MiniExcel.Csv.Tests.csproj" />
<Project Path="tests/MiniExcel.OpenXml.Tests/MiniExcel.OpenXml.Tests.csproj" />
<Project Path="tests/MiniExcel.Tests.Common/MiniExcel.Tests.Common.csproj" />
</Folder>
</Solution>
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageReference Include="EPPlus" Version="7.7.3" />
<PackageReference Include="ExcelDataReader" Version="3.8.0" />
<PackageReference Include="NPOI" Version="2.8.0" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.3" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.10" />
</ItemGroup>

<ItemGroup>
Expand Down
20 changes: 20 additions & 0 deletions src/MiniExcel.OpenXml.FluentMapping/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Global using directives

global using System.Collections;
global using System.Globalization;
global using System.IO.Compression;
global using System.Linq.Expressions;
global using System.Reflection;
global using System.Runtime.CompilerServices;
global using System.Text;
global using System.Text.RegularExpressions;
global using System.Xml;
global using MiniExcelLib.Core;
global using MiniExcelLib.Core.Abstractions;
global using MiniExcelLib.Core.Helpers;
global using MiniExcelLib.Core.Reflection;
global using MiniExcelLib.OpenXml.Constants;
global using MiniExcelLib.OpenXml.Helpers;
global using MiniExcelLib.OpenXml.Models;
global using MiniExcelLib.OpenXml.Utils;
global using Zomp.SyncMethodGenerator;
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,15 @@ internal static class ConversionHelper
// Cache compiled conversion delegates
private static readonly ConcurrentDictionary<(Type Source, Type Target), Func<object, object?>> ConversionCache = new();

public static object? ConvertValue(object value, Type targetType, string? format = null)
public static object? ConvertValue(object? value, Type targetType, string? format = null)
{
if (value is null)
{
return targetType.IsValueType && Nullable.GetUnderlyingType(targetType) is null
? Activator.CreateInstance(targetType)
: null;
}

Comment thread
coderabbitai[bot] marked this conversation as resolved.
var sourceType = value.GetType();

// Fast path: no conversion needed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public static CompiledMapping<T> Compile<T>(MappingConfiguration<T>? configurati
if (prop.CellAddress is null)
continue;

CellReferenceConverter.TryParseCellReference(prop.CellAddress, out int cellCol, out int cellRow);
if (!CellReferenceConverter.TryParseCellReference(prop.CellAddress, out int cellCol, out int cellRow))
throw new InvalidOperationException($"Invalid cell address '{prop.CellAddress}' for property '{propertyName}'.");

properties.Add(new CompiledPropertyMapping
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ private static async IAsyncEnumerable<T> QueryOptimizedAsync(Stream stream, Comp
var cellGrid = mapping.OptimizedCellGrid!;

// Read the Excel file using OpenXmlReader's direct mapping path
using var reader = await OpenXmlReader.CreateAsync(stream, new OpenXmlConfiguration
var reader = await OpenXmlMappingReader.CreateAsync(stream, new OpenXmlConfiguration
{
FillMergedCells = false,
FastMode = false
}, leaveOpen, cancellationToken).ConfigureAwait(false);
await using var disposableReader = reader.ConfigureAwait(false);

// If we have collections, we need to handle multiple items with collections
if (mapping.Collections.Any())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static async Task ApplyTemplateAsync(
if (!templateStream.CanSeek)
{
// Copy to memory stream if not seekable
var memStream = new MemoryStream();
using var memStream = new MemoryStream();
await templateStream.CopyToAsync(memStream
#if NET
, cancellationToken
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<RootNamespace>MiniExcelLib.OpenXml.FluentMapping</RootNamespace>
</PropertyGroup>

<PropertyGroup>
<Title>MiniExcel.OpenXml.FluentMapping</Title>
<PackageId>MiniExcel.OpenXml.FluentMapping</PackageId>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\MiniExcel.Core\MiniExcel.Core.csproj" />
<ProjectReference Include="..\MiniExcel.OpenXml\MiniExcel.OpenXml.csproj" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="MiniExcel.OpenXml.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010091c2c6c10d20b6c884dbc48892f91cc773d33c3a1f43ba3352700031d2d5f6a2b37cccd60469733a4597bdd94b54ee63f514dc487b21be797b1b63063941630b46ad090baabaf0650d05b9c590ea497644f0c296bb223e17dc785f0fbb255ef780905aabf4cf14ee5bca087cbd41d2231169a620529626035215604261b533c9"/>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,10 +1,48 @@
using MiniExcelLib.OpenXml.FluentMapping;
using MiniExcelLib.OpenXml.Reader;
using MiniExcelLib.OpenXml.Styles;

namespace MiniExcelLib.OpenXml.Reader;
namespace MiniExcelLib.OpenXml.FluentMapping;

internal partial class OpenXmlReader
internal partial class OpenXmlMappingReader(OpenXmlZip archive, IMiniExcelConfiguration? configuration) : OpenXmlReader(archive, configuration)
{
[CreateSyncVersion]
internal new static async Task<OpenXmlMappingReader> CreateAsync(Stream stream, IMiniExcelConfiguration? configuration, bool leaveOpen = false, CancellationToken cancellationToken = default)
{
OpenXmlZip? archive = null;
OpenXmlMappingReader? reader = null;

try
{
ThrowHelper.ThrowIfInvalidOpenXml(stream);

archive = await OpenXmlZip.CreateAsync(stream, leaveOpen: leaveOpen, cancellationToken: cancellationToken).ConfigureAwait(false);
reader = new OpenXmlMappingReader(archive, configuration);
await reader.SetSharedStringsAsync(cancellationToken).ConfigureAwait(false);

var result = reader;
reader = null;
archive = null;
stream = null!;

return result;
}
finally
{
#if SYNC_ONLY
reader?.Dispose();
#else
if (reader?.DisposeAsync() is { } disposeTask)
await disposeTask.ConfigureAwait(false);
#endif

if (archive is not null)
await archive.DisposeAsync().ConfigureAwait(false);

if (!leaveOpen && (Stream?)stream is not null)
await stream.DisposeAsync().ConfigureAwait(false);
}
}

/// <summary>
/// Direct mapped query that bypasses dictionary creation for better performance
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions src/MiniExcel.OpenXml/MiniExcel.OpenXml.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@

<ItemGroup>
<InternalsVisibleTo Include="MiniExcel.OpenXml.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010091c2c6c10d20b6c884dbc48892f91cc773d33c3a1f43ba3352700031d2d5f6a2b37cccd60469733a4597bdd94b54ee63f514dc487b21be797b1b63063941630b46ad090baabaf0650d05b9c590ea497644f0c296bb223e17dc785f0fbb255ef780905aabf4cf14ee5bca087cbd41d2231169a620529626035215604261b533c9"/>
<InternalsVisibleTo Include="MiniExcel.OpenXml.FluentMapping, PublicKey=002400000480000094000000060200000024000052534131000400000100010091c2c6c10d20b6c884dbc48892f91cc773d33c3a1f43ba3352700031d2d5f6a2b37cccd60469733a4597bdd94b54ee63f514dc487b21be797b1b63063941630b46ad090baabaf0650d05b9c590ea497644f0c296bb223e17dc785f0fbb255ef780905aabf4cf14ee5bca087cbd41d2231169a620529626035215604261b533c9"/>
</ItemGroup>

<ItemGroup>
<Folder Include="FluentMapping\" />
</ItemGroup>

</Project>
17 changes: 9 additions & 8 deletions src/MiniExcel.OpenXml/Reader/OpenXmlReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@

namespace MiniExcelLib.OpenXml.Reader;

internal sealed partial class OpenXmlReader : IMiniExcelReader
internal partial class OpenXmlReader : IMiniExcelReader
{
private static readonly string[] Ns = [Schemas.SpreadsheetmlXmlMain, Schemas.SpreadsheetmlXmlStrictNs];
private static readonly string[] RelationshiopNs = [Schemas.SpreadsheetmlXmlRelationships, Schemas.SpreadsheetmlXmlStrictRelationships];
private readonly OpenXmlConfiguration _config;

protected static readonly string[] Ns = [Schemas.SpreadsheetmlXmlMain, Schemas.SpreadsheetmlXmlStrictNs];
protected readonly OpenXmlConfiguration _config;
protected OpenXmlStyles? _style;

private List<SheetRecord>? _sheetRecords;
private OpenXmlStyles? _style;
private bool _disposed;

internal readonly OpenXmlZip Archive;
internal IDictionary<int, string> SharedStrings = new Dictionary<int, string>();

private OpenXmlReader(OpenXmlZip archive, IMiniExcelConfiguration? configuration)
protected OpenXmlReader(OpenXmlZip archive, IMiniExcelConfiguration? configuration)
{
Archive = archive;
_config = (OpenXmlConfiguration?)configuration ?? OpenXmlConfiguration.Default;
Expand Down Expand Up @@ -362,7 +363,7 @@ internal static async Task<OpenXmlReader> CreateAsync(Stream stream, IMiniExcelC
yield return cell;
}

private ZipArchiveEntry GetSheetEntry(string? sheetName)
protected ZipArchiveEntry GetSheetEntry(string? sheetName)
{
// if sheets count > 1 need to read xl/_rels/workbook.xml.rels
var sheets = Archive.EntryCollection
Expand Down Expand Up @@ -429,7 +430,7 @@ private static void SetCellsValueAndHeaders(object? cellValue, bool hasHeaderRow
}

[CreateSyncVersion]
private async Task SetSharedStringsAsync(CancellationToken cancellationToken = default)
protected async Task SetSharedStringsAsync(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();

Expand Down Expand Up @@ -606,7 +607,7 @@ internal class CellAndColumn(object? cellValue, int columnIndex)
}

[CreateSyncVersion]
private async Task<CellAndColumn> ReadCellAndSetColumnIndexAsync(XmlReader reader, int columnIndex, bool withoutCr, int startColumnIndex, string aR, string aT, CancellationToken cancellationToken = default)
protected async Task<CellAndColumn> ReadCellAndSetColumnIndexAsync(XmlReader reader, int columnIndex, bool withoutCr, int startColumnIndex, string aR, string aT, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();

Expand Down
1 change: 1 addition & 0 deletions src/MiniExcel/MiniExcel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<ProjectReference Include="..\MiniExcel.Core\MiniExcel.Core.csproj" />
<ProjectReference Include="..\MiniExcel.Csv\MiniExcel.Csv.csproj" />
<ProjectReference Include="..\MiniExcel.OpenXml\MiniExcel.OpenXml.csproj" />
<ProjectReference Include="..\MiniExcel.OpenXml.FluentMapping\MiniExcel.OpenXml.FluentMapping.csproj" />
</ItemGroup>

</Project>
3 changes: 2 additions & 1 deletion tests/MiniExcel.OpenXml.Tests/MiniExcel.OpenXml.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
<PackageReference Include="ExcelDataReader.DataSet" Version="3.8.0" />
<PackageReference Include="NPOI" Version="2.8.0" />
<PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.9" Condition="'$(TargetFramework)' == 'net8.0' OR '$(TargetFramework)' == 'net9.0'" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.10" />

<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />

<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand All @@ -34,6 +34,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\MiniExcel.Core\MiniExcel.Core.csproj" />
<ProjectReference Include="..\..\src\MiniExcel.OpenXml\MiniExcel.OpenXml.csproj" />
<ProjectReference Include="..\..\src\MiniExcel.OpenXml.FluentMapping\MiniExcel.OpenXml.FluentMapping.csproj" />
<ProjectReference Include="..\MiniExcel.Tests.Common\MiniExcel.Tests.Common.csproj" />
</ItemGroup>

Expand Down
Loading