Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Friday, June 17, 2016 9:51 PM
I have 5 Different arrays that I'm trying to add to 5 different columns in a ListView, BUT I am only going to use 2 Arrays & 2 Columns to make it less complicated for this example.
So I'm trying to add 2 Arrays that have "Product Titles" & "Prices" that I'm trying to put into 2 columns of a Listview which looks like the image that I have attached below:
I have tried numerous times to use the "For each" & "For loop" methods for adding both arrays to the listview, but with NO success. I'm really not sure how to do it. I will have a button1 that the user can click & it will add the arrays to the list. The products were collected from my site & added into 2 separate Array Lists that I would like to add to the listview1 via button1 click. Would appreciate the help. Thanks in advance.
All replies (37)
Monday, June 20, 2016 10:28 PM âś…Answered | 1 vote
I'm not quite understanding this. Why would we need to "simulate parsing source data from a .csv file"? Why couldn't we just parse it directly from the HTML webpage using the WebClient & Regex? This isn't making any sense to me at this point. Also, could you give me an example using the DataGridView instead? I've decided that this will be a better control to use than the listview. I have NO experience using classes either, so making this all tie in isn't going to be easy for me at this point. Thanks again for your support.
The problem has nothing to do with the parsing of an HTML page. I assume you can already do that part since the problem occurs when you try to take the results you gathered and display them in the ListView.
So the reason for the "simulation" is so that the example code can get data from somewhere. In your real application this "somewhere" is the web page you are scraping. It is up to you to replace the simulated code with your real parsing routine.
The ListView versus DataGridView is also irrelevant to the problem at hand. Once you can successfully load the data from the arrays into the ListView, you can do the same to load it into a DataGridView instead.
As far as "no experience with classes" that is why I went back to your original post and the original question and created an example which solved the problem you were asking about.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Friday, June 17, 2016 10:27 PM | 1 vote
I will have a button1 that the user can click & it will add the arrays to the list.
For I As Integer = 0 To ara1.Count - 1
Dim LVI As New ListViewItem(ara1(I))
LVI.SubItems.Add(Ara2(I))
ListView1.Items.Add(LVI)
Next
You should always post the code you are using. Otherwise you will only get suggestions that you already know won't work.
Friday, June 17, 2016 10:28 PM | 2 votes
Hi
Here is some code to do it. This assumes the size of the arrays are the same (ie Item 100 of array1 has a corresponding item at the same position in array2)
Dim array1() As String = {"Item1", "Item2", "Item3", "Item4", "Item5"}
Dim array2() As Decimal = {33.35, 12.55, 123.56, 11, 22.22}
ListView1.View = View.Details
ListView1.Columns.Add("Product Title")
ListView1.Columns.Add("Price")
' ListView1.Columns.Add("Column3")
' ListView1.Columns.Add("Column4")
' ListView1.Columns.Add("Column5")
For i As Integer = 0 To array1.Count - 1
ListView1.Items.Add(array1(i))
ListView1.Items(i).SubItems.Add(array2(i).ToString("C"))
' ListView1.Items(i).SubItems.Add(array3(i))
' ListView1.Items(i).SubItems.Add(array4(i))
' ListView1.Items(i).SubItems.Add(array5(i))
Next
Regards Les, Livingston, Scotland
Friday, June 17, 2016 10:39 PM
Hey Acamar,
So the problem is that I'm NOT always going to know how many elements that each array will have. So if the arrays aren't matching up, then I get this error:
So what if Array2, Array3, Array4 or Array5 are less than or have less elements in them? How do I fix this issue that shown in the picture?
This code only seems to work if both Arrays are even or equal in the amount of elements that they both contain. If one is shorter than the other, the Index goes out of bounds of the array.
P.S.
I've tried your code as well & I'm still getting the SAME EXACT error message. Thanks again Acmar.
Friday, June 17, 2016 10:40 PM | 1 vote
You would add the ListViewItem to the ListView, that will be the 1st column. Then add a SubItem to that ListViewItem for each additional array. The first SubItem you add will be the 2nd column, the second SubItem you add would be the 3rd column, and so on....
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'an example of the two arrays
Dim Names() As String = {"QuadCopterMotor", "QuadCopterMicro", "QuadCopterMini"} 'the names of the products
Dim Prices() As Double = {10.5, 9.8, 5.6} 'the prices of the products
For i As Integer = 0 To Names.Length - 1
Dim lvi As ListViewItem = ListView1.Items.Add(Names(i)) 'add the ListViewItem to the ListView, this will be the 1st column
lvi.SubItems.Add(Prices(i).ToString("C2")) 'add the price of the product to the SubItems of the ListViewItem. This will be the 2nd column
Next
End Sub
If you say it can`t be done then i`ll try it
Friday, June 17, 2016 10:41 PM | 1 vote
Aaron,
Don't rely on the indexes - create a class or a datatable so that you get encapsulation, then populate your ListView (use a DatagridView - it's much better for this) with the instances of the class or the rows of the datatable.
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Friday, June 17, 2016 10:47 PM | 1 vote
Hey Acamar,
So the problem is that I'm NOT always going to know how many elements that each array will have. So if the arrays aren't matching up, then I get this error:
So what if Array2, Array3, Array4 or Array5 are less than or have less elements in them? How do I fix this issue that shown in the picture?
This code only seems to work if both Arrays are even or equal in the amount of elements that they both contain. If one is shorter than the other, the Index goes out of bounds of the array.
P.S.
I've tried your code as well & I'm still getting the SAME EXACT error message. Thanks again Acmar.
You will have to make sure the arrays all have the same number of elements, otherwise there will be no way to tell which elements should be added to which product. A better way to do this would be to create a small class that represents a Product. Add a Property for each thing you need to keep track of to the class such as Product Name, Price, and whatever else.
Then just use one List(Of YourClass) or one Array of your class that you can iterate through to add them to the ListView.
If you say it can`t be done then i`ll try it
Friday, June 17, 2016 10:55 PM
So the problem is that I'm NOT always going to know how many elements that each array will have. So if the arrays aren't matching up, then I get this error:
Will 2, 3, 4 or 5 always be less? I guess they must be, if 1 contains the item description.
Before inserting the sub item, test that you haven't exceeded the count of items in those other arrays.
For I As Integer = 0 To ara1.Count - 1
Dim LVI As New ListViewItem(ara1(I))
If I < Ara2.Count Then LVI.SubItems.Add(Ara2(I))
ListView1.Items.Add(LVI)
Next
If 3 could be longer than 2, then you need to allow for that.
For I As Integer = 0 To ara1.Count - 1
Dim LVI As New ListViewItem(ara1(I))
If I < Ara2.Count Then
LVI.SubItems.Add(Ara2(I))
Else
LVI.SubItems.Add("Missing")
ListView1.Items.Add(LVI)
Next
Friday, June 17, 2016 10:55 PM
Would I have to use both the class & the datatable or will a datatable be good enough on its own? If so, then I am lost with creating the class & trying to put this all together. Thanks again Frank.
Friday, June 17, 2016 10:56 PM
I don't know how to create a class that will do this. Sorry.
Friday, June 17, 2016 11:00 PM
Would I have to use both the class & the datatable or will a datatable be good enough on its own? If so, then I am lost with creating the class & trying to put this all together. Thanks again Frank.
Possibly, but only remotely if you want to use something that can accept a .DataSource - but we're venturing out here and I don't want to confuse you.
I like to use a collection class so that you avoid having to have an external collection like a generic list. But that aside - a class (or DataTable) encapsulates the information for one "thing" - in this case, one part.
That one part has a name, for example, a description, a price and so on. It's all part of that one "thing".
Make sense?
If you'll tell me more about the information that you're working with then I'll help you put something together for it.
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Friday, June 17, 2016 11:08 PM | 1 vote
I don't know how to create a class that will do this. Sorry.
Your class simply reflects the objects in the arrays.
Public Class MyData
Public Property Description As String
Public Property Price as Double
' etc
End Class
Then load a List(Of MyData) in much the same way that you are loading the listview, by creating a new instance of MyData from each element in array 1 and adding it to the List. Your checking for missing array elements will vary slightly, because value variables (eg, Price) will already be initialized to zero, and it might not matter if reference variables are Nothing.
Displaying that List in the Listview is then a one-to-one copy, or you could bind the listview to the List, depending on what your other processing is. That other processing will also determine what other features you want to put into the Class.
Saturday, June 18, 2016 12:43 PM
Would I have to use both the class & the datatable or will a datatable be good enough on its own? If so, then I am lost with creating the class & trying to put this all together. Thanks again Frank.
Aaron,
I've put something together for you and the entire project folder is zipped up and uploaded to my website at the following:
http://www.fls-online.com/VBNet_Forum/06-18-16/ExampleForAaron.zip
That includes a class library which has a collection class (named "PartsCollection") in it and I want to explain a few things to you.
Lets's say that I put together the following class to be used for this:
Public Class Parts
Public Property Name As String
Public Property Price As Decimal
End Class
There's nothing wrong with that - it will work fine. I could then create a new list:
Private _partsList As New List(Of Parts)
And I'd be set. It would work fine but let's talk a little about what's not so good with what I show above:
What if you created an instance of that class and gave it a null value for the property "Name"? It would accept it just fine because there's nothing preventing that. What if I gave it a price of $-5.00? Again, there's nothing to prevent it so it would accept it.
Also though, what if I gave it a duplicate entry?
All of these things can be handled, but not with the simple ways that I show above.
One way would be to set the class up with shared methods so that it's always working with the collection (the list) which isn't an uncommon way at all (the factory pattern), but I've come to use a collection class so that I can build all of it together and that's what's in that zip file.
When you download and extract it, open it in Visual Studio and follow the prompts to convert it to your version. It should then work, but you'll notice that I didn't add many because I can't: There are already duplicates in there (motor, for example) and that's where we need to talk some more about how you distinguish one from another. Most likely that's in the arrays that you're not currently showing?
Once I understand it all, I can add those in and set it all up for those, so give some thought to it.
*****
The code for Form1 is shown below:
Option Strict On
Option Explicit On
Option Infer Off
Imports Parts.QuadCopter
Public Class Form1
Private _parts As PartsCollection
Private Sub Form1_Load(sender As System.Object, _
e As System.EventArgs) _
Handles MyBase.Load
_parts = New PartsCollection
InitializeParts()
DGVSetup()
UpdateDGV()
End Sub
Private Sub InitializeParts()
Try
If _parts IsNot Nothing Then
With _parts
.Add("Quadcopter Motor", 10.5D)
.Add("Quadcopter Micro", 9.8D)
.Add("Quadcopter Mini", 5.6D)
.Add("Quadcopter Monitor", 16.99D)
End With
End If
Catch ex As Exception
MessageBox.Show(String.Format("An error occurred:{0}{0}{1}", _
vbCrLf, ex.Message), _
"Exception Thrown", _
MessageBoxButtons.OK, _
MessageBoxIcon.Warning)
End Try
End Sub
Private Sub DGVSetup()
With PartsDataGridView
.AllowUserToAddRows = False
.AllowUserToDeleteRows = False
.AllowUserToOrderColumns = False
.AllowUserToResizeRows = False
.AlternatingRowsDefaultCellStyle.BackColor = Color.Aquamarine
.ReadOnly = True
.SelectionMode = DataGridViewSelectionMode.FullRowSelect
.MultiSelect = False
.RowHeadersVisible = False
.RowTemplate.Height = 50
.EnableHeadersVisualStyles = False
With .ColumnHeadersDefaultCellStyle
.Font = New Font("Tahoma", 9, FontStyle.Bold)
.BackColor = Color.LightGreen
.WrapMode = DataGridViewTriState.True
.Alignment = DataGridViewContentAlignment.MiddleCenter
End With
.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
.ColumnHeadersHeight = 50
.DataSource = Nothing
.Enabled = False
End With
End Sub
Private Sub UpdateDGV()
With PartsBindingNavigator
.BindingSource = Nothing
.Enabled = False
End With
With PartsDataGridView
.DataSource = Nothing
.Enabled = False
End With
If _parts IsNot Nothing Then
Dim bs As BindingSource = _parts.GetBindingSource
If bs IsNot Nothing Then
With PartsDataGridView
.SuspendLayout()
.DataSource = bs
.Columns(0).Visible = False
With .Columns(1)
.Width = 225
With .DefaultCellStyle
.WrapMode = DataGridViewTriState.True
.Alignment = DataGridViewContentAlignment.MiddleCenter
End With
End With
With .Columns(2)
.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
.DefaultCellStyle.Format = "c2"
.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
End With
.ResumeLayout()
.Enabled = True
If .RowCount > 0 Then
.Rows(0).Selected = True
End If
End With
With PartsBindingNavigator
.BindingSource = bs
.Enabled = True
End With
End If
End If
End Sub
End Class
The class contains a method that I put in there which will return a BindingSource and I use that BindingSource as the DataSource for a DataGridView:
I think that a DataGridView is a much better control than a ListView, but I can also set it up for a ListView if you prefer.
It wouldn't make sense to show the code for the class library here (there's a fair amount of code in it) but you'll see it once you open the project in Visual Studio. The class diagram is pretty simple though and might give you a feel for what's in it. You can see that here.
I hope this gives you food for thought. :)
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Monday, June 20, 2016 5:23 PM
Hi Frank,
Thank you for your support! I haven't tried your code yet, but I will!
I apologize that I didn't get back to you sooner. I've had nothing but a busy weekend! I meant to get back to you much earlier.
So actually what I've been trying to do is practice collecting data from one of my temporary websites (more like a web page).
I have added product details to this web page & was trying to practice parsing the data & then sending that data to either a listview or datagridview into their own columns & rows.
I would try collecting each array (into it's own list) from each html element (Product Title, Price, & # Sold), but have had NOTHING BUT TROUBLE trying to get them into the datagridview!
Here is the code that I've been working with. I know that this is DEFINITELY NOT the way to add the elements to the DataGridView, but it's DEFINITELY a good start:
Here's what my DataGridView looks like:
Would appreciate any help that you could provide. Thanks again for helping Frank!
Monday, June 20, 2016 5:26 PM
Aaron,
I'm totally lost in everything you said there. What I put together has nothing to do with a website though - I didn't know that's what you were working with.
Would another forum be a better choice maybe?
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Monday, June 20, 2016 5:31 PM
Aaron,
I'm totally lost in everything you said there. What I put together has nothing to do with a website though - I didn't know that's what you were working with.
Would another forum be a better choice maybe?
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Hi again Frank,
Yes, I didn't include this in my first inquiry because I was just trying to keep it simple by using the Arrays example, but you asked for the specifics in which that I didn't get back to you (had a busy weekend) until today. So again, my apologies that I wasn't this specific in the beginning, but I thought that just using the arrays would be sufficient to help others help get me on the right track with adding these elements to either a listview or datagridview. I hope you better understand what I'm working on now. Thanks again Frank.
Monday, June 20, 2016 5:39 PM
Aaron,
How about download what I uploaded the other day, extract it then run it (it'll ask you to convert it) and let's go from there.
I want you to see just what I have.
I might have it close, or I might be completely off-base with it, but we'll know once you run it. ;-)
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Monday, June 20, 2016 5:43 PM
Aaron,
How about download what I uploaded the other day, extract it then run it (it'll ask you to convert it) and let's go from there.
I want you to see just what I have.
I might have it close, or I might be completely off-base with it, but we'll know once you run it. ;-)
In the middle of difficulty ... lies opportunity. -- Albert Einstein
My apologies again to Frank. I didn't know that you would go and create a whole project like this. I should have been more specific from the very beginning. I didn't realize that you would go this far with creating a whole project for me. I appreciate what you've done, but after looking at your code, it looks like it's a bit over what I'm trying to achieve here. It may not be more than what is needed, but from the looks right off the bat, it looks like more work than necessary (again, I could be wrong).
Let me take a look at it & I'll let you know what I think. Thanks again for your time & patience Frank.
Monday, June 20, 2016 5:47 PM
I appreciate what you've done, but after looking at your code, it looks like it's a bit over what I'm trying to achieve here...
Well think about something: You don't *really* know what's in the BCL, but you use them all the time. You know how to use them, but not what's behind them, not really.
In that sense, this is no different. So long as you know how to use it then that's what counts.
I'm happy to explain it all though, if you want, but let me know what you think once you've had a chance to run it.
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Monday, June 20, 2016 5:58 PM
Okay Frank,
So the problem with the code you gave to me is that it's only good if your "Product Details" is already predetermined. I won't always know exactly what's going to be on my webpage at the time of parsing it. Sometimes there will be more than 5 products, some without the "# of Sold" & some with. The page will eventually have hundreds of products & I won't know the exact order or amount either.
Again, I apologize & feel bad that you went out of your way to create a project like this. However, I'm still going to need help with the code that I've mentioned above due to the random data that I will be pulling back from my web pages. Do you think that you could add these arrays to the datagridview without having to create a whole class? I'm not that advanced with programming anyhow, so trying to break down the code that you sent would be a learning curve for me right now. Also, I believe that you were right when you said that this is almost irrelevant to what I'm trying to do. Binding shouldn't be something necessary unless the data is predetermined, am I right?
Monday, June 20, 2016 6:06 PM
Okay Frank,
So the problem with the code you gave to me is that it's only good if your "Product Details" is already predetermined. I won't always know exactly what's going to be on my webpage at the time of parsing it. Sometimes there will be more than 5 products, some without the "# of Sold" & some with. The page will eventually have hundreds of products & I won't know the exact order or amount either.
Again, I apologize & feel bad that you went out of your way to create a project like this. However, I'm still going to need help with the code that I've mentioned above due to the random data that I will be pulling back from my web pages. Do you think that you could add these arrays to the datagridview without having to create a whole class? I'm not that advanced with programming anyhow, so trying to break down the code that you sent would be a learning curve for me right now. Also, I believe that you were right when you said that this is almost irrelevant to what I'm trying to do. Binding shouldn't be something necessary unless the data is predetermined, am I right?
Simply put, yes - you do need encapsulation to do it right. A bunch of arrays is easily broken by the one weak link between them being only the index of the arrays.
I can't imagine how you can't know the basic data structure though. How would you set up a DataTable for this, as an example?
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Monday, June 20, 2016 6:11 PM
... I won't always know exactly what's going to be on my webpage at the time of parsing it. Sometimes there will be more than 5 products, some without the "# of Sold" & some with. The page will eventually have hundreds of products & I won't know the exact order or amount either.
...due to the random data that I will be pulling back from my web pages. Do you think that you could add these arrays to the datagridview without having to create a whole class? ...
Binding shouldn't be something necessary unless the data is predetermined, am I right?
Hi Aaron,
The initial problem you face here is that each of your different arrays must have the same number of elements. If they do not, then you have no way to know which indices from each array match up to make a single record. You have to have a way of "grouping" the values for each product together, even if each product doesn't have the same number of values.
To do this with a separate array for each product value, you need to use a placeholder value which represents "blank" in each array. A numeric array such as the product's Cost could use a negative value (-1D for example) to indicate a "blank", but that may not work for a Quantity value where negative could indicate back order (which would be a valid quantity).
So what you likely want to do is declare your arrays to use the Nullable(Of T) type for Integer and Decimal values. Then when you are parsing your source data, you can insert the value "Nothing" into a given location in any array. That way all arrays have the same number of elements, even when there was no data for a particular product value.
Also it sounds like you want to use List(Of T) instances instead of arrays. If you don't know how many items you will have, a List is easier to manage because it can grow dynamically.
I suspect these two changes would allow your original code routine to work as intended. Granted, I would encourage using a single List(Of T) to hold instances of a custom class, rather than separate Lists, but you should still be able to make the code work as intended if for no other reason than to understand the problem you are facing.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Monday, June 20, 2016 6:17 PM
"I can't imagine how you can't know the basic data structure though."
Well, it shows in your code that the 5 predetermined ("encapsulation") data is set to 5. This number could change or it simply may not always have a piece of "# Sold" data which could also be the "one weak link" to break the chain of the arrays.
Using the code that I gave above wouldn't require that you use encapsulation or binding in order to populate the datagridview. I could be wrong, but it does seem like this should be something much simpler to do vs using encapsulation & data binding. What do you think?
Also, have you ever worked with the "WebClient Library" for collecting web data? I've combined both "Regex" & the "Webclient" methods to parse the html elements, form them into arrays, & now I'm just trying to get them into the DataGridView. Do you really think that this should require encapsulation & data binding? Please tell me what you think. Thanks again.
Monday, June 20, 2016 6:20 PM
"I can't imagine how you can't know the basic data structure though."
Well, it shows in your code that the 5 predetermined ("encapsulation") data is set to 5. This number could change or it simply may not always have a piece of "# Sold" data which could also be the "one weak link" to break the chain of the arrays.
Using the code that I gave above wouldn't require that you use encapsulation or binding in order to populate the datagridview. I could be wrong, but it does seem like this should be something much simpler to do vs using encapsulation & data binding. What do you think?
Also, have you ever worked with the "WebClient Library" for collecting web data? I've combined both "Regex" & the "Webclient" methods to parse the html elements, form them into arrays, & now I'm just trying to get them into the DataGridView. Do you really think that this should require encapsulation & data binding? Please tell me what you think. Thanks again.
Who are you addressing?
*****
You can do it the way that Reed suggests (and he's right to use nullables rather than any value type that might be "blank"), but I guess that I just don't understand how there could ever be anything blank.
Look at the initial graphic that you used: How would a user know know which motor to order? By the way, what I put together isn't an order - that really should be separate from the data itself.
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Monday, June 20, 2016 6:33 PM
Here is an example along the lines of your initial post:
Option Strict On
Public Class ListViewExampleForm
'create example listview control
Friend ListView1 As New ListView With {.Dock = DockStyle.Fill}
Private Sub ListViewExampleForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'configure example control and add to form
ListView1.Columns.Add("Name")
ListView1.Columns.Add("Qty")
ListView1.Columns.Add("Price")
ListView1.View = View.Details
Controls.Add(ListView1)
'create example source data with missing values
Dim exampleTextToParse As String = "cool widget, 12, $14.95
hunk-o-junk,,$1.42
priceless artifact,1,
,2,$99.95"
'define collections to parse data into
Dim names As New List(Of String)
Dim qtys As New List(Of Nullable(Of Integer))
Dim prices As New List(Of Nullable(Of Decimal))
'simulate parsing source data by reading a "CSV file"
Using ms As New IO.MemoryStream(System.Text.Encoding.ASCII.GetBytes(exampleTextToParse))
Using tfp As New Microsoft.VisualBasic.FileIO.TextFieldParser(ms)
tfp.SetDelimiters(",")
While Not tfp.EndOfData
'get the values for one "record"
Dim values() = tfp.ReadFields
'add the first value to the names collection if it exists
If values.Length > 0 AndAlso Not String.IsNullOrEmpty(values(0)) Then
names.Add(values(0))
Else
'...otherwise add Nothing
names.Add(Nothing)
End If
'Repeat the above for all other possible values
If values.Length > 1 AndAlso Not String.IsNullOrEmpty(values(1)) Then
qtys.Add(CInt(values(1)))
Else
qtys.Add(Nothing)
End If
If values.Length > 2 AndAlso Not String.IsNullOrEmpty(values(2)) Then
prices.Add(CDec(values(2)))
Else
prices.Add(Nothing)
End If
End While
End Using
End Using
'Now all collections contain the same number of elements
For i As Integer = 0 To names.Count - 1
'The names collection contains strings so we test for null before calling ToString
With ListView1.Items.Add(names(i)?.ToString).SubItems
'the qtys and prices collections contain Nullable(Of T) instaces, which is a
'value-type, so we can safely call ToString or use string formatting.
.Add(qtys(i).ToString)
.Add($"{prices(i):c}")
End With
Next
End Sub
End Class
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Monday, June 20, 2016 6:48 PM
Frank,
"but I guess that I just don't understand how there could ever be anything blank."
The "# Sold" could be blank as I've mentioned before. So in other words, the products on the various web pages may only have the "Product Title" & "Price", but NOT always the "# Sold" which could have an affect on the arrays indices (the values may NOT always match up breaking the chain).
"Look at the initial graphic that you used: How would a user know know which motor to order?"
Actually the graphic isn't an illustration of the webpage that the user would place orders on. It was a picture of my DataGridView after collecting the data. The user would see these details to place the order, once I add the "Buy Now" buttons next to each section on this webpage:
"By the way, what I put together isn't an order - that really should be separate from the data itself."
Right, but I need the code to add this data to a datagridview from any random order, depending on whatever the webpage will contain. Do you know how to do this with the code that I've already given? I will also take a look at Reed's ideas next. Thanks again to both of you.
Monday, June 20, 2016 6:51 PM
Frank,
"but I guess that I just don't understand how there could ever be anything blank."
The "# Sold" could be blank as I've mentioned before. So in other words, the products on the various web pages may only have the "Product Title" & "Price", but NOT always the "# Sold" which could have an affect on the arrays indices (the values may NOT always match up breaking the chain).
"Look at the initial graphic that you used: How would a user know know which motor to order?"
Actually the graphic isn't an illustration of the webpage that the user would place orders on. It was a picture of my DataGridView after collecting the data. The user would see these details to place the order, once I add the "Buy Now" buttons next to each section on this webpage:
"By the way, what I put together isn't an order - that really should be separate from the data itself."
Right, but I need the code to add this data to a datagridview from any random order, depending on whatever the webpage will contain. Do you know how to do this with the code that I've already given? I will also take a look at Reed's ideas next. Thanks again to both of you.
Have a look at what Reed posted.
All I'll say it that it's not how I'd set it up. ;-)
Good luck with your entrepreneurship though. :)
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Monday, June 20, 2016 6:57 PM
... I won't always know exactly what's going to be on my webpage at the time of parsing it. Sometimes there will be more than 5 products, some without the "# of Sold" & some with. The page will eventually have hundreds of products & I won't know the exact order or amount either.
...due to the random data that I will be pulling back from my web pages. Do you think that you could add these arrays to the datagridview without having to create a whole class? ...
Binding shouldn't be something necessary unless the data is predetermined, am I right?
Hi Aaron,
The initial problem you face here is that each of your different arrays must have the same number of elements. If they do not, then you have no way to know which indices from each array match up to make a single record. You have to have a way of "grouping" the values for each product together, even if each product doesn't have the same number of values.
To do this with a separate array for each product value, you need to use a placeholder value which represents "blank" in each array. A numeric array such as the product's Cost could use a negative value (-1D for example) to indicate a "blank", but that may not work for a Quantity value where negative could indicate back order (which would be a valid quantity).
So what you likely want to do is declare your arrays to use the Nullable(Of T) type for Integer and Decimal values. Then when you are parsing your source data, you can insert the value "Nothing" into a given location in any array. That way all arrays have the same number of elements, even when there was no data for a particular product value.
Also it sounds like you want to use List(Of T) instances instead of arrays. If you don't know how many items you will have, a List is easier to manage because it can grow dynamically.
I suspect these two changes would allow your original code routine to work as intended. Granted, I would encourage using a single List(Of T) to hold instances of a custom class, rather than separate Lists, but you should still be able to make the code work as intended if for no other reason than to understand the problem you are facing.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Hi Reed & thank you for your support.
So how exactly would I implement the code for Nullable(Of T) type for Integer and Decimal values or use the List(Of T) instances instead of arrays? I don't believe that I've ever even heard of these methods. Can you please elaborate on how to use your ideas with the code that I've given above? Thanks again for your support Reed.
Monday, June 20, 2016 7:15 PM
...
Hi Reed & thank you for your support.
So how exactly would I implement the code for Nullable(Of T) type for Integer and Decimal values or use the List(Of T) instances instead of arrays? I don't believe that I've ever even heard of these methods. Can you please elaborate on how to use your ideas with the code that I've given above? Thanks again for your support Reed.
Just in case our posts overlapped...
I replied to my own post (the one you've quoted) with a bit of example code. It should be above this post in the thread. Please give that sample code a try in a new, empty project and see if it helps you understand the problem and a way in which you can solve it.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Monday, June 20, 2016 9:32 PM
Here is an example along the lines of your initial post:
Option Strict On Public Class ListViewExampleForm 'create example listview control Friend ListView1 As New ListView With {.Dock = DockStyle.Fill} Private Sub ListViewExampleForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load 'configure example control and add to form ListView1.Columns.Add("Name") ListView1.Columns.Add("Qty") ListView1.Columns.Add("Price") ListView1.View = View.Details Controls.Add(ListView1) 'create example source data with missing values Dim exampleTextToParse As String = "cool widget, 12, $14.95 hunk-o-junk,,$1.42 priceless artifact,1, ,2,$99.95" 'define collections to parse data into Dim names As New List(Of String) Dim qtys As New List(Of Nullable(Of Integer)) Dim prices As New List(Of Nullable(Of Decimal)) 'simulate parsing source data by reading a "CSV file" Using ms As New IO.MemoryStream(System.Text.Encoding.ASCII.GetBytes(exampleTextToParse)) Using tfp As New Microsoft.VisualBasic.FileIO.TextFieldParser(ms) tfp.SetDelimiters(",") While Not tfp.EndOfData 'get the values for one "record" Dim values() = tfp.ReadFields 'add the first value to the names collection if it exists If values.Length > 0 AndAlso Not String.IsNullOrEmpty(values(0)) Then names.Add(values(0)) Else '...otherwise add Nothing names.Add(Nothing) End If 'Repeat the above for all other possible values If values.Length > 1 AndAlso Not String.IsNullOrEmpty(values(1)) Then qtys.Add(CInt(values(1))) Else qtys.Add(Nothing) End If If values.Length > 2 AndAlso Not String.IsNullOrEmpty(values(2)) Then prices.Add(CDec(values(2))) Else prices.Add(Nothing) End If End While End Using End Using 'Now all collections contain the same number of elements For i As Integer = 0 To names.Count - 1 'The names collection contains strings so we test for null before calling ToString With ListView1.Items.Add(names(i)?.ToString).SubItems 'the qtys and prices collections contain Nullable(Of T) instaces, which is a 'value-type, so we can safely call ToString or use string formatting. .Add(qtys(i).ToString) .Add($"{prices(i):c}") End With Next End Sub End Class
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Hi Reed,
I'm not quite understanding this. Why would we need to "simulate parsing source data from a .csv file"? Why couldn't we just parse it directly from the HTML webpage using the WebClient & Regex? This isn't making any sense to me at this point. Also, could you give me an example using the DataGridView instead? I've decided that this will be a better control to use than the listview. I have NO experience using classes either, so making this all tie in isn't going to be easy for me at this point. Thanks again for your support.
Monday, June 20, 2016 9:35 PM
Frank,
"but I guess that I just don't understand how there could ever be anything blank."
The "# Sold" could be blank as I've mentioned before. So in other words, the products on the various web pages may only have the "Product Title" & "Price", but NOT always the "# Sold" which could have an affect on the arrays indices (the values may NOT always match up breaking the chain).
"Look at the initial graphic that you used: How would a user know know which motor to order?"
Actually the graphic isn't an illustration of the webpage that the user would place orders on. It was a picture of my DataGridView after collecting the data. The user would see these details to place the order, once I add the "Buy Now" buttons next to each section on this webpage:
"By the way, what I put together isn't an order - that really should be separate from the data itself."
Right, but I need the code to add this data to a datagridview from any random order, depending on whatever the webpage will contain. Do you know how to do this with the code that I've already given? I will also take a look at Reed's ideas next. Thanks again to both of you.
Have a look at what Reed posted.
All I'll say it that it's not how I'd set it up. ;-)
Good luck with your entrepreneurship though. :)
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Frank,
"Have a look at what Reed posted.
All I'll say it that it's not how I'd set it up. ;-)
Good luck with your entrepreneurship though. :)"
Where are you going? You believe that you have a better way? I didn't quite understand your code because I didn't see how it matched the code that I gave you as my starting point. Are you giving up on me now? Where did you go?
Monday, June 20, 2016 9:46 PM
Aaron,
I'm here of course - I never give up. :)
I just don't understand how you can have some data and not some other data. The class(es) can also use Nullable(Of ValueTypeHere), but in some regard, that doesn't make sense to me.
Also though, the data (the information about the parts) shouldn't be confused with an order of one, and in fact you can make a good argument that my inclusion of a price violates the concept of layer separation.
If you had just the data about the part itself - no price, just the part and everything associated with it like a part number, then another class could hold the price and effective date of the price.
Now when you get to the order/invoicing/inventory and all that, now you can tie that stuff together.
I wasn't abandoning anything, just being quiet and watching is all. :)
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Monday, June 20, 2016 10:04 PM
Aaron,
I'm here of course - I never give up. :)
I just don't understand how you can have some data and not some other data. The class(es) can also use Nullable(Of ValueTypeHere), but in some regard, that doesn't make sense to me.
Also though, the data (the information about the parts) shouldn't be confused with an order of one, and in fact you can make a good argument that my inclusion of a price violates the concept of layer separation.
If you had just the data about the part itself - no price, just the part and everything associated with it like a part number, then another class could hold the price and effective date of the price.
Now when you get to the order/invoicing/inventory and all that, now you can tie that stuff together.
I wasn't abandoning anything, just being quiet and watching is all. :)
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Oh, okay. I thought that you got the hell outta dodge or abandoned ship on me. Was wondering why you weren't replying anymore. So do you still feel that your code was relevant or I needed to try another option? You seemed like you didn't agree with Reed (respectfully of course), so I awaited a better solution from you. I'm still waiting for Reed to explain "this class" reference to me in a little more detail. I've never really used a class in this way. I'm just trying to see how it relates to the original code that I've posted with using the WebClient & Regex classes. Thanks again my friend.
Monday, June 20, 2016 10:29 PM | 1 vote
Oh, okay. I thought that you got the hell outta dodge or abandoned ship on me. Was wondering why you weren't replying anymore. So do you still feel that your code was relevant or I needed to try another option? You seemed like you didn't agree with Reed (respectfully of course), so I awaited a better solution from you. I'm still waiting for Reed to explain "this class" reference to me in a little more detail. I've never really used a class in this way. I'm just trying to see how it relates to the original code that I've posted with using the WebClient & Regex classes. Thanks again my friend.
Be patient and I'm sure that Reed will explain.
He knows what he's talking about - it's not how I'd go about doing it was my only point, but I do see how he has things and he'll help you work through it.
I do wish you'd give more thought to a better structure for it all though, and give thought to what I said about separating things: A class (or DataTable) that only deals with parts. Things that don't change like the name, description, part number, and so on.
Later, add a class which has a price and and effective date of the price along with with a reference to the instance of the first class (or if a DataTable, a relation to something unique like the part number).
The whole thing sounds confusing right now, but once you see how it all works, how all the cogs fit into place, you'll get a better understanding of it and Reed knows what he's doing with this.
I'll watch and if you need me, I won't be far. :)
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Monday, June 20, 2016 10:40 PM | 1 vote
Be patient and I'm sure that Reed will explain.
He knows what he's talking about - it's not how I'd go about doing it was my only point, but I do see how he has things and he'll help you work through it....
I'll watch and if you need me, I won't be far. :)
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Thanks Frank, and sorry for busting in. It just looked like there was a fundamental hurdle that the OP would need to get past before any of the "right way" to do this would make sense. I thought it might be better to forego the idea of designing the application correctly and just concentrate on the root problem at hand.
Without understanding the concept in my example, and recognizing how the code I posted fits with the code he already has, I'm afraid everything else is going to be lost in translation.
There might be room for a second design-based discussion thread following this one, if Aaron really wants to dig into the why-and-how of designing a program like this.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Monday, June 20, 2016 10:41 PM
Thanks Frank, and sorry for busting in. It just looked like there was a fundamental hurdle that the OP would need to get past before any of the "right way" to do this would make sense. I thought it might be better to forego the idea of designing the application correctly and just concentrate on the root problem at hand.
Without understanding the concept in my example, and recognizing how the code I posted fits with the code he already has, I'm afraid everything else is going to be lost in translation.
There might be room for a second design-based discussion thread following this one, if the Aaron really wants to dig into the why-and-how of designing a program like this.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Point taken. :)
In the middle of difficulty ... lies opportunity. -- Albert Einstein
Monday, June 20, 2016 10:45 PM
The problem has nothing to do with the parsing of an HTML page. I assume you can already do that part since the problem occurs when you try to take the results you gathered and display them in the ListView.
So the reason for the "simulation" is so that the example code can get data from somewhere. In your real application this "somewhere" is the web page you are scraping. It is up to you to replace the simulated code with your real parsing routine.
The ListView versus DataGridView is also irrelevant to the problem at hand. Once you can successfully load the data from the arrays into the ListView, you can do the same to load it into a DataGridView instead.
As far as "no experience with classes" that is why I went back to your original post and the original question and created an example which solved the problem you were asking about.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Aaron,
Reed makes several good points here:
The "input" is immaterial; it might be from anything.
The "output" is immaterial; it might be to anywhere.
That's the basic concept of the sort of separation that I meant, and there are some really good ways to do that which get involved so I won't go there now, but think it through:
Data is data - input is input - output (presentation) is output.
Are the wheels starting to turn some now?
In the middle of difficulty ... lies opportunity. -- Albert Einstein