2012-03-30 6 views
15

Я работаю над приложением, которое будет экспортировать мой DataGridView под названием scannerDataGridView в файл csv.Экспорт datagridview в файл csv

Нашел код примера, чтобы сделать это, но не может заставить его работать. Btw my datagrid не привязан к источнику данных.

Когда я пытаюсь использовать Streamwriter только для записи заголовков столбцов, все идет хорошо, но когда я пытаюсь экспортировать весь файл данных, включая данные, я получаю exeption trhown.

System.NullReferenceException: Object reference not set to an instance of an object. at Scanmonitor.Form1.button1_Click(Object sender, EventArgs 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()); 
    } 
+0

На какой линии выбрасывается исключение? Также вы можете использовать foreach для прохождения столбцов каждой строки: foreach (ячейка DataGridViewCell в dataRowObject.Cells), если только не существует конкретной причины, по которой вы предпочитаете нормальный цикл? – Dan

+0

Также, возможно, проверьте, что scannerDataGridView.Rows.Count> 0 – Dan

+0

Привет, PandaNL, я удалил свой ответ. Я по-прежнему считаю, что строка offsending должна читать 'object value = dataRowObject.Cells [i] .Value; dataFromGrid = dataFromGrid + ',' + (значение? String.Empty) .ToString()); ' –

ответ

2

Нашли проблему, кодирование было хорошо, но я имел пустую ячейку, которая дала эту проблему.

+6

! кодирование защищено! = fine –

1

Линия «csvFileWriter.WriteLine (dataFromGrid)»; должны быть перемещены вниз на одну строку ниже закрывающей скобки, иначе вы получите много повторяющихся результатов:

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

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 будет правильно преобразовать в пустую строку.

+1

Я получал сообщение об ошибке с исходным кодом и должен был сделать одно редактирование: headers.Select (column => "\" "+ column.HeaderText +" \ ""); .Выберите (column => "\" "+ column.HeaderText +" \ ""). ToArray(); –

+0

Я нашел то же, что и BH (и представил редактирование). В стороне, это отличный ответ! –

+0

Кроме того, у меня была (отдельная) проблема, когда в первом столбце использовалось специальное свойство «RowIndex», которое (как ни странно) не задавало значение ячейки. Исправлено путем захвата «cell.FormattedValue» вместо ячейки. Значение для первого столбца. sb.AppendLine (\t string.join (" " \t cells.Select (ячейка => \t \t "\"" + (cell.ColumnIndex == 0 cell.FormattedValue: cell.Value) +" \ "" \t \t \t \t) .ToArray())); –

13

Незначительная функция DataGridView - это возможность программно выбирать некоторые или все данные DataGridCells и отправлять их на номер DataObject, используя метод DataGridView.GetClipboardContent(). В чем преимущество этого тогда?

A DataObject не просто хранит объект, а представляет собой представление этого объекта в различных форматах. Вот как Clipboard способен работать над своей магией; он имеет различные форматы, и различные элементы управления/классы могут указать формат, который они хотят принять. В этом случае DataGridView будет сохранять выбранные ячейки в DataObject как текстовый формат с разделителями табуляции, формат CSV или как HTML (*).

Содержимое объекта DataObject можно получить, вызвав методы или DataObject.GetText() и указав предопределенное перечисление формата данных. В этом случае мы хотим, чтобы формат был TextDataFormat.CommaSeparatedValue для CSV, тогда мы можем просто записать этот результат в файл с использованием класса System.IO.File.

(*) Собственно, то, что он возвращает, не является, строго говоря, HTML. Этот формат также будет содержать заголовок данных, которого вы не ожидали. Хотя заголовок содержит исходную позицию HTML, я просто отбрасываю что-либо выше тега HTML, например myString.Substring(IndexOf("<HTML>"));.

соблюдать следующий код:

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

Теперь, не в том, что лучше? Зачем изобретать колесо?

Надеется, что это помогает ...

+1

Я видел это уродливое решение, циркулирующее в сети. Пожалуйста, не используйте его! Прежде всего, это не работает, когда 'SelectionMode = Single'. Во-вторых, использование буфера обмена в качестве временного хранилища является сумасшедшим. Некоторые другие приложения могут помешать и заменить контент между вызовами на «SetDataObject» и «GetText». – l33t

+1

@ l33t Спасибо.Вы правы, так как это полный хак, злоупотребление буфером обмена, и в производственном коде не следует полагаться. Я действительно не рассматривал влияние других приложений на вмешательство в буфер обмена, но это является серьезной проблемой. По-видимому, есть вызов WIN32 API, который может блокировать буфер обмена, но не назовите его здесь, потому что это будет происходить от плохих, а тем более, до безумного отказа от рельсов. Хотя этот код работал для меня для моих нужд (прототипирование POC) ретроспективно, я согласен с этим здесь, что этот хак никогда не должен использоваться. –

+1

с использованием буфера обмена не требуется http://stackoverflow.com/a/40743651/1383168 – Slai

7

Я знаю, что это, вероятно, уже мертво, но я сделал простой код, который создает CSV на основе объекта DataGridView, и спрашивает, где вы хотите, чтобы сохранить его.

Его довольно прямолинейный, просто вставьте функцию и используйте ее. У этого уже есть некоторая основная обработка исключений, поэтому довольно безопасно использовать. наслаждаться.

private void SaveToCSV(DataGridView DGV) 
    { 
     string filename = ""; 
     SaveFileDialog sfd = new SaveFileDialog(); 
     sfd.Filter = "CSV (*.csv)|*.csv"; 
     sfd.FileName = "Output.csv"; 
     if (sfd.ShowDialog() == DialogResult.OK) 
     { 
      MessageBox.Show("Data will be exported and you will be notified when it is ready."); 
      if (File.Exists(filename)) 
      { 
       try 
       { 
        File.Delete(filename); 
       } 
       catch (IOException ex) 
       { 
        MessageBox.Show("It wasn't possible to write the data to the disk." + ex.Message); 
       } 
      } 
      int columnCount = DGV.ColumnCount; 
      string columnNames = ""; 
      string[] output = new string[DGV.RowCount + 1]; 
      for (int i = 0; i < columnCount; i++) 
      { 
       columnNames += DGV.Columns[i].Name.ToString() + ","; 
      } 
      output[0] += columnNames; 
      for (int i = 1; (i - 1) < DGV.RowCount; i++) 
      { 
       for (int j = 0; j < columnCount; j++) 
       { 
        output[i] += DGV.Rows[i - 1].Cells[j].Value.ToString() + ","; 
       } 
      } 
      System.IO.File.WriteAllLines(sfd.FileName, output, System.Text.Encoding.UTF8); 
      MessageBox.Show("Your file was generated and its ready for use."); 
     } 
    } 

EDIT: изменено ';' to ',' поскольку мы говорим о файлах CSV.

+0

Сбой, когда значение в некоторой ячейке в DataGrid равно null. – RRM

2

Ваш код был почти там ... Но я сделал следующие исправления, и он отлично работает. Спасибо за сообщение.

Ошибка:

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); 
+0

Я обновил его в своем коде. бит ленивый и просто скопировал его здесь (прямо из программного обеспечения, которое он использовал). –

0

Я думаю, что это правильно для вашей функции SaveToCSV: (в противном случае Null ...)

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

Не:

for (int i = 1; (i - 1) < DGV.RowCount; i++) 
1
 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(""); 
     } 
Смежные вопросы