i m not able to fix my auto id generator - vb.net

I am able to successfully generate an id on form load but when I leave that form and try to load it again the id generated is the same as the previous one
Try
Dim num As Integer
conn.ConnectionString = String.Format("server=localhost;user id=root;password=root;database=rishab")
conn.Open()
sqlcommand = New MySqlCommand("select max(ID) from inc", conn)
sqlcommand.ExecuteNonQuery()
If IsDBNull(sqlcommand.ExecuteScalar) Then
num = 1
id5.Text = num
Else
num = sqlcommand.ExecuteScalar + 1
id5.Text = num
End If
sqlcommand.Dispose()
conn.Close()
conn.Dispose()
Catch ex As Exception
End Try
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
autogenerate()
End Sub

If I understand this correctly you need to declare your num Integer as public. It will then hold the latest value and when you re-load the form it will count on from the latest value. Do this before your form class starts or I will personally add this in a module with all my other public strings, booleans and integers.
''In a module add -
Public num As Integer
''Do not add a value here as in Public num as Integer = 0 as it will give the value 0 every time you make a call to it.
''Also remember to handle the value throughout your app, change back to 0 or leave it to the last value etc.

Related

Pasting new records to a Bound DataGridView

Apologies if this has already been asked. If so, I am unable to find a simple solution. I am trying to allow a user to copy/paste multiple records in a DataGridView (the in memory copy of the data, to be saved later when the user clicks the save button) and cannot find anything that works. It probably is because there is something I do not understand about all of this.
I set up a standard edit form with Visual Studio's drag/table into a form, so it's using a BindingSource control and all the other controls that come with doing that. It works just fine when manually entering something in the new row one by one, so it seems to be set up correctly, but when it comes to adding a record (or multiples) using code, nothing seems to work.
I tried a few things as outline in the code below. Could someone please at least steer me in the right direction? It cannot be that difficult to paste multiple records.
I run this when the user presses Control-V (the clipboard correctly holds the delimited strings):
Private Sub PasteClipboard()
If Clipboard.ContainsText Then
Dim sLines() As String = Clipboard.GetText.Split(vbCrLf)
For Each sLine As String In sLines
Dim Items() As String = sLine.Split(vbTab)
Dim drv As DataRowView = AdjustmentsBindingSource.AddNew()
drv.Item(1) = Items(0)
drv.Item(2) = Items(1)
drv.Item(3) = Items(2)
drv.Item(4) = Items(3)
'Error on next line : Cannot add external objects to this list.
AdjustmentsBindingSource.Add(drv)
Next
End If
End Sub
EDIT
(the bindingsource is bound to a dataadapter, which is bound to a table in an mdb file, if that helps understand)
I adjusted the inner part of the code to this:
If (RowHasData(Items)) Then
Dim drv As DataRowView = AdjustmentsBindingSource.AddNew()
drv.Item("FontName") = Items(0)
drv.Item("FontSize") = Items(1)
drv.Item("LetterCombo") = Items(2)
drv.Item("Adjustment") = Items(3)
drv.Item("HorV") = Items(4)
End If
It kinda works, but it also adds a blank row before the 2 new rows. Not sure where that is coming from, as I have even included your RowHasData() routine...
I would think that “attemp3” SHOULD work, however, it is unclear “what” the AdjustmentsBindingSource’s DataSource is. Is it a List<T> or DataTable?
If I set the BinngSource.DataSource to a DataTable, then attempt 3 appears to work. Below is an example that worked.
Private Sub PasteClipboard2()
If Clipboard.ContainsText Then
Dim sLines() As String = Clipboard.GetText.Split(vbCrLf)
For Each sLine As String In sLines
Dim Items() As String = sLine.Split(vbTab)
If (RowHasData(Items)) Then
Dim drv As DataRowView = AdjustmentsBindingSource.AddNew()
drv.Item("FontName") = Items(0)
drv.Item("FontSize") = Items(1)
drv.Item("LetterCombo") = Items(2)
drv.Item("Adjustment") = Items(3)
drv.Item("HorV") = Items(4)
End If
Next
End If
End Sub
This appears to work in my tests. I added a small function (RowHasData) to avoid malformed strings causing problems. It simply checks the size (at least 5 items) and also checks to make sure a row actually has “some” data. If a row is just empty strings, then it is ignored.
Private Function RowHasData(items As String())
If (items.Count >= 5) Then
For Each item In items
If (item <> "") Then Return True
Next
End If
Return False
End Function
I am guessing it would be just as easy to add the new rows “directly” to the BindingSource’s DataSource. In the example below, the code is adding the row “directly” to the DataTable that is used as a DataSource to the BindingSource. I am confident you could do the same thing with a List<T> by simply adding a new object to the list. Below is a complete example using a BindingSource and a DataTable. This simply adds the rows to the bottom of the table.
Dim gridTable1 As DataTable
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PasteClipboard()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
gridTable1 = GetTable()
FillTable(gridTable1)
AdjustmentsBindingSource.DataSource = gridTable1
AdjustmentsDataGridView.DataSource = AdjustmentsBindingSource
End Sub
Private Function GetTable() As DataTable
Dim dt = New DataTable()
dt.Columns.Add("FontName", GetType(String))
dt.Columns.Add("FontSize", GetType(String))
dt.Columns.Add("LetterCombo", GetType(String))
dt.Columns.Add("Adjustment", GetType(String))
dt.Columns.Add("HorV", GetType(String))
Return dt
End Function
Private Sub FillTable(dt As DataTable)
For index = 1 To 10
dt.Rows.Add("Name_" + index.ToString(), "Size_" + index.ToString(), "Combo_" + index.ToString(), "Adjust_" + index.ToString(), "HorV_" + index.ToString())
Next
End Sub
Private Sub PasteClipboard()
If Clipboard.ContainsText Then
Dim sLines() As String = Clipboard.GetText.Split(vbCrLf)
Try
Dim dataRow As DataRow
For Each sLine As String In sLines
Dim Items() As String = sLine.Split(vbTab)
If (RowHasData(Items)) Then
dataRow = gridTable1.NewRow()
dataRow("FontName") = Items(0)
dataRow("FontSize") = Items(1)
dataRow("LetterCombo") = Items(2)
dataRow("Adjustment") = Items(3)
dataRow("HorV") = Items(4)
gridTable1.Rows.Add(dataRow)
End If
Next
Catch ex As Exception
MessageBox.Show("Error: " + ex.Message)
End Try
End If
End Sub
Private Function RowHasData(items As String())
If (items.Count >= 5) Then
For Each item In items
If (item <> "") Then Return True
Next
End If
Return False
End Function
Hope the code helps…
Last but important, I am only guessing that you may have not “TESTED” the different ways users can “SELECT” data and “how” other applications “copy” that selected data. My previous tests using the WIN-OS “Clipboard” can sometimes give unexpected results. Example, if the user selects multiple items using the ”Ctrl” key to “ADD” to the selection, extra rows appeared in the Clipboard if the selection was not contiguous. My important point is that using the OS clipboard is quirky IMHO. I recommend LOTS of testing on the “different” ways the user can select the data. If this is not an issue then the code above should work.

