DataTable filtern



  • Hallo.

    Meine Aufgabe ist es, aus SharePoint eine Liste in eine DataTable zu übertragen und diese zu filtern... gerne auch, dass vorher gefiltert wird, aber das ist nicht so wichtig.

    Das Laden der kompletten Liste klappt wunderbar mit folgendem Code:

    private System.Data.DataTable GetDataTableFromSharePointWithFilter(System.Uri Link, string ListName/*, System.Data.DataTable Filter*/)
            {
                System.Data.DataTable dt = null;
                System.Data.DataRow[] FilteredRows = null;
                #region Accessing share point
                Microsoft.SharePoint.Client.ClientContext cC = new Microsoft.SharePoint.Client.ClientContext(Link);
                cC.Credentials = System.Net.CredentialCache.DefaultCredentials;
                Microsoft.SharePoint.Client.List SPList = cC.Web.Lists.GetByTitle(ListName);
                Microsoft.SharePoint.Client.CamlQuery cQuery = new Microsoft.SharePoint.Client.CamlQuery();
                cQuery = Microsoft.SharePoint.Client.CamlQuery.CreateAllItemsQuery();
                Microsoft.SharePoint.Client.ListItemCollection LIC = SPList.GetItems(cQuery);
                cC.Load(LIC);
                cC.ExecuteQuery();
                #endregion
    
                dt = new DataTable();
    
                #region Create columns
                foreach (var Field in LIC[0].FieldValues)
                {
                    dt.Columns.Add(Field.Key);
                }
                #endregion
    
                #region Reading data
                foreach (Microsoft.SharePoint.Client.ListItem It in LIC)
                {
                    System.Data.DataRow row = dt.NewRow();
    
                    foreach (var Field in It.FieldValues)
                    {
                        row[Field.Key] = Field.Value;
                    }
                    dt.Rows.Add(row);
                }
                #endregion
    
                return dt;
            }
    

    Was ich jetzt tun kann ist, dass ich über die Select-Methode die Daten filtere:

    //Only rows with "Kostenstelle" in the column "Kontierungsobjekt" are contained
                string fltExp = "Kontierungsobjekt = 'Kostenstelle'";
                FilteredRows = dt.Select(fltExp);
    

    Auch das funktioniert wunderbar. Jetzt möchte ich allerdings, dass alle nicht
    gefilterten Rows gelöscht werden, dass in der zurückgegebenen DataTable nur noch
    die gefilterten Rows enthalten sind. Klar, ich kann zwei Schleifen ineinander verschachteln und das so lösen, aber dann wird der code sehr langsam, denn so eine SharePointListe kann schon ein paar Tausend Einträge haben und die Filterkriterien werden am Ende mehrdimensional, so dass der Aufwand immens wäre.

    Fällt Euch eine Lösung ein?
    Ich habe schon überlegt, eine neue DataTable zu erstellen und dann über DataTable.Rows.Add(FilteredRows) diese zu übergeben, aber das geht nicht, da
    die DataRows einer DataTable zugeordnet sind. Die Zuordnung DataRow.Table ist ReadOnly.

    Vielen Dank für alle Anregungen,
    Jan

    Ps.: Ich bin nicht flexibel mit der Nutzung der DataTable. Ich weiß selbst, dass es mit DataView einfacher wäre...



  • Gibt es einen Grund, dass die ausgefilterten Datensätze aus der DataTable zu löschen sind?

    Ansonsten, was spricht gegen die Verwendung einer DataView?

    DataTable myTable;
    // fill mytable....
    
    DataView myDataView = new DataView(myTable);
    myDataView.RowFilter = "Kontierungsobjekt = 'Kostenstelle'";
    
    return myDataView.ToTable();
    

    Und falls du wirklich kein DataView verwenden kannst, aus welchem Grund auch immer, dann geht vielleicht folgendes?

    DataRow[] filteredRows; 
    // ... filtering ...
    DataTable newTable = new DataTable();
    newDataTable.ImportRows(filteredRows);
    


  • Hi,

    ich schreibe hier eine Erweiterung für ein Programm mit dem Namen "Blue Prism" und dieses Programm benötigt als Rückgabewert eine DataTable mit den gefilterten Daten. Deshalb kann ich kein DataView nutzen und ich muss die Daten a.d. DataTable löschen.

    Ich habe das jetzt schon gelöst, indem ich einfach eine zweite DataTable erstelle und nur die relevanten Daten rüber kopiere... ist aber nicht sehr elegant der Weg.

    Es gibt ja die DataTable-Methode ToDataView().
    Wenn es dann im DataView eine Methode ToDataTable() gäbe, wäre ich glücklich und könnte mit dem DataView arbeiten und es am Ende dann in ein DataTable packen und zurück geben.

    Deine zweiten Weg werde ich mal probieren... und Euch über Erfolg / Miserfolg informieren.

    Danke erstmal bis hier her...



  • Hi inflames,

    vielen Dank für den Hinweis - das hat meinen Code auf jeden Fall schonmal gut vereinfacht. Anbei der Code der funktioniert, aber vllt. nicht so ganz elegant ist:

    private System.Data.DataTable GetDataTableFromSharePointWithFilter(System.Uri Link, string ListName, ref System.Data.DataTable Filter)
            {
                #region Local variables
                System.Data.DataTable dt = null, dtd = null;
                System.Data.DataRow[] FilteredRows = null;
                #endregion
    
                #region Accessing share point
                Microsoft.SharePoint.Client.ClientContext cC = new Microsoft.SharePoint.Client.ClientContext(Link);
                cC.Credentials = System.Net.CredentialCache.DefaultCredentials;
                Microsoft.SharePoint.Client.List SPList = cC.Web.Lists.GetByTitle(ListName);
                Microsoft.SharePoint.Client.CamlQuery cQuery = new Microsoft.SharePoint.Client.CamlQuery();
                cQuery = Microsoft.SharePoint.Client.CamlQuery.CreateAllItemsQuery();
                Microsoft.SharePoint.Client.ListItemCollection LIC = SPList.GetItems(cQuery);
                cC.Load(LIC);
                cC.ExecuteQuery();
                #endregion
    
                #region Create data tables
                dt = new DataTable();
                dtd = new DataTable();
                #endregion
    
                #region Create columns
                foreach (var Field in LIC[0].FieldValues)
                {
                    dt.Columns.Add(Field.Key);
                    dtd.Columns.Add(Field.Key);
                }
                #endregion
    
                #region Reading data
                foreach (Microsoft.SharePoint.Client.ListItem It in LIC)
                {
                    System.Data.DataRow row = dt.NewRow();
    
                    foreach (var Field in It.FieldValues)
                    {
                        row[Field.Key] = Field.Value;
                    }
                    dt.Rows.Add(row);
                }
                #endregion
    
                #region Create filter list item
                List<System.Collections.Generic.KeyValuePair<string, string>> KeyList = new List<KeyValuePair<string, string>>();
                foreach(DataColumn Col in Filter.Columns)
                {
                    System.Collections.Generic.KeyValuePair<string, string> KeyPair = new KeyValuePair<string, string>(Col.ColumnName, Filter.Rows[0][Col].ToString());
                    KeyList.Add(KeyPair);
                }
                #endregion
    
                #region Filtering data
                string fltExp = string.Empty;
                bool FirstLoop = true;
                foreach (System.Collections.Generic.KeyValuePair<string, string> KeyPair in KeyList)
                {
                    string Value = string.Empty;
    
                    if (FirstLoop)
                    {
                        FirstLoop = false;
                    }
                    else
                    {
                        fltExp += " AND ";
                    }
                    Value = KeyPair.Value;
                    if(Value.Substring(0,1) != "'") { Value = "'" + KeyPair.Value; }
                    if (Value.Substring(Value.Length - 1, 1) != "'") { Value += "'"; }
                    fltExp += KeyPair.Key + " = " + Value;
    
                }
    
                FilteredRows = dt.Select(fltExp);
                #endregion
    
                #region Copy data and clearing large stack
                foreach(DataRow dr in FilteredRows) { dtd.ImportRow(dr); }
                dt.Clear();
                #endregion
    
                return dtd;
            }
    


  • Nur so nebenbei... DataView hat eine Methode ToTable!



  • inflames2k schrieb:

    Gibt es einen Grund, dass die ausgefilterten Datensätze aus der DataTable zu löschen sind?

    Ansonsten, was spricht gegen die Verwendung einer DataView?

    DataTable myTable;
    // fill mytable....
    
    DataView myDataView = new DataView(myTable);
    myDataView.RowFilter = "Kontierungsobjekt = 'Kostenstelle'";
    
    return myDataView.ToTable();
    

    Und falls du wirklich kein DataView verwenden kannst, aus welchem Grund auch immer, dann geht vielleicht folgendes?

    DataRow[] filteredRows; 
    // ... filtering ...
    DataTable newTable = new DataTable();
    newDataTable.ImportRows(filteredRows);
    

    Super, das ist ja mal wirklich die einfachste Variante. Vielen vielen Dank.
    👍 👍 👍



  • Ich habe jetzt den Filter erstellt.

    string FilterExpression = "(Spalte A = 'Kriterium A' OR Spalte A = 'Kriterium B') AND Spalte B = 'Kriterium C'"
    DataView dv = new DataView(myTable)
    dv.RowFilter = FilterExpression;
    return dv.ToTable();
    

    Funktioniert erstmal super, vielen Dank. Jetzt noch eine Frage: Wie kann ich als Kriterium "irgendeine Zahl", "irgendeine Zeichenfolge" angeben?

    Und noch eine Frage habe ich:
    Folgender Audruck funtioniert:

    string filterExp = "Status = 'Active'";
    

    Folgender Ausdruck funktioniert nicht:

    string filterExp = "Aktueller-Status = 'Active'"; //Fehler wegen dem '-'
    

    Wie kann man das implementieren?

    Sorry für die vielen Fragen, aber:
    a, es ist keinem geholfen, wenn ich daraus hundert Posts mache und
    b, jeder, der das googelt wird sehen, dass es zu diesen spezifischen Problemen nicht viel Hilfe gibt.

    Vielen Dank,
    Jan

    Ps.: Das hier funktioniert definitiv NICHT:
    http://stackoverflow.com/questions/34628778/unable-to-have-dash-in-dataview-filter-c-sharp


Log in to reply