Skip to content

Commit 22f522b

Browse files
authored
Merge branch 'mini-software:master' into master
2 parents 0fd519c + a30d3bb commit 22f522b

10 files changed

Lines changed: 90 additions & 24 deletions

File tree

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,17 @@ MiniExcel.Query(path, configuration: config);
11621162
}
11631163
```
11641164

1165+
#### 5. FastMode
1166+
1167+
System will not control memory, but you can get faster save speed.
1168+
1169+
```csharp
1170+
var config = new OpenXmlConfiguration() { FastMode = true };
1171+
MiniExcel.SaveAs(path, reader,configuration:config);
1172+
```
1173+
1174+
1175+
11651176

11661177

11671178

README.zh-CN.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,15 @@ MiniExcel.Query(path, configuration: config);
11591159
}
11601160
```
11611161

1162+
#### 5. FastMode
1163+
1164+
系统不会限制内存,达到更快的效率
1165+
1166+
```csharp
1167+
var config = new OpenXmlConfiguration() { FastMode = true };
1168+
MiniExcel.SaveAs(path, reader,configuration:config);
1169+
```
1170+
11621171

11631172

11641173
### 例子

README.zh-Hant.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,15 @@ MiniExcel.Query(path,configuration: config);
11591159
}
11601160
```
11611161

1162+
#### 5. FastMode
1163+
1164+
系統不會限制記憶體,達到更快的效率
1165+
1166+
```csharp
1167+
var config = new OpenXmlConfiguration() { FastMode = true };
1168+
MiniExcel.SaveAs(path, reader,configuration:config);
1169+
```
1170+
11621171

11631172

11641173
### 範例

docs/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424

2525

2626

27+
### 1.29.0
28+
29+
- [New] SaveAs support FastMode
30+
- [Bug] Fixed SaveAs OOM problem
31+
2732
### 1.28.2
2833

2934
- [New] Support Assembly Strong Name Signature #450

docs/README.zh-CN.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727

2828

2929

30+
### 1.29.0
31+
32+
- [New] SaveAs 支持 FastMode
33+
- [Bug] 修正 SaveAs OOM
34+
3035
### 1.28.2
3136

3237
- [New] 支持 Assembly Strong Name Signature #450

docs/README.zh-Hant.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626

2727

2828

29+
### 1.29.0
2930

31+
- [New] SaveAs 支持 FastMode
32+
- [Bug] 修正 SaveAs OOM
3033

3134
### 1.28.2
3235

src/MiniExcel/IConfiguration.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ public abstract class Configuration : IConfiguration
99
public CultureInfo Culture { get; set; } = CultureInfo.InvariantCulture;
1010
public DynamicExcelColumn[] DynamicColumns { get; set; }
1111
public int BufferSize { get; set; } = 1024 * 512;
12+
public bool FastMode { get; set; } = false;
1213
}
1314
}

src/MiniExcel/MiniExcelLibs.csproj

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFrameworks>net45;netstandard2.0;net5.0</TargetFrameworks>
4-
<Version>1.28.5</Version>
4+
<Version>1.29.0</Version>
55
</PropertyGroup>
66
<PropertyGroup>
77
<AssemblyName>MiniExcel</AssemblyName>
@@ -29,7 +29,7 @@ Todo : https://github.com/mini-software/MiniExcel/projects/1?fullscreen=true</De
2929
<RepositoryType>Github</RepositoryType>
3030
<AssemblyOriginatorKeyFile>miniexcel.snk</AssemblyOriginatorKeyFile>
3131
<SignAssembly>True</SignAssembly>
32-
<ProjectGuid>{70FA8638-157A-4380-A4F6-8E2C3EE92CAE}</ProjectGuid>
32+
<ProjectGuid>{097903C9-1F81-4427-B4C8-530CB59687B8}</ProjectGuid>
3333
<PublishRepositoryUrl>true</PublishRepositoryUrl>
3434
<IncludeSymbols>true</IncludeSymbols>
3535
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
@@ -51,4 +51,7 @@ Todo : https://github.com/mini-software/MiniExcel/projects/1?fullscreen=true</De
5151
<ItemGroup>
5252
<None Include="icon.png" Pack="true" PackagePath="\" />
5353
</ItemGroup>
54+
<ItemGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
55+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
56+
</ItemGroup>
5457
</Project>

src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,11 @@ public ExcelOpenXmlSheetWriter(Stream stream, object value, string sheetName, IC
5656
this._stream = stream;
5757
// Why ZipArchiveMode.Update not ZipArchiveMode.Create?
5858
// R : Mode create - ZipArchiveEntry does not support seeking.'
59-
this._archive = new MiniExcelZipArchive(_stream, ZipArchiveMode.Update, true, _utf8WithBom);
6059
this._configuration = configuration as OpenXmlConfiguration ?? OpenXmlConfiguration.DefaultConfig;
60+
if (_configuration.FastMode)
61+
this._archive = new MiniExcelZipArchive(_stream, ZipArchiveMode.Update, true, _utf8WithBom);
62+
else
63+
this._archive = new MiniExcelZipArchive(_stream, ZipArchiveMode.Create, true, _utf8WithBom);
6164
this._printHeader = printHeader;
6265
this._value = value;
6366
_sheets.Add(new SheetDto { Name = sheetName, SheetIdx = 1 }); //TODO:remove
@@ -120,7 +123,7 @@ private void CreateSheetXml(object value, string sheetPath)
120123
{
121124
ZipArchiveEntry entry = _archive.CreateEntry(sheetPath, CompressionLevel.Fastest);
122125
using (var zipStream = entry.Open())
123-
using (MiniExcelStreamWriter writer = new MiniExcelStreamWriter(zipStream, _utf8WithBom,_configuration.BufferSize))
126+
using (MiniExcelStreamWriter writer = new MiniExcelStreamWriter(zipStream, _utf8WithBom, _configuration.BufferSize))
124127
{
125128
if (value == null)
126129
{
@@ -166,14 +169,14 @@ private void CreateSheetXml(object value, string sheetPath)
166169
{
167170
mode = "IDictionary<string, object>";
168171
var dic = item as IDictionary<string, object>;
169-
props = GetDictionaryColumnInfo(dic,null);
172+
props = GetDictionaryColumnInfo(dic, null);
170173
maxColumnIndex = props.Count;
171174
}
172175
else if (item is IDictionary)
173176
{
174177
var dic = item as IDictionary;
175178
mode = "IDictionary";
176-
props = GetDictionaryColumnInfo(null,dic);
179+
props = GetDictionaryColumnInfo(null, dic);
177180
//maxColumnIndex = dic.Keys.Count;
178181
maxColumnIndex = props.Count; // why not using keys, because ignore attribute ![image](https://user-images.githubusercontent.com/12729184/163686902-286abb70-877b-4e84-bd3b-001ad339a84a.png)
179182
}
@@ -253,7 +256,7 @@ private void CreateSheetXml(object value, string sheetPath)
253256
WriteC(writer, r, columnName: p.ExcelColumnName);
254257
cellIndex++;
255258
}
256-
259+
257260
writer.Write($"</x:row>");
258261
yIndex++;
259262
}
@@ -353,7 +356,7 @@ private void WriteEmptySheet(MiniExcelStreamWriter writer)
353356
private void GenerateSheetByColumnInfo<T>(MiniExcelStreamWriter writer, IEnumerable value, List<ExcelColumnInfo> props, int xIndex = 1, int yIndex = 1)
354357
{
355358
var isDic = typeof(T) == typeof(IDictionary);
356-
var isDapperRow = typeof(T) == typeof(IDictionary<string,object>);
359+
var isDapperRow = typeof(T) == typeof(IDictionary<string, object>);
357360
foreach (T v in value)
358361
{
359362
writer.Write($"<x:row r=\"{yIndex}\">");
@@ -375,14 +378,14 @@ private void GenerateSheetByColumnInfo<T>(MiniExcelStreamWriter writer, IEnumera
375378
else if (isDapperRow)
376379
{
377380
cellValue = ((IDictionary<string, object>)v)[p.Key.ToString()];
378-
}
381+
}
379382
else
380383
{
381384
cellValue = p.Property.GetValue(v);
382385
}
383386
WriteCell(writer, yIndex, cellIndex, cellValue, p);
384-
385-
387+
388+
386389
cellIndex++;
387390
}
388391
writer.Write($"</x:row>");
@@ -403,15 +406,15 @@ private void WriteCell(MiniExcelStreamWriter writer, int rowIndex, int cellIndex
403406
{
404407
v = ExcelOpenXmlUtils.EncodeXML(str);
405408
}
406-
else if(p?.ExcelFormat != null && value is IFormattable formattableValue)
409+
else if (p?.ExcelFormat != null && value is IFormattable formattableValue)
407410
{
408411
var formattedStr = formattableValue.ToString(p.ExcelFormat, _configuration.Culture);
409412
v = ExcelOpenXmlUtils.EncodeXML(formattedStr);
410413
}
411414
else
412415
{
413416
Type type = null;
414-
if (p==null || p.Key != null)
417+
if (p == null || p.Key != null)
415418
{
416419
// TODO: need to optimize
417420
// Dictionary need to check type every time, so it's slow..
@@ -503,7 +506,7 @@ private void WriteCell(MiniExcelStreamWriter writer, int rowIndex, int cellIndex
503506
}
504507
else if (type == typeof(DateTime))
505508
{
506-
if(_configuration.Culture != CultureInfo.InvariantCulture)
509+
if (_configuration.Culture != CultureInfo.InvariantCulture)
507510
{
508511
t = "str";
509512
v = ((DateTime)value).ToString(_configuration.Culture);
@@ -518,18 +521,18 @@ private void WriteCell(MiniExcelStreamWriter writer, int rowIndex, int cellIndex
518521
{
519522
// TODO: now it'll lose date type information
520523
t = "str";
521-
v = ((DateTime)value).ToString(p.ExcelFormat,_configuration.Culture);
524+
v = ((DateTime)value).ToString(p.ExcelFormat, _configuration.Culture);
522525
}
523526
}
524527
else
525528
{
526529
//TODO: _configuration.Culture
527-
v = ExcelOpenXmlUtils.EncodeXML(value.ToString());
530+
v = ExcelOpenXmlUtils.EncodeXML(value.ToString());
528531
}
529532
}
530533

531534
var columname = ExcelOpenXmlUtils.ConvertXyToCell(cellIndex, rowIndex);
532-
if (v != null && (v.StartsWith(" ",StringComparison.Ordinal) || v.EndsWith(" ",StringComparison.Ordinal))) /*Prefix and suffix blank space will lost after SaveAs #294*/
535+
if (v != null && (v.StartsWith(" ", StringComparison.Ordinal) || v.EndsWith(" ", StringComparison.Ordinal))) /*Prefix and suffix blank space will lost after SaveAs #294*/
533536
writer.Write($"<x:c r=\"{columname}\" {(t == null ? "" : $"t =\"{t}\"")} s=\"{s}\" xml:space=\"preserve\"><x:v>{v}</x:v></x:c>");
534537
else
535538
//t check avoid format error ![image](https://user-images.githubusercontent.com/12729184/118770190-9eee3480-b8b3-11eb-9f5a-87a439f5e320.png)
@@ -590,8 +593,13 @@ private void GenerateSheetByIDataReader(MiniExcelStreamWriter writer, IDataReade
590593
var yIndex = xy.Item2;
591594
var xIndex = 0;
592595
{
593-
dimensionWritePosition = writer.WriteAndFlush($@"<x:dimension ref=""");
594-
writer.Write($@" />"); // end of code will be replaced
596+
597+
if (_configuration.FastMode)
598+
{
599+
dimensionWritePosition = writer.WriteAndFlush($@"<x:dimension ref=""");
600+
writer.Write(" />"); // end of code will be replaced
601+
}
602+
595603
writer.Write("<x:sheetData>");
596604
int fieldCount = reader.FieldCount;
597605
if (_printHeader)
@@ -626,11 +634,14 @@ private void GenerateSheetByIDataReader(MiniExcelStreamWriter writer, IDataReade
626634
}
627635
writer.Write("</x:sheetData>");
628636
if (_configuration.AutoFilter)
629-
writer.Write($"<x:autoFilter ref=\"A1:{ExcelOpenXmlUtils.ConvertXyToCell((xIndex-1)/*TODO:code smell*/, yIndex-1)}\" />");
637+
writer.Write($"<x:autoFilter ref=\"A1:{ExcelOpenXmlUtils.ConvertXyToCell((xIndex - 1)/*TODO:code smell*/, yIndex - 1)}\" />");
630638
writer.WriteAndFlush("</x:worksheet>");
631639

632-
writer.SetPosition(dimensionWritePosition);
633-
writer.WriteAndFlush($@"A1:{ExcelOpenXmlUtils.ConvertXyToCell((xIndex - 1)/*TODO:code smell*/, yIndex - 1)}""");
640+
if (_configuration.FastMode)
641+
{
642+
writer.SetPosition(dimensionWritePosition);
643+
writer.WriteAndFlush($@"A1:{ExcelOpenXmlUtils.ConvertXyToCell((xIndex - 1)/*TODO:code smell*/, yIndex - 1)}""");
644+
}
634645
}
635646
636647
private static void WriteC(MiniExcelStreamWriter writer, string r, string columnName)
@@ -779,7 +790,7 @@ private string GetDimensionRef(int maxRowIndex, int maxColumnIndex)
779790

780791
public async Task SaveAsAsync(CancellationToken cancellationToken = default(CancellationToken))
781792
{
782-
await Task.Run(() => SaveAs(),cancellationToken).ConfigureAwait(false);
793+
await Task.Run(() => SaveAs(), cancellationToken).ConfigureAwait(false);
783794
}
784795

785796
public void Insert()

tests/MiniExcelTests/MiniExcelIssueTests.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ public MiniExcelIssueTests(ITestOutputHelper output)
3434
this.output = output;
3535
}
3636

37+
//[Fact]
38+
public void TestIssue()
39+
{
40+
var path = PathHelper.GetTempFilePath();
41+
var value = Enumerable.Range(1, 10000000).Select(s => new { s, id = Guid.NewGuid() });
42+
MiniExcel.SaveAs(path, value);
43+
}
44+
3745
/// <summary>
3846
/// https://gitee.com/dotnetchina/MiniExcel/issues/I4X92G
3947
/// </summary>
@@ -115,7 +123,8 @@ public void TestIssue_DataReaderSupportDimension()
115123
}
116124
var path = Path.GetTempPath() + Guid.NewGuid() + ".xlsx";
117125
DataTableReader reader = table.CreateDataReader();
118-
MiniExcel.SaveAs(path, reader);
126+
var config = new OpenXmlConfiguration() { FastMode = true };
127+
MiniExcel.SaveAs(path, reader,configuration:config);
119128
var xml = Helpers.GetZipFileContent(path, "xl/worksheets/sheet1.xml");
120129
Assert.Contains("<x:autoFilter ref=\"A1:B3\" />", xml);
121130
Assert.Contains("<x:dimension ref=\"A1:B3\" />", xml);

0 commit comments

Comments
 (0)