I am trying to change combobox's DropDownWidth based on maximum string in Combobox's items.
The code below returns the maximum string length from all the items.
Dim maxStringLength As Integer = cboDt.AsEnumerable().
SelectMany(Function(row) row.ItemArray.OfType(Of String)()).
Max(Function(str) str.Length)
cboDt is the datatable attached to combobox.
I want to return the actual string.
For example if combobox items are:
"aaa"
"bbbb"
"ccccc"
My code returns maxStringLength = 5 (because 5 is the maximum number of characters of all items-here is ccccc)
I want code to retun "ccccc" (of course in a string variable)
Order the list by string-length descending, and then take the first result.
Dim maxStringLength As Integer =
cboDt.AsEnumerable().
SelectMany(Function(row) row.ItemArray.OfType(Of String)()).
OrderByDescending(Function(str) str.Length).
First() ' You can use FirstOrDefault here, if you are
' not certain there will be a result.
Assuming that the first column of the DataTable is displayed in the ComboBox:
Dim maxStringLength As Integer = cboDt.AsEnumerable().
Max(Function(r) r.Field(Of String)(0).Length)
Note that this assumes that this requires that this column is never null.
( I don't see a reason why you would measure the length of the (possibly available) other columns of the table when they aren't shown in the ComboBox at all. )
Update
Find the maximum string in Combobox
Now i got it, you want the string not the length:
Dim longestString = cboDt.AsEnumerable().
OrderByDescending(Function(r) r.Field(Of String)(0).Length).
First().Field(Of String)(0)
You can achieve this using linq and Finding the Index of maxStringLength = 5
Dim ls = comboBox4.Items.Cast(Of String)().ToList()
Dim index = ls.FindIndex(Function(c) c.ToString().Count() >= 5)
comboBox4.SelectedIndex = index
or using Max() Method
Dim ls = comboBox4.Items.Cast(Of String)().ToList()
Dim index = ls.Max()
comboBox4.Text = index
Related
I have a list of records and for Employee R1005, I need to check if that Employee has been Enabled for login alert (i.e EnableLoginAlert = Yes), then a button will be displayed.
CompanyID EmployeeNo EnableLoginAlert
10046 R1005 Yes
20041 Ajax12 No
47021 Drek Yes
I have tried the below codes:
If dCompanyDetails.Tables(0).Rows.Count > 0 Then
Dim dataView As DataView = dCompanyDetails.Tables(0).DefaultView
dataView.RowFilter = "EmployeeNo = '" & strEmployeeNumber & "'"
Dim svalue As String = dataView.Table.Rows(0).ItemArray(0).ToString()
If svalue = "No" Then
AlertButton.Visible = False
ElseIf svalue = "Yes" Then
{
//Do something else
}
End If
End If
If you are going to use a DataView then use it. This:
Dim svalue As String = dataView.Table.Rows(0).ItemArray(0).ToString()
is simply going back to the DataTable and using it, ignoring the DataView. The DataView contains DataRowView objects so get the one you need and use it. It is similar to a DataRow and you can use it the same way in this case:
Dim enableLoginAlert = CStr(dataView(0)("EnableLoginAlert")) = "Yes"
Now you have an actual Boolean that represents the state you want.
That's not how you should do it though. Generally speaking, you would use a DataView when you want to bind data. In fact, if you bind a DataTable then the data you see in the UI actually comes from the DefaultView. That's why you can filter and sort it. In this case, there are better options.
If you want to find a row by its primary key then the Rows collection of a DataTable has a Find method, e.g.
Dim row = dCompanyDetails.Tables(0).Rows.Find(strEmployeeNumber)
Dim enableLoginAlert = CStr(row("EnableLoginAlert")) = "Yes"
If you're searching by other than the primary key, the DataTable itself has a Select method. Because multiple rows may match, it returns an array, so you need to get the row out of that, e.g.
Dim row = dCompanyDetails.Tables(0).Select($"EmployeeNo = '{strEmployeeNumber}'").First()
Dim enableLoginAlert = CStr(row("EnableLoginAlert")) = "Yes"
If you want to look up a single row it's perhaps easiest to use LINQ:
Dim row = dCompanyDetails.Tables(0).Rows.Cast(Of DataRow).AsQueryable().FirstOrDefault(Function(r) r("EmployeeNo").ToString() = strEmployeeNumber)
If row IsNot Nothing AndAlso row("EnableLoginAlert").ToString() = "Yes" Then
...
..though I'd be the first to claim that using LINQ on base DataTables is very verbose, because of the Cast/AsQueryable. I'd use strongly typed DataTables (in a dataset); if you were to convert your code to using strongly typed tables it would look like:
Dim r = someDataSet.AProperTableName.FirstOrDefault(Function(r) r.EmployeeNo = strEmployeeNumber)
If r?.EnableLoginALert = "Yes" Then
...
...using strongly typed datatables is much less messy..
nb: You need to Imports System.Linq for these to work
That LINQ is the same thing as:
For Each r as DataRow in dCompanyDetails.Tables(0)
If r("EmployeeNo").ToString() = "R1005" AndAlso r("EnableLoginAlert").ToString() = "Yes" Then
...
You also have the option of using DataTable.Select (not a LINQ thing, though LINQ has a Select too)
Dim matchingRows = dCompanyDetails.Tables(0).Select($"[EmployeeNo] = '{strEmployeeNumber}'")
If matchingrows.Count > 0 AndAlso matchingRows(0)("EnableLoginAlert").ToString() = "Yes"
I have a listbox1 containing some values
value 1
value 2
value 3
value 4
value 5
and TextBox1 containing some lines
Value 3
Value 5
Value 10
Value 14
I want to get values matching in listbox1 and TextBox1
like
Value 3
Value 5
and perform some action code if values matches and loop until last value match
I have used this code but its not giving accurate output.
Dim compare As String
Dim comparear() As String
Dim list As String
Dim listar() As String
compare = TextBox1.Text
comparear = compare.Split(vbNewLine)
list = TextBox2.Text
listar = list.Split(vbNewLine)
For i = 0 To comparear.Length - 1
For p = 0 To listar.Length - 1
If listar(p).Contains(comparear(i)) Then
txt_match.Text = txt_match.Text & listar(p) & vbNewLine
Else
End If
Next
Next
You can write
Dim result = listBox1.Items.OfType(Of String).Intersect(textBox1.Lines)
result is of type IEnumerable(Of String). I.e., you can use it in For Each or add .ToList or .ToArray to get a collection.
Note that the match is case sensitive. If you want to ignore the case, you can write
Dim result = listBox1.Items.OfType(Of String) _
.Intersect(textBox1.Lines, StringComparer.OrdinalIgnoreCase)
Since the ListBox Items are returned as Objects, I used listBox1.Items.OfType(Of String) to convert them to Strings.
As I can see in the code example that you have added, you are comparing the lines of 2 TextBoxes and joning the result into a 3rd one, You can do it with these 2 code lines
Dim result = textBox1.Lines.Intersect(textBox2.Lines, StringComparer.OrdinalIgnoreCase)
txt_match.Text = String.Join(vbNewLine, result)
If you wanted to compare the items of 2 ListBoxes
Dim r = listBox1.Items.OfType(Of String) _
.Intersect(listBox2.Items.OfType(Of String), StringComparer.OrdinalIgnoreCase)
Intersect works with any two enumerations or collections of the same type
A.Intersect(B)
returns a IEnumerable(Of T) where both A and B are themselves IEnumerable(Of T). So it does not matter whether you are using the lines of a TextBox, the Items of a ListBox casted to T or arrays or List(Of T) or anything else.
Your code does not work because of 2 different errors:
You have Option Strict Off. This hides an error showing you that you are calling the wrong overload of Split. VB tries to convert vbNewLine (which is a String) to a Char, and calls Split with the 1st char found in vbNewLine. Use Option Strict On in your project and you will get a compile error. Write this instead
comparear = compare.Split(New String() {vbNewLine}, StringSplitOptions.RemoveEmptyEntries)
listar = list.Split(New String() {vbNewLine}, StringSplitOptions.RemoveEmptyEntries)
Your match is case sensitive. Instead compare like this
If listar(p).ToLowerInvariant = comparear(i).ToLowerInvariant Then
I am trying to return the first row value on colunn rep-id. Here is what I have but is only working half way I am not getting my string value
Dim text as string = sdTableAdapter.Repds(endweek).Rows (0)
How do I get the first row string from my column
You can use the Field extension method, assuming it's the first column:
Dim table As DataTable = sdTableAdapter.Repds(endweek)
Dim text As String = table.Rows(0).Field(Of String)(0)
You can also use it via column-name:
Dim text As String = table.Rows(0).Field(Of String)("ColumnName")
You'll get an exception if the type is not String, then you need to convert it from the correct type(e.g. Int32):
Dim text As String = table.Rows(0).Field(Of Int32)("ColumnName").ToString()
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.
I have this project that let user inputs 5 different numbers from 1 to 50. But I want to validate it before saving to DB that i will be 5 unique numbers. What's the best and fastest way to do this?
You can use HashSet(Of T) to check this:
Dim numbers As IEnumerable(Of Integer) = GetInputFromUser()
Dim hash As HashSet(Of Integer) = new HashSet(Of Integer)(numbers)
Dim unique As Boolean = hash.Count = numbers.Count()
This will be much more efficient than options requiring a sort + iteration.
Check this code
Private Function HasDuplicates(ByVal arr As Array) As Boolean
For i As Integer = 0 To arr.Length - 1
If Not arr(i) Is Nothing Then
Dim l As Integer = Array.LastIndexOf(arr, arr(i))
If l <> i Then Return True
End If
Next
Return False
End Function
Reed Copsey's suggestion to use hash sets was a good one (I hadn't worked with the HashSet class before).
But I then discovered that the IEnumerable class offers an extension method called Distinct that copies the unique values from a source IEnumerable to a target IEnumerable.
Borrowing the first line of Reed's sample code, here's the new sample VB.NET code:
Dim numbers As IEnumerable(Of Integer) = GetInputFromUser()
Dim isUnique As Boolean = (numbers.Distinct.Count = numbers.Count)
The variable isUnique is True if the numbers IEnumerable contains no duplicate values, or False if it contains one or more duplicate values.
Put in an array, sort it and check if elements 1,2 2,3 3,4 and 4,5 are different (in a loop).
Pseudocode:
integer numbers[50]
zeroarray(numbers, 50)
integer count = 0;
while (count < 5)
{
integer value = getinput()
if (value >= 1 and value <= 50)
if (numbers[value] = 0)
{
count = count + 1
numbers[value] = 1
}
else
reject duplicate
else
reject invalid
}
You can try this very simple method:
Filtering Arrays using LINQ
To simplifiy lets say the user inputs 5 different numbers from 0 to 49.
You can create a Boolean Array IsUsed(49) with 50 elements.
Then when the user input the value iInputNum=30 you can set IsUsed(30)=TRUE.
Next time, when the user input the second value iInputNum=7, you can set IsUsed(7)=TRUE
In this way you can check in a very fast way if the number was already inserted.
if IsUsed(iInputNum) then
'Skip the Input (put the right code here)
else
'Accept the number
IsUsed(iInputNum)=TRUE
'save iInputNum in the database
end if
Do not forget to clear the array after inserting all 5 numbers.
Remenber to put the right index in order to handle the number 1-50 (e not 0-49)
Here's an alternate solution, not sure how it compares, efficiency wise, to the other solutions, but it seems to work (uses LINQ).
Dim numbers As List<int> = getListOfNumbers()
Dim allUnique As Boolean = numbers.Distinct().Count() = numbers.Count()
Very late to the party, but what about something like this (C#, sorry)?
byte[] hits = new byte[51];
byte[] entries = new byte[] { 1, 12, 12, 32, 26, 49 };
foreach (var entry in entries)
{
hits[entry]++;
}
The elements in the hits array are automatically initialized to 0. When the foreach loop is complete, hits will contain the occurrence count for every number in entries. If any is greater than 1, you have dupes.