Laden...

Setzen eines DataGridViewAutoFilter zeigt zwar die Pfeile, aber ein Klick darauf führt zu Exception

Erstellt von Edzio vor 9 Jahren Letzter Beitrag vor 9 Jahren 4.523 Views
E
Edzio Themenstarter:in
68 Beiträge seit 2013
vor 9 Jahren
Setzen eines DataGridViewAutoFilter zeigt zwar die Pfeile, aber ein Klick darauf führt zu Exception

Hallo zusammen,

ich habe eine Windowsform [Arbeitsmaske]
in dieser Form habe ich ein DataGridView [dGvexcel]

in meiner Funktion

Form1_Load

rufe ich meine Funktion

dGvexcel_initialisieren();

auf
in dieser setze ich Parameter wie:

 dGvexcel.ColumnCount = 10;
            dGvexcel.ColumnHeadersVisible = true;

            // Set the column header style.
            DataGridViewCellStyle columnHeaderStyle = new DataGridViewCellStyle();

            columnHeaderStyle.BackColor = Color.Beige;
            columnHeaderStyle.Font = new System.Drawing.Font("Arial", 10, FontStyle.Bold);
            dGvexcel.ColumnHeadersDefaultCellStyle = columnHeaderStyle;
            
            // Spalten hinzufügen
            dGvexcel.Columns[0].Name = "Projektnummer";
            dGvexcel.Columns[1].Name = "Auftrag";
            dGvexcel.Columns[2].Name = "Priorität";
            dGvexcel.Columns[3].Name = "Team";
            dGvexcel.Columns[4].Name = "Zusatz";

anschließend rufe ich meine Funktion

dgv_fuellen();

auf
in dieser füttere ich das DGV mit Daten aus einer Excelliste. (das funktioniert auch perfekt)

Nun habe ich das DataGridViewAutoFilter entdeckt und mir hierzu auch die MS Seite angeschaut,
allerdings blicke ich es gerade nicht, wo ich was einsetzen soll.

Wenn ich diese Funktion

foreach (DataGridViewColumn col in dGvexcel.Columns)
            {
               col.HeaderCell = new DataGridViewAutoFilterColumnHeaderCell(col.HeaderCell);
            }

in meine

dGvexel_initialisieren();

setze
sehe ich zwar die dropdown Pfeile in jeder Spalte, aber sobald ich draufklicke kommt ein Fehler mit den Funktionen DataSource und DataBinding,
bei denen ich nicht blicke, wo ich die reinsetzen muss...

Vielleicht kann mir einer weiterhelfen.

Danke im Voraus.
Gruß

K
89 Beiträge seit 2013
vor 9 Jahren

Welche Fehlermeldung erscheint denn?

E
Edzio Themenstarter:in
68 Beiträge seit 2013
vor 9 Jahren

in dem Bild sieht man die Fehlermeldung
und wie die Dropdownpfeile angezeigt werden (so wie ich mir das vorstelle)

1.696 Beiträge seit 2006
vor 9 Jahren

Hallo,

schaue dir bitte den Part Dependencies hier an: Building a Drop-Down Filter List for a DataGridView Column Header Cell

Grüße

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

E
Edzio Themenstarter:in
68 Beiträge seit 2013
vor 9 Jahren

ja da war ich schon drauf,
und ich blick gerade hauptsächlich die Funktion

// Add this code to the form Load event handler.
  dataGridView1.DataSource = customersBindingSource;

umgeschrieben hab ich des dann so:

dGvexcel.DataSource = customersBindingSource;

aber wo hole ich mein bindingsource etc.?

da häng ich gerade bzw. blicke es nicht... 😦

1.696 Beiträge seit 2006
vor 9 Jahren

Hallo,

du musst ein BindingSource Objekt erzeugen und dein Excel als BindingSource.DataSource, damit kannst du dein DGV zuweisen.

Schaue dir das Beispiel an BindingSource-Klasse (am Ende der Seite)

Grüße

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

E
Edzio Themenstarter:in
68 Beiträge seit 2013
vor 9 Jahren

