我有一个包含 60 行数据的数据网格和一个将其导入 Excel 的按钮:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Source}"
CanUserAddRows="False" HeadersVisibility="All"
Name="dgDisplay">
<DataGrid.Columns>
<DataGridTextColumn Header="Day" Binding="{Binding Day}"/>
<DataGridTextColumn Header="Data" Binding="{Binding Data}"/>
</DataGrid.Columns>
</DataGrid>
<Button Command="{Binding SaveDataGridToExcelCommand}"
CommandParameter="{Binding ElementName=dgDisplay}"/>
其中
Day
和 Data
只是一些随机生成的 int 数据。
我的代码使用 ClosedXML 将数据从中导出到 Excel,它使用 MainWindowViewModel: ObservableObject
调用 MVVM.Toolkit
。
[RelayCommand]
public void SaveDataGridToExcel(DataGrid dataGrid)
{
DataTable dt = new DataTable();
foreach (DataGridColumn column in dataGrid.Columns)
{
dt.Columns.Add(column.Header.ToString());
}
foreach (var item in dataGrid.Items)
{
DataRow dr = dt.NewRow();
bool rowHasData = false;
for (int i = 0; i < dataGrid.Columns.Count; i++)
{
var cellContent = dataGrid.Columns[i].GetCellContent(item);
if (cellContent is TextBlock textBlock)
{
//check if row empty, dont add this row.I add it on purpose to check
//if the datagrid recognite the rest 50 rows not have data. It actually
//dont save those data
dr[i] = textBlock.Text;
if (!string.IsNullOrEmpty(textBlock.Text))
{
rowHasData = true;
}
}
}
if (rowHasData)
{
dt.Rows.Add(dr);
}
}
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Excel files (*.xlsx)|*.xlsx";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
using (XLWorkbook wb = new XLWorkbook())
{
wb.Worksheets.Add(dt, "Sheet1");
wb.SaveAs(saveFileDialog.FileName);
}
}
}
但是保存的60行结果只显示了10行数据,其余50行都是空的。如果疑问为什么不使用
Microsoft.Interop.Excel
,那是因为该包不适合我的 Excel 版本。我没有在 ClosedXML 中看到任何对此有限制或许可的地方,所以我想知道为什么。如有任何帮助,我们将不胜感激。
在浏览 github 几个小时后,我自己找到了答案。 我没有访问单元格内容,而是直接从 DataGrid 的 ItemsSource 访问数据:
public void SaveDataGridToExcel(DataGrid dataGrid)
{
DataTable dataTable = new DataTable();
foreach (DataGridColumn column in dataGrid.Columns)
{
dataTable.Columns.Add(column.Header.ToString());
}
var itemsSource = dataGrid.ItemsSource as IEnumerable;
if (itemsSource != null)
{
foreach (var item in itemsSource)
{
var properties = item.GetType().GetProperties();
var row = dataTable.NewRow();
foreach (var property in properties)
{
row[property.Name] = property.GetValue(item);
}
dataTable.Rows.Add(row);
}
}
//show dialog...
}