I have rowfilter which i use to filter my datasource. I have couple controls which user can pick up checking specific checkboxes either to be used for Rowilter or not. Below code.
Dim ds = CType(dgvAbmessungen.PrimaryGrid.DataSource, DataSet)
Dim dtMain As DataTable = ds.Tables(0)
Dim filterStr As String = String.Empty
Dim byNummer As String = " [Nummer] like '" & txtFilterByNummer.Text.Trim() & "%'"
Dim byUser As String = " [User] = '" + cbUser.Text
Dim byCreateDateFrom As String = " [CreateDate] >= '" + CType(Convert.ToDateTime(calFrom.Value.Date), String)
Dim byCreateDateTo As String = "' ([CreateDate] < '" + CType(Convert.ToDateTime(calTo.Value.Date), String)
'select case checboxes and construct final rowfilter's string
dtMain.DefaultView.RowFilter = filterStr
Checboxes for diffrent controls to be checked:
for Nummer there is checkboxNummer
for User there is checkboxUser
for CreateDateFrom there is checkboxCreateDateFrom
for CreateDateTo there is checkboxCreateDateTo
Target is user checks one or more checboxes and filter should be constructed (string). Problem is i have no idea how to also concat "And" keywords between strings if user check more than one diffrent checboxes.
Currently i try to do it using select case. What could be the most efficient way to do so?
I would use LINQ:
Dim data = dtMain.AsEnumerable()
If checkboxNummer.Checked Then
data = data.Where(Function(row) row.Field(Of String)("Nummer").Contains(txtFilterByNummer.Text.Trim()))
End If
If checkboxUser.Checked Then
data = data.Where(Function(row) row.Field(Of String)("User") = cbUser.Text.Trim())
End If
If CreateDateFrom.Checked Then
data = data.Where(Function(row) row.Field(Of Date)("CreateDate") >= calFrom.Value.Date)
End If
If CreateDateTo.Checked Then
data = data.Where(Function(row) row.Field(Of Date)("CreateDate") < calTo.Value.Date)
End If
If you need the result as DataRow() use data.ToArray(). If you need a DataTable use:
If data.Any() Then dtMain = data.CopyToDataTable()
In my project, at some point I tend to load all rows in my DataSet and add them to my FlowLayoutPanel in order of their "Time" Item. This is what I'm trying to do but I need the controls to be added first if their "Time" value are the oldest :
For i=1 to DataSet.Tables("myTable").Rows.Count
Dim Row as Datarow = DataSet.Tables("myTable").Select("ID = " & i)
Dim Time as Date = Row.Item("Time")
Dim NewLabel as Label
NewLabel.text = Time.ToString()
FlowLayoutPanel.Controls.Add(newLabel)
Next
How do I do that ?
You can use Linq-To-DataSet:
Dim timeOrderedRows = From row in DataSet.Tables("myTable")
Order By row.Field(Of Date)("Time")
For Each row As DataRow In timeOrderedRows
Dim Time as Date = row.Field(Of Date)("Time")
Dim Label as New Label
Label.text = Time.ToString()
FlowLayoutPanel.Controls.Add(Label)
Next
How can I do this in reverse (from newest to the oldest)
You just have to add Descending:
....
Order By row.Field(Of Date)("Time") Descending
Dim myReader As OleDbDataReader
Dim Index As Integer
Dim status As Array
Index = 0
cmd.CommandText = "SELECT CPALLOCATIONTIME from RECORDMASTER where ID='" & TxtID.Text & "'"
cmd.CommandType = CommandType.Text
myReader = cmd.ExecuteReader()
Do While myReader.Read()
status(Index) = myReader.Item(0)
Index = Index + 1
Loop
myReader.Close()
If (Index = 2) Then
If ((status(0) = "Fp" Or status(0) = "Op") And status(1) = "OXp") Then
qText = TxtSTS.Text + "X"
Update = True
ApplicationStatus = 2
ElseIf ((status(0) = "Fp" Or status(0) = "Op") And status(1) = "FXp") Then
qText = TxtSTS.Text + "X"
Update = True
ApplicationStatus = 2
End If
Can some one please help me with status(Index) = myReader.Item(0), giving an error with conversion
You want your array to grow as elements are added. That's not what arrays are for. Use a List(Of T) instead. (See the examples on MSDN for the exact syntax.)
Make sure the data read from the reader has the correct data type. You have two ways of doing that:
Cast it (e.g. DirectCast(myReader(0), String)) or
(better) use the reader method that already returns the correct data type, e.g. myReader.GetString(0).
Redim status(0) ' < -- declare like this
Then in Loop
Redim preserve status(index)
status(Index) = myReader("Column_name")
index = index + 1
Try
status(Index) = myReader.Item(0).ToString
I have a datatable like this
X,Y,Z
0,0,A
0,2,B
0,0,C
1,0,A
1,0,C
2,2,A
2,2,B
2,0,C
3,2,B
3,1,C
4,3,A
4,0,B
4,1,C
5,3,A
5,2,B
5,0,C
and I want to convert it to something like this:
X,A,B,C
0,0,2,0
1,0, ,0
2,2,2,0
3, ,2,1
4,3,0,1
5,3,2,0
I tried with dataset and linq but not I wasn't lucky.
My code for linq:
Dim q = (From c In dt _
Select c("Z") Distinct) 'I found out which categories I have in Z column (my example :A,B,C)
Dim ldt(q.Count) As DataTable
For i = 0 To q.Count - 1
Dim sfil As String = q(i).ToString
Dim r = (From c In dt _
Select c Where c("Z") = sfil)
ldt(i) = r.CopyToDataTable
Next
So now I have 3 tables (ldt(0) with values for A, ldt(1) with values for B, ldt(2) with values for C)
and I was thinking to do something like leftJoin but anything that I tried is fail.
Any solution or even a better idea?
Thanks
So a new example it would be:
I have this table:
id,Price,Item
0,0,Laptop
0,2,Tablet
0,0,Cellphone
1,0,Laptop
1,0,Tablet
2,2,Laptop
2,2,Cellphone
2,0,Tablet
3,2,Cellphone
3,1,Tablet
4,3,Laptop
4,0,Cellphone
4,1,Tablet
5,3,Laptop
5,2,Cellphone
5,0,Tablet
and I would like to convert it to this:
X,Laptop,Tablet,Cellphone
0,0,2,0
1,0, ,0
2,2,2,0
3, ,2,1
4,3,0,1
5,3,2,0
The values for each of the columns Laptop, Tablet, Cellphone are the Y values from the first table.
I hope it make more sense now.
I believe you can create a DataTable with column names corresponding to the item names. Then you group the previous DataTable by id and use each grouping to populate a row. Forgive me if I get anything wrong. I don't work with VB or DataTables that much.
Dim itemNames = (From c In dt _
Select c("Item") Distinct)
Dim newDt as DataTable = new DataTable()
Dim idColumn As DataColumn = new DataColumn()
idColumn.DataType = System.Type.GetType("System.Int32")
idColumn.ColumnName = "id"
idColumn.ReadOnly = True
idColumn.Unique = True
newDt.Columns.Add(idColumn)
For Each itemName As String In itemNames
Dim column As DataColumn = new DataColumn()
column.DataType = GetType(Nullable(Of Integer))
column.ColumnName = itemName
column.ReadOnly = True
column.Unique = False
newDt.Columns.Add(column)
Next
Dim groupingById = From row in dt
Group By Id = row("id")
Into RowsForId = Group
For Each grouping In groupingById
Dim row as DataRow = newDt.NewRow()
row("id") = grouping.Id
For Each rowForId in grouping.RowsForId
row(rowForId("Item")) = rowForId("Price")
Next
newDt.Rows.Add(row)
Next
I am trying to populate a dataset with data from a dynamic SQL dataset created by a code generator (PDSA). If I want the first row of data, or I use a specific "Where" clause to retrieve 1 row, I have no problem. But, when I loop through the dataset that has four entries, instead of getting the four entries, I get the first row 4 times. Any idea why?
Code Example:
Dim DS_C as New DS
Dim dr_A As DS_C.Tbl_ARow
Me.DS_C.Tbl_A.Clear()
Dim bo As PDSA.DataLayer.tbl_BDC = New PDSA.BusinessLayer.tbl_B
With bo
.ConnectionString = AppConfig.SQLConnectString
.SelectFilter = PDSA.DataLayer.tbl_BDC.SelectFilters.All
.WhereFilter = tbl_BDC.WhereFilters.None
.Load()
End With
For Each dr As DataRow In bo.DataSet.Tables(0).Rows
dr_A = DS_C.Tbl_A.NewRow
With dr_A
.CustomerID = bo.CustomerID
.FirstName = bo.FirstName
.LastName = bo.LastName
.Street = bo.Street
.City = bo.City
.State = bo.State
.ZipCode = bo.ZipCode
End With
DS_C.Tbl_A.AddTbl_ARow(dr_A)
Next
If I try to change it to use dr instead of bo , it wont accept it.
I get:
.CustomerID = dr.CustomerID(CustomerID is not a member of System.Data.DataRow)
If I try using DS_C.Tbl_ARow
For Each dr As DS_C.Tbl_ARow In bo.DataSet.Tables(0).Rows
I get type 'DS_C.Tbl_ARow' is not defined
If I try :
For Each dr As DS.Tbl_ARow In bo.DataSet.Tables(0).Rows
I get:
System.InvalidCastException = {"Unable to cast object of type 'System.Data.DataRow' to type 'TblXLMajorPerilsRow'."}
You need to access it like this:
.CustomerID = dr("CustomerID");