 |
Visual Basic 2010 General Discussion For any discussions about Visual Basic 2010 topics which aren't related to a specific Wrox book |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the Visual Basic 2010 General Discussion section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|

July 19th, 2012, 08:14 PM
|
Authorized User
|
|
Join Date: Jun 2012
Posts: 12
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
New to VB 2010 - I need help with OLEDB
I need to programatically access my .mdb file using OLEDB commands. I do not want to link listbox, combobox, datagrid, viewgrid, etc... obejects to the data base. What I'm looking for is snippets or code to read, add, delete, and edit items in my .mdb tables.
I did learn to connect to the .mdb using OLEDB, but only after days of searching and trying this and that (I have purchased 3 books and none provide exactly what I'm looking for.). I do need to re-write my VB6 programs (which include many old 3rd party .DLLs) using VB.net because they will not run on Windows 7 or above.
This old VB6 programmer will appreciate help with accessing my .mdb tables using OLEDB.
Martin 
|

August 8th, 2012, 10:14 AM
|
Authorized User
|
|
Join Date: Mar 2012
Posts: 59
Thanks: 2
Thanked 4 Times in 4 Posts
|
|
Just subscribed to this forum.
Do you still need help with this?
Kind regards,
Ian
|

August 8th, 2012, 12:14 PM
|
Authorized User
|
|
Join Date: Jun 2012
Posts: 12
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hi Ian, I have yet to see an answer (other than yours). Yes I do need help.
You said "Just subscribed to this forum.", I thought I was, or am I missing something and thats why I'm not seeing answers????????
Martin
|

August 9th, 2012, 04:28 AM
|
Authorized User
|
|
Join Date: Mar 2012
Posts: 59
Thanks: 2
Thanked 4 Times in 4 Posts
|
|
OLEDB Data Access Code
Hi Martin,
Firstly, to clarify, it is me that has just joined this forum. I have just finished one of the ASP books on one of the other forums and decided to have a look around to see what was going on elsewhere. As to not getting any answers, it happens sometimes, due to people not knowing an answer or not wanting to help?
Secondly and to your query, please see the following which I have based on the Products table of the Northwind.mdf database to demonstrate Read, Insert, Update and Delete techniques:-
1) Create a new class object and call it DataLayer. This will form the basis of your data access layer. Then copy the following code to the class. Replace the sqlConnString variable to a connection string that accesses the Northwind database on your local machine.
Code:
<Serializable()> Public Class DataLayer
Private Shared sqlConnString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source='D:\Access Databases\northwind.mdb'"
Private Shared sqlConn As New OleDb.OleDbConnection(sqlConnString)
Private Shared sqlCmnd As New OleDb.OleDbCommand
Private Shared sqlTrans As OleDb.OleDbTransaction
#Region "Northwind Data Classes"
Public Class Product
'you define the database fields here
Public Property ProductID As Integer
Public Property ProductName As String
Public Property SupplierID As Integer
Public Property CategoryID As Integer
Public Property QuantityPerUnit As String
Public Property UnitPrice As Decimal
Public Property UnitsInStock As Integer
Public Property UnitsOnOrder As Integer
Public Property ReorderLevel As Integer
Public Property Discontinued As Boolean
Public Overrides Function ToString() As String
'you define the tostring function of your class here - this is what is shown as a default
'when you add a class object to the likes of a listbox and combobox etc
'when you do NOT provide get and set values for a property an automatic
'private variable of <underscore>FieldName is created i.e. _ProductName
Return _ProductName
End Function
'define any data selection functions here using standard SQL syntax
Public Shared Function GetAllRecords() As List(Of Product)
Const sqlString As String = "SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, " & _
"ReorderLevel, Discontinued FROM Products"
Dim lstProducts As New List(Of Product)
Dim Reader As OleDb.OleDbDataReader
Try
With sqlCmnd
.Parameters.Clear()
.Connection = sqlConn
.CommandText = sqlString
End With
sqlConn.Open()
Reader = sqlCmnd.ExecuteReader
If Reader.HasRows Then
While Reader.Read
Dim PROD As New Product
With PROD
.ProductID = Reader.Item("ProductID")
'how to deal with null values:-
.ProductName = IIf(IsDBNull(Reader.Item("ProductName")), String.Empty, Reader.Item("ProductName"))
.SupplierID = Reader.Item("SupplierID")
.CategoryID = Reader.Item("CategoryID")
.QuantityPerUnit = Reader.Item("QuantityPerUnit")
.UnitPrice = Reader.Item("UnitPrice")
.UnitsInStock = Reader.Item("UnitsInStock")
.UnitsOnOrder = Reader.Item("UnitsOnOrder")
.ReorderLevel = Reader.Item("ReorderLevel")
.Discontinued = Reader.Item("Discontinued")
End With
lstProducts.Add(PROD)
End While
End If
Return lstProducts
Catch ex As Exception
Throw ex
Return Nothing
Exit Function
Finally
If sqlConn.State = ConnectionState.Open Then
sqlConn.Close()
End If
End Try
End Function
Public Shared Function InsertRecord(PROD As Product) As Integer
Const sqlString As String = "INSERT INTO Products (ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued) " & _
"VALUES (@ProductName,@SupplierID,@CategoryID,@QuantityPerUnit,@UnitPrice,@UnitsInStock,@UnitsOnOrder,@ReorderLevel,@Discontinued)"
'in SQL Server you can use ";Select SCOPE_IDENTITY();" with ExecuteScalar instead of ExecuteNonQuery to return
'the New IDNo generated by a primary key where its Identity Increment if set to 1 or more
'After testing this is not available is Access#
Dim NewRecordIDNo As Integer
'we use transaction processing here to detect for errors and rollback if needed
Try
sqlConn.Open()
sqlTrans = sqlConn.BeginTransaction
With sqlCmnd
.Connection = sqlConn
.Transaction = sqlTrans
.CommandText = sqlString
.Parameters.Clear()
.Parameters.AddWithValue("@ProductName", PROD.ProductName)
.Parameters.AddWithValue("@SupplierID", PROD.SupplierID)
.Parameters.AddWithValue("@CategoryID", PROD.CategoryID)
.Parameters.AddWithValue("@QuantityPerUnit", PROD.QuantityPerUnit)
.Parameters.AddWithValue("@UnitPrice", PROD.UnitPrice)
.Parameters.AddWithValue("@UnitsInStock", PROD.UnitsInStock)
.Parameters.AddWithValue("@UnitsOnOrder", PROD.UnitsOnOrder)
.Parameters.AddWithValue("@ReorderLevel", PROD.ReorderLevel)
.Parameters.AddWithValue("@Discontinued", PROD.Discontinued)
End With
'executenonquery returns 1 doe success and 0 for failure
NewRecordIDNo = Convert.ToInt32(sqlCmnd.ExecuteNonQuery)
sqlTrans.Commit()
Return NewRecordIDNo
Catch ex As Exception
sqlTrans.Rollback()
Throw ex
Return -1
Finally
If sqlConn.State = ConnectionState.Open Then
sqlConn.Close()
End If
End Try
End Function
Public Shared Function UpdateRecordByIDNo(PROD As Product) As Integer
Const sqlString As String = "UPDATE Products SET ProductName = @ProductName, SupplierID = @SupplierID, CategoryID = @CategoryID, QuantityPerUnit = @QuantityPerUnit, UnitPrice = @UnitPrice, UnitsInStock = " & _
"@UnitsInStock, UnitsOnOrder = @UnitsOnOrder, ReorderLevel = @ReorderLevel, Discontinued = @Discontinued WHERE ProductID=@ProductID"
'be careful here! - Access has a quirk whereby if you do not add the parameters below in the order that they are
'used in the query then the query WILL run but will NOT do anything - it bombs for some reason????
'This is an Access quirk and is not replicated in SQL Server
Dim RowsUpdated As Integer
Try
sqlConn.Open()
sqlTrans = sqlConn.BeginTransaction
With sqlCmnd
.Connection = sqlConn
.Transaction = sqlTrans
.CommandText = sqlString
.Parameters.Clear()
.Parameters.AddWithValue("@ProductName", PROD.ProductName)
.Parameters.AddWithValue("@SupplierID", PROD.SupplierID)
.Parameters.AddWithValue("@CategoryID", PROD.CategoryID)
.Parameters.AddWithValue("@QuantityPerUnit", PROD.QuantityPerUnit)
.Parameters.AddWithValue("@UnitPrice", PROD.UnitPrice)
.Parameters.AddWithValue("@UnitsInStock", PROD.UnitsInStock)
.Parameters.AddWithValue("@UnitsOnOrder", PROD.UnitsOnOrder)
.Parameters.AddWithValue("@ReorderLevel", PROD.ReorderLevel)
.Parameters.AddWithValue("@Discontinued", PROD.Discontinued)
.Parameters.AddWithValue("@ProductID", PROD.ProductID)
End With
'executenonquery returns 1 doe success and 0 for failure
RowsUpdated = sqlCmnd.ExecuteNonQuery
sqlTrans.Commit()
Return RowsUpdated
Catch ex As Exception
sqlTrans.Rollback()
Throw ex
Return -1
Finally
If sqlConn.State = ConnectionState.Open Then
sqlConn.Close()
End If
End Try
End Function
Public Shared Function DeleteRecordByIDNo(PROD As Product) As Integer
Const sqlString As String = "DELETE FROM Products WHERE (ProductID = @ProductID)"
Dim RowsUpdated As Integer
Try
sqlConn.Open()
sqlTrans = sqlConn.BeginTransaction
With sqlCmnd
.Connection = sqlConn
.Transaction = sqlTrans
.CommandText = sqlString
.Parameters.Clear()
.Parameters.AddWithValue("@ProductID", PROD.ProductID)
End With
'executenonquery returns 1 doe success and 0 for failure
RowsUpdated = sqlCmnd.ExecuteNonQuery()
sqlTrans.Commit()
Return RowsUpdated
Catch ex As Exception
sqlTrans.Rollback()
Throw ex
Return -1
Finally
If sqlConn.State = ConnectionState.Open Then
sqlConn.Close()
End If
End Try
End Function
End Class
Public Class NextTableEtc
'add each table in database defined as above
'add additional function and subroutines to do whatever you want with the data that you need to retrieve
End Class
#End Region
End Class
2) Create a new form and add a listbox and three buttons named Add, Update and Delete
3) On the form load event add the following code:-
Code:
For Each PROD As DataLayer.Product In DataLayer.Product.GetAllRecords
ListBox1.Items.Add(PROD)
Next
4) Add the following code to the Add button:-
Code:
If MsgBox("Add record?", vbYesNoCancel) = vbYes Then
Dim AddRec As New DataLayer.Product
Dim RecAdded As Integer
With AddRec
.ProductName = "My New Product Name"
.SupplierID = 1
.CategoryID = 1
.QuantityPerUnit = "New Quantity"
.UnitPrice = 9.5
.UnitsInStock = 0
.UnitsOnOrder = 20
.ReorderLevel = 10
.Discontinued = False
End With
Try
RecAdded = DataLayer.Product.InsertRecord(AddRec)
If RecAdded > 0 Then
ListBox1.Items.Add(AddRec)
MsgBox("Added!")
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
5) Add the following code to the Update button:-
Code:
If ListBox1.SelectedIndices.Count > 0 Then
If MsgBox("Update record?", vbYesNoCancel) = vbYes Then
Dim UpdateRec As DataLayer.Product
Dim RecUpdated As Integer
Dim UpdateRecIndex As Integer
UpdateRec = ListBox1.SelectedItem
UpdateRecIndex = ListBox1.SelectedIndex
With UpdateRec
.ProductName = "My New Product Name"
End With
Try
RecUpdated = DataLayer.Product.UpdateRecordByIDNo(UpdateRec)
If RecUpdated > 0 Then
ListBox1.Items.Remove(UpdateRec)
ListBox1.Items.Insert(UpdateRecIndex, UpdateRec)
MsgBox("Updated!")
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End If
6) Add the following code to the Delete button:-
Code:
If ListBox1.SelectedIndices.Count > 0 Then
If MsgBox("Delete record?", vbYesNoCancel) = vbYes Then
Dim DeleteRec As DataLayer.Product
Dim RecDeleted As Integer
DeleteRec = ListBox1.SelectedItem
Try
RecDeleted = DataLayer.Product.DeleteRecordByIDNo(DeleteRec)
If RecDeleted > 0 Then
ListBox1.Items.Remove(DeleteRec)
MsgBox("Deleted!")
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End If
7) Run the program and try the buttons to see how they work
I have commented where I think comments were needed but if you need me to delve deeper into any of the coding then just post back any questions on the forum.
If I were to make any recommendations to you then it would be to move to SQL Server 2008 Express R2. Works excellent, Lot more stable than Access and Free from Microsoft
Hope this gives you what you need and good luck.
Kind regards,
Ian
|

