Entwickler-Ecke

WinForms - DataGridView zu Excel geht nicht


tomycat - Fr 02.09.16 12:45
Titel: DataGridView zu Excel geht nicht
hallo,
Button Inhalt:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
{
                // Creating a Excel object. 
                Microsoft.Office.Interop.Excel._Application excel = new Microsoft.Office.Interop.Excel.Application();
                Microsoft.Office.Interop.Excel._Workbook workbook = excel.Workbooks.Add(Type.Missing);
                Microsoft.Office.Interop.Excel._Worksheet worksheet = null;

                try
                {

                    worksheet = workbook.ActiveSheet;

                    worksheet.Name = "ExportedFromDatGrid";

                    int cellRowIndex = 1;
                    int cellColumnIndex = 1;

                    //Loop through each row and read value from each column. 
                    for (int i = 0; i < dataGridView6.Rows.Count - 1; i++)
                    {
                        for (int j = 0; j < dataGridView6.Columns.Count; j++)
                        {
                            // Excel index starts from 1,1. As first Row would have the Column headers, adding a condition check. 
                            if (cellRowIndex == 1)
                            {
                                worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView6.Columns[j].HeaderText;
                            }
                            else
                            {
                                worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView6.Rows[i].Cells[j].Value.ToString();
                            }
                            cellColumnIndex++;
                        }
                        cellColumnIndex = 1;
                        cellRowIndex++;
                    }

                    //Getting the location and file name of the excel to save from user. 
                    SaveFileDialog saveDialog = new SaveFileDialog();
                    saveDialog.Filter = "Excel files (*.xlsx)|*.xlsx|All files (*.*)|*.*";
                    saveDialog.FilterIndex = 2;

                    if (saveDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        workbook.SaveAs(saveDialog.FileName);
                        MessageBox.Show("Export Successful");
                    }
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    excel.Quit();
                    workbook = null;
                    excel = null;
                }

            }


Ich fülle einfach die Tabelle dataGridView6 aus,die hat 3 Spalten. Ein klick auf den Button siehe oben und es kommt:
eine Messagebox mit :
der objektverweis wurde nicht auf eine objektinstanz festgelegt

Meine Vorlage:
https://code.msdn.microsoft.com/office/How-to-Export-DataGridView-62f1f8ff


Th69 - Fr 02.09.16 13:36

Hallo,

eine einfache NullReferenceException solltest du mittels dem Debugger selber finden können.


tomycat - Fr 02.09.16 19:09

Ich habe das Problem eingegenzt.
Sobald eine leere Zelle im datagridview vorkommt, kommt die Fehlermeldung.
Meine Idee war, ich prüfe immer ob die Zelle leer oder NULL ist. Leider kommmt trotzdem die Fehlermeldung.

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
  for (int i = 0; i < dataGridView6.Rows.Count - 1; i++)  //Zeile
                    {

                        for (int j = 0; j < dataGridView6.Columns.Count; j++) //Spalte
                        {
                        //      MessageBox.Show(dataGridView6.Rows.Count.ToString());
                              MessageBox.Show(dataGridView6.Rows[i].Cells[j].Value.ToString());

        
                        if (String.IsNullOrEmpty(dataGridView6.Rows[i].Cells[j].Value.ToString()))
                        {
                            worksheet.Cells[cellRowIndex, cellColumnIndex] = " ";
                        }
                        else
                        {
                            worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView6.Rows[i].Cells[j].Value.ToString();
                        }
                    
                            cellColumnIndex++;
                        }
                        cellColumnIndex = 1;
                        cellRowIndex++;
                    }


Th69 - Sa 03.09.16 07:34

Die Abfrage erfolgt bei dir so zu spät, da erst der Parameter dataGridView6.Rows[i].Cells[j].Value evaluiert wird und darauf dann die ToString-Methode angewendet wird - und diese führt eben bei einem null-Objekt zu der NullReferenceException.

Das ist einer der Gründe warum ich selber die verschachtelten Zugriffe innerhalb einer Zeile versuche zu vermeiden.
Besser dann auf mehrere Zeilen (bzw. Variablen) aufteilen, um explizite Abfragen durchführen zu können. Oder aber, wie auch in deinem Fall, um nicht mehrmals den Gesamtausdruck innerhalb der Schleife berechnen zu lassen!

Trifft zwar jetzt nicht genau diesen Fall (da du ja selber nicht die Klasse DataGridView erstellt hast ;-)), es gibt das Gesetz von Demeter (Law of Demeter) [https://de.wikipedia.org/wiki/Gesetz_von_Demeter] als Software Design Pattern.


tomycat - Sa 03.09.16 14:56

thx,
ich habe jetzt den Code so angepasst, dass immmer ein Zeichen drin ist.

2 Fragen sind entstanden:

worksheet.Cells[123123] <-------- Diese Zelle soll die doppelte Berite in Excel bekommen, wie mache ich das?

Wenn ich die Excel Datei speichere und später öffne, dann soll Sie beim drucken NUR 1 cm Rand haben.

Ich bin für jeden Tipp dankbar.

Moderiert von user profile iconTh69: C#-Tags hinzugefügt


tomycat - Sa 03.09.16 20:22

...update

worksheet.Columns[1].AutoFit(); <<------- orientiert sich an der Zelle die am längsten ist. Die Zeilelänge muss aber Fix sein. Aber wie?

Moderiert von user profile iconTh69: C#-Tags hinzugefügt


Delete - Sa 03.09.16 21:16

- Nachträglich durch die Entwickler-Ecke gelöscht -


tomycat - So 11.09.16 13:31

thx,
hat super geklappt.

Hat jemand noch einen Ansatz/Idee für den Seitenabstand? Sobald ich die Exceldatei öffne, soll der linke Rand 0,5 cm sein.


Ralf Jansen - So 11.09.16 15:41

Zitat:
Sobald ich die Exceldatei öffne, soll der linke Rand 0,5 cm sein.

Welchen linken Rand hat man den beim öffnen? Oder sprichst du vom späteren drucken irgendwann nach dem öffnen? Dann wohl

C#-Quelltext
1:
worksheet.PageSetup.LeftMargin = Application.CentimetersToPoints(0.5);                    

Achtung ich habe die Info einfach der Dokumentation entnommen (die ist nicht versteckt) und nicht ausprobiert.