[New] ExcelFormat support DateTimeOffset/Decimal/double etc. type format #I49RZH #312 #305

This commit is contained in:
Wei 2022-01-22 17:02:16 +08:00
parent 09ec6fd124
commit a3693db188
10 changed files with 135 additions and 20 deletions

View File

@ -486,7 +486,7 @@ MiniExcel.SaveAs(path, value);
### 11. File Export
#### 11. File Export
Since 0.21.0, when value type is `byte[]` then system will save base64 string at cell by default, and when import system can be converted to `byte[]`. And if you don't want to use it, you can set `OpenXmlConfiguration.ConvertByteArrayToBase64String` to `false`, it can improve the system efficiency.
@ -771,7 +771,9 @@ Assert.Equal("Test4", rows[0].Test7);
#### 2. Custom DateTime Format (ExcelFormatAttribute)
#### 2. Custom Format (ExcelFormatAttribute)
Since V0.21.0 support class which contains `ToString(string content)` method format
Class

View File

@ -14,9 +14,10 @@
---
<div align="center">
<p> 您的 <a href="https://github.com/shps951023/MiniExcel">Star</a> 能帮助 MiniExcel 让更多人看到 </p>
<p> 您的 <a href="https://github.com/shps951023/miniexcel">Star★</a> 能帮助 MiniExcel 让更多人看到 </p>
</div>
---
### 简介
@ -492,7 +493,7 @@ MiniExcel.SaveAs(path, value);
### 11. 文件导出
#### 11. 文件导出
从 0.21.0 开始,当值类型为 `byte[]` 系统预设会转成 base64 字串以便导入时转回 `byte[]`,如不想转换可以将 `OpenXmlConfiguration.ConvertByteArrayToBase64String` 改为 `false`,能提升系统效率。
@ -782,7 +783,9 @@ Assert.Null(rows[0].Test6);
Assert.Equal("Test4", rows[0].Test7);
```
#### 2. 自定义日期格式 (ExcelFormatAttribute)
#### 2. 自定义Format格式 (ExcelFormatAttribute)
從 V0.21.0 開始支持有 `ToString(string content)` 的類別 format
类别
@ -1450,5 +1453,10 @@ public static DataTable QueryAsDataTableWithoutEmptyRow(Stream stream, bool useH
![](https://contrib.rocks/image?repo=shps951023/MiniExcel)
### QQ群
欢迎交流QQ群 813100564(.NET MiniExcel、MiniReport)请给源码项目点个Star吧
希望MiniExcel对您有用您的支持也是MiniExcel开源的动力MiniExcel有您更精彩
欢迎交流QQ群号 [813100564](https://qm.qq.com/cgi-bin/qm/qr?k=3OkxuL14sXhJsUimWK8wx_Hf28Wl49QE&jump_from=webapi)
### 闲话家常
开源项目不容易如果觉得本项目对您的工作还是有帮助的话请在帮忙在Github [![img](https://img.shields.io/github/stars/shps951023/miniexcel.svg?style=flat-square&label=Stars&logo=github)](https://github.com/shps951023/miniexcel)点个★Star。

View File

@ -496,7 +496,7 @@ MiniExcel.SaveAs(path, value);
### 11. 文件導出
#### 11. 文件導出
從 0.21.0 開始,當值類型為 `byte[]` 系統預設會轉成 base64 字串以便導入時轉回 `byte[]`,如不想轉換可以將 `OpenXmlConfiguration.ConvertByteArrayToBase64String` 改為 `false`,能提升系統效率。
@ -784,7 +784,9 @@ Assert.Null(rows[0].Test6);
Assert.Equal("Test4", rows[0].Test7);
```
#### 2. 自定義日期格式 (ExcelFormatAttribute)
#### 2. 自定義Format格式 (ExcelFormatAttribute)
從 V0.21.0 開始支持有 `ToString(string content)` 的類別 format
類別

View File

