Skip to content

Commit

Permalink
0.13.5
Browse files Browse the repository at this point in the history
- [New] Support QueryAsDataTable method [#216](#216)
- [New] SaveAs support IDataReader value parameter [#211](#211)
- [Bug] Fix numeric format string will be cast to numeric type [#I3OSKV](https://gitee.com/dotnetchina/MiniExcel/issues/I3OSKV)
- [Opt] Optimize SaveAs convert value type logic to improve performance
  • Loading branch information
shps951023 committed Apr 30, 2021
1 parent 8a45590 commit 44b89cc
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 104 deletions.
54 changes: 22 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,22 @@ foreach(IDictionary<string,object> row in MiniExcel.Query(path))



#### 9. Query Query Excel return DataTable

Not recommended, because DataTable will load all data into memory and lose MiniExcel's low memory consumption feature.

```C#
var table = MiniExcel.QueryAsDataTable(path, useHeaderRow: true);
```

![image](https://user-images.githubusercontent.com/12729184/116673475-07917200-a9d6-11eb-947e-a6f68cce58df.png)







### Create Excel <a name="getstart2"></a>

1. Must be a non-abstract type with a public parameterless constructor .
Expand Down Expand Up @@ -302,6 +318,12 @@ using (var stream = File.Create(path))
}
```

#### 6. Support IDataReader value parameter

```csharp
MiniExcel.SaveAs(path, reader);
```



### Fill Data To Excel Template <a name="getstart3"></a>
Expand Down Expand Up @@ -760,38 +782,6 @@ public static IEnumerable<T> Page<T>(IEnumerable<T> en, int pageSize, int page)

### FAQ

#### Q: How to convert query results to DataTable

Reminder: Not recommended, because DataTable will load all data into memory and lose MiniExcel's low memory consumption function.

```csharp
public static DataTable QueryAsDataTable(string path)
{
var rows = MiniExcel.Query(path, true);
var dt = new DataTable();
var first = true;
foreach (IDictionary<string, object> row in rows)
{
if (first)
{
foreach (var key in row.Keys)
{
var type = row[key]?.GetType() ?? typeof(string);
dt.Columns.Add(key, type);
}

first = false;
}
dt.Rows.Add(row.Values.ToArray());
}
return dt;
}
```

![image](https://user-images.githubusercontent.com/12729184/115068722-3105c480-9f25-11eb-8f5a-994416754134.png)



#### Q: Excel header title not equal class property name, how to mapping?

A. Please use ExcelColumnName attribute
Expand Down
48 changes: 17 additions & 31 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,15 @@ foreach(IDictionary<string,object> row in MiniExcel.Query(path))
}
```

#### 9. Query 读 Excel 返回 DataTable

提醒 : 不建议使用,因为DataTable会将数据`全载入内存`,失去MiniExcel低内存消耗功能。

```C#
var table = MiniExcel.QueryAsDataTable(path, useHeaderRow: true);
```

![image](https://user-images.githubusercontent.com/12729184/116673475-07917200-a9d6-11eb-947e-a6f68cce58df.png)



Expand Down Expand Up @@ -297,7 +305,7 @@ output :
| MiniExcel | 1 |
| Github | 2 |

#### 5. SaveAs 支援 Stream [[Try it]](https://dotnetfiddle.net/JOen0e)
#### 5. SaveAs 支持 Stream [[Try it]](https://dotnetfiddle.net/JOen0e)

```csharp
using (var stream = File.Create(path))
Expand All @@ -308,6 +316,14 @@ using (var stream = File.Create(path))



#### 6. 支持 IDataReader 参数

```csharp
MiniExcel.SaveAs(path, reader);
```





### 模板填充 Excel <a name="getstart3"></a>
Expand Down Expand Up @@ -769,36 +785,6 @@ public static IEnumerable<T> Page<T>(IEnumerable<T> en, int pageSize, int page)

### FAQ 常见问题

#### Q: 如何将查询结果转为 DataTable

提醒 : 不建议使用,因为DataTable会将数据`全载入内存`,失去MiniExcel低内存消耗功能。

```csharp
public static DataTable QueryAsDataTable(string path)
{
var rows = MiniExcel.Query(path, true);
var dt = new DataTable();
var first = true;
foreach (IDictionary<string, object> row in rows)
{
if (first)
{
foreach (var key in row.Keys)
{
var type = row[key]?.GetType() ?? typeof(string);
dt.Columns.Add(key, type);
}

first = false;
}
dt.Rows.Add(row.Values.ToArray());
}
return dt;
}
```

![image](https://user-images.githubusercontent.com/12729184/115068549-fac84500-9f24-11eb-9f12-884b19cf1489.png)

#### Q: Excel 表头标题名称跟 class 属性名称不一致,如何对应?

A. 请使用 ExcelColumnName 作 mapping
Expand Down
46 changes: 16 additions & 30 deletions README.zh-Hant.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,21 @@ foreach(IDictionary<string,object> row in MiniExcel.Query(path))
}
```

![image](https://user-images.githubusercontent.com/12729184/116673475-07917200-a9d6-11eb-947e-a6f68cce58df.png)



#### 9. Query 讀 Excel 返回 DataTable

提醒 : 不建議使用,因為DataTable會將數據`全載入內存`,失去MiniExcel低記憶體消耗功能。

```C#
var table = MiniExcel.QueryAsDataTable(path, useHeaderRow: true);
```

![image](https://user-images.githubusercontent.com/12729184/116673475-07917200-a9d6-11eb-947e-a6f68cce58df.png)



### 寫 Excel <a name="getstart2"></a>

Expand Down Expand Up @@ -304,7 +316,11 @@ using (var stream = File.Create(path))
}
```

#### 6. 支持 IDataReader 參數

```csharp
MiniExcel.SaveAs(path, reader);
```



Expand Down Expand Up @@ -768,36 +784,6 @@ public static IEnumerable<T> Page<T>(IEnumerable<T> en, int pageSize, int page)

### FAQ 常見問題

#### Q: 如何將查詢結果轉為 DataTable

提醒 : 不建議使用,因為DataTable會將數據`全載入記憶體`,失去MiniExcel低記憶體消耗功能。

```csharp
public static DataTable QueryAsDataTable(string path)
{
var rows = MiniExcel.Query(path, true);
var dt = new DataTable();
var first = true;
foreach (IDictionary<string, object> row in rows)
{
if (first)
{
foreach (var key in row.Keys)
{
var type = row[key]?.GetType() ?? typeof(string);
dt.Columns.Add(key, type);
}

first = false;
}
dt.Rows.Add(row.Values.ToArray());
}
return dt;
}
```

![image](https://user-images.githubusercontent.com/12729184/115068722-3105c480-9f25-11eb-8f5a-994416754134.png)

#### Q: Excel 表頭標題名稱跟 class 屬性名稱不一致,如何對應?

A. 請使用 ExcelColumnName 作 mapping
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### 0.13.5
- [New] Support QueryAsDataTable method [#216](https://github.com/shps951023/MiniExcel/issues/216)
- [New] SaveAs support IDataReader value parameter [#211](https://github.com/shps951023/MiniExcel/issues/211)
- [Bug] Fix numeric format string will be cast to numeric type [#I3OSKV](https://gitee.com/dotnetchina/MiniExcel/issues/I3OSKV)
- [Opt] Optimize SaveAs convert value type logic to improve performance

Expand Down
1 change: 1 addition & 0 deletions docs/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

### 0.13.5
- [New] 新增 QueryAsDataTable 方法 [#216](https://github.com/shps951023/MiniExcel/issues/216)
- [New] SaveAs 支持 IDataReader value 参数 [#211](https://github.com/shps951023/MiniExcel/issues/211)
- [Bug] 修正数字格式的字串会被强制转换为decimal类型 [#I3OSKV](https://gitee.com/dotnetchina/MiniExcel/issues/I3OSKV)
- [Opt] 优化 SaveAs 类别转换算法,避免效率浪费

Expand Down
1 change: 1 addition & 0 deletions docs/README.zh-Hant.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

### 0.13.5
- [New] 新增 QueryAsDataTable 方法 [#216](https://github.com/shps951023/MiniExcel/issues/216)
- [New] SaveAs 支持 IDataReader value 參數 [#211](https://github.com/shps951023/MiniExcel/issues/211)
- [Bug] 修正數字格式的字串會被強制轉換為decimal類型 [#I3OSKV](https://gitee.com/dotnetchina/MiniExcel/issues/I3OSKV)
- [Opt] 優化 SaveAs 類別轉換算法,避免效率浪費

Expand Down
4 changes: 2 additions & 2 deletions src/MiniExcel/MiniExcel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public static void SaveAsByTemplate(this Stream stream, byte[] templateBytes, ob
/// <summary>
/// This method is not recommended, because it'll load all data into memory.
/// </summary>
public static DataTable QueryAsDataTable(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null)
public static DataTable QueryAsDataTable(string path, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null)
{
using (var stream = Helpers.OpenSharedRead(path))
return QueryAsDataTable(stream, useHeaderRow, sheetName, GetExcelType(path, excelType), configuration);
Expand All @@ -115,7 +115,7 @@ public static DataTable QueryAsDataTable(string path, bool useHeaderRow = false,
/// <summary>
/// This method is not recommended, because it'll load all data into memory.
/// </summary>
public static DataTable QueryAsDataTable(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null)
public static DataTable QueryAsDataTable(this Stream stream, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null)
{
var dt = new DataTable();
dt.TableName = sheetName;
Expand Down
2 changes: 1 addition & 1 deletion src/MiniExcel/MiniExcelLibs.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;netstandard2.0;net5.0</TargetFrameworks>
<Version>0.13.4</Version>
<Version>0.13.5</Version>
</PropertyGroup>
<PropertyGroup>
<AssemblyName>MiniExcel</AssemblyName>
Expand Down
53 changes: 53 additions & 0 deletions src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ public void SaveAs(object value, string sheetName, bool printHeader, IConfigurat
{
GenerateSheetByDataTable(writer, archive, value as DataTable, printHeader);
}
else if (value is IDataReader)
{
GenerateSheetByIDataReader(writer, archive, value as IDataReader, printHeader);
}
else
{
throw new NotImplementedException($"Type {type.Name} & genericType {genericType.Name} not Implemented. please issue for me.");
Expand Down Expand Up @@ -332,6 +336,55 @@ private void GenerateSheetByDataTable(StreamWriter writer, MiniExcelZipArchive a
writer.Write("</x:sheetData></x:worksheet>");
}

private void GenerateSheetByIDataReader(StreamWriter writer, MiniExcelZipArchive archive, IDataReader value, bool printHeader)
{
var xy = ExcelOpenXmlUtils.ConvertCellToXY("A1");

writer.Write($@"<?xml version=""1.0"" encoding=""utf-8""?><x:worksheet xmlns:x=""http://schemas.openxmlformats.org/spreadsheetml/2006/main"">");
{
var yIndex = xy.Item2;

// TODO: dimension
//var maxRowIndex = value.Rows.Count + (printHeader && value.Rows.Count > 0 ? 1 : 0);
//var maxColumnIndex = value.Columns.Count;
//writer.Write($@"<x:dimension ref=""{GetDimensionRef(maxRowIndex, maxColumnIndex)}""/>");
writer.Write("<x:sheetData>");
int fieldCount = value.FieldCount;
if (printHeader)
{
writer.Write($"<x:row r=\"{yIndex.ToString()}\">");
var xIndex = xy.Item1;
for (int i = 0; i < fieldCount; i++)
{
var r = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
writer.Write($"<x:c r=\"{r}\" t=\"str\">");
writer.Write($"<x:v>{value.GetName(i)}");
writer.Write($"</x:v>");
writer.Write($"</x:c>");
xIndex++;
}
writer.Write($"</x:row>");
yIndex++;
}

while (value.Read())
{
writer.Write($"<x:row r=\"{yIndex.ToString()}\">");
var xIndex = xy.Item1;

for(int i = 0; i < fieldCount; i++)
{
var cellValue = value.GetValue(i);
WriteCell(writer, yIndex, xIndex, cellValue);
xIndex++;
}
writer.Write($"</x:row>");
yIndex++;
}
}
writer.Write("</x:sheetData></x:worksheet>");
}

private void GenerateContentTypesXml(MiniExcelZipArchive archive, Dictionary<string, ZipPackageInfo> packages)
{
//[Content_Types].xml
Expand Down
Loading

0 comments on commit 44b89cc

Please sign in to comment.