finding min and maxin list using LINQ and DBNulls - vb.net

i have the following code which will get the max and min values from a list of type double
Dim sprices As List(Of Double) = grp.ProductGroups.AsEnumerable().[Select](Function(sm) sm.Field(Of Double)("sprice")).Distinct().ToList()
Dim min As Integer = sprices.Min()
Dim max As Integer = sprices.Max()
how ever in the first line i get the exception "Cannot cast DBNull.Value to type 'System.Double'. Please use a nullable type."
how can i avoid this or not add the DBNulls to the list?

One way is to use a nullable Double, which can be expressed as Double?:
Dim sprices As List(Of Double?) = grp.ProductGroups.AsEnumerable().[Select](Function(sm) sm.Field(Of Double?)("sprice")).Distinct().ToList()

Related

TryCast for string to integer in VB.NET

I do not understand at all how to use TryCast in my code, but it is something I need to use for validating user input. I have done various searches and looked at various questions on here, but no one seems to actually say how to use it, and the MSDN website doesn't seem to help at all.
Function ValidateInput(Var_In As String) As Integer
If TryCast(Var_In, Integer) = Nothing Then
Return vbNull
Else
Return Var_In
End If
End Function
The error says that
The operand must be of reference type but Integer is of value type
What is the explanation of what I have done wrong?
TryParse doesn't accept more than 10 digits so for example, an input of "12345678901" won't be accepted. How do I fix this?
Let's try to understand the differences between TryCast, Convert and TryParse.
TryCast
This function will attempt to convert one object into another type, as long as it is a reference type.
Dim MyNewObject = TryCast(MyObject, MyReferenceClass)
If IsNothing(MyNewObject) Then
MessageBox.Show("Impossible to cast")
End If
Since Integer is a value type, it will not work, so we have to figure something out...
Convert
Convert Class on MSDN
From MSDN:
Converts a base data type to another base data type.
So we can try:
Dim myInt = Convert.ToInt32(MyObject)
The problem is that it will generate an exception InvalidCastException if it's impossible to do the conversion.
TryParse
This function is trying to convert a String into something you want. And it will not generate an exception:
Dim myInt As Integer = 0
If Not Integer.TryParse(MyString, myInt) Then
MessageBox.show("This is not an integer")
End If
Limitation
Converting a String into a Integer can sometimes be tricky... If the String represents a number that is greater or lesser than Integer.MaxValue and Integer.MinValue, you will end up with no conversion...
So you can go with a Double:
Double.TryParse(MyString, MyDouble)
Or personally, if you know that it will be a number, use Decimal:
Decimal.TryParse(MyString, MyDecimal)
See Decimals on MSDN
Decimal still has a Max and Min value, according to MSDN:
The Decimal value type represents decimal numbers ranging from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. The Decimal value type is appropriate for financial calculations that require large numbers of significant integral and fractional digits and no round-off errors.
Convert.ChangeType
This one is also interesting, but is a bit weird...
You are attempting to perform TryCast against an Integer, which is a value type. TryCast works only on reference types, such as (but not limited to) a Class, Object, or String type.
If you are trying to convert the input parameter to an Integer, you might try one of the methods in the Convert class, such as Convert.ToInt32() or Integer.TryParse.
Instead of TryCast, use TryParse:
Function ValidateInput(Var_In As String) As Integer
Dim iNum As Integer
If (Integer.TryParse(Var_In, iNum)) Then
Return iNum
Else
Return vbNull
End If
End Function
Much better is to use TryParse:
Function ValidateInput(Var_In As String) As Integer
Dim num as Integer
If Not Integer.TryParse(Var_In, num) Then
Return vbNull
Else
Return num
End If
End Function
I'm late to the discussion, but if anyone lands here (like I did) looking for a quick & dirty solution, here a function I'm using for simple cell validation in a DataGridView control.
Function TryTypeFit(theString As String, theType As Type, ShowError As Boolean) As Boolean
Dim TempReturn As Boolean = False
Dim TempObject As Object
Try
TempObject = Convert.ChangeType(theString, theType)
TempReturn = True
Catch ex As Exception
' didn't work
TempReturn = False
If ShowError Then
Dim eMessage As String = "Error: Value must be castable to a " & CStr(theType.Name)
MsgBox(eMessage)
End If
End Try
100:
Return TempReturn
End Function

Linq query that returns Ids as List(Of String)

I have tried several casts and can't get this to work.
Here is what I am trying to convert into a linq query in vb.net:
The Ids are of type int
Dim listOfProductIds As New List(Of String)
For Each s In Products
listOfProductIds.Add(s.Id)
Next
This is what isn't working when I expect it to:
Dim listOfProductIds As List(Of String) = (From s In Products
Select s.Id.ToString()).ToList()
Maybe I'm not following what you are trying to do but converting int to a string is straight forward.
Dim listOfProductIds As New List(Of String)
For Each s In Products
listOfProductIds.Add(s.Id.ToString())
Next
You have to convert the value like this because we can't project the ToString() function to a LINQ variable.
Dim _ids = (From p In products Select Convert.ToString(p.Id)).ToList