heißt des, dass ich meine separate Funktion

dgv_fuelle()

wegfallen lassen kann?
(ausschnitt aus der Funktion)

public void dgv_fuellen()
        {

            dgverledigt = 0;
            dgvzeile = 6;
            do
            {
                Microsoft.Office.Interop.Excel.Application dgvxlapp = new Microsoft.Office.Interop.Excel.Application();
                dgvxlapp.Visible = false;
                Workbook dgvwb;
                object missing = System.Reflection.Missing.Value;

                try
                {

                    System.Threading.Thread.Sleep(300); //Kurze Wartetimer

                    dgvwb = dgvxlapp.Workbooks.Open(
                                                verbindung_zu_definitionen.getPfad(),
                                                ExcelKonstanten.UpdateLinks.DontUpdate,
                                                ExcelKonstanten.ReadWrite,
                                                ExcelKonstanten.Format.Nothing,
                                                "", // Passwort
                                                "", // WriteResPasswort
                                                ExcelKonstanten.IgnoreReadOnlyRecommended,
                                                Microsoft.Office.Interop.Excel.XlPlatform.xlWindows,
                                                "", // Trennzeichen
                                                ExcelKonstanten.Editable,
                                                ExcelKonstanten.Notify,
                                                ExcelKonstanten.Converter.Default,
                                                ExcelKonstanten.DontAddToMru,
                                                ExcelKonstanten.Local,
                                                ExcelKonstanten.CorruptLoad.NormalLoad
                                              );

                    // Arbeitsblätter lesen
                    Sheets sheets = dgvwb.Worksheets;
                    // ein Arbeitsblatt auswählen…
                    Worksheet dgvws = (Worksheet)sheets.get_Item("CM");
                    //erste leere Zeile suchen
                    do
                    {
                        object dgvwertzelle = dgvxlapp.Cells[dgvzeile, spalte_excel_erledigt].Value2;                      //erldigt feld
                        string wert_projektnummer = dgvxlapp.Cells[dgvzeile, spalte_excel_Projektnummer].Value.ToString();       //Typumwandlung, da sonst Fehler beim sortieren 
                        object wert_auftrag = dgvxlapp.Cells[dgvzeile, spalte_excel_Auftrag].Value2;
                        object wert_prio = dgvxlapp.Cells[dgvzeile, spalte_excel_Prio].Value2;
                        object wert_team = dgvxlapp.Cells[dgvzeile, spalte_excel_Team].Value2;
                        object wert_zusatz = dgvxlapp.Cells[dgvzeile, spalte_excel_Zusatz].Value2;
                        object wert_teilenummer = dgvxlapp.Cells[dgvzeile, spalte_excel_TnAnlage].Value2;
                        object wert_eingelastet = dgvxlapp.Cells[dgvzeile, spalte_excel_Eingelastet].Value2;                   //Fehler mit Datum
                        object wert_zieltermin = dgvxlapp.Cells[dgvzeile, spalte_excel_Zieltermin].Value2;
                        object wert_konstrukteur = dgvxlapp.Cells[dgvzeile, spalte_excel_Konstrukteur].Value2;
                        object wert_projektleiter = dgvxlapp.Cells[dgvzeile, spalte_excel_Projektleiter].Value2;

                        //wert_zieltermin = wert_zieltermin.ToString();//typeof(DateTime);
                        wert_eingelastet = Convert.ToDateTime(wert_eingelastet);
                        wert_zieltermin = Convert.ToDateTime(wert_zieltermin);

                        if (dgvwertzelle != null)
                        {
                            dgverledigt = dgverledigt + 1;
                        }
                        else
                        {
                            dGvexcel.Rows.Add(wert_projektnummer,wert_auftrag, wert_prio, wert_team,wert_zusatz,wert_teilenummer, wert_eingelastet,wert_zieltermin, wert_konstrukteur, wert_projektleiter);
                        }
                        lbl_zeile.Text = Convert.ToString(dgvzeile - dgverledigt - 5);
                        dgvzeile = dgvzeile + 1;
                        binding_excel.DataSource = dgvws;

                    } while (dgvws.Cells[dgvzeile, 1].Value != null);

                    
                    dgvwb.Close(true, missing, false);       //Workbook schließen & speichern
                    dgvxlapp.Quit();                         //Excel beenden
                    System.Threading.Thread.Sleep(300);   //Kurze Wartetimer

                    dgvexcelfehler = 0;

                }

In meiner Form_load habe ich nun ein

 binding_excel = new BindingSource();

in dem Excelaufruf habe ich das binding drin,
aber irgendwie kommt mir das falsch vor.... 😦

1.696 Beiträge seit 2006
vor 9 Jahren

Hallo,

zuviel Code ... ich lese kein Codes, die mehr als 20 Zeilen beinhalten, da keine Zeit und zu faul 😜

Excel kannst du über OLEDB direkt auslesen, ohne Excel zu öffnen, damit ise es einfacher zu arbeiten und schneller


System.Data.OleDb.OleDbConnection oledbConnection;
System.Data.DataSet dataSet;
System.Data.OleDb.OleDbDataAdapter dataAdapter;
oledbConnection = new System.Data.OleDb.OleDbConnection(@"provider=Microsoft.Jet.OLEDB.4.0;Data Source='c:\test.xls';Extended Properties=Excel 8.0;");
dataAdapter = new System.Data.OleDb.OleDbDataAdapter("select * from [Sheet1$]", oledbConnection);
dataAdapter.TableMappings.Add("Table", "test");
dataSet = new System.Data.DataSet();
dataAdapter.Fill(dataSet);
// z.B. dann
bindingSource.DataSource = dataSet.Tables[0];

Grüße

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

E
Edzio Themenstarter:in
68 Beiträge seit 2013
vor 9 Jahren

😃
kenn ich irgendwoher (bin auch lesefaul)

ok des mit dem OLEDB kenn ich gar nicht, jetzt will ich erst versuchen das auf die herkömmliche art zu machen
hier der Code in Kurzform 😃

-excel öffnen
-excel zeile für zeile in Variable einlesen
-Variable Zeile für Zeile ins dGvexcel mit .Rows.Add

und wie kann ich jetzt diese Daten zuordnen?

binding_excel.DataSource = ????;

oder brauch ich das nicht mehr, da ja eigtentlich mein DGV gefüllt ist?

1.696 Beiträge seit 2006
vor 9 Jahren

Hallo,

Excel Applikation öffnet man nur, wenn man ein Excel Datei direkt manipulieren möchte, nicht aber wenn man nur Daten ausliest, das ist nicht performant und falsch. Mach lieber mit OLEDB.

Wenn du aber nicht anders willst, kannst du die Exceldaten in einer DataTable eines DataSet ablegen und dann als DataSource deines BindingSource Objekt verwenden. That's it.

Grüße

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

E
Edzio Themenstarter:in
68 Beiträge seit 2013
vor 9 Jahren

ja gut in der Funktion les ich nur, aber in einem anderen Teil des programms schreibe ich auch oder ändere die formatierung.

mh ok
dann versuch ich das mal irgendwie zu handhaben,
von dem DataTable und DataSet hab ich auch noch nie was gehört 🤔
(ja bin noch blutiger Anfänger 🙁 )

danke dir aber schon mal ...

1.696 Beiträge seit 2006
vor 9 Jahren

Hallo,

bitte lesen Verwenden des DataSet Objekts (und vorsorglich [Hinweis] Wie poste ich richtig? Punkt 1.1.1

Grüße

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

E
Edzio Themenstarter:in
68 Beiträge seit 2013
vor 9 Jahren

Hallo,

also ich komm nicht weiter mit den ganzen bindings und sources.

In meine Form1_Load habe ich versucht die BindingDinger einzufügen:


....
            //Versuch Excel in Form mit DataGridView

                binding_excel = new BindingSource();

                dGvexcel_initialisieren();
                dgv_fuellen();

                
                binding_excel.DataSource = GetExcelDataSet(verbindung_zu_definitionen.getPfad(), true);
                dGvexcel.DataSource = binding_excel;

        }

In die Funktion

dGvexcel_initialisieren();

habe ich den Handler eingebaut:

            dGvexcel.BindingContextChanged += new EventHandler(dGvexcel_BindingContextChanged);

mit diesem sollen ja die DropdownButtons in mein GridView Header reinkommen.

private void dGvexcel_BindingContextChanged(object sender, EventArgs e)
        {
            if (dGvexcel.DataSource == null) return;

            foreach (DataGridViewColumn col in dGvexcel.Columns)
            {
                col.HeaderCell = new
                    DataGridViewAutoFilterColumnHeaderCell(col.HeaderCell);
            }
            dGvexcel.AutoResizeColumns();
        }

Meine GetDataSet Methode habe ich versucht nach deinem Tip (vbprogger) mit dem OLEDB

die sieht dann so aus:

 public static DataSet GetExcelDataSet(string excelFile, bool hasHeaders)
        {
            var hdr = hasHeaders ? "Yes" : "No";
            string strConn;
            if (excelFile.Substring(excelFile.LastIndexOf('.')).ToLower() == ".xlsx")
                strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFile +
                          ";Extended Properties=\"Excel 12.0 Macro;HDR=" + hdr + ";IMEX=1\"";
            else
                strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + excelFile + ";Extended Properties=\"Excel 8.0;HDR=" + hdr +
                          ";IMEX=1\"";

            var output = new DataSet();

            using (var conn = new OleDbConnection(strConn))
            {
                conn.Open();

                var schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });

                if (schemaTable != null)
                    foreach (DataRow schemaRow in schemaTable.Rows)
                    {
                        var tableName = schemaRow["CM"].ToString();

                        if (tableName.LastIndexOf("'", StringComparison.Ordinal) < tableName.Length - 1)
                            continue;
                        try
                        {
                            var cmd = new OleDbCommand("SELECT * FROM [" + tableName + "]", conn) { CommandType = CommandType.Text };
                            var outputTable = new System.Data.DataTable(tableName);
                            new OleDbDataAdapter(cmd).Fill(outputTable);
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(ex.Message + "Sheet:" + tableName + ".File:" + excelFile, ex);
                        }
                    }

                conn.Close();
            }
            return output;
        }

