c# - 通过 SpreadSheetGear 将 .xlsx 读取到 dto
问题描述
我想在 .Net Core 3.1 控制台应用程序中使用电子表格将 exel 文件读取到自定义模型(映射它!)。我的 excel 文件如下所示:
| Customers | Sales Item | Sale Date | Contact | Quantity |
| IBM | Keyboard | 28-10-2011 | | 2 |
| Logitech | Mouse | 27-09-2011 | joe | 5 |
DTO
public class CustomersDto
{
public string Customers { get; set; }
public string SalesItem { get; set; }
public DateTime Date { get; set; }
public string Contact { get; set; }
public int Quantity{ get; set; }
}
通用代码:
private static void Main(string[] args)
{
var workbook =
Factory.GetWorkbook(
@"D:\MyFiles\SellersCollections.xlsx");
var worksheet = workbook.Worksheets[0];
var cells = worksheet.UsedRange;
List<CustomersDto> test = new List<CustomersDto>();
CustomersDto dto = new CustomersDto();
for (var i = 0; i < cells.RowCount; i++)
{
if (i == 1) // skip header (0)
{
for (var j = 0; j < cells.ColumnCount; j++)
{
Console.WriteLine(cells[i,j].Value);
// What should I do HERE to MAP to DTO
// Something like:
// dto.Customers = cells[i, j]; ???
}
}
}
Console.ReadLine();
}
有没有办法映射cells[i, j]
或IRange
建模类?
解决方案
SpreadsheetGear 中不存在任何内置映射或绑定功能来为您执行此操作,因此您需要构建自己的例程来执行此操作。如果您的工作簿和 DTO 定义明确且事先已知,我将保留外部“行循环”,但删除内部“列循环”并手动索引每个列单元格值,并根据需要将其放入相应的 DTO 属性中。当然,这意味着您的代码对每一列中包含的信息及其在 DTO 中的相应属性有一些了解。如果你需要一些更动态的东西,你必须建立一个更精细的系统,这超出了这里的回答范围。
在获取单元格值方面,IRange
您可能需要查看两个主要属性:
- 范围。值- 此属性是类型
object
并返回单元格的“原始”值。例如 adouble
of1.23
或 abool
oftrue
或string
of"abc"
。 - 范围。文本- 这是类型
string
并返回单元格的“格式化”值 - 这意味着它采用 IRange.Value 并将该单元格的数字格式 (IRange. NumberFormat ) 应用于该值并返回结果字符串。换句话说,这将返回您从 Excel 的 UI 和/或 SpreadsheetGear 的 WorkbookView UI 控件看到的内容。因此,如果一个单元格的 IRange.Value 为双 1.23,但被格式化为显示 4 个小数位 (IRange.NumberFormat == "0.0000"
),则 IRange.Text 将返回字符串"1.2300"
。假设具有 的单元格的通用 NumberFormatbool
,true
IRange.Text 将返回字符串"TRUE"
。等等。
需要特别考虑日期。这是因为 Excel 中的日期、时间和日期时间在内部存储为序列数字双精度值,值 1.0 为 1900 年 1 月 1 日,2.0 为 1900 年 1 月 2 日,今天(2021 年 3 月 23 日)为 44278 等;该值的小数部分表示当天的时间(即,0.5 是中午,0.625 是下午 3:00)。单元格显示为“日期”或“时间”或“日期时间”的事实纯粹是应用于单元格的 IRange.NumberFormat 的函数(“m/d/yyyy”或“h:mm:ss”, ETC)。如果DateTime
要从单元格中获取实际对象,则需要使用 IWorkbook。NumberToDateTime ( double serialDate ) 辅助方法来执行此操作。
所以底线,你的例程可能看起来像下面这样:
private static void Main(string[] args)
{
var workbook =
Factory.GetWorkbook(
@"D:\MyFiles\SellersCollections.xlsx");
var worksheet = workbook.Worksheets[0];
var cells = worksheet.UsedRange;
List<CustomersDto> dtoList = new List<CustomersDto>();
for (var i = 0; i < cells.RowCount; i++)
{
if (i == 1) // skip header (0)
{
CustomersDto dto = new CustomersDto();
// First two columns appear to be text, using IRange.Text should be fine
// but could probably use IRange.Value as well.
dto.Customers = cells[i, 0].Text;
dto.SalesItem = cells[i, 1].Text;
// Need to convert serial date stored in cell values to actual DateTimes.
// Use IRange.Value and cast to double (may need to introduce some value
// type checking here if other values or empty cell values are allowed.
// See IRange.ValueType to detect what kind of value is stored in a given
// cell).
double serialDate = (double)cells[i, 2].Value;
// Convert serial date to a true DateTime object
DateTime dateTime = workbook.NumberToDateTime(serialDate);
dto.Date = dateTime;
// Contact column appears to be text, so IRange.Text should suffice.
dto.Contact = cells[i, 3].Text;
// Appears to be a number so cast to double (see note above about possible
// value type checking) and then cast again to int.
dto.Quantity = (int)(double)cells[i, 4].Value;
// Add to list
dtoList.Add(dto);
}
}
Console.ReadLine();
}
推荐阅读
- c++ - 如果找到函数,则启用复制构造函数
- firebase - Firebase.functions().httpsCallable 自动验证令牌还是我需要手动 getIdToken() 并使用 firebase admin sdk 进行验证
- java - 使用 selenium Web 驱动程序自动测试以检查来自 gmail 的电子邮件的最佳方法?
- deep-learning - 深度学习中哪种图像预处理更好
- oracle-apex - 如何在摘要中包含过滤器链接 - 徽章列表插件
- mongodb - 无法从 Mongo Shell 连接到 Atlas 集群(Mongo shell 版本 4.0.10)
- azure - 如何使用 Azure APIM 公开我的 REST API?
- tensorflow - 如何在tensorflow2.0的keras模型中使用tf.train.ExponentialMovingAverage
- tfs - 在 TFS 2018 构建中显示 CFML CFLint 结果总结
- haskell - 可以用 `fold/foldl` 和 `f` 等价地定义`foldMap f` 吗?