@ -19,11 +19,13 @@
### 0.20.1
- [New] ExcelFormat support DateTimeOffset/Decimal/double etc. type format #I49RZH #312 #305
- [New] Support byte file import/export
- [New] SaveAs support to convert byte[] value to base64 string
- [New] Query support to convert base64 value to byte[]
- [New] OpenXmlConfiguration add `ConvertByteArrayToBase64String` to turn on/off base64 convertor
- [New] Query support ExcelInvalidCastException to store column, row index #309
- [New] Query support ExcelInvalidCastException to store column, row, value data #309
### 0.20.0
- [New] SaveAs support image #304

View File

@ -24,6 +24,7 @@
---
### 0.20.1
- [New] ExcelFormat 支持 DateTimeOffset/Decimal/double 等类别 format #I49RZH #312 #305
- [New] 支持byte文件导入/导出
- [New] SaveAs 支持预设转换byte[] 值为 base64 字串
- [New] Query 支持转换 base64 字串值为 bytep[]

View File

@ -18,6 +18,7 @@
---
### 0.20.1
- [New] ExcelFormat 支持 DateTimeOffset/Decimal/double 等類別 format #I49RZH #312 #305
- [New] 支持byte文件導入/導出
- [New] SaveAs 支持預設轉換byte[] 值為 base64 字串
- [New] Query 支持轉換 base64 字串值為 bytep[]

View File

@ -1,4 +1,5 @@
using MiniExcelLibs.Utils;
using MiniExcelLibs.OpenXml;
using MiniExcelLibs.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
@ -241,7 +242,11 @@ namespace MiniExcelLibs.Csv
type = p.ExcludeNullableType; //sometime it doesn't need to re-get type like prop
}
if (type == typeof(DateTime))
if (p?.ExcelFormat != null && p?.ExcelFormatToStringMethod != null)
{
return p.ExcelFormatToStringMethod.Invoke(value, new[] { p.ExcelFormat })?.ToString();
}
else if (type == typeof(DateTime))
{
if (p == null || p.ExcelFormat == null)
{

View File

@ -359,6 +359,11 @@ namespace MiniExcelLibs.OpenXml
{
v = ExcelOpenXmlUtils.EncodeXML(value.ToString());
}
else if(p?.ExcelFormat != null && p?.ExcelFormatToStringMethod != null)
{
var formatedStr = p.ExcelFormatToStringMethod.Invoke(value, new[] { p.ExcelFormat })?.ToString();
v = ExcelOpenXmlUtils.EncodeXML(formatedStr);
}
else
{
Type type = null;
@ -433,7 +438,7 @@ namespace MiniExcelLibs.OpenXml
}
else
{
v = ExcelOpenXmlUtils.EncodeXML(value.ToString());
v = ExcelOpenXmlUtils.EncodeXML(value.ToString());
}
}

View File

@ -18,6 +18,8 @@
public bool Nullable { get; internal set; }
public string ExcelFormat { get; internal set; }
public double? ExcelColumnWidth { get; internal set; }
public MethodInfo ExcelFormatToStringMethod { get; internal set; }
}
internal static partial class CustomPropertyHelper
@ -149,17 +151,25 @@
{
var gt = Nullable.GetUnderlyingType(p.PropertyType);
var excelColumnName = p.GetAttribute<ExcelColumnNameAttribute>();
var excludeNullableType = gt ?? p.PropertyType;
var excelFormat = p.GetAttribute<ExcelFormatAttribute>()?.Format;
MethodInfo method = null;
if(excelFormat != null && excludeNullableType != null)
{
method = excludeNullableType.GetMethod("ToString", new[] { typeof(string) });
}
return new ExcelCustomPropertyInfo
{
Property = p,
ExcludeNullableType = gt ?? p.PropertyType,
ExcludeNullableType = excludeNullableType,
Nullable = gt != null,
ExcelColumnAliases = excelColumnName?.Aliases,
ExcelColumnName = excelColumnName?.ExcelColumnName ?? p.Name,
ExcelColumnIndex = p.GetAttribute<ExcelColumnIndexAttribute>()?.ExcelColumnIndex,
ExcelColumnWidth = p.GetAttribute<ExcelColumnWidthAttribute>()?.ExcelColumnWidth,
ExcelFormat = p.GetAttribute<ExcelFormatAttribute>()?.Format,
ExcelFormat = excelFormat,
ExcelFormatToStringMethod = method
};
});
}

