From b27b169e2ac71be63932a0be35ca2e4ac04e483a Mon Sep 17 00:00:00 2001 From: Jef Date: Sun, 31 Mar 2024 17:49:31 +0200 Subject: [PATCH] Make System.DateOnly available as date in Excel (#576) * Format the code and remove trailing whitespaces * Update Visual Studio gitignore template * Refactor: rename variables, add comments * Support writing DateOnly type to Excel --------- Co-authored-by: Jef Van den Brandt --- .gitattributes | 12 +- .gitignore | 179 ++++++++++++++++-- .../Attributes/ExcelColumnAttribute.cs | 10 +- .../Attributes/ExcelColumnIndexAttribute.cs | 4 +- .../Attributes/ExcelColumnNameAttribute.cs | 3 +- src/MiniExcel/Csv/CsvHelpers.cs | 2 +- src/MiniExcel/Csv/CsvReader.cs | 13 +- src/MiniExcel/Csv/CsvWriter.cs | 14 +- src/MiniExcel/ExcelFactory.cs | 9 +- .../Exceptions/ExcelInvalidCastException.cs | 6 +- src/MiniExcel/IExcelReader.cs | 12 +- src/MiniExcel/IExcelTemplate.cs | 7 +- src/MiniExcel/IExcelWriter.cs | 5 +- src/MiniExcel/MiniExcel.Async.cs | 69 +++---- src/MiniExcel/MiniExcel.Code.cs | 3 - src/MiniExcel/MiniExcel.cs | 2 - src/MiniExcel/MiniExcelDataReader.cs | 3 +- src/MiniExcel/MiniExcelLibs.csproj | 5 + src/MiniExcel/OpenXml/Config.cs | 2 +- .../OpenXml/ExcelOpenXmlSheetReader.cs | 2 +- .../OpenXml/ExcelOpenXmlSheetWriter.Async.cs | 62 +++--- .../ExcelOpenXmlSheetWriter.DefualtOpenXml.cs | 12 +- .../OpenXml/ExcelOpenXmlSheetWriter.cs | 148 +++++++++------ .../OpenXml/ExcelOpenXmlTemplate.Impl.cs | 48 +++-- .../ExcelOpenXmlTemplate.MergeCells.cs | 12 +- src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.cs | 12 +- src/MiniExcel/OpenXml/ExcelOpenXmlUtils.cs | 4 +- .../OpenXml/MiniExcelAsyncStreamWriter.cs | 4 +- .../OpenXml/MiniExcelStreamWriter.cs | 4 +- src/MiniExcel/Reflection/Property.cs | 2 +- src/MiniExcel/Utils/CustomPropertyHelper.cs | 4 +- src/MiniExcel/Utils/DateTimeHelper.cs | 4 +- src/MiniExcel/Utils/ExcelNumberFormat.cs | 10 +- src/MiniExcel/Utils/ImageHelper.cs | 4 - src/MiniExcel/Utils/StringHelper.cs | 6 +- src/MiniExcel/Utils/TypeHelper.cs | 1 - src/MiniExcel/Utils/XmlReaderHelper.cs | 2 +- src/MiniExcel/Utils/calChainHelper.cs | 10 +- src/MiniExcel/Zip/ExcelOpenXmlZip.cs | 12 +- src/MiniExcel/Zip/MiniExcelZipArchive.cs | 18 +- src/MiniExcel/Zip/ZipPackageInfo.cs | 3 +- tests/MiniExcelTests/MiniExcelCsvTests.cs | 120 ++++++------ .../MiniExcelIssueAsyncTests.cs | 14 +- tests/MiniExcelTests/MiniExcelIssueTests.cs | 27 +-- .../MiniExcelOpenXmlAsyncTests.cs | 48 ++--- ...MiniExcelOpenXmlMultipleSheetAsyncTests.cs | 15 +- .../MiniExcelOpenXmlMultipleSheetTests.cs | 8 +- tests/MiniExcelTests/MiniExcelOpenXmlTests.cs | 44 ++--- .../MiniExcelTemplateAsyncTests.cs | 29 ++- .../MiniExcelTests/MiniExcelTemplateTests.cs | 16 +- tests/MiniExcelTests/Utils/Db.cs | 9 +- tests/MiniExcelTests/Utils/Helpers.cs | 9 +- 52 files changed, 610 insertions(+), 473 deletions(-) diff --git a/.gitattributes b/.gitattributes index 1cf0fcd..3b6f31a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15,7 +15,7 @@ *.png binary *.gif binary -*.cs -text diff=csharp +*.cs -text diff=csharp *.vb -text *.c -text *.cpp -text @@ -44,8 +44,8 @@ *.fsx -text *.hs -text -*.csproj -text merge=union -*.vbproj -text merge=union -*.fsproj -text merge=union -*.dbproj -text merge=union -*.sln -text merge=union +*.csproj -text merge=union +*.vbproj -text merge=union +*.fsproj -text merge=union +*.dbproj -text merge=union +*.sln -text merge=union diff --git a/.gitignore b/.gitignore index b53b74f..ba3deb0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore # User-specific files +*.rsuser *.suo *.user *.userosscache @@ -10,6 +13,9 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs +# Mono auto generated files +mono_crash.* + # Build results [Dd]ebug/ [Dd]ebugPublic/ @@ -17,42 +23,62 @@ [Rr]eleases/ x64/ x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ +[Ll]ogs/ -# Visual Studio 2015 cache/options directory +# Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ +# Visual Studio 2017 auto generated files +Generated\ Files/ + # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* -# NUNIT +# NUnit *.VisualState.xml TestResult.xml +nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c -# DNX +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core project.lock.json project.fragment.lock.json artifacts/ +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio *_i.c *_p.c -*_i.h +*_h.h *.ilk *.meta *.obj +*.iobj *.pch *.pdb +*.ipdb *.pgc *.pgd *.rsp @@ -62,7 +88,9 @@ artifacts/ *.tlh *.tmp *.tmp_proj +*_wpftmp.csproj *.log +*.tlog *.vspscc *.vssscc .builds @@ -90,6 +118,9 @@ ipch/ *.vspx *.sap +# Visual Studio Trace Files +*.e2e + # TFS 2012 Local Workspace $tf/ @@ -101,15 +132,25 @@ _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user -# JustCode is a .NET coding add-in -.JustCode - # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + # NCrunch _NCrunch_* .*crunch*.local.xml @@ -141,9 +182,9 @@ publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings +# Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted -#*.pubxml +*.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to @@ -153,13 +194,15 @@ PublishScripts/ # NuGet Packages *.nupkg +# NuGet Symbol Packages +*.snupkg # The packages folder can be ignored because of Package Restore -**/packages/* +**/[Pp]ackages/* # except build/, which is used as an MSBuild target. -!**/packages/build/ +!**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed -#!**/packages/repositories.config -# NuGet v3's project.json files produces more ignoreable files +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets @@ -176,12 +219,15 @@ AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt +*.appx +*.appxbundle +*.appxupload # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache -!*.[Cc]ache/ +!?*.[Cc]ache/ # Others ClientBin/ @@ -192,9 +238,12 @@ ClientBin/ *.jfm *.pfx *.publishsettings -node_modules/ orleans.codegen.cs +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ @@ -209,15 +258,22 @@ _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak # SQL Server files *.mdf *.ldf +*.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ @@ -227,6 +283,7 @@ FakesAssemblies/ # Node.js Tools for Visual Studio .ntvs_analysis.dat +node_modules/ # Visual Studio 6 build log *.plg @@ -234,6 +291,20 @@ FakesAssemblies/ # Visual Studio 6 workspace options file *.opt +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts @@ -249,17 +320,83 @@ paket-files/ # FAKE - F# Make .fake/ -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush -.cr/ +# CodeRush personal settings +.cr/personal # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + /BenchmarkDotNet.Artifacts /tests/MiniExcel.Tests.AspNetMvc/packages /TestTemplate diff --git a/src/MiniExcel/Attributes/ExcelColumnAttribute.cs b/src/MiniExcel/Attributes/ExcelColumnAttribute.cs index 21473b2..d733741 100644 --- a/src/MiniExcel/Attributes/ExcelColumnAttribute.cs +++ b/src/MiniExcel/Attributes/ExcelColumnAttribute.cs @@ -1,5 +1,5 @@ -using System; -using MiniExcelLibs.Utils; +using MiniExcelLibs.Utils; +using System; namespace MiniExcelLibs.Attributes { @@ -46,9 +46,9 @@ namespace MiniExcelLibs.Attributes _xName = ColumnHelper.GetAlphabetColumnName(index); _index = index; } - } - - + } + + public class DynamicExcelColumn : ExcelColumnAttribute { public string Key { get; set; } diff --git a/src/MiniExcel/Attributes/ExcelColumnIndexAttribute.cs b/src/MiniExcel/Attributes/ExcelColumnIndexAttribute.cs index 8329ae8..d576baa 100644 --- a/src/MiniExcel/Attributes/ExcelColumnIndexAttribute.cs +++ b/src/MiniExcel/Attributes/ExcelColumnIndexAttribute.cs @@ -12,14 +12,14 @@ .GetColumnIndex(columnName), columnName); public ExcelColumnIndexAttribute(int columnIndex) => Init(columnIndex); - private void Init(int columnIndex,string columnName=null) + private void Init(int columnIndex, string columnName = null) { if (columnIndex < 0) { throw new ArgumentOutOfRangeException(nameof(columnIndex), columnIndex, $"Column index {columnIndex} must be greater or equal to zero."); } if (ExcelXName == null) - if(columnName != null) + if (columnName != null) ExcelXName = columnName; else ExcelXName = ColumnHelper.GetAlphabetColumnName(columnIndex); diff --git a/src/MiniExcel/Attributes/ExcelColumnNameAttribute.cs b/src/MiniExcel/Attributes/ExcelColumnNameAttribute.cs index 0dcb8f1..eb16530 100644 --- a/src/MiniExcel/Attributes/ExcelColumnNameAttribute.cs +++ b/src/MiniExcel/Attributes/ExcelColumnNameAttribute.cs @@ -1,13 +1,12 @@ namespace MiniExcelLibs.Attributes { - using MiniExcelLibs.Utils; using System; [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public class ExcelColumnNameAttribute : Attribute { public string ExcelColumnName { get; set; } public string[] Aliases { get; set; } - public ExcelColumnNameAttribute(string excelColumnName, string[] aliases=null) + public ExcelColumnNameAttribute(string excelColumnName, string[] aliases = null) { ExcelColumnName = excelColumnName; Aliases = aliases; diff --git a/src/MiniExcel/Csv/CsvHelpers.cs b/src/MiniExcel/Csv/CsvHelpers.cs index 8dc32a5..a9b878a 100644 --- a/src/MiniExcel/Csv/CsvHelpers.cs +++ b/src/MiniExcel/Csv/CsvHelpers.cs @@ -21,7 +21,7 @@ if (alwaysQuote) return $"\"{value}\""; - + return value; } } diff --git a/src/MiniExcel/Csv/CsvReader.cs b/src/MiniExcel/Csv/CsvReader.cs index 7a0d068..f8d3645 100644 --- a/src/MiniExcel/Csv/CsvReader.cs +++ b/src/MiniExcel/Csv/CsvReader.cs @@ -2,7 +2,6 @@ using MiniExcelLibs.OpenXml; using MiniExcelLibs.Utils; using System; using System.Collections.Generic; -using System.Data; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -11,7 +10,7 @@ using System.Threading.Tasks; namespace MiniExcelLibs.Csv { - internal class CsvReader : IExcelReader + internal class CsvReader : IExcelReader { private Stream _stream; private CsvConfiguration _config; @@ -24,7 +23,7 @@ namespace MiniExcelLibs.Csv { if (startCell != "A1") throw new NotImplementedException("CSV not Implement startCell"); - if(_stream.CanSeek) + if (_stream.CanSeek) _stream.Position = 0; var reader = _config.StreamReaderFunc(_stream); { @@ -94,14 +93,14 @@ namespace MiniExcelLibs.Csv } } - public Task>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell,CancellationToken cancellationToken = default(CancellationToken)) + public Task>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) { - return Task.Run(() => Query(UseHeaderRow, sheetName, startCell),cancellationToken); + return Task.Run(() => Query(UseHeaderRow, sheetName, startCell), cancellationToken); } - public Task> QueryAsync(string sheetName, string startCell,CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + public Task> QueryAsync(string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() { - return Task.Run(() => Query(sheetName, startCell),cancellationToken); + return Task.Run(() => Query(sheetName, startCell), cancellationToken); } public void Dispose() diff --git a/src/MiniExcel/Csv/CsvWriter.cs b/src/MiniExcel/Csv/CsvWriter.cs index 1adf46e..48f0896 100644 --- a/src/MiniExcel/Csv/CsvWriter.cs +++ b/src/MiniExcel/Csv/CsvWriter.cs @@ -143,7 +143,7 @@ namespace MiniExcelLibs.Csv public async Task SaveAsAsync(CancellationToken cancellationToken = default(CancellationToken)) { - await Task.Run(() => SaveAs(),cancellationToken).ConfigureAwait(false); + await Task.Run(() => SaveAs(), cancellationToken).ConfigureAwait(false); } private void GenerateSheetByIDataReader(object value, string seperator, string newLine, StreamWriter writer) @@ -162,7 +162,7 @@ namespace MiniExcelLibs.Csv if (i != 0) writer.Write(seperator); - writer.Write(CsvHelpers.ConvertToCsvValue(ToCsvString(columnName,null), _configuration.AlwaysQuote, _configuration.Seperator)); + writer.Write(CsvHelpers.ConvertToCsvValue(ToCsvString(columnName, null), _configuration.AlwaysQuote, _configuration.Seperator)); } writer.Write(newLine); } @@ -174,7 +174,7 @@ namespace MiniExcelLibs.Csv var cellValue = reader.GetValue(i); if (i != 0) writer.Write(seperator); - writer.Write(CsvHelpers.ConvertToCsvValue(ToCsvString(cellValue,null), _configuration.AlwaysQuote, _configuration.Seperator)); + writer.Write(CsvHelpers.ConvertToCsvValue(ToCsvString(cellValue, null), _configuration.AlwaysQuote, _configuration.Seperator)); } writer.Write(newLine); } @@ -192,7 +192,7 @@ namespace MiniExcelLibs.Csv var first = true; for (int j = 0; j < dt.Columns.Count; j++) { - var cellValue = CsvHelpers.ConvertToCsvValue(ToCsvString(dt.Rows[i][j],null), _configuration.AlwaysQuote, _configuration.Seperator); + var cellValue = CsvHelpers.ConvertToCsvValue(ToCsvString(dt.Rows[i][j], null), _configuration.AlwaysQuote, _configuration.Seperator); if (!first) writer.Write(seperator); writer.Write(cellValue); @@ -206,7 +206,7 @@ namespace MiniExcelLibs.Csv { foreach (var v in value) { - var values = props.Select(s => CsvHelpers.ConvertToCsvValue(ToCsvString(s?.Property.GetValue(v),s), _configuration.AlwaysQuote, _configuration.Seperator)); + var values = props.Select(s => CsvHelpers.ConvertToCsvValue(ToCsvString(s?.Property.GetValue(v), s), _configuration.AlwaysQuote, _configuration.Seperator)); writer.Write(string.Join(seperator, values)); writer.Write(newLine); } @@ -216,7 +216,7 @@ namespace MiniExcelLibs.Csv { foreach (IDictionary v in value) { - var values = keys.Select(key => CsvHelpers.ConvertToCsvValue(ToCsvString(v[key],null), _configuration.AlwaysQuote, _configuration.Seperator)); + var values = keys.Select(key => CsvHelpers.ConvertToCsvValue(ToCsvString(v[key], null), _configuration.AlwaysQuote, _configuration.Seperator)); writer.Write(string.Join(seperator, values)); writer.Write(newLine); } @@ -226,7 +226,7 @@ namespace MiniExcelLibs.Csv { foreach (IDictionary v in value) { - var values = keys.Select(key => CsvHelpers.ConvertToCsvValue(ToCsvString(v[key],null), _configuration.AlwaysQuote, _configuration.Seperator)); + var values = keys.Select(key => CsvHelpers.ConvertToCsvValue(ToCsvString(v[key], null), _configuration.AlwaysQuote, _configuration.Seperator)); writer.Write(string.Join(seperator, values)); writer.Write(newLine); } diff --git a/src/MiniExcel/ExcelFactory.cs b/src/MiniExcel/ExcelFactory.cs index 879eee5..3dfa468 100644 --- a/src/MiniExcel/ExcelFactory.cs +++ b/src/MiniExcel/ExcelFactory.cs @@ -1,14 +1,13 @@ namespace MiniExcelLibs { + using MiniExcelLibs.Csv; using MiniExcelLibs.OpenXml; using System; - using MiniExcelLibs.Csv; using System.IO; - using System.Globalization; internal class ExcelReaderFactory - { - internal static IExcelReader GetProvider(Stream stream, ExcelType excelType,IConfiguration configuration) + { + internal static IExcelReader GetProvider(Stream stream, ExcelType excelType, IConfiguration configuration) { switch (excelType) { @@ -45,7 +44,7 @@ internal class ExcelTemplateFactory { - internal static IExcelTemplateAsync GetProvider(Stream stream, IConfiguration configuration, ExcelType excelType= ExcelType.XLSX) + internal static IExcelTemplateAsync GetProvider(Stream stream, IConfiguration configuration, ExcelType excelType = ExcelType.XLSX) { switch (excelType) { diff --git a/src/MiniExcel/Exceptions/ExcelInvalidCastException.cs b/src/MiniExcel/Exceptions/ExcelInvalidCastException.cs index eca91c9..35155e8 100644 --- a/src/MiniExcel/Exceptions/ExcelInvalidCastException.cs +++ b/src/MiniExcel/Exceptions/ExcelInvalidCastException.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MiniExcelLibs.Exceptions { @@ -12,7 +8,7 @@ namespace MiniExcelLibs.Exceptions public int Row { get; set; } public object Value { get; set; } public Type InvalidCastType { get; set; } - public ExcelInvalidCastException(string columnName, int row,object value,Type invalidCastType, string message) : base(message) + public ExcelInvalidCastException(string columnName, int row, object value, Type invalidCastType, string message) : base(message) { ColumnName = columnName; Row = row; diff --git a/src/MiniExcel/IExcelReader.cs b/src/MiniExcel/IExcelReader.cs index 66ef8c1..d1b34be 100644 --- a/src/MiniExcel/IExcelReader.cs +++ b/src/MiniExcel/IExcelReader.cs @@ -1,20 +1,16 @@ using System; -using MiniExcelLibs.Utils; using System.Collections.Generic; -using System.Data; -using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; namespace MiniExcelLibs { - internal interface IExcelReader: IDisposable + internal interface IExcelReader : IDisposable { - IEnumerable> Query(bool UseHeaderRow, string sheetName,string startCell); + IEnumerable> Query(bool UseHeaderRow, string sheetName, string startCell); IEnumerable Query(string sheetName, string startCell) where T : class, new(); - Task>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell,CancellationToken cancellationToken = default(CancellationToken)); - Task> QueryAsync(string sheetName, string startCell,CancellationToken cancellationToken = default(CancellationToken)) where T : class, new(); + Task>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)); + Task> QueryAsync(string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new(); IEnumerable> QueryRange(bool UseHeaderRow, string sheetName, string startCell, string endCell); IEnumerable QueryRange(string sheetName, string startCell, string endCell) where T : class, new(); Task>> QueryAsyncRange(bool UseHeaderRow, string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default(CancellationToken)); diff --git a/src/MiniExcel/IExcelTemplate.cs b/src/MiniExcel/IExcelTemplate.cs index 310ea54..d4a66c5 100644 --- a/src/MiniExcel/IExcelTemplate.cs +++ b/src/MiniExcel/IExcelTemplate.cs @@ -1,5 +1,4 @@ -using System.IO; -using System.Threading; +using System.Threading; using System.Threading.Tasks; namespace MiniExcelLibs @@ -14,8 +13,8 @@ namespace MiniExcelLibs internal interface IExcelTemplateAsync : IExcelTemplate { - Task SaveAsByTemplateAsync(string templatePath, object value,CancellationToken cancellationToken = default(CancellationToken)); - Task SaveAsByTemplateAsync(byte[] templateBtyes, object value,CancellationToken cancellationToken = default(CancellationToken)); + Task SaveAsByTemplateAsync(string templatePath, object value, CancellationToken cancellationToken = default(CancellationToken)); + Task SaveAsByTemplateAsync(byte[] templateBtyes, object value, CancellationToken cancellationToken = default(CancellationToken)); Task MergeSameCellsAsync(string path, CancellationToken cancellationToken = default(CancellationToken)); Task MergeSameCellsAsync(byte[] fileInBytes, CancellationToken cancellationToken = default(CancellationToken)); } diff --git a/src/MiniExcel/IExcelWriter.cs b/src/MiniExcel/IExcelWriter.cs index 452dfe2..b8fb6d0 100644 --- a/src/MiniExcel/IExcelWriter.cs +++ b/src/MiniExcel/IExcelWriter.cs @@ -1,10 +1,9 @@ -using System.IO; -using System.Threading; +using System.Threading; using System.Threading.Tasks; namespace MiniExcelLibs { - internal interface IExcelWriter + internal interface IExcelWriter { void SaveAs(); Task SaveAsAsync(CancellationToken cancellationToken = default(CancellationToken)); diff --git a/src/MiniExcel/MiniExcel.Async.cs b/src/MiniExcel/MiniExcel.Async.cs index 0da5d6e..8cf080d 100644 --- a/src/MiniExcel/MiniExcel.Async.cs +++ b/src/MiniExcel/MiniExcel.Async.cs @@ -1,16 +1,16 @@ namespace MiniExcelLibs { - using Utils; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Threading; using System.Threading.Tasks; + using Utils; public static partial class MiniExcel { - public static async Task SaveAsAsync(string path, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, bool overwriteFile = false,CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsAsync(string path, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, bool overwriteFile = false, CancellationToken cancellationToken = default(CancellationToken)) { if (Path.GetExtension(path).ToLowerInvariant() == ".xlsm") throw new NotSupportedException("MiniExcel SaveAs not support xlsm"); @@ -19,14 +19,14 @@ await SaveAsAsync(stream, value, printHeader, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), configuration); } - public static async Task SaveAsAsync(this Stream stream, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsAsync(this Stream stream, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { await ExcelWriterFactory.GetProvider(stream, value, sheetName, excelType, configuration, printHeader).SaveAsAsync(cancellationToken); } - - public static async Task MergeSameCellsAsync(string mergedFilePath, string path, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) + + public static async Task MergeSameCellsAsync(string mergedFilePath, string path, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { - await Task.Run(() => MergeSameCells(mergedFilePath, path, excelType, configuration) ,cancellationToken).ConfigureAwait(false); + await Task.Run(() => MergeSameCells(mergedFilePath, path, excelType, configuration), cancellationToken).ConfigureAwait(false); } public static async Task MergeSameCellsAsync(this Stream stream, string path, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) @@ -39,25 +39,26 @@ await ExcelTemplateFactory.GetProvider(stream, configuration, excelType).MergeSameCellsAsync(fileBytes, cancellationToken); } - public static async Task> QueryAsync(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) + public static async Task> QueryAsync(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { - return await Task.Run(() => Query(path, useHeaderRow, sheetName, excelType, startCell, configuration),cancellationToken); + return await Task.Run(() => Query(path, useHeaderRow, sheetName, excelType, startCell, configuration), cancellationToken); } - public static async Task> QueryAsync(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + public static async Task> QueryAsync(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() { - return await ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration).QueryAsync(sheetName, startCell,cancellationToken).ConfigureAwait(false); + return await ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration).QueryAsync(sheetName, startCell, cancellationToken).ConfigureAwait(false); } - public static async Task> QueryAsync(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + public static async Task> QueryAsync(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() { - return await Task.Run(() => Query(path, sheetName, excelType, startCell, configuration),cancellationToken).ConfigureAwait(false); + return await Task.Run(() => Query(path, sheetName, excelType, startCell, configuration), cancellationToken).ConfigureAwait(false); } - public static async Task> QueryAsync(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) + public static async Task> QueryAsync(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { TaskCompletionSource> tcs = new TaskCompletionSource>(); - cancellationToken.Register(() => { + cancellationToken.Register(() => + { tcs.TrySetCanceled(); }); @@ -74,44 +75,44 @@ }, cancellationToken); return await tcs.Task; - + } - public static async Task SaveAsByTemplateAsync(this Stream stream, string templatePath, object value, IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsByTemplateAsync(this Stream stream, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { - await ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplateAsync(templatePath, value,cancellationToken).ConfigureAwait(false); + await ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplateAsync(templatePath, value, cancellationToken).ConfigureAwait(false); } - public static async Task SaveAsByTemplateAsync(this Stream stream, byte[] templateBytes, object value, IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsByTemplateAsync(this Stream stream, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { - await ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplateAsync(templateBytes, value,cancellationToken).ConfigureAwait(false); + await ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplateAsync(templateBytes, value, cancellationToken).ConfigureAwait(false); } - public static async Task SaveAsByTemplateAsync(string path, string templatePath, object value, IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsByTemplateAsync(string path, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { - await Task.Run(() => SaveAsByTemplate(path, templatePath, value, configuration),cancellationToken).ConfigureAwait(false); + await Task.Run(() => SaveAsByTemplate(path, templatePath, value, configuration), cancellationToken).ConfigureAwait(false); } - public static async Task SaveAsByTemplateAsync(string path, byte[] templateBytes, object value, IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsByTemplateAsync(string path, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { - await Task.Run(() => SaveAsByTemplate(path, templateBytes, value, configuration),cancellationToken).ConfigureAwait(false); - } - - /// - /// QueryAsDataTable is not recommended, because it'll load all data into memory. - /// - [Obsolete("QueryAsDataTable is not recommended, because it'll load all data into memory.")] - public static async Task QueryAsDataTableAsync(string path, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) - { - return await Task.Run(() => QueryAsDataTable(path, useHeaderRow, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration),cancellationToken).ConfigureAwait(false); + await Task.Run(() => SaveAsByTemplate(path, templateBytes, value, configuration), cancellationToken).ConfigureAwait(false); } /// /// QueryAsDataTable is not recommended, because it'll load all data into memory. /// [Obsolete("QueryAsDataTable is not recommended, because it'll load all data into memory.")] - public static async Task QueryAsDataTableAsync(this Stream stream, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null,CancellationToken cancellationToken = default(CancellationToken)) + public static async Task QueryAsDataTableAsync(string path, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { - return await Task.Run(() => QueryAsDataTable(stream, useHeaderRow, sheetName, excelType, startCell, configuration),cancellationToken).ConfigureAwait(false); + return await Task.Run(() => QueryAsDataTable(path, useHeaderRow, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration), cancellationToken).ConfigureAwait(false); + } + + /// + /// QueryAsDataTable is not recommended, because it'll load all data into memory. + /// + [Obsolete("QueryAsDataTable is not recommended, because it'll load all data into memory.")] + public static async Task QueryAsDataTableAsync(this Stream stream, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return await Task.Run(() => QueryAsDataTable(stream, useHeaderRow, sheetName, excelType, startCell, configuration), cancellationToken).ConfigureAwait(false); } } } diff --git a/src/MiniExcel/MiniExcel.Code.cs b/src/MiniExcel/MiniExcel.Code.cs index b5aa2d5..0df1e93 100644 --- a/src/MiniExcel/MiniExcel.Code.cs +++ b/src/MiniExcel/MiniExcel.Code.cs @@ -1,8 +1,5 @@ namespace MiniExcelLibs { - using System; - using System.Linq; - public static partial class MiniExcel { public static string LISENCE_CODE = null; diff --git a/src/MiniExcel/MiniExcel.cs b/src/MiniExcel/MiniExcel.cs index dea683e..abf5649 100644 --- a/src/MiniExcel/MiniExcel.cs +++ b/src/MiniExcel/MiniExcel.cs @@ -8,8 +8,6 @@ using System.Dynamic; using System.IO; using System.Linq; - using System.Threading; - using System.Threading.Tasks; using Utils; using Zip; diff --git a/src/MiniExcel/MiniExcelDataReader.cs b/src/MiniExcel/MiniExcelDataReader.cs index c258c24..754ed83 100644 --- a/src/MiniExcel/MiniExcelDataReader.cs +++ b/src/MiniExcel/MiniExcelDataReader.cs @@ -1,6 +1,5 @@ namespace MiniExcelLibs { - using MiniExcelLibs.Utils; using System; using System.Collections.Generic; using System.Data; @@ -65,7 +64,7 @@ public void Close() { - return; + return; } public int Depth => throw new NotImplementedException(); diff --git a/src/MiniExcel/MiniExcelLibs.csproj b/src/MiniExcel/MiniExcelLibs.csproj index 56ae2a5..5b1c373 100644 --- a/src/MiniExcel/MiniExcelLibs.csproj +++ b/src/MiniExcel/MiniExcelLibs.csproj @@ -54,4 +54,9 @@ Todo : https://github.com/mini-software/MiniExcel/projects/1?fullscreen=true + + + 8.0.0 + + diff --git a/src/MiniExcel/OpenXml/Config.cs b/src/MiniExcel/OpenXml/Config.cs index eceed02..fed5318 100644 --- a/src/MiniExcel/OpenXml/Config.cs +++ b/src/MiniExcel/OpenXml/Config.cs @@ -1,6 +1,6 @@ namespace MiniExcelLibs.OpenXml { - internal class Config + internal class Config { public const string SpreadsheetmlXmlns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; public const string SpreadsheetmlXmlStrictns = "http://purl.oclc.org/ooxml/spreadsheetml/main"; diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs index 73ace9e..2fd927c 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs @@ -77,7 +77,7 @@ namespace MiniExcelLibs.OpenXml sheetEntry = sheets.Single(w => w.FullName == $"xl/{s.Path}" || w.FullName == $"/xl/{s.Path}"); #elif NETSTANDARD2_0_OR_GREATER - // fixed by argo@live.ca + // fixed by argo@live.ca // s.Path = "/xl/sheets/sheet1.xml" s.FullName = "/xl/sheets/sheet1.xml" sheetEntry = sheets.Single(w => w.FullName == $"xl/{s.Path}" || w.FullName == $"/xl/{s.Path}" || w.FullName.TrimStart('/') == s.Path.TrimStart('/')); #endif diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs index c6b8788..0039ce2 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.Async.cs @@ -21,43 +21,43 @@ namespace MiniExcelLibs.OpenXml switch (_value) { case IDictionary sheets: - { - var sheetId = 0; - _sheets.RemoveAt(0);//TODO:remove - foreach (var sheet in sheets) { - sheetId++; - var sheetInfos = GetSheetInfos(sheet.Key); - var sheetDto = sheetInfos.ToDto(sheetId); - _sheets.Add(sheetDto); //TODO:remove + var sheetId = 0; + _sheets.RemoveAt(0);//TODO:remove + foreach (var sheet in sheets) + { + sheetId++; + var sheetInfos = GetSheetInfos(sheet.Key); + var sheetDto = sheetInfos.ToDto(sheetId); + _sheets.Add(sheetDto); //TODO:remove - currentSheetIndex = sheetId; + currentSheetIndex = sheetId; - await CreateSheetXmlAsync(sheet.Value, sheetDto.Path, cancellationToken); + await CreateSheetXmlAsync(sheet.Value, sheetDto.Path, cancellationToken); + } + + break; } - break; - } - case DataSet sheets: - { - var sheetId = 0; - _sheets.RemoveAt(0);//TODO:remove - foreach (DataTable dt in sheets.Tables) { - sheetId++; - var sheetInfos = GetSheetInfos(dt.TableName); - var sheetDto = sheetInfos.ToDto(sheetId); - _sheets.Add(sheetDto); //TODO:remove + var sheetId = 0; + _sheets.RemoveAt(0);//TODO:remove + foreach (DataTable dt in sheets.Tables) + { + sheetId++; + var sheetInfos = GetSheetInfos(dt.TableName); + var sheetDto = sheetInfos.ToDto(sheetId); + _sheets.Add(sheetDto); //TODO:remove - currentSheetIndex = sheetId; + currentSheetIndex = sheetId; - await CreateSheetXmlAsync(dt, sheetDto.Path, cancellationToken); + await CreateSheetXmlAsync(dt, sheetDto.Path, cancellationToken); + } + + break; } - break; - } - default: //Single sheet export. currentSheetIndex++; @@ -251,7 +251,7 @@ namespace MiniExcelLibs.OpenXml { mode = "IDictionary"; props = GetDictionaryColumnInfo(null, dic); - //maxColumnIndex = dic.Keys.Count; + //maxColumnIndex = dic.Keys.Count; maxColumnIndex = props.Count; // why not using keys, because ignore attribute ![image](https://user-images.githubusercontent.com/12729184/163686902-286abb70-877b-4e84-bd3b-001ad339a84a.png) } else @@ -511,7 +511,7 @@ namespace MiniExcelLibs.OpenXml } } - // styles.xml + // styles.xml { var styleXml = string.Empty; @@ -523,7 +523,7 @@ namespace MiniExcelLibs.OpenXml { styleXml = _defaultStylesXml; } - + await CreateZipEntryAsync(@"xl/styles.xml", "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml", styleXml, cancellationToken); } @@ -606,7 +606,7 @@ namespace MiniExcelLibs.OpenXml } workbookRelsXml.AppendLine($@""); - //TODO: support multiple drawing + //TODO: support multiple drawing //TODO: ../drawings/drawing1.xml or /xl/drawings/drawing1.xml var sheetRelsXml = $@""; await CreateZipEntryAsync($"xl/worksheets/_rels/sheet{s.SheetIdx}.xml.rels", "", @@ -618,7 +618,7 @@ namespace MiniExcelLibs.OpenXml _defaultWorkbookXmlRels.Replace("{{sheets}}", workbookRelsXml.ToString()), cancellationToken); } - //[Content_Types].xml + //[Content_Types].xml { var sb = new StringBuilder(@""); foreach (var p in _zipDictionary) diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.DefualtOpenXml.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.DefualtOpenXml.cs index 66d19e9..bd244d1 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.DefualtOpenXml.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.DefualtOpenXml.cs @@ -1,10 +1,6 @@ using MiniExcelLibs.Zip; -using System; using System.Collections.Generic; -using System.IO; using System.IO.Compression; -using System.Text; -using System.Xml; namespace MiniExcelLibs.OpenXml { @@ -191,13 +187,13 @@ namespace MiniExcelLibs.OpenXml CreateZipEntry("xl/sharedStrings.xml", "application/vnd.openxmlformats-package.relationships+xml", ExcelOpenXmlSheetWriter._defaultSharedString); } - private void CreateZipEntry(string path,string contentType,string content) + private void CreateZipEntry(string path, string contentType, string content) { ZipArchiveEntry entry = _archive.CreateEntry(path, CompressionLevel.Fastest); using (var zipStream = entry.Open()) - using (MiniExcelStreamWriter writer = new MiniExcelStreamWriter(zipStream, _utf8WithBom,_configuration.BufferSize)) + using (MiniExcelStreamWriter writer = new MiniExcelStreamWriter(zipStream, _utf8WithBom, _configuration.BufferSize)) writer.Write(content); - if(!string.IsNullOrEmpty(contentType)) + if (!string.IsNullOrEmpty(contentType)) _zipDictionary.Add(path, new ZipPackageInfo(entry, contentType)); } @@ -205,7 +201,7 @@ namespace MiniExcelLibs.OpenXml { ZipArchiveEntry entry = _archive.CreateEntry(path, CompressionLevel.Fastest); using (var zipStream = entry.Open()) - zipStream.Write(content,0, content.Length); + zipStream.Write(content, 0, content.Length); } } } diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs index 0ac7d06..2552dc2 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs @@ -9,8 +9,6 @@ using System.IO; using System.IO.Compression; using System.Linq; using System.Text; -using System.Threading; -using System.Threading.Tasks; using static MiniExcelLibs.Utils.ImageHelper; namespace MiniExcelLibs.OpenXml @@ -382,9 +380,9 @@ namespace MiniExcelLibs.OpenXml writer.Write($""); var cellIndex = xIndex; - foreach (var p in props) + foreach (var columnInfo in props) { - if (p == null) //reason:https://github.com/shps951023/MiniExcel/issues/142 + if (columnInfo == null) //reason:https://github.com/shps951023/MiniExcel/issues/142 { cellIndex++; continue; @@ -392,20 +390,20 @@ namespace MiniExcelLibs.OpenXml object cellValue = null; if (isDic) { - cellValue = ((IDictionary)v)[p.Key]; + cellValue = ((IDictionary)v)[columnInfo.Key]; //WriteCell(writer, yIndex, cellIndex, cellValue, null); // why null because dictionary that needs to check type every time //TODO: user can specefic type to optimize efficiency } else if (isDapperRow) { - cellValue = ((IDictionary)v)[p.Key.ToString()]; + cellValue = ((IDictionary)v)[columnInfo.Key.ToString()]; } else { - cellValue = p.Property.GetValue(v); + cellValue = columnInfo.Property.GetValue(v); } - WriteCell(writer, yIndex, cellIndex, cellValue, p); + WriteCell(writer, yIndex, cellIndex, cellValue, columnInfo); cellIndex++; } @@ -416,54 +414,57 @@ namespace MiniExcelLibs.OpenXml return yIndex - 1; } - private void WriteCell(MiniExcelStreamWriter writer, int rowIndex, int cellIndex, object value, ExcelColumnInfo p) + private void WriteCell(MiniExcelStreamWriter writer, int rowIndex, int cellIndex, object value, ExcelColumnInfo columnInfo) { var columname = ExcelOpenXmlUtils.ConvertXyToCell(cellIndex, rowIndex); - var s = "2"; var valueIsNull = value is null || value is DBNull; if (_configuration.EnableWriteNullValueCell && valueIsNull) { - writer.Write($""); + writer.Write($""); // s: style index return; } - var tuple = GetCellValue(rowIndex, cellIndex, value, p, valueIsNull); + var tuple = GetCellValue(rowIndex, cellIndex, value, columnInfo, valueIsNull); - s = tuple.Item1; - var t = tuple.Item2; - var v = tuple.Item3; + var styleIndex = tuple.Item1; // https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.cell?view=openxml-3.0.1 + var dataType = tuple.Item2; // https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.cellvalues?view=openxml-3.0.1 + var cellValue = tuple.Item3; - if (v != null && (v.StartsWith(" ", StringComparison.Ordinal) || v.EndsWith(" ", StringComparison.Ordinal))) /*Prefix and suffix blank space will lost after SaveAs #294*/ - writer.Write($"{v}"); + if (cellValue != null && (cellValue.StartsWith(" ", StringComparison.Ordinal) || cellValue.EndsWith(" ", StringComparison.Ordinal))) /*Prefix and suffix blank space will lost after SaveAs #294*/ + { + writer.Write($"{cellValue}"); + } else + { //t check avoid format error ![image](https://user-images.githubusercontent.com/12729184/118770190-9eee3480-b8b3-11eb-9f5a-87a439f5e320.png) - writer.Write($"{v}"); + writer.Write($"{cellValue}"); + } } - private Tuple GetCellValue(int rowIndex, int cellIndex, object value, ExcelColumnInfo p, bool valueIsNull) + private Tuple GetCellValue(int rowIndex, int cellIndex, object value, ExcelColumnInfo columnInfo, bool valueIsNull) { - var s = "2"; - var v = string.Empty; - var t = "str"; + var styleIndex = "2"; // format code: 0.00 + var cellValue = string.Empty; + var dataType = "str"; if (valueIsNull) { - + // use defaults } else if (value is string str) { - v = ExcelOpenXmlUtils.EncodeXML(str); + cellValue = ExcelOpenXmlUtils.EncodeXML(str); } - else if (p?.ExcelFormat != null && value is IFormattable formattableValue) + else if (columnInfo?.ExcelFormat != null && value is IFormattable formattableValue) { - var formattedStr = formattableValue.ToString(p.ExcelFormat, _configuration.Culture); - v = ExcelOpenXmlUtils.EncodeXML(formattedStr); + var formattedStr = formattableValue.ToString(columnInfo.ExcelFormat, _configuration.Culture); + cellValue = ExcelOpenXmlUtils.EncodeXML(formattedStr); } else { - Type type = null; - if (p == null || p.Key != null) + Type type; + if (columnInfo == null || columnInfo.Key != null) { // TODO: need to optimize // Dictionary need to check type every time, so it's slow.. @@ -472,52 +473,52 @@ namespace MiniExcelLibs.OpenXml } else { - type = p.ExcludeNullableType; //sometime it doesn't need to re-get type like prop + type = columnInfo.ExcludeNullableType; //sometime it doesn't need to re-get type like prop } if (type.IsEnum) { - t = "str"; + dataType = "str"; var description = CustomPropertyHelper.DescriptionAttr(type, value); //TODO: need to optimze if (description != null) - v = description; + cellValue = description; else - v = value.ToString(); + cellValue = value.ToString(); } else if (TypeHelper.IsNumericType(type)) { if (_configuration.Culture != CultureInfo.InvariantCulture) - t = "str"; //TODO: add style format + dataType = "str"; //TODO: add style format else - t = "n"; + dataType = "n"; if (type.IsAssignableFrom(typeof(decimal))) - v = ((decimal)value).ToString(_configuration.Culture); + cellValue = ((decimal)value).ToString(_configuration.Culture); else if (type.IsAssignableFrom(typeof(Int32))) - v = ((Int32)value).ToString(_configuration.Culture); + cellValue = ((Int32)value).ToString(_configuration.Culture); else if (type.IsAssignableFrom(typeof(Double))) - v = ((Double)value).ToString(_configuration.Culture); + cellValue = ((Double)value).ToString(_configuration.Culture); else if (type.IsAssignableFrom(typeof(Int64))) - v = ((Int64)value).ToString(_configuration.Culture); + cellValue = ((Int64)value).ToString(_configuration.Culture); else if (type.IsAssignableFrom(typeof(UInt32))) - v = ((UInt32)value).ToString(_configuration.Culture); + cellValue = ((UInt32)value).ToString(_configuration.Culture); else if (type.IsAssignableFrom(typeof(UInt16))) - v = ((UInt16)value).ToString(_configuration.Culture); + cellValue = ((UInt16)value).ToString(_configuration.Culture); else if (type.IsAssignableFrom(typeof(UInt64))) - v = ((UInt64)value).ToString(_configuration.Culture); + cellValue = ((UInt64)value).ToString(_configuration.Culture); else if (type.IsAssignableFrom(typeof(Int16))) - v = ((Int16)value).ToString(_configuration.Culture); + cellValue = ((Int16)value).ToString(_configuration.Culture); else if (type.IsAssignableFrom(typeof(Single))) - v = ((Single)value).ToString(_configuration.Culture); + cellValue = ((Single)value).ToString(_configuration.Culture); else if (type.IsAssignableFrom(typeof(Single))) - v = ((Single)value).ToString(_configuration.Culture); + cellValue = ((Single)value).ToString(_configuration.Culture); else - v = (decimal.Parse(value.ToString())).ToString(_configuration.Culture); + cellValue = (decimal.Parse(value.ToString())).ToString(_configuration.Culture); } else if (type == typeof(bool)) { - t = "b"; - v = (bool)value ? "1" : "0"; + dataType = "b"; + cellValue = (bool)value ? "1" : "0"; } else if (type == typeof(byte[]) && _configuration.EnableConvertByteArray) { @@ -549,38 +550,61 @@ namespace MiniExcelLibs.OpenXml //TODO:Convert to base64 var base64 = $"@@@fileid@@@,{file.Path}"; - v = ExcelOpenXmlUtils.EncodeXML(base64); - s = "4"; + cellValue = ExcelOpenXmlUtils.EncodeXML(base64); + styleIndex = "4"; } } else if (type == typeof(DateTime)) { if (_configuration.Culture != CultureInfo.InvariantCulture) { - t = "str"; - v = ((DateTime)value).ToString(_configuration.Culture); + dataType = "str"; + cellValue = ((DateTime)value).ToString(_configuration.Culture); } - else if (p == null || p.ExcelFormat == null) + else if (columnInfo == null || columnInfo.ExcelFormat == null) { - t = null; - s = "3"; - v = ((DateTime)value).ToOADate().ToString(CultureInfo.InvariantCulture); + dataType = null; + styleIndex = "3"; + cellValue = ((DateTime)value).ToOADate().ToString(CultureInfo.InvariantCulture); } else { // TODO: now it'll lose date type information - t = "str"; - v = ((DateTime)value).ToString(p.ExcelFormat, _configuration.Culture); + dataType = "str"; + cellValue = ((DateTime)value).ToString(columnInfo.ExcelFormat, _configuration.Culture); } } +#if NETSTANDARD2_0_OR_GREATER + else if (type == typeof(DateOnly)) + { + if (_configuration.Culture != CultureInfo.InvariantCulture) + { + dataType = "str"; + cellValue = ((DateOnly)value).ToString(_configuration.Culture); + } + else if (columnInfo == null || columnInfo.ExcelFormat == null) + { + var day = (DateOnly)value; + dataType = "n"; + styleIndex = "3"; + cellValue = day.ToDateTime(TimeOnly.MinValue).ToOADate().ToString(CultureInfo.InvariantCulture); + } + else + { + // TODO: now it'll lose date type information + dataType = "str"; + cellValue = ((DateOnly)value).ToString(columnInfo.ExcelFormat, _configuration.Culture); + } + } +#endif else { //TODO: _configuration.Culture - v = ExcelOpenXmlUtils.EncodeXML(value.ToString()); + cellValue = ExcelOpenXmlUtils.EncodeXML(value.ToString()); } } - return Tuple.Create(s, t, v); + return Tuple.Create(styleIndex, dataType, cellValue); } private void GenerateSheetByDataTable(MiniExcelStreamWriter writer, DataTable value) @@ -631,7 +655,7 @@ namespace MiniExcelLibs.OpenXml for (int j = 0; j < value.Columns.Count; j++) { var cellValue = value.Rows[i][j]; - WriteCell(writer, yIndex, xIndex, cellValue, null); + WriteCell(writer, yIndex, xIndex, cellValue, columnInfo: null); xIndex++; } writer.Write($""); @@ -683,7 +707,7 @@ namespace MiniExcelLibs.OpenXml for (int i = 0; i < fieldCount; i++) { var cellValue = reader.GetValue(i); - WriteCell(writer, yIndex, xIndex, cellValue, null); + WriteCell(writer, yIndex, xIndex, cellValue, columnInfo: null); xIndex++; } writer.Write($""); diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.Impl.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.Impl.cs index 2c6c379..0e509cb 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.Impl.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.Impl.cs @@ -34,7 +34,7 @@ namespace MiniExcelLibs.OpenXml public class PropInfo { - public PropertyInfo PropertyInfo { get; set; } + public PropertyInfo PropertyInfo { get; set; } public FieldInfo FieldInfo { get; set; } public Type UnderlyingTypePropType { get; set; } public PropertyInfoOrFieldInfo PropertyInfoOrFieldInfo { get; set; } = PropertyInfoOrFieldInfo.None; @@ -128,11 +128,11 @@ namespace MiniExcelLibs.OpenXml ReplaceSharedStringsToStr(sharedStrings, ref rows); GetMercells(doc, worksheet); UpdateDimensionAndGetRowsInfo(inputMaps, ref doc, ref rows, !mergeCells); - + WriteSheetXml(stream, doc, sheetData, mergeCells); } - + private void GetMercells(XmlDocument doc, XmlNode worksheet) { var mergeCells = doc.SelectSingleNode($"/x:worksheet/x:mergeCells", _ns); @@ -199,11 +199,11 @@ namespace MiniExcelLibs.OpenXml ColIndex = StringHelper.GetLetter(att), RowIndex = StringHelper.GetNumber(att) }; - }).OrderBy(x=>x.RowIndex).ToList(); + }).OrderBy(x => x.RowIndex).ToList(); var mergeColumns = columns.Where(s => s.InnerText.Contains("@merge")).ToList(); var endMergeColumns = columns.Where(s => s.InnerText.Contains("@endmerge")).ToList(); - var mergeLimitColumn = mergeColumns.FirstOrDefault(x=>x.InnerText.Contains("@mergelimit")); + var mergeLimitColumn = mergeColumns.FirstOrDefault(x => x.InnerText.Contains("@mergelimit")); foreach (var mergeColumn in mergeColumns) { @@ -226,7 +226,7 @@ namespace MiniExcelLibs.OpenXml x.ColIndex == taggedColumn.Key.ColIndex && x.RowIndex > taggedColumn.Key.RowIndex && x.RowIndex < taggedColumn.Value.RowIndex)); } - + Dictionary lastMergeCellIndexes = new Dictionary(); @@ -242,7 +242,7 @@ namespace MiniExcelLibs.OpenXml var childNodeLetter = StringHelper.GetLetter(att); var childNodeNumber = StringHelper.GetNumber(att); - if(!string.IsNullOrEmpty(childNode.InnerText)) + if (!string.IsNullOrEmpty(childNode.InnerText)) { var xmlNodes = calculatedColumns .Where(j => j.InnerText == childNode.InnerText && j.ColIndex == childNodeLetter) @@ -260,7 +260,7 @@ namespace MiniExcelLibs.OpenXml xmlNodes = xmlNodes.Where(j => j.RowIndex >= limitedNode.RowIndex && j.RowIndex <= limitedMaxNode.RowIndex).ToList(); } - + var firstRow = xmlNodes.FirstOrDefault(); var lastRow = xmlNodes.LastOrDefault(s => s.RowIndex <= firstRow?.RowIndex + xmlNodes.Count && @@ -356,7 +356,7 @@ namespace MiniExcelLibs.OpenXml { isHeaderRow = true; } - else if(row.InnerText.Contains("@merge") && mergeCells) + else if (row.InnerText.Contains("@merge") && mergeCells) { mergeRowCount++; continue; @@ -616,7 +616,7 @@ namespace MiniExcelLibs.OpenXml rowXml.Replace(extract, newCellValue); } - foreach (var propInfo in rowInfo.PropsMap ) + foreach (var propInfo in rowInfo.PropsMap) { var prop = propInfo.Value.PropertyInfo; @@ -729,7 +729,7 @@ namespace MiniExcelLibs.OpenXml writer.Write(CleanXml(_newRow.OuterXml, endPrefix)); } } - + } } } @@ -834,7 +834,7 @@ namespace MiniExcelLibs.OpenXml // change type = str and replace its value c.SetAttribute("t", "str"); } - //TODO: remove sharedstring? + //TODO: remove sharedstring? } } } @@ -943,16 +943,19 @@ namespace MiniExcelLibs.OpenXml } else { - + var values = new Dictionary(); var props = xRowInfo.IEnumerableGenricType.GetProperties(); foreach (var p in props) { - values.Add(p.Name, new PropInfo { PropertyInfo = p, - PropertyInfoOrFieldInfo = PropertyInfoOrFieldInfo.PropertyInfo, - UnderlyingTypePropType = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType }); + values.Add(p.Name, new PropInfo + { + PropertyInfo = p, + PropertyInfoOrFieldInfo = PropertyInfoOrFieldInfo.PropertyInfo, + UnderlyingTypePropType = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType + }); } var fields = xRowInfo.IEnumerableGenricType.GetFields(); @@ -961,9 +964,12 @@ namespace MiniExcelLibs.OpenXml if (!values.ContainsKey(f.Name)) { - values.Add(f.Name, new PropInfo { FieldInfo = f, - PropertyInfoOrFieldInfo = PropertyInfoOrFieldInfo.FieldInfo, - UnderlyingTypePropType = Nullable.GetUnderlyingType(f.FieldType) ?? f.FieldType }); + values.Add(f.Name, new PropInfo + { + FieldInfo = f, + PropertyInfoOrFieldInfo = PropertyInfoOrFieldInfo.FieldInfo, + UnderlyingTypePropType = Nullable.GetUnderlyingType(f.FieldType) ?? f.FieldType + }); } } @@ -994,7 +1000,7 @@ namespace MiniExcelLibs.OpenXml } // auto check type https://github.com/shps951023/MiniExcel/issues/177 var prop = xRowInfo.PropsMap[propNames[1]]; - var type = prop.UnderlyingTypePropType; //avoid nullable + var type = prop.UnderlyingTypePropType; //avoid nullable if (isMultiMatch) { @@ -1041,7 +1047,7 @@ namespace MiniExcelLibs.OpenXml } var column = dt.Columns[propNames[1]]; - var type = Nullable.GetUnderlyingType(column.DataType) ?? column.DataType; //avoid nullable + var type = Nullable.GetUnderlyingType(column.DataType) ?? column.DataType; //avoid nullable if (!xRowInfo.PropsMap.ContainsKey(propNames[1])) throw new InvalidDataException($"{propNames[0]} doesn't have {propNames[1]} property"); diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.MergeCells.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.MergeCells.cs index e1311a2..900086a 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.MergeCells.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.MergeCells.cs @@ -1,4 +1,6 @@ -using System; +using MiniExcelLibs.Utils; +using MiniExcelLibs.Zip; +using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; @@ -6,8 +8,6 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; -using MiniExcelLibs.Utils; -using MiniExcelLibs.Zip; namespace MiniExcelLibs.OpenXml { @@ -28,7 +28,7 @@ namespace MiniExcelLibs.OpenXml private void MergeSameCellsImpl(Stream stream) { stream.CopyTo(_stream); - + var reader = new ExcelOpenXmlSheetReader(_stream, null); var _archive = new ExcelOpenXmlZip(_stream, mode: ZipArchiveMode.Update, true, Encoding.UTF8); { @@ -66,12 +66,12 @@ namespace MiniExcelLibs.OpenXml public Task MergeSameCellsAsync(string path, CancellationToken cancellationToken = default(CancellationToken)) { - return Task.Run(() => MergeSameCells(path),cancellationToken); + return Task.Run(() => MergeSameCells(path), cancellationToken); } public Task MergeSameCellsAsync(byte[] fileInBytes, CancellationToken cancellationToken = default(CancellationToken)) { - return Task.Run(() => MergeSameCells(fileInBytes),cancellationToken); + return Task.Run(() => MergeSameCells(fileInBytes), cancellationToken); } } } \ No newline at end of file diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.cs index aa44b8f..c2a38ea 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlTemplate.cs @@ -4,14 +4,12 @@ namespace MiniExcelLibs.OpenXml using MiniExcelLibs.Utils; using MiniExcelLibs.Zip; using System; - using System.Collections; using System.Collections.Generic; using System.Data; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; - using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Text.RegularExpressions; using System.Threading; @@ -52,7 +50,7 @@ namespace MiniExcelLibs.OpenXml public void SaveAsByTemplateImpl(Stream templateStream, object value) { - //only support xlsx + //only support xlsx Dictionary values = null; if (value is Dictionary) { @@ -119,7 +117,7 @@ namespace MiniExcelLibs.OpenXml // disposing writer disposes streams as well. reopen the entry to read and parse calc functions using (var filledStream = entry.Open()) { - sheetIdx++; + sheetIdx++; var filledDoc = new XmlDocument(); filledDoc.Load(filledStream); var filledSheetData = filledDoc.SelectSingleNode("/x:worksheet/x:sheetData", _ns); @@ -127,18 +125,18 @@ namespace MiniExcelLibs.OpenXml } } - var calcChain = _archive.zipFile.Entries.FirstOrDefault( e => e.FullName.Contains("xl/calcChain.xml")); + var calcChain = _archive.zipFile.Entries.FirstOrDefault(e => e.FullName.Contains("xl/calcChain.xml")); if (calcChain != null) { string calcChainPathname = calcChain.FullName; calcChain.Delete(); - var calcChainEntry = _archive.zipFile.CreateEntry(calcChainPathname); + var calcChainEntry = _archive.zipFile.CreateEntry(calcChainPathname); using (var calcChainStream = calcChainEntry.Open()) { CalcChainHelper.GenerateCalcChainSheet(calcChainStream, _calcChainContent.ToString()); } } - + } _archive.zipFile.Dispose(); diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlUtils.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlUtils.cs index bd0a96b..f22f39e 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlUtils.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlUtils.cs @@ -3,9 +3,9 @@ using MiniExcelLibs.Utils; using System; #if DEBUG - public + public #else - internal + internal #endif static class ExcelOpenXmlUtils { diff --git a/src/MiniExcel/OpenXml/MiniExcelAsyncStreamWriter.cs b/src/MiniExcel/OpenXml/MiniExcelAsyncStreamWriter.cs index 8b81fb7..ffc6474 100644 --- a/src/MiniExcel/OpenXml/MiniExcelAsyncStreamWriter.cs +++ b/src/MiniExcel/OpenXml/MiniExcelAsyncStreamWriter.cs @@ -4,11 +4,11 @@ namespace MiniExcelLibs.OpenXml { + using System; using System.IO; using System.Text; - using System; - using System.Threading.Tasks; using System.Threading; + using System.Threading.Tasks; internal class MiniExcelAsyncStreamWriter : IDisposable { diff --git a/src/MiniExcel/OpenXml/MiniExcelStreamWriter.cs b/src/MiniExcel/OpenXml/MiniExcelStreamWriter.cs index e82ad7c..1cc0018 100644 --- a/src/MiniExcel/OpenXml/MiniExcelStreamWriter.cs +++ b/src/MiniExcel/OpenXml/MiniExcelStreamWriter.cs @@ -10,7 +10,7 @@ namespace MiniExcelLibs.OpenXml private readonly Encoding _encoding; private readonly StreamWriter _streamWriter; private bool disposedValue; - public MiniExcelStreamWriter(Stream stream,Encoding encoding, int bufferSize) + public MiniExcelStreamWriter(Stream stream, Encoding encoding, int bufferSize) { this._stream = stream; this._encoding = encoding; @@ -45,7 +45,7 @@ namespace MiniExcelLibs.OpenXml { if (!disposedValue) { - this._streamWriter?.Dispose(); + this._streamWriter?.Dispose(); disposedValue = true; } } diff --git a/src/MiniExcel/Reflection/Property.cs b/src/MiniExcel/Reflection/Property.cs index a0972d9..f670a5c 100644 --- a/src/MiniExcel/Reflection/Property.cs +++ b/src/MiniExcel/Reflection/Property.cs @@ -10,7 +10,7 @@ namespace MiniExcelLibs { } - public class Property: Member + public class Property : Member { private static readonly ConcurrentDictionary m_cached = new ConcurrentDictionary(); diff --git a/src/MiniExcel/Utils/CustomPropertyHelper.cs b/src/MiniExcel/Utils/CustomPropertyHelper.cs index 97f2b68..794d777 100644 --- a/src/MiniExcel/Utils/CustomPropertyHelper.cs +++ b/src/MiniExcel/Utils/CustomPropertyHelper.cs @@ -191,7 +191,7 @@ { return null; } - //TODO:or configulation Dynamic + //TODO:or configulation Dynamic var excelColumnIndex = excelColumn?.Index > -1 ? excelColumn.Index : (int?)null; return new ExcelColumnInfo { @@ -210,7 +210,7 @@ private static IEnumerable GetExcelPropertyInfo(Type type, BindingFlags bindingFlags, Configuration configuration) { - //TODO:assign column index + //TODO:assign column index return ConvertToExcelCustomPropertyInfo(type.GetProperties(bindingFlags), configuration); } diff --git a/src/MiniExcel/Utils/DateTimeHelper.cs b/src/MiniExcel/Utils/DateTimeHelper.cs index 439e9ad..c9da83b 100644 --- a/src/MiniExcel/Utils/DateTimeHelper.cs +++ b/src/MiniExcel/Utils/DateTimeHelper.cs @@ -1,13 +1,11 @@ namespace MiniExcelLibs.Utils { - using MiniExcelLibs.Utils; using System; - using System.Globalization; #if DEBUG public #else - internal + internal #endif static partial class DateTimeHelper { diff --git a/src/MiniExcel/Utils/ExcelNumberFormat.cs b/src/MiniExcel/Utils/ExcelNumberFormat.cs index 92b3dd1..27fec51 100644 --- a/src/MiniExcel/Utils/ExcelNumberFormat.cs +++ b/src/MiniExcel/Utils/ExcelNumberFormat.cs @@ -131,7 +131,7 @@ namespace MiniExcelLibs.Utils internal class ExcelDateTime { /// - /// The closest .NET DateTime to the specified excel date. + /// The closest .NET DateTime to the specified excel date. /// public DateTime AdjustedDateTime { get; } @@ -658,10 +658,10 @@ namespace MiniExcelLibs.Utils public static bool IsLiteral(string token) { return - token.StartsWith("_",StringComparison.Ordinal) || - token.StartsWith("\\",StringComparison.Ordinal) || - token.StartsWith("\"",StringComparison.Ordinal) || - token.StartsWith("*",StringComparison.Ordinal) || + token.StartsWith("_", StringComparison.Ordinal) || + token.StartsWith("\\", StringComparison.Ordinal) || + token.StartsWith("\"", StringComparison.Ordinal) || + token.StartsWith("*", StringComparison.Ordinal) || token == "," || token == "!" || token == "&" || diff --git a/src/MiniExcel/Utils/ImageHelper.cs b/src/MiniExcel/Utils/ImageHelper.cs index e82f953..861448e 100644 --- a/src/MiniExcel/Utils/ImageHelper.cs +++ b/src/MiniExcel/Utils/ImageHelper.cs @@ -1,9 +1,5 @@ namespace MiniExcelLibs.Utils { - using System; - using System.Linq; - using System.Text; - internal class ImageHelper { public enum ImageFormat diff --git a/src/MiniExcel/Utils/StringHelper.cs b/src/MiniExcel/Utils/StringHelper.cs index da5064f..e0f3bcb 100644 --- a/src/MiniExcel/Utils/StringHelper.cs +++ b/src/MiniExcel/Utils/StringHelper.cs @@ -31,12 +31,12 @@ while (!reader.EOF) { - if (XmlReaderHelper.IsStartElement(reader,"t", _ns)) + if (XmlReaderHelper.IsStartElement(reader, "t", _ns)) { // There are multiple in a . Concatenate within an . result.Append(reader.ReadElementContentAsString()); } - else if (XmlReaderHelper.IsStartElement(reader,"r", _ns)) + else if (XmlReaderHelper.IsStartElement(reader, "r", _ns)) { result.Append(ReadRichTextRun(reader)); } @@ -60,7 +60,7 @@ while (!reader.EOF) { - if (XmlReaderHelper.IsStartElement(reader,"t", _ns)) + if (XmlReaderHelper.IsStartElement(reader, "t", _ns)) { result.Append(reader.ReadElementContentAsString()); } diff --git a/src/MiniExcel/Utils/TypeHelper.cs b/src/MiniExcel/Utils/TypeHelper.cs index a043976..3424c8f 100644 --- a/src/MiniExcel/Utils/TypeHelper.cs +++ b/src/MiniExcel/Utils/TypeHelper.cs @@ -1,6 +1,5 @@ namespace MiniExcelLibs.Utils { - using MiniExcelLibs.Attributes; using MiniExcelLibs.Exceptions; using System; using System.Collections.Generic; diff --git a/src/MiniExcel/Utils/XmlReaderHelper.cs b/src/MiniExcel/Utils/XmlReaderHelper.cs index 97852e4..bc63b47 100644 --- a/src/MiniExcel/Utils/XmlReaderHelper.cs +++ b/src/MiniExcel/Utils/XmlReaderHelper.cs @@ -76,7 +76,7 @@ namespace MiniExcelLibs.Utils return null; } - + public static IEnumerable GetSharedStrings(Stream stream, params string[] nss) { using (var reader = XmlReader.Create(stream)) diff --git a/src/MiniExcel/Utils/calChainHelper.cs b/src/MiniExcel/Utils/calChainHelper.cs index d613443..6747c7a 100644 --- a/src/MiniExcel/Utils/calChainHelper.cs +++ b/src/MiniExcel/Utils/calChainHelper.cs @@ -1,11 +1,5 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Runtime.InteropServices.ComTypes; +using System.IO; using System.Text; -using System.Threading.Tasks; using System.Xml; namespace MiniExcelLibs.Utils @@ -24,7 +18,7 @@ namespace MiniExcelLibs.Utils StringBuilder calcChainContent = new StringBuilder(); - // each c having f nodes + // each c having f nodes var cs = sheetData.SelectNodes($"x:row/x:c[./x:f]", ns); foreach (XmlElement c in cs) { diff --git a/src/MiniExcel/Zip/ExcelOpenXmlZip.cs b/src/MiniExcel/Zip/ExcelOpenXmlZip.cs index da8de15..968becf 100644 --- a/src/MiniExcel/Zip/ExcelOpenXmlZip.cs +++ b/src/MiniExcel/Zip/ExcelOpenXmlZip.cs @@ -16,12 +16,12 @@ namespace MiniExcelLibs.Zip internal MiniExcelZipArchive zipFile; public ReadOnlyCollection entries; - private static readonly XmlReaderSettings XmlSettings = new XmlReaderSettings - { - IgnoreComments = true, - IgnoreWhitespace = true, - XmlResolver = null, - }; + private static readonly XmlReaderSettings XmlSettings = new XmlReaderSettings + { + IgnoreComments = true, + IgnoreWhitespace = true, + XmlResolver = null, + }; public ExcelOpenXmlZip(Stream fileStream, ZipArchiveMode mode = ZipArchiveMode.Read, bool leaveOpen = false, Encoding entryNameEncoding = null) { zipFile = new MiniExcelZipArchive(fileStream, mode, leaveOpen, entryNameEncoding); diff --git a/src/MiniExcel/Zip/MiniExcelZipArchive.cs b/src/MiniExcel/Zip/MiniExcelZipArchive.cs index 7965804..0062559 100644 --- a/src/MiniExcel/Zip/MiniExcelZipArchive.cs +++ b/src/MiniExcel/Zip/MiniExcelZipArchive.cs @@ -7,15 +7,15 @@ namespace MiniExcelLibs.Zip { public class MiniExcelZipArchive : ZipArchive { - public MiniExcelZipArchive(Stream stream, ZipArchiveMode mode, bool leaveOpen, Encoding entryNameEncoding) - : base(stream, mode, leaveOpen, entryNameEncoding) - { - } + public MiniExcelZipArchive(Stream stream, ZipArchiveMode mode, bool leaveOpen, Encoding entryNameEncoding) + : base(stream, mode, leaveOpen, entryNameEncoding) + { + } - public new void Dispose() - { - Dispose(disposing: true); - GC.SuppressFinalize(this); - } + public new void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } } } diff --git a/src/MiniExcel/Zip/ZipPackageInfo.cs b/src/MiniExcel/Zip/ZipPackageInfo.cs index 26115a4..7ee4c05 100644 --- a/src/MiniExcel/Zip/ZipPackageInfo.cs +++ b/src/MiniExcel/Zip/ZipPackageInfo.cs @@ -1,5 +1,4 @@ -using System; -using System.IO.Compression; +using System.IO.Compression; namespace MiniExcelLibs.Zip { diff --git a/tests/MiniExcelTests/MiniExcelCsvTests.cs b/tests/MiniExcelTests/MiniExcelCsvTests.cs index 42aa5a6..904d2d8 100644 --- a/tests/MiniExcelTests/MiniExcelCsvTests.cs +++ b/tests/MiniExcelTests/MiniExcelCsvTests.cs @@ -22,9 +22,9 @@ namespace MiniExcelLibs.Tests var path = PathHelper.GetFile("csv/gb2312_Encoding_Read_Test.csv"); var config = new MiniExcelLibs.Csv.CsvConfiguration() { - StreamReaderFunc = (stream) => new StreamReader(stream,encoding: Encoding.GetEncoding("gb2312")) + StreamReaderFunc = (stream) => new StreamReader(stream, encoding: Encoding.GetEncoding("gb2312")) }; - var rows = MiniExcel.Query(path, true,excelType:ExcelType.CSV,configuration: config).ToList(); + var rows = MiniExcel.Query(path, true, excelType: ExcelType.CSV, configuration: config).ToList(); Assert.Equal("世界你好", rows[0].栏位1); } @@ -37,7 +37,7 @@ namespace MiniExcelLibs.Tests new Dictionary{{ "a", @"""<>+-*//}{\\n" }, { "b", 1234567890 },{ "c", true },{ "d", new DateTime(2021, 1, 1) } }, new Dictionary{{ "a", @"Hello World" }, { "b", -1234567890 },{ "c", false },{ "d", new DateTime(2021, 1, 2) } }, }; - MiniExcel.SaveAs(path, values,configuration: new MiniExcelLibs.Csv.CsvConfiguration() {Seperator=';'}); + MiniExcel.SaveAs(path, values, configuration: new MiniExcelLibs.Csv.CsvConfiguration() { Seperator = ';' }); var expected = @"a;b;c;d """"""<>+-*//}{\\n"";1234567890;True;""2021-01-01 00:00:00"" ""Hello World"";-1234567890;False;""2021-01-02 00:00:00"" @@ -54,7 +54,7 @@ namespace MiniExcelLibs.Tests new Dictionary{{ "a", @"""<>+-*//}{\\n" }, { "b", 1234567890 },{ "c", true },{ "d", new DateTime(2021, 1, 1) } }, new Dictionary{{ "a", @"Hello World" }, { "b", -1234567890 },{ "c", false },{ "d", new DateTime(2021, 1, 2) } }, }; - MiniExcel.SaveAs(path, values,configuration: new MiniExcelLibs.Csv.CsvConfiguration() {AlwaysQuote = true}); + MiniExcel.SaveAs(path, values, configuration: new MiniExcelLibs.Csv.CsvConfiguration() { AlwaysQuote = true }); var expected = @"""a"",""b"",""c"",""d"" """"""<>+-*//}{\\n"",""1234567890"",""True"",""2021-01-01 00:00:00"" ""Hello World"",""-1234567890"",""False"",""2021-01-02 00:00:00"" @@ -70,7 +70,7 @@ namespace MiniExcelLibs.Tests { new Dictionary{{ "a", @"potato,banana" }, { "b", "text\ntest" },{ "c", "text\rpotato" },{ "d", new DateTime(2021, 1, 1) } }, }; - MiniExcel.SaveAs(path, values,configuration: new MiniExcelLibs.Csv.CsvConfiguration()); + MiniExcel.SaveAs(path, values, configuration: new MiniExcelLibs.Csv.CsvConfiguration()); var expected = "a,b,c,d\r\n\"potato,banana\",\"text\ntest\",\"text\rpotato\",\"2021-01-01 00:00:00\"\r\n"; Assert.Equal(expected, File.ReadAllText(path)); } @@ -206,8 +206,8 @@ namespace MiniExcelLibs.Tests public class Test { public string c1 { get; set; } - public string c2 { get; set; } - } + public string c2 { get; set; } + } public class TestWithAlias { [ExcelColumnName(excelColumnName: "c1", aliases: new[] { "column1", "col1" })] @@ -249,30 +249,30 @@ namespace MiniExcelLibs.Tests } [Fact()] - public void Create2x2_Test() + public void Create2x2_Test() { - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv"); - MiniExcel.SaveAs(path, new[] { - new { c1 = "A1" ,c2 = "B1"}, - new { c1 = "A2" ,c2 = "B2"}, - }); + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv"); + MiniExcel.SaveAs(path, new[] { + new { c1 = "A1" ,c2 = "B1"}, + new { c1 = "A2" ,c2 = "B2"}, + }); using (var stream = File.OpenRead(path)) { - var rows = stream.Query(useHeaderRow: true,excelType:ExcelType.CSV).ToList(); + var rows = stream.Query(useHeaderRow: true, excelType: ExcelType.CSV).ToList(); Assert.Equal("A1", rows[0].c1); Assert.Equal("B1", rows[0].c2); Assert.Equal("A2", rows[1].c1); Assert.Equal("B2", rows[1].c2); } - { - var rows = MiniExcel.Query(path,useHeaderRow: true, excelType: ExcelType.CSV).ToList(); - Assert.Equal("A1", rows[0].c1); - Assert.Equal("B1", rows[0].c2); - Assert.Equal("A2", rows[1].c1); - Assert.Equal("B2", rows[1].c2); - } + { + var rows = MiniExcel.Query(path, useHeaderRow: true, excelType: ExcelType.CSV).ToList(); + Assert.Equal("A1", rows[0].c1); + Assert.Equal("B1", rows[0].c2); + Assert.Equal("A2", rows[1].c1); + Assert.Equal("B2", rows[1].c2); + } File.Delete(path); } @@ -295,13 +295,13 @@ namespace MiniExcelLibs.Tests Assert.Equal("B2", rows[1].c2); } - { - var rows = MiniExcel.Query(path, excelType: ExcelType.CSV).ToList(); - Assert.Equal("A1", rows[0].c1); - Assert.Equal("B1", rows[0].c2); - Assert.Equal("A2", rows[1].c1); - Assert.Equal("B2", rows[1].c2); - } + { + var rows = MiniExcel.Query(path, excelType: ExcelType.CSV).ToList(); + Assert.Equal("A1", rows[0].c1); + Assert.Equal("B1", rows[0].c2); + Assert.Equal("A2", rows[1].c1); + Assert.Equal("B2", rows[1].c2); + } } [Fact()] @@ -364,46 +364,46 @@ namespace MiniExcelLibs.Tests } [Fact()] - public void Delimiters_Test() + public void Delimiters_Test() { - //TODO:Datetime have default format like yyyy-MM-dd HH:mm:ss ? - { - Assert.Equal(Generate("\"\"\""), MiniExcelGenerateCsv("\"\"\"")); - Assert.Equal(Generate(","), MiniExcelGenerateCsv(",")); - Assert.Equal(Generate(" "), MiniExcelGenerateCsv(" ")); - Assert.Equal(Generate(";"), MiniExcelGenerateCsv(";")); - Assert.Equal(Generate("\t"), MiniExcelGenerateCsv("\t")); - } - } + //TODO:Datetime have default format like yyyy-MM-dd HH:mm:ss ? + { + Assert.Equal(Generate("\"\"\""), MiniExcelGenerateCsv("\"\"\"")); + Assert.Equal(Generate(","), MiniExcelGenerateCsv(",")); + Assert.Equal(Generate(" "), MiniExcelGenerateCsv(" ")); + Assert.Equal(Generate(";"), MiniExcelGenerateCsv(";")); + Assert.Equal(Generate("\t"), MiniExcelGenerateCsv("\t")); + } + } - string Generate(string value) - { - var records = Enumerable.Range(1, 1).Select((s, idx) => new { v1 = value, v2 = value }); - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv"); - using (var writer = new StreamWriter(path)) - using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) - { - csv.WriteRecords(records); - } + string Generate(string value) + { + var records = Enumerable.Range(1, 1).Select((s, idx) => new { v1 = value, v2 = value }); + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv"); + using (var writer = new StreamWriter(path)) + using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) + { + csv.WriteRecords(records); + } - var content = File.ReadAllText(path); - File.Delete(path); - return content; - } + var content = File.ReadAllText(path); + File.Delete(path); + return content; + } - string MiniExcelGenerateCsv(string value) - { - var records = Enumerable.Range(1, 1).Select((s, idx) => new { v1 = value, v2 = value }); - var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv"); + string MiniExcelGenerateCsv(string value) + { + var records = Enumerable.Range(1, 1).Select((s, idx) => new { v1 = value, v2 = value }); + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv"); using (var stream = File.Create(path)) { - stream.SaveAs(records,excelType:ExcelType.CSV); + stream.SaveAs(records, excelType: ExcelType.CSV); } - var content = File.ReadAllText(path); - File.Delete(path); - return content; - } + var content = File.ReadAllText(path); + File.Delete(path); + return content; + } } } \ No newline at end of file diff --git a/tests/MiniExcelTests/MiniExcelIssueAsyncTests.cs b/tests/MiniExcelTests/MiniExcelIssueAsyncTests.cs index ee1ef9e..bf51e63 100644 --- a/tests/MiniExcelTests/MiniExcelIssueAsyncTests.cs +++ b/tests/MiniExcelTests/MiniExcelIssueAsyncTests.cs @@ -158,15 +158,17 @@ namespace MiniExcelLibs.Tests { var path = PathHelper.GetFile("xls/TestIssue242.xls"); - await Assert.ThrowsAsync(async () => { + await Assert.ThrowsAsync(async () => + { var q = await MiniExcel.QueryAsync(path); q.ToList(); }); using (var stream = File.OpenRead(path)) { - await Assert.ThrowsAsync(async () => { - var q = await stream.QueryAsync(); + await Assert.ThrowsAsync(async () => + { + var q = await stream.QueryAsync(); q.ToList(); }); } @@ -801,7 +803,7 @@ namespace MiniExcelLibs.Tests using (var stream = new MemoryStream()) { stream.SaveAs(new[] { new { V = "test1" }, new { V = "test2" } }); - var q = (await stream.QueryAsync(true)).Cast>(); + var q = (await stream.QueryAsync(true)).Cast>(); var rows = q.ToList(); Assert.Equal("test1", rows[0]["V"]); Assert.Equal("test2", rows[1]["V"]); @@ -852,7 +854,7 @@ Leave"; var outputPath = PathHelper.GetTempPath(); MiniExcel.SaveAs(outputPath, rows); - var q1 = await MiniExcel.QueryAsync(outputPath); + var q1 = await MiniExcel.QueryAsync(outputPath); var rows2 = q1.ToList(); Assert.Equal(Issue89VO.WorkState.OnDuty, rows2[0].State); Assert.Equal(Issue89VO.WorkState.Fired, rows2[1].State); @@ -1369,7 +1371,7 @@ MyProperty4,MyProperty1,MyProperty5,MyProperty2,MyProperty6,,MyProperty3 { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); //MiniExcel.SaveAs(path, new[] { "1", "2" }); - await Assert.ThrowsAnyAsync(async() => await MiniExcel.SaveAsAsync(path, new[] { 1, 2 })); + await Assert.ThrowsAnyAsync(async () => await MiniExcel.SaveAsAsync(path, new[] { 1, 2 })); File.Delete(path); await Assert.ThrowsAnyAsync(async () => await MiniExcel.SaveAsAsync(path, new[] { "1", "2" })); File.Delete(path); diff --git a/tests/MiniExcelTests/MiniExcelIssueTests.cs b/tests/MiniExcelTests/MiniExcelIssueTests.cs index cbdaa43..4030a0e 100644 --- a/tests/MiniExcelTests/MiniExcelIssueTests.cs +++ b/tests/MiniExcelTests/MiniExcelIssueTests.cs @@ -1,10 +1,13 @@ using Dapper; using MiniExcelLibs.Attributes; +using MiniExcelLibs.Csv; +using MiniExcelLibs.Exceptions; using MiniExcelLibs.OpenXml; using MiniExcelLibs.Tests.Utils; using Newtonsoft.Json; using OfficeOpenXml; using System; +using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; @@ -13,28 +16,23 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; using static MiniExcelLibs.Tests.MiniExcelOpenXmlTests; -using System.Collections; -using MiniExcelLibs.Exceptions; -using System.Text.RegularExpressions; -using MiniExcelLibs.Csv; -using System.Threading.Tasks; -using System.Data.SqlClient; namespace MiniExcelLibs.Tests { - public partial class MiniExcelIssueTests { private readonly ITestOutputHelper output; + public MiniExcelIssueTests(ITestOutputHelper output) { this.output = output; } - [Fact] public void TestIssue24020201() { @@ -43,7 +41,7 @@ namespace MiniExcelLibs.Tests var templatePath = PathHelper.GetFile("xlsx/TestIssue24020201.xlsx"); var data = new Dictionary() { - ["title"]="This's title", + ["title"] = "This's title", ["B"] = new List>() { new Dictionary(){ { "specialMark", 1 } }, @@ -60,9 +58,12 @@ namespace MiniExcelLibs.Tests { var path = PathHelper.GetTempFilePath(); var templatePath = PathHelper.GetFile("xlsx/TestIssue553.xlsx"); - var data = new { B = new[] { + var data = new + { + B = new[] { new{ ITM=1 },new{ ITM=2 }, new{ ITM=3 }, - } }; + } + }; MiniExcel.SaveAsByTemplate(path, templatePath, data); } @@ -132,7 +133,7 @@ namespace MiniExcelLibs.Tests ", content); } { - var value = new { ID=3,Name = "Mike", InDate = new DateTime(2021, 04, 23) }; + var value = new { ID = 3, Name = "Mike", InDate = new DateTime(2021, 04, 23) }; MiniExcel.Insert(path, value); var content = File.ReadAllText(path); Assert.Equal(@"ID,Name,InDate @@ -194,7 +195,7 @@ namespace MiniExcelLibs.Tests var path = Path.GetTempPath() + Guid.NewGuid() + ".xlsx"; DataTableReader reader = table.CreateDataReader(); var config = new OpenXmlConfiguration() { FastMode = true }; - MiniExcel.SaveAs(path, reader,configuration:config); + MiniExcel.SaveAs(path, reader, configuration: config); var xml = Helpers.GetZipFileContent(path, "xl/worksheets/sheet1.xml"); Assert.Contains("", xml); Assert.Contains("", xml); diff --git a/tests/MiniExcelTests/MiniExcelOpenXmlAsyncTests.cs b/tests/MiniExcelTests/MiniExcelOpenXmlAsyncTests.cs index 06cd18b..6a15cfa 100644 --- a/tests/MiniExcelTests/MiniExcelOpenXmlAsyncTests.cs +++ b/tests/MiniExcelTests/MiniExcelOpenXmlAsyncTests.cs @@ -1,21 +1,21 @@ -using Xunit; -using System; -using System.Linq; -using System.IO; -using OfficeOpenXml; -using ClosedXML.Excel; -using System.IO.Packaging; -using System.Data; -using ExcelDataReader; -using System.Collections.Generic; -using System.Data.SQLite; +using ClosedXML.Excel; using Dapper; -using System.Globalization; -using static MiniExcelLibs.Tests.Utils.MiniExcelOpenXml; -using MiniExcelLibs.Tests.Utils; +using ExcelDataReader; using MiniExcelLibs.Attributes; -using System.Threading.Tasks; +using MiniExcelLibs.Tests.Utils; +using OfficeOpenXml; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SQLite; +using System.Globalization; +using System.IO; +using System.IO.Packaging; +using System.Linq; using System.Threading; +using System.Threading.Tasks; +using Xunit; +using static MiniExcelLibs.Tests.Utils.MiniExcelOpenXml; namespace MiniExcelLibs.Tests { @@ -208,7 +208,7 @@ namespace MiniExcelLibs.Tests var path = @"../../../../../samples/xlsx/TestCenterEmptyRow/TestCenterEmptyRow.xlsx"; using (var stream = File.OpenRead(path)) { - var d = (await stream.QueryAsync()).Cast>(); + var d = (await stream.QueryAsync()).Cast>(); var rows = d.ToList(); Assert.Equal("a", rows[0]["A"]); Assert.Equal("b", rows[0]["B"]); @@ -279,7 +279,7 @@ namespace MiniExcelLibs.Tests var path = @"../../../../../samples/xlsx/TestDynamicQueryBasic_WithoutHead.xlsx"; using (var stream = File.OpenRead(path)) { - var d= (await stream.QueryAsync()).Cast>(); + var d = (await stream.QueryAsync()).Cast>(); var rows = d.ToList(); Assert.Equal("MiniExcel", rows[0]["A"]); Assert.Equal(1d, rows[0]["B"]); @@ -377,7 +377,7 @@ namespace MiniExcelLibs.Tests var path = @"../../../../../samples/xlsx/TestTypeMapping_AutoCheckFormat.xlsx"; using (var stream = FileHelper.OpenRead(path)) { - var d= await stream.QueryAsync(); + var d = await stream.QueryAsync(); d.ToList(); } } @@ -661,14 +661,14 @@ namespace MiniExcelLibs.Tests var rows = d.ToList(); Assert.Equal(2, rows.Count); Assert.Equal(@"""<>+-*//}{\\n", rows[0]["a"]); - Assert.Equal(1234567890d,rows[0]["b"]); + Assert.Equal(1234567890d, rows[0]["b"]); Assert.Null(rows[0]["c"]); Assert.Null(rows[0]["d"]); } using (var stream = File.OpenRead(path)) { - var d= (await stream.QueryAsync()).Cast>(); + var d = (await stream.QueryAsync()).Cast>(); var rows = d.ToList(); Assert.Equal(3, rows.Count); Assert.Equal("a", rows[0]["A"]); @@ -1020,7 +1020,7 @@ namespace MiniExcelLibs.Tests { var rows = (await stream.QueryAsync()).Cast>(); foreach (var row in rows) - connection.Execute("insert into T (A,B) values (@A,@B)", new { A = row["A"],B = row["B"] }, transaction: transaction); + connection.Execute("insert into T (A,B) values (@A,@B)", new { A = row["A"], B = row["B"] }, transaction: transaction); transaction.Commit(); } } @@ -1205,7 +1205,8 @@ namespace MiniExcelLibs.Tests [Fact()] public async Task ReadBigExcel_TakeCancel_Throws_TaskCanceledException() { - await Assert.ThrowsAsync(async () => { + await Assert.ThrowsAsync(async () => + { CancellationTokenSource cts = new CancellationTokenSource(); var path = @"../../../../../samples/xlsx/bigExcel.xlsx"; @@ -1222,7 +1223,8 @@ namespace MiniExcelLibs.Tests [Fact()] public async Task ReadBigExcel_Prcoessing_TakeCancel_Throws_TaskCanceledException() { - await Assert.ThrowsAsync(async () => { + await Assert.ThrowsAsync(async () => + { CancellationTokenSource cts = new CancellationTokenSource(); var path = @"../../../../../samples/xlsx/bigExcel.xlsx"; diff --git a/tests/MiniExcelTests/MiniExcelOpenXmlMultipleSheetAsyncTests.cs b/tests/MiniExcelTests/MiniExcelOpenXmlMultipleSheetAsyncTests.cs index ca6ad1d..6b19ce4 100644 --- a/tests/MiniExcelTests/MiniExcelOpenXmlMultipleSheetAsyncTests.cs +++ b/tests/MiniExcelTests/MiniExcelOpenXmlMultipleSheetAsyncTests.cs @@ -1,9 +1,9 @@ -using Xunit; -using System.Linq; -using System; -using System.IO; -using System.Threading.Tasks; +using System; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Xunit; namespace MiniExcelLibs.Tests { @@ -35,8 +35,9 @@ namespace MiniExcelLibs.Tests Assert.Equal(2, rows[0].B); } { - await Assert.ThrowsAsync(async() => { - var q= await MiniExcel.QueryAsync(path, sheetName: "xxxx"); + await Assert.ThrowsAsync(async () => + { + var q = await MiniExcel.QueryAsync(path, sheetName: "xxxx"); q.ToList(); }); } diff --git a/tests/MiniExcelTests/MiniExcelOpenXmlMultipleSheetTests.cs b/tests/MiniExcelTests/MiniExcelOpenXmlMultipleSheetTests.cs index 57c8c00..75ac1c2 100644 --- a/tests/MiniExcelTests/MiniExcelOpenXmlMultipleSheetTests.cs +++ b/tests/MiniExcelTests/MiniExcelOpenXmlMultipleSheetTests.cs @@ -164,12 +164,12 @@ namespace MiniExcelLibs.Tests Assert.Equal(2, users.Count()); Assert.Equal("Jack", users[0].Name); - // take second sheet by sheet name + // take second sheet by sheet name var departments = stream.Query(sheetName: "Departments", configuration: configuration, useHeaderRow: true).ToList(); Assert.Equal(2, departments.Count()); Assert.Equal("HR", departments[0].Name); - // take second sheet by sheet key + // take second sheet by sheet key departments = stream.Query(sheetName: "departmentSheet", configuration: configuration, useHeaderRow: true).ToList(); Assert.Equal(2, departments.Count()); Assert.Equal("HR", departments[0].Name); @@ -181,12 +181,12 @@ namespace MiniExcelLibs.Tests Assert.Equal(2, users.Count()); Assert.Equal("Jack", users[0].Name); - // take second sheet by sheet name + // take second sheet by sheet name var departments = MiniExcel.Query(path, sheetName: "Departments", configuration: configuration, useHeaderRow: true).ToList(); Assert.Equal(2, departments.Count()); Assert.Equal("HR", departments[0].Name); - // take second sheet by sheet key + // take second sheet by sheet key departments = MiniExcel.Query(path, sheetName: "departmentSheet", configuration: configuration, useHeaderRow: true).ToList(); Assert.Equal(2, departments.Count()); Assert.Equal("HR", departments[0].Name); diff --git a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs index d19eb0a..bd95f28 100644 --- a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs +++ b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs @@ -1,22 +1,22 @@ -using Xunit; -using System; -using System.Linq; -using System.IO; -using OfficeOpenXml; -using ClosedXML.Excel; -using System.IO.Packaging; -using System.Data; -using ExcelDataReader; -using System.Collections.Generic; -using System.Data.SQLite; -using System.Diagnostics; +using ClosedXML.Excel; using Dapper; -using System.Globalization; -using static MiniExcelLibs.Tests.Utils.MiniExcelOpenXml; -using MiniExcelLibs.Tests.Utils; +using ExcelDataReader; using MiniExcelLibs.Attributes; using MiniExcelLibs.OpenXml; +using MiniExcelLibs.Tests.Utils; +using OfficeOpenXml; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SQLite; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.IO.Packaging; +using System.Linq; +using Xunit; using Xunit.Abstractions; +using static MiniExcelLibs.Tests.Utils.MiniExcelOpenXml; namespace MiniExcelLibs.Tests { @@ -1177,12 +1177,12 @@ namespace MiniExcelLibs.Tests Assert.Equal(new[] { "A", "B", "C" }, columns); var rows = MiniExcel.Query(path).ToList(); - Assert.Equal(rows[0].A , "title1"); - Assert.Equal(rows[0].B , "title2"); - Assert.Equal(rows[0].C , "title3"); - Assert.Equal(rows[1].A , "value1"); - Assert.Equal(rows[1].B , "value2"); - Assert.Equal(rows[1].C , "value3"); + Assert.Equal(rows[0].A, "title1"); + Assert.Equal(rows[0].B, "title2"); + Assert.Equal(rows[0].C, "title3"); + Assert.Equal(rows[1].A, "value1"); + Assert.Equal(rows[1].B, "value2"); + Assert.Equal(rows[1].C, "value3"); } [Fact] @@ -1250,7 +1250,7 @@ namespace MiniExcelLibs.Tests using (var stream = File.OpenRead(path)) { var rows = stream.Query(useHeaderRow: true) - .Select(x => (IDictionary)x) + .Select(x => (IDictionary)x) .ToList(); Assert.Contains("Name of something", rows[0]); diff --git a/tests/MiniExcelTests/MiniExcelTemplateAsyncTests.cs b/tests/MiniExcelTests/MiniExcelTemplateAsyncTests.cs index dc2cb12..01f93aa 100644 --- a/tests/MiniExcelTests/MiniExcelTemplateAsyncTests.cs +++ b/tests/MiniExcelTests/MiniExcelTemplateAsyncTests.cs @@ -8,8 +8,6 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Xml; -using MiniExcelLibs.OpenXml; using Xunit; namespace MiniExcelTests @@ -551,7 +549,7 @@ namespace MiniExcelTests { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); var templatePath = @"../../../../../samples/xlsx/TestTemplateBasicIEmumerableFill.xlsx"; - + //1. By POCO var value = new { @@ -565,7 +563,7 @@ namespace MiniExcelTests } }; await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value); - + var demension = Helpers.GetFirstSheetDimensionRefValue(path); Assert.Equal("A1:B7", demension); } @@ -625,7 +623,7 @@ namespace MiniExcelTests { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); var templatePath = @"../../../../../samples/xlsx/TestTemplateBasicIEmumerableFillGroup.xlsx"; - + //1. By POCO var value = new { @@ -639,7 +637,7 @@ namespace MiniExcelTests } }; await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value); - + var demension = Helpers.GetFirstSheetDimensionRefValue(path); Assert.Equal("A1:B18", demension); } @@ -699,7 +697,7 @@ namespace MiniExcelTests { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); var templatePath = @"../../../../../samples/xlsx/TestTemplateBasicIEmumerableFillConditional.xlsx"; - + //1. By POCO var value = new { @@ -713,15 +711,15 @@ namespace MiniExcelTests } }; await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value); - + var demension = Helpers.GetFirstSheetDimensionRefValue(path); Assert.Equal("A1:B18", demension); } - + { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); var templatePath = @"../../../../../samples/xlsx/TestTemplateBasicIEmumerableFillConditional.xlsx"; - + //2. By Dictionary var value = new Dictionary() { @@ -735,15 +733,15 @@ namespace MiniExcelTests } }; await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value); - + var demension = Helpers.GetFirstSheetDimensionRefValue(path); Assert.Equal("A1:B18", demension); } - + { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); var templatePath = @"../../../../../samples/xlsx/TestTemplateBasicIEmumerableFillConditional.xlsx"; - + //3. By DataTable var dt = new DataTable(); { @@ -761,7 +759,7 @@ namespace MiniExcelTests ["employees"] = dt }; await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value); - + var demension = Helpers.GetFirstSheetDimensionRefValue(path); Assert.Equal("A1:B18", demension); } @@ -890,7 +888,8 @@ namespace MiniExcelTests [Fact()] public async Task SaveAsByTemplateAsync_TakeCancel_Throws_TaskCanceledException() { - await Assert.ThrowsAsync(async () => { + await Assert.ThrowsAsync(async () => + { CancellationTokenSource cts = new CancellationTokenSource(); cts.Cancel(); diff --git a/tests/MiniExcelTests/MiniExcelTemplateTests.cs b/tests/MiniExcelTests/MiniExcelTemplateTests.cs index da51419..8762be5 100644 --- a/tests/MiniExcelTests/MiniExcelTemplateTests.cs +++ b/tests/MiniExcelTests/MiniExcelTemplateTests.cs @@ -840,35 +840,35 @@ namespace MiniExcelTests } } - + [Fact] public void MergeSameCellsWithTagTest() { var mergedFilePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); - + var path = @"../../../../../samples/xlsx/TestMergeWithTag.xlsx"; - + MiniExcel.MergeSameCells(mergedFilePath, path); { var mergedCells = Helpers.GetFirstSheetMergedCells(mergedFilePath); - + Assert.Equal("A2:A4", mergedCells[0]); Assert.Equal("C3:C4", mergedCells[1]); Assert.Equal("A7:A8", mergedCells[2]); } } - + [Fact] public void MergeSameCellsWithLimitTagTest() { var mergedFilePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx"); - + var path = @"../../../../../samples/xlsx/TestMergeWithLimitTag.xlsx"; - + MiniExcel.MergeSameCells(mergedFilePath, path); { var mergedCells = Helpers.GetFirstSheetMergedCells(mergedFilePath); - + Assert.Equal("A3:A4", mergedCells[0]); Assert.Equal("C3:C6", mergedCells[1]); Assert.Equal("A5:A6", mergedCells[2]); diff --git a/tests/MiniExcelTests/Utils/Db.cs b/tests/MiniExcelTests/Utils/Db.cs index b5af88a..2681332 100644 --- a/tests/MiniExcelTests/Utils/Db.cs +++ b/tests/MiniExcelTests/Utils/Db.cs @@ -4,10 +4,9 @@ internal static class Db { - internal static SQLiteConnection GetConnection(string connectionString= "Data Source=:memory:") - { - return new SQLiteConnection(connectionString); - } + internal static SQLiteConnection GetConnection(string connectionString = "Data Source=:memory:") + { + return new SQLiteConnection(connectionString); + } } - } diff --git a/tests/MiniExcelTests/Utils/Helpers.cs b/tests/MiniExcelTests/Utils/Helpers.cs index 5daa006..742def1 100644 --- a/tests/MiniExcelTests/Utils/Helpers.cs +++ b/tests/MiniExcelTests/Utils/Helpers.cs @@ -1,6 +1,5 @@ namespace MiniExcelLibs.Tests.Utils { - using MiniExcelLibs.OpenXml; using System; using System.Collections.Generic; using System.IO; @@ -69,14 +68,14 @@ } return result; } - internal static string GetZipFileContent(string zipPath,string filePath) + internal static string GetZipFileContent(string zipPath, string filePath) { var ns = new XmlNamespaceManager(new NameTable()); ns.AddNamespace("x", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); using (var stream = File.OpenRead(zipPath)) using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Read, false, Encoding.UTF8)) { - var sheet = archive.Entries.Single(w => w.FullName== filePath); + var sheet = archive.Entries.Single(w => w.FullName == filePath); using (var sheetStream = sheet.Open()) { var doc = XDocument.Load(sheetStream); @@ -123,8 +122,8 @@ var doc = new XmlDocument(); doc.Load(sheetStream); var mergeCells = doc.SelectSingleNode($"/x:worksheet/x:mergeCells", ns)?.Cast().ToList(); - - if(mergeCells is { Count: > 0 }) + + if (mergeCells is { Count: > 0 }) { for (int i = 0; i < mergeCells.Count; i++) {