calling a VB.net Function for SQL recordset

Beginner here
I have the following code which I would like to call using a button called findCustomerBTN
Public Function Execute(ByVal sqlQuery As String) As ADODB.Recordset
If SecuritySSPIchkbx.Checked Then
chk = "TRUE"
Else chk = "FALSE"
End If
builder.DataSource = ServerBox.Text
builder.InitialCatalog = DatabaseBox.Text
builder.UserID = Username.Text
builder.Password = Password.Text
builder.IntegratedSecurity = chk
MessageBox.Show(builder.ConnectionString)
Using sqlConnection1 As New SqlConnection(builder.ConnectionString)
sqlConnection1.Open()
Try
command = New SqlCommand(sqlQuery, sqlConnection1)
adapter.SelectCommand = command
adapter.Fill(ds, "Create DataView")
adapter.Dispose()
command.Dispose()
sqlConnection1.Close()
dv = ds.Tables(0).DefaultView
DataGridView1.DataSource = dv
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Using
End Function
How do I call this function:
Private Sub findCustomerBTN_Click(sender As Object, e As EventArgs) Handles
sqlquery = "Select * from customers where name = 'Smith'"
call function?
End Sub
I have googled but I can't wrap my head around how a function works any pointers to help me understand would be great thanks
In VB, a function is a block of code that returns a value. Your code does not return a value, and the type of query execution you're carrying out will never return an ADODB.RecordSet - that's an ancient technology remeniscent of the VB6 era, and you're using a much more modern data access strategy (ADO.NET, DataTables and DataAdapter) though it's not the latest and greatest.
To offer a run through of your code, and the other issues it has:
Execute is a pretty bland name - go for something more specific, just incase you run the wrong execute and some poor prisoner ends up in front of the firing squad
Your function takes an sql string as a parameter to run, but then overwrites it with a fixed string, so there isn't much point offering it as a parameter in the first place. I could call Execute("SELECT * FROM kittens") expecting to get some cute data back, and all I get is the same old customer
Avoid calling MessageBox.Show in any code that shoudl reasonably be expected to run quietly and repeatedly, otherwise the user is going to get hella annoyed. If youre putting this here for debugging purposes, learn how the visual studio debugger works instead
Your code runs an sql query and assigns the resulting data table data to the datasource of a grid, so that the grid will show the data. There's absolutely no need for this code to be a function (and in c# it wouldnt even compile because it doesn't return a value
What are functions? What do they do? They take some inuts and return some outputs:
Public Function AddTheseTwo(a as Integer, b as Integer) As Integer
Return a + b
End Function
They are called like this:
Dim sum = AddTheseTwo(2, 3)
I.e. you give the name of the function and the input values, which can be variables, and store the result (usually, because you want to use it). Here's a code of yours that is a sub - a block of code that doesn't return a value
Private Sub findCustomerBTN_Click(sender As Object, e As EventArgs) Handles
Execute("Select * from customers where name = 'Smith'")
End Sub
It's not linked to your button click, because there's nothing afte rthe Handles keyword. It should be something like Handles findCustomerBTN.Click. You can mash that button all day and nothing will happen
It called Execute but didn't store the return value (because it didn't need to, because Execute doesn't return anything, so Execute should have been declared as a sub, not a function)
Edit:
You mentioned you want the function to return a datatable:
Public Function GetDataTable(ByVal sqlQuery As String) As DataTable 'need to Imports System.Data if you haven't already
If SecuritySSPIchkbx.Checked Then
chk = "TRUE"
Else chk = "FALSE"
End If
'better to declare builder in this function, not elsewhere
builder.DataSource = ServerBox.Text
builder.InitialCatalog = DatabaseBox.Text
builder.UserID = Username.Text
builder.Password = Password.Text
builder.IntegratedSecurity = chk
MessageBox.Show(builder.ConnectionString)
Using sqlConnection1 As New SqlConnection(builder.ConnectionString)
sqlConnection1.Open()
Try
'note: better to declare adapter and command in this function too
command = New SqlCommand(sqlQuery, sqlConnection1)
adapter.SelectCommand = command
Dim dt as New DataTable
adapter.Fill(dt)
adapter.Dispose()
command.Dispose()
sqlConnection1.Close()
Return dt
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Using
Return Nothing 'a function has to return something from all possible code paths, even if it's Nothing :)
End Function
And then you call it like this, perhaps:
Private Sub findCustomerBTN_Click(sender As Object, e As EventArgs) Handles whateverbutton.Click
'you can set a datatable as a datasource, doesn't have to be the datatable.defaultview
myDataGRidView.DataSource = GetDataTable("Select * from customers where name = 'Smith'")
End Sub
I recommend you turn on the options for Strict/Explicit etc, to encourage better coding practices. By default VB is quite loose, letting you use variables that havent been declared (autodeclaring variable names that are a typo of another variable name etc), automatically returning Nothing for you from functions etc - it's these little auto's that will later lead to bugs and frsutrations. Computer programming si a precise art; turn on all options to force yourself to be as precise as possible
You can call Execute function using this code:
Private Sub findCustomerBTN_Click(sender As Object, e As EventArgs) Handles
Execute("Select * from customers where name = 'Smith'")
End Sub
You also have to remove this line from Execute function:
sqlQuery = ("select * from ac_billbook where ref = '900123'")
Please follow Steve suggestion to read a good book about programming in VB.NET.

