Filter, Sort and Default Value all in one LINQ

Here is a sample data from a large data table that consists of about 25-30 columns. The columns of interest are shown below.
image

I need to filter out the blank rows and then sort this data table by Column headers A, B and then C. Notice that one of cells in “C” is highlighted in yellow. There is a missing value in there that causes my sort to fail, when I use the following command.

Assign dt = (From x In dt.AsEnumerable Order By cint(x(“A”).ToString), cint(x(“B”).ToString), cint(x(“C”).ToString)).CopyToDataTable

Error: Assign: Conversion from string “” to type ‘Integer’ is not valid.

When the blank cell is replaced with a value of 2 the results are displayed as follows:

image

Any help overcoming this issue? I do not want to loop through the table but would prefer to use LINQ and do it all in one step, if that is possible.

1 Like

Hi @csathys

Try this:

Assign dt = (From x In dt.AsEnumerable
            Where Not String.IsNullOrEmpty(x("A").ToString) And
                  Not String.IsNullOrEmpty(x("B").ToString) And
                  Not String.IsNullOrEmpty(x("C").ToString)
            Order By CInt(x("A").ToString), CInt(x("B").ToString), 
                If(String.IsNullOrEmpty(x("C").ToString), 0, CInt(x("C").ToString))
            Select x).CopyToDataTable

Explanation:

  1. From x In dt.AsEnumerable: This part of the query converts the data table (dt) into an enumerable sequence of rows, and we assign each row to the variable x.
  2. Where Not String.IsNullOrEmpty(x("A").ToString) And Not String.IsNullOrEmpty(x("B").ToString) And Not String.IsNullOrEmpty(x("C").ToString): This is a filtering condition. It ensures that only rows where columns “A,” “B,” and “C” are not blank (empty or null) are considered for sorting.
  3. Order By CInt(x("A").ToString), CInt(x("B").ToString), If(String.IsNullOrEmpty(x("C").ToString), 0, CInt(x("C").ToString)): This is the sorting part. It orders the selected rows based on the values in columns “A,” “B,” and “C.” For column “C,” it checks if the value is empty. If it’s empty, it assigns a value of 0 to make the sorting process valid.
  4. Select x: This part of the query selects the rows that satisfy the filtering condition and arranges them in the sorted order.
  5. .CopyToDataTable: Finally, this function is used to convert the result of the LINQ query back into a data table, and the sorted, non-blank rows are stored in the dt variable.

Hope it helps!!

1 Like

I m coming up with this statement that it can have any number of columns

To make it even more dynamic I kept sorting considering that there can be any number of columns

use this in a assign activity

dt = (From x In dt.AsEnumerable
             Where Not x.ItemArray.Any(Function(c) String.IsNullOrWhiteSpace(c.ToString()) OrElse Not Integer.TryParse(c.ToString(), Nothing))
             Order By x.ItemArray.Cast(Of Integer)()
             Select x).CopyToDataTable

Hope this helps

Cheers @csathys

hi @Parvathy

Thanks for your response. Great explanation of the solution. However, like any SQL, when AND is used in the “where” clause, the row with blank cell in column “C” is eliminated first. By the time the rows are passed to the “Order by” clause, there would be no need for the IF condition in it.

I added couple more rows to the table (shown within the box) that I posted earlier to see a better outcome of our sort result.

image

With this sample data, when I run your query as-is, you will notice that the blank cell row is ignored.

When I replace those ANDs with ORs, it returns what is needed.

@Palaniyappan Your query returns a no rows exception. What did I miss?

Instead of Isnullorwhitespace try with IsNullOrEmpty method

Let me check once

@csathys

(From d In dt.AsEnumerable
Let chk = {0,1,2}.All(Function (x) isNothing(d(x)) OrElse String.IsNullOrEmpty(d(x).toString.Trim))
Where Not chk
Let aco = {"A","B","C"}.Select(Function (p) If(Int32.TryParse(d(p).toString.Trim, Nothing), Int32.Parse(d(p).toString.Trim),0))
Order By aco(0), aco(1), aco(2)
Select r = d ).CopyToDataTable

Hi Peter, this worked as well. Thanks for your input. Would you be able to explain what’s happening here?

hi @Palaniyappan , it still results in same error.

[HowTo] LINQ (VB.Net) Learning Catalogue - Help / Something Else - UiPath Community Forum

With Let Clause we can memorize values ~ like a local variable

loop over the datatable rows

use a predefined Set of Column Indexes and check if the values are filled

filter on the chk result, deny it as were are interested on rows where the first 3 col values are not Null or empty

use a set of columnnames, when we can parse the corresponding column value use the int32, or a default value: 0

use the aco result and access the frist, second, third vaue for the sorting

a formal to part of using the datarow and copy it to a new datatable

Perfect, so the topic can be closed?
Forum FAQ - How to mark a post as a solution - News / Tutorials - UiPath Community Forum

Yes please. Thank you all for your quick help.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.