mirror of
https://gitee.com/dotnetchina/MiniExcel.git
synced 2024-11-29 18:38:08 +08:00
Reduce string memory allocation when template save (#439)
* Bump BenchmarkDotNet 0.12.1 -> 0.13.2 * Add TFM net6.0 to benchmark * Reduce string memory allocation when template save
This commit is contained in:
parent
492ddd555a
commit
19c7076111
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFrameworks>netcoreapp3.1;net6.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
|
||||||
<PackageReference Include="ClosedXML" Version="0.95.4" />
|
<PackageReference Include="ClosedXML" Version="0.95.4" />
|
||||||
<PackageReference Include="ClosedXML.Report" Version="0.2.1" />
|
<PackageReference Include="ClosedXML.Report" Version="0.2.1" />
|
||||||
<PackageReference Include="DocumentFormat.OpenXml" Version="2.12.3" />
|
<PackageReference Include="DocumentFormat.OpenXml" Version="2.12.3" />
|
||||||
|
@ -144,6 +144,7 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
#region Generate rows and cells
|
#region Generate rows and cells
|
||||||
int originRowIndex;
|
int originRowIndex;
|
||||||
int rowIndexDiff = 0;
|
int rowIndexDiff = 0;
|
||||||
|
var rowXml = new StringBuilder();
|
||||||
foreach (var rowInfo in XRowInfos)
|
foreach (var rowInfo in XRowInfos)
|
||||||
{
|
{
|
||||||
var row = rowInfo.Row;
|
var row = rowInfo.Row;
|
||||||
@ -152,21 +153,32 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
originRowIndex = int.Parse(row.GetAttribute("r"));
|
originRowIndex = int.Parse(row.GetAttribute("r"));
|
||||||
var newRowIndex = originRowIndex + rowIndexDiff;
|
var newRowIndex = originRowIndex + rowIndexDiff;
|
||||||
|
|
||||||
|
string innerXml = row.InnerXml;
|
||||||
|
rowXml.Clear()
|
||||||
|
.AppendFormat(@"<{0}", row.Name);
|
||||||
|
foreach (var attr in row.Attributes.Cast<XmlAttribute>()
|
||||||
|
.Where(e => e.Name != "r"))
|
||||||
|
{
|
||||||
|
rowXml.AppendFormat(@" {0}=""{1}""", attr.Name, attr.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
string outerXmlOpen = rowXml.ToString();
|
||||||
|
|
||||||
if (rowInfo.CellIEnumerableValues != null)
|
if (rowInfo.CellIEnumerableValues != null)
|
||||||
{
|
{
|
||||||
var first = true;
|
var first = true;
|
||||||
var iEnumerableIndex = 0;
|
var iEnumerableIndex = 0;
|
||||||
|
|
||||||
foreach (var item in rowInfo.CellIEnumerableValues)
|
foreach (var item in rowInfo.CellIEnumerableValues)
|
||||||
{
|
{
|
||||||
iEnumerableIndex++;
|
iEnumerableIndex++;
|
||||||
|
|
||||||
var newRow = row.Clone() as XmlElement;
|
rowXml.Clear()
|
||||||
newRow.SetAttribute("r", newRowIndex.ToString());
|
.Append(outerXmlOpen)
|
||||||
StringBuilder rowXml = new StringBuilder(newRow.InnerXml);
|
.AppendFormat(@" r=""{0}"">", newRowIndex)
|
||||||
// newRow.InnerXml = row.InnerXml.Replace($"{{{{$rowindex}}}}", newRowIndex.ToString());
|
.Append(innerXml)
|
||||||
rowXml.Replace($"{{{{$rowindex}}}}", newRowIndex.ToString());
|
.Replace($"{{{{$rowindex}}}}", newRowIndex.ToString())
|
||||||
|
.AppendFormat(@"</{0}>", row.Name);
|
||||||
|
|
||||||
if (rowInfo.IsDictionary)
|
if (rowInfo.IsDictionary)
|
||||||
{
|
{
|
||||||
@ -176,7 +188,6 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
var key = $"{{{{{rowInfo.IEnumerablePropName}.{propInfo.Key}}}}}";
|
var key = $"{{{{{rowInfo.IEnumerablePropName}.{propInfo.Key}}}}}";
|
||||||
if (item == null) //![image](https://user-images.githubusercontent.com/12729184/114728510-bc3e5900-9d71-11eb-9721-8a414dca21a0.png)
|
if (item == null) //![image](https://user-images.githubusercontent.com/12729184/114728510-bc3e5900-9d71-11eb-9721-8a414dca21a0.png)
|
||||||
{
|
{
|
||||||
// newRow.InnerXml = newRow.InnerXml.Replace(key, "");
|
|
||||||
rowXml.Replace(key, "");
|
rowXml.Replace(key, "");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -184,7 +195,6 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
var cellValue = dic[propInfo.Key];
|
var cellValue = dic[propInfo.Key];
|
||||||
if (cellValue == null)
|
if (cellValue == null)
|
||||||
{
|
{
|
||||||
// newRow.InnerXml = newRow.InnerXml.Replace(key, "");
|
|
||||||
rowXml.Replace(key, "");
|
rowXml.Replace(key, "");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -202,7 +212,6 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO: ![image](https://user-images.githubusercontent.com/12729184/114848248-17735880-9e11-11eb-8258-63266bda0a1a.png)
|
//TODO: ![image](https://user-images.githubusercontent.com/12729184/114848248-17735880-9e11-11eb-8258-63266bda0a1a.png)
|
||||||
//newRow.InnerXml = newRow.InnerXml.Replace(key, cellValueStr);
|
|
||||||
rowXml.Replace(key, cellValueStr);
|
rowXml.Replace(key, cellValueStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,7 +223,6 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
var key = $"{{{{{rowInfo.IEnumerablePropName}.{propInfo.Key}}}}}";
|
var key = $"{{{{{rowInfo.IEnumerablePropName}.{propInfo.Key}}}}}";
|
||||||
if (item == null) //![image](https://user-images.githubusercontent.com/12729184/114728510-bc3e5900-9d71-11eb-9721-8a414dca21a0.png)
|
if (item == null) //![image](https://user-images.githubusercontent.com/12729184/114728510-bc3e5900-9d71-11eb-9721-8a414dca21a0.png)
|
||||||
{
|
{
|
||||||
// newRow.InnerXml = newRow.InnerXml.Replace(key, "");
|
|
||||||
rowXml.Replace(key, "");
|
rowXml.Replace(key, "");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -222,7 +230,6 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
var cellValue = datarow[propInfo.Key];
|
var cellValue = datarow[propInfo.Key];
|
||||||
if (cellValue == null)
|
if (cellValue == null)
|
||||||
{
|
{
|
||||||
// newRow.InnerXml = newRow.InnerXml.Replace(key, "");
|
|
||||||
rowXml.Replace(key, "");
|
rowXml.Replace(key, "");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -240,7 +247,6 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO: ![image](https://user-images.githubusercontent.com/12729184/114848248-17735880-9e11-11eb-8258-63266bda0a1a.png)
|
//TODO: ![image](https://user-images.githubusercontent.com/12729184/114848248-17735880-9e11-11eb-8258-63266bda0a1a.png)
|
||||||
//newRow.InnerXml = newRow.InnerXml.Replace(key, cellValueStr);
|
|
||||||
rowXml.Replace(key, cellValueStr);
|
rowXml.Replace(key, cellValueStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,7 +259,6 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
var key = $"{{{{{rowInfo.IEnumerablePropName}.{prop.Name}}}}}";
|
var key = $"{{{{{rowInfo.IEnumerablePropName}.{prop.Name}}}}}";
|
||||||
if (item == null) //![image](https://user-images.githubusercontent.com/12729184/114728510-bc3e5900-9d71-11eb-9721-8a414dca21a0.png)
|
if (item == null) //![image](https://user-images.githubusercontent.com/12729184/114728510-bc3e5900-9d71-11eb-9721-8a414dca21a0.png)
|
||||||
{
|
{
|
||||||
//newRow.InnerXml = newRow.InnerXml.Replace(key, "");
|
|
||||||
rowXml.Replace(key, "");
|
rowXml.Replace(key, "");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -261,7 +266,6 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
var cellValue = prop.GetValue(item);
|
var cellValue = prop.GetValue(item);
|
||||||
if (cellValue == null)
|
if (cellValue == null)
|
||||||
{
|
{
|
||||||
//newRow.InnerXml = newRow.InnerXml.Replace(key, "");
|
|
||||||
rowXml.Replace(key, "");
|
rowXml.Replace(key, "");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -284,14 +288,10 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO: ![image](https://user-images.githubusercontent.com/12729184/114848248-17735880-9e11-11eb-8258-63266bda0a1a.png)
|
//TODO: ![image](https://user-images.githubusercontent.com/12729184/114848248-17735880-9e11-11eb-8258-63266bda0a1a.png)
|
||||||
// newRow.InnerXml = newRow.InnerXml.Replace(key, cellValueStr);
|
|
||||||
rowXml.Replace(key, cellValueStr);
|
rowXml.Replace(key, cellValueStr);
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newRow.InnerXml = rowXml.ToString();
|
|
||||||
|
|
||||||
// note: only first time need add diff ![image](https://user-images.githubusercontent.com/12729184/114494728-6bceda80-9c4f-11eb-9685-8b5ed054eabe.png)
|
// note: only first time need add diff ![image](https://user-images.githubusercontent.com/12729184/114494728-6bceda80-9c4f-11eb-9685-8b5ed054eabe.png)
|
||||||
if (!first)
|
if (!first)
|
||||||
//rowIndexDiff++;
|
//rowIndexDiff++;
|
||||||
@ -300,8 +300,7 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
|
|
||||||
var mergeBaseRowIndex = newRowIndex;
|
var mergeBaseRowIndex = newRowIndex;
|
||||||
newRowIndex = newRowIndex + (rowInfo.IEnumerableMercell == null ? 1 : rowInfo.IEnumerableMercell.Height);
|
newRowIndex = newRowIndex + (rowInfo.IEnumerableMercell == null ? 1 : rowInfo.IEnumerableMercell.Height);
|
||||||
writer.Write(CleanXml(newRow.OuterXml, endPrefix));
|
writer.Write(CleanXml(rowXml, endPrefix)); // pass StringBuilder for netcoreapp3.0 or above
|
||||||
newRow = null;
|
|
||||||
|
|
||||||
//mergecells
|
//mergecells
|
||||||
if (rowInfo.RowMercells != null)
|
if (rowInfo.RowMercells != null)
|
||||||
@ -348,9 +347,13 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
row.SetAttribute("r", newRowIndex.ToString());
|
rowXml.Clear()
|
||||||
row.InnerXml = new StringBuilder(row.InnerXml).Replace($"{{{{$rowindex}}}}", newRowIndex.ToString()).ToString();
|
.Append(outerXmlOpen)
|
||||||
writer.Write(CleanXml(row.OuterXml, endPrefix));
|
.AppendFormat(@" r=""{0}"">", newRowIndex)
|
||||||
|
.Append(innerXml)
|
||||||
|
.Replace($"{{{{$rowindex}}}}", newRowIndex.ToString())
|
||||||
|
.AppendFormat("</{0}>", row.Name);
|
||||||
|
writer.Write(CleanXml(rowXml, endPrefix)); // pass StringBuilder for netcoreapp3.0 or above
|
||||||
|
|
||||||
//mergecells
|
//mergecells
|
||||||
if (rowInfo.RowMercells != null)
|
if (rowInfo.RowMercells != null)
|
||||||
@ -408,12 +411,18 @@ namespace MiniExcelLibs.OpenXml
|
|||||||
return cellValueStr;
|
return cellValueStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static StringBuilder CleanXml(StringBuilder xml, string endPrefix)
|
||||||
|
{
|
||||||
|
return xml
|
||||||
|
.Replace("xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\"", "")
|
||||||
|
.Replace($"xmlns{endPrefix}=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"", "");
|
||||||
|
}
|
||||||
|
|
||||||
private static string CleanXml(string xml, string endPrefix)
|
private static string CleanXml(string xml, string endPrefix)
|
||||||
{
|
{
|
||||||
//TODO: need to optimize
|
//TODO: need to optimize
|
||||||
return xml
|
return CleanXml(new StringBuilder(xml), endPrefix)
|
||||||
.Replace("xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\"", "")
|
.ToString();
|
||||||
.Replace($"xmlns{endPrefix}=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"", "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReplaceSharedStringsToStr(IDictionary<int, string> sharedStrings, ref XmlNodeList rows)
|
private void ReplaceSharedStringsToStr(IDictionary<int, string> sharedStrings, ref XmlNodeList rows)
|
||||||
|
@ -9,7 +9,13 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string EncodeXML(string value) => value == null
|
internal static string EncodeXML(string value) => value == null
|
||||||
? string.Empty
|
? string.Empty
|
||||||
: XmlEncoder.EncodeString(value).Replace("&", "&").Replace("<", "<").Replace(">", ">").Replace("\"", """).Replace("'", "'");
|
: XmlEncoder.EncodeString(value)
|
||||||
|
.Replace("&", "&")
|
||||||
|
.Replace("<", "<")
|
||||||
|
.Replace(">", ">")
|
||||||
|
.Replace("\"", """)
|
||||||
|
.Replace("'", "'")
|
||||||
|
.ToString();
|
||||||
|
|
||||||
/// <summary>X=CellLetter,Y=CellNumber,ex:A1=(1,1),B2=(2,2)</summary>
|
/// <summary>X=CellLetter,Y=CellNumber,ex:A1=(1,1),B2=(2,2)</summary>
|
||||||
internal static string ConvertXyToCell(Tuple<int, int> xy)
|
internal static string ConvertXyToCell(Tuple<int, int> xy)
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
private static readonly Regex xHHHHRegex = new Regex("_(x[\\dA-Fa-f]{4})_", RegexOptions.Compiled);
|
private static readonly Regex xHHHHRegex = new Regex("_(x[\\dA-Fa-f]{4})_", RegexOptions.Compiled);
|
||||||
private static readonly Regex Uppercase_X_HHHHRegex = new Regex("_(X[\\dA-Fa-f]{4})_", RegexOptions.Compiled);
|
private static readonly Regex Uppercase_X_HHHHRegex = new Regex("_(X[\\dA-Fa-f]{4})_", RegexOptions.Compiled);
|
||||||
|
|
||||||
public static string EncodeString(string encodeStr)
|
public static StringBuilder EncodeString(string encodeStr)
|
||||||
{
|
{
|
||||||
if (encodeStr == null) return null;
|
if (encodeStr == null) return null;
|
||||||
|
|
||||||
@ -27,7 +27,7 @@
|
|||||||
sb.Append(XmlConvert.EncodeName(ch.ToString()));
|
sb.Append(XmlConvert.EncodeName(ch.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string DecodeString(string decodeStr)
|
public static string DecodeString(string decodeStr)
|
||||||
|
Loading…
Reference in New Issue
Block a user