c# wpf 导入 excel 性能
c# wpf importing excel performance
我正在导入一个大的 excel 文件,该文件的长度可以变化(250 多列 * 100,000 行),它包含数据列,其中列的数量及其名称可以更改,行也是变量,但它们是值。
我正在使用 Interop 将数据提取到绑定到数据网格的数据表中,但是我正在单独导入每一行,对于较大的文件可能需要 25 分钟以上的时间才能完成。
public Task<DataTable> ParseExcel(string filePath)
{
return Task.Run(() =>
{
var excelApp = new Microsoft.Office.Interop.Excel.Application();
var excelBook = excelApp.Workbooks.Open(filePath, 0, true, 5, "", "", true,
Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
var excelSheet = (Microsoft.Office.Interop.Excel.Worksheet)excelBook.Worksheets.Item[1];
Microsoft.Office.Interop.Excel.Range excelRange = excelSheet.UsedRange;
DataTable sessiondt = new DataTable();
object[,] value = excelRange.Value;
int columnsCount = value.GetLength(1);
for (var colCnt = 1; colCnt <= columnsCount; colCnt++)
{
sessiondt.Columns.Add((string)value[1, colCnt], typeof(string));
}
int rowsCount = value.GetLength(0);
for (var rowCnt = 2; rowCnt <= rowsCount; rowCnt++)
{
var dataRow = sessiondt.NewRow();
for (var colCnt = 1; colCnt <= columnsCount; colCnt++)
{
dataRow[colCnt - 1] = value[rowCnt, colCnt];
}
sessiondt.Rows.Add(dataRow);
}
excelBook.Close(true);
excelApp.Quit();
return sessiondt;
});
}
与其单独插入每一行,不如将其全部放入可以绑定数据的自定义对象的列表中可能会更快。但我不确定该怎么做。
另外,我想以一种不需要提前在列名中编码的方式绑定列。我将尝试在图表中显示这些,并且能够自动将列名填充到组合框中会更容易。
提前谢谢你,我是 c# 和 wpf 的新手,还在学习中。
Interop 有一些特定用途,但如果您只想从 Excel 文件中获取数据,Interop 可能是最慢、最麻烦的方法。
Excel 文件,无论是 .xls 还是 .xlsx 都可以像数据库一样处理和访问。
只要您的工作sheets 中的行和列中有数据,您就可以打开到它的OleDb
连接并运行 查询它。
Sheet 名称代替了 table 名称,如果您在 sheet 的第一行中有列标题,那么这些就是字段名称。
您只需要正确的连接字符串:
https://www.connectionstrings.com/excel/
使用这种方法检索数据的 'watch-outs' 之一是数据类型是根据每列中的前几个条目自动分配的。您无法覆盖此行为(您曾经可以,但现在不能)。如果您在一列中有 alpha-numerics,并且前十几个条目都是数字,这可能会导致问题。然后该列将自动分配为数字类型。如果您在该列后面的行中有混合 alpha-numeric 或纯文本的数据,这些条目将被忽略(不导入),因为它们与最初分配的数据类型不匹配。
解决此问题的唯一好方法是以编程方式解压缩并解析 xml 文件的内容。
如果您始终拥有一致的数据,那么这不是问题。
这是使用 GemBox.Spreadsheet 库实现此目的的另一种方法,既快速又直接:
public Task<DataTable> ParseExcel(string filePath)
{
return Task.Run(() =>
{
ExcelFile excelBook = ExcelFile.Load(filePath);
ExcelWorksheet excelSheet = excelBook.Worksheets[0];
CreateDataTableOptions options = new CreateDataTableOptions();
return excelSheet.CreateDataTable(options);
});
}
我正在导入一个大的 excel 文件,该文件的长度可以变化(250 多列 * 100,000 行),它包含数据列,其中列的数量及其名称可以更改,行也是变量,但它们是值。
我正在使用 Interop 将数据提取到绑定到数据网格的数据表中,但是我正在单独导入每一行,对于较大的文件可能需要 25 分钟以上的时间才能完成。
public Task<DataTable> ParseExcel(string filePath)
{
return Task.Run(() =>
{
var excelApp = new Microsoft.Office.Interop.Excel.Application();
var excelBook = excelApp.Workbooks.Open(filePath, 0, true, 5, "", "", true,
Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
var excelSheet = (Microsoft.Office.Interop.Excel.Worksheet)excelBook.Worksheets.Item[1];
Microsoft.Office.Interop.Excel.Range excelRange = excelSheet.UsedRange;
DataTable sessiondt = new DataTable();
object[,] value = excelRange.Value;
int columnsCount = value.GetLength(1);
for (var colCnt = 1; colCnt <= columnsCount; colCnt++)
{
sessiondt.Columns.Add((string)value[1, colCnt], typeof(string));
}
int rowsCount = value.GetLength(0);
for (var rowCnt = 2; rowCnt <= rowsCount; rowCnt++)
{
var dataRow = sessiondt.NewRow();
for (var colCnt = 1; colCnt <= columnsCount; colCnt++)
{
dataRow[colCnt - 1] = value[rowCnt, colCnt];
}
sessiondt.Rows.Add(dataRow);
}
excelBook.Close(true);
excelApp.Quit();
return sessiondt;
});
}
与其单独插入每一行,不如将其全部放入可以绑定数据的自定义对象的列表中可能会更快。但我不确定该怎么做。
另外,我想以一种不需要提前在列名中编码的方式绑定列。我将尝试在图表中显示这些,并且能够自动将列名填充到组合框中会更容易。
提前谢谢你,我是 c# 和 wpf 的新手,还在学习中。
Interop 有一些特定用途,但如果您只想从 Excel 文件中获取数据,Interop 可能是最慢、最麻烦的方法。
Excel 文件,无论是 .xls 还是 .xlsx 都可以像数据库一样处理和访问。
只要您的工作sheets 中的行和列中有数据,您就可以打开到它的OleDb
连接并运行 查询它。
Sheet 名称代替了 table 名称,如果您在 sheet 的第一行中有列标题,那么这些就是字段名称。
您只需要正确的连接字符串: https://www.connectionstrings.com/excel/
使用这种方法检索数据的 'watch-outs' 之一是数据类型是根据每列中的前几个条目自动分配的。您无法覆盖此行为(您曾经可以,但现在不能)。如果您在一列中有 alpha-numerics,并且前十几个条目都是数字,这可能会导致问题。然后该列将自动分配为数字类型。如果您在该列后面的行中有混合 alpha-numeric 或纯文本的数据,这些条目将被忽略(不导入),因为它们与最初分配的数据类型不匹配。
解决此问题的唯一好方法是以编程方式解压缩并解析 xml 文件的内容。
如果您始终拥有一致的数据,那么这不是问题。
这是使用 GemBox.Spreadsheet 库实现此目的的另一种方法,既快速又直接:
public Task<DataTable> ParseExcel(string filePath)
{
return Task.Run(() =>
{
ExcelFile excelBook = ExcelFile.Load(filePath);
ExcelWorksheet excelSheet = excelBook.Worksheets[0];
CreateDataTableOptions options = new CreateDataTableOptions();
return excelSheet.CreateDataTable(options);
});
}