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

C# WinForm导入CSV后实现数据转置(列转行)的问题及解决

C# WinForm实现CSV数据转置功能问题

我正在使用C#开发Windows Form桌面应用,希望实现用户导入CSV文件后将数据转置(列转为行)的功能,请问如何编写对应代码?

我已编写导入按钮的代码:

private void btnImport_Click(object sender, System.EventArgs e)
{
    try
    {
        if (txtCSVFolderPath.Text == "")
        {
            MessageBox.Show("The Folder Path TextBox cannot be empty.", "Warning");
            return;
        }
        else if (txtCSVFilePath.Text == "")
        {
            MessageBox.Show("The File Path TextBox cannot be empty.", "Warning");
            return;
        }

        else
        {
            ConnectCSV();
            btnUpload.Enabled = true;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    { }
}

以及ConnectCSV方法:

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;
}

更新:转置代码无效果的问题

我尝试使用StringBuilder实现转置,但没有效果,请问问题出在哪里?或者有没有其他实现方法?

我的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++;
            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);
            }
        }

        StringBuilder sb = new StringBuilder();// code I add for transpose the data table

        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;
    }
}

问题分析

你当前的转置代码存在几个关键问题:

  • 未包含表头信息:原CSV的表头(第一行)没有被加入转置结果,导致输出的转置CSV缺少列名标识
  • 空值未处理:直接调用dt.Rows[i][u].ToString(),如果单元格为空(DBNull.Value)会引发异常
  • 分隔符不一致:原CSV使用逗号分隔,但转置结果用分号,可能不符合预期格式
  • 未更新界面显示:转置结果仅写入文件,没有绑定到dGridCSVdata,所以你无法在界面看到转置效果

解决方案

方案1:修复现有StringBuilder转置逻辑

修改RowEnumerator中的StringBuilder部分,补上表头处理、空值判断和统一分隔符:

StringBuilder sb = new StringBuilder();

// 先处理表头:将原表头作为转置后每一行的第一个元素
for (int colIndex = 0; colIndex < dt.Columns.Count; colIndex++)
{
    // 添加表头
    sb.Append(dt.Columns[colIndex].ColumnName);
    // 添加当前列的所有行数据
    for (int rowIndex = 0; rowIndex < dt.Rows.Count; rowIndex++)
    {
        sb.Append(',');
        // 处理空值,避免ToString()报错
        var cellValue = dt.Rows[rowIndex][colIndex];
        sb.Append(cellValue == DBNull.Value ? "" : cellValue.ToString().Trim());
    }
    sb.AppendLine();
}

// 注意:路径最好让用户选择,避免硬编码导致权限或路径不存在问题
File.WriteAllText("C:\\Users\\Desktop\\Transposed_Output.csv", sb.ToString());

方案2:创建转置后的DataTable(推荐)

这种方法可以将转置结果绑定到DataGridView,同时也方便导出CSV,更符合WinForm的交互逻辑:

首先添加一个转置方法:

private DataTable TransposeDataTable(DataTable originalTable)
{
    DataTable transposedTable = new DataTable("TransposedData");

    // 转置后的第一列是原表的列名,后续列对应原表的每一行
    transposedTable.Columns.Add("Column_Name");
    for (int rowIndex = 0; rowIndex < originalTable.Rows.Count; rowIndex++)
    {
        transposedTable.Columns.Add($"Row_{rowIndex + 1}");
    }

    // 遍历原表的每一列,生成转置后的每一行
    foreach (DataColumn originalCol in originalTable.Columns)
    {
        DataRow newRow = transposedTable.NewRow();
        newRow["Column_Name"] = originalCol.ColumnName;
        
        for (int rowIndex = 0; rowIndex < originalTable.Rows.Count; rowIndex++)
        {
            var cellValue = originalTable.Rows[rowIndex][originalCol];
            newRow[rowIndex + 1] = cellValue ?? DBNull.Value;
        }
        
        transposedTable.Rows.Add(newRow);
    }

    return transposedTable;
}

然后在ConnectCSV方法中调用,更新界面显示:

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

    string fileName = openFileDialogCSVFilePath.FileName;
    CsvReader reader = new CsvReader(fileName);
    ds = reader.RowEnumerator;
    
    // 获取原数据表并转置
    DataTable originalTable = ds.Tables["TheData"];
    DataTable transposedTable = TransposeDataTable(originalTable);
    
    // 将转置后的表加入DataSet,绑定到DataGridView
    ds.Tables.Add(transposedTable);
    dGridCSVdata.DataSource = ds;
    dGridCSVdata.DataMember = "TransposedData";
    
    // 导出转置后的CSV(可选)
    ExportDataTableToCsv(transposedTable, "C:\\Users\\Desktop\\Transposed_Output.csv");
    
    btnUpload.Enabled = true;
    return ds;
}

// 添加CSV导出辅助方法
private void ExportDataTableToCsv(DataTable dt, string filePath)
{
    StringBuilder sb = new StringBuilder();
    
    // 写入表头
    string[] columnNames = dt.Columns.Cast<DataColumn>().Select(col => col.ColumnName).ToArray();
    sb.AppendLine(string.Join(",", columnNames));
    
    // 写入行数据
    foreach (DataRow row in dt.Rows)
    {
        string[] fields = row.ItemArray.Select(field => 
            field == DBNull.Value ? "" : $"\"{field.ToString().Replace("\"", "\"\"")}\""
        ).ToArray();
        sb.AppendLine(string.Join(",", fields));
    }
    
    File.WriteAllText(filePath, sb.ToString());
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 05:05:22