How do I do func( of datarow)

This should be easy but I'm not getting it. After an hour of Googling and MSDN perusing I'm still not getting it.
I want to sum an entire column in a typed datatable using Linq.
Won't compile:
Dim sum4 As Decimal = PmtList.Sum(x System.Func(Of GSRDataSet.PmtHistRow)())
Won't compile:
Dim x As Decimal
Dim sum3 = PmtList.AsEnumerable().Sum(x >= x.Field < Int() > ("Balance"))
Also tried: Got error "missing operand"
Dim sumObj As Object = PmtList.Compute("Sum(Total)", "=<>0")
How do I sum an entire column in a datatable using Linq?
If your Balance field is of type Decimal then you could do it like this:
Dim sum As Decimal = PmtList.AsEnumerable().Sum(Function(row As DataRow) row.Field(Of Decimal)("Balance"))
This should work:
Dim sum3 = PmtList.AsEnumerable().Sum(Function(x) x.Field(Of Int)("Balance"))

IndexOf a ComboBox just will not work for me

VB2010. I am trying to populate a ComboBox with the contents of an Enumeration of units. I have managed to do this with a Dictionary. Something like
Dim dUnits As New Dictionary(Of String, Integer)
Dim da As String
For Each enumValue As eUnits In System.Enum.GetValues(GetType(eUnits))
da = ConvertEnumToCommonName 'gets unique name for an enumeration
dUnits.Add(da, enumValue)
Next
cbo.DisplayMember = "Key" 'display the the common name
cbo.ValueMember = "Value" 'use the enumeration as the value
cbo.DataSource = New BindingSource(dUnits, Nothing)
When I load up my form that works well. Now the user can choose to select a default unit to display. So then I try
Dim defUnits As eUnits = eUnits.Feet
Dim idx As Integer = cbo.Items.IndexOf(defUnits) 'doesnt work, returns a -1
cbo.SelectedIndex = idx
I have been doing some research for some time and am fairly sure that this has to do with the ComboBox storing Values as a string and in reality I'm searching for an enumeration which is an integer. Don't know if I have that right or not. Anyway, I just cant seem to get the default item selected. Is there another approach I can try?
First of all you have a collection of integers and you're searching for the enum value. For that, try one of the following:
Store the enum value in the dictionary instead of a string:
Dim dUnits As New Dictionary(Of String, eUnits)
Keep the integers in the Dictionary but use the integer value of the enum when searching the ComboBox:
Dim idx As Integer = cbo.Items.IndexOf(CInt(defUnits))
But this is not going to work yet. You are data-bound to a Dictionary, which means the items in cbo.Items are not of the enum type, but of the type of the elements in the Dictionary (KeyValuePair(Of String, eUnits) assuming #1 above).
The easiest solution is just to set the SelectedValue property of the combo box instead of the SelectedIndex. Assuming you used option #1 above, this would be:
cbo.SelectedValue = defUnits
If you used option #2 instead, you'll have to convert this to an integer first:
cbo.SelectedValue = CInt(defUnits)

DataTable to ArrayList

I want to get value from datatable and then store it to the string() arraylist. datatable contain 3 column (columnA | columnB | columnC). I want to get all value from columnB and store it to arraylist.
I have try something like this
If myTableData.Rows.Count > 0 Then
For i As Integer = 0 To myTableData.Rows.Count - 1
Dim value() As String = myTableData.Rows(i)(1)
Next
End If
but when I compile that code, I got error message like this :
Unable to cast object of type 'System.String' to type 'System.String[]'
please help me.....
You could do that with LINQ:
Dim colBValues = (From row In myTableData Select colB = row(1).ToString).ToList
Or if you prefer the "old-school" way:
Dim colBValues = New List(Of String)
For Each row As DataRow In myTableData.Rows
colBValues.Add(row(1).ToString)
Next
I've used a List(Of String) because it's type-safe, therefore you don't need to cast the values everytime. That makes code more readable, more failsafe and faster.
If you need it as String-Array, you could simply use ToArray:
Dim colBValues = (From row In myTableData Select colB = row(1).ToString).ToArray
List(T)
LINQ
Dim a() As String
Dim total As Integer
'Count the number of rows
total = myTableData.Rows.Count - 1
ReDim a(0 To total)
For i = 0 To total
a(i) = myTableData.Rows(i)(1)
Next
This is really old question, but I'll provide one more variant of answer :
Dim value = myTableData.Rows.OfType(Of DataRow).Select(Function(x) x(1).ToString()).ToArray
So, if You have more than one column in Your DataTable You can use x(columnIndex) instead 1.