通过 SpreadSheetGear 读取 .xlsx 到 dto
Read .xlsx to dto via SpreadSheetGear
我想在 .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
映射到模型 class?
SpreadsheetGear 中不存在任何类型的内置映射或绑定功能来为您执行此操作,因此您需要构建自己的例程来执行此操作。如果您的工作簿和 DTO 定义明确且事先已知,我会保留外部“行循环”但删除内部“列循环”并手动索引每个列单元格值并将其放入相应的 DTO 属性 如所须。当然,这意味着您的代码对每一列中包含的信息及其对应的 属性 在 DTO 中的内容有所了解。如果您需要更动态的东西,则必须构建一个更复杂的系统,这超出了此处的回答范围。
就获取单元格值而言,您可能需要查看两个主要 IRange
属性:
- IRange.Value - 此 属性 属于
object
类型,return 是单元格的“原始”值。因此,例如 1.23
的 double
或 true
的 bool
或 "abc"
的 string
。
- IRange.Text - this is of type
string
and returns the "formatted" value of a cell--meaning it takes IRange.Value and applies that cell's Number Format (IRange.NumberFormat) 到值和 returns 结果字符串。换句话说,这 return 是您从 Excel 的 UI 和/或 SpreadsheetGear 的 WorkbookView UI 控件中看到的内容。因此,如果一个单元格的 IRange.Value 为 double 1.23,但其格式设置为显示小数点后 4 位 (IRange.NumberFormat == "0.0000"
),则 IRange.Text 将 return 字符串 "1.2300"
。假设 bool
为 true
的单元格的通用 NumberFormat,IRange.Text 将 return 字符串 "TRUE"
。等等。
需要特别考虑日期。这是因为 Excel 中的日期、时间和日期时间在内部存储为连续数字双精度值,值 1.0 为 1900 年 1 月 1 日,2.0 为 1900 年 1 月 2 日,今天(2021 年 3 月 23 日)为 44278, ETC。;该值的小数部分表示当天的时间(即 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();
}
我想在 .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
映射到模型 class?
SpreadsheetGear 中不存在任何类型的内置映射或绑定功能来为您执行此操作,因此您需要构建自己的例程来执行此操作。如果您的工作簿和 DTO 定义明确且事先已知,我会保留外部“行循环”但删除内部“列循环”并手动索引每个列单元格值并将其放入相应的 DTO 属性 如所须。当然,这意味着您的代码对每一列中包含的信息及其对应的 属性 在 DTO 中的内容有所了解。如果您需要更动态的东西,则必须构建一个更复杂的系统,这超出了此处的回答范围。
就获取单元格值而言,您可能需要查看两个主要 IRange
属性:
- IRange.Value - 此 属性 属于
object
类型,return 是单元格的“原始”值。因此,例如1.23
的double
或true
的bool
或"abc"
的string
。 - IRange.Text - this is of type
string
and returns the "formatted" value of a cell--meaning it takes IRange.Value and applies that cell's Number Format (IRange.NumberFormat) 到值和 returns 结果字符串。换句话说,这 return 是您从 Excel 的 UI 和/或 SpreadsheetGear 的 WorkbookView UI 控件中看到的内容。因此,如果一个单元格的 IRange.Value 为 double 1.23,但其格式设置为显示小数点后 4 位 (IRange.NumberFormat == "0.0000"
),则 IRange.Text 将 return 字符串"1.2300"
。假设bool
为true
的单元格的通用 NumberFormat,IRange.Text 将 return 字符串"TRUE"
。等等。
需要特别考虑日期。这是因为 Excel 中的日期、时间和日期时间在内部存储为连续数字双精度值,值 1.0 为 1900 年 1 月 1 日,2.0 为 1900 年 1 月 2 日,今天(2021 年 3 月 23 日)为 44278, ETC。;该值的小数部分表示当天的时间(即 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();
}