Click here to Skip to main content
14,297,905 members
Rate this:
Please Sign up or sign in to vote.
See more:
When a user has many thousands of items selected in a DataGridView (we're talking hundreds of thousands or even millions) I have presently a loop but it takes way too long so remembering I have some nifty code that performed an export of selected rows to a CSV of hundreds of thousands/millions of rows in just a few seconds, I lifted out the linq/lambada code.
Slightly modifying it for my needs, I seem to be unable to get the following code working:

Dim SelectedList As New List(Of Long)


SelectedList = From row As DataGridViewRow In DataGridView1.Rows.Cast(Of DataGridViewRow)()
                           Select Convert.ToInt64(row.Cells("ID").Value)


Getting an
Unable to cast object of type 'WhereSelectEnumerableIterator`2[System.Windows.Forms.DataGridViewRow,System.Int64]' to type 'System.Collections.Generic.List`1[System.Int64]'."

- my guess is that it doesnt like managing what I am trying to and/or converting it to Int64 is not the thing it likes, even though the item is a Long - tried int32 and I get the same error, but relating to int32. The reason why I have chosen int64 is because of the ID value records may fall out of the int32 bracket due to huge amounts of records (in their tens of millions and climbing).

I think Im very close and its only the conversion or Cast/DirectCast that would need modifying but I am stumped, or maybe is that "stupid".

Thanking you in advance for any help :)

What I have tried:

Googling "fastest way to get selected cells into a list" did not return what I wanted and neither did "vb.net datagridview using lambada to get the selected cells into a list"
Posted
Updated 5-Feb-19 0:49am
v2
Rate this:
Please Sign up or sign in to vote.

Solution 1

Your first problem is: you have completely the wrong approach.
Quote:
When a user has many thousands of items selected in a DataGridView (we're talking hundreds of thousands or even millions)
Do you seriously think that any user will conscientiously select that many records? That he will even look at that many records?
That he has the time to wait for that many records to be displayed - and that will take a significant amount of time?

Never mind about improving your processing speed - think of the poor user who is faced with thousands or even millions of rows of data and what exactly you are expecting him to do with it? Are they going to go "that one, and that one, but not that one" for each row? or "Select all" and move on? And if they are going to select all of them, why are you wasting their time and effort displaying that many?

And then look at your error message: it's telling you that what you are trying to convert is a generic collection, not a list. Try calling ToList on the collection ...

But converting it to Linq won't solve your problem, it just "hides" the loop - it doesn't remove it at all!
   
v2
Comments
Member 12561559 5-Feb-19 7:53am
   
The poor user is me unfortunately hahaha, no seriously, the list contains a bunch of files I have backed up (18 million of the suckers) so yes, although I am not viewing them all, I do need to copy the selected DGV list into a managable list :)

The reason why so many records, is that, although there are various filters I utilise to narrow down the amount of records, selecting all in one go an then removing a few that I dont want, works out perfect.

As for the loop part of it - the linq is a thousand times faster than looping through all selected rows via a for next, took about 2 seconds to select 171,500 ID values.

Thanks Griff - I knew it was something simple - Im new to the lists thing (new to vb.net really only been using it a year and unfortunately have 20 years of bad vb6 habits to get rid of!). Thanks again !! :)
OriginalGriff 5-Feb-19 8:25am
   
"the linq is a thousand times faster than looping through all selected rows via a for next, took about 2 seconds to select 171,500 ID values."
No, it isn't: the actual work isn't done until you *use the results* - Linq is a deferred execution system, not a magic wand. In many cases it 's slower than an explicit loop because the iterator has its own overhead, which is not trivial.
All the "From ... " code you execute does is set up the iterator ready to run, not actually process any rows. It's only when you use the information that any processing is done. Want proof? Use ToList on the Linq result and see how long that takes!

Have a look at this:
https://www.codeproject.com/Tips/312312/Counting-Lines-in-a-String
And check the numbers at the end!
Rate this:
Please Sign up or sign in to vote.

Solution 2

First of all, i completely agree with OriginalGriff[^]. BTW: i'd suggest to read about data paging[^].

As to the error message:
Unable to cast object of type 'WhereSelectEnumerableIterator`2[System.Windows.Forms.DataGridViewRow,System.Int64]' to type 'System.Collections.Generic.List`1[System.Int64]'."

You have to call ToList() method[^] to be able to return a List(Of Long)
Dim SelectedList As New List(Of Long) = (From row As DataGridViewRow In DataGridView1.Rows.Cast(Of DataGridViewRow)()
    Select Convert.ToInt64(row.Cells("ID").Value)) _
    .ToList()

'''lambda version
'Dim SelectedList As New List(Of Long) = DataGridView1.Rows.Cast(Of DataGridViewRow) _
'    .Select(Function(row) Convert.ToInt64(row.Cells("ID").Value)) _
'    .ToList()


Good luck!
   
Comments
Member 12561559 5-Feb-19 7:54am
   
Thanks Macej - just what I needed and Im getting there (I think!) - most appreciated !
Maciej Los 5-Feb-19 8:18am
   
You're very welcome.
Richard Deeming 5-Feb-19 12:29pm
   
You don't really want the New in there - you're creating a new list, then throwing it away and replacing it with the results of the LINQ query. :)
Dim SelectedList As List(Of Long) = ...
Richard Deeming 5-Feb-19 12:30pm
   
You could also improve the performance by pre-allocating the size of the list to match the number of rows in the grid:
Dim SelectedList As New List(Of Long)(DataGridview1.Rows.Count)
SelectedList.AddRange(DataGridView1.Rows.Cast(Of DataGridViewRow)().Select(Function(row) Convert.ToInt64(row.Cells("ID").Value)))
Maciej Los 5-Feb-19 12:37pm
   
Agree.
Thanks for your valuable comments, Richard.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100