使用 ClosedXML 和 OpenFileDialog 将 Excel 导入 DataGrid
Importing Excel to DataGrid using ClosedXML and OpenFileDialog
我想使用 ClosedXML 将 Excel 文件加载到我的 DataGrid 中。
我有这个方法:
public static DataTable ImportExceltoDataTable(string filePath, string sheetName) {
using (XLWorkbook wb = new(filePath)) {
IXLWorksheet ws = wb.Worksheet(1);
DataTable dt = new();
bool firstRow = true;
foreach (IXLRow row in ws.Rows()) {
if (firstRow) {
foreach (IXLCell cell in row.Cells()) {
dt.Columns.Add(cell.CachedValue.ToString());
}
firstRow = false;
} else {
dt.Rows.Add();
int i = 0;
foreach (IXLCell cell in row.Cells(row.FirstCellUsed().Address.ColumnNumber, row.LastCellUsed().Address.ColumnNumber)) {
dt.Rows[dt.Rows.Count - 1][i} = cell.CachedValue.ToString();
i++;
}
}
}
return dt;
}
}
在点击事件中,我尝试使用 OpenFileDialog
选择我的文件,见下文:
OpenFileDialog of = new();
of.Filter = "Excel Files | *.xlsx;";
of.Title = "Import Excel file.";
if (of.ShowDialog()==true) {
dataGrid.ItemsSource = ImportExceltoDataTable("...", "...").DefaultView;
}
但我不知道如何通知 DataTable
我在 OpenFileDialog
中选择了一个文件。
在 DataTable
方法的第一行,我收到以下异常错误:
System.ArgumentException: 'Empty extension is not supported'
有道理...我如何告诉它我选择了哪个文件?
您可能想要 re-think 您阅读 excel 文件的方法。一个可能的问题是 if (firstRow) { …
… 语句,它很奇怪并且做出了一个危险的假设。代码“假设”每一列数据“有”一个 header 单元格。换句话说,添加到 DataTable
的列数将取决于在“FIRST”行上找到的单元格数(单元格中有一些文本)。如果一列数据没有 header 单元格怎么办?
因此,如果第一行的单元格右侧有任何行具有 headers 的数据,则 DataTable
的列数将不正确......并且,当代码到达下面 else
部分中的这些单元格……当 i
超出 dt
的列数时,代码很可能会崩溃。
代码需要保证dt
有正确的列数以避免上述问题。一种帮助方法是找到定义数据开始的“top-left”单元格(因为它不一定总是工作表中的第一个单元格)和“bottom-right”单元格的两个单元格找到包含数据的“最后一个”单元格。
一旦我们有了这两个单元格(top-left 和 bottom-right)……然后,我们就可以确定 DataTable
中需要多少列……并且……我们几乎可以保证工作表中的所有数据都将适合 DataTable
.
下面是使用上述想法的一种可能的解决方案。请注意,下面的代码不使用特定的工作表名称,只是使用给定工作簿中的第一个工作表。
private void Button_Click(object sender, RoutedEventArgs e) {
OpenFileDialog of = new OpenFileDialog();
of.Filter = "Excel Files | *.xlsx;";
of.Title = "Import Excel file.";
if (of.ShowDialog() == true) {
dataGrid.ItemsSource = ImportExceltoDataTable(of.FileName).DefaultView;
}
}
public static DataTable ImportExceltoDataTable(string filePath) {
using (XLWorkbook wb = new XLWorkbook(filePath)) {
IXLWorksheet ws = wb.Worksheet(1);
int tl_Row = ws.FirstCellUsed().Address.RowNumber;
int tl_Col = ws.FirstCellUsed().Address.ColumnNumber;
int br_Row = ws.LastCellUsed().Address.RowNumber;
int br_Col = ws.LastCellUsed().Address.ColumnNumber;
DataTable dt = new DataTable();
// add dt columns using the first row of data
for (int i = tl_Col; i <= br_Col; i++) {
dt.Columns.Add(ws.Cell(tl_Row, i).CachedValue.ToString());
}
IXLRow currentRow;
// add data from the worksheet to dt - we already used the first row of data for the columns
for (int dtRow = 0; dtRow < br_Row - tl_Row; dtRow++) {
currentRow = ws.Row(tl_Row + dtRow + 1);
dt.Rows.Add();
for (int dtCol = 0; dtCol < br_Col - tl_Col + 1; dtCol++) {
dt.Rows[dtRow][dtCol] = currentRow.Cell(tl_Col + dtCol).CachedValue;
}
}
return dt;
}
}
我希望这有道理并有所帮助。
我想使用 ClosedXML 将 Excel 文件加载到我的 DataGrid 中。
我有这个方法:
public static DataTable ImportExceltoDataTable(string filePath, string sheetName) {
using (XLWorkbook wb = new(filePath)) {
IXLWorksheet ws = wb.Worksheet(1);
DataTable dt = new();
bool firstRow = true;
foreach (IXLRow row in ws.Rows()) {
if (firstRow) {
foreach (IXLCell cell in row.Cells()) {
dt.Columns.Add(cell.CachedValue.ToString());
}
firstRow = false;
} else {
dt.Rows.Add();
int i = 0;
foreach (IXLCell cell in row.Cells(row.FirstCellUsed().Address.ColumnNumber, row.LastCellUsed().Address.ColumnNumber)) {
dt.Rows[dt.Rows.Count - 1][i} = cell.CachedValue.ToString();
i++;
}
}
}
return dt;
}
}
在点击事件中,我尝试使用 OpenFileDialog
选择我的文件,见下文:
OpenFileDialog of = new();
of.Filter = "Excel Files | *.xlsx;";
of.Title = "Import Excel file.";
if (of.ShowDialog()==true) {
dataGrid.ItemsSource = ImportExceltoDataTable("...", "...").DefaultView;
}
但我不知道如何通知 DataTable
我在 OpenFileDialog
中选择了一个文件。
在 DataTable
方法的第一行,我收到以下异常错误:
System.ArgumentException: 'Empty extension is not supported'
有道理...我如何告诉它我选择了哪个文件?
您可能想要 re-think 您阅读 excel 文件的方法。一个可能的问题是 if (firstRow) { …
… 语句,它很奇怪并且做出了一个危险的假设。代码“假设”每一列数据“有”一个 header 单元格。换句话说,添加到 DataTable
的列数将取决于在“FIRST”行上找到的单元格数(单元格中有一些文本)。如果一列数据没有 header 单元格怎么办?
因此,如果第一行的单元格右侧有任何行具有 headers 的数据,则 DataTable
的列数将不正确......并且,当代码到达下面 else
部分中的这些单元格……当 i
超出 dt
的列数时,代码很可能会崩溃。
代码需要保证dt
有正确的列数以避免上述问题。一种帮助方法是找到定义数据开始的“top-left”单元格(因为它不一定总是工作表中的第一个单元格)和“bottom-right”单元格的两个单元格找到包含数据的“最后一个”单元格。
一旦我们有了这两个单元格(top-left 和 bottom-right)……然后,我们就可以确定 DataTable
中需要多少列……并且……我们几乎可以保证工作表中的所有数据都将适合 DataTable
.
下面是使用上述想法的一种可能的解决方案。请注意,下面的代码不使用特定的工作表名称,只是使用给定工作簿中的第一个工作表。
private void Button_Click(object sender, RoutedEventArgs e) {
OpenFileDialog of = new OpenFileDialog();
of.Filter = "Excel Files | *.xlsx;";
of.Title = "Import Excel file.";
if (of.ShowDialog() == true) {
dataGrid.ItemsSource = ImportExceltoDataTable(of.FileName).DefaultView;
}
}
public static DataTable ImportExceltoDataTable(string filePath) {
using (XLWorkbook wb = new XLWorkbook(filePath)) {
IXLWorksheet ws = wb.Worksheet(1);
int tl_Row = ws.FirstCellUsed().Address.RowNumber;
int tl_Col = ws.FirstCellUsed().Address.ColumnNumber;
int br_Row = ws.LastCellUsed().Address.RowNumber;
int br_Col = ws.LastCellUsed().Address.ColumnNumber;
DataTable dt = new DataTable();
// add dt columns using the first row of data
for (int i = tl_Col; i <= br_Col; i++) {
dt.Columns.Add(ws.Cell(tl_Row, i).CachedValue.ToString());
}
IXLRow currentRow;
// add data from the worksheet to dt - we already used the first row of data for the columns
for (int dtRow = 0; dtRow < br_Row - tl_Row; dtRow++) {
currentRow = ws.Row(tl_Row + dtRow + 1);
dt.Rows.Add();
for (int dtCol = 0; dtCol < br_Col - tl_Col + 1; dtCol++) {
dt.Rows[dtRow][dtCol] = currentRow.Cell(tl_Col + dtCol).CachedValue;
}
}
return dt;
}
}
我希望这有道理并有所帮助。