Limit the number of rows - vb.net

How can I limit the number of rows in Datagridview column to lets say 50 record and place the other 50 into the next column on the same Datagridview? In my vb.net project I can't be scrolling up and down.
The Datagridview pull the data from an excel sheet.
Appreciate your help

Try this.
dataGridView1.RowCount = 50; //Let say we have 50 rows
if (dataGridView1.Rows.Count >= 50)
{
//TODO:
}

I assumed this as single column table ..
dim tbl as DataTable '--------> this is your displayed table
dim nLimit as Integer = 15 '----- this is your limit as you want
dim dc as DataColumn
'get column name
dim sCol as String = tbl.Columns(0).Name
dim nRow as Integer = tbl.rows.count
'how much column ?
dim n as Integer = nRow / nLimit
if n * nLimit < nRow then n+= 1
for x as Integer = 1 to n
dc = New DataColumn
dc.DataType = System.Type.GetType("System.String")
dc.Caption = sCol & n.ToString
dc.ColumnName = sCol & n.ToString
tbl.Columns.Add(dc)
next
Then you can show it ...

Related

Does the textbox that is generated when creating a detail view not count as a textbox?

My code searches for certain numbers in textboxes and replaces them. The code however does not change the number if it is in a textbox that is created from a detail view(see figure 1). Do these not count as textboxes?
Figure 1
Dim Totalsheets As Integer
Dim target_text As String
Dim FirstPage As Integer
Dim replace_text As String
Dim result As String
Dim n As Integer 'count No. of text frames changed
Dim i As Integer 'count views for the sheet
Dim x As Integer 'takes the value of the first page of the old config
Dim y As Integer 'takes the value of the total number of sheets of the old config
Dim z As Integer 'takes the value of the number that needs to be added to update the zoning
Dim a As String 'takes the value of the letter found in the zoning box
Dim b As Integer
n = 0
Set osheets = odoc.Sheets
Set osheets = osheets.Item("DRAFT") 'makes sure only sheet "DRAFT" is edited
Set oViews = osheets.Views
Totalsheets = Totalsheets1.Value 'draws value from the textbox
FirstPage = FirstPage1.Value 'draws value from the textbox
For i = 3 To oViews.Count 'scans through all views in sheet
Set oView = oViews.Item(i)
Set oTexts = oView.Texts
For Each SrcText In oTexts 'scans through all text in view
x = FirstPage
y = Totalsheets
b = x + y
Do Until x = b + 1
z = x + Totalsheets
a = "A"
Do Until a = "[" 'goes from A to Z
result = SrcText.Text
target_text = " " & x & a 'gets space in front and letter at back to ensure only zone box are updated
replace_text = " " & z & a
If InStr(result, target_text) Then
result = Replace(result, target_text, replace_text)
SrcText.Text = result
n = n + 1
End If
a = Chr(Asc(a) + 1)
Loop
x = x + 1
Loop
Next
Next
Although the detail view identifier is a DrawingText, it does not belong to the DrawingTexts-collection.
You could access the DrawingText by searching in the view.
Better would be to rename the property of the view.
EDIT:
Example for using the (slower) selection:
Set oSel = oDoc.Selection
oSel.Clear
oSel.Add oView
oSel.Search "CATDrwSearch.DrwText,sel"
for i = 1 to oSel.Count2
Set oDrwText = oSel.Item2(i).Value
'do something with the text
next

Doubles will not output in DataGridView