Adding Data to DataTable

This code is recording the inserted IDs in arraylist and when press on button it should create loop for this array and get the data of each ID from the array and put it in Datatable and add the new data while looping to the datatable and finaly show it in datagridview .
The problem in the result when I insert one record it works fine but when I insert more than one the datagridview shows just the last one , what the mistake that I Done ?!!
In Mainform
Public Inserted_record_hold_dt As New DataTable
Public Inserted_record_dt As New DataTable
Public Sub Addcolumnstodatagrid()
Inserted_record_dt.Columns.Add("ID")
Inserted_record_dt.Columns(0).AutoIncrement = True
Inserted_record_dt.Columns.Add("drawingname")
Inserted_record_dt.Columns.Add("serial")
End Sub
and call this in main_Load
Addcolumnstodatagrid()
And this in the show button when click to loop on the array list that already have the latest ID's that has been added
Private Sub show_btn_Click(sender As System.Object, e As System.EventArgs) Handles show_btn.Click
Dim InsertedID As Integer
Inserted_record_dt.Clear()
Dim R As DataRow = Inserted_record_dt.NewRow
'Loop For each ID in the array "Inserted_List_Array"
For Each InsertedID In mainadd.Inserted_List_Array
'MsgBox(InsertedID.ToString)
Dim cmd As New SqlCommand("select drawingname , serial from main where drawingid = '" & InsertedID & "'", DBConnection)
DBConnection.Open()
Inserted_record_hold_dt.Load(cmd.ExecuteReader)
Try
R("drawingname") = Inserted_record_hold_dt.Rows(0).Item(0)
R("serial") = Inserted_record_hold_dt.Rows(0).Item(1)
Inserted_record_dt.Rows.Add(R)
Catch
End Try
'MsgBox("added")
DBConnection.Close()
cmd = Nothing
Inserted_record_hold_dt.Clear()
Next
sendmail.Show()
sendmail.Mail_DGView.DataSource = Inserted_record_dt
End Sub
Please tell me what is the problem in my code .
Your mistake is in declaring the R variable just one time outside the loop. In this way you continuously replace the values on the same instance of a DataRow and insert always the same instance.
Just move the declaration inside the loop
For Each InsertedID In mainadd.Inserted_List_Array
......
Try
Dim R As DataRow = Inserted_record_dt.NewRow
R("drawingname") = Inserted_record_hold_dt.Rows(0).Item(0)
R("serial") = Inserted_record_hold_dt.Rows(0).Item(1)
Inserted_record_dt.Rows.Add(R)
Catch
....
Next
Another important thing to do is to remove the empty Try/Catch because you are just killing the exception (no message, no log) and thus you will never know if there are errors in this import. At the end you will ship a product that could give incorrect results to your end user.