View File

@ -29,6 +29,85 @@ namespace MiniExcelLibs.Tests
this.output = output;
}
/// <summary>
/// https://gitee.com/dotnetchina/MiniExcel/issues/I49RZH
/// https://github.com/shps951023/MiniExcel/issues/305
/// </summary>
[Fact]
public void TestIssueI49RZH()
{
// xlsx
{
var path = PathHelper.GetTempFilePath();
var value = new TestIssueI49RZHDto[] {
new TestIssueI49RZHDto{ dd = DateTimeOffset.Parse("2022-01-22")},
new TestIssueI49RZHDto{ dd = null}
};
MiniExcel.SaveAs(path, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("2022-01-22", rows[1].A);
}
//TODO:CSV
{
var path = PathHelper.GetTempFilePath("csv");
var value = new TestIssueI49RZHDto[] {
new TestIssueI49RZHDto{ dd = DateTimeOffset.Parse("2022-01-22")},
new TestIssueI49RZHDto{ dd = null}
};
MiniExcel.SaveAs(path, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("2022-01-22", rows[1].A);
}
}
public class TestIssueI49RZHDto
{
[ExcelFormat("yyyy-MM-dd")]
public DateTimeOffset? dd { get; set; }
}
/// <summary>
/// https://github.com/shps951023/MiniExcel/issues/312
/// </summary>
[Fact]
public void TestIssue312()
{
//xlsx
{
var path = PathHelper.GetTempFilePath();
var value = new TestIssue312Dto[] {
new TestIssue312Dto{ value = 12345.6789},
new TestIssue312Dto{ value = null}
};
MiniExcel.SaveAs(path, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("12,345.68", rows[1].A);
}
//TODO:CSV
{
var path = PathHelper.GetTempFilePath("csv");
var value = new TestIssue312Dto[] {
new TestIssue312Dto{ value = 12345.6789},
new TestIssue312Dto{ value = null}
};
MiniExcel.SaveAs(path, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("12,345.68", rows[1].A);
}
}
public class TestIssue312Dto
{
[ExcelFormat("0,0.00")]
public double? value { get; set; }
}
/// <summary>
/// Query type conversion error
/// https://github.com/shps951023/MiniExcel/issues/309
@ -47,8 +126,8 @@ namespace MiniExcelLibs.Tests
Assert.Equal(4, ex.Row);
Assert.Equal("Error", ex.Value);
Assert.Equal(typeof(int), ex.InvalidCastType);
Assert.Equal("ColumnName : SEQ, CellRow : 4, Value : Error, it can't cast to Int32 type.",ex.Message);
}
Assert.Equal("ColumnName : SEQ, CellRow : 4, Value : Error, it can't cast to Int32 type.", ex.Message);
}
}
public class TestIssue209Dto
@ -78,12 +157,12 @@ namespace MiniExcelLibs.Tests
var expectedBase64 = "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAEXRFWHRTb2Z0d2FyZQBTbmlwYXN0ZV0Xzt0AAALNSURBVEiJ7ZVLTBNBGMdndrfdIofy0ERbCgcFeYRuCy2JGOPNRA9qeIZS6YEEogQj0YMmGOqDSATxQaLRxKtRID4SgjGelUBpaQvGZ7kpII8aWtjd2dkdDxsJoS1pIh6M/k+z8833m/3+8+0OJISArRa15cT/0D8CZTYPe32+Zy+GxjzjMzOzAACDYafdZquqOG7hzJtkwUQthRC6cavv0eN+QRTBujUQQp1OV1dbffZMq1arTRaqKIok4eZTrSNjHqIo6gIIIQBgbQwpal+Z/f7dPo2GoaiNHtJut3vjPhBe7+kdfvW61Mq1nGyaX1xYjkRzsk2Z6Rm8IOTvzWs73SLwwqjHK4jCgf3lcV6VxGgiECji7AXm0gvtHYQQnue/zy8ghCRJWlxaWuV5Qsilq9cKzLYiiz04ORVLiHP6A4NPRQlhjLWsVpZlnU63Y3umRqNhGCYjPV3HsrIsMwyDsYQQejIwGEuIA/WMT1AAaDSahnoHTdPKL1vXPKVp2umoZVkWAOj1+ZOCzs7NKYTo9XqjYRcAgKIo9ZRUu9VxltGYZTQAAL5+m0kKijEmAPCrqyJCcRuOECKI4lL4ByEEYykpaE62iQIgurLi9wchhLIsry8fYwwh9PomwuEwACDbZEoKauHMgKJSU1PbOy6Hpqdpml5fPsMwn7+EOru6IYQAghKrJSloTVUFURSX02G3lRw+WulqbA4EJ9XQh4+f2s6dr65zhkLTEEIKwtqaylhCnG/fauFO1Nfde/Bw6Hm/0WiYevc+LU2vhlK2pQwNvwQAsCwrYexyOrji4lhCnOaXZRljXONoOHTk2Ju3I/5AcC3EC0JZ+cE9Bea8IqursUkUker4BsWBqpIk6aL7Sm4htzvfvByJqJORaDS3kMsvLuns6kYIJcpNCFU17pvouXlHEET1URDEnt7bo2OezbMS/vp+R3/PdfKPQ38Ccg0E/CDcpY8AAAAASUVORK5CYII=";
var actulBase64 = Convert.ToBase64String((byte[])rows[0].Image);
Assert.Equal(expectedBase64, actulBase64);
}
}
// import to base64 string
{
var config = new OpenXmlConfiguration() { ConvertByteArrayToBase64String = false };
var rows = MiniExcel.Query(path, true,configuration: config).ToList();
var rows = MiniExcel.Query(path, true, configuration: config).ToList();
var expectedBase64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAEXRFWHRTb2Z0d2FyZQBTbmlwYXN0ZV0Xzt0AAALNSURBVEiJ7ZVLTBNBGMdndrfdIofy0ERbCgcFeYRuCy2JGOPNRA9qeIZS6YEEogQj0YMmGOqDSATxQaLRxKtRID4SgjGelUBpaQvGZ7kpII8aWtjd2dkdDxsJoS1pIh6M/k+z8833m/3+8+0OJISArRa15cT/0D8CZTYPe32+Zy+GxjzjMzOzAACDYafdZquqOG7hzJtkwUQthRC6cavv0eN+QRTBujUQQp1OV1dbffZMq1arTRaqKIok4eZTrSNjHqIo6gIIIQBgbQwpal+Z/f7dPo2GoaiNHtJut3vjPhBe7+kdfvW61Mq1nGyaX1xYjkRzsk2Z6Rm8IOTvzWs73SLwwqjHK4jCgf3lcV6VxGgiECji7AXm0gvtHYQQnue/zy8ghCRJWlxaWuV5Qsilq9cKzLYiiz04ORVLiHP6A4NPRQlhjLWsVpZlnU63Y3umRqNhGCYjPV3HsrIsMwyDsYQQejIwGEuIA/WMT1AAaDSahnoHTdPKL1vXPKVp2umoZVkWAOj1+ZOCzs7NKYTo9XqjYRcAgKIo9ZRUu9VxltGYZTQAAL5+m0kKijEmAPCrqyJCcRuOECKI4lL4ByEEYykpaE62iQIgurLi9wchhLIsry8fYwwh9PomwuEwACDbZEoKauHMgKJSU1PbOy6Hpqdpml5fPsMwn7+EOru6IYQAghKrJSloTVUFURSX02G3lRw+WulqbA4EJ9XQh4+f2s6dr65zhkLTEEIKwtqaylhCnG/fauFO1Nfde/Bw6Hm/0WiYevc+LU2vhlK2pQwNvwQAsCwrYexyOrji4lhCnOaXZRljXONoOHTk2Ju3I/5AcC3EC0JZ+cE9Bea8IqursUkUker4BsWBqpIk6aL7Sm4htzvfvByJqJORaDS3kMsvLuns6kYIJcpNCFU17pvouXlHEET1URDEnt7bo2OezbMS/vp+R3/PdfKPQ38Ccg0E/CDcpY8AAAAASUVORK5CYII=";
var actulBase64 = (string)rows[0].Image;
Assert.Equal(expectedBase64, actulBase64);