I have a DataGridView that I want to fill with values that are Doubles. The DataGridView filled fine when the values were strings, but now it outputs System.Double[] in the first column and nothing in any other column. I know the conversion is working because I can print the double values to the console. How do I format all columns programmatically? (I don't want to use the designer)
My code:
Dim cols() as String = {"col1", "col2", "col3"} ' this goes on for 33 cols
Dim currentRow As String()
Dim row() As Double
Dim c As Integer
DataGridView1.Rows.Clear()
DataGridView1.ReadOnly = True
DataGridView1.DefaultCellStyle.Format = "G"
DataGridView1.ColumnCount = 33
For c = 0 To (cols.Length - 1)
DataGridView1.Columns(c).Name = cols(c)
Next
While Not at EndOfFile ' This line and the next are semi-pseudocode, but it's the same idea
read/parse line into currentRow
Dim x As Integer
For x = 0 To (currentRow.Length - 1)
ReDim Preserve row(x)
Double.TryParse(currentRow(x), row(x))
Next
With Me.DataGridView1.Rows
.Add(row)
End With
Screenshot of the output:
You can first add the row to the grid, then loop through your array to add the information to each cell.
Dim i as integer = DataGridView1.Rows.Add
For x As Integer = 0 to row.Count - 1
DataGridView1.Rows(i).Cells(x).Value = row(x)
Next

Find value of visible rows in datagridview

I'm able to get the correct row count, but the problem is when I run through the loop.
OrdNum = dgvWsNorth.Rows(i).Cells("ORDNUM").Value.ToString()
This line will loop through all visible and non visible rows = to the row count.
I need it to loop through only the visible rows = to the row count.
Dim AllRows As Integer = dgvWsNorth.Rows.GetRowCount(DataGridViewElementStates.Visible)
Dim OrdNum As Integer
Dim LinNum As Integer
Dim UnitPriority As Integer
Dim Ws_N As Integer = My.Settings.NorthLine
For i = 0 To AllRows - 1
OrdNum = dgvWsNorth.Rows(i).Cells("ORDNUM").Value.ToString()
LinNum = dgvWsNorth.Rows(i).Cells("LINE").Value.ToString()
If IsDBNull(dgvWsNorth.Rows(i).Cells("UNIT_PRIORITY").Value) Then
UnitPriority = 999
Else
UnitPriority = dgvWsNorth.Rows(i).Cells("UNIT_PRIORITY").Value.ToString()
End If
clsScheduler.UPDATE_ASSIGNED_WS(Ws_N, OrdNum, LinNum, clsLogin.plant_id, clsLogin.dept_id, UnitPriority)
Next
How about looping through all rows, and only counting the rows that are visible?
Dim i = 0
Dim OrdNum As Integer
Dim LinNum As Integer
Dim UnitPriority As Integer
Dim Ws_N As Integer = My.Settings.NorthLine
For Each r As DataGridViewRow In dgvWsNorth.Rows
If r.Visible Then
OrdNum = r.Cells("ORDNUM").Value.ToString()
LinNum = r.Cells("LINE").Value.ToString()
If IsDBNull(r.Cells("UNIT_PRIORITY").Value) Then
UnitPriority = 999
Else
UnitPriority = r.Cells("UNIT_PRIORITY").Value.ToString()
End If
clsScheduler.UPDATE_ASSIGNED_WS(Ws_N, OrdNum, LinNum, clsLogin.plant_id, clsLogin.dept_id, UnitPriority)
i += 1
End If
Next
Actually, I decided to give this a shot and I think you can do this with a Lambda on your for each statement
Instead of a for next loop use a for each with a lambda expression
For each r as datagridviewrow in DataGridView1.Rows.Cast(Of Datagridviewrow)().Where(Function(row) row.Visible = true)
... your loop code using r instead of rows(i)
Next
This should only iterate through rows that are visible.

I want to align Dynamic pictureboxs with Dynamic Labels

Here is my function that allows me to get from a webpage the image link for my PictureBoxs and the title for my labels
Public Shared Function getPics(website As String, pattern As String)
Dim tempTitles As New List(Of String)()
Dim tempTitles2 As New List(Of String)()
Dim lestitres As New List(Of titlesclass)
Dim webClient As New WebClient()
webClient.Headers.Add("user-agent", "null")
Dim counter As Integer = 0
Dim counter2 As Integer = 0
Dim counter3 As Integer = 0
Dim counter4 As Integer = 1
Dim counter5 As Integer = 0
Dim counter6 As Integer = 0
'If the website happens to go offline, at least your application wont crash.
Dim content As String = webClient.DownloadString(website)
Dim query = From title In Regex.Matches(content, pattern).Cast(Of Match)
Select New With {Key .Link = String.Concat("http://www.gamestop.com", title.Groups("Data").Value),
Key .Title = title.Groups("Dataa").Value}
For Each letitre In query.Distinct
'MsgBox(letitre.Link & " ======= " & letitre.Title)
Next
'For Each title As Match In (New Regex(pattern).Matches(content)) 'Since you are only pulling a few strings, I thought a regex would be better.
' Dim letitre As New titlesclass
' letitre.Link = title.Groups("Data").Value
' letitre.Title = title.Groups("Dataa").Value
' lestitres.Add(letitre)
' 'tempTitles2.Add(title.Groups("Dataa").Value)
'Next
Dim titles = tempTitles.Distinct().ToArray() 'remove duplicate titles
'Dim titles2 = tempTitles2.Distinct().ToArray()
Dim titles2 = lestitres.Distinct().ToArray()
lestitres.Clear()
'For Each title As titlesclass In titles2
For Each letitre In query.Distinct
'ListBox.Items.Add(title) 'what you do with the values from here is up to you.
Dim ImageInBytes() As Byte = webClient.DownloadData(letitre.Link)
Dim ImageStream As New IO.MemoryStream(ImageInBytes)
Dim MyPic As New PictureBox
Dim MyLab As New Label
If (counter2 > 0 AndAlso ((counter2 Mod 4 = 0) OrElse counter3 = 1)) Then
counter3 = 1
counter4 += 1
If (counter2 Mod 4 = 0) Then
counter5 = 0
counter6 += 170
End If
MyPic.Location = New Point(counter5, MyPic.Location.Y + counter6)
MyLab.Location = New Point(counter5, MyPic.Location.Y + counter6)
If counter4 = 4 Then
counter3 = 0
End If
counter5 += 200
Else
MyPic.Location = New Point(counter, MyPic.Location.Y)
MyLab.Location = New Point(counter, MyPic.Location.Y)
End If
counter += 200
counter2 += 1
MyPic.SizeMode = PictureBoxSizeMode.AutoSize
MyLab.Text = letitre.Title
MyPic.Image = New System.Drawing.Bitmap(ImageStream)
Form2.Controls.Add(MyPic)
Form2.Controls.Add(MyLab)
Next
End Function
The class named titlesclass contain two elements which i will store my Link and Title in :
Public Class titlesclass
Public Property Link As String
Public Property Title As String
End Class
And My little button does all the work
Dim websiteURL1 As String = "http://www.gamestop.com/collection/upcoming-video-games"
Class1.getPics(websiteURL1, "<img src=""(?<Data>[^>]*)""><p>(?<Dataa>[^>]*)<br>")
What i'm trying to do is to show 4 pictureboxs per row with the lables right bellow each picture , for now some labels doesn't show , some shows just in the right place and some shows very far bellow ! I tested the values i'm getting with a Message Box and it shows me the informations in the order i need , i'm not sure if i screw up in the x,y values or if it's something else ...
Edit : I can already show the 4 pictureboxes per row , the labels also , but the Y of some labels isn't well adjusted it can go far far bellow !
Here is some pictures that will help you to understand my situation Don't mind the buttons and listboxs , it's just for the test :
My list containt a lot of pictures , so i just showed you some when the thing work kind of well , when it shows couple of rows far from the designed picture
http://img110.xooimage.com/files/f/a/d/picture1-5239f7c.png
http://img110.xooimage.com/files/8/f/8/picture-2-5239f7e.png
http://img110.xooimage.com/files/4/7/b/picture-3-5239f80.png
http://img110.xooimage.com/files/f/0/f/picture4-5239f82.png
So I cleaned the way you where generating the position of the PictureBox by using a row principle and increment:
Note:
If you need space at the top to add information start the row count at 1 instead of 0
Note 2:
Here the image dimensions are harcoded but you could use dynamic ones which would be more fluid. I just cleaned the positioning code not the rest.
Replace your function by this one:
Public Shared Sub getPics(website As String, pattern As String)
Dim tempTitles As New List(Of String)()
Dim tempTitles2 As New List(Of String)()
Dim lestitres As New List(Of titlesclass)
Dim webClient As New WebClient()
webClient.Headers.Add("user-agent", "null")
Dim counter As Integer = 0
Dim counter2 As Integer = 0
Dim counter3 As Integer = 0
Dim counter4 As Integer = 1
Dim counter5 As Integer = 0
Dim counter6 As Integer = 0
'If the website happens to go offline, at least your application wont crash.
'Handle default proxy
Dim proxy As IWebProxy = WebRequest.GetSystemWebProxy()
proxy.Credentials = CredentialCache.DefaultCredentials
webClient.Proxy = proxy
Dim content As String = webClient.DownloadString(website)
Dim query = From title In Regex.Matches(content, pattern).Cast(Of Match)
Select New With {Key .Link = String.Concat("http://www.gamestop.com", title.Groups("Data").Value),
Key .Title = title.Groups("Dataa").Value}
Dim titles = tempTitles.Distinct().ToArray() 'remove duplicate titles
Dim titles2 = lestitres.Distinct().ToArray()
lestitres.Clear()
'Count Items
Dim item As Integer = 0
'Count Row
Dim row As Integer = 0
'image: 222*122
For Each letitre In query.Distinct
Dim ImageInBytes() As Byte = webClient.DownloadData(letitre.Link)
Dim ImageStream As New IO.MemoryStream(ImageInBytes)
Dim MyPic As New PictureBox
Dim MyLab As New Label
'x = numéro item fois largeur image
'y = numéro de ligne fois hauteur image
MyPic.Location = New Point(item * 222, row * 122)
MyLab.Location = New Point(item * 222, row * 122)
MyPic.SizeMode = PictureBoxSizeMode.AutoSize
MyLab.Text = letitre.Title
MyPic.Image = New System.Drawing.Bitmap(ImageStream)
Form1.Controls.Add(MyPic)
Form1.Controls.Add(MyLab)
'Bring Labels to front
For Each ctrl As Control In Form1.Controls
'If the control is of type label
If TypeOf ctrl Is Label Then
'Then bring to front
ctrl.BringToFront()
End If
Next
'Increment the item count
item = item + 1
'If item is multiple of 4 or could check 4 then
If item Mod 4 = 0 Then
'Reset counter
item = 0
'Increment Row
row = row + 1
End If
Next
End Sub
Example return:

Datatable: add computed column with subtotals

I have generated a datatable by querying a large mysql-database.
This resulted in about 7000 rows. Now I would like to add a column that calculates the sum of column "QUANTITY" for every unique value in column "BREAK2" (like a 'group by').
Example:
BREAK2 | QUANTITY | COMPUTED
A 10 30
B 20 40
A 10 30
A 20 30
B 20 40
If I use
Dim dc As DataColumn = New DataColumn
dc.DataType = System.Type.GetType("System.Double")
dc.ColumnName = "SumQTY"
dt.Columns.Add(dc)
For Each dr As DataRow In DT.Rows
dr("SumQTY") = DT.Compute("Sum(QUANTITY)", "BREAK2 = '" & dr("BREAK2") & "'")
Next
it takes a long time (several minutes before I break it off).
When I query the same data with a querytool named BRIO, and I add a computed column with formula "Sum(QUANTITY,BREAK2)", it takes about 1 second to get the results.
What could be the difference between these methods?
Why is the VB.net code taking so long?
I have tried to use LINQ but same bad performance.
Thanks.
Nas
This seems to be pretty fast
Sub Main
Dim sw = new Stopwatch()
sw.Start()
Dim rnd = new Random()
Dim dt = new DataTable()
dt.Columns.Add("BREAK2", "".GetType())
dt.Columns.Add("QUANTITY", 0.GetType())
dt.Columns.Add("COMPUTED", 0.GetType())
for i = 0 to 7000
dt.Rows.Add("A", rnd.Next(0, 30))
dt.Rows.Add("B", rnd.Next(0, 30))
dt.Rows.Add("C", rnd.Next(0, 30))
dt.Rows.Add("D", rnd.Next(0, 30))
Next
Dim keys As List(Of String) = dt.AsEnumerable() _
.Select(Function(x) x("BREAK2").ToString()) _
.Distinct().ToList()
For Each k in keys
Dim listOfRow = dt.AsEnumerable() _
.Where(Function(x) x.Field(Of String)("BREAK2") = k).ToList()
Dim total = listOfRow.Sum(Function(t) t.Field(Of Integer)("QUANTITY"))
For Each row in listOfRow
row.SetField(Of Integer)("COMPUTED", total)
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds)
End Sub
As I have said in my comment above, it is silly to recalculate the same value for thousands of time.
Using LINQ you could extract the unique values of the column BREAK2, execute the sum just one time for the subset of rows identified by the key and then set the same subset of rows with the total.
On my PC this takes at max 100 milliseconds.