Round cell values of a datatable (VB.NET)

I have trouble rounding some cells from my datatable.
I want this round to 2 decimal places, as you can imagine. I will explain quickly how I charge data to the DataTable :
I have this function stored in a class:
Protected Friend Function cargarPref(ByVal id_Pref As String) As DataTable
Dim cmd As String = "Select Material,Cubicaje,SubTotal,ITBM,Total from Preferencia WHERE Id_Preferencia=#id_Pref"
Dim t As New DataTable
Try
con.Open()
comando = New OleDbCommand(cmd, con)
comando.Parameters.AddWithValue("#id_Pref", id_Pref)
adapter = New OleDbDataAdapter(comando)
adapter.Fill(t)
comando.Dispose()
adapter.Dispose()
con.Close()
Catch ex As Exception
MsgBox("Error en la consulta: " + ex.Message, MsgBoxStyle.Critical)
End Try
Return t
End Function
Ok, now I call it in my windows form:
Private Sub DataCliente_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataCliente.CellContentClick
If (Not IsNothing(DataMate)) Then
DataMate.DataSource = Nothing
mt.Clear()
End If
Dim index As Integer = 0
If (DataCliente.Columns(DataCliente.CurrentCell.ColumnIndex).Name.Equals("Empresa")) Then
index = Me.DataCliente.CurrentRow.Index
lblid.Text = DataCliente.Rows(index).Cells("Id_Cliente").Value
lblempresa.Text = DataCliente.Rows(index).Cells("Empresa").Value
lbldirecc.Text = DataCliente.Rows(index).Cells("Direccion").Value
lblcorreo.Text = DataCliente.Rows(index).Cells("Correo").Value
lbltel.Text = DataCliente.Rows(index).Cells("Telefono").Value
lblpreyd.Text = Math.Round(CDbl(DataCliente.Rows(index).Cells("PrecioYD").Value), 2).ToString("N2")
End If
mt = data.cargarPref(DataCliente.Rows(index).Cells("Id_Preferencia").Value) <--HERE!!!
DataMate.DataSource = mt
PanelMaterial.Enabled = True
End Sub
Now, watch as my values ​​are in my database access, Along With the datagrid of the program!
For some strange reason ... the data I have taken from the database , the program treats them as if they were integers.
How I can then round off those values ​​that are within the datatable, before printing in datagridview?
I finally discovered a solution , and I am going to show you how to solve this problem, if you need it (Before you do this , you must define all the columns you want to see on your datagridview !):
First, I create a class with public properties:
Public Class Preferencia
Public Property Material() As String
Public Property Cubicaje() As String
Public Property SubTotal() As String
Public Property ITBM() As String
Public Property Total() As String
End Class
Second , I create 2 functions and one procedural method :
Private Function setPreferencia(ByVal material As String, ByVal cubicaje As String, ByVal subtotal As String, ByVal itbm As String, ByVal total As String) As Preferencia
Dim item As New Preferencia
item.Material = material
item.Cubicaje = FormatNumber(cubicaje, 2)
item.SubTotal = FormatNumber(subtotal, 2)
item.ITBM = FormatNumber(itbm, 2)
item.Total = FormatNumber(total, 2)
Return item
End Function
Private Function registrarPreferencia() As List(Of Preferencia)
Dim lista As New List(Of Preferencia)
For Each itm In mt.Rows
lista.Add(setPreferencia(itm(0), itm(1), itm(2), itm(3), itm(4)))
Next
Return lista
Protected Friend Sub FillGrid()
DataMate.AutoGenerateColumns = False
DataMate.DataSource = registrarPreferencia()
DataMate.Columns("Material").DataPropertyName = "Material"
DataMate.Columns("Cubicaje").DataPropertyName = "Cubicaje"
DataMate.Columns("SubTotal").DataPropertyName = "SubTotal"
DataMate.Columns("ITBM").DataPropertyName = "ITBM"
DataMate.Columns("Total").DataPropertyName = "Total"
End Sub
Now the only thing is to call the method " FillGrid ()" when you want to print the data. And finaly, I resolved it!

