You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

将多个DataGridView导出至Excel工作簿不同工作表的实现求助

嘿,作为Visual Studio新手要搞定这个多窗体DataGridView导出到同个Excel多工作表的需求确实有点头大,不过我给你整理了一套实用的方案,你可以一步步跟着来实现,应该能解决你的问题!

解决方案步骤

1. 准备工作:安装EPPlus库

首先我们需要一个好用的Excel操作库,推荐用EPPlus——它免费、轻量,而且对WinForms项目很友好。你可以通过NuGet安装:

  • 打开Visual Studio的「NuGet包管理器控制台」
  • 输入命令:Install-Package EPPlus -Version 4.5.3.3(这个版本无需商用许可证,适合非商业场景)

2. 封装每个楼层窗体的数据获取方法

为了让主窗体能轻松拿到各个楼层窗体的DataGridView数据,我们在每个楼层窗体(比如Floor1FormFloor2Form)里写一个公共方法,把DataGridView的数据转换成DataTable:

// 以一楼窗体为例,其他楼层窗体同理
public DataTable GetCheckListData()
{
    DataTable dataTable = new DataTable();
    
    // 先添加列(对应DataGridView的表头)
    foreach (DataGridViewColumn col in dgvFloor1.Columns)
    {
        dataTable.Columns.Add(col.HeaderText);
    }
    
    // 再添加行数据
    foreach (DataGridViewRow row in dgvFloor1.Rows)
    {
        if (!row.IsNewRow) // 跳过DataGridView的空行
        {
            DataRow dataRow = dataTable.NewRow();
            for (int i = 0; i < dgvFloor1.Columns.Count; i++)
            {
                dataRow[i] = row.Cells[i].Value ?? DBNull.Value; // 处理空值
            }
            dataTable.Rows.Add(dataRow);
        }
    }
    
    return dataTable;
}

3. 主窗体实现多工作表导出逻辑

在你的主窗体(包含CheckedListBox的那个)里,添加一个导出按钮,编写点击事件逻辑:

private void btnExportMultiFloors_Click(object sender, EventArgs e)
{
    // 先判断有没有勾选楼层
    if (checkedListBoxFloors.CheckedItems.Count == 0)
    {
        MessageBox.Show("请至少勾选一个楼层哦!");
        return;
    }

    // 让用户选择Excel保存路径
    SaveFileDialog saveDialog = new SaveFileDialog();
    saveDialog.Filter = "Excel文件 (*.xlsx)|*.xlsx";
    saveDialog.Title = "导出多楼层检查表";
    if (saveDialog.ShowDialog() != DialogResult.OK)
    {
        return;
    }

    // 创建Excel工作簿
    using (ExcelPackage excelPackage = new ExcelPackage())
    {
        // 遍历每个勾选的楼层
        foreach (var checkedItem in checkedListBoxFloors.CheckedItems)
        {
            string floorName = checkedItem.ToString();
            // 为当前楼层创建一个工作表
            ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add(floorName);

            // 获取对应楼层窗体的数据
            DataTable floorData = GetFloorDataTable(floorName);
            if (floorData == null || floorData.Rows.Count == 0)
            {
                worksheet.Cells["A1"].Value = $"{floorName}暂无检查数据";
                continue;
            }

            // 将DataTable数据填充到工作表
            worksheet.Cells["A1"].LoadFromDataTable(floorData, true);
            // 自动调整列宽,让内容更美观
            worksheet.Cells.AutoFitColumns();
        }

        // 保存Excel文件
        excelPackage.SaveAs(new FileInfo(saveDialog.FileName));
        MessageBox.Show("多楼层检查表导出成功!");
    }
}

// 根据楼层名称匹配对应的窗体,获取数据
private DataTable GetFloorDataTable(string floorName)
{
    switch (floorName)
    {
        case "一楼":
            // 优先用已打开的窗体实例,避免重复创建
            Floor1Form floor1Form = Application.OpenForms.OfType<Floor1Form>().FirstOrDefault() ?? new Floor1Form();
            return floor1Form.GetCheckListData();
        case "二楼":
            Floor2Form floor2Form = Application.OpenForms.OfType<Floor2Form>().FirstOrDefault() ?? new Floor2Form();
            return floor2Form.GetCheckListData();
        // 其他楼层依次添加case
        default:
            return null;
    }
}

4. 单个楼层窗体的单独导出逻辑

如果要实现每个楼层窗体单独导出的功能,直接在对应窗体里添加导出按钮,编写如下逻辑:

private void btnExportSingleFloor_Click(object sender, EventArgs e)
{
    SaveFileDialog saveDialog = new SaveFileDialog();
    saveDialog.Filter = "Excel文件 (*.xlsx)|*.xlsx";
    saveDialog.Title = $"导出{this.Text}检查表";
    if (saveDialog.ShowDialog() != DialogResult.OK)
    {
        return;
    }

    using (ExcelPackage excelPackage = new ExcelPackage())
    {
        ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add(this.Text);
        DataTable floorData = GetCheckListData();
        
        if (floorData == null || floorData.Rows.Count == 0)
        {
            worksheet.Cells["A1"].Value = "暂无检查数据";
        }
        else
        {
            worksheet.Cells["A1"].LoadFromDataTable(floorData, true);
            worksheet.Cells.AutoFitColumns();
        }

        excelPackage.SaveAs(new FileInfo(saveDialog.FileName));
        MessageBox.Show("检查表导出成功!");
    }
}

5. 几个关键注意事项

  • 窗体实例化问题:代码里用Application.OpenForms获取已打开的窗体,避免重复创建新窗体导致数据不一致
  • 空值处理:用?? DBNull.Value处理DataGridView里的空单元格,避免导出时出错
  • EPPlus版本:如果使用5.x及以上版本,商用场景需要购买许可证,非商用可以免费使用;嫌麻烦就直接用4.5.3.3版本

内容的提问来源于stack exchange,提问作者shine

火山引擎 最新活动