diff --git a/MiniExcel.sln b/MiniExcel.sln index c6457cd..20dc5eb 100644 --- a/MiniExcel.sln +++ b/MiniExcel.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniExcelLibs", "src\MiniExcel\MiniExcelLibs.csproj", "{097903C9-1F81-4427-B4C8-530CB59687B8}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2AFABF2E-D6C3-4983-B43A-76ADA2BB2876}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs and setting", "Docs and setting", "{2AFABF2E-D6C3-4983-B43A-76ADA2BB2876}" ProjectSection(SolutionItems) = preProject .gitattributes = .gitattributes .gitignore = .gitignore @@ -21,7 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CC1E0601-AEC EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{359A7094-3353-48F2-B3E1-FE9E59698318}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{3E370222-8E9E-45E8-8DCD-E5F41EE52A39}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Releases", "Releases", "{3E370222-8E9E-45E8-8DCD-E5F41EE52A39}" ProjectSection(SolutionItems) = preProject docs\README.md = docs\README.md docs\README.zh-CN.md = docs\README.zh-CN.md diff --git a/docs/README.md b/docs/README.md index b8cccf2..0a33ee7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -22,7 +22,14 @@ --- + + +### 1.27.0 + +- [Optimization] SaveAs by datareader support dimension #231 (via @shps951023) + ### 1.26.7 + - [OPT] Reduce memory allocation when using MemoryStream #427 (via @cupsos) - [OPT] Add System.Memory pacakge #427 (via @cupsos) - [OPT] Reduce memory allocation in GetImageFormat() #427 (via @cupsos) diff --git a/docs/README.zh-CN.md b/docs/README.zh-CN.md index ac6f071..9bb1c2e 100644 --- a/docs/README.zh-CN.md +++ b/docs/README.zh-CN.md @@ -25,7 +25,14 @@ --- + + +### 1.27.0 + +- [Optimization] SaveAs by datareader 支持 dimension #231 (via @shps951023) + ### 1.26.7 + - [OPT] 减少 memory allocation 使用 MemoryStream #427 (via @cupsos) - [OPT] 添加 System.Memory pacakge #427 (via @cupsos) - [OPT] 减少 memory allocation in GetImageFormat() #427 (via @cupsos) diff --git a/docs/README.zh-Hant.md b/docs/README.zh-Hant.md index 6e6c49d..942f686 100644 --- a/docs/README.zh-Hant.md +++ b/docs/README.zh-Hant.md @@ -25,7 +25,13 @@ --- + +### 1.27.0 + +- [Optimization] SaveAs by datareader 支持 dimension #231 (via @shps951023) + ### 1.26.7 + - [OPT] 減少 memory allocation 使用 MemoryStream #427 (via @cupsos) - [OPT] 添加 System.Memory pacakge #427 (via @cupsos) - [OPT] 減少 memory allocation in GetImageFormat() #427 (via @cupsos) diff --git a/src/MiniExcel/MiniExcelLibs.csproj b/src/MiniExcel/MiniExcelLibs.csproj index 9afcfc2..8afec0a 100644 --- a/src/MiniExcel/MiniExcelLibs.csproj +++ b/src/MiniExcel/MiniExcelLibs.csproj @@ -1,31 +1,32 @@  net45;netstandard2.0;net5.0 - 1.26.7 + 1.27.0 MiniExcel MiniExcel MiniExcel excel;xlsx;csv;micro-helper;mini;openxml;helper; - Fast, Low-Memory, Easy Excel .NET helper to import/export/template spreadsheet + + Fast, Low-Memory, Easy Excel .NET helper to import/export/template spreadsheet -Github : https://github.com/shps951023/MiniExcel -Gitee : https://gitee.com/dotnetchina/MiniExcel -Issues : https://github.com/shps951023/MiniExcel/issues -Todo : https://github.com/shps951023/MiniExcel/projects/1?fullscreen=true - + Github : https://github.com/MiniExcel/MiniExcel + Gitee : https://gitee.com/dotnetchina/MiniExcel + Issues : https://github.com/MiniExcel/MiniExcel/issues + Todo : https://github.com/MiniExcel/MiniExcel/projects/1?fullscreen=true + LIN,WEI-HAN MiniExcel LIN,WEI-HAN, 2021 onwards en - https://raw.githubusercontent.com/shps951023/MiniExcel/master/LICENSE + https://raw.githubusercontent.com/MiniExcel/MiniExcel/master/LICENSE MiniExcelLibs Apache-2.0 - https://github.com/shps951023/MiniExcel - https://github.com/shps951023/MiniExcel + https://github.com/MiniExcel/MiniExcel + https://github.com/MiniExcel/MiniExcel icon.png - Please Check [Release Notes](https://github.com/shps951023/MiniExcel/tree/master/docs) + Please Check [Release Notes](https://github.com/MiniExcel/MiniExcel/tree/master/docs) Github @@ -35,14 +36,14 @@ Todo : https://github.com/shps951023/MiniExcel/projects/1?fullscreen=true - - PreserveNewest - + + PreserveNewest + + + + + + + - - - - - - diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs index 5476ab4..ee6fdc9 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs @@ -54,7 +54,9 @@ namespace MiniExcelLibs.OpenXml public ExcelOpenXmlSheetWriter(Stream stream, object value, string sheetName, IConfiguration configuration, bool printHeader) { this._stream = stream; - this._archive = new MiniExcelZipArchive(_stream, ZipArchiveMode.Create, true, _utf8WithBom); + // Why ZipArchiveMode.Update not ZipArchiveMode.Create? + // R : Mode create - ZipArchiveEntry does not support seeking.' + this._archive = new MiniExcelZipArchive(_stream, ZipArchiveMode.Update, true, _utf8WithBom); this._configuration = configuration as OpenXmlConfiguration ?? OpenXmlConfiguration.DefaultConfig; this._printHeader = printHeader; this._value = value; @@ -579,15 +581,13 @@ namespace MiniExcelLibs.OpenXml private void GenerateSheetByIDataReader(MiniExcelStreamWriter writer, IDataReader reader) { var xy = ExcelOpenXmlUtils.ConvertCellToXY("A1"); /*TODO:code smell*/ - + long dimensionWritePosition = 0; writer.Write($@""); var yIndex = xy.Item2; var xIndex = 0; { - // TODO: dimension - //var maxRowIndex = value.Rows.Count + (printHeader && value.Rows.Count > 0 ? 1 : 0); - //var maxColumnIndex = value.Columns.Count; - //writer.Write($@""); + dimensionWritePosition = writer.WriteAndFlush($@""); // end of code will be replaced writer.Write(""); int fieldCount = reader.FieldCount; if (_printHeader) @@ -623,7 +623,10 @@ namespace MiniExcelLibs.OpenXml writer.Write(""); if (_configuration.AutoFilter) writer.Write($""); - writer.Write(""); + writer.WriteAndFlush(""); + + writer.SetPosition(dimensionWritePosition); + writer.WriteAndFlush($@"A1:{ExcelOpenXmlUtils.ConvertXyToCell((xIndex - 1)/*TODO:code smell*/, yIndex - 1)}"""); } private static void WriteC(MiniExcelStreamWriter writer, string r, string columnName) diff --git a/src/MiniExcel/OpenXml/MiniExcelStreamWriter.cs b/src/MiniExcel/OpenXml/MiniExcelStreamWriter.cs index 1031119..a926cb8 100644 --- a/src/MiniExcel/OpenXml/MiniExcelStreamWriter.cs +++ b/src/MiniExcel/OpenXml/MiniExcelStreamWriter.cs @@ -8,53 +8,42 @@ namespace MiniExcelLibs.OpenXml { private readonly Stream _stream; private readonly Encoding _encoding; - private readonly StreamWriter _streamWriter; + internal readonly StreamWriter _streamWriter; private bool disposedValue; - //private byte[] _cacheValueBytes; - public MiniExcelStreamWriter(Stream stream,Encoding encoding, int bufferSize) { this._stream = stream; this._encoding = encoding; this._streamWriter = new StreamWriter(stream, this._encoding, bufferSize); } - public void Write(string content,bool flushImmediately=false) + public void Write(string content) { if (string.IsNullOrEmpty(content)) return; - //if (flushImmediately) - //else - //_cacheValueBytes.CopyTo - //TODO: - //var bytes = this._encoding.GetBytes(content); - //this._stream.Write(bytes, 0, bytes.Length); - this._streamWriter.Write(content); } + public long WriteAndFlush(string content) + { + this.Write(content); + this._streamWriter.Flush(); + return this._streamWriter.BaseStream.Position; + } + + public void SetPosition(long position) + { + this._streamWriter.BaseStream.Position = position; + } + protected virtual void Dispose(bool disposing) { if (!disposedValue) { - if (disposing) - { - // TODO: dispose managed state (managed objects) - } - - // free unmanaged resources (unmanaged objects) and override finalizer - this._streamWriter?.Dispose(); - // TODO: set large fields to null + this._streamWriter?.Dispose(); disposedValue = true; } } - // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources - // ~MiniExcelStreamWriter() - // { - // // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method - // Dispose(disposing: false); - // } - public void Dispose() { // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method diff --git a/tests/LINQPad/ZipArchive Set Position.linq b/tests/LINQPad/ZipArchive Set Position.linq new file mode 100644 index 0000000..d4f1ee5 --- /dev/null +++ b/tests/LINQPad/ZipArchive Set Position.linq @@ -0,0 +1,41 @@ + + MiniExcel + MiniExcelLibs + + +void Main() +{ + ConsoleApplication.Program.Main(null); +} + +// You can define other methods, fields, classes and namespaces here + + +namespace ConsoleApplication +{ + using System; + using System.IO; + using System.IO.Compression; + public class Program + { + public static void Main(string[] args) + { + var path = Path.GetTempPath() + Guid.NewGuid() + ".zip"; + Console.WriteLine(path); + using (FileStream zipToOpen = new FileStream(path, FileMode.Create)) + { + using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update)) + { + ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt"); + using (StreamWriter writer = new StreamWriter(readmeEntry.Open())) + { + writer.WriteLine("Information about this package."); + writer.Flush(); + writer.BaseStream.Position=0; + writer.WriteLine("========================"); + } + } + } + } + } +} \ No newline at end of file diff --git a/tests/MiniExcelTests/MiniExcelIssueTests.cs b/tests/MiniExcelTests/MiniExcelIssueTests.cs index 7e508f8..8d3d95e 100644 --- a/tests/MiniExcelTests/MiniExcelIssueTests.cs +++ b/tests/MiniExcelTests/MiniExcelIssueTests.cs @@ -34,6 +34,26 @@ namespace MiniExcelLibs.Tests this.output = output; } + [Fact] + public void TestIssue_DataReaderSupportDimension() + { + { + DataTable table = new DataTable(); + { + table.Columns.Add("id", typeof(int)); + table.Columns.Add("name", typeof(string)); + table.Rows.Add(1, "Jack"); + table.Rows.Add(2, "Mike"); + } + var path = Path.GetTempPath() + Guid.NewGuid() + ".xlsx"; + DataTableReader reader = table.CreateDataReader(); + MiniExcel.SaveAs(path, reader); + var xml = Helpers.GetZipFileContent(path, "xl/worksheets/sheet1.xml"); + Assert.Contains("", xml); + Assert.Contains("", xml); + } + } + /// /// [ · Issue #413 · MiniExcel/MiniExcel] /// (https://github.com/MiniExcel/MiniExcel/issues/413)