How to sort DataGridView Column by date in VB visual studio 2012?

In my DGV, I have date list in the column (1):
11-Sep-2014
11-May-2011
11-Jan-2014
11-Mar-2014
12-Sep-2010
how to get descending result like this:
11-Sep-2014
11-Mar-2014
11-Jan-2014
11-May-2011
12-Sep-2010
The Column(1) is not DateTime type but SortText type, I must set string like that. Could it sorted?
I have tried using code:
DGV.Columns(1).SortMode = DGV.Sort(DGV.Columns(1), System.ComponentModel.ListSortDirection.Descending)
but it's useless, it don't sort by date :(
this is my DGV:
Okeh, this is my DGV code in brief:
Imports System.Data.OleDb
Public Class LapTransaksiSimpanan
Public Sub Koneksi()
str = "provider=microsoft.jet.oledb.4.0;data source=dbkoperasi.mdb"
Conn = New OleDbConnection(str)
If Conn.State = ConnectionState.Closed Then
Conn.Open()
End If
End Sub
Sub TampilGrid()
da = New OleDbDataAdapter("select * from LapTransaksiSimpanan", Conn)
ds = New DataSet
da.Fill(ds, "LapTransaksiSimpanan")
DGV.DataSource = ds.Tables("LapTransaksiSimpanan")
'on the below I wanna to sort the column, my code below is useless :(
DGV.Sort(DGV.Columns(1), System.ComponentModel.ListSortDirection.Descending)
DGV.Columns("ID_Simpanan").Width = 120
DGV.Columns("NAK").Width = 37
DGV.Columns("Tanggal").Width = 75
DGV.Columns("Jumlah").Width = 110
End Sub
Private Sub Setoran_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Call Koneksi()
Call TampilGrid()
End Sub
End Class
There's a difference between storing and displaying data.
You need to change you database table schema. The Tanggal column should be of type date or datetime. When you've fixed this, it's trivial to display dates using a custom format:
Me.DGV.Columns("Tanggal").DefaultCellStyle.Format = "dd-MMM-yyyy"
If you for some reason cannot change the schema, then you need to create a custom comparer by implementing IComparer. There's an example at the bottom of this MSDN page.
Dim tnd As Date
For Me.i = 0 To X1.RowCount - 2
tnd = X1.Item(1, i).Value
X1.Item(6, i).Value = tnd.ToOADate.ToString
Next
X1 is DataGridView
Column 1 would have your date ex 5/4/1987
Column 6 would be calculated as MS date number in integer and must be converted to string.
Make sure X1 grid is Sort enabled
Now simply click on Column 6 header to sort.
Hope that works.