将datagridview导出到csv文件

Posted

技术标签:

【中文标题】将datagridview导出到csv文件【英文标题】:Exporting datagridview to csv file 【发布时间】:2012-04-14 04:28:42 【问题描述】:

我正在开发一个应用程序,它将我的名为scannerDataGridView 的DataGridView 导出到一个csv 文件。

找到了一些示例代码来执行此操作,但无法使其正常工作。顺便说一句,我的数据网格没有数据绑定到源。

当我尝试使用 Streamwriter 仅写入列标题时,一切顺利,但是当我尝试导出包括数据在内的整个数据网格时,我得到了一个例外。

System.NullReferenceException:对象引用未设置为实例 的一个对象。在 Scanmonitor.Form1.button1_Click(对象发件人, 事件参数 e)

这是我的代码,以下行给出了错误:

dataFromGrid = dataFromGrid + ',' + dataRowObject.Cells[i].Value.ToString();

//csvFileWriter = StreamWriter
//scannerDataGridView = DataGridView   

private void button1_Click(object sender, EventArgs e)

    string CsvFpath = @"C:\scanner\CSV-EXPORT.csv";
    try
    
        System.IO.StreamWriter csvFileWriter = new StreamWriter(CsvFpath, false);

        string columnHeaderText = "";

        int countColumn = scannerDataGridView.ColumnCount - 1;

        if (countColumn >= 0)
        
            columnHeaderText = scannerDataGridView.Columns[0].HeaderText;
        

        for (int i = 1; i <= countColumn; i++)
        
            columnHeaderText = columnHeaderText + ',' + scannerDataGridView.Columns[i].HeaderText;
        


        csvFileWriter.WriteLine(columnHeaderText);

        foreach (DataGridViewRow dataRowObject in scannerDataGridView.Rows)
        
            if (!dataRowObject.IsNewRow)
            
                string dataFromGrid = "";

                dataFromGrid = dataRowObject.Cells[0].Value.ToString();

                for (int i = 1; i <= countColumn; i++)
                
                    dataFromGrid = dataFromGrid + ',' + dataRowObject.Cells[i].Value.ToString();

                    csvFileWriter.WriteLine(dataFromGrid);
                
            
        


        csvFileWriter.Flush();
        csvFileWriter.Close();
    
    catch (Exception exceptionObject)
    
        MessageBox.Show(exceptionObject.ToString());
    

【问题讨论】:

在哪一行抛出异常?您也可以使用 foreach 来遍历每一行的列:foreach(dataRowObject.Cells 中的 DataGridViewCell 单元格),除非有特定原因您更喜欢正常的 for 循环? 也可以检查scannerDataGridView.Rows.Count > 0 嗨 PandaNL,我已经删除了我的答案。我仍然认为违规行应该是object value = dataRowObject.Cells[i].Value; dataFromGrid = dataFromGrid + ',' + (value ?? string.Empty).ToString()); 在close()之前不需要flush()。 Dispose() 调用 Close() 并调用 flush()。 【参考方案1】:

LINQ FTW!

var sb = new StringBuilder();

var headers = dataGridView1.Columns.Cast<DataGridViewColumn>();
sb.AppendLine(string.Join(",", headers.Select(column => "\"" + column.HeaderText + "\"").ToArray()));

foreach (DataGridViewRow row in dataGridView1.Rows)

    var cells = row.Cells.Cast<DataGridViewCell>();
    sb.AppendLine(string.Join(",", cells.Select(cell => "\"" + cell.Value + "\"").ToArray()));

确实,c.Value.ToString() 将抛出空值,而c.Value 将正确转换为空字符串。

【讨论】:

我在原始代码中遇到错误,必须进行一次编辑: headers.Select(column => "\"" + column.HeaderText + "\""); headers.Select(column => "\"" + column.HeaderText + "\"").ToArray(); 我发现了和 BH 一样的东西(并提交了编辑)。除此之外,这是一个很好的答案! 另外,我有一个(单独的)问题,第一列使用了一个特殊的“RowIndex”属性,(奇怪的是)没有设置单元格值。通过抓取“cell.FormattedValue”而不是第一列的 cell.Value 来修复。 sb.AppendLine( string.Join(",", cells.Select( cell => "\"" + (cell.ColumnIndex == 0 ? cell.FormattedValue : cell.Value) + "\"" ).ToArray() )); 使用CurrentCulture.TextInfo.ListSeparatorì而不是"," 如何检查演员表行中的任何单元格是否为空?【参考方案2】:

DataGridView 的一个鲜为人知的功能是能够以编程方式选择部分或全部 DataGridCell,并使用方法 DataGridView.GetClipboardContent() 将它们发送到 DataObject。那这有什么好处呢?

DataObject 不只是存储一个对象,而是以各种不同格式表示该对象。这就是剪贴板能够发挥其魔力的方式;它存储了各种格式,并且不同的控件/类可以指定他们希望接受的格式。在这种情况下,DataGridView 会将 DataObject 中选定的单元格存储为制表符分隔的文本格式、CSV 格式或 html (*)。

可以通过调用DataObject.GetData()DataObject.GetText() 方法并指定预定义的数据格式枚举来检索DataObject 的内容。在这种情况下,我们希望 CSV 的格式为 TextDataFormat.CommaSeparatedValue,然后我们可以使用 System.IO.File 类将该结果写入文件。