Irgendwie will das alles nicht so wie es sein soll.
Und so einfach wie es in den Foren steht ist das auch nicht...

vlt. kann mir einer noch n Tip geben ...

Danke.

Gruß

4.931 Beiträge seit 2008
vor 9 Jahren

Es fehlt noch


output.Tables.Add(outputTable);

in der GetExcelDataSet-Methode.

Du solltest aber passende Fehlerbeschreibungen liefern und nicht "Irgendwie will das alles nicht so wie es sein soll."
Und den Umgang mit dem Debugger solltest du auch lernen, dann hättest du gesehen, daß das DataSet nirgends gefüllt wird: [Artikel] Debugger: Wie verwende ich den von Visual Studio?

E
Edzio Themenstarter:in
68 Beiträge seit 2013
vor 9 Jahren

ok danke TH69
habe es eingefügt, nun ist mir aber aufgefallen,
dass er in der Funktion


        public static DataSet GetExcelDataSet(string excelFile, bool hasHeaders)

nach dem for schleifen einstieg

foreach (DataRow schemaRow in schemaTable.Rows)
                    {
                        var tableName = schemaRow["CM"].ToString();

gar nicht mehr weiter macht, sondern mein UI aufruft und dann kann ich es normal bedienen (wie davor ohne die AutoGrid DropDownbuttons im Header des DGV´s)
Ich geh dem mal auf den Grund und melde mich wieder, falls ich nicht weiter komme.

Ausser es sieht ein Profi auf anhieb 😃

Gruß

E
Edzio Themenstarter:in
68 Beiträge seit 2013
vor 9 Jahren

hallo zusammen,

ich habe es nun geschafft, dass sich das DGV mit dem OLEDB füllen läßt und der Filter geht nun auch.
Meine Füllen Funktion:

        public void dgv_fuellen()
        {
            
            try
            {
                var excelFile = verbindung_zu_definitionen.getPfad();
                var hdr = "Yes";                    //hasHeaders ? "Yes" : "No";
                var binding_excel = new BindingSource();
                string connectionString;
                //Prüfen welches Excel OLEDB geladen werden soll
                if (excelFile.Substring(excelFile.LastIndexOf('.')).ToLower() == ".xlsx")
                    connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFile +
                                ";Extended Properties=\"Excel 12.0 Macro;HDR=" + hdr + ";IMEX=1\"";
                else
                    connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + excelFile + ";Extended Properties=\"Excel 8.0;HDR=" + hdr +
                                    ";IMEX=1\"";

                //Alle Spalten von Tabelle1 lesen
                var adapter = new OleDbDataAdapter("SELECT * FROM [CM$]", connectionString);
                //Verbindung zur Tabelle aufbauen
                var ds = new DataSet();
                //Zu lesende Tabelle angeben
                adapter.Fill(ds, "CM");
                //Tabelle auswählen
                dt_filter = ds.Tables["CM"];
                //Binden da DataGridViewAutoFilter nur mit einem Binding arbeiten
                binding_excel.DataSource = dt_filter;
                //Mit DGV verknüpfen
                dGvexcel.DataSource = binding_excel;//dt_filter;        //Daten mit dem DGV verknüpfen
            }
            catch (Exception fehler_fuellen)
            {
                MessageBox.Show("Die Daten konnten nicht geladen werden, folgendes Problem trat auf:\n" + fehler_fuellen + "\n sollte das Problem weiterhin bestehen, \n" +
                                "wenden sie sich an:\n fheb@de.festo.com", "Datenfehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            //nicht benötigte Spalten ausblenden
            dGvexcel.Columns["Angebot"].Visible = false;
            dGvexcel.Columns["Auftrags Nr"].Visible = false;
            dGvexcel.Columns["erledigt"].Visible = false;
            dGvexcel.Columns["Beschreibung"].Visible = false;

            dGvexcel.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

        }//Ende DGV füllen neu

Teile aus meiner Form_Load Funktion:

            //Versuch Excel in Form mit DataGridView und DGVAutoFilter
                dGvexcel.BindingContextChanged += new EventHandler(dGvexcel_BindingContextChanged);

                dGvexcel_initialisieren();
                dgv_fuellen();

Die BindingContextChange Funktion in meine Hauptklasse Form1:


        private void dGvexcel_BindingContextChanged(object sender, EventArgs e)
        {
            if (dGvexcel.DataSource == null) return;

            foreach (DataGridViewColumn col in dGvexcel.Columns)
            {
                col.HeaderCell = new
                    DataGridViewAutoFilterColumnHeaderCell(col.HeaderCell);
            }
            dGvexcel.AutoResizeColumns();
        }

und ganz wichtig war anscheinend die Rückstzefunktion meines DGV´s:

        public void dgvclear()
        {
            var dgvtable = (dGvexcel.DataSource as BindingSource).DataSource as System.Data.DataTable;
            dgvtable.Rows.Clear();
            
            
        }

Jetzt will ich noch versuchen die Spaltenbreite an mein DGV anzupassen, irgendwie geht das mit dem

dGvexcel.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

nicht richtig.
Ah und den Header farbig markieren wenn in dieser Spalte gefiltert wurde...

Vielleicht weiß einer ja noch Rat, ansonsten versuch ich mein Glück und melde mich wieder 😄

Danke nochmal an alle.

Gruß

E
Edzio Themenstarter:in
68 Beiträge seit 2013
vor 9 Jahren

ok ich habe es hinbekommen mit der spaltenaufteilung,
ich hab in meiner dGvexcel_initialisieren() Methode die Funktion:

 dGvexcel.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;

eingebaut, da mir gesagt wurde, dass "AutoSizeColumns" sich nicht auf die vorgegebene Breite meines DGV´s bezeieht, sondern sich auf den Inhalt der Spalten bezieht und jede Spalte so breit wie der längste Eintrag in der Spalte macht.