我需要将数据从DataGridView导出到Excel,但仅导出选定的单元格。 DataGridView绑定到DataTable。我已经看到了很多有关如何复制所选行的示例,但是找不到如何仅将所选单元格复制到新的DataTable中的示例。到目前为止,这是我尝试过的:
//First, copy structure of DataTable into new one
DataTable dt = ((DataTable)dgv.DataSource).Clone();
//Then insert data into new datatable
foreach (DataGridViewCell cell in dgv.SelectedCells)
{
//We get Index of column and row from bounded DataTable
int col_indx = ((DataTable)dgv.DataSource).Columns.IndexOf(dgv.Columns[cell.ColumnIndex].Name);
int row_indx = ((DataTable)dgv.DataSource).Rows.IndexOf(((DataRowView)dgv.Rows[cell.RowIndex].DataBoundItem).Row);
//First check if row already exists
if (dt.Columns.Contains(dgv.Columns[cell.ColumnIndex].Name))
{
DataRow newrow = dt.NewRow();
newrow[col_indx] = cell.Value;
dt.Rows.InsertAt(newrow, row_indx);
}
else
{
dt.Rows[row_indx][cell_indx] = cell.Value;
}
}
dt.AcceptChanges();
这部分将数据插入到新的DataTable中,但在单独的行中如果我从同一行中选择了一些单元格。我该如何解决?
编辑:
for (int i = 0; i < dgv.Rows.Count; i++)
{
dt.Rows.Add();
for (int j = 0; j < dgv.ColumnCount; j++)
{
if (dgv.Rows[i].Cells[j].Selected == true)
{
dt.Rows[i][j] = dgv.Rows[i].Cells[j].Value;
}
}
}
dt.AcceptChanges();
这是我能实现的最接近的目标。它将选定的数据复制到新的DataTable中,但不幸的是,它也保留了空行。所以当我从例如选择Datagridview中的单元格时第3行,Excel中的输出将前2行为空。我想避免这种情况,但是如何避免呢?换句话说,我在Datagridview中选择的内容必须从第1行的新Datatable开始,依此类推...
答案 0 :(得分:1)
您为每一行添加一行。您必须为每个选定的行添加一行。试试这个
int k=0;
bool addRow;
for (int i = 0; i < dgv.Rows.Count; i++)
{
addRow=true;
for (int j = 0; j < dgv.ColumnCount; j++)
{
if (dgv.Rows[i].Cells[j].Selected == true)
{
if(addRow){
dt.Rows.Add();
addRow=false;
k++;
}
dt.Rows[k-1][j] = dgv.Rows[i].Cells[j].Value;
}
}
}
dt.AcceptChanges();
答案 1 :(得分:0)
您正在遍历每个选定的单元格,并在指定的 row_indx 中创建/插入新行,而无需检查单元格是否属于同一行,以及 dt 是否已在 row_indx 处插入一行。
我建议检查您是否已经在 row_indx 处插入了一行,然后抓取该行并添加到该行(如果没有)没有该行,然后创建新行并添加所选单元格。
答案 2 :(得分:0)
问题解决了。不过,这并不容易。首先,我必须创建一个与绑定DataTable具有相同结构的新DataTable。然后将所有选定的单元格复制到该DataTable中。最后,我使用this answer of Levitikon中的CopyToDataTable方法创建了一个仅包含非空行的新DataTable。这是完整的代码:
//First, copy structure of DataTable into new one
DataTable dt = ((DataTable)dgv.DataSource).Clone();
//Add all selected cells into this DataTable
for (int i = 0; i < dgv.Rows.Count; i++)
{
dt.Rows.Add();
for (int j = 0; j < dgv.ColumnCount; j++)
{
if (dgv.Rows[i].Cells[j].Selected == true)
{
dt.Rows[i][j] = dgv.Rows[i].Cells[j].Value;
}
}
}
dt.AcceptChanges();
// Then create a new DataTable without blank rows
DataTable final_dt = dt.Rows.Cast<DataRow>()
.Where(row => !row.ItemArray.All(field => field is DBNull ||
string.IsNullOrWhiteSpace(field.ToString()))).CopyToDataTable();
现在,我在DataGridView中选择的所有内容都会添加到新的DataTable中,并且一旦我在Excel中导出此DataTable,所有数据就会根据需要从第0行开始。如果有人知道更好/更短的解决方案,请告诉我。