(*) 实际上,它返回的并不是严格意义上的 HTML。此格式还将包含您不期望的数据标题。虽然标题确实包含 HTML 的起始位置,但我只是丢弃了 HTML 标记上方的任何内容,例如 myString.Substring(IndexOf("&lt;HTML&gt;"));

观察以下代码:

void SaveDataGridViewToCSV(string filename)
        
    // Choose whether to write header. Use EnableWithoutHeaderText instead to omit header.
    dataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText;
    // Select all the cells
    dataGridView1.SelectAll();
    // Copy selected cells to DataObject
    DataObject dataObject = dataGridView1.GetClipboardContent();
    // Get the text of the DataObject, and serialize it to a file
    File.WriteAllText(filename, dataObject.GetText(TextDataFormat.CommaSeparatedValue));

现在,这不是更好吗?为什么要重新发明***?

希望这会有所帮助...

【讨论】:

我看到这个丑陋的解决方案在网上流传。请不要使用它!首先,SelectionMode = Single 时不起作用。其次,使用剪贴板作为临时存储显然很疯狂。其他一些应用程序可能会干扰和替换对SetDataObjectGetText 的调用之间的内容。 @l33t 谢谢。你是对的,因为这是一个彻底的黑客攻击,对剪贴板的滥用,绝对不应该在生产代码中依赖。我并没有真正考虑其他应用程序干扰剪贴板的影响,但这是一个有效的担忧。显然有一个 WIN32 API 调用可以锁定剪贴板,但不会在这里命名,因为这会变得更糟,更糟糕的是,完全脱离了疯狂的轨道。尽管回想起来,这段代码对我的需求(原型 POC)有用,但我同意 l33t 的观点,即永远不应该实际使用这种 hack。 目前这似乎是最好的答案,因为.GetClipboardContent 使用单元格格式的值而不是单元格值,并且还可以处理其他答案没有的少数罕见边缘情况,例如包含 @987654334 的值@、"\t\r\n 或当前正在编辑的单元格。对于不想使用.GetClipboardContent 的任何人,我建议寻找处理上述分隔符和转义字符的解决方案。 添加dataGridView1.ClearSelection();最后【参考方案3】:
      Please check this code.its working fine  

          try
               
            //Build the CSV file data as a Comma separated string.
            string csv = string.Empty;

            //Add the Header row for CSV file.
            foreach (DataGridViewColumn column in dataGridView1.Columns)
            
                csv += column.HeaderText + ',';
            
            //Add new line.
            csv += "\r\n";

            //Adding the Rows

            foreach (DataGridViewRow row in dataGridView1.Rows)
            
                foreach (DataGridViewCell cell in row.Cells)
                
                    if (cell.Value != null)
                    
                        //Add the Data rows.
                        csv += cell.Value.ToString().TrimEnd(',').Replace(",", ";") + ',';
                    
                    // break;
                
                //Add new line.
                csv += "\r\n";
            

            //Exporting to CSV.
            string folderPath = "C:\\CSV\\";
            if (!Directory.Exists(folderPath))
            
                Directory.CreateDirectory(folderPath);
            
            File.WriteAllText(folderPath + "Invoice.csv", csv);
            MessageBox.Show("");
        
        catch
        
            MessageBox.Show("");
        

【讨论】:

【参考方案4】:

发现问题,编码没问题,但我有一个空单元格出现问题。

【讨论】:

!防御性编码!= 很好【参考方案5】:

您的代码几乎就在那里......但我做了以下更正,效果很好。谢谢你的帖子。

错误:

string[] output = new string[dgvLista_Apl_Geral.RowCount + 1];

更正:

string[] output = new string[DGV.RowCount + 1];

错误:

System.IO.File.WriteAllLines(filename, output, System.Text.Encoding.UTF8);

更正:

System.IO.File.WriteAllLines(sfd.FileName, output, System.Text.Encoding.UTF8);

【讨论】:

我已经在我的代码中更新了它。我有点懒,只是在这里复制粘贴(直接来自它使用的软件)。【参考方案6】:

“csvFileWriter.WriteLine(dataFromGrid);”行应该在右括号下面下移一行,否则你会得到很多重复的结果:

for (int i = 1; i <= countColumn; i++)

dataFromGrid = dataFromGrid + ',' + dataRowObject.Cells[i].Value.ToString();

csvFileWriter.WriteLine(dataFromGrid);

【讨论】:

【参考方案7】:

我认为这对您的 SaveToCSV 函数是正确的:(否则为 Null ...)

 for (int i = 0; i < columnCount; i++)

不是:

 for (int i = 1; (i - 1) < DGV.RowCount; i++)

【讨论】:

以上是关于将datagridview导出到csv文件的主要内容,如果未能解决你的问题,请参考以下文章

如何通过按钮单击将数据导出到 linq c# 中的 .csv 文件

请问谁有C#datagridview导出csv格式的excel的代码啊,发一下学习学习?

如何将datagridview中数据导出

vb.net 导出csv后数字格式问题

如何将数据框导出到数据湖中的 CSV 文件? [复制]

将 DataGridView 导出到文本文件,保持列对齐