You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何实现DataGridView数据的保存与加载?

DataGridView Excel加载错误修复与替代方案

错误原因分析

  • xlrange类型错误:UsedRange返回的是Range对象,你错误地将其强制转换为_Worksheet,触发E_NOINTERFACE错误。
  • 单元格索引错误:加载时从第2列开始读取(xlrow,2),但导出时是从第1列写入的,导致列索引越界,触发DISP_E_BADINDEX错误。
  • 硬编码列数:代码里固定读取到第7列,若DataGridView列数变化会直接出错。

修复后的Interop加载代码

修正上述问题,同时匹配你的导出格式(第一行是标题,从第二行加载数据):

using (OpenFileDialog ofd = new OpenFileDialog())
{
    ofd.Filter = "Excel Files Only | *.xlsx; *.xls";
    ofd.Title = "Choose the File";
    if (ofd.ShowDialog() == DialogResult.OK)
        FileName_LBL.Text = ofd.FileName;
}

Microsoft.Office.Interop.Excel.Application xlapp = null;
Microsoft.Office.Interop.Excel.Workbook xlworkbook = null;
Microsoft.Office.Interop.Excel.Worksheet xlworksheet = null;
Microsoft.Office.Interop.Excel.Range xlrange = null;

try
{
    xlapp = new Microsoft.Office.Interop.Excel.Application();
    xlapp.Visible = false; // 后台操作避免弹窗干扰
    xlworkbook = xlapp.Workbooks.Open(FileName_LBL.Text);
    
    // 优先按导出的工作表名称查找,找不到则用第一个工作表
    xlworksheet = xlworkbook.Worksheets["Exported from Journal Pro"] as Microsoft.Office.Interop.Excel.Worksheet;
    if (xlworksheet == null)
        xlworksheet = xlworkbook.Worksheets[1] as Microsoft.Office.Interop.Excel.Worksheet;

    xlrange = xlworksheet.UsedRange;
    int columnCount = xlrange.Columns.Count;
    int rowCount = xlrange.Rows.Count;

    // 清空DataGridView现有数据
    dataGridView1.Rows.Clear();
    dataGridView1.Columns.Clear();

    // 从Excel第一行读取并设置列标题
    for (int col = 1; col <= columnCount; col++)
    {
        string headerText = xlrange.Cells[1, col].Value?.ToString() ?? "";
        dataGridView1.Columns.Add($"Column{col}", headerText);
    }

    // 从Excel第二行开始加载数据
    for (int row = 2; row <= rowCount; row++)
    {
        string[] rowData = new string[columnCount];
        for (int col = 1; col <= columnCount; col++)
        {
            rowData[col - 1] = xlrange.Cells[row, col].Value?.ToString() ?? "";
        }
        dataGridView1.Rows.Add(rowData);
    }
}
catch (Exception ex)
{
    MessageBox.Show($"加载失败:{ex.Message}");
}
finally
{
    // 释放Excel COM对象,避免进程残留
    if (xlrange != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlrange);
    if (xlworksheet != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlworksheet);
    if (xlworkbook != null)
    {
        xlworkbook.Close(false);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlworkbook);
    }
    if (xlapp != null)
    {
        xlapp.Quit();
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlapp);
    }
}

非Excel的替代方案(CSV格式)

如果不想依赖Office Interop,CSV是更轻量、稳定的选择,以下是匹配原导出格式的保存和加载代码:

CSV保存代码

private void SaveToCsv()
{
    using (SaveFileDialog sfd = new SaveFileDialog())
    {
        sfd.Filter = "CSV Files (*.csv)|*.csv";
        sfd.Title = "Save as CSV";
        if (sfd.ShowDialog() != DialogResult.OK) return;

        using (StreamWriter writer = new StreamWriter(sfd.FileName))
        {
            // 写入列标题(处理含引号的特殊字符)
            string[] headers = dataGridView1.Columns.Cast<DataGridViewColumn>()
                .Select(col => $"\"{col.HeaderText.Replace("\"", "\"\"")}\"")
                .ToArray();
            writer.WriteLine(string.Join(",", headers));

            // 写入数据行,跳过新增行
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                if (row.IsNewRow) continue;
                string[] rowData = row.Cells.Cast<DataGridViewCell>()
                    .Select(cell => 
                    {
                        string value = cell.Value?.ToString() ?? "";
                        return $"\"{value.Replace("\"", "\"\"")}\"";
                    })
                    .ToArray();
                writer.WriteLine(string.Join(",", rowData));
            }
        }
        MessageBox.Show("保存成功");
    }
}

CSV加载代码

private void LoadFromCsv()
{
    using (OpenFileDialog ofd = new OpenFileDialog())
    {
        ofd.Filter = "CSV Files (*.csv)|*.csv";
        ofd.Title = "Choose CSV File";
        if (ofd.ShowDialog() != DialogResult.OK) return;

        dataGridView1.Rows.Clear();
        dataGridView1.Columns.Clear();

        using (StreamReader reader = new StreamReader(ofd.FileName))
        {
            // 读取列标题
            string headerLine = reader.ReadLine();
            if (!string.IsNullOrEmpty(headerLine))
            {
                string[] headers = ParseCsvLine(headerLine);
                foreach (string header in headers)
                {
                    dataGridView1.Columns.Add($"Column{dataGridView1.Columns.Count + 1}", header);
                }
            }

            // 读取数据行
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                string[] rowData = ParseCsvLine(line);
                dataGridView1.Rows.Add(rowData);
            }
        }
        MessageBox.Show("加载成功");
    }
}

// 解析带引号转义的CSV行
private string[] ParseCsvLine(string line)
{
    List<string> fields = new List<string>();
    StringBuilder currentField = new StringBuilder();
    bool inQuotes = false;

    foreach (char c in line)
    {
        if (c == '"')
        {
            inQuotes = !inQuotes;
            // 处理双引号转义(两个连续引号表示一个实际引号)
            if (inQuotes && currentField.Length > 0 && currentField[currentField.Length - 1] == '"')
            {
                currentField.Append('"');
                inQuotes = false;
            }
        }
        else if (c == ',' && !inQuotes)
        {
            fields.Add(currentField.ToString());
            currentField.Clear();
        }
        else
        {
            currentField.Append(c);
        }
    }
    fields.Add(currentField.ToString());
    return fields.ToArray();
}

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:05:30