From 4af43aca6fd6bedec385bccda6b95ea17bd32378 Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Fri, 22 May 2026 00:04:29 +0200 Subject: [PATCH 01/12] Minor refactoring Renamed classes and variables, moved Excel data types to own static class, added new values to ExcelContentTypes, Schemas and ExcelFileNames, improved consistency of rels indexing --- .../Constants/ExcelContentTypes.cs | 7 ++-- .../Constants/ExcelDataTypes.cs | 12 +++++++ .../Constants/ExcelFileNames.cs | 7 ++-- src/MiniExcel.OpenXml/Constants/ExcelXml.cs | 6 ---- src/MiniExcel.OpenXml/Constants/Schemas.cs | 1 + .../Constants/WorksheetXml.cs | 10 +++--- .../Builder/DefaultSheetStyleBuilder.cs | 4 +-- .../Builder/MinimalSheetStyleBuilder.cs | 4 +-- .../Styles/Builder/SheetStyleBuildContext.cs | 4 +-- .../Styles/Builder/SheetStyleBuilderBase.cs | 4 +-- .../Styles/Builder/SheetStyleFormatsCache.cs | 1 + .../Writer/OpenXmlWriter.CopyInsert.cs | 24 ++++++------- .../Writer/OpenXmlWriter.DefaultOpenXml.cs | 26 +++++++------- src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs | 35 ++++++++++--------- 14 files changed, 78 insertions(+), 67 deletions(-) create mode 100644 src/MiniExcel.OpenXml/Constants/ExcelDataTypes.cs diff --git a/src/MiniExcel.OpenXml/Constants/ExcelContentTypes.cs b/src/MiniExcel.OpenXml/Constants/ExcelContentTypes.cs index dcef2d61..9f207e4d 100644 --- a/src/MiniExcel.OpenXml/Constants/ExcelContentTypes.cs +++ b/src/MiniExcel.OpenXml/Constants/ExcelContentTypes.cs @@ -3,9 +3,10 @@ internal static class ExcelContentTypes { internal const string Relationships = "application/vnd.openxmlformats-package.relationships+xml"; - internal const string SharedStrings = "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"; + internal const string Workbook = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"; internal const string Worksheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"; + internal const string SharedStrings = "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"; internal const string Styles = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"; internal const string Drawing = "application/vnd.openxmlformats-officedocument.drawing+xml"; - internal const string Workbook = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"; -} \ No newline at end of file + internal const string Table = "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"; +} diff --git a/src/MiniExcel.OpenXml/Constants/ExcelDataTypes.cs b/src/MiniExcel.OpenXml/Constants/ExcelDataTypes.cs new file mode 100644 index 00000000..0541c6f6 --- /dev/null +++ b/src/MiniExcel.OpenXml/Constants/ExcelDataTypes.cs @@ -0,0 +1,12 @@ +namespace MiniExcelLib.OpenXml.Constants; + +internal static class ExcelDataTypes +{ + internal const string InlineString = "inlineStr"; + internal const string CalculatedString = "str"; + internal const string SharedString = "s"; + internal const string Numeric = "n"; + internal const string Boolean = "b"; + internal const string DateTime = "d"; + internal const string Error = "e"; +} diff --git a/src/MiniExcel.OpenXml/Constants/ExcelFileNames.cs b/src/MiniExcel.OpenXml/Constants/ExcelFileNames.cs index eb5d7947..a5e98cf1 100644 --- a/src/MiniExcel.OpenXml/Constants/ExcelFileNames.cs +++ b/src/MiniExcel.OpenXml/Constants/ExcelFileNames.cs @@ -11,9 +11,10 @@ internal static class ExcelFileNames internal const string Workbook = "xl/workbook.xml"; internal const string WorkbookRels = "xl/_rels/workbook.xml.rels"; internal const string WorksheetBase = "xl/worksheets/sheet"; - + internal static string Worksheet(int sheetId) => $"xl/worksheets/sheet{sheetId}.xml"; internal static string SheetRels(int sheetId) => $"xl/worksheets/_rels/sheet{sheetId}.xml.rels"; - internal static string Drawing(int sheetIndex) => $"xl/drawings/drawing{sheetIndex + 1}.xml"; - internal static string DrawingRels(int sheetIndex) => $"xl/drawings/_rels/drawing{sheetIndex + 1}.xml.rels"; + internal static string Drawing(int sheetIndex) => $"xl/drawings/drawing{sheetIndex}.xml"; + internal static string DrawingRels(int sheetIndex) => $"xl/drawings/_rels/drawing{sheetIndex}.xml.rels"; + internal static string Table(int tableIndex) => $"xl/tables/table{tableIndex}.xml"; } diff --git a/src/MiniExcel.OpenXml/Constants/ExcelXml.cs b/src/MiniExcel.OpenXml/Constants/ExcelXml.cs index 13ba39dd..b9e2e183 100644 --- a/src/MiniExcel.OpenXml/Constants/ExcelXml.cs +++ b/src/MiniExcel.OpenXml/Constants/ExcelXml.cs @@ -11,12 +11,6 @@ static ExcelXml() DefaultDrawing = XmlHelper.MinifyXml(DefaultDrawing); } - internal const string InlineStringDataType = "inlineStr"; - internal const string CalculatedStringDataType = "str"; - internal const string SharedStringDataType = "s"; - internal const string NumericDataType = "n"; - internal const string BooleanDataType = "b"; - internal const string EmptySheetXml = """"""; internal static readonly string DefaultRels = diff --git a/src/MiniExcel.OpenXml/Constants/Schemas.cs b/src/MiniExcel.OpenXml/Constants/Schemas.cs index 88d436a4..94dfb55e 100644 --- a/src/MiniExcel.OpenXml/Constants/Schemas.cs +++ b/src/MiniExcel.OpenXml/Constants/Schemas.cs @@ -8,6 +8,7 @@ internal static class Schemas public const string OpenXmlPackageRelationships = "http://schemas.openxmlformats.org/package/2006/relationships"; public const string SpreadsheetmlXmlRelationships = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"; public const string SpreadsheetmlXmlStrictRelationships = "http://purl.oclc.org/ooxml/officeDocument/relationships"; + public const string SpreadsheetmlXmlTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"; public const string SpreadsheetmlXmlComments = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; public const string SpreadsheetmlXmlThreadedComment = "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment"; diff --git a/src/MiniExcel.OpenXml/Constants/WorksheetXml.cs b/src/MiniExcel.OpenXml/Constants/WorksheetXml.cs index fdfbee8a..ee909365 100644 --- a/src/MiniExcel.OpenXml/Constants/WorksheetXml.cs +++ b/src/MiniExcel.OpenXml/Constants/WorksheetXml.cs @@ -57,13 +57,13 @@ internal static string Cell(string cellReference, string? cellType, string style return cellType switch { _ when columnType == ColumnType.Formula - => $"""{XmlHelper.EncodeXml(cellValue)}""", + => $"""{XmlHelper.EncodeXml(cellValue)}""", - ExcelXml.InlineStringDataType - => $"""{XmlHelper.EncodeXml(cellValue)}""", + ExcelDataTypes.InlineString + => $"""{XmlHelper.EncodeXml(cellValue)}""", - ExcelXml.SharedStringDataType - => $"""{cellValue}""", + ExcelDataTypes.SharedString + => $"""{cellValue}""", _ => $"""{cellValue}""" }; diff --git a/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs b/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs index 191ad637..b6ac86ab 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs @@ -3,7 +3,7 @@ namespace MiniExcelLib.OpenXml.Styles.Builder; -internal partial class DefaultSheetStyleBuilder(SheetStyleBuildContext context, OpenXmlStyleOptions styleOptions) : SheetStyleBuilderBase(context) +internal partial class DefaultSheetStyleBuilder(SheetStyleBuilderContext context, OpenXmlStyleOptions styleOptions) : SheetStyleBuilderBase(context) { private const HorizontalCellAlignment DefaultHorizontalAlignment = HorizontalCellAlignment.Left; private const VerticalCellAlignment DefaultVerticalAlignment = VerticalCellAlignment.Bottom; @@ -19,7 +19,7 @@ internal partial class DefaultSheetStyleBuilder(SheetStyleBuildContext context, CellXfCount = 6 }; - private readonly SheetStyleBuildContext _context = context; + private readonly SheetStyleBuilderContext _context = context; private readonly OpenXmlStyleOptions _styleOptions = styleOptions; private XmlReader OldReader => _context.OldXmlReader!; diff --git a/src/MiniExcel.OpenXml/Styles/Builder/MinimalSheetStyleBuilder.cs b/src/MiniExcel.OpenXml/Styles/Builder/MinimalSheetStyleBuilder.cs index cfab877f..4da5e49b 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/MinimalSheetStyleBuilder.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/MinimalSheetStyleBuilder.cs @@ -1,6 +1,6 @@ namespace MiniExcelLib.OpenXml.Styles.Builder; -internal partial class MinimalSheetStyleBuilder(SheetStyleBuildContext context) : SheetStyleBuilderBase(context) +internal partial class MinimalSheetStyleBuilder(SheetStyleBuilderContext context) : SheetStyleBuilderBase(context) { private static readonly SheetStyleElementInfos GenerateElementInfos = new() { @@ -12,7 +12,7 @@ internal partial class MinimalSheetStyleBuilder(SheetStyleBuildContext context) CellXfCount = 6 }; - private readonly SheetStyleBuildContext _context = context; + private readonly SheetStyleBuilderContext _context = context; private XmlReader OldReader => _context.OldXmlReader!; private XmlWriter NewWriter => _context.NewXmlWriter!; diff --git a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs index dea1c482..06a155d4 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs @@ -2,7 +2,7 @@ namespace MiniExcelLib.OpenXml.Styles.Builder; -internal sealed partial class SheetStyleBuildContext(Dictionary contentTypes, ZipArchive archive, Encoding encoding) : IDisposable, IAsyncDisposable +internal sealed partial class SheetStyleBuilderContext(Dictionary contentTypes, ZipArchive archive, Encoding encoding) : IDisposable, IAsyncDisposable { private const string EmptyStylesXml = """ @@ -137,7 +137,7 @@ public async Task FinalizeAndUpdateZipDictionaryAsync(CancellationToken cancella if (!_initialized) throw new InvalidOperationException("The context has not been initialized."); if (_disposed) - throw new ObjectDisposedException(nameof(SheetStyleBuildContext)); + throw new ObjectDisposedException(nameof(SheetStyleBuilderContext)); if (_finalized) throw new InvalidOperationException("The context has been finalized."); diff --git a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuilderBase.cs b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuilderBase.cs index 534f9737..35e8e362 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuilderBase.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuilderBase.cs @@ -1,8 +1,8 @@ namespace MiniExcelLib.OpenXml.Styles.Builder; -internal abstract partial class SheetStyleBuilderBase(SheetStyleBuildContext context) : ISheetStyleBuilder +internal abstract partial class SheetStyleBuilderBase(SheetStyleBuilderContext context) : ISheetStyleBuilder { - private readonly SheetStyleBuildContext _context = context; + private readonly SheetStyleBuilderContext _context = context; //todo: these may actually be null if used when the context is not initialized private XmlReader OldReader => _context.OldXmlReader!; diff --git a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleFormatsCache.cs b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleFormatsCache.cs index e7ec1ca9..2feb550b 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleFormatsCache.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleFormatsCache.cs @@ -1,5 +1,6 @@ namespace MiniExcelLib.OpenXml.Styles.Builder; +// todo: find a way to make it compatible with SharedStringsDiskCache internal class SheetStyleFormatsCache { private readonly Dictionary _formatMappings = []; diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs index 7839b7c8..164018a8 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs @@ -71,8 +71,8 @@ public async Task CopyAndInsertAsync(bool overwriteSheet = false, IProgress var sheetStylesBuilderUtils = await CopySheetStylesAndGetBuilderUtilsAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStylesBuilderUtils = sheetStylesBuilderUtils.ConfigureAwait(false); - await _sheetStyleBuildContext.DisposeAsync().ConfigureAwait(false); - _sheetStyleBuildContext = sheetStylesBuilderUtils.SheetStyleBuildContext; + await _sheetStyleBuilderContext.DisposeAsync().ConfigureAwait(false); + _sheetStyleBuilderContext = sheetStylesBuilderUtils.SheetStyleBuilderContext; var sharedStringsEntry = _oldArchive.GetEntry(ExcelFileNames.SharedStrings); if (sharedStringsEntry is not null) @@ -101,8 +101,8 @@ public async Task CopyAndInsertAsync(bool overwriteSheet = false, IProgress entriesToIgnoreOnCopy.AddRange([ ExcelFileNames.Worksheet(_currentSheetIndex), ExcelFileNames.SheetRels(_currentSheetIndex), - ExcelFileNames.Drawing(_currentSheetIndex - 1), - ExcelFileNames.DrawingRels(_currentSheetIndex - 1) + ExcelFileNames.Drawing(_currentSheetIndex), + ExcelFileNames.DrawingRels(_currentSheetIndex) ]); } @@ -132,8 +132,8 @@ public async Task CopyAndInsertAsync(bool overwriteSheet = false, IProgress await AddFilesToZipAsync(cancellationToken).ConfigureAwait(false); await GenerateSharedStringsAsync(cancellationToken).ConfigureAwait(false); - await GenerateDrawingRelXmlAsync(_currentSheetIndex - 1, cancellationToken).ConfigureAwait(false); - await GenerateDrawingXmlAsync(_currentSheetIndex - 1, cancellationToken).ConfigureAwait(false); + await GenerateDrawingRelXmlAsync(_currentSheetIndex, cancellationToken).ConfigureAwait(false); + await GenerateDrawingXmlAsync(_currentSheetIndex, cancellationToken).ConfigureAwait(false); await CreateZipEntryAsync( ExcelFileNames.SheetRels(_currentSheetIndex), @@ -184,10 +184,10 @@ private async Task CopySheetStylesAndGetBuilderUtil backingStream.Seek(0, SeekOrigin.Begin); var copiedArchive = await ZipArchive.CreateAsync(backingStream, ZipArchiveMode.Update, true, Utf8WithBom, cancellationToken).ConfigureAwait(false); - SheetStyleBuildContext? oldStylesContext = null; + SheetStyleBuilderContext? oldStylesContext = null; try { - oldStylesContext = new SheetStyleBuildContext(_zipContentsMap, copiedArchive, Utf8WithBom); + oldStylesContext = new SheetStyleBuilderContext(_zipContentsMap, copiedArchive, Utf8WithBom); SheetStyleBuilderBase builder = _configuration.TableStyles switch { TableStyles.None => new MinimalSheetStyleBuilder(oldStylesContext), @@ -285,24 +285,24 @@ private async Task CopyAndUpdateContentTypesAsync(CancellationToken cancellation #endif } - private class TempSheetStylesBuilderUtils(Stream backingStream, ZipArchive archive, SheetStyleBuildContext sheetStyleBuildContext, ISheetStyleBuilder sheetStyleBuilder) : IDisposable, IAsyncDisposable + private class TempSheetStylesBuilderUtils(Stream backingStream, ZipArchive archive, SheetStyleBuilderContext sheetStyleBuilderContext, ISheetStyleBuilder sheetStyleBuilder) : IDisposable, IAsyncDisposable { private readonly Stream _backingStream = backingStream; public ZipArchive Archive { get; } = archive; public ISheetStyleBuilder SheetStyleBuilder { get; } = sheetStyleBuilder; - public SheetStyleBuildContext SheetStyleBuildContext { get; } = sheetStyleBuildContext; + public SheetStyleBuilderContext SheetStyleBuilderContext { get; } = sheetStyleBuilderContext; public void Dispose() { - SheetStyleBuildContext.Dispose(); + SheetStyleBuilderContext.Dispose(); Archive.Dispose(); _backingStream.Dispose(); } public async ValueTask DisposeAsync() { - await SheetStyleBuildContext.DisposeAsync().ConfigureAwait(false); + await SheetStyleBuilderContext.DisposeAsync().ConfigureAwait(false); #if NET10_0_OR_GREATER await Archive.DisposeAsync().ConfigureAwait(false); #else diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs index 6db4ac8b..9f1a9512 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs @@ -216,23 +216,23 @@ private string GetPanes() var cellValue = GetNumericValue(value, type); if (columnMapping?.ExcelFormat is null) { - var dataType = ReferenceEquals(_configuration.Culture, CultureInfo.InvariantCulture) ? ExcelXml.NumericDataType : GetStringType(); + var dataType = ReferenceEquals(_configuration.Culture, CultureInfo.InvariantCulture) ? ExcelDataTypes.Numeric : GetStringType(); return (RegularCellStyleIndex, dataType, cellValue); } - return (columnMapping.ExcelFormatId.ToString(), ExcelXml.NumericDataType, cellValue); + return (columnMapping.ExcelFormatId.ToString(), ExcelDataTypes.Numeric, cellValue); } if (type == typeof(bool)) - return (RegularCellStyleIndex, ExcelXml.BooleanDataType, (bool)value ? "1" : "0"); + return (RegularCellStyleIndex, ExcelDataTypes.Boolean, (bool)value ? "1" : "0"); if (type == typeof(byte[]) && _configuration.EnableConvertByteArray) { if (!_configuration.EnableWriteFilePath) - return (FillCellStyleIndex, ExcelXml.CalculatedStringDataType, ""); + return (FillCellStyleIndex, ExcelDataTypes.CalculatedString, ""); var base64 = GetFileValue(rowIndex, cellIndex, value); - return (FillCellStyleIndex, ExcelXml.InlineStringDataType, base64); + return (FillCellStyleIndex, ExcelDataTypes.InlineString, base64); } return (RegularCellStyleIndex, GetStringType(), value.ToString()); @@ -240,11 +240,11 @@ private string GetPanes() string GetStringType() { if (columnMapping?.ExcelColumnType == ColumnType.Formula) - return ExcelXml.CalculatedStringDataType; + return ExcelDataTypes.CalculatedString; return _configuration.StringStorageMode == StringStorageMode.Shared - ? ExcelXml.SharedStringDataType - : ExcelXml.InlineStringDataType; + ? ExcelDataTypes.SharedString + : ExcelDataTypes.InlineString; } } @@ -332,14 +332,14 @@ private string GetFileValue(int rowIndex, int cellIndex, object value) if (!ReferenceEquals(_configuration.Culture, CultureInfo.InvariantCulture)) { cellValue = value.ToString(_configuration.Culture); - return (RegularCellStyleIndex, ExcelXml.CalculatedStringDataType, cellValue); + return (RegularCellStyleIndex, ExcelDataTypes.CalculatedString, cellValue); } var oaDate = CorrectDateTimeValue(value); cellValue = oaDate.ToString(CultureInfo.InvariantCulture); var format = columnMapping?.ExcelFormatId is { } fmt and not -1 ? fmt.ToString() : DateCellStyleIndex; - return (format, ExcelXml.NumericDataType, cellValue); + return (format, ExcelDataTypes.Numeric, cellValue); } private static double CorrectDateTimeValue(DateTime value) @@ -366,7 +366,7 @@ private static double CorrectDateTimeValue(DateTime value) var cellValue = value.TotalDays.ToString(CultureInfo.InvariantCulture); var format = columnMapping?.ExcelFormatId is { } fmt and not -1 ? fmt.ToString() : TimeCellStyleIndex; - return (format, ExcelXml.NumericDataType, cellValue); + return (format, ExcelDataTypes.Numeric, cellValue); } private static string GetDimensionRef(int maxRowIndex, int maxColumnIndex) @@ -383,7 +383,7 @@ private static string GetDimensionRef(int maxRowIndex, int maxColumnIndex) private string GetDrawingRelationshipXml(int sheetIndex) { var drawing = new StringBuilder(); - foreach (var image in _files.Where(w => w.IsImage && w.SheetId == sheetIndex + 1)) + foreach (var image in _files.Where(w => w.IsImage && w.SheetId == sheetIndex)) { drawing.AppendLine(ExcelXml.ImageRelationship(image)); } @@ -398,7 +398,7 @@ private string GetDrawingXml(int sheetIndex) for (int fileIndex = 0; fileIndex < _files.Count; fileIndex++) { var file = _files[fileIndex]; - if (file.IsImage && file.SheetId == sheetIndex + 1) + if (file.IsImage && file.SheetId == sheetIndex) { drawing.Append(ExcelXml.DrawingXml(file, fileIndex)); } diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs index 0363b789..7d50c111 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs @@ -22,8 +22,9 @@ internal partial class OpenXmlWriter : IMiniExcelWriter private readonly bool _printHeader; private readonly object? _value; - private int _currentSheetIndex = 0; - private SheetStyleBuildContext _sheetStyleBuildContext; + // the index is 1-based to match how the rels work in OpenXml and to make it more intuitive to reason about them + private int _currentSheetIndex; + private SheetStyleBuilderContext _sheetStyleBuilderContext; private OpenXmlWriter(Stream stream, ZipArchive archive, object? value, string sheetName, OpenXmlConfiguration configuration, bool printHeader) @@ -37,7 +38,7 @@ private OpenXmlWriter(Stream stream, ZipArchive archive, object? value, string s _printHeader = printHeader; _sheetName = sheetName; - _sheetStyleBuildContext = new SheetStyleBuildContext(_zipContentsMap, _archive, Utf8WithBom); + _sheetStyleBuilderContext = new SheetStyleBuilderContext(_zipContentsMap, _archive, Utf8WithBom); } [CreateSyncVersion] @@ -67,7 +68,7 @@ public async Task SaveAsAsync(IProgress? progress = null, Cancellati #endif await CreateZipEntryAsync(ExcelFileNames.Rels, ExcelContentTypes.Relationships, ExcelXml.DefaultRels, cancellationToken).ConfigureAwait(false); - await using var sbc = _sheetStyleBuildContext.ConfigureAwait(false); + await using var sbc = _sheetStyleBuilderContext.ConfigureAwait(false); var styleBuilder = await GetSheetStyleBuilderAsync(cancellationToken).ConfigureAwait(false); var sheets = GetSheets(); @@ -105,7 +106,7 @@ public async Task InsertAsync(bool overwriteSheet = false, IProgress? #else using var disposableArchive = _archive; #endif - await using var sbc = _sheetStyleBuildContext.ConfigureAwait(false); + await using var sbc = _sheetStyleBuilderContext.ConfigureAwait(false); using var reader = await OpenXmlReader.CreateAsync(_stream, _configuration, cancellationToken: cancellationToken).ConfigureAwait(false); var rels = await reader.GetWorkbookRelsAsync(_archive.Entries, cancellationToken).ConfigureAwait(false) ?? []; @@ -158,11 +159,11 @@ public async Task InsertAsync(bool overwriteSheet = false, IProgress? sharedStringsEntry?.Delete(); await GenerateSharedStringsAsync(cancellationToken).ConfigureAwait(false); - _archive.Entries.SingleOrDefault(s => s.FullName == ExcelFileNames.DrawingRels(_currentSheetIndex - 1))?.Delete(); - await GenerateDrawingRelXmlAsync(_currentSheetIndex - 1, cancellationToken).ConfigureAwait(false); + _archive.Entries.SingleOrDefault(s => s.FullName == ExcelFileNames.DrawingRels(_currentSheetIndex))?.Delete(); + await GenerateDrawingRelXmlAsync(_currentSheetIndex, cancellationToken).ConfigureAwait(false); - _archive.Entries.SingleOrDefault(s => s.FullName == ExcelFileNames.Drawing(_currentSheetIndex - 1))?.Delete(); - await GenerateDrawingXmlAsync(_currentSheetIndex - 1, cancellationToken).ConfigureAwait(false); + _archive.Entries.SingleOrDefault(s => s.FullName == ExcelFileNames.Drawing(_currentSheetIndex))?.Delete(); + await GenerateDrawingXmlAsync(_currentSheetIndex, cancellationToken).ConfigureAwait(false); await GenerateWorkbookXmlAsync(true, cancellationToken).ConfigureAwait(false); await InsertContentTypesXmlAsync(cancellationToken).ConfigureAwait(false); @@ -253,7 +254,7 @@ private async Task WriteValuesAsync(MiniExcelStreamWriter writer, object va return 0; } - _sheetStyleBuildContext.UpdateFormatIds(mappings); + _sheetStyleBuilderContext.UpdateFormatIds(mappings); int maxRowIndex; var maxColumnIndex = mappings.Count(x => x is { ExcelIgnoreColumn: false }); @@ -433,7 +434,7 @@ private static async Task PrintHeaderAsync(MiniExcelStreamWriter writer, List GetSheetStyleBuilderAsync(CancellationTok { SheetStyleBuilderBase builder = _configuration.TableStyles switch { - TableStyles.None => new MinimalSheetStyleBuilder(_sheetStyleBuildContext), - TableStyles.Default => new DefaultSheetStyleBuilder(_sheetStyleBuildContext, _configuration.StyleOptions), + TableStyles.None => new MinimalSheetStyleBuilder(_sheetStyleBuilderContext), + TableStyles.Default => new DefaultSheetStyleBuilder(_sheetStyleBuilderContext, _configuration.StyleOptions), _ => throw new InvalidEnumArgumentException(nameof(_configuration.TableStyles), (int)_configuration.TableStyles, typeof(TableStyles)) }; var newInfos = builder.GetGeneratedElementInfos(); - await _sheetStyleBuildContext.CreateAsync(newInfos, cancellationToken).ConfigureAwait(false); + await _sheetStyleBuilderContext.CreateAsync(newInfos, cancellationToken).ConfigureAwait(false); return builder; } @@ -529,7 +530,7 @@ private async Task GetSheetStyleBuilderAsync(CancellationTok [CreateSyncVersion] private async Task GenerateDrawingRelXmlAsync(CancellationToken cancellationToken) { - for (int sheetIndex = 0; sheetIndex < _sheets.Count; sheetIndex++) + for (int sheetIndex = 1; sheetIndex <= _sheets.Count; sheetIndex++) { cancellationToken.ThrowIfCancellationRequested(); await GenerateDrawingRelXmlAsync(sheetIndex, cancellationToken).ConfigureAwait(false); @@ -550,7 +551,7 @@ await CreateZipEntryAsync( [CreateSyncVersion] private async Task GenerateDrawingXmlAsync(CancellationToken cancellationToken) { - for (int sheetIndex = 0; sheetIndex < _sheets.Count; sheetIndex++) + for (int sheetIndex = 1; sheetIndex <= _sheets.Count; sheetIndex++) { cancellationToken.ThrowIfCancellationRequested(); await GenerateDrawingXmlAsync(sheetIndex, cancellationToken).ConfigureAwait(false); From 8b1873179141654c6a6b1c75625a743c6af3150f Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Fri, 22 May 2026 20:36:42 +0200 Subject: [PATCH 02/12] Cleaning up some tests --- tests/MiniExcel.Csv.Tests/AsyncIssueTests.cs | 195 +++++------------- tests/MiniExcel.Csv.Tests/IssueTests.cs | 139 ++----------- .../MiniExcelOpenXmlAsyncTests.cs | 2 - .../MiniExcelOpenXmlTests.cs | 3 +- 4 files changed, 80 insertions(+), 259 deletions(-) diff --git a/tests/MiniExcel.Csv.Tests/AsyncIssueTests.cs b/tests/MiniExcel.Csv.Tests/AsyncIssueTests.cs index 5487c9e5..6ef7284a 100644 --- a/tests/MiniExcel.Csv.Tests/AsyncIssueTests.cs +++ b/tests/MiniExcel.Csv.Tests/AsyncIssueTests.cs @@ -5,8 +5,6 @@ public class AsyncIssueTests private readonly CsvExporter _csvExporter = MiniExcel.Exporters.GetCsvExporter(); private readonly CsvImporter _csvImporter = MiniExcel.Importers.GetCsvImporter(); - private readonly OpenXmlExporter _openXmlExporter = MiniExcel.Exporters.GetOpenXmlExporter(); - private readonly OpenXmlImporter _openXmlImporter = MiniExcel.Importers.GetOpenXmlImporter(); /// /// Csv SaveAs by datareader with encoding default show messy code #253 /// @@ -111,60 +109,36 @@ public enum WorkState [Fact] public async Task Issue89() { - { - const string text = - """ - State - OnDuty - Fired - Leave - """; - await using var stream = new MemoryStream(); - await using var writer = new StreamWriter(stream); - - await writer.WriteAsync(text); - await writer.FlushAsync(); - - stream.Position = 0; - var q = _csvImporter.QueryAsync(stream).ToBlockingEnumerable(); - var rows = q.ToList(); - - Assert.Equal(Issue89Dto.WorkState.OnDuty, rows[0].State); - Assert.Equal(Issue89Dto.WorkState.Fired, rows[1].State); - Assert.Equal(Issue89Dto.WorkState.Leave, rows[2].State); - - var outputPath = PathHelper.GetTempPath(); - var rowsWritten = await _openXmlExporter.ExportAsync(outputPath, rows); - Assert.Single(rowsWritten); - Assert.Equal(3, rowsWritten[0]); - - var q2 = _openXmlImporter.QueryAsync(outputPath).ToBlockingEnumerable(); - var rows2 = q2.ToList(); - Assert.Equal(Issue89Dto.WorkState.OnDuty, rows2[0].State); - Assert.Equal(Issue89Dto.WorkState.Fired, rows2[1].State); - Assert.Equal(Issue89Dto.WorkState.Leave, rows2[2].State); - } + const string text = + """ + State + OnDuty + Fired + Leave + """; - //xlsx - { - var path = PathHelper.GetFile("xlsx/TestIssue89.xlsx"); - var q = _openXmlImporter.QueryAsync(path).ToBlockingEnumerable(); - var rows = q.ToList(); - Assert.Equal(Issue89Dto.WorkState.OnDuty, rows[0].State); - Assert.Equal(Issue89Dto.WorkState.Fired, rows[1].State); - Assert.Equal(Issue89Dto.WorkState.Leave, rows[2].State); - - var outputPath = PathHelper.GetTempPath(); - var rowsWritten = await _openXmlExporter.ExportAsync(outputPath, rows); - Assert.Single(rowsWritten); - Assert.Equal(3, rowsWritten[0]); - - var q1 = _openXmlImporter.QueryAsync(outputPath).ToBlockingEnumerable(); - var rows2 = q1.ToList(); - Assert.Equal(Issue89Dto.WorkState.OnDuty, rows2[0].State); - Assert.Equal(Issue89Dto.WorkState.Fired, rows2[1].State); - Assert.Equal(Issue89Dto.WorkState.Leave, rows2[2].State); - } + await using var stream = new MemoryStream(); + await using var writer = new StreamWriter(stream); + + await writer.WriteAsync(text); + await writer.FlushAsync(); + + stream.Position = 0; + var rows1 = await _csvImporter.QueryAsync(stream).ToListAsync(); + + Assert.Equal(Issue89Dto.WorkState.OnDuty, rows1[0].State); + Assert.Equal(Issue89Dto.WorkState.Fired, rows1[1].State); + Assert.Equal(Issue89Dto.WorkState.Leave, rows1[2].State); + + var outputPath = PathHelper.GetTempPath(); + var rowsWritten = await MiniExcel.Exporters.GetOpenXmlExporter().ExportAsync(outputPath, rows1); + Assert.Single(rowsWritten); + Assert.Equal(3, rowsWritten[0]); + + var rows2 = await MiniExcel.Importers.GetOpenXmlImporter().QueryAsync(outputPath).ToListAsync(); + 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 Issue142VoDuplicateColumnName @@ -184,76 +158,27 @@ private class Issue142VoDuplicateColumnName [Fact] public async Task Issue142() { - { - using var file = AutoDeletingPath.Create(); - var path = file.ToString(); - await _openXmlExporter.ExportAsync(path, new[] { new Issue142Dto { MyProperty1 = "MyProperty1", MyProperty2 = "MyProperty2", MyProperty3 = "MyProperty3", MyProperty4 = "MyProperty4", MyProperty5 = "MyProperty5", MyProperty6 = "MyProperty6", MyProperty7 = "MyProperty7" } }); - - { - var q = _openXmlImporter.QueryAsync(path).ToBlockingEnumerable(); - var rows = q.ToList(); - Assert.Equal("MyProperty4", rows[0].A); - Assert.Equal("CustomColumnName", rows[0].B); //note - 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); //note - 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 q = _openXmlImporter.QueryAsync(path).ToBlockingEnumerable(); - var rows = q.ToList(); - - Assert.Equal("MyProperty4", rows[0].MyProperty4); - Assert.Equal("MyProperty1", rows[0].MyProperty1); //note - 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); - } - } - - { - using var file = AutoDeletingPath.Create(ExcelType.Csv); - var path = file.ToString(); - await _csvExporter.ExportAsync(path, new[] { new Issue142Dto { MyProperty1 = "MyProperty1", MyProperty2 = "MyProperty2", MyProperty3 = "MyProperty3", MyProperty4 = "MyProperty4", MyProperty5 = "MyProperty5", MyProperty6 = "MyProperty6", MyProperty7 = "MyProperty7" } }); - const string expected = - """ - MyProperty4,CustomColumnName,MyProperty5,MyProperty2,MyProperty6,,MyProperty3 - MyProperty4,MyProperty1,MyProperty5,MyProperty2,MyProperty6,,MyProperty3 - - """; - Assert.Equal(expected, await File.ReadAllTextAsync(path)); - - { - var q = _csvImporter.QueryAsync(path).ToBlockingEnumerable(); - var rows = q.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); - } - } + using var file = AutoDeletingPath.Create(ExcelType.Csv); + var path = file.ToString(); - { - using var path = AutoDeletingPath.Create(); - Issue142VoDuplicateColumnName[] input = [new() { MyProperty1 = 0, MyProperty2 = 0, MyProperty3 = 0, MyProperty4 = 0 }]; - Assert.Throws(() => _openXmlExporter.Export(path.ToString(), input)); - } + await _csvExporter.ExportAsync(path, new[] { new Issue142Dto { MyProperty1 = "MyProperty1", MyProperty2 = "MyProperty2", MyProperty3 = "MyProperty3", MyProperty4 = "MyProperty4", MyProperty5 = "MyProperty5", MyProperty6 = "MyProperty6", MyProperty7 = "MyProperty7" } }); + const string expected = + """ + MyProperty4,CustomColumnName,MyProperty5,MyProperty2,MyProperty6,,MyProperty3 + MyProperty4,MyProperty1,MyProperty5,MyProperty2,MyProperty6,,MyProperty3 + + """; + + Assert.Equal(expected, await File.ReadAllTextAsync(path)); + var rows = await _csvImporter.QueryAsync(path).ToListAsync(); + + 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); } /// @@ -273,8 +198,7 @@ public async Task Issue217() using var path = AutoDeletingPath.Create(ExcelType.Csv); await _csvExporter.ExportAsync(path.ToString(), table); - var q = _csvImporter.QueryAsync(path.ToString()).ToBlockingEnumerable(); - var rows = q.ToList(); + var rows = await _csvImporter.QueryAsync(path.ToString()).ToListAsync(); Assert.Equal("Name", rows[0].B); Assert.Equal("Limit", rows[0].C); } @@ -295,9 +219,7 @@ public async Task Issue237() }; await _csvExporter.ExportAsync(path.ToString(), value); - var q = _csvImporter.QueryAsync(path.ToString(), true).ToBlockingEnumerable(); - var rows = q.ToList(); - + var rows = await _csvImporter.QueryAsync(path.ToString(), true).ToListAsync(); Assert.Equal("\"\"1,2,3\"\"", rows[0].id); Assert.Equal("1,2,3", rows[1].id); } @@ -322,13 +244,11 @@ public async Task Issue241() Assert.Single(rowsWritten); Assert.Equal(2, rowsWritten[0]); - var q1 = _csvImporter.QueryAsync(path, true).ToBlockingEnumerable(); - var rows1 = q1.ToList(); + var rows1 = await _csvImporter.QueryAsync(path, true).ToListAsync(); Assert.Equal(rows1[0].InDate, "01 04, 2021"); Assert.Equal(rows1[1].InDate, "04 05, 2020"); - var q2 = _csvImporter.QueryAsync(path).ToBlockingEnumerable(); - var rows2 = q2.ToList(); + var rows2 = await _csvImporter.QueryAsync(path).ToListAsync(); Assert.Equal(rows2[0].InDate, new DateTime(2021, 01, 04)); Assert.Equal(rows2[1].InDate, new DateTime(2020, 04, 05)); } @@ -343,17 +263,16 @@ public async Task Issue243() using var path = AutoDeletingPath.Create(ExcelType.Csv); 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)}, + new { Name = "Jack", Age = 25, InDate = new DateTime(2021,01,03) }, + new { Name = "Henry", Age = 36, InDate = new DateTime(2020,05,03) } }; var rowsWritten = await _csvExporter.ExportAsync(path.ToString(), value); Assert.Single(rowsWritten); Assert.Equal(2, rowsWritten[0]); - var q = _csvImporter.QueryAsync(path.ToString()).ToBlockingEnumerable(); - var rows = q.ToList(); - + var rows = await _csvImporter.QueryAsync(path.ToString()).ToListAsync(); + Assert.Equal("Jack", rows[0].Name); Assert.Equal(25, rows[0].Age); Assert.Equal(new DateTime(2021, 01, 03), rows[0].InDate); diff --git a/tests/MiniExcel.Csv.Tests/IssueTests.cs b/tests/MiniExcel.Csv.Tests/IssueTests.cs index 47f8adcc..a8a8fe17 100644 --- a/tests/MiniExcel.Csv.Tests/IssueTests.cs +++ b/tests/MiniExcel.Csv.Tests/IssueTests.cs @@ -324,81 +324,6 @@ public void TestIssueI4Wda9() [Fact] public void TestIssue316() { - // XLSX - { - using var file = AutoDeletingPath.Create(); - var path = file.ToString(); - var value = new[] - { - new{ Amount=123_456.789M, CreateTime=DateTime.Parse("2018-01-31",CultureInfo.InvariantCulture)} - }; - var config = new OpenXmlConfiguration - { - Culture = new CultureInfo("fr-FR"), - }; - _openXmlExporter.Export(path, value, configuration: config); - - //Datetime error - Assert.Throws(() => - { - var conf = new OpenXmlConfiguration - { - Culture = new CultureInfo("en-US"), - }; - _ = _openXmlImporter.Query(path, configuration: conf).ToList(); - }); - - // dynamic - var rows = _openXmlImporter.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(); - var path = file.ToString(); - var value = new[] - { - new { Amount = 123_456.789M, CreateTime = new DateTime(2018, 5, 12) } - }; - { - var config = new OpenXmlConfiguration - { - Culture = new CultureInfo("fr-FR"), - }; - _openXmlExporter.Export(path, value, configuration: config); - } - - { - var rows = _openXmlImporter.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 OpenXmlConfiguration - { - Culture = new CultureInfo("en-US"), - }; - var rows = _openXmlImporter.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 OpenXmlConfiguration - { - Culture = new CultureInfo("fr-FR"), - }; - var rows = _openXmlImporter.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); - } - } - // CSV { using var file = AutoDeletingPath.Create(ExcelType.Csv); @@ -677,53 +602,33 @@ public enum WorkState public void Issue89() { //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, useHeaderRow: 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(); + const string text = + """ + State + OnDuty + Fired + Leave + """; - Assert.Equal(Issue89Model.WorkState.OnDuty, rows2[0].State); - Assert.Equal(Issue89Model.WorkState.Fired, rows2[1].State); - Assert.Equal(Issue89Model.WorkState.Leave, rows2[2].State); - } + using var stream = new MemoryStream(); + using var writer = new StreamWriter(stream); - //xlsx - { - var path = PathHelper.GetFile("xlsx/TestIssue89.xlsx"); - var rows = _openXmlImporter.Query(path).ToList(); + writer.Write(text); + writer.Flush(); + stream.Position = 0; + var rows = _csvImporter.Query(stream, useHeaderRow: true).ToList(); - Assert.Equal(Issue89Model.WorkState.OnDuty, rows[0].State); - Assert.Equal(Issue89Model.WorkState.Fired, rows[1].State); - Assert.Equal(Issue89Model.WorkState.Leave, rows[2].State); + 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 xlsxPath = AutoDeletingPath.Create(); - _openXmlExporter.Export(xlsxPath.ToString(), rows); - var rows2 = _openXmlImporter.Query(xlsxPath.ToString()).ToList(); + 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); - } + 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 diff --git a/tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlAsyncTests.cs b/tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlAsyncTests.cs index 31b58c15..de39a2a4 100644 --- a/tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlAsyncTests.cs +++ b/tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlAsyncTests.cs @@ -388,9 +388,7 @@ public async Task LargeFileQueryStrongTypeMapping_Test() [InlineData("../../../../data/xlsx/TestCenterEmptyRow/TestCenterEmptyRow.xlsx")] public async Task QueryExcelDataReaderCheckTest(string path) { -#if NETCOREAPP3_1_OR_GREATER Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); -#endif await using var fs = File.OpenRead(path); using var reader = ExcelReaderFactory.CreateReader(fs); diff --git a/tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlTests.cs b/tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlTests.cs index fedb55ef..14b663be 100644 --- a/tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlTests.cs +++ b/tests/MiniExcel.OpenXml.Tests/MiniExcelOpenXmlTests.cs @@ -455,9 +455,8 @@ public void LargeFileQueryStrongTypeMapping_Test() [InlineData("../../../../data/xlsx/TestCenterEmptyRow/TestCenterEmptyRow.xlsx")] public void QueryDataReaderCheckTest(string path) { -#if NETCOREAPP3_1_OR_GREATER Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); -#endif + using var fs = File.OpenRead(path); using var reader = ExcelReaderFactory.CreateReader(fs); var exceldatareaderResult = reader.AsDataSet(); From 8d58b0d5464e9dd155aca6c1a3da7e5241abd70b Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Fri, 22 May 2026 20:55:41 +0200 Subject: [PATCH 03/12] Added Dictionary.TryAdd polyfill for netstandard2.0 --- src/MiniExcel.Core/Helpers/ExpandoHelper.cs | 10 ---------- src/MiniExcel.Core/Helpers/Polyfills.cs | 10 ++++++++++ src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs | 5 ----- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/MiniExcel.Core/Helpers/ExpandoHelper.cs b/src/MiniExcel.Core/Helpers/ExpandoHelper.cs index 5d5572ef..e099a010 100644 --- a/src/MiniExcel.Core/Helpers/ExpandoHelper.cs +++ b/src/MiniExcel.Core/Helpers/ExpandoHelper.cs @@ -10,12 +10,7 @@ public static class ExpandoHelper for (int i = startCellIndex; i <= maxColumnIndex; i++) { var key = CellReferenceConverter.GetAlphabeticalIndex(i); -#if NETCOREAPP2_0_OR_GREATER cell.TryAdd(key, null); -#else - if (!cell.ContainsKey(key)) - cell.Add(key, null); -#endif } return cell; @@ -26,12 +21,7 @@ public static class ExpandoHelper IDictionary cell = new ExpandoObject(); foreach (var hr in headers) { -#if NETCOREAPP2_0_OR_GREATER cell.TryAdd(hr.Value, null); -#else - if (!cell.ContainsKey(hr.Value)) - cell.Add(hr.Value, null); -#endif } return cell; diff --git a/src/MiniExcel.Core/Helpers/Polyfills.cs b/src/MiniExcel.Core/Helpers/Polyfills.cs index 164d0792..b6454259 100644 --- a/src/MiniExcel.Core/Helpers/Polyfills.cs +++ b/src/MiniExcel.Core/Helpers/Polyfills.cs @@ -15,6 +15,16 @@ public static class Polyfills return dictionary.TryGetValue(key, out var value) ? value : defaultValue; } + [EditorBrowsable(EditorBrowsableState.Advanced)] + public static bool TryAdd(this IDictionary dictionary, TKey key, TValue value) + { + if (dictionary.ContainsKey(key)) + return false; + + dictionary.Add(key, value); + return true; + } + [EditorBrowsable(EditorBrowsableState.Advanced)] public static void Deconstruct(this KeyValuePair kvp, out TKey key, out TValue value) { diff --git a/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs b/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs index 20f51a19..8783cbd5 100644 --- a/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs +++ b/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs @@ -86,12 +86,7 @@ public OpenXmlStyles(OpenXmlZip zip) type = typeof(DateTime?); } -#if NETCOREAPP2_0_OR_GREATER _customFormats.TryAdd(numFmtId, new NumberFormatString(formatCode, type)); -#else - if (!_customFormats.ContainsKey(numFmtId)) - _customFormats.Add(numFmtId, new NumberFormatString(formatCode, type)); -#endif reader.Skip(); } else if (!reader.SkipContent()) From c7f2816ec64c166d11b23ba90c26dd43e4038fc2 Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Fri, 22 May 2026 22:21:22 +0200 Subject: [PATCH 04/12] Simplified preprocessor directives Changed all directives between `#if NETCOREAPP2_0` and `#if NET8_0` to the simpler `#if NET` to reflect the project's minimum target framework of .NET8 --- .../Helpers/MiniExcelStreamWriter.cs | 4 +- src/MiniExcel.Core/MiniExcelDataReader.cs | 2 +- .../Reflection/MiniExcelMapper.cs | 4 +- src/MiniExcel.Csv/CsvReader.cs | 6 +- src/MiniExcel.Csv/CsvWriter.cs | 96 ++++++++----------- src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs | 8 +- src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs | 20 ++-- src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs | 10 +- .../FluentMapping/Api/MappingExporter.cs | 2 +- .../FluentMapping/Api/MappingImporter.cs | 4 +- .../FluentMapping/Api/MappingTemplater.cs | 4 +- .../Configuration/CollectionMappingBuilder.cs | 4 +- .../Configuration/PropertyMappingBuilder.cs | 4 +- .../MappingTemplateApplicator.cs | 14 +-- src/MiniExcel.OpenXml/Helpers/XmlHelper.cs | 4 +- src/MiniExcel.OpenXml/OpenXmlReader.cs | 38 ++++---- .../Picture/OpenXmlPictureImplement.cs | 2 +- .../Styles/Builder/SheetStyleBuildContext.cs | 16 ++-- .../Templates/OpenXmlTemplate.Impl.cs | 28 ++---- .../Templates/OpenXmlTemplate.MergeCells.cs | 4 +- .../Templates/OpenXmlTemplate.cs | 16 ++-- .../Utils/CalcChainHelper.cs | 2 +- .../Utils/XmlReaderHelper.cs | 14 +-- .../Writer/OpenXmlWriter.CopyInsert.cs | 10 +- .../Writer/OpenXmlWriter.DefaultOpenXml.cs | 2 +- src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs | 14 +-- 26 files changed, 151 insertions(+), 181 deletions(-) diff --git a/src/MiniExcel.Core/Helpers/MiniExcelStreamWriter.cs b/src/MiniExcel.Core/Helpers/MiniExcelStreamWriter.cs index 03ce8479..813e47bc 100644 --- a/src/MiniExcel.Core/Helpers/MiniExcelStreamWriter.cs +++ b/src/MiniExcel.Core/Helpers/MiniExcelStreamWriter.cs @@ -12,7 +12,7 @@ public async Task WriteAsync(string content, CancellationToken cancellationToken { if (!string.IsNullOrEmpty(content)) { -#if NET8_0_OR_GREATER +#if NET await _streamWriter.WriteAsync(content.AsMemory(), cancellationToken) #else cancellationToken.ThrowIfCancellationRequested(); @@ -33,7 +33,7 @@ public async Task WriteAndFlushAsync(string content, CancellationToken can public async Task FlushAndGetPositionAsync(CancellationToken cancellationToken = default) { await _streamWriter.FlushAsync( -#if NET8_0_OR_GREATER +#if NET cancellationToken #endif ).ConfigureAwait(false); diff --git a/src/MiniExcel.Core/MiniExcelDataReader.cs b/src/MiniExcel.Core/MiniExcelDataReader.cs index 6f34a85b..18de8a9e 100644 --- a/src/MiniExcel.Core/MiniExcelDataReader.cs +++ b/src/MiniExcel.Core/MiniExcelDataReader.cs @@ -300,7 +300,7 @@ public async Task CloseAsync() } _source?.Dispose(); -#if NETCOREAPP3_0_OR_GREATER +#if NET await _stream!.DisposeAsync().ConfigureAwait(false); #else _stream.Dispose(); diff --git a/src/MiniExcel.Core/Reflection/MiniExcelMapper.cs b/src/MiniExcel.Core/Reflection/MiniExcelMapper.cs index 257509f5..fb82fc7d 100644 --- a/src/MiniExcel.Core/Reflection/MiniExcelMapper.cs +++ b/src/MiniExcel.Core/Reflection/MiniExcelMapper.cs @@ -145,8 +145,8 @@ public static partial class MiniExcelMapper else throw new InvalidCastException($"{vs} cannot be cast to DateTime"); } - -#if NET6_0_OR_GREATER + +#if NET else if (map.ExcludeNullableType == typeof(DateOnly)) { if (itemValue is DateOnly) diff --git a/src/MiniExcel.Csv/CsvReader.cs b/src/MiniExcel.Csv/CsvReader.cs index 0b01092d..f2b648d4 100644 --- a/src/MiniExcel.Csv/CsvReader.cs +++ b/src/MiniExcel.Csv/CsvReader.cs @@ -33,7 +33,7 @@ internal CsvReader(Stream stream, IMiniExcelConfiguration? configuration) var rowIndex = 0; while (await reader.ReadLineAsync( -#if NET7_0_OR_GREATER +#if NET cancellationToken #endif ).ConfigureAwait(false) is { } row) @@ -49,7 +49,7 @@ internal CsvReader(Stream stream, IMiniExcelConfiguration? configuration) while (finalRow.Count(c => c == '"') % 2 != 0) { var nextPart = await reader.ReadLineAsync( -#if NET7_0_OR_GREATER +#if NET cancellationToken #endif ).ConfigureAwait(false); @@ -165,6 +165,6 @@ private string[] Split(string row) public void Dispose() { - ((Stream?)_stream)?.Dispose(); + _stream?.Dispose(); } } diff --git a/src/MiniExcel.Csv/CsvWriter.cs b/src/MiniExcel.Csv/CsvWriter.cs index cc24173e..506f9801 100644 --- a/src/MiniExcel.Csv/CsvWriter.cs +++ b/src/MiniExcel.Csv/CsvWriter.cs @@ -60,31 +60,26 @@ private async Task WriteValuesAsync(StreamWriter writer, object values, str if (mappings is null) { - await _writer.WriteAsync(_configuration.NewLine -#if NET5_0_OR_GREATER - .AsMemory(), cancellationToken -#endif - ).ConfigureAwait(false); - await _writer.FlushAsync( -#if NET8_0_OR_GREATER - cancellationToken +#if NET + await _writer.WriteAsync(_configuration.NewLine.AsMemory(), cancellationToken).ConfigureAwait(false); + await _writer.FlushAsync(cancellationToken).ConfigureAwait(false); +#else + await _writer.WriteAsync(_configuration.NewLine).ConfigureAwait(false); + await _writer.FlushAsync().ConfigureAwait(false); #endif - ).ConfigureAwait(false); + return 0; } if (_printHeader) { - await _writer.WriteAsync(GetHeader(mappings) -#if NET5_0_OR_GREATER - .AsMemory(), cancellationToken -#endif - ).ConfigureAwait(false); - await _writer.WriteAsync(newLine -#if NET5_0_OR_GREATER - .AsMemory(), cancellationToken +#if NET + await _writer.WriteAsync(GetHeader(mappings).AsMemory(), cancellationToken).ConfigureAwait(false); + await _writer.WriteAsync(newLine.AsMemory(), cancellationToken).ConfigureAwait(false); +#else + await _writer.WriteAsync(GetHeader(mappings)).ConfigureAwait(false); + await _writer.WriteAsync(newLine).ConfigureAwait(false); #endif - ).ConfigureAwait(false); } var rowBuilder = new StringBuilder(); @@ -103,17 +98,13 @@ await _writer.WriteAsync(newLine } RemoveTrailingSeparator(rowBuilder); - await _writer.WriteAsync(rowBuilder.ToString() -#if NET5_0_OR_GREATER - .AsMemory(), cancellationToken -#endif - ).ConfigureAwait(false); - await _writer.WriteAsync(newLine -#if NET5_0_OR_GREATER - .AsMemory(), cancellationToken +#if NET + await _writer.WriteAsync(rowBuilder.ToString().AsMemory(), cancellationToken).ConfigureAwait(false); + await _writer.WriteAsync(newLine.AsMemory(), cancellationToken).ConfigureAwait(false); +#else + await _writer.WriteAsync(rowBuilder.ToString()).ConfigureAwait(false); + await _writer.WriteAsync(newLine).ConfigureAwait(false); #endif - ).ConfigureAwait(false); - rowsWritten++; } } @@ -132,17 +123,13 @@ await _writer.WriteAsync(newLine } RemoveTrailingSeparator(rowBuilder); - await _writer.WriteAsync(rowBuilder.ToString() -#if NET5_0_OR_GREATER - .AsMemory(), cancellationToken -#endif - ).ConfigureAwait(false); - await _writer.WriteAsync(newLine -#if NET5_0_OR_GREATER - .AsMemory(), cancellationToken +#if NET + await _writer.WriteAsync(rowBuilder.ToString().AsMemory(), cancellationToken).ConfigureAwait(false); + await _writer.WriteAsync(newLine.AsMemory(), cancellationToken).ConfigureAwait(false); +#else + await _writer.WriteAsync(rowBuilder.ToString()).ConfigureAwait(false); + await _writer.WriteAsync(newLine).ConfigureAwait(false); #endif - ).ConfigureAwait(false); - rowsWritten++; } #endif @@ -152,10 +139,8 @@ await _writer.WriteAsync(newLine finally { #if !SYNC_ONLY - if (asyncWriteAdapter is IAsyncDisposable asyncDisposable) - { - await asyncDisposable.DisposeAsync().ConfigureAwait(false); - } + if (asyncWriteAdapter is not null) + await asyncWriteAdapter.DisposeAsync().ConfigureAwait(false); #endif } } @@ -170,22 +155,19 @@ public async Task SaveAsAsync(IProgress? progress = null, Cancellati if (_value is null) { - await _writer.WriteAsync("" -#if NET5_0_OR_GREATER - .AsMemory(), cancellationToken -#endif - ).ConfigureAwait(false); - await _writer.FlushAsync( -#if NET5_0_OR_GREATER - cancellationToken +#if NET + await _writer.WriteAsync("".AsMemory(), cancellationToken).ConfigureAwait(false); + await _writer.FlushAsync(cancellationToken).ConfigureAwait(false); +#else + await _writer.WriteAsync("").ConfigureAwait(false); + await _writer.FlushAsync().ConfigureAwait(false); #endif - ).ConfigureAwait(false); return []; } var rowsWritten = await WriteValuesAsync(_writer, _value, seperator, newLine, progress, cancellationToken).ConfigureAwait(false); await _writer.FlushAsync( -#if NET5_0_OR_GREATER +#if NET cancellationToken #endif ).ConfigureAwait(false); @@ -200,23 +182,23 @@ public async Task InsertAsync(bool overwriteSheet = false, IProgress? return rowsWritten.FirstOrDefault(); } - public string ToCsvString(object? value, MiniExcelColumnMapping? p) + private string ToCsvString(object? value, MiniExcelColumnMapping? mapping) { if (value is null) return ""; if (value is DateTime dateTime) { - if (p?.ExcelFormat is not null) - return dateTime.ToString(p.ExcelFormat, _configuration.Culture); + if (mapping?.ExcelFormat is not null) + return dateTime.ToString(mapping.ExcelFormat, _configuration.Culture); return _configuration.Culture.Equals(CultureInfo.InvariantCulture) ? dateTime.ToString("yyyy-MM-dd HH:mm:ss", _configuration.Culture) : dateTime.ToString(_configuration.Culture); } - if (p?.ExcelFormat is not null && value is IFormattable formattableValue) - return formattableValue.ToString(p.ExcelFormat, _configuration.Culture); + if (mapping?.ExcelFormat is not null && value is IFormattable formattableValue) + return formattableValue.ToString(mapping.ExcelFormat, _configuration.Culture); return Convert.ToString(value, _configuration.Culture) ?? ""; } diff --git a/src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs b/src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs index b2b11d5b..12d9de9b 100644 --- a/src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs +++ b/src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs @@ -36,7 +36,7 @@ public async Task InsertSheetAsync(string path, object value, string sheetN return rowsWritten.FirstOrDefault(); } -#if NET8_0_OR_GREATER +#if NET var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.SequentialScan); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -130,7 +130,7 @@ public async Task 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 NET8_0_OR_GREATER + #if NET var inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.RandomAccess); await using var disposableInputStream = inputStream.ConfigureAwait(false); @@ -164,7 +164,7 @@ public async Task ExportAsync(string path, object value, bool printHeader if (Path.GetExtension(path).Equals(".xlsm", StringComparison.InvariantCultureIgnoreCase)) throw new NotSupportedException("MiniExcel's Export does not support the .xlsm format"); -#if NET8_0_OR_GREATER +#if NET var stream = overwriteFile ? File.Create(path) : new FileStream(path, FileMode.CreateNew); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -210,7 +210,7 @@ public async Task ExportAsync(Stream stream, object value, bool printHead [CreateSyncVersion] public async Task AlterSheetAsync(string path, string sheetName, string? newSheetName = null, int? newSheetIndex = null, SheetState? newSheetState = null, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); await using var disposableStream = stream.ConfigureAwait(false); #else diff --git a/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs b/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs index 738db2f0..f434f9dd 100644 --- a/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs +++ b/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs @@ -14,7 +14,7 @@ public async IAsyncEnumerable QueryAsync(string path, string? sheetName = string startCell = "A1", bool treatHeaderAsData = false, OpenXmlConfiguration? configuration = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) where T : class, new() { -#if NET8_0_OR_GREATER +#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -41,7 +41,7 @@ public async IAsyncEnumerable QueryAsync(string path, bool useHeaderRow string? sheetName = null, string startCell = "A1", OpenXmlConfiguration? configuration = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -79,7 +79,7 @@ public async IAsyncEnumerable QueryRangeAsync(string path, bool useHead string? sheetName = null, string startCell = "A1", string endCell = "", OpenXmlConfiguration? configuration = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -105,7 +105,7 @@ public async IAsyncEnumerable QueryRangeAsync(string path, bool useHead int? endColumnIndex = null, OpenXmlConfiguration? configuration = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -138,7 +138,7 @@ public async Task QueryAsDataTableAsync(string path, bool useHeaderRo string? sheetName = null, string startCell = "A1", OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -208,7 +208,7 @@ public async Task QueryAsDataTableAsync(Stream stream, bool useHeader [CreateSyncVersion] public async Task> GetSheetNamesAsync(string path, OpenXmlConfiguration? config = null, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -233,7 +233,7 @@ public async Task> GetSheetNamesAsync(Stream stream, OpenXmlConfigu [CreateSyncVersion] public async Task> GetSheetInformationsAsync(string path, OpenXmlConfiguration? config = null, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -258,7 +258,7 @@ public async Task> GetSheetInformationsAsync(Stream stream, Open [CreateSyncVersion] public async Task> GetSheetDimensionsAsync(string path, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -279,7 +279,7 @@ public async Task> GetColumnNamesAsync(string path, bool use string? sheetName = null, string startCell = "A1", OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -305,7 +305,7 @@ public async Task> GetColumnNamesAsync(Stream stream, bool u [CreateSyncVersion] public async Task RetrieveCommentsAsync(string path, string? sheetName, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else diff --git a/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs b/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs index dd6d486f..6386127f 100644 --- a/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs +++ b/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs @@ -12,7 +12,7 @@ internal OpenXmlTemplater() { } [CreateSyncVersion] public async Task AddPictureAsync(string path, CancellationToken cancellationToken = default, params MiniExcelPicture[] images) { -#if NET8_0_OR_GREATER +#if NET var stream = File.Open(path, FileMode.OpenOrCreate); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -31,7 +31,7 @@ public async Task AddPictureAsync(Stream excelStream, CancellationToken cancella public async Task FillTemplateAsync(string path, string templatePath, object value, bool overwriteFile = false, OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = overwriteFile ? File.Create(path) : File.Open(path, FileMode.CreateNew); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -44,7 +44,7 @@ public async Task FillTemplateAsync(string path, string templatePath, object val public async Task FillTemplateAsync(string path, Stream templateStream, object value, bool overwriteFile = false, OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = overwriteFile ? File.Create(path) : File.Open(path, FileMode.CreateNew); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -75,7 +75,7 @@ public async Task FillTemplateAsync(Stream stream, Stream templateStream, object public async Task FillTemplateAsync(string path, byte[] templateBytes, object value, bool overwriteFile = false, OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = overwriteFile ? File.Create(path) : File.Open(path, FileMode.CreateNew); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -98,7 +98,7 @@ public async Task FillTemplateAsync(Stream stream, byte[] templateBytes, object public async Task MergeSameCellsAsync(string mergedFilePath, string path, OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = File.Create(mergedFilePath); await using var disposableStream = stream.ConfigureAwait(false); #else diff --git a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingExporter.cs b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingExporter.cs index 5cfed4c6..39f9ae95 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingExporter.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingExporter.cs @@ -19,7 +19,7 @@ public async Task ExportAsync(string path, IEnumerable? values, bool overw { var filePath = path.EndsWith(".xlsx", StringComparison.InvariantCultureIgnoreCase) ? path : $"{path}.xlsx" ; -#if NET8_0_OR_GREATER +#if NET var stream = overwriteFile ? File.Create(filePath) : new FileStream(filePath, FileMode.CreateNew); await using var disposableStream = stream.ConfigureAwait(false); #else diff --git a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingImporter.cs b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingImporter.cs index d6427048..9aa8d960 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingImporter.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingImporter.cs @@ -12,7 +12,7 @@ public MappingImporter(MappingRegistry registry) : this() [CreateSyncVersion] public async IAsyncEnumerable QueryAsync(string path, [EnumeratorCancellation] CancellationToken cancellationToken = default) where T : class, new() { - #if NET8_0_OR_GREATER + #if NET var stream = File.OpenRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -39,7 +39,7 @@ public MappingImporter(MappingRegistry registry) : this() [CreateSyncVersion] public async Task QuerySingleAsync(string path, CancellationToken cancellationToken = default) where T : class, new() { -#if NET8_0_OR_GREATER +#if NET var stream = File.OpenRead(path); await using var disposableStream = stream.ConfigureAwait(false); #else diff --git a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingTemplater.cs b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingTemplater.cs index 248f9702..0df0e110 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingTemplater.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingTemplater.cs @@ -23,7 +23,7 @@ public async Task FillTemplateAsync( if (values is null) throw new ArgumentNullException(nameof(values)); -#if NET8_0_OR_GREATER +#if NET var outputStream = File.Create(outputPath); await using var disposableOutputStream = outputStream.ConfigureAwait(false); @@ -73,7 +73,7 @@ public async Task FillTemplateAsync( if (values is null) throw new ArgumentNullException(nameof(values)); -#if NET8_0_OR_GREATER +#if NET var templateStream = new MemoryStream(templateBytes); await using var disposableTemplateStream = templateStream.ConfigureAwait(false); #else diff --git a/src/MiniExcel.OpenXml/FluentMapping/Configuration/CollectionMappingBuilder.cs b/src/MiniExcel.OpenXml/FluentMapping/Configuration/CollectionMappingBuilder.cs index 9cae1c35..5bf8ca6a 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Configuration/CollectionMappingBuilder.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Configuration/CollectionMappingBuilder.cs @@ -5,7 +5,7 @@ namespace MiniExcelLib.OpenXml.FluentMapping.Configuration; internal partial class CollectionMappingBuilder : ICollectionMappingBuilder where TCollection : IEnumerable { -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex("^[A-Z]+[0-9]+$")] private static partial Regex CellAddressRegexImpl(); private static readonly Regex CellAddressRegex = CellAddressRegexImpl(); #else @@ -56,4 +56,4 @@ public ICollectionMappingBuilder WithItemMapping(Action : IPropertyMappingBuilder { -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex("^[A-Z]+[0-9]+$")] private static partial Regex CellAddressRegexImpl(); private static readonly Regex CellAddressRegex = CellAddressRegexImpl(); #else @@ -42,4 +42,4 @@ public IPropertyMappingBuilder WithFormula(string formula) _mapping.Formula = formula; return this; } -} \ No newline at end of file +} diff --git a/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs b/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs index 1d9bcdd6..77c1851a 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs @@ -24,11 +24,11 @@ public static async Task ApplyTemplateAsync( { // Copy to memory stream if not seekable var memStream = new MemoryStream(); -#if NETCOREAPP2_1_OR_GREATER - await templateStream.CopyToAsync(memStream, cancellationToken).ConfigureAwait(false); -#else - await templateStream.CopyToAsync(memStream).ConfigureAwait(false); + await templateStream.CopyToAsync(memStream +#if NET + , cancellationToken #endif + ).ConfigureAwait(false); memStream.Position = 0; templateStream = memStream; } @@ -111,7 +111,7 @@ private static async Task CopyEntryAsync( targetEntry.LastWriteTime = sourceEntry.LastWriteTime; // Copy content -#if NET8_0_OR_GREATER +#if NET var sourceStream = await sourceEntry.OpenAsync(cancellationToken).ConfigureAwait(false); var targetStream = await targetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); @@ -141,7 +141,7 @@ private static async Task ProcessWorksheetAsync( targetEntry.LastWriteTime = sourceEntry.LastWriteTime; // Open streams -#if NET8_0_OR_GREATER +#if NET var sourceStream = await sourceEntry.OpenAsync(cancellationToken).ConfigureAwait(false); var targetStream = await targetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); @@ -165,4 +165,4 @@ await processor.ProcessSheetAsync( enumerator, cancellationToken).ConfigureAwait(false); } -} \ No newline at end of file +} diff --git a/src/MiniExcel.OpenXml/Helpers/XmlHelper.cs b/src/MiniExcel.OpenXml/Helpers/XmlHelper.cs index 04a3a4ef..48baaadc 100644 --- a/src/MiniExcel.OpenXml/Helpers/XmlHelper.cs +++ b/src/MiniExcel.OpenXml/Helpers/XmlHelper.cs @@ -3,7 +3,7 @@ /// XmlEncoder MIT Copyright ©2021 from https://github.com/ClosedXML internal static partial class XmlHelper { -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex("_(x[\\dA-Fa-f]{4})_", RegexOptions.Compiled)] private static partial Regex X4LRegexImpl(); private static readonly Regex X4LRegex = X4LRegexImpl(); @@ -59,4 +59,4 @@ public static string EncodeXml(string? value) => value is null ? "" .Replace("\"", """) .Replace("'", "'") .ToString() ?? ""; -} \ No newline at end of file +} diff --git a/src/MiniExcel.OpenXml/OpenXmlReader.cs b/src/MiniExcel.OpenXml/OpenXmlReader.cs index 0606099d..e2655405 100644 --- a/src/MiniExcel.OpenXml/OpenXmlReader.cs +++ b/src/MiniExcel.OpenXml/OpenXmlReader.cs @@ -178,7 +178,7 @@ internal static async Task CreateAsync(Stream stream, IMiniExcelC maxColumnIndex = endColumnIndex.Value; } -#if NET8_0_OR_GREATER +#if NET var sheetStream = await sheetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); #else @@ -418,7 +418,7 @@ private async Task SetSharedStringsAsync(CancellationToken cancellationToken = d return; var idx = 0; -#if NET8_0_OR_GREATER +#if NET var stream = await sharedStringsEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -459,7 +459,7 @@ private static async IAsyncEnumerable ReadWorkbookAsync(ReadOnlyCol ); var entry = entries.Single(w => w.FullName == ExcelFileNames.Workbook); -#if NET8_0_OR_GREATER +#if NET var stream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -491,7 +491,7 @@ private static async IAsyncEnumerable ReadWorkbookAsync(ReadOnlyCol } await reader.SkipAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false); @@ -521,7 +521,7 @@ await reader.SkipAsync() ); sheetCount++; await reader.SkipAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false); @@ -556,7 +556,7 @@ await reader.SkipAsync() var entry = entries.Single(w => w.FullName == ExcelFileNames.WorkbookRels); -#if NET8_0_OR_GREATER +#if NET var stream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -581,7 +581,7 @@ await reader.SkipAsync() } await reader.SkipAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false); @@ -648,7 +648,7 @@ private async Task ReadCellAndSetColumnIndexAsync(XmlReader reade if (reader.IsStartElement("v", Ns)) { var rawValue = await reader.ReadElementContentAsStringAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false); @@ -759,7 +759,7 @@ internal async Task> GetDimensionsAsync(CancellationToken canc var withoutCr = false; -#if NET8_0_OR_GREATER +#if NET var crSheetStream = await sheet.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableCrSheetStream = crSheetStream.ConfigureAwait(false); #else @@ -812,7 +812,7 @@ internal async Task> GetDimensionsAsync(CancellationToken canc if (withoutCr) { -#if NET8_0_OR_GREATER +#if NET var sheetStream = await sheet.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); #else @@ -912,7 +912,7 @@ internal static async Task TryGetMaxRowColumnIndexAs int maxRowIndex = -1; int maxColumnIndex = -1; -#if NET8_0_OR_GREATER +#if NET var crSheetStream = await sheetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableCrSheetStream = crSheetStream.ConfigureAwait(false); #else @@ -921,7 +921,7 @@ internal static async Task TryGetMaxRowColumnIndexAs using (var reader = XmlReader.Create(crSheetStream, xmlSettings)) { while (await reader.ReadAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false)) @@ -967,7 +967,7 @@ internal static async Task TryGetMaxRowColumnIndexAs if (withoutCr) { -#if NET8_0_OR_GREATER +#if NET var sheetStream = await sheetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); #else @@ -1047,7 +1047,7 @@ internal static async Task TryGetMergeCellsAsync(ZipArchiveEntry sheetEntr ); var mergeCells = new MergeCells(); -#if NET8_0_OR_GREATER +#if NET var sheetStream = await sheetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); #else @@ -1124,7 +1124,7 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance List people = []; if (Archive.GetEntry(ExcelFileNames.Person) is { } persons) { -#if NET8_0_OR_GREATER +#if NET var personStream = await persons.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposablePersonStream = personStream.ConfigureAwait(false); #else @@ -1150,7 +1150,7 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance if (Archive.GetEntry($"xl/worksheets/_rels/{sheetFile}.rels") is not { } rel) return new CommentResultSet(sheetName, [], []); -#if NET8_0_OR_GREATER +#if NET var stream = await rel.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -1178,7 +1178,7 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance HashSet refCells = []; if (Archive.GetEntry($"xl/{threadedCommentsPath}") is { } threadEntry) { -#if NET8_0_OR_GREATER +#if NET var threadEntryStream = await threadEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableThreadEntryStream = threadEntryStream.ConfigureAwait(false); #else @@ -1231,7 +1231,7 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance if (Archive.GetEntry($"xl/{notesPath}") is { } noteEntry) { -#if NET8_0_OR_GREATER +#if NET var noteEntryStream = await noteEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableNoteEntryStream = noteEntryStream.ConfigureAwait(false); #else @@ -1303,7 +1303,7 @@ internal async IAsyncEnumerable QueryMappedAsync( Async = true }; -#if NET8_0_OR_GREATER +#if NET var sheetStream = await sheetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); #else diff --git a/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs b/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs index ab47642f..4bfc3fdb 100644 --- a/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs +++ b/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs @@ -136,7 +136,7 @@ public static async Task AddPictureAsync(Stream excelStream, CancellationToken c var imagePath = $"xl/media/{imageName}"; var imageEntry = archive.CreateEntry(imagePath); -#if NET8_0_OR_GREATER +#if NET var entryStream = await imageEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = entryStream.ConfigureAwait(false); await entryStream.WriteAsync(imageBytes.AsMemory(), cancellationToken).ConfigureAwait(false); diff --git a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs index 06a155d4..66304762 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs @@ -49,7 +49,7 @@ public async Task CreateAsync(SheetStyleElementInfos generatedElementInfos, Canc if (styleEntry is not null) { -#if NET8_0_OR_GREATER +#if NET var oldStyleXmlStream = await styleEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = oldStyleXmlStream.ConfigureAwait(false); #else @@ -88,7 +88,7 @@ public async Task InitializeAsync(SheetStyleElementInfos generatedElementInfos, var xmlReaderSettings = XmlReaderHelper.GetXmlReaderSettings(isAsync); if (_oldStyleXmlZipEntry is not null) { -#if NET8_0_OR_GREATER +#if NET var oldStyleXmlStream = await _oldStyleXmlZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using (_ = oldStyleXmlStream.ConfigureAwait(false)) #else @@ -99,7 +99,7 @@ public async Task InitializeAsync(SheetStyleElementInfos generatedElementInfos, OldElementInfos = await ReadSheetStyleElementInfosAsync(reader, cancellationToken).ConfigureAwait(false); } -#if NET8_0_OR_GREATER +#if NET _oldXmlReaderStream = await _oldStyleXmlZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); #else _oldXmlReaderStream = _oldStyleXmlZipEntry.Open(); @@ -116,7 +116,7 @@ public async Task InitializeAsync(SheetStyleElementInfos generatedElementInfos, _newStyleXmlZipEntry = _archive.CreateEntry(ExcelFileNames.Styles, CompressionLevel.Fastest); } -#if NET8_0_OR_GREATER +#if NET _newXmlWriterStream = await _newStyleXmlZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); #else _newXmlWriterStream = _newStyleXmlZipEntry.Open(); @@ -145,7 +145,7 @@ public async Task FinalizeAndUpdateZipDictionaryAsync(CancellationToken cancella { OldXmlReader?.Dispose(); OldXmlReader = null; -#if NET8_0_OR_GREATER +#if NET if (_oldXmlReaderStream is not null) { await _oldXmlReaderStream.DisposeAsync().ConfigureAwait(false); @@ -159,7 +159,7 @@ public async Task FinalizeAndUpdateZipDictionaryAsync(CancellationToken cancella _emptyStylesXmlStringReader = null; await NewXmlWriter!.FlushAsync().ConfigureAwait(false); -#if NET8_0_OR_GREATER +#if NET await NewXmlWriter.DisposeAsync().ConfigureAwait(false); #else NewXmlWriter.Dispose(); @@ -167,7 +167,7 @@ public async Task FinalizeAndUpdateZipDictionaryAsync(CancellationToken cancella NewXmlWriter = null; -#if NET8_0_OR_GREATER +#if NET await _newXmlWriterStream!.DisposeAsync().ConfigureAwait(false); #else _newXmlWriterStream?.Dispose(); @@ -184,7 +184,7 @@ public async Task FinalizeAndUpdateZipDictionaryAsync(CancellationToken cancella _oldStyleXmlZipEntry = null; var finalStyleXmlZipEntry = _archive.CreateEntry(ExcelFileNames.Styles, CompressionLevel.Fastest); -#if NET8_0_OR_GREATER +#if NET var tempStream = await _newStyleXmlZipEntry!.OpenAsync(cancellationToken).ConfigureAwait(false); var newStream = await finalStyleXmlZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using (_ = tempStream.ConfigureAwait(false)) diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs index 859654d0..d972620f 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs @@ -15,17 +15,8 @@ internal partial class OpenXmlTemplate Async = true #endif }; - - private static readonly XmlWriterSettings FragXmlWriterSettings = new() - { - OmitXmlDeclaration = true, - ConformanceLevel = ConformanceLevel.Fragment, -#if !SYNC_ONLY - Async = true -#endif - }; -#if NET8_0_OR_GREATER +#if NET [GeneratedRegex("(?<={{).*?(?=}})")] private static partial Regex ExpressionRegex(); private static readonly Regex IsExpressionRegex = ExpressionRegex(); [GeneratedRegex("([A-Z]+)([0-9]+)")] private static partial Regex CellRegexImpl(); @@ -53,7 +44,7 @@ internal partial class OpenXmlTemplate [CreateSyncVersion] private async Task GenerateSheetByUpdateModeAsync(ZipArchiveEntry sheetZipEntry, Stream stream, Stream sheetStream, IDictionary inputMaps, IDictionary sharedStrings, bool mergeCells = false, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var doc = await XDocument.LoadAsync(sheetStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); await sheetStream.DisposeAsync().ConfigureAwait(false); #else @@ -73,7 +64,7 @@ private async Task GenerateSheetByUpdateModeAsync(ZipArchiveEntry sheetZipEntry, GetMergeCells(worksheet); UpdateDimensionAndGetRowsInfo(inputMaps, worksheet, rows, !mergeCells); -#if NET8_0_OR_GREATER +#if NET var writer = XmlWriter.Create(stream, DocXmlWriterSettings); await using var disposableWriter = writer.ConfigureAwait(false); #else @@ -86,7 +77,7 @@ private async Task GenerateSheetByUpdateModeAsync(ZipArchiveEntry sheetZipEntry, [CreateSyncVersion] private async Task GenerateSheetByCreateModeAsync(ZipArchiveEntry templateSheetZipEntry, Stream outputZipSheetEntryStream, IDictionary inputMaps, IDictionary sharedStrings, bool mergeCells = false, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var newTemplateStream = await templateSheetZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableNewTemplateStream = newTemplateStream.ConfigureAwait(false); var doc = await XDocument.LoadAsync(newTemplateStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); @@ -111,7 +102,7 @@ private async Task GenerateSheetByCreateModeAsync(ZipArchiveEntry templateSheetZ GetMergeCells(worksheet); UpdateDimensionAndGetRowsInfo(inputMaps, worksheet, rows, !mergeCells); -#if NET8_0_OR_GREATER +#if NET var writer = XmlWriter.Create(outputZipSheetEntryStream, DocXmlWriterSettings); await using var disposableWriter = writer.ConfigureAwait(false); #else @@ -236,7 +227,7 @@ private async Task WriteSheetXmlAsync(XmlWriter writer, XElement worksheet, XEle foreach (var beforeElement in beforeSheetData) { -#if NET8_0_OR_GREATER +#if NET await beforeElement.WriteToAsync(writer, cancellationToken).ConfigureAwait(false); #else beforeElement.WriteTo(writer); @@ -493,7 +484,7 @@ var s when s.StartsWith("@header") => SpecialCellType.Header, foreach (var afterElement in afterSheetData) { -#if NET8_0_OR_GREATER +#if NET await afterElement.WriteToAsync(writer, cancellationToken).ConfigureAwait(false); #else afterElement.WriteTo(writer); @@ -633,11 +624,8 @@ private async Task GenerateCellValuesAsync( else { var replacements = new Dictionary(); -#if NET8_0_OR_GREATER string MatchDelegate(Match x) => replacements.GetValueOrDefault(x.Groups[1].Value, ""); -#else - string MatchDelegate(Match x) => replacements.TryGetValue(x.Groups[1].Value, out var repl) ? repl : ""; -#endif + foreach (var prop in rowInfo.PropsMap) { var propInfo = prop.Value.PropertyInfo; diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs index 5d84f3b4..4c376a34 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs @@ -30,7 +30,7 @@ public async Task MergeSameCellsAsync(byte[] fileInBytes, CancellationToken canc private async Task MergeSameCellsImplAsync(Stream stream, CancellationToken cancellationToken = default) { await stream.CopyToAsync(_outputFileStream -#if NET8_0_OR_GREATER +#if NET , cancellationToken #endif ).ConfigureAwait(false); @@ -58,7 +58,7 @@ await stream.CopyToAsync(_outputFileStream var entry = archive.ZipFile.CreateEntry(sheet.FullName); -#if NET8_0_OR_GREATER +#if NET var sheetStream = await sheet.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs index eb52eaa3..65237a9d 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs @@ -20,7 +20,7 @@ internal OpenXmlTemplate(Stream stream, IMiniExcelConfiguration? configuration, [CreateSyncVersion] public async Task SaveAsByTemplateAsync(string templatePath, object value, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = File.Open(templatePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -32,7 +32,7 @@ public async Task SaveAsByTemplateAsync(string templatePath, object value, Cance [CreateSyncVersion] public async Task SaveAsByTemplateAsync(byte[] templateBytes, object value, CancellationToken cancellationToken = default) { -#if NET8_0_OR_GREATER +#if NET var stream = new MemoryStream(templateBytes); await using var disposableStream = stream.ConfigureAwait(false); #else @@ -87,7 +87,7 @@ public async Task SaveAsByTemplateAsync(Stream templateStream, object value, Can var newEntry = outputFileArchive.ZipFile.CreateEntry(entry.FullName); // Copy the content of the original entry to the new entry -#if NET8_0_OR_GREATER +#if NET var originalEntryStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableEntryStream = originalEntryStream.ConfigureAwait(false); @@ -99,7 +99,7 @@ public async Task SaveAsByTemplateAsync(Stream templateStream, object value, Can #endif await originalEntryStream.CopyToAsync(newEntryStream -#if NET8_0_OR_GREATER +#if NET , cancellationToken #endif ).ConfigureAwait(false); @@ -128,7 +128,7 @@ await originalEntryStream.CopyToAsync(newEntryStream var inputValues = _inputValueExtractor.ToValueDictionary(value); var outputZipEntry = outputFileArchive.ZipFile.CreateEntry(templateFullName); -#if NET8_0_OR_GREATER +#if NET var outputZipSheetEntryStream = await outputZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetEntryStream = outputZipSheetEntryStream.ConfigureAwait(false); #else @@ -151,7 +151,7 @@ await originalEntryStream.CopyToAsync(newEntryStream //calcChain.Delete(); var calcChainEntry = outputFileArchive.ZipFile.CreateEntry(calcChainPathName); -#if NET8_0_OR_GREATER +#if NET var calcChainStream = await calcChainEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableChainEntryStream = calcChainStream.ConfigureAwait(false); #else @@ -168,7 +168,7 @@ await originalEntryStream.CopyToAsync(newEntryStream var newEntry = outputFileArchive.ZipFile.CreateEntry(entry.FullName); // Copy the content of the original entry to the new entry -#if NET8_0_OR_GREATER +#if NET var originalEntryStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableEntryStream = originalEntryStream.ConfigureAwait(false); @@ -180,7 +180,7 @@ await originalEntryStream.CopyToAsync(newEntryStream #endif await originalEntryStream.CopyToAsync(newEntryStream -#if NET8_0_OR_GREATER +#if NET , cancellationToken #endif ).ConfigureAwait(false); diff --git a/src/MiniExcel.OpenXml/Utils/CalcChainHelper.cs b/src/MiniExcel.OpenXml/Utils/CalcChainHelper.cs index f58fadfc..130d2aa9 100644 --- a/src/MiniExcel.OpenXml/Utils/CalcChainHelper.cs +++ b/src/MiniExcel.OpenXml/Utils/CalcChainHelper.cs @@ -24,7 +24,7 @@ public static async Task GenerateCalcChainSheetAsync(Stream calcChainStream, str { var content = $"{calcChainContent}"; -#if NET8_0_OR_GREATER +#if NET var writer = new StreamWriter(calcChainStream, Encoding.UTF8); await using var disposableWriter = writer.ConfigureAwait(false); await writer.WriteAsync(content.AsMemory(), cancellationToken).ConfigureAwait(false); diff --git a/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs b/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs index 0373d302..12cfead1 100644 --- a/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs +++ b/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs @@ -13,7 +13,7 @@ public static async Task ReadFirstContentAsync(this XmlReader reader, Canc if (reader.IsEmptyElement) { await reader.ReadAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false); @@ -21,13 +21,13 @@ await reader.ReadAsync() } await reader.MoveToContentAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false); await reader.ReadAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false); @@ -41,7 +41,7 @@ public static async Task SkipContentAsync(this XmlReader reader, Cancellat if (reader.NodeType == XmlNodeType.EndElement) { await reader.ReadAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false); @@ -49,7 +49,7 @@ await reader.ReadAsync() } await reader.SkipAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false); @@ -95,7 +95,7 @@ public static async Task ReadStringItemAsync(this XmlReader reader, Canc { // There are multiple in a . Concatenate within an . result.Append(await reader.ReadElementContentAsStringAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false)); @@ -126,7 +126,7 @@ private static async Task ReadRichTextRunAsync(this XmlReader reader, Ca if (reader.IsStartElement("t", Ns)) { result.Append(await reader.ReadElementContentAsStringAsync() -#if NET6_0_OR_GREATER +#if NET .WaitAsync(cancellationToken) #endif .ConfigureAwait(false)); diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs index 164018a8..abfe993d 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs @@ -118,7 +118,7 @@ public async Task CopyAndInsertAsync(bool overwriteSheet = false, IProgress var newStylesEntryStream = await newStylesEntry.OpenAsync(cancellationToken).ConfigureAwait(false); var tempStylesEntryStream = await tempStylesEntry.OpenAsync(cancellationToken).ConfigureAwait(false); -#if NET8_0_OR_GREATER +#if NET await using var disposableNewStylesEntryStream = newStylesEntryStream.ConfigureAwait(false); await using var disposableTempStylesEntryStream = tempStylesEntryStream.ConfigureAwait(false); #else @@ -218,7 +218,7 @@ private async Task CopyEntryAsync(ZipArchiveEntry entry, CancellationToken cance { var newEntry = _archive.CreateEntry(entry.FullName, CompressionLevel.Fastest); -#if NET8_0_OR_GREATER +#if NET var oldEntryStream = await _oldArchive!.GetEntry(entry.FullName)!.OpenAsync(cancellationToken).ConfigureAwait(false); await using var oldDisposableSheetStream = oldEntryStream.ConfigureAwait(false); @@ -243,7 +243,7 @@ private async Task CopyAndUpdateContentTypesAsync(CancellationToken cancellation return; } -#if NET8_0_OR_GREATER +#if NET var stream = await contentTypesZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); var doc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); @@ -276,7 +276,7 @@ private async Task CopyAndUpdateContentTypesAsync(CancellationToken cancellation var contentTypesEntry = _archive.CreateEntry(ExcelFileNames.ContentTypes, CompressionLevel.Fastest); var contentTypesEntryStream = await contentTypesEntry.OpenAsync(cancellationToken).ConfigureAwait(false); -#if NET8_0_OR_GREATER +#if NET await using var disposableContetTypesEntryStream = contentTypesEntryStream.ConfigureAwait(false); await doc.SaveAsync(contentTypesEntryStream, SaveOptions.None, cancellationToken).ConfigureAwait(false); #else @@ -308,7 +308,7 @@ public async ValueTask DisposeAsync() #else Archive.Dispose(); #endif -#if NET8_0_OR_GREATER +#if NET await _backingStream.DisposeAsync().ConfigureAwait(false); #else _backingStream.Dispose(); diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs index 9f1a9512..56c01a0f 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs @@ -188,7 +188,7 @@ private string GetPanes() if (type == typeof(TimeSpan)) return GetTimeSpanValue((TimeSpan)value, columnMapping); -#if NET8_0_OR_GREATER +#if NET if (type == typeof(DateOnly)) return GetDateTimeValue(((DateOnly)value).ToDateTime(default), columnMapping); diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs index 7d50c111..93641276 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs @@ -176,7 +176,7 @@ private async Task CreateSheetXmlAsync(object? values, string sheetPath, IP var entry = _archive.CreateEntry(sheetPath, CompressionLevel.Fastest); var rowsWritten = 0; -#if NET8_0_OR_GREATER +#if NET var zipStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableZipStream = zipStream.ConfigureAwait(false); #else @@ -500,7 +500,7 @@ private async Task AddFilesToZipAsync(CancellationToken cancellationToken) var entry = _archive.CreateEntry(item.Path, CompressionLevel.Fastest); -#if NET8_0_OR_GREATER +#if NET var zipStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableZipStream = zipStream.ConfigureAwait(false); await zipStream.WriteAsync(item.Contents, cancellationToken).ConfigureAwait(false); @@ -632,7 +632,7 @@ private async Task InsertContentTypesXmlAsync(CancellationToken cancellationToke return; } -#if NET8_0_OR_GREATER +#if NET var stream = await contentTypesZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); var doc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); @@ -664,7 +664,7 @@ private async Task InsertContentTypesXmlAsync(CancellationToken cancellationToke } stream.Position = 0; -#if NET8_0_OR_GREATER +#if NET await doc.SaveAsync(stream, SaveOptions.None, cancellationToken).ConfigureAwait(false); #else doc.Save(stream); @@ -678,7 +678,7 @@ private async Task CreateZipEntryAsync(string path, string? contentType, string var entry = _archive.CreateEntry(path, CompressionLevel.Fastest); -#if NET8_0_OR_GREATER +#if NET var zipStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableZipStream = zipStream.ConfigureAwait(false); #else @@ -709,7 +709,7 @@ internal async Task AlterWorksheetAsync(string sheetName, string? newSheetName, oldWorkbookEntry.Delete(); var newWorkbookEntry = _archive.CreateEntry("xl/workbook.xml", CompressionLevel.Fastest); -#if NET8_0_OR_GREATER +#if NET var newZipStream = await newWorkbookEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var newDisposableZipStream = newZipStream.ConfigureAwait(false); var writer = XmlWriter.Create(newZipStream, new XmlWriterSettings @@ -738,7 +738,7 @@ internal async Task AlterWorksheetAsync(string sheetName, string? newSheetName, async Task LoadWorkbook() { -#if NET8_0_OR_GREATER +#if NET var zipStream = await oldWorkbookEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableZipStream = zipStream.ConfigureAwait(false); var workbookDoc = await XDocument.LoadAsync(zipStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); From 7a609fd79cabf5d08b1f7c7148d56116f46fd96f Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Sat, 23 May 2026 17:34:39 +0200 Subject: [PATCH 05/12] Changed some access modifiers in sheet style builders Context, OldXmlReader and NewXmlWriter are now protected instead of private, so that they need to be assigned only in the `SheetStyleBuilderBase` class. --- .../Builder/DefaultSheetStyleBuilder.cs | 66 ++++++++--------- .../Builder/MinimalSheetStyleBuilder.cs | 11 +-- .../Styles/Builder/SheetStyleBuildContext.cs | 13 +--- .../Styles/Builder/SheetStyleBuilderBase.cs | 70 +++++++++---------- 4 files changed, 71 insertions(+), 89 deletions(-) diff --git a/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs b/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs index b6ac86ab..e08a308b 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs @@ -19,12 +19,8 @@ internal partial class DefaultSheetStyleBuilder(SheetStyleBuilderContext context CellXfCount = 6 }; - private readonly SheetStyleBuilderContext _context = context; private readonly OpenXmlStyleOptions _styleOptions = styleOptions; - private XmlReader OldReader => _context.OldXmlReader!; - private XmlWriter NewWriter => _context.NewXmlWriter!; - protected internal override SheetStyleElementInfos GetGeneratedElementInfos() { return GeneratedElementInfos; @@ -35,7 +31,7 @@ protected override async Task GenerateNumFmtAsync() { const int numFmtIndex = 166; var index = 0; - foreach (var map in _context.SheetStyleFormatsCache.FormatMappings) + foreach (var map in Context.SheetStyleFormatsCache.FormatMappings) { index++; @@ -43,7 +39,7 @@ protected override async Task GenerateNumFmtAsync() * @@ -544,10 +540,10 @@ protected override async Task GenerateCellXfAsync() * */ await NewWriter.WriteStartElementAsync(OldReader.Prefix, "xf", OldReader.NamespaceURI).ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "numFmtId", null, (numFmtIndex + i + _context.OldElementInfos.NumFmtCount).ToString()).ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "fontId", null, $"{_context.OldElementInfos.FontCount}").ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "fillId", null, $"{_context.OldElementInfos.FillCount}").ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "borderId", null, $"{_context.OldElementInfos.BorderCount + 1}").ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "numFmtId", null, (numFmtIndex + i + Context.OldElementInfos.NumFmtCount).ToString()).ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "fontId", null, $"{Context.OldElementInfos.FontCount}").ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "fillId", null, $"{Context.OldElementInfos.FillCount}").ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "borderId", null, $"{Context.OldElementInfos.BorderCount + 1}").ConfigureAwait(false); await NewWriter.WriteAttributeStringAsync(null, "xfId", null, "0").ConfigureAwait(false); await NewWriter.WriteAttributeStringAsync(null, "applyNumberFormat", null, "1").ConfigureAwait(false); await NewWriter.WriteAttributeStringAsync(null, "applyFill", null, "1").ConfigureAwait(false); diff --git a/src/MiniExcel.OpenXml/Styles/Builder/MinimalSheetStyleBuilder.cs b/src/MiniExcel.OpenXml/Styles/Builder/MinimalSheetStyleBuilder.cs index 4da5e49b..7afce315 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/MinimalSheetStyleBuilder.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/MinimalSheetStyleBuilder.cs @@ -11,11 +11,6 @@ internal partial class MinimalSheetStyleBuilder(SheetStyleBuilderContext context CellStyleXfCount = 1, CellXfCount = 6 }; - - private readonly SheetStyleBuilderContext _context = context; - - private XmlReader OldReader => _context.OldXmlReader!; - private XmlWriter NewWriter => _context.NewXmlWriter!; protected internal override SheetStyleElementInfos GetGeneratedElementInfos() { @@ -27,7 +22,7 @@ protected override async Task GenerateNumFmtAsync() { const int numFmtIndex = 166; var index = 0; - foreach (var map in _context.SheetStyleFormatsCache.FormatMappings) + foreach (var map in Context.SheetStyleFormatsCache.FormatMappings) { index++; @@ -35,7 +30,7 @@ protected override async Task GenerateNumFmtAsync() * */ await NewWriter.WriteStartElementAsync(OldReader.Prefix, "numFmt", OldReader.NamespaceURI).ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "numFmtId", null, (numFmtIndex + index + _context.OldElementInfos.NumFmtCount).ToString()).ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "numFmtId", null, (numFmtIndex + index + Context.OldElementInfos.NumFmtCount).ToString()).ConfigureAwait(false); await NewWriter.WriteAttributeStringAsync(null, "formatCode", null, map.Format).ConfigureAwait(false); await NewWriter.WriteEndElementAsync().ConfigureAwait(false); } @@ -125,7 +120,7 @@ protected override async Task GenerateCellXfAsync() await NewWriter.WriteEndElementAsync().ConfigureAwait(false); const int numFmtIndex = 166; - for (var i = 1; i <= _context.CustomFormatCount; i++) + for (var i = 1; i <= Context.CustomFormatCount; i++) { /* * _context.OldXmlReader!; - private XmlWriter NewWriter => _context.NewXmlWriter!; + protected XmlReader OldReader => Context.OldXmlReader!; + protected XmlWriter NewWriter => Context.NewXmlWriter!; private static readonly Dictionary AllElements = new() { @@ -26,7 +26,7 @@ internal abstract partial class SheetStyleBuilderBase(SheetStyleBuilderContext c [CreateSyncVersion] public virtual async Task BuildAsync(CancellationToken cancellationToken = default) { - await _context.InitializeAsync(GetGeneratedElementInfos(), cancellationToken).ConfigureAwait(false); + await Context.InitializeAsync(GetGeneratedElementInfos(), cancellationToken).ConfigureAwait(false); while (await OldReader.ReadAsync().ConfigureAwait(false)) { cancellationToken.ThrowIfCancellationRequested(); @@ -72,7 +72,7 @@ public virtual async Task BuildAsync(CancellationToken cancellationToken = defau } } - await _context.FinalizeAndUpdateZipDictionaryAsync(cancellationToken).ConfigureAwait(false); + await Context.FinalizeAndUpdateZipDictionaryAsync(cancellationToken).ConfigureAwait(false); } protected internal abstract SheetStyleElementInfos GetGeneratedElementInfos(); @@ -106,12 +106,12 @@ protected virtual async Task WriteAttributesAsync(string element, CancellationTo { var value = element switch { - "numFmts" => (_context.OldElementInfos.NumFmtCount + _context.GeneratedElementInfos.NumFmtCount + _context.CustomFormatCount).ToString(), - "fonts" => (_context.OldElementInfos.FontCount + _context.GeneratedElementInfos.FontCount).ToString(), - "fills" => (_context.OldElementInfos.FillCount + _context.GeneratedElementInfos.FillCount).ToString(), - "borders" => (_context.OldElementInfos.BorderCount + _context.GeneratedElementInfos.BorderCount).ToString(), - "cellStyleXfs" => (_context.OldElementInfos.CellStyleXfCount + _context.GeneratedElementInfos.CellStyleXfCount).ToString(), - "cellXfs" => (_context.OldElementInfos.CellXfCount + _context.GeneratedElementInfos.CellXfCount + _context.CustomFormatCount).ToString(), + "numFmts" => (Context.OldElementInfos.NumFmtCount + Context.GeneratedElementInfos.NumFmtCount + Context.CustomFormatCount).ToString(), + "fonts" => (Context.OldElementInfos.FontCount + Context.GeneratedElementInfos.FontCount).ToString(), + "fills" => (Context.OldElementInfos.FillCount + Context.GeneratedElementInfos.FillCount).ToString(), + "borders" => (Context.OldElementInfos.BorderCount + Context.GeneratedElementInfos.BorderCount).ToString(), + "cellStyleXfs" => (Context.OldElementInfos.CellStyleXfCount + Context.GeneratedElementInfos.CellStyleXfCount).ToString(), + "cellXfs" => (Context.OldElementInfos.CellXfCount + Context.GeneratedElementInfos.CellXfCount + Context.CustomFormatCount).ToString(), _ => OldReader.Value }; await NewWriter.WriteStringAsync(value).ConfigureAwait(false); @@ -133,35 +133,35 @@ protected virtual async Task GenerateElementBeforStartElementAsync() if (!AllElements.TryGetValue(OldReader.LocalName, out var elementIndex)) return; - if (!_context.OldElementInfos.ExistsNumFmts && !_context.GeneratedElementInfos.ExistsNumFmts && AllElements["numFmts"] < elementIndex) + if (!Context.OldElementInfos.ExistsNumFmts && !Context.GeneratedElementInfos.ExistsNumFmts && AllElements["numFmts"] < elementIndex) { await GenerateNumFmtsAsync().ConfigureAwait(false); - _context.GeneratedElementInfos.ExistsNumFmts = true; + Context.GeneratedElementInfos.ExistsNumFmts = true; } - else if (!_context.OldElementInfos.ExistsFonts && !_context.GeneratedElementInfos.ExistsFonts && AllElements["fonts"] < elementIndex) + else if (!Context.OldElementInfos.ExistsFonts && !Context.GeneratedElementInfos.ExistsFonts && AllElements["fonts"] < elementIndex) { await GenerateFontsAsync().ConfigureAwait(false); - _context.GeneratedElementInfos.ExistsFonts = true; + Context.GeneratedElementInfos.ExistsFonts = true; } - else if (!_context.OldElementInfos.ExistsFills && !_context.GeneratedElementInfos.ExistsFills && AllElements["fills"] < elementIndex) + else if (!Context.OldElementInfos.ExistsFills && !Context.GeneratedElementInfos.ExistsFills && AllElements["fills"] < elementIndex) { await GenerateFillsAsync().ConfigureAwait(false); - _context.GeneratedElementInfos.ExistsFills = true; + Context.GeneratedElementInfos.ExistsFills = true; } - else if (!_context.OldElementInfos.ExistsBorders && !_context.GeneratedElementInfos.ExistsBorders && AllElements["borders"] < elementIndex) + else if (!Context.OldElementInfos.ExistsBorders && !Context.GeneratedElementInfos.ExistsBorders && AllElements["borders"] < elementIndex) { await GenerateBordersAsync().ConfigureAwait(false); - _context.GeneratedElementInfos.ExistsBorders = true; + Context.GeneratedElementInfos.ExistsBorders = true; } - else if (!_context.OldElementInfos.ExistsCellStyleXfs && !_context.GeneratedElementInfos.ExistsCellStyleXfs && AllElements["cellStyleXfs"] < elementIndex) + else if (!Context.OldElementInfos.ExistsCellStyleXfs && !Context.GeneratedElementInfos.ExistsCellStyleXfs && AllElements["cellStyleXfs"] < elementIndex) { await GenerateCellStyleXfsAsync().ConfigureAwait(false); - _context.GeneratedElementInfos.ExistsCellStyleXfs = true; + Context.GeneratedElementInfos.ExistsCellStyleXfs = true; } - else if (!_context.OldElementInfos.ExistsCellXfs && !_context.GeneratedElementInfos.ExistsCellXfs && AllElements["cellXfs"] < elementIndex) + else if (!Context.OldElementInfos.ExistsCellXfs && !Context.GeneratedElementInfos.ExistsCellXfs && AllElements["cellXfs"] < elementIndex) { await GenerateCellXfsAsync().ConfigureAwait(false); - _context.GeneratedElementInfos.ExistsCellXfs = true; + Context.GeneratedElementInfos.ExistsCellXfs = true; } } @@ -170,7 +170,7 @@ protected virtual async Task GenerateElementBeforEndElementAsync() { switch (OldReader.LocalName) { - case "styleSheet" when !_context.OldElementInfos.ExistsNumFmts && !_context.GeneratedElementInfos.ExistsNumFmts: + case "styleSheet" when !Context.OldElementInfos.ExistsNumFmts && !Context.GeneratedElementInfos.ExistsNumFmts: await GenerateNumFmtsAsync().ConfigureAwait(false); break; case "numFmts": @@ -198,11 +198,11 @@ protected virtual async Task GenerateElementBeforEndElementAsync() protected virtual async Task GenerateNumFmtsAsync() { await NewWriter.WriteStartElementAsync(OldReader.Prefix, "numFmts", OldReader.NamespaceURI).ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "count", null, (_context.OldElementInfos.NumFmtCount + _context.GeneratedElementInfos.NumFmtCount + _context.CustomFormatCount).ToString()).ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "count", null, (Context.OldElementInfos.NumFmtCount + Context.GeneratedElementInfos.NumFmtCount + Context.CustomFormatCount).ToString()).ConfigureAwait(false); await GenerateNumFmtAsync().ConfigureAwait(false); await NewWriter.WriteFullEndElementAsync().ConfigureAwait(false); - if (!_context.OldElementInfos.ExistsFonts) + if (!Context.OldElementInfos.ExistsFonts) { await GenerateFontsAsync().ConfigureAwait(false); } @@ -215,11 +215,11 @@ protected virtual async Task GenerateNumFmtsAsync() protected virtual async Task GenerateFontsAsync() { await NewWriter.WriteStartElementAsync(OldReader.Prefix, "fonts", OldReader.NamespaceURI).ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "count", null, (_context.OldElementInfos.FontCount + _context.GeneratedElementInfos.FontCount).ToString()).ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "count", null, (Context.OldElementInfos.FontCount + Context.GeneratedElementInfos.FontCount).ToString()).ConfigureAwait(false); await GenerateFontAsync().ConfigureAwait(false); await NewWriter.WriteFullEndElementAsync().ConfigureAwait(false); - if (!_context.OldElementInfos.ExistsFills) + if (!Context.OldElementInfos.ExistsFills) { await GenerateFillsAsync().ConfigureAwait(false); } @@ -232,11 +232,11 @@ protected virtual async Task GenerateFontsAsync() protected virtual async Task GenerateFillsAsync() { await NewWriter.WriteStartElementAsync(OldReader.Prefix, "fills", OldReader.NamespaceURI).ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "count", null, (_context.OldElementInfos.FillCount + _context.GeneratedElementInfos.FillCount).ToString()).ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "count", null, (Context.OldElementInfos.FillCount + Context.GeneratedElementInfos.FillCount).ToString()).ConfigureAwait(false); await GenerateFillAsync().ConfigureAwait(false); await NewWriter.WriteFullEndElementAsync().ConfigureAwait(false); - if (!_context.OldElementInfos.ExistsBorders) + if (!Context.OldElementInfos.ExistsBorders) { await GenerateBordersAsync().ConfigureAwait(false); } @@ -249,11 +249,11 @@ protected virtual async Task GenerateFillsAsync() protected virtual async Task GenerateBordersAsync() { await NewWriter.WriteStartElementAsync(OldReader.Prefix, "borders", OldReader.NamespaceURI).ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "count", null, (_context.OldElementInfos.BorderCount + _context.GeneratedElementInfos.BorderCount).ToString()).ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "count", null, (Context.OldElementInfos.BorderCount + Context.GeneratedElementInfos.BorderCount).ToString()).ConfigureAwait(false); await GenerateBorderAsync().ConfigureAwait(false); await NewWriter.WriteFullEndElementAsync().ConfigureAwait(false); - if (!_context.OldElementInfos.ExistsCellStyleXfs) + if (!Context.OldElementInfos.ExistsCellStyleXfs) { await GenerateCellStyleXfsAsync().ConfigureAwait(false); } @@ -266,11 +266,11 @@ protected virtual async Task GenerateBordersAsync() protected virtual async Task GenerateCellStyleXfsAsync() { await NewWriter.WriteStartElementAsync(OldReader.Prefix, "cellStyleXfs", OldReader.NamespaceURI).ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "count", null, (_context.OldElementInfos.CellStyleXfCount + _context.GeneratedElementInfos.CellStyleXfCount).ToString()).ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "count", null, (Context.OldElementInfos.CellStyleXfCount + Context.GeneratedElementInfos.CellStyleXfCount).ToString()).ConfigureAwait(false); await GenerateCellStyleXfAsync().ConfigureAwait(false); await NewWriter.WriteFullEndElementAsync().ConfigureAwait(false); - if (!_context.OldElementInfos.ExistsCellXfs) + if (!Context.OldElementInfos.ExistsCellXfs) { await GenerateCellXfsAsync().ConfigureAwait(false); } @@ -283,7 +283,7 @@ protected virtual async Task GenerateCellStyleXfsAsync() protected virtual async Task GenerateCellXfsAsync() { await NewWriter.WriteStartElementAsync(OldReader.Prefix, "cellXfs", OldReader.NamespaceURI).ConfigureAwait(false); - await NewWriter.WriteAttributeStringAsync(null, "count", null, (_context.OldElementInfos.CellXfCount + _context.GeneratedElementInfos.CellXfCount + _context.CustomFormatCount).ToString()).ConfigureAwait(false); + await NewWriter.WriteAttributeStringAsync(null, "count", null, (Context.OldElementInfos.CellXfCount + Context.GeneratedElementInfos.CellXfCount + Context.CustomFormatCount).ToString()).ConfigureAwait(false); await GenerateCellXfAsync().ConfigureAwait(false); await NewWriter.WriteFullEndElementAsync().ConfigureAwait(false); } From 164320b99a88dc120c3230cf247b7100fa9fddc7 Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Sat, 23 May 2026 19:08:36 +0200 Subject: [PATCH 06/12] Added XDocument.LoadAsyn and XDocument.SaveAsync polyfills --- src/MiniExcel.Core/Helpers/Polyfills.cs | 42 ++++++++++++++----- src/MiniExcel.OpenXml/OpenXmlReader.cs | 19 --------- .../Templates/OpenXmlTemplate.Impl.cs | 7 ++-- .../Writer/OpenXmlWriter.CopyInsert.cs | 6 +-- src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs | 13 ++---- 5 files changed, 40 insertions(+), 47 deletions(-) diff --git a/src/MiniExcel.Core/Helpers/Polyfills.cs b/src/MiniExcel.Core/Helpers/Polyfills.cs index b6454259..36991067 100644 --- a/src/MiniExcel.Core/Helpers/Polyfills.cs +++ b/src/MiniExcel.Core/Helpers/Polyfills.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using System.IO.Compression; +using System.Xml.Linq; namespace MiniExcelLib.Core.Helpers; @@ -9,20 +10,23 @@ in the other projects that require it so as to prevent the consumers' IDEs to be public static class Polyfills { #if NETSTANDARD2_0 - [EditorBrowsable(EditorBrowsableState.Advanced)] - public static TValue? GetValueOrDefault(this IDictionary dictionary, TKey key, TValue? defaultValue = default) + extension(IDictionary dictionary) { - return dictionary.TryGetValue(key, out var value) ? value : defaultValue; - } + [EditorBrowsable(EditorBrowsableState.Advanced)] + public TValue? GetValueOrDefault(TKey key, TValue? defaultValue = default) + { + return dictionary.TryGetValue(key, out var value) ? value : defaultValue; + } - [EditorBrowsable(EditorBrowsableState.Advanced)] - public static bool TryAdd(this IDictionary dictionary, TKey key, TValue value) - { - if (dictionary.ContainsKey(key)) - return false; + [EditorBrowsable(EditorBrowsableState.Advanced)] + public bool TryAdd(TKey key, TValue value) + { + if (dictionary.ContainsKey(key)) + return false; - dictionary.Add(key, value); - return true; + dictionary.Add(key, value); + return true; + } } [EditorBrowsable(EditorBrowsableState.Advanced)] @@ -68,6 +72,22 @@ public ValueTask OpenAsync(CancellationToken cancellationToken = default } } + extension(XDocument doc) + { + [EditorBrowsable(EditorBrowsableState.Advanced)] + public static ValueTask LoadAsync(Stream stream, LoadOptions loadOptions, CancellationToken cancellationToken = default) + { + return new ValueTask(XDocument.Load(stream, loadOptions)); + } + + [EditorBrowsable(EditorBrowsableState.Advanced)] + public ValueTask SaveAsync(Stream stream, SaveOptions saveOptions, CancellationToken cancellationToken = default) + { + doc.Save(stream, saveOptions); + return default; + } + } + extension(ZipArchive) { [EditorBrowsable(EditorBrowsableState.Advanced)] diff --git a/src/MiniExcel.OpenXml/OpenXmlReader.cs b/src/MiniExcel.OpenXml/OpenXmlReader.cs index e2655405..6f93b5c0 100644 --- a/src/MiniExcel.OpenXml/OpenXmlReader.cs +++ b/src/MiniExcel.OpenXml/OpenXmlReader.cs @@ -1131,11 +1131,7 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance using var personStream = persons.Open(); #endif -#if NETSTANDARD2_0 - var personDoc = XDocument.Load(personStream, LoadOptions.None); -#else var personDoc = await XDocument.LoadAsync(personStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); -#endif var personElements = personDoc.Root?.Elements(ns18Tc + "person"); people = personElements ?.Select(p => new Author @@ -1156,12 +1152,7 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance #else using var stream = rel.Open(); #endif - -#if NETSTANDARD2_0 - var relDoc = XDocument.Load(stream, LoadOptions.None); -#else var relDoc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); -#endif var threadedCommentRels = relDoc.Root?.Elements(nsRel + "Relationship"); var threadedCommentsElement = threadedCommentRels?.FirstOrDefault(x => x.Attribute("Type")?.Value == Schemas.SpreadsheetmlXmlThreadedComment); @@ -1184,12 +1175,7 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance #else using var threadEntryStream = threadEntry.Open(); #endif - -#if NETSTANDARD2_0 - var doc = XDocument.Load(threadEntryStream, LoadOptions.None); -#else var doc = await XDocument.LoadAsync(threadEntryStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); -#endif var commentThreadElements = doc.Root?.Elements(ns18Tc + "threadedComment"); commentThreads = commentThreadElements @@ -1237,12 +1223,7 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance #else using var noteEntryStream = noteEntry.Open(); #endif - -#if NETSTANDARD2_0 - var doc = XDocument.Load(noteEntryStream, LoadOptions.None); -#else var doc = await XDocument.LoadAsync(noteEntryStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); -#endif var authorElements = doc.Root?.Element(nsMain + "authors")?.Elements(nsMain + "author"); var authors = authorElements?.Select(a => a.Value).ToArray(); diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs index d972620f..d36f0c2d 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs @@ -44,11 +44,10 @@ internal partial class OpenXmlTemplate [CreateSyncVersion] private async Task GenerateSheetByUpdateModeAsync(ZipArchiveEntry sheetZipEntry, Stream stream, Stream sheetStream, IDictionary inputMaps, IDictionary sharedStrings, bool mergeCells = false, CancellationToken cancellationToken = default) { -#if NET var doc = await XDocument.LoadAsync(sheetStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); +#if NET await sheetStream.DisposeAsync().ConfigureAwait(false); #else - var doc = XDocument.Load(sheetStream); sheetStream.Dispose(); #endif @@ -80,11 +79,11 @@ private async Task GenerateSheetByCreateModeAsync(ZipArchiveEntry templateSheetZ #if NET var newTemplateStream = await templateSheetZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableNewTemplateStream = newTemplateStream.ConfigureAwait(false); - var doc = await XDocument.LoadAsync(newTemplateStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); #else using var newTemplateStream = templateSheetZipEntry.Open(); - var doc = XDocument.Load(newTemplateStream); #endif + var doc = await XDocument.LoadAsync(newTemplateStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); + var worksheet = doc.Element(SpreadsheetNs + "worksheet"); var prefix = worksheet?.GetPrefixOfNamespace(SpreadsheetNs); if (!string.IsNullOrEmpty(prefix)) diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs index abfe993d..d75ee34b 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs @@ -246,11 +246,10 @@ private async Task CopyAndUpdateContentTypesAsync(CancellationToken cancellation #if NET var stream = await contentTypesZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); - var doc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); #else using var stream = contentTypesZipEntry.Open(); - var doc = XDocument.Load(stream); #endif + var doc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var ns = doc.Root!.GetDefaultNamespace(); var typesElement = doc.Descendants(ns + "Types").Single(); @@ -278,11 +277,10 @@ private async Task CopyAndUpdateContentTypesAsync(CancellationToken cancellation var contentTypesEntryStream = await contentTypesEntry.OpenAsync(cancellationToken).ConfigureAwait(false); #if NET await using var disposableContetTypesEntryStream = contentTypesEntryStream.ConfigureAwait(false); - await doc.SaveAsync(contentTypesEntryStream, SaveOptions.None, cancellationToken).ConfigureAwait(false); #else using var disposableContetTypesEntryStream = contentTypesEntryStream; - doc.Save(contentTypesEntryStream); #endif + await doc.SaveAsync(contentTypesEntryStream, SaveOptions.None, cancellationToken).ConfigureAwait(false); } private class TempSheetStylesBuilderUtils(Stream backingStream, ZipArchive archive, SheetStyleBuilderContext sheetStyleBuilderContext, ISheetStyleBuilder sheetStyleBuilder) : IDisposable, IAsyncDisposable diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs index 93641276..4057eca5 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs @@ -635,12 +635,11 @@ private async Task InsertContentTypesXmlAsync(CancellationToken cancellationToke #if NET var stream = await contentTypesZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); - var doc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); #else using var stream = contentTypesZipEntry.Open(); - var doc = XDocument.Load(stream); #endif + var doc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var ns = doc.Root!.GetDefaultNamespace(); var typesElement = doc.Descendants(ns + "Types").Single(); @@ -663,12 +662,8 @@ private async Task InsertContentTypesXmlAsync(CancellationToken cancellationToke } } - stream.Position = 0; -#if NET + stream.Seek(0, SeekOrigin.Begin); await doc.SaveAsync(stream, SaveOptions.None, cancellationToken).ConfigureAwait(false); -#else - doc.Save(stream); -#endif } [CreateSyncVersion] @@ -741,11 +736,11 @@ async Task LoadWorkbook() #if NET var zipStream = await oldWorkbookEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableZipStream = zipStream.ConfigureAwait(false); - var workbookDoc = await XDocument.LoadAsync(zipStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); #else using var zipStream = oldWorkbookEntry.Open(); - var workbookDoc = XDocument.Load(zipStream); #endif + + var workbookDoc = await XDocument.LoadAsync(zipStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var sheetsContainer = workbookDoc.Root?.Element((XNamespace)Schemas.SpreadsheetmlXmlMain + "sheets")!; var sheets = sheetsContainer.Elements().ToList(); From 32f455a27e8303dba6e4f4a9076c893147802376 Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Sat, 23 May 2026 19:47:52 +0200 Subject: [PATCH 07/12] Removed obsolete FillTemplate method overloads --- src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs | 46 +------------------ 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs b/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs index 6386127f..77e5b2b0 100644 --- a/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs +++ b/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs @@ -131,48 +131,4 @@ private static OpenXmlTemplate GetOpenXmlTemplate(Stream stream, OpenXmlConfigur } #endregion - - #region Obsolete - [CreateSyncVersion, Obsolete("Please use FillTemplate or FillTemplateAsync instead")] - public Task ApplyTemplateAsync(string path, string templatePath, object value, - OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) - { - return FillTemplateAsync(path, templatePath, value, true, configuration, cancellationToken); - } - - [CreateSyncVersion, Obsolete("Please use FillTemplate or FillTemplateAsync instead")] - public Task ApplyTemplateAsync(string path, Stream templateStream, object value, - OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) - { - return FillTemplateAsync(path, templateStream, value, true, configuration, cancellationToken); - } - - [CreateSyncVersion, Obsolete("Please use FillTemplate or FillTemplateAsync instead")] - public Task ApplyTemplateAsync(Stream stream, string templatePath, object value, - OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) - { - return FillTemplateAsync(stream, templatePath, value, configuration, cancellationToken); - } - - [CreateSyncVersion, Obsolete("Please use FillTemplate or FillTemplateAsync instead")] - public Task ApplyTemplateAsync(Stream stream, Stream templateStream, object value, - OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) - { - return FillTemplateAsync(stream, templateStream, value, configuration, cancellationToken); - } - - [CreateSyncVersion, Obsolete("Please use FillTemplate or FillTemplateAsync instead")] - public Task ApplyTemplateAsync(string path, byte[] templateBytes, object value, - OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) - { - return FillTemplateAsync(path, templateBytes, value, true, configuration, cancellationToken); - } - - [CreateSyncVersion, Obsolete("Please use FillTemplate or FillTemplateAsync instead")] - public Task ApplyTemplateAsync(Stream stream, byte[] templateBytes, object value, - OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) - { - return FillTemplateAsync(stream, templateBytes, value, configuration, cancellationToken); - } - #endregion -} \ No newline at end of file +} From 7daf93f8ea0bbc9940791702404155ab4ffe5f10 Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Sat, 23 May 2026 20:00:15 +0200 Subject: [PATCH 08/12] Added source generated regex to CsvReader --- src/MiniExcel.Csv/CsvReader.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/MiniExcel.Csv/CsvReader.cs b/src/MiniExcel.Csv/CsvReader.cs index f2b648d4..f28e2f1c 100644 --- a/src/MiniExcel.Csv/CsvReader.cs +++ b/src/MiniExcel.Csv/CsvReader.cs @@ -159,7 +159,7 @@ private string[] Split(string row) //this code from S.O : https://stackoverflow.com/a/11365961/9131476 return Regex.Split(row, $"[\t{_config.Seperator}](?=(?:[^\"]|\"[^\"]*\")*$)") - .Select(s => Regex.Replace(s.Replace("\"\"", "\""), "^\"|\"$", "")) + .Select(s => DoubleQuotesRegexImpl.Replace(s.Replace("\"\"", "\""), "")) .ToArray(); } @@ -167,4 +167,11 @@ public void Dispose() { _stream?.Dispose(); } +#if NET + [GeneratedRegex("^\"|\"$")] + private static partial Regex DoubleQuotesRegex(); + private static readonly Regex DoubleQuotesRegexImpl = DoubleQuotesRegex(); +#else + private static readonly Regex DoubleQuotesRegexImpl = new Regex("^\"|\"$", RegexOptions.Compiled); +#endif } From 3fb589c4d3cc409664e88e4a1e362ca46c111631 Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Sat, 23 May 2026 22:03:54 +0200 Subject: [PATCH 09/12] Added more constants to schemas and filenames, and substituted them wherever they had been prevoiusly hardcoded --- .../Constants/ExcelFileNames.cs | 2 ++ src/MiniExcel.OpenXml/Constants/Schemas.cs | 11 +++++-- .../MappingTemplateApplicator.cs | 4 ++- src/MiniExcel.OpenXml/Models/SheetDto.cs | 8 +++-- src/MiniExcel.OpenXml/OpenXmlReader.cs | 15 ++++----- .../Picture/OpenXmlPictureImplement.cs | 33 ++++++++++--------- src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs | 2 +- .../Templates/OpenXmlTemplate.Impl.cs | 2 +- .../Templates/OpenXmlTemplate.MergeCells.cs | 5 +-- .../Templates/OpenXmlTemplate.cs | 22 ++++++++----- .../Utils/CalcChainHelper.cs | 4 +-- .../Utils/XmlReaderHelper.cs | 2 +- src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs | 6 ++-- 13 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/MiniExcel.OpenXml/Constants/ExcelFileNames.cs b/src/MiniExcel.OpenXml/Constants/ExcelFileNames.cs index a5e98cf1..e38c5add 100644 --- a/src/MiniExcel.OpenXml/Constants/ExcelFileNames.cs +++ b/src/MiniExcel.OpenXml/Constants/ExcelFileNames.cs @@ -8,6 +8,8 @@ internal static class ExcelFileNames internal const string ContentTypes = "[Content_Types].xml"; internal const string Person = "xl/persons/person.xml"; internal const string Styles = "xl/styles.xml"; + internal const string CalcChain = "xl/calcChain.xml"; + internal const string Workbook = "xl/workbook.xml"; internal const string WorkbookRels = "xl/_rels/workbook.xml.rels"; internal const string WorksheetBase = "xl/worksheets/sheet"; diff --git a/src/MiniExcel.OpenXml/Constants/Schemas.cs b/src/MiniExcel.OpenXml/Constants/Schemas.cs index 94dfb55e..622b5eea 100644 --- a/src/MiniExcel.OpenXml/Constants/Schemas.cs +++ b/src/MiniExcel.OpenXml/Constants/Schemas.cs @@ -8,9 +8,14 @@ internal static class Schemas public const string OpenXmlPackageRelationships = "http://schemas.openxmlformats.org/package/2006/relationships"; public const string SpreadsheetmlXmlRelationships = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"; public const string SpreadsheetmlXmlStrictRelationships = "http://purl.oclc.org/ooxml/officeDocument/relationships"; - public const string SpreadsheetmlXmlTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"; - public const string SpreadsheetmlXmlComments = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; - public const string SpreadsheetmlXmlThreadedComment = "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment"; + public const string SpreadsheetmlXmlSpreadsheetDrawing = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"; + public const string SpreadsheetmlXmlDrawingml2006 = "http://schemas.openxmlformats.org/drawingml/2006/main"; + public const string SpreadsheetmlXmlDrawing2014 = "http://schemas.microsoft.com/office/drawing/2014/main"; + public const string SpreadsheetmlXmlDrawingRelationship = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"; + public const string SpreadsheetmlXmlImageRelationship = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"; + public const string SpreadsheetmlXmlTableRelationship = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"; + public const string SpreadsheetmlXmlCommentsRelationship = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; + public const string SpreadsheetmlXmlThreadedCommentRelationship = "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment"; public const string SpreadsheetmlXmlX14Ac = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"; public const string SpreadsheetmlXmlX18Tc = "http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments"; diff --git a/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs b/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs index 77c1851a..dd0d46f2 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs @@ -1,3 +1,5 @@ +using MiniExcelLib.OpenXml.Constants; + namespace MiniExcelLib.OpenXml.FluentMapping; internal static partial class MappingTemplateApplicator where T : class @@ -88,7 +90,7 @@ await ProcessWorksheetAsync( private static bool IsWorksheetEntry(string fullName) { - return fullName.StartsWith("xl/worksheets/sheet", StringComparison.OrdinalIgnoreCase) && + return fullName.StartsWith(ExcelFileNames.WorksheetBase, StringComparison.OrdinalIgnoreCase) && fullName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase); } diff --git a/src/MiniExcel.OpenXml/Models/SheetDto.cs b/src/MiniExcel.OpenXml/Models/SheetDto.cs index 1bea641f..7ed27612 100644 --- a/src/MiniExcel.OpenXml/Models/SheetDto.cs +++ b/src/MiniExcel.OpenXml/Models/SheetDto.cs @@ -1,11 +1,13 @@ -namespace MiniExcelLib.OpenXml.Models; +using MiniExcelLib.OpenXml.Constants; + +namespace MiniExcelLib.OpenXml.Models; internal class SheetDto { internal string ID { get; set; } = $"R{Guid.NewGuid():N}"; internal string? Name { get; set; } internal int SheetIdx { get; set; } - internal string Path => $"xl/worksheets/sheet{SheetIdx}.xml"; + internal string Path => ExcelFileNames.Worksheet(SheetIdx); internal string State { get; set; } -} \ No newline at end of file +} diff --git a/src/MiniExcel.OpenXml/OpenXmlReader.cs b/src/MiniExcel.OpenXml/OpenXmlReader.cs index 6f93b5c0..7ffffe3e 100644 --- a/src/MiniExcel.OpenXml/OpenXmlReader.cs +++ b/src/MiniExcel.OpenXml/OpenXmlReader.cs @@ -679,7 +679,7 @@ private void ConvertCellValue(string rawValue, string aT, int xfIndex, out objec switch (aT) { - case "s": + case ExcelDataTypes.SharedString: if (int.TryParse(rawValue, style, invariantCulture, out var sstIndex)) { if (sstIndex >= 0 && sstIndex < SharedStrings?.Count) @@ -689,8 +689,7 @@ private void ConvertCellValue(string rawValue, string aT, int xfIndex, out objec } break; - case "inlineStr": - case "str": + case ExcelDataTypes.InlineString or ExcelDataTypes.CalculatedString: //TODO: it will unbox,box var v = XmlHelper.DecodeString(rawValue); value = v; @@ -711,17 +710,17 @@ private void ConvertCellValue(string rawValue, string aT, int xfIndex, out objec } break; - case "b": + case ExcelDataTypes.Boolean: value = rawValue == "1"; return; - case "d": + case ExcelDataTypes.DateTime: value = DateTime.TryParseExact(rawValue, "yyyy-MM-dd", invariantCulture, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite, out var date) ? date : rawValue; return; - case "e": + case ExcelDataTypes.Error: value = rawValue; return; @@ -1155,12 +1154,12 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance var relDoc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var threadedCommentRels = relDoc.Root?.Elements(nsRel + "Relationship"); - var threadedCommentsElement = threadedCommentRels?.FirstOrDefault(x => x.Attribute("Type")?.Value == Schemas.SpreadsheetmlXmlThreadedComment); + var threadedCommentsElement = threadedCommentRels?.FirstOrDefault(x => x.Attribute("Type")?.Value == Schemas.SpreadsheetmlXmlThreadedCommentRelationship); var threadedCommentsTarget = threadedCommentsElement?.Attribute("Target"); var threadedCommentsPath = threadedCommentsTarget?.Value.TrimStart('.', '/'); var noteRels = relDoc.Root?.Elements(nsRel + "Relationship"); - var notesElement = noteRels?.FirstOrDefault(x => x.Attribute("Type")?.Value == Schemas.SpreadsheetmlXmlComments); + var notesElement = noteRels?.FirstOrDefault(x => x.Attribute("Type")?.Value == Schemas.SpreadsheetmlXmlCommentsRelationship); var notesTarget = notesElement?.Attribute("Target"); var notesPath = notesTarget?.Value.TrimStart('.', '/'); diff --git a/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs b/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs index 4bfc3fdb..95430518 100644 --- a/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs +++ b/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs @@ -1,5 +1,6 @@ using System.Drawing; using MiniExcelLib.Core.Enums; +using MiniExcelLib.OpenXml.Constants; namespace MiniExcelLib.OpenXml.Picture; @@ -8,8 +9,8 @@ internal static partial class MiniExcelPictureImplement private static XmlNamespaceManager GetRNamespaceManager(XmlDocument doc) { var nsmgr = new XmlNamespaceManager(doc.NameTable); - nsmgr.AddNamespace("x", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - nsmgr.AddNamespace("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + nsmgr.AddNamespace("x", Schemas.SpreadsheetmlXmlMain); + nsmgr.AddNamespace("r", Schemas.SpreadsheetmlXmlRelationships); return nsmgr; } @@ -58,7 +59,7 @@ public static async Task AddPictureAsync(Stream excelStream, CancellationToken c var relsDoc = LoadXml(relsEntry); var namespaceManager = new XmlNamespaceManager(relsDoc.NameTable); - namespaceManager.AddNamespace("x", "http://schemas.openxmlformats.org/package/2006/relationships"); + namespaceManager.AddNamespace("x", Schemas.OpenXmlPackageRelationships); var xpath = $"/x:Relationships/x:Relationship[@Id='{drawingRelId}']"; var relNode = relsDoc.SelectSingleNode(xpath, namespaceManager); @@ -85,13 +86,13 @@ public static async Task AddPictureAsync(Stream excelStream, CancellationToken c var relsDoc = LoadXml(relsEntry); var relNode = relsDoc.CreateElement("Relationship", relsDoc.DocumentElement.NamespaceURI); relNode.SetAttribute("Id", drawingRelId); - relNode.SetAttribute("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"); + relNode.SetAttribute("Type", Schemas.SpreadsheetmlXmlDrawingRelationship); relNode.SetAttribute("Target", $"../drawings/drawing{drawingId}.xml"); relsDoc.DocumentElement.AppendChild(relNode); SaveXml(relsDoc, relsEntry); // Update [Content_Types].xml for drawing - var contentTypesEntry = archive.GetEntry("[Content_Types].xml"); + var contentTypesEntry = archive.GetEntry(ExcelFileNames.ContentTypes); var contentTypesDoc = LoadXml(contentTypesEntry); var overrideDrawingFileExists = contentTypesDoc.DocumentElement .ChildNodes @@ -103,7 +104,7 @@ public static async Task AddPictureAsync(Stream excelStream, CancellationToken c { var overrideNode = contentTypesDoc.CreateElement("Override", contentTypesDoc.DocumentElement.NamespaceURI); overrideNode.SetAttribute("PartName", $"/xl/drawings/drawing{drawingId}.xml"); - overrideNode.SetAttribute("ContentType", "application/vnd.openxmlformats-officedocument.drawing+xml"); + overrideNode.SetAttribute("ContentType", ExcelContentTypes.Drawing); contentTypesDoc.DocumentElement.AppendChild(overrideNode); } @@ -146,7 +147,7 @@ public static async Task AddPictureAsync(Stream excelStream, CancellationToken c #endif // Step 2: Update [Content_Types].xml for image - var contentTypesEntry = archive.GetEntry("[Content_Types].xml"); + var contentTypesEntry = archive.GetEntry(ExcelFileNames.ContentTypes); var contentTypesDoc = LoadXml(contentTypesEntry); if (!contentTypesDoc.DocumentElement.InnerXml.Contains("image/png")) { @@ -164,7 +165,7 @@ public static async Task AddPictureAsync(Stream excelStream, CancellationToken c // Step 4: Add image relationship to drawing rels var relNode = drawingRelsDoc.CreateElement("Relationship", drawingRelsDoc.DocumentElement.NamespaceURI); relNode.SetAttribute("Id", relId); - relNode.SetAttribute("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"); + relNode.SetAttribute("Type", Schemas.SpreadsheetmlXmlImageRelationship); relNode.SetAttribute("Target", $"../media/{imageName}"); drawingRelsDoc.DocumentElement.AppendChild(relNode); } @@ -208,7 +209,7 @@ private static void SaveXml(XmlDocument doc, ZipArchiveEntry entry) private static XmlNamespaceManager GetNamespaceManager(XmlDocument doc) { var nsmgr = new XmlNamespaceManager(doc.NameTable); - nsmgr.AddNamespace("x", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + nsmgr.AddNamespace("x", Schemas.SpreadsheetmlXmlMain); return nsmgr; } @@ -219,8 +220,8 @@ private static XmlDocument CreateDrawingXml(XmlDocument existingDoc, int col, in private static class DrawingXmlHelper { - private const string XdrNamespace = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"; - private const string ANamespace = "http://schemas.openxmlformats.org/drawingml/2006/main"; + private const string XdrNamespace = Schemas.SpreadsheetmlXmlSpreadsheetDrawing; + private const string ANamespace = Schemas.SpreadsheetmlXmlDrawingml2006; private static long PixelsToEmu(int pixels) => pixels * 9525; @@ -251,7 +252,7 @@ Point location var ns = new XmlNamespaceManager(doc.NameTable); ns.AddNamespace("xdr", XdrNamespace); ns.AddNamespace("a", ANamespace); - ns.AddNamespace("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + ns.AddNamespace("r", Schemas.SpreadsheetmlXmlRelationships); // Root XmlElement wsDr; @@ -350,8 +351,8 @@ Point location var extNode = doc.CreateElement("a", "ext", ANamespace); extNode.SetAttribute("uri", "{FF2B5EF4-FFF2-40B4-BE49-F238E27FC236}"); - var creationId = doc.CreateElement("a16", "creationId", "http://schemas.microsoft.com/office/drawing/2014/main"); - creationId.SetAttribute("id", "http://schemas.microsoft.com/office/drawing/2014/main", $"{{00000000-0008-0000-0000-0000{nextId:D6}000000}}"); + var creationId = doc.CreateElement("a16", "creationId", Schemas.SpreadsheetmlXmlDrawing2014); + creationId.SetAttribute("id", Schemas.SpreadsheetmlXmlDrawing2014, $"{{00000000-0008-0000-0000-0000{nextId:D6}000000}}"); extNode.AppendChild(creationId); extLst.AppendChild(extNode); @@ -371,7 +372,7 @@ Point location var blipFill = doc.CreateElement("xdr", "blipFill", XdrNamespace); var blip = doc.CreateElement("a", "blip", ANamespace); - blip.SetAttribute("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + blip.SetAttribute("xmlns:r", Schemas.SpreadsheetmlXmlRelationships); blip.SetAttribute("embed", ns.LookupNamespace("r"), relId); blip.SetAttribute("cstate", "print"); @@ -435,4 +436,4 @@ private static void AppendXmlElement(XmlDocument doc, XmlElement parent, string parent.AppendChild(el); } } -} \ No newline at end of file +} diff --git a/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs b/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs index 8783cbd5..db3c3280 100644 --- a/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs +++ b/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs @@ -13,7 +13,7 @@ internal class OpenXmlStyles public OpenXmlStyles(OpenXmlZip zip) { - using var reader = zip.GetXmlReader("xl/styles.xml"); + using var reader = zip.GetXmlReader(ExcelFileNames.Styles); if (reader is null) throw new InvalidDataException("The OpenXml styles could not be found, the file might be malformed."); diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs index d36f0c2d..837871fc 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs @@ -28,7 +28,7 @@ internal partial class OpenXmlTemplate [GeneratedRegex(@"<(?:x:)?v>\s*")] private static partial Regex EmptyVTagRegexImpl(); private static readonly Regex EmptyVTagRegex = EmptyVTagRegexImpl(); #else - private static readonly Regex IsExpressionRegex = new("(?<={{).*?(?=}})"); + private static readonly Regex IsExpressionRegex = new("(?<={{).*?(?=}})", RegexOptions.Compiled); private static readonly Regex CellRegex = new("([A-Z]+)([0-9]+)", RegexOptions.Compiled); private static readonly Regex TemplateRegex = new(@"\{\{(.*?)\}\}", RegexOptions.Compiled); private static readonly Regex NonTemplateRegex = new(@".*?\{\{.*?\}\}.*?", RegexOptions.Compiled); diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs index 4c376a34..f7e5a4f8 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs @@ -1,3 +1,5 @@ +using MiniExcelLib.OpenXml.Constants; + namespace MiniExcelLib.OpenXml.Templates; internal partial class OpenXmlTemplate @@ -44,8 +46,7 @@ await stream.CopyToAsync(_outputFileStream //read all xlsx sheets var sheets = archive.ZipFile.Entries.Where(w => - w.FullName.StartsWith("xl/worksheets/sheet", StringComparison.OrdinalIgnoreCase) || - w.FullName.StartsWith("/xl/worksheets/sheet", StringComparison.OrdinalIgnoreCase) + w.FullName.TrimStart('/').StartsWith(ExcelFileNames.WorksheetBase, StringComparison.OrdinalIgnoreCase) ).ToList(); foreach (var sheet in sheets) diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs index 65237a9d..41e70076 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs @@ -1,4 +1,5 @@ using MiniExcelLib.Core; +using MiniExcelLib.OpenXml.Constants; using CalcChainHelper = MiniExcelLib.OpenXml.Utils.CalcChainHelper; namespace MiniExcelLib.OpenXml.Templates; @@ -80,9 +81,12 @@ public async Task SaveAsByTemplateAsync(Stream templateStream, object value, Can foreach (var entry in originalArchive.Entries) { var entryName = entry.FullName.TrimStart('/'); - if (entryName.StartsWith("xl/worksheets/sheet", StringComparison.OrdinalIgnoreCase) || entryName.Equals("xl/calcChain.xml")) + if (entryName.StartsWith(ExcelFileNames.WorksheetBase, StringComparison.OrdinalIgnoreCase) || + entryName.Equals(ExcelFileNames.CalcChain, StringComparison.OrdinalIgnoreCase)) + { continue; - + } + // Create a new entry in the new archive with the same name var newEntry = outputFileArchive.ZipFile.CreateEntry(entry.FullName); @@ -113,7 +117,7 @@ await originalEntryStream.CopyToAsync(newEntryStream var templateSheets = templateReader.Archive.ZipFile.Entries .Where(entry => entry.FullName .TrimStart('/') - .StartsWith("xl/worksheets/sheet", StringComparison.OrdinalIgnoreCase)); + .StartsWith(ExcelFileNames.WorksheetBase, StringComparison.OrdinalIgnoreCase)); int sheetIdx = 0; foreach (var templateSheet in templateSheets) @@ -134,6 +138,7 @@ await originalEntryStream.CopyToAsync(newEntryStream #else using var outputZipSheetEntryStream = outputZipEntry.Open(); #endif + await GenerateSheetByCreateModeAsync(templateSheet, outputZipSheetEntryStream, inputValues, templateSharedStrings, cancellationToken: cancellationToken).ConfigureAwait(false); //doc.Save(zipStream); //don't do it because: https://user-images.githubusercontent.com/12729184/114361127-61a5d100-9ba8-11eb-9bb9-34f076ee28a2.png @@ -144,14 +149,13 @@ await originalEntryStream.CopyToAsync(newEntryStream } // create mode we need to not create first then create here - var calcChain = outputFileArchive.EntryCollection.FirstOrDefault(e => e.FullName.Contains("xl/calcChain.xml")); + var calcChain = outputFileArchive.EntryCollection.FirstOrDefault(e + => e.FullName.TrimStart('/').Equals(ExcelFileNames.CalcChain, StringComparison.OrdinalIgnoreCase)); + if (calcChain is not null) { - var calcChainPathName = calcChain.FullName; - //calcChain.Delete(); - - var calcChainEntry = outputFileArchive.ZipFile.CreateEntry(calcChainPathName); #if NET + var calcChainEntry = outputFileArchive.ZipFile.CreateEntry(calcChain.FullName); var calcChainStream = await calcChainEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableChainEntryStream = calcChainStream.ConfigureAwait(false); #else @@ -163,7 +167,7 @@ await originalEntryStream.CopyToAsync(newEntryStream { foreach (var entry in originalArchive.Entries) { - if (entry.FullName.Contains("xl/calcChain.xml")) + if (entry.FullName.TrimStart('/').Equals(ExcelFileNames.CalcChain, StringComparison.OrdinalIgnoreCase)) { var newEntry = outputFileArchive.ZipFile.CreateEntry(entry.FullName); diff --git a/src/MiniExcel.OpenXml/Utils/CalcChainHelper.cs b/src/MiniExcel.OpenXml/Utils/CalcChainHelper.cs index 130d2aa9..db076575 100644 --- a/src/MiniExcel.OpenXml/Utils/CalcChainHelper.cs +++ b/src/MiniExcel.OpenXml/Utils/CalcChainHelper.cs @@ -28,9 +28,9 @@ public static async Task GenerateCalcChainSheetAsync(Stream calcChainStream, str var writer = new StreamWriter(calcChainStream, Encoding.UTF8); await using var disposableWriter = writer.ConfigureAwait(false); await writer.WriteAsync(content.AsMemory(), cancellationToken).ConfigureAwait(false); - #else +#else using var writer = new StreamWriter(calcChainStream, Encoding.UTF8); await writer.WriteAsync(content).ConfigureAwait(false); - #endif +#endif } } diff --git a/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs b/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs index 12cfead1..45e079bc 100644 --- a/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs +++ b/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs @@ -127,7 +127,7 @@ private static async Task ReadRichTextRunAsync(this XmlReader reader, Ca { result.Append(await reader.ReadElementContentAsStringAsync() #if NET - .WaitAsync(cancellationToken) + .WaitAsync(cancellationToken) #endif .ConfigureAwait(false)); } diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs index 4057eca5..89fe564a 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs @@ -696,15 +696,15 @@ internal async Task AlterWorksheetAsync(string sheetName, string? newSheetName, if (newSheetName is null && newSheetIndex is null && newSheetState is null) return; - var oldWorkbookEntry = _archive.GetEntry("xl/workbook.xml")!; + var oldWorkbookEntry = _archive.GetEntry(ExcelFileNames.Workbook)!; try { var xmlDoc = await LoadWorkbook().ConfigureAwait(false); oldWorkbookEntry.Delete(); - var newWorkbookEntry = _archive.CreateEntry("xl/workbook.xml", CompressionLevel.Fastest); -#if NET + var newWorkbookEntry = _archive.CreateEntry(ExcelFileNames.Workbook, CompressionLevel.Fastest); + var newZipStream = await newWorkbookEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var newDisposableZipStream = newZipStream.ConfigureAwait(false); var writer = XmlWriter.Create(newZipStream, new XmlWriterSettings From 70e23a849b072e5460c3c917bda6cda70de85123 Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Sat, 23 May 2026 22:35:38 +0200 Subject: [PATCH 10/12] Added Stream.DisposeAsync polyfill This polyfill, alongside the `StreamConfiguredAsyncDisposable` struct that copies the behaviour of the runtime's `ConfiguredAsyncDisposable` and the `Stream.ConfigureAwait` method that resturns it, allowed for cleaning all of the preprocessor directives that were used throughout whole codebase to dispose synchronously of streams for the netstandard2.0 (which was most of them). This also added the benefit of allowing for their asynchronous disposal in framework versions not expicitly targeted by checking if they implement the `IAsyncDisposable` interface. --- .../Helpers/MiniExcelStreamWriter.cs | 5 +- src/MiniExcel.Core/Helpers/Polyfills.cs | 42 +++++++++++ src/MiniExcel.Core/MiniExcelDataReader.cs | 10 +-- src/MiniExcel.Csv/Api/CsvExporter.cs | 10 +-- src/MiniExcel.Csv/Api/CsvImporter.cs | 14 ++-- src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs | 20 +----- src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs | 49 +++---------- src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs | 24 ++----- .../FluentMapping/Api/MappingExporter.cs | 4 -- .../FluentMapping/Api/MappingImporter.cs | 11 +-- .../FluentMapping/Api/MappingTemplater.cs | 12 +--- .../MappingTemplateApplicator.cs | 22 ++---- src/MiniExcel.OpenXml/OpenXmlReader.cs | 71 ++++--------------- .../Picture/OpenXmlPictureImplement.cs | 3 +- .../Styles/Builder/SheetStyleBuildContext.cs | 36 ++-------- .../Templates/OpenXmlTemplate.Impl.cs | 8 --- .../Templates/OpenXmlTemplate.MergeCells.cs | 15 +--- .../Templates/OpenXmlTemplate.cs | 29 +------- .../Writer/OpenXmlWriter.CopyInsert.cs | 29 ++------ src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs | 22 +----- 20 files changed, 120 insertions(+), 316 deletions(-) diff --git a/src/MiniExcel.Core/Helpers/MiniExcelStreamWriter.cs b/src/MiniExcel.Core/Helpers/MiniExcelStreamWriter.cs index 813e47bc..aa0711ed 100644 --- a/src/MiniExcel.Core/Helpers/MiniExcelStreamWriter.cs +++ b/src/MiniExcel.Core/Helpers/MiniExcelStreamWriter.cs @@ -13,12 +13,11 @@ public async Task WriteAsync(string content, CancellationToken cancellationToken if (!string.IsNullOrEmpty(content)) { #if NET - await _streamWriter.WriteAsync(content.AsMemory(), cancellationToken) + await _streamWriter.WriteAsync(content.AsMemory(), cancellationToken).ConfigureAwait(false); #else cancellationToken.ThrowIfCancellationRequested(); - await _streamWriter.WriteAsync(content) + await _streamWriter.WriteAsync(content).ConfigureAwait(false); #endif - .ConfigureAwait(false); } } diff --git a/src/MiniExcel.Core/Helpers/Polyfills.cs b/src/MiniExcel.Core/Helpers/Polyfills.cs index 36991067..5fcbf252 100644 --- a/src/MiniExcel.Core/Helpers/Polyfills.cs +++ b/src/MiniExcel.Core/Helpers/Polyfills.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using System.IO.Compression; +using System.Runtime.InteropServices; using System.Xml.Linq; namespace MiniExcelLib.Core.Helpers; @@ -59,6 +60,47 @@ public static IEnumerable ExceptBy(this IEnumerable new(stream, continueOnCapturedContext); + } + + /// + /// This is a copy of the runtime's , which we cannot instantiate directly for our needs + /// due to the constructor that initializes the object to eventually dispose being internal. + /// + [StructLayout(LayoutKind.Auto)] + [EditorBrowsable(EditorBrowsableState.Advanced)] + public readonly struct StreamConfiguredAsyncDisposable : IDisposable + { + private readonly Stream? _source; + private readonly bool _continueOnCapturedContext; + + internal StreamConfiguredAsyncDisposable(Stream? source, bool continueOnCapturedContext) + { + _source = source; + _continueOnCapturedContext = continueOnCapturedContext; + } + + public ConfiguredValueTaskAwaitable DisposeAsync() + => _source.DisposeAsync().ConfigureAwait(_continueOnCapturedContext); + + public void Dispose() + => _source?.Dispose(); + } #endif #if !NET10_0_OR_GREATER diff --git a/src/MiniExcel.Core/MiniExcelDataReader.cs b/src/MiniExcel.Core/MiniExcelDataReader.cs index 18de8a9e..f7f2d77d 100644 --- a/src/MiniExcel.Core/MiniExcelDataReader.cs +++ b/src/MiniExcel.Core/MiniExcelDataReader.cs @@ -294,17 +294,11 @@ public async Task CloseAsync() if (IsClosed) return; - if (_isAsyncSource) - { + if (_isAsyncSource) await _asyncSource!.DisposeAsync().ConfigureAwait(false); - } - _source?.Dispose(); -#if NET + _source?.Dispose(); await _stream!.DisposeAsync().ConfigureAwait(false); -#else - _stream.Dispose(); -#endif IsClosed = true; } diff --git a/src/MiniExcel.Csv/Api/CsvExporter.cs b/src/MiniExcel.Csv/Api/CsvExporter.cs index e9ac9039..3da4a5ee 100644 --- a/src/MiniExcel.Csv/Api/CsvExporter.cs +++ b/src/MiniExcel.Csv/Api/CsvExporter.cs @@ -1,5 +1,3 @@ -using MiniExcelLib.Core; - // ReSharper disable once CheckNamespace namespace MiniExcelLib.Csv; @@ -20,7 +18,9 @@ public async Task AppendAsync(string path, object value, bool printHeader = return rowsWritten.FirstOrDefault(); } - using var stream = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read, 4096, FileOptions.SequentialScan); + var stream = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read, 4096, FileOptions.SequentialScan); + await using var disposableStream = stream.ConfigureAwait(false); + return await AppendAsync(stream, value, configuration, progress, cancellationToken).ConfigureAwait(false); } @@ -39,7 +39,9 @@ public async Task AppendAsync(Stream stream, object value, CsvConfiguration public async Task ExportAsync(string path, object value, bool printHeader = true, bool overwriteFile = false, CsvConfiguration? configuration = null, IProgress? progress = null, CancellationToken cancellationToken = default) { - using var stream = overwriteFile ? File.Create(path) : new FileStream(path, FileMode.CreateNew); + var stream = overwriteFile ? File.Create(path) : new FileStream(path, FileMode.CreateNew); + await using var disposableStream = stream.ConfigureAwait(false); + return await ExportAsync(stream, value, printHeader, configuration, progress, cancellationToken).ConfigureAwait(false); } diff --git a/src/MiniExcel.Csv/Api/CsvImporter.cs b/src/MiniExcel.Csv/Api/CsvImporter.cs index 9bbbfb08..8d10290c 100644 --- a/src/MiniExcel.Csv/Api/CsvImporter.cs +++ b/src/MiniExcel.Csv/Api/CsvImporter.cs @@ -15,7 +15,8 @@ public async IAsyncEnumerable QueryAsync(string path, bool treatHeaderAsDa CsvConfiguration? configuration = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) where T : class, new() { - using var stream = FileHelper.OpenSharedRead(path); + var stream = FileHelper.OpenSharedRead(path); + await using var disposableStream = stream.ConfigureAwait(false); var query = QueryAsync(stream, treatHeaderAsData, configuration, cancellationToken); @@ -38,7 +39,9 @@ public async IAsyncEnumerable QueryAsync(Stream stream, bool treatHeaderAs public async IAsyncEnumerable QueryAsync(string path, bool useHeaderRow = false, CsvConfiguration? configuration = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { - using var stream = FileHelper.OpenSharedRead(path); + var stream = FileHelper.OpenSharedRead(path); + await using var disposableStream = stream.ConfigureAwait(false); + await foreach (var item in QueryAsync(stream, useHeaderRow, configuration, cancellationToken).ConfigureAwait(false)) yield return item; } @@ -64,7 +67,9 @@ public async IAsyncEnumerable QueryAsync(Stream stream, bool useHeaderR public async Task QueryAsDataTableAsync(string path, bool useHeaderRow = true, CsvConfiguration? configuration = null, CancellationToken cancellationToken = default) { - using var stream = FileHelper.OpenSharedRead(path); + var stream = FileHelper.OpenSharedRead(path); + await using var disposableStream = stream.ConfigureAwait(false); + return await QueryAsDataTableAsync(stream, useHeaderRow, configuration, cancellationToken).ConfigureAwait(false); } @@ -127,7 +132,8 @@ public async Task QueryAsDataTableAsync(Stream stream, bool useHeader public async Task> GetColumnNamesAsync(string path, bool useHeaderRow = false, CsvConfiguration? configuration = null, CancellationToken cancellationToken = default) { - using var stream = FileHelper.OpenSharedRead(path); + var stream = FileHelper.OpenSharedRead(path); + await using var disposableStream = stream.ConfigureAwait(false); return await GetColumnNamesAsync(stream, useHeaderRow, configuration, cancellationToken).ConfigureAwait(false); } diff --git a/src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs b/src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs index 12d9de9b..035c6e67 100644 --- a/src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs +++ b/src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs @@ -36,12 +36,9 @@ public async Task InsertSheetAsync(string path, object value, string sheetN return rowsWritten.FirstOrDefault(); } -#if NET var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.SequentialScan); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.SequentialScan); -#endif + return await InsertSheetAsync(stream, value, sheetName, printHeader, overwriteSheet, configuration, progress, cancellationToken).ConfigureAwait(false); } @@ -130,16 +127,11 @@ public async Task 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 NET var inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.RandomAccess); await using var disposableInputStream = inputStream.ConfigureAwait(false); var outputStream = new FileStream(outputFile, overwriteFile ? FileMode.Create : FileMode.CreateNew, FileAccess.Write, FileShare.None, 4096, FileOptions.SequentialScan); await using var disposableOutputStream = outputStream.ConfigureAwait(false); - #else - using var inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.RandomAccess); - using var outputStream = new FileStream(outputFile, mode: overwriteFile ? FileMode.Create : FileMode.CreateNew, FileAccess.Write, FileShare.None, 4096, FileOptions.SequentialScan); - #endif return await CopyAndAddSheetAsync(inputStream, outputStream, value, sheetName, printHeader, overwriteSheet, configuration, progress, cancellationToken).ConfigureAwait(false); } @@ -164,12 +156,9 @@ public async Task ExportAsync(string path, object value, bool printHeader if (Path.GetExtension(path).Equals(".xlsm", StringComparison.InvariantCultureIgnoreCase)) throw new NotSupportedException("MiniExcel's Export does not support the .xlsm format"); -#if NET var stream = overwriteFile ? File.Create(path) : new FileStream(path, FileMode.CreateNew); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = overwriteFile ? File.Create(path) : new FileStream(path, FileMode.CreateNew); -#endif + return await ExportAsync(stream, value, printHeader, sheetName, configuration, progress, cancellationToken).ConfigureAwait(false); } @@ -210,12 +199,9 @@ public async Task ExportAsync(Stream stream, object value, bool printHead [CreateSyncVersion] public async Task AlterSheetAsync(string path, string sheetName, string? newSheetName = null, int? newSheetIndex = null, SheetState? newSheetState = null, CancellationToken cancellationToken = default) { -#if NET var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); -#endif + await AlterSheetAsync(stream, sheetName, newSheetName, newSheetIndex, newSheetState, cancellationToken).ConfigureAwait(false); } diff --git a/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs b/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs index f434f9dd..79481b76 100644 --- a/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs +++ b/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs @@ -14,12 +14,9 @@ public async IAsyncEnumerable QueryAsync(string path, string? sheetName = string startCell = "A1", bool treatHeaderAsData = false, OpenXmlConfiguration? configuration = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) where T : class, new() { -#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = FileHelper.OpenSharedRead(path); -#endif + var query = QueryAsync(stream, sheetName, startCell, treatHeaderAsData, configuration, cancellationToken); await foreach (var item in query.ConfigureAwait(false)) @@ -41,12 +38,8 @@ public async IAsyncEnumerable QueryAsync(string path, bool useHeaderRow string? sheetName = null, string startCell = "A1", OpenXmlConfiguration? configuration = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { -#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = FileHelper.OpenSharedRead(path); -#endif await foreach (var item in QueryAsync(stream, useHeaderRow, sheetName, startCell, configuration, cancellationToken).ConfigureAwait(false)) yield return item; @@ -79,12 +72,9 @@ public async IAsyncEnumerable QueryRangeAsync(string path, bool useHead string? sheetName = null, string startCell = "A1", string endCell = "", OpenXmlConfiguration? configuration = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { -#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = FileHelper.OpenSharedRead(path); -#endif + await foreach (var item in QueryRangeAsync(stream, useHeaderRow, sheetName, startCell, endCell, configuration, cancellationToken).ConfigureAwait(false)) yield return item; } @@ -105,12 +95,9 @@ public async IAsyncEnumerable QueryRangeAsync(string path, bool useHead int? endColumnIndex = null, OpenXmlConfiguration? configuration = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { -#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = FileHelper.OpenSharedRead(path); -#endif + await foreach (var item in QueryRangeAsync(stream, useHeaderRow, sheetName, startRowIndex, startColumnIndex, endRowIndex, endColumnIndex, configuration, cancellationToken).ConfigureAwait(false)) yield return item; } @@ -138,12 +125,9 @@ public async Task QueryAsDataTableAsync(string path, bool useHeaderRo string? sheetName = null, string startCell = "A1", OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = FileHelper.OpenSharedRead(path); -#endif + return await QueryAsDataTableAsync(stream, useHeaderRow, sheetName, startCell, configuration, cancellationToken).ConfigureAwait(false); } @@ -208,12 +192,9 @@ public async Task QueryAsDataTableAsync(Stream stream, bool useHeader [CreateSyncVersion] public async Task> GetSheetNamesAsync(string path, OpenXmlConfiguration? config = null, CancellationToken cancellationToken = default) { -#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = FileHelper.OpenSharedRead(path); -#endif + return await GetSheetNamesAsync(stream, config, cancellationToken).ConfigureAwait(false); } @@ -233,12 +214,9 @@ public async Task> GetSheetNamesAsync(Stream stream, OpenXmlConfigu [CreateSyncVersion] public async Task> GetSheetInformationsAsync(string path, OpenXmlConfiguration? config = null, CancellationToken cancellationToken = default) { -#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = FileHelper.OpenSharedRead(path); -#endif + return await GetSheetInformationsAsync(stream, config, cancellationToken).ConfigureAwait(false); } @@ -258,12 +236,9 @@ public async Task> GetSheetInformationsAsync(Stream stream, Open [CreateSyncVersion] public async Task> GetSheetDimensionsAsync(string path, CancellationToken cancellationToken = default) { -#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = FileHelper.OpenSharedRead(path); -#endif + return await GetSheetDimensionsAsync(stream, cancellationToken).ConfigureAwait(false); } @@ -279,12 +254,9 @@ public async Task> GetColumnNamesAsync(string path, bool use string? sheetName = null, string startCell = "A1", OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = FileHelper.OpenSharedRead(path); -#endif + return await GetColumnNamesAsync(stream, useHeaderRow, sheetName, startCell, configuration, cancellationToken).ConfigureAwait(false); } @@ -305,12 +277,9 @@ public async Task> GetColumnNamesAsync(Stream stream, bool u [CreateSyncVersion] public async Task RetrieveCommentsAsync(string path, string? sheetName, CancellationToken cancellationToken = default) { -#if NET var stream = FileHelper.OpenSharedRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = FileHelper.OpenSharedRead(path); -#endif + return await RetrieveCommentsAsync(stream, sheetName, cancellationToken).ConfigureAwait(false); } diff --git a/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs b/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs index 77e5b2b0..61932cdc 100644 --- a/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs +++ b/src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs @@ -12,12 +12,9 @@ internal OpenXmlTemplater() { } [CreateSyncVersion] public async Task AddPictureAsync(string path, CancellationToken cancellationToken = default, params MiniExcelPicture[] images) { -#if NET var stream = File.Open(path, FileMode.OpenOrCreate); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = File.Open(path, FileMode.OpenOrCreate); -#endif + await MiniExcelPictureImplement.AddPictureAsync(stream, cancellationToken, images).ConfigureAwait(false); } @@ -31,12 +28,9 @@ public async Task AddPictureAsync(Stream excelStream, CancellationToken cancella public async Task FillTemplateAsync(string path, string templatePath, object value, bool overwriteFile = false, OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET var stream = overwriteFile ? File.Create(path) : File.Open(path, FileMode.CreateNew); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = overwriteFile ? File.Create(path) : File.Open(path, FileMode.CreateNew); -#endif + await FillTemplateAsync(stream, templatePath, value, configuration, cancellationToken).ConfigureAwait(false); } @@ -44,12 +38,8 @@ public async Task FillTemplateAsync(string path, string templatePath, object val public async Task FillTemplateAsync(string path, Stream templateStream, object value, bool overwriteFile = false, OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET var stream = overwriteFile ? File.Create(path) : File.Open(path, FileMode.CreateNew); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = overwriteFile ? File.Create(path) : File.Open(path, FileMode.CreateNew); -#endif var template = GetOpenXmlTemplate(stream, configuration); await template.SaveAsByTemplateAsync(templateStream, value, cancellationToken).ConfigureAwait(false); @@ -75,12 +65,9 @@ public async Task FillTemplateAsync(Stream stream, Stream templateStream, object public async Task FillTemplateAsync(string path, byte[] templateBytes, object value, bool overwriteFile = false, OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET var stream = overwriteFile ? File.Create(path) : File.Open(path, FileMode.CreateNew); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = overwriteFile ? File.Create(path) : File.Open(path, FileMode.CreateNew); -#endif + await FillTemplateAsync(stream, templateBytes, value, configuration, cancellationToken).ConfigureAwait(false); } @@ -98,12 +85,9 @@ public async Task FillTemplateAsync(Stream stream, byte[] templateBytes, object public async Task MergeSameCellsAsync(string mergedFilePath, string path, OpenXmlConfiguration? configuration = null, CancellationToken cancellationToken = default) { -#if NET var stream = File.Create(mergedFilePath); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = File.Create(mergedFilePath); -#endif + await MergeSameCellsAsync(stream, path, configuration, cancellationToken).ConfigureAwait(false); } diff --git a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingExporter.cs b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingExporter.cs index 39f9ae95..855dc066 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingExporter.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingExporter.cs @@ -19,12 +19,8 @@ public async Task ExportAsync(string path, IEnumerable? values, bool overw { var filePath = path.EndsWith(".xlsx", StringComparison.InvariantCultureIgnoreCase) ? path : $"{path}.xlsx" ; -#if NET var stream = overwriteFile ? File.Create(filePath) : new FileStream(filePath, FileMode.CreateNew); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = overwriteFile ? File.Create(filePath) : new FileStream(filePath, FileMode.CreateNew); -#endif await ExportAsync(stream, values, cancellationToken).ConfigureAwait(false); } diff --git a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingImporter.cs b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingImporter.cs index 9aa8d960..affafd18 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingImporter.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingImporter.cs @@ -12,12 +12,8 @@ public MappingImporter(MappingRegistry registry) : this() [CreateSyncVersion] public async IAsyncEnumerable QueryAsync(string path, [EnumeratorCancellation] CancellationToken cancellationToken = default) where T : class, new() { - #if NET var stream = File.OpenRead(path); await using var disposableStream = stream.ConfigureAwait(false); - #else - using var stream = File.OpenRead(path); - #endif await foreach (var item in QueryAsync(stream, cancellationToken).ConfigureAwait(false)) yield return item; @@ -39,12 +35,9 @@ public MappingImporter(MappingRegistry registry) : this() [CreateSyncVersion] public async Task QuerySingleAsync(string path, CancellationToken cancellationToken = default) where T : class, new() { -#if NET var stream = File.OpenRead(path); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = File.OpenRead(path); -#endif + return await QuerySingleAsync(stream, cancellationToken).ConfigureAwait(false); } @@ -64,4 +57,4 @@ public MappingImporter(MappingRegistry registry) : this() throw new InvalidOperationException("No data found."); } -} \ No newline at end of file +} diff --git a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingTemplater.cs b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingTemplater.cs index 0df0e110..cb32fa2b 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Api/MappingTemplater.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Api/MappingTemplater.cs @@ -23,16 +23,12 @@ public async Task FillTemplateAsync( if (values is null) throw new ArgumentNullException(nameof(values)); -#if NET var outputStream = File.Create(outputPath); await using var disposableOutputStream = outputStream.ConfigureAwait(false); var templateStream = File.OpenRead(templatePath); await using var disposableTemplateStream = templateStream.ConfigureAwait(false); -#else - using var outputStream = File.Create(outputPath); - using var templateStream = File.OpenRead(templatePath); -#endif + await FillTemplateAsync(outputStream, templateStream, values, cancellationToken).ConfigureAwait(false); } @@ -73,12 +69,9 @@ public async Task FillTemplateAsync( if (values is null) throw new ArgumentNullException(nameof(values)); -#if NET var templateStream = new MemoryStream(templateBytes); await using var disposableTemplateStream = templateStream.ConfigureAwait(false); -#else - using var templateStream = new MemoryStream(templateBytes); -#endif + await FillTemplateAsync(outputStream, templateStream, values, cancellationToken).ConfigureAwait(false); } @@ -115,3 +108,4 @@ public Task ApplyTemplateAsync( } #endregion } + diff --git a/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs b/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs index dd0d46f2..378cc357 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs @@ -113,20 +113,13 @@ private static async Task CopyEntryAsync( targetEntry.LastWriteTime = sourceEntry.LastWriteTime; // Copy content -#if NET var sourceStream = await sourceEntry.OpenAsync(cancellationToken).ConfigureAwait(false); - var targetStream = await targetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); - await using var disposableSourceStream = sourceStream.ConfigureAwait(false); - await using var disposableTargetStream = targetStream.ConfigureAwait(false); - await sourceStream.CopyToAsync(targetStream, cancellationToken).ConfigureAwait(false); -#else - using var sourceStream = sourceEntry.Open(); - using var targetStream = targetEntry.Open(); + var targetStream = await targetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); + await using var disposableTargetStream = targetStream.ConfigureAwait(false); - await sourceStream.CopyToAsync(targetStream).ConfigureAwait(false); -#endif + await sourceStream.CopyToAsync(targetStream, 81920, cancellationToken).ConfigureAwait(false); } [CreateSyncVersion] @@ -143,16 +136,11 @@ private static async Task ProcessWorksheetAsync( targetEntry.LastWriteTime = sourceEntry.LastWriteTime; // Open streams -#if NET var sourceStream = await sourceEntry.OpenAsync(cancellationToken).ConfigureAwait(false); - var targetStream = await targetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); - await using var disposableSourceStream = sourceStream.ConfigureAwait(false); + + var targetStream = await targetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableTargetStream = targetStream.ConfigureAwait(false); -#else - using var sourceStream = sourceEntry.Open(); - using var targetStream = targetEntry.Open(); -#endif // Create processor for this worksheet var processor = new MappingTemplateProcessor(mapping); diff --git a/src/MiniExcel.OpenXml/OpenXmlReader.cs b/src/MiniExcel.OpenXml/OpenXmlReader.cs index 7ffffe3e..86a9990c 100644 --- a/src/MiniExcel.OpenXml/OpenXmlReader.cs +++ b/src/MiniExcel.OpenXml/OpenXmlReader.cs @@ -178,12 +178,9 @@ internal static async Task CreateAsync(Stream stream, IMiniExcelC maxColumnIndex = endColumnIndex.Value; } -#if NET var sheetStream = await sheetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); -#else - using var sheetStream = sheetEntry.Open(); -#endif + using var reader = XmlReader.Create(sheetStream, xmlSettings); if (!reader.IsStartElement("worksheet", Ns)) @@ -417,13 +414,10 @@ private async Task SetSharedStringsAsync(CancellationToken cancellationToken = d if (Archive.GetEntry(ExcelFileNames.SharedStrings) is not { } sharedStringsEntry) return; - var idx = 0; -#if NET var stream = await sharedStringsEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = sharedStringsEntry.Open(); -#endif + + var idx = 0; if (_config.EnableSharedStringCache && sharedStringsEntry.Length >= _config.SharedStringCacheSize) { SharedStrings = new SharedStringsDiskCache(_config.SharedStringCachePath); @@ -459,12 +453,9 @@ private static async IAsyncEnumerable ReadWorkbookAsync(ReadOnlyCol ); var entry = entries.Single(w => w.FullName == ExcelFileNames.Workbook); -#if NET var stream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = entry.Open(); -#endif + using var reader = XmlReader.Create(stream, xmlSettings); if (!reader.IsStartElement("workbook", Ns)) @@ -522,7 +513,7 @@ await reader.SkipAsync() sheetCount++; await reader.SkipAsync() #if NET - .WaitAsync(cancellationToken) + .WaitAsync(cancellationToken) #endif .ConfigureAwait(false); } @@ -556,12 +547,9 @@ await reader.SkipAsync() var entry = entries.Single(w => w.FullName == ExcelFileNames.WorkbookRels); -#if NET var stream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = entry.Open(); -#endif + using var reader = XmlReader.Create(stream, xmlSettings); if (!XmlReaderHelper.IsStartElement(reader, "Relationships", Schemas.OpenXmlPackageRelationships)) @@ -758,12 +746,8 @@ internal async Task> GetDimensionsAsync(CancellationToken canc var withoutCr = false; -#if NET var crSheetStream = await sheet.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableCrSheetStream = crSheetStream.ConfigureAwait(false); -#else - using var crSheetStream = sheet.Open(); -#endif using (var reader = XmlReader.Create(crSheetStream, xmlSettings)) { while (await reader.ReadAsync().ConfigureAwait(false)) @@ -811,12 +795,9 @@ internal async Task> GetDimensionsAsync(CancellationToken canc if (withoutCr) { -#if NET var sheetStream = await sheet.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); -#else - using var sheetStream = sheet.Open(); -#endif + using var reader = XmlReader.Create(sheetStream, xmlSettings); if (!reader.IsStartElement("worksheet", Ns)) @@ -911,12 +892,8 @@ internal static async Task TryGetMaxRowColumnIndexAs int maxRowIndex = -1; int maxColumnIndex = -1; -#if NET var crSheetStream = await sheetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableCrSheetStream = crSheetStream.ConfigureAwait(false); -#else - using var crSheetStream = sheetEntry.Open(); -#endif using (var reader = XmlReader.Create(crSheetStream, xmlSettings)) { while (await reader.ReadAsync() @@ -966,12 +943,9 @@ internal static async Task TryGetMaxRowColumnIndexAs if (withoutCr) { -#if NET var sheetStream = await sheetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); -#else - using var sheetStream = sheetEntry.Open(); -#endif + using var reader = XmlReader.Create(sheetStream, xmlSettings); if (!reader.IsStartElement("worksheet", Ns)) @@ -1046,12 +1020,9 @@ internal static async Task TryGetMergeCellsAsync(ZipArchiveEntry sheetEntr ); var mergeCells = new MergeCells(); -#if NET var sheetStream = await sheetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); -#else - using var sheetStream = sheetEntry.Open(); -#endif + using var reader = XmlReader.Create(sheetStream, xmlSettings); if (!reader.IsStartElement("worksheet", Ns)) @@ -1123,12 +1094,8 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance List people = []; if (Archive.GetEntry(ExcelFileNames.Person) is { } persons) { -#if NET var personStream = await persons.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposablePersonStream = personStream.ConfigureAwait(false); -#else - using var personStream = persons.Open(); -#endif var personDoc = await XDocument.LoadAsync(personStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var personElements = personDoc.Root?.Elements(ns18Tc + "person"); @@ -1145,12 +1112,9 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance if (Archive.GetEntry($"xl/worksheets/_rels/{sheetFile}.rels") is not { } rel) return new CommentResultSet(sheetName, [], []); -#if NET var stream = await rel.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = rel.Open(); -#endif + var relDoc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var threadedCommentRels = relDoc.Root?.Elements(nsRel + "Relationship"); @@ -1168,12 +1132,9 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance HashSet refCells = []; if (Archive.GetEntry($"xl/{threadedCommentsPath}") is { } threadEntry) { -#if NET var threadEntryStream = await threadEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableThreadEntryStream = threadEntryStream.ConfigureAwait(false); -#else - using var threadEntryStream = threadEntry.Open(); -#endif + var doc = await XDocument.LoadAsync(threadEntryStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var commentThreadElements = doc.Root?.Elements(ns18Tc + "threadedComment"); @@ -1216,12 +1177,9 @@ internal async Task ReadCommentsAsync(string? sheetName, Cance if (Archive.GetEntry($"xl/{notesPath}") is { } noteEntry) { -#if NET var noteEntryStream = await noteEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableNoteEntryStream = noteEntryStream.ConfigureAwait(false); -#else - using var noteEntryStream = noteEntry.Open(); -#endif + var doc = await XDocument.LoadAsync(noteEntryStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var authorElements = doc.Root?.Element(nsMain + "authors")?.Elements(nsMain + "author"); @@ -1283,12 +1241,9 @@ internal async IAsyncEnumerable QueryMappedAsync( Async = true }; -#if NET var sheetStream = await sheetEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); -#else - using var sheetStream = sheetEntry.Open(); -#endif + using var reader = XmlReader.Create(sheetStream, xmlSettings); if (!reader.IsStartElement("worksheet", Ns)) diff --git a/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs b/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs index 95430518..a6220c54 100644 --- a/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs +++ b/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs @@ -137,12 +137,11 @@ public static async Task AddPictureAsync(Stream excelStream, CancellationToken c var imagePath = $"xl/media/{imageName}"; var imageEntry = archive.CreateEntry(imagePath); -#if NET var entryStream = await imageEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = entryStream.ConfigureAwait(false); +#if NET await entryStream.WriteAsync(imageBytes.AsMemory(), cancellationToken).ConfigureAwait(false); #else - using var entryStream = imageEntry.Open(); await entryStream.WriteAsync(imageBytes, 0, imageBytes.Length, cancellationToken).ConfigureAwait(false); #endif diff --git a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs index ad80b786..00bb239d 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs @@ -49,13 +49,10 @@ public async Task CreateAsync(SheetStyleElementInfos generatedElementInfos, Canc if (styleEntry is not null) { -#if NET var oldStyleXmlStream = await styleEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = oldStyleXmlStream.ConfigureAwait(false); -#else - using var oldStyleXmlStream = styleEntry.Open(); -#endif using var reader = XmlReader.Create(oldStyleXmlStream, XmlReaderHelper.GetXmlReaderSettings(isAsync)); + infos = await ReadSheetStyleElementInfosAsync(reader, cancellationToken).ConfigureAwait(false); } else @@ -88,22 +85,14 @@ public async Task InitializeAsync(SheetStyleElementInfos generatedElementInfos, var xmlReaderSettings = XmlReaderHelper.GetXmlReaderSettings(isAsync); if (_oldStyleXmlZipEntry is not null) { -#if NET var oldStyleXmlStream = await _oldStyleXmlZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using (_ = oldStyleXmlStream.ConfigureAwait(false)) -#else - using (var oldStyleXmlStream = _oldStyleXmlZipEntry.Open()) -#endif { using var reader = XmlReader.Create(oldStyleXmlStream, xmlReaderSettings); OldElementInfos = await ReadSheetStyleElementInfosAsync(reader, cancellationToken).ConfigureAwait(false); } -#if NET _oldXmlReaderStream = await _oldStyleXmlZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); -#else - _oldXmlReaderStream = _oldStyleXmlZipEntry.Open(); -#endif OldXmlReader = XmlReader.Create(_oldXmlReaderStream, xmlReaderSettings); _newStyleXmlZipEntry = _archive.CreateEntry(ExcelFileNames.Styles + ".temp", CompressionLevel.Fastest); } @@ -116,11 +105,7 @@ public async Task InitializeAsync(SheetStyleElementInfos generatedElementInfos, _newStyleXmlZipEntry = _archive.CreateEntry(ExcelFileNames.Styles, CompressionLevel.Fastest); } -#if NET _newXmlWriterStream = await _newStyleXmlZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); -#else - _newXmlWriterStream = _newStyleXmlZipEntry.Open(); -#endif NewXmlWriter = XmlWriter.Create(_newXmlWriterStream, new XmlWriterSettings { Indent = true, Encoding = _encoding, Async = isAsync }); _initialized = true; @@ -145,23 +130,18 @@ public async Task FinalizeAndUpdateZipDictionaryAsync(CancellationToken cancella { OldXmlReader?.Dispose(); OldXmlReader = null; -#if NET if (_oldXmlReaderStream is not null) { await _oldXmlReaderStream.DisposeAsync().ConfigureAwait(false); } -#else - _oldXmlReaderStream?.Dispose(); -#endif await NewXmlWriter!.FlushAsync().ConfigureAwait(false); #if NET await NewXmlWriter.DisposeAsync().ConfigureAwait(false); - await _newXmlWriterStream!.DisposeAsync().ConfigureAwait(false); #else NewXmlWriter.Dispose(); - _newXmlWriterStream?.Dispose(); #endif + await _newXmlWriterStream!.DisposeAsync().ConfigureAwait(false); NewXmlWriter = null; _newXmlWriterStream = null; @@ -175,16 +155,12 @@ public async Task FinalizeAndUpdateZipDictionaryAsync(CancellationToken cancella _oldStyleXmlZipEntry = null; var finalStyleXmlZipEntry = _archive.CreateEntry(ExcelFileNames.Styles, CompressionLevel.Fastest); -#if NET var tempStream = await _newStyleXmlZipEntry!.OpenAsync(cancellationToken).ConfigureAwait(false); - var newStream = await finalStyleXmlZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); - await using (_ = tempStream.ConfigureAwait(false)) - await using (_= newStream.ConfigureAwait(false)) -#else - using (var tempStream = _newStyleXmlZipEntry!.Open()) - using (var newStream = finalStyleXmlZipEntry.Open()) -#endif + await using (var disposableTempStream = tempStream.ConfigureAwait(false)) { + var newStream = await finalStyleXmlZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); + await using var disposableNewStream = newStream.ConfigureAwait(false); + await tempStream.CopyToAsync(newStream, 4096, cancellationToken).ConfigureAwait(false); } diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs index 837871fc..4d4aacf4 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs @@ -45,11 +45,7 @@ internal partial class OpenXmlTemplate private async Task GenerateSheetByUpdateModeAsync(ZipArchiveEntry sheetZipEntry, Stream stream, Stream sheetStream, IDictionary inputMaps, IDictionary sharedStrings, bool mergeCells = false, CancellationToken cancellationToken = default) { var doc = await XDocument.LoadAsync(sheetStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); -#if NET await sheetStream.DisposeAsync().ConfigureAwait(false); -#else - sheetStream.Dispose(); -#endif // we can't update ZipArchiveEntry directly, so we delete the original entry and recreate it sheetZipEntry.Delete(); @@ -76,12 +72,8 @@ private async Task GenerateSheetByUpdateModeAsync(ZipArchiveEntry sheetZipEntry, [CreateSyncVersion] private async Task GenerateSheetByCreateModeAsync(ZipArchiveEntry templateSheetZipEntry, Stream outputZipSheetEntryStream, IDictionary inputMaps, IDictionary sharedStrings, bool mergeCells = false, CancellationToken cancellationToken = default) { -#if NET var newTemplateStream = await templateSheetZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableNewTemplateStream = newTemplateStream.ConfigureAwait(false); -#else - using var newTemplateStream = templateSheetZipEntry.Open(); -#endif var doc = await XDocument.LoadAsync(newTemplateStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var worksheet = doc.Element(SpreadsheetNs + "worksheet"); diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs index f7e5a4f8..26eb58a6 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs @@ -7,24 +7,18 @@ internal partial class OpenXmlTemplate [CreateSyncVersion] public async Task MergeSameCellsAsync(string path, CancellationToken cancellationToken = default) { -#if NETSTANDARD2_0 - using var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); -#else var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); await using var disposableStream = stream.ConfigureAwait(false); -#endif + await MergeSameCellsImplAsync(stream, cancellationToken).ConfigureAwait(false); } [CreateSyncVersion] public async Task MergeSameCellsAsync(byte[] fileInBytes, CancellationToken cancellationToken = default) { -#if NETSTANDARD2_0 - using var stream = new MemoryStream(fileInBytes); -#else var stream = new MemoryStream(fileInBytes); await using var disposableStream = stream.ConfigureAwait(false); -#endif + await MergeSameCellsImplAsync(stream, cancellationToken).ConfigureAwait(false); } @@ -59,16 +53,11 @@ await stream.CopyToAsync(_outputFileStream var entry = archive.ZipFile.CreateEntry(sheet.FullName); -#if NET var sheetStream = await sheet.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetStream = sheetStream.ConfigureAwait(false); var zipStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableZipStream = zipStream.ConfigureAwait(false); -#else - using var sheetStream = sheet.Open(); - using var zipStream = entry.Open(); -#endif await GenerateSheetByUpdateModeAsync(sheet, zipStream, sheetStream, new Dictionary(), sharedStrings, mergeCells: true, cancellationToken).ConfigureAwait(false); } diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs index 41e70076..fce1e092 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs @@ -21,24 +21,18 @@ internal OpenXmlTemplate(Stream stream, IMiniExcelConfiguration? configuration, [CreateSyncVersion] public async Task SaveAsByTemplateAsync(string templatePath, object value, CancellationToken cancellationToken = default) { -#if NET var stream = File.Open(templatePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = File.Open(templatePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); -#endif + await SaveAsByTemplateAsync(stream, value, cancellationToken).ConfigureAwait(false); } [CreateSyncVersion] public async Task SaveAsByTemplateAsync(byte[] templateBytes, object value, CancellationToken cancellationToken = default) { -#if NET var stream = new MemoryStream(templateBytes); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = new MemoryStream(templateBytes); -#endif + await SaveAsByTemplateAsync(stream, value, cancellationToken).ConfigureAwait(false); } @@ -91,16 +85,11 @@ public async Task SaveAsByTemplateAsync(Stream templateStream, object value, Can var newEntry = outputFileArchive.ZipFile.CreateEntry(entry.FullName); // Copy the content of the original entry to the new entry -#if NET var originalEntryStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableEntryStream = originalEntryStream.ConfigureAwait(false); var newEntryStream = await newEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableNewEntryStream = newEntryStream.ConfigureAwait(false); -#else - using var originalEntryStream = entry.Open(); - using var newEntryStream = newEntry.Open(); -#endif await originalEntryStream.CopyToAsync(newEntryStream #if NET @@ -132,12 +121,8 @@ await originalEntryStream.CopyToAsync(newEntryStream var inputValues = _inputValueExtractor.ToValueDictionary(value); var outputZipEntry = outputFileArchive.ZipFile.CreateEntry(templateFullName); -#if NET var outputZipSheetEntryStream = await outputZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableSheetEntryStream = outputZipSheetEntryStream.ConfigureAwait(false); -#else - using var outputZipSheetEntryStream = outputZipEntry.Open(); -#endif await GenerateSheetByCreateModeAsync(templateSheet, outputZipSheetEntryStream, inputValues, templateSharedStrings, cancellationToken: cancellationToken).ConfigureAwait(false); @@ -154,13 +139,10 @@ await originalEntryStream.CopyToAsync(newEntryStream if (calcChain is not null) { -#if NET var calcChainEntry = outputFileArchive.ZipFile.CreateEntry(calcChain.FullName); var calcChainStream = await calcChainEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableChainEntryStream = calcChainStream.ConfigureAwait(false); -#else - using var calcChainStream = calcChainEntry.Open(); -#endif + await CalcChainHelper.GenerateCalcChainSheetAsync(calcChainStream, _calcChainContent.ToString(), cancellationToken).ConfigureAwait(false); } else @@ -172,16 +154,11 @@ await originalEntryStream.CopyToAsync(newEntryStream var newEntry = outputFileArchive.ZipFile.CreateEntry(entry.FullName); // Copy the content of the original entry to the new entry -#if NET var originalEntryStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableEntryStream = originalEntryStream.ConfigureAwait(false); var newEntryStream = await newEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableNewEntryStream = newEntryStream.ConfigureAwait(false); -#else - using var originalEntryStream = entry.Open(); - using var newEntryStream = newEntry.Open(); -#endif await originalEntryStream.CopyToAsync(newEntryStream #if NET diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs index d75ee34b..71e80b59 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs @@ -116,15 +116,10 @@ public async Task CopyAndInsertAsync(bool overwriteSheet = false, IProgress { var newStylesEntry = _archive.CreateEntry(ExcelFileNames.Styles, CompressionLevel.Fastest); var newStylesEntryStream = await newStylesEntry.OpenAsync(cancellationToken).ConfigureAwait(false); - var tempStylesEntryStream = await tempStylesEntry.OpenAsync(cancellationToken).ConfigureAwait(false); - -#if NET await using var disposableNewStylesEntryStream = newStylesEntryStream.ConfigureAwait(false); + + var tempStylesEntryStream = await tempStylesEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableTempStylesEntryStream = tempStylesEntryStream.ConfigureAwait(false); -#else - using var disposableNewStylesEntryStream = newStylesEntryStream; - using var disposableTempStylesEntryStream = tempStylesEntryStream; -#endif await tempStylesEntryStream.CopyToAsync(newStylesEntryStream, 81920, cancellationToken).ConfigureAwait(false); await newStylesEntryStream.FlushAsync(cancellationToken).ConfigureAwait(false); @@ -218,16 +213,11 @@ private async Task CopyEntryAsync(ZipArchiveEntry entry, CancellationToken cance { var newEntry = _archive.CreateEntry(entry.FullName, CompressionLevel.Fastest); -#if NET var oldEntryStream = await _oldArchive!.GetEntry(entry.FullName)!.OpenAsync(cancellationToken).ConfigureAwait(false); await using var oldDisposableSheetStream = oldEntryStream.ConfigureAwait(false); var newEntryStream = await newEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var newDisposableSheetStream = newEntryStream.ConfigureAwait(false); -#else - using var oldEntryStream = await _oldArchive!.GetEntry(entry.FullName)!.OpenAsync(cancellationToken).ConfigureAwait(false); - using var newEntryStream = await newEntry.OpenAsync(cancellationToken).ConfigureAwait(false); -#endif await oldEntryStream.CopyToAsync(newEntryStream, 81920, cancellationToken).ConfigureAwait(false); await newEntryStream.FlushAsync(cancellationToken).ConfigureAwait(false); @@ -243,14 +233,10 @@ private async Task CopyAndUpdateContentTypesAsync(CancellationToken cancellation return; } -#if NET var stream = await contentTypesZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = contentTypesZipEntry.Open(); -#endif - var doc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); + var doc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var ns = doc.Root!.GetDefaultNamespace(); var typesElement = doc.Descendants(ns + "Types").Single(); @@ -275,11 +261,8 @@ private async Task CopyAndUpdateContentTypesAsync(CancellationToken cancellation var contentTypesEntry = _archive.CreateEntry(ExcelFileNames.ContentTypes, CompressionLevel.Fastest); var contentTypesEntryStream = await contentTypesEntry.OpenAsync(cancellationToken).ConfigureAwait(false); -#if NET await using var disposableContetTypesEntryStream = contentTypesEntryStream.ConfigureAwait(false); -#else - using var disposableContetTypesEntryStream = contentTypesEntryStream; -#endif + await doc.SaveAsync(contentTypesEntryStream, SaveOptions.None, cancellationToken).ConfigureAwait(false); } @@ -306,11 +289,7 @@ public async ValueTask DisposeAsync() #else Archive.Dispose(); #endif -#if NET await _backingStream.DisposeAsync().ConfigureAwait(false); -#else - _backingStream.Dispose(); -#endif } } } diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs index 89fe564a..9eee4a12 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs @@ -176,12 +176,8 @@ private async Task CreateSheetXmlAsync(object? values, string sheetPath, IP var entry = _archive.CreateEntry(sheetPath, CompressionLevel.Fastest); var rowsWritten = 0; -#if NET var zipStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableZipStream = zipStream.ConfigureAwait(false); -#else - using var zipStream = entry.Open(); -#endif var writer = new MiniExcelStreamWriter(zipStream, Utf8WithBom, _configuration.BufferSize); await using var disposableWriter = writer.ConfigureAwait(false); @@ -500,12 +496,12 @@ private async Task AddFilesToZipAsync(CancellationToken cancellationToken) var entry = _archive.CreateEntry(item.Path, CompressionLevel.Fastest); -#if NET var zipStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableZipStream = zipStream.ConfigureAwait(false); + +#if NET await zipStream.WriteAsync(item.Contents, cancellationToken).ConfigureAwait(false); #else - using var zipStream = entry.Open(); await zipStream.WriteAsync(item.Contents, 0, item.Contents.Length, cancellationToken).ConfigureAwait(false); #endif } @@ -632,12 +628,8 @@ private async Task InsertContentTypesXmlAsync(CancellationToken cancellationToke return; } -#if NET var stream = await contentTypesZipEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableStream = stream.ConfigureAwait(false); -#else - using var stream = contentTypesZipEntry.Open(); -#endif var doc = await XDocument.LoadAsync(stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var ns = doc.Root!.GetDefaultNamespace(); @@ -673,12 +665,8 @@ private async Task CreateZipEntryAsync(string path, string? contentType, string var entry = _archive.CreateEntry(path, CompressionLevel.Fastest); -#if NET var zipStream = await entry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableZipStream = zipStream.ConfigureAwait(false); -#else - using var zipStream = entry.Open(); -#endif var writer = new MiniExcelStreamWriter(zipStream, Utf8WithBom, _configuration.BufferSize); await using var disposableWriter = writer.ConfigureAwait(false); @@ -707,6 +695,7 @@ internal async Task AlterWorksheetAsync(string sheetName, string? newSheetName, var newZipStream = await newWorkbookEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var newDisposableZipStream = newZipStream.ConfigureAwait(false); +#if NET var writer = XmlWriter.Create(newZipStream, new XmlWriterSettings { #if !SYNC_ONLY @@ -716,7 +705,6 @@ internal async Task AlterWorksheetAsync(string sheetName, string? newSheetName, await using var disposableWriter = writer.ConfigureAwait(false); await xmlDoc.WriteToAsync(writer, CancellationToken.None).ConfigureAwait(false); #else - using var newZipStream = newWorkbookEntry.Open(); using var writer = XmlWriter.Create(newZipStream, new XmlWriterSettings { Async = false }); xmlDoc.WriteTo(writer); #endif @@ -733,12 +721,8 @@ internal async Task AlterWorksheetAsync(string sheetName, string? newSheetName, async Task LoadWorkbook() { -#if NET var zipStream = await oldWorkbookEntry.OpenAsync(cancellationToken).ConfigureAwait(false); await using var disposableZipStream = zipStream.ConfigureAwait(false); -#else - using var zipStream = oldWorkbookEntry.Open(); -#endif var workbookDoc = await XDocument.LoadAsync(zipStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); var sheetsContainer = workbookDoc.Root?.Element((XNamespace)Schemas.SpreadsheetmlXmlMain + "sheets")!; From 545adbedd2439264e045acb435c7217005a3b8dd Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Sun, 24 May 2026 00:59:02 +0200 Subject: [PATCH 11/12] Added more global usings directives and renamed OpenXmlWriter.DefaultOpenXml to OpenXmlWriter.XmlGeneration --- src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs | 2 +- src/MiniExcel.OpenXml/Api/ProviderExtensions.cs | 2 +- src/MiniExcel.OpenXml/Constants/WorksheetXml.cs | 4 +--- .../FluentMapping/Api/ProviderExtensions.cs | 2 -- src/MiniExcel.OpenXml/FluentMapping/CompiledMapping.cs | 2 -- .../Configuration/CollectionMappingBuilder.cs | 1 - .../Configuration/ICollectionMappingBuilder.cs | 2 -- .../FluentMapping/Configuration/IMappingConfiguration.cs | 3 --- .../FluentMapping/Configuration/MappingConfiguration.cs | 3 --- .../FluentMapping/Helpers/ConversionHelper.cs | 1 - .../FluentMapping/Helpers/MappingMetadataExtractor.cs | 1 - src/MiniExcel.OpenXml/FluentMapping/MappingCellStream.cs | 1 - src/MiniExcel.OpenXml/FluentMapping/MappingCompiler.cs | 2 -- src/MiniExcel.OpenXml/FluentMapping/MappingReader.cs | 1 - .../FluentMapping/MappingTemplateApplicator.cs | 2 -- src/MiniExcel.OpenXml/FluentMapping/NestedMappingInfo.cs | 2 -- src/MiniExcel.OpenXml/GlobalUsings.cs | 7 +++++++ src/MiniExcel.OpenXml/Models/SheetDto.cs | 4 +--- src/MiniExcel.OpenXml/OpenXmlConfiguration.cs | 1 - src/MiniExcel.OpenXml/OpenXmlReader.cs | 3 --- src/MiniExcel.OpenXml/Picture/OpenXmlPicture.cs | 1 - src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs | 2 -- .../Styles/Builder/DefaultSheetStyleBuilder.cs | 1 - .../Styles/Builder/SheetStyleBuildContext.cs | 4 +--- src/MiniExcel.OpenXml/Styles/OpenXmlHeaderStyle.cs | 1 - src/MiniExcel.OpenXml/Styles/OpenXmlStyleOptions.cs | 2 -- src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs | 1 - src/MiniExcel.OpenXml/Styles/SheetStyleElementInfos.cs | 4 ++-- src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs | 5 ----- .../Templates/OpenXmlTemplate.MergeCells.cs | 2 -- src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs | 2 -- src/MiniExcel.OpenXml/Templates/OpenXmlTemplateUtils.cs | 4 +--- src/MiniExcel.OpenXml/Utils/MiniExcelPropertyHelper.cs | 2 -- src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs | 2 -- src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs | 4 ---- ...er.DefaultOpenXml.cs => OpenXmlWriter.XmlGeneration.cs} | 3 --- src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs | 4 ---- 37 files changed, 15 insertions(+), 75 deletions(-) rename src/MiniExcel.OpenXml/Writer/{OpenXmlWriter.DefaultOpenXml.cs => OpenXmlWriter.XmlGeneration.cs} (96%) diff --git a/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs b/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs index 79481b76..aaf53100 100644 --- a/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs +++ b/src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs @@ -1,4 +1,4 @@ -using MiniExcelLib.Core; + // ReSharper disable once CheckNamespace namespace MiniExcelLib.OpenXml; diff --git a/src/MiniExcel.OpenXml/Api/ProviderExtensions.cs b/src/MiniExcel.OpenXml/Api/ProviderExtensions.cs index 782f71ba..da617808 100644 --- a/src/MiniExcel.OpenXml/Api/ProviderExtensions.cs +++ b/src/MiniExcel.OpenXml/Api/ProviderExtensions.cs @@ -1,4 +1,4 @@ -using MiniExcelLib.Core; + // ReSharper disable once CheckNamespace namespace MiniExcelLib.OpenXml; diff --git a/src/MiniExcel.OpenXml/Constants/WorksheetXml.cs b/src/MiniExcel.OpenXml/Constants/WorksheetXml.cs index ee909365..39a1dffb 100644 --- a/src/MiniExcel.OpenXml/Constants/WorksheetXml.cs +++ b/src/MiniExcel.OpenXml/Constants/WorksheetXml.cs @@ -1,6 +1,4 @@ -using MiniExcelLib.Core.Attributes; - -namespace MiniExcelLib.OpenXml.Constants; +namespace MiniExcelLib.OpenXml.Constants; internal static class WorksheetXml { diff --git a/src/MiniExcel.OpenXml/FluentMapping/Api/ProviderExtensions.cs b/src/MiniExcel.OpenXml/FluentMapping/Api/ProviderExtensions.cs index 1a4a502e..19391f5c 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Api/ProviderExtensions.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Api/ProviderExtensions.cs @@ -1,5 +1,3 @@ -using MiniExcelLib.Core; - namespace MiniExcelLib.OpenXml.FluentMapping.Api; public static class ProviderExtensions diff --git a/src/MiniExcel.OpenXml/FluentMapping/CompiledMapping.cs b/src/MiniExcel.OpenXml/FluentMapping/CompiledMapping.cs index 322e2e51..a5daa206 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/CompiledMapping.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/CompiledMapping.cs @@ -1,5 +1,3 @@ -using System.Collections; - namespace MiniExcelLib.OpenXml.FluentMapping; internal class CompiledMapping diff --git a/src/MiniExcel.OpenXml/FluentMapping/Configuration/CollectionMappingBuilder.cs b/src/MiniExcel.OpenXml/FluentMapping/Configuration/CollectionMappingBuilder.cs index 5bf8ca6a..13fa931c 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Configuration/CollectionMappingBuilder.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Configuration/CollectionMappingBuilder.cs @@ -1,4 +1,3 @@ -using System.Collections; using System.Text.RegularExpressions; namespace MiniExcelLib.OpenXml.FluentMapping.Configuration; diff --git a/src/MiniExcel.OpenXml/FluentMapping/Configuration/ICollectionMappingBuilder.cs b/src/MiniExcel.OpenXml/FluentMapping/Configuration/ICollectionMappingBuilder.cs index ab459c4c..2db93369 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Configuration/ICollectionMappingBuilder.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Configuration/ICollectionMappingBuilder.cs @@ -1,5 +1,3 @@ -using System.Collections; - namespace MiniExcelLib.OpenXml.FluentMapping.Configuration; public interface ICollectionMappingBuilder where TCollection : IEnumerable diff --git a/src/MiniExcel.OpenXml/FluentMapping/Configuration/IMappingConfiguration.cs b/src/MiniExcel.OpenXml/FluentMapping/Configuration/IMappingConfiguration.cs index 01c18bb7..2738ec55 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Configuration/IMappingConfiguration.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Configuration/IMappingConfiguration.cs @@ -1,6 +1,3 @@ -using System.Collections; -using System.Linq.Expressions; - namespace MiniExcelLib.OpenXml.FluentMapping.Configuration; public interface IMappingConfiguration diff --git a/src/MiniExcel.OpenXml/FluentMapping/Configuration/MappingConfiguration.cs b/src/MiniExcel.OpenXml/FluentMapping/Configuration/MappingConfiguration.cs index 7322cde7..ba4432a8 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Configuration/MappingConfiguration.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Configuration/MappingConfiguration.cs @@ -1,6 +1,3 @@ -using System.Collections; -using System.Linq.Expressions; - namespace MiniExcelLib.OpenXml.FluentMapping.Configuration; internal class MappingConfiguration : IMappingConfiguration diff --git a/src/MiniExcel.OpenXml/FluentMapping/Helpers/ConversionHelper.cs b/src/MiniExcel.OpenXml/FluentMapping/Helpers/ConversionHelper.cs index 45da6d89..40089cae 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Helpers/ConversionHelper.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Helpers/ConversionHelper.cs @@ -1,6 +1,5 @@ using System.Collections.Concurrent; using System.Globalization; -using System.Linq.Expressions; using System.Reflection; namespace MiniExcelLib.OpenXml.FluentMapping.Helpers; diff --git a/src/MiniExcel.OpenXml/FluentMapping/Helpers/MappingMetadataExtractor.cs b/src/MiniExcel.OpenXml/FluentMapping/Helpers/MappingMetadataExtractor.cs index 0cd44fd5..0a260557 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/Helpers/MappingMetadataExtractor.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/Helpers/MappingMetadataExtractor.cs @@ -1,4 +1,3 @@ -using System.Collections; using System.Reflection; using MiniExcelLib.Core.Helpers; using MiniExcelLib.Core.Reflection; diff --git a/src/MiniExcel.OpenXml/FluentMapping/MappingCellStream.cs b/src/MiniExcel.OpenXml/FluentMapping/MappingCellStream.cs index 4f382695..403cd52c 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/MappingCellStream.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/MappingCellStream.cs @@ -1,4 +1,3 @@ -using System.Collections; using MiniExcelLib.Core.Abstractions; namespace MiniExcelLib.OpenXml.FluentMapping; diff --git a/src/MiniExcel.OpenXml/FluentMapping/MappingCompiler.cs b/src/MiniExcel.OpenXml/FluentMapping/MappingCompiler.cs index b7dbae53..efc5b6c3 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/MappingCompiler.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/MappingCompiler.cs @@ -1,5 +1,3 @@ -using System.Collections; -using System.Linq.Expressions; using System.Reflection; using MiniExcelLib.Core.Helpers; using MiniExcelLib.Core.Reflection; diff --git a/src/MiniExcel.OpenXml/FluentMapping/MappingReader.cs b/src/MiniExcel.OpenXml/FluentMapping/MappingReader.cs index bf1181c2..611f9f1b 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/MappingReader.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/MappingReader.cs @@ -1,4 +1,3 @@ -using System.Collections; using System.Runtime.CompilerServices; using Zomp.SyncMethodGenerator; diff --git a/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs b/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs index 378cc357..2936994f 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/MappingTemplateApplicator.cs @@ -1,5 +1,3 @@ -using MiniExcelLib.OpenXml.Constants; - namespace MiniExcelLib.OpenXml.FluentMapping; internal static partial class MappingTemplateApplicator where T : class diff --git a/src/MiniExcel.OpenXml/FluentMapping/NestedMappingInfo.cs b/src/MiniExcel.OpenXml/FluentMapping/NestedMappingInfo.cs index 300918a1..cef573d1 100644 --- a/src/MiniExcel.OpenXml/FluentMapping/NestedMappingInfo.cs +++ b/src/MiniExcel.OpenXml/FluentMapping/NestedMappingInfo.cs @@ -1,5 +1,3 @@ -using System.Collections; - namespace MiniExcelLib.OpenXml.FluentMapping; /// diff --git a/src/MiniExcel.OpenXml/GlobalUsings.cs b/src/MiniExcel.OpenXml/GlobalUsings.cs index c8bc554b..35a30d40 100644 --- a/src/MiniExcel.OpenXml/GlobalUsings.cs +++ b/src/MiniExcel.OpenXml/GlobalUsings.cs @@ -1,17 +1,24 @@ // Global using directives global using System.Collections; +global using System.ComponentModel; global using System.Data; 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 System.Xml.Linq; +global using MiniExcelLib.Core; global using MiniExcelLib.Core.Abstractions; +global using MiniExcelLib.Core.Attributes; +global using MiniExcelLib.Core.Enums; 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; diff --git a/src/MiniExcel.OpenXml/Models/SheetDto.cs b/src/MiniExcel.OpenXml/Models/SheetDto.cs index 7ed27612..99f14e21 100644 --- a/src/MiniExcel.OpenXml/Models/SheetDto.cs +++ b/src/MiniExcel.OpenXml/Models/SheetDto.cs @@ -1,6 +1,4 @@ -using MiniExcelLib.OpenXml.Constants; - -namespace MiniExcelLib.OpenXml.Models; +namespace MiniExcelLib.OpenXml.Models; internal class SheetDto { diff --git a/src/MiniExcel.OpenXml/OpenXmlConfiguration.cs b/src/MiniExcel.OpenXml/OpenXmlConfiguration.cs index 586483bb..20babe76 100644 --- a/src/MiniExcel.OpenXml/OpenXmlConfiguration.cs +++ b/src/MiniExcel.OpenXml/OpenXmlConfiguration.cs @@ -1,4 +1,3 @@ -using MiniExcelLib.Core; using MiniExcelLib.OpenXml.Styles; namespace MiniExcelLib.OpenXml; diff --git a/src/MiniExcel.OpenXml/OpenXmlReader.cs b/src/MiniExcel.OpenXml/OpenXmlReader.cs index 86a9990c..ab514bef 100644 --- a/src/MiniExcel.OpenXml/OpenXmlReader.cs +++ b/src/MiniExcel.OpenXml/OpenXmlReader.cs @@ -1,7 +1,4 @@ using System.Collections.ObjectModel; -using System.Xml.Linq; -using MiniExcelLib.Core; -using MiniExcelLib.OpenXml.Constants; using MiniExcelLib.OpenXml.Styles; using MiniExcelMapper = MiniExcelLib.Core.Reflection.MiniExcelMapper; using XmlReaderHelper = MiniExcelLib.OpenXml.Utils.XmlReaderHelper; diff --git a/src/MiniExcel.OpenXml/Picture/OpenXmlPicture.cs b/src/MiniExcel.OpenXml/Picture/OpenXmlPicture.cs index d0c38039..cda090d3 100644 --- a/src/MiniExcel.OpenXml/Picture/OpenXmlPicture.cs +++ b/src/MiniExcel.OpenXml/Picture/OpenXmlPicture.cs @@ -1,5 +1,4 @@ using System.Drawing; -using MiniExcelLib.Core.Enums; namespace MiniExcelLib.OpenXml.Picture; diff --git a/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs b/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs index a6220c54..67b15e5e 100644 --- a/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs +++ b/src/MiniExcel.OpenXml/Picture/OpenXmlPictureImplement.cs @@ -1,6 +1,4 @@ using System.Drawing; -using MiniExcelLib.Core.Enums; -using MiniExcelLib.OpenXml.Constants; namespace MiniExcelLib.OpenXml.Picture; diff --git a/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs b/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs index e08a308b..aa6f6073 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/DefaultSheetStyleBuilder.cs @@ -1,5 +1,4 @@ using System.Drawing; -using MiniExcelLib.Core.Enums; namespace MiniExcelLib.OpenXml.Styles.Builder; diff --git a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs index 00bb239d..83d3ccbe 100644 --- a/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs +++ b/src/MiniExcel.OpenXml/Styles/Builder/SheetStyleBuildContext.cs @@ -1,6 +1,4 @@ -using MiniExcelLib.OpenXml.Constants; - -namespace MiniExcelLib.OpenXml.Styles.Builder; +namespace MiniExcelLib.OpenXml.Styles.Builder; internal sealed partial class SheetStyleBuilderContext(Dictionary contentTypes, ZipArchive archive, Encoding encoding) : IDisposable, IAsyncDisposable { diff --git a/src/MiniExcel.OpenXml/Styles/OpenXmlHeaderStyle.cs b/src/MiniExcel.OpenXml/Styles/OpenXmlHeaderStyle.cs index 3f0b14b3..95ea3f01 100644 --- a/src/MiniExcel.OpenXml/Styles/OpenXmlHeaderStyle.cs +++ b/src/MiniExcel.OpenXml/Styles/OpenXmlHeaderStyle.cs @@ -1,5 +1,4 @@ using System.Drawing; -using MiniExcelLib.Core.Enums; namespace MiniExcelLib.OpenXml.Styles; diff --git a/src/MiniExcel.OpenXml/Styles/OpenXmlStyleOptions.cs b/src/MiniExcel.OpenXml/Styles/OpenXmlStyleOptions.cs index b81762ed..c4c232cb 100644 --- a/src/MiniExcel.OpenXml/Styles/OpenXmlStyleOptions.cs +++ b/src/MiniExcel.OpenXml/Styles/OpenXmlStyleOptions.cs @@ -1,7 +1,5 @@ namespace MiniExcelLib.OpenXml.Styles; -using MiniExcelLib.Core.Enums; - public class OpenXmlStyleOptions { public bool WrapCellContents { get; set; } diff --git a/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs b/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs index db3c3280..70937eb3 100644 --- a/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs +++ b/src/MiniExcel.OpenXml/Styles/OpenXmlStyles.cs @@ -1,4 +1,3 @@ -using MiniExcelLib.OpenXml.Constants; using XmlReaderHelper = MiniExcelLib.OpenXml.Utils.XmlReaderHelper; namespace MiniExcelLib.OpenXml.Styles; diff --git a/src/MiniExcel.OpenXml/Styles/SheetStyleElementInfos.cs b/src/MiniExcel.OpenXml/Styles/SheetStyleElementInfos.cs index db6bc188..e89eb16e 100644 --- a/src/MiniExcel.OpenXml/Styles/SheetStyleElementInfos.cs +++ b/src/MiniExcel.OpenXml/Styles/SheetStyleElementInfos.cs @@ -1,6 +1,6 @@ namespace MiniExcelLib.OpenXml.Styles; -public class SheetStyleElementInfos +internal class SheetStyleElementInfos { public bool ExistsNumFmts { get; set; } public int NumFmtCount { get; set; } @@ -14,4 +14,4 @@ public class SheetStyleElementInfos public int CellStyleXfCount { get; set; } public bool ExistsCellXfs { get; set; } public int CellXfCount { get; set; } -} \ No newline at end of file +} diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs index 4d4aacf4..fa170553 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.Impl.cs @@ -1,8 +1,3 @@ -using MiniExcelLib.Core.Attributes; -using System.ComponentModel; -using System.Xml.Linq; -using MiniExcelLib.OpenXml.Constants; - namespace MiniExcelLib.OpenXml.Templates; internal partial class OpenXmlTemplate diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs index 26eb58a6..1ff7f05d 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.MergeCells.cs @@ -1,5 +1,3 @@ -using MiniExcelLib.OpenXml.Constants; - namespace MiniExcelLib.OpenXml.Templates; internal partial class OpenXmlTemplate diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs index fce1e092..d14b36b5 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplate.cs @@ -1,5 +1,3 @@ -using MiniExcelLib.Core; -using MiniExcelLib.OpenXml.Constants; using CalcChainHelper = MiniExcelLib.OpenXml.Utils.CalcChainHelper; namespace MiniExcelLib.OpenXml.Templates; diff --git a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplateUtils.cs b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplateUtils.cs index b0ffcc62..0d5d0c7a 100644 --- a/src/MiniExcel.OpenXml/Templates/OpenXmlTemplateUtils.cs +++ b/src/MiniExcel.OpenXml/Templates/OpenXmlTemplateUtils.cs @@ -1,6 +1,4 @@ -using System.Xml.Linq; - -namespace MiniExcelLib.OpenXml.Templates; +namespace MiniExcelLib.OpenXml.Templates; internal class XRowInfo { diff --git a/src/MiniExcel.OpenXml/Utils/MiniExcelPropertyHelper.cs b/src/MiniExcel.OpenXml/Utils/MiniExcelPropertyHelper.cs index 58f73568..c44e4fb6 100644 --- a/src/MiniExcel.OpenXml/Utils/MiniExcelPropertyHelper.cs +++ b/src/MiniExcel.OpenXml/Utils/MiniExcelPropertyHelper.cs @@ -1,5 +1,3 @@ -using MiniExcelLib.Core; - namespace MiniExcelLib.OpenXml.Utils; internal static class MiniExcelPropertyHelper diff --git a/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs b/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs index 45e079bc..2266bfb8 100644 --- a/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs +++ b/src/MiniExcel.OpenXml/Utils/XmlReaderHelper.cs @@ -1,5 +1,3 @@ -using MiniExcelLib.OpenXml.Constants; - namespace MiniExcelLib.OpenXml.Utils; internal static partial class XmlReaderHelper diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs index 71e80b59..24b0f3aa 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.CopyInsert.cs @@ -1,7 +1,3 @@ -using System.ComponentModel; -using System.Xml.Linq; -using MiniExcelLib.Core; -using MiniExcelLib.OpenXml.Constants; using MiniExcelLib.OpenXml.Styles.Builder; namespace MiniExcelLib.OpenXml.Writer; diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.XmlGeneration.cs similarity index 96% rename from src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs rename to src/MiniExcel.OpenXml/Writer/OpenXmlWriter.XmlGeneration.cs index 56c01a0f..6bd6091d 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.DefaultOpenXml.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.XmlGeneration.cs @@ -1,6 +1,3 @@ -using System.ComponentModel; -using MiniExcelLib.Core.Attributes; -using MiniExcelLib.OpenXml.Constants; using static MiniExcelLib.Core.Helpers.ImageHelper; namespace MiniExcelLib.OpenXml.Writer; diff --git a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs index 9eee4a12..e59694df 100644 --- a/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs +++ b/src/MiniExcel.OpenXml/Writer/OpenXmlWriter.cs @@ -1,8 +1,4 @@ -using System.ComponentModel; -using System.Xml.Linq; -using MiniExcelLib.Core; using MiniExcelLib.Core.WriteAdapters; -using MiniExcelLib.OpenXml.Constants; using MiniExcelLib.OpenXml.Styles.Builder; namespace MiniExcelLib.OpenXml.Writer; From f6789cdcf01b11d2575b4e5aefb04133cb8ecaef Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Sun, 24 May 2026 16:15:35 +0200 Subject: [PATCH 12/12] Null check oversight fix --- src/MiniExcel.Core/Helpers/Polyfills.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/MiniExcel.Core/Helpers/Polyfills.cs b/src/MiniExcel.Core/Helpers/Polyfills.cs index 5fcbf252..47ad6be6 100644 --- a/src/MiniExcel.Core/Helpers/Polyfills.cs +++ b/src/MiniExcel.Core/Helpers/Polyfills.cs @@ -94,12 +94,15 @@ internal StreamConfiguredAsyncDisposable(Stream? source, bool continueOnCaptured _source = source; _continueOnCapturedContext = continueOnCapturedContext; } - - public ConfiguredValueTaskAwaitable DisposeAsync() - => _source.DisposeAsync().ConfigureAwait(_continueOnCapturedContext); - public void Dispose() - => _source?.Dispose(); + public ConfiguredValueTaskAwaitable DisposeAsync() + { + return _source is not null + ? _source.DisposeAsync().ConfigureAwait(_continueOnCapturedContext) + : default; + } + + public void Dispose() => _source?.Dispose(); } #endif