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

如何用C#在CSV数据表顶部插入空行并适配DataGridView?

问题描述

我用C#开发Windows Forms桌面应用,将上传的CSV数据存入DataGridView后,转置功能无法正常工作——索引为0的行未被包含在转置输出文件里。手动在CSV顶部插入空行后,应用显示和转置功能都恢复正常,我试过用以下代码插入空行,但没达到预期效果:

DataRow dr1 = dt.NewRow();
dt.Rows.InsertAt(dr1, 0);

需要写出能在索引0位置插入空行并在DataGridView正常显示,让转置功能恢复正常的代码。


存储数据到DataGridView的代码

public DataSet ConnectCSV()
{
    DataSet ds = new DataSet();

    string fileName = openFileDialogCSVFilePath.FileName;

    CsvReader reader = new CsvReader(fileName);

    ds = reader.RowEnumerator;
    dGridCSVdata.DataSource = ds;
    dGridCSVdata.DataMember = "TheData";
    return ds;
}

private void dGridCSVdata_Navigate(object sender, NavigateEventArgs ne)
{

}

CSV读取与转置的代码

public DataSet RowEnumerator
{
    get
    {
        if (null == __reader)
            throw new System.ApplicationException("I can't start reading without CSV input.");

        __rowno = 0;
        string sLine;
        string sNextLine;
        DataSet ds = new DataSet();
        DataTable dt = ds.Tables.Add("TheData");
        DataRow dr1 = dt.NewRow();
        dt.Rows.InsertAt(dr1, 0);

        while (null != (sLine = __reader.ReadLine()))
        {
            while (rexRunOnLine.IsMatch(sLine) && null != (sNextLine = __reader.ReadLine()))
                sLine += "\n" + sNextLine;

            __rowno++;
            DataRow dr = dt.NewRow();
            string[] values = rexCsvSplitter.Split(sLine);

            for (int i = 0; i < values.Length; i++)
            {
                values[i] = Csv.Unescape(values[i]);
                if (__rowno == 1)
                {
                    dt.Columns.Add(values[i].Trim());
                }
                else
                {
                    if (Csv.CharNotAllowes(values[i]))
                    {
                        dr[i] = values[i].Trim();
                    }

                }
            }
            if (__rowno != 1)
            {
                dt.Rows.Add(dr);
            }

            ds.Tables.Add(Transposer.Transpose(dt));
            // transpose code
            StringBuilder sb = new StringBuilder();

            for (int u = 0; u < dt.Columns.Count; u++)
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    sb.Append(dt.Rows[i][u].ToString());

                    if (i < dt.Rows.Count - 1)
                    {
                        sb.Append(',');
                    }
                }
                sb.AppendLine();
            }

            File.WriteAllText("C:\\Users\\Desktop\\Output.csv", sb.ToString());
        }
        __reader.Close();

        return ds;
    }
}

解决方案

问题出在你插入空行的时机不对——一开始就插入空行时,DataTable还没有创建任何列,空行没有对应的数据结构,导致后续转置逻辑异常。同时你每读取一行就写入一次输出文件,会造成文件被多次覆盖。

修改后的RowEnumerator代码如下:

public DataSet RowEnumerator
{
    get
    {
        if (null == __reader)
            throw new System.ApplicationException("I can't start reading without CSV input.");

        __rowno = 0;
        string sLine;
        string sNextLine;
        DataSet ds = new DataSet();
        DataTable dt = ds.Tables.Add("TheData");

        while (null != (sLine = __reader.ReadLine()))
        {
            while (rexRunOnLine.IsMatch(sLine) && null != (sNextLine = __reader.ReadLine()))
                sLine += "\n" + sNextLine;

            __rowno++;
            string[] values = rexCsvSplitter.Split(sLine);
            values = Array.ConvertAll(values, v => Csv.Unescape(v).Trim());

            if (__rowno == 1)
            {
                // 先读取表头,创建DataTable的所有列
                foreach (string colName in values)
                {
                    dt.Columns.Add(colName);
                }
                // 列结构创建完成后,插入空行到索引0位置
                DataRow emptyRow = dt.NewRow();
                dt.Rows.InsertAt(emptyRow, 0);
            }
            else
            {
                DataRow dr = dt.NewRow();
                for (int i = 0; i < values.Length; i++)
                {
                    // 防止行数据列数与表头列数不匹配导致索引越界
                    if (i < dt.Columns.Count)
                    {
                        dr[i] = values[i];
                    }
                }
                dt.Rows.Add(dr);
            }
        }

        // 所有数据读取完成后,再执行转置和文件写入
        ds.Tables.Add(Transposer.Transpose(dt));
        StringBuilder sb = new StringBuilder();
        for (int u = 0; u < dt.Columns.Count; u++)
        {
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                sb.Append(dt.Rows[i][u].ToString());
                if (i < dt.Rows.Count - 1)
                {
                    sb.Append(',');
                }
            }
            sb.AppendLine();
        }
        File.WriteAllText("C:\\Users\\Desktop\\Output.csv", sb.ToString());

        __reader.Close();
        return ds;
    }
}

关键修改点

  1. 调整空行插入时机:先读取CSV第一行作为表头,创建完整的DataTable列结构,再插入空行,确保空行能匹配所有列。
  2. 优化文件写入逻辑:把转置和写入文件的代码移到循环外,避免每读一行就覆盖一次输出文件,确保所有数据加载完成后生成完整的转置结果。
  3. 增加列数校验:添加if (i < dt.Columns.Count)判断,防止CSV行数据列数与表头列数不一致时出现索引越界错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:05:24