August 9th, 2012, 10:27 AM
|
Authorized User
|
|
Join Date: Jun 2012
Posts: 12
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hi Ian,
Thanks a million for your response. The code you have provided is what I was looking for. I have just skimmed over it but I can see that I'll be able to learn how to access and modify my .mdb files.
So far I have designed the screens and tested the many object functions by bypassing all data access code which I now can implement, thanks to you.
This VB.net is not easy to learn for one that is used to VB6 and earlier (at least for this old man). My VB6 pgms had many do Loops for enabling/disabling, hiding/showing, text boxes, buttons, panels, etc. but VB.net does not seem to allow (at least I have'nt found how) object arrays.
I will yield to your advice to learn SQL Server 2008 Express R2 but for now I will try your suggested code.
Once again, Thank you!
Martin 
Last edited by toconce; August 9th, 2012 at 10:35 AM..
|

August 9th, 2012, 12:27 PM
|
Authorized User
|
|
Join Date: Mar 2012
Posts: 59
Thanks: 2
Thanked 4 Times in 4 Posts
|
|
You are welcome Martin,
I am the same as you, an old VB6/Access Programmer who migrated to VB.NET a few years ago, so we are on the same page here.
Arrays (even though they can still be used) have basically been replaced by:-
List (of <any object type>)
Dictionary (of <any object type>)
IEnumerable (of <any object type>)
HashTables
SortedList (of <any object type>)
SortedDictionary (of <any object type>)
All of which provide the same functionality as arrays but provide a lot more power than a simple array once did in VB6.
Send me an example of one of your control arrays that you used in VB6 and I will see if I can give you a steer of how to convert in VB.NET.
Cheers,
Ian
PS. with regards to SQL Server, the best thing about this is that you can use "Select SCOPE_IDENTY" after a record insert to return the ID of the new record that has been entered which is great when needing to add related records in the same save routine that you may be writing.
|

September 3rd, 2012, 10:32 AM
|
Authorized User
|
|
Join Date: Jun 2012
Posts: 12
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
[QUOTE=Ian Ryder;286127]You are welcome Martin,
Send me an example of one of your control arrays that you used in VB6 and I will see if I can give you a steer of how to convert in VB.NET.
Hi Ian sorry it has taken so long to reply.
I have a screen with close to 50 objects as text boxes, comboboxes, and check boxes. I need to set to their ENABLE property. In VB6 it was a simple {For i = 0 to n : text(i).enabled = False: next i } Somehow, I just can't understan how the list(of...) works and less trying to code using it to achieve what was so simple in VB6.
I'd appreciate sample code.
Thanks
Martin
|

September 3rd, 2012, 10:44 AM
|
Authorized User
|
|
Join Date: Mar 2012
Posts: 59
Thanks: 2
Thanked 4 Times in 4 Posts
|
|
Hi Martin,
I hope the previous code has put you on the right track?
With regards to controls on a form there is a collection called "Me.Controls". Sorry I did not mention collections in my last narrative so give me 20 minutes to write a quick example of how to access and manipulate different controls on a form.
Cheers
Ian
|

September 3rd, 2012, 11:01 AM
|
Authorized User
|
|
Join Date: Mar 2012
Posts: 59
Thanks: 2
Thanked 4 Times in 4 Posts
|
|
Hi Martin,
This is how you enumerate the controls collection in VB.NET.
First of all you need to test the type of each control in the collection using GetType and then you need to cast the control using CType to obtain all the properties that are available for each type of control.
To test, add a textbox, checkbox, listbox and combobox to a form and then add the following code to the form load event. This will disable all controls and demonstrate how this works.
Code:
For Each ctrl As Control In Me.Controls
Select Case ctrl.GetType
Case GetType(TextBox)
Dim txtBox As TextBox
txtBox = CType(ctrl, TextBox)
txtBox.Enabled = False
Case GetType(CheckBox)
Dim chkBox As CheckBox
chkBox = CType(ctrl, CheckBox)
chkBox.Enabled = False
Case GetType(ListBox)
Dim lstBox As ListBox
lstBox = CType(ctrl, ListBox)
lstBox.Enabled = False
Case GetType(ComboBox)
Dim cboBox As ComboBox
cboBox = CType(ctrl, ComboBox)
cboBox.Enabled = False
End Select
Next
Hope this helps.
Kind regards,
Ian
|

November 22nd, 2014, 01:39 AM
|
Registered User
|
|
Join Date: Nov 2014
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Need help with Random Unique Strings/Text drawn from an array (using Collections)
Sure hope thi is the right place to post this problem. I am trying to go from programming in VB4 Professional (which I loved) to trying to program in VB 2010 Express but I am struggling with this problem: I want to draw random, unique, cards (names) from "a hat" - i.e. an array based on Generic Collections. This seems like it should be a SIMPLE problem but I am totally baffled. NOTHING that I have tried works. I anticipate that the final number of cards or names will exceed 500 but I am only using 10 cards/(names) as a trial run until I work through the code to a solid program. I have reduced this code down to the barest basics and it still has problems (which are defined in the REM comments where they occur). I hope someone can help me. I've tried for so long I am now just going in circles. This is the pathetic code I have so far:
Code:
Imports System
Imports System.Collections.Generic REM To work with collections
Imports Microsoft.VisualBasic
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
REM Two individuals take turns drawing a unique random name from a hat until all 500 or so
REM names/cards are pulled and displayed. Then same array of names is to be regenerated and
REM randomized for next prizes to be drawn again as unique random names/cards by the same two
REM individuals (or players).
End Sub
Private Sub btnEnd_Click(sender As System.Object, e As System.EventArgs) Handles btnEnd.Click
REM create a form with three buttons and a richtextbox
End
End Sub
Private Sub RichTextBox1_Click(sender As Object, e As System.EventArgs) Handles RichTextBox1.Click
'Dim Rcards As New ArrayList()
Dim deckIdx As New List(Of Integer)
Dim Rcards As New List(Of String)
Dim i As Integer = 0
Dim Count As Integer = 0
Dim prng As New Random
Rcards.Add("1 ABE")
Rcards.Add("2 BARB")
Rcards.Add("3 BOB")
Rcards.Add("4 CHARLES")
Rcards.Add("5 DON")
Rcards.Add("6 EDWARD")
Rcards.Add("7 FRAN")
Rcards.Add("8 GENE")
Rcards.Add("9 IAN")
Rcards.Add("10 JILL")
REM LOAD ARRAY
For i = 0 To Count - 1
Rcards.Add(i)
MessageBox.Show(Rcards(i))
REM PROBLEM: The ONLY card THIS displays is "! ABE" ???????
Next i
REM SHUFFLE NAMES - i.e. Rcards
REM PROBLEM: The following code generates an error that states:
REM "Value of type 'System.Collections.Generic.List(Of Integer)' cannot be converted to Integer"
deckIdx = deckIdx.OrderBy(Function(r) prng.Next).ToList
'deckIdx = Enumerable.Range(0, 9).ToList
MessageBox.Show(Rcards(i))
REM PROBLEM: The above code doesn't appear to generate any names
REM Remove the name/card picked
REM Error received for next line of code is: "Index is out of range"
REM I remarked this line of code out because the program won't load right the next time if I don't
'deckIdx.RemoveAt(i)
REM The following code isn't allowed either with collections
'deckIdx += 1
REM The SECOND person now draws a random unique name. Thus a card must be removed each time
REM there is a name drawn so that the next person has one less name available in the hat.
REM Remarks: The ONLY value returned is "1 ABE" - There are NO ERRORS to indicate problem ????
End Sub
Private Function Rcards(deckIdx As List(Of Integer)) As String
Rem I haven't looked at this code yet but no problems here (yet!)
Throw New NotImplementedException
End Function
End Class
Thank you for any help.
|
|
 |