Global Class for SQL enumerated objects - vb.net

I'm working on a tool crib VB.NET project, my first real one, so I'm struggling with a few things. In my SQL database I have a few tables that translate into enumerated fields. For example I have code and code type tables. I have a code type with CodeTypeID = 2 and description = Tool Status. These are used to track the location of a tool; Shop, In Transit, On Site, Out of Service, etc. I've set up enumerations for some of these.
Enum CodeType
User = 1
ToolStatus = 2
Repair = 3
OutOfService = 4
End Enum
ToolStatus
Shop = 5
Reserved = 6
InTransit = 7
OnSite = 9
ReturnTransit = 10
OutOfService = 11
Repair = 12
End Enum
The problem is if I change a code in SQL I then have to edit my enumerations as well. In the SQL tables I am only storing the CodeID and join to the code table to get the description. Other than an enumeration, I haven't found a good way to load these tables when the project opens that will allow me to code as easily, for example ToolStatus.OnSite to return the number 9 to my SQL table. It just seems inefficient to me. I always try to code my SQL procedures so if something changes I don't have to go and edit a bunch of procedures and would like to do the same here, especially as a simple addition of a new code could force a version update. Is there a better way to do this? I have searched the Internet and haven't found anything that really works as well as enumeration.
Example Code:
In the following code both OnSite and ReturnTransit are enumerations.
I'm moving items between two datagridviews, a Source and a Target DGV. Also updating the underlying shared datatable.
Dim cbo As ComboBox = sender
With cbo
Select Case .Name
Case "cboPeeps"
dvgFilter = "N"
Case "cboToolbox"
For i As Integer = 0 To dtTools.Rows.Count - 1
dtTools.Rows(i)("dgvFilter") = dtTools.Rows(i)("dbFilter")
Next
If cbo.Items.Count > 0 Then
filter = "ToolboxID=" & .SelectedValue.ToString & " And ToolStatus=" & OnSite
filter += " And UserID=" & .SelectedItem("UserID").ToString
End If
dvgFilter = "T"
End Select
End With
End If
Dim result() As DataRow = dtTools.Select(filter)
For i As Integer = 0 To result.Count - 1
result(i)("dgvFilter") = dvgFilter
If result(i)("dgvToolStatus") <> OutOfService Then result(i)("dgvToolStatus") = ReturnTransit
Next

I was, of course, trying to make this way too difficult. Simple solution along these lines.
Public Class Crepair
Public repairID As Integer
Public techID As Integer
Public repairCodeID As Integer
Public acceptedDate As Date
Public remarks As String
Public isComplete As Boolean
End Class
With nRepair
.repairID = row.Cells("RepairID").Value
.techID = row.Cells("TechID").Value
.repairCodeID = row.Cells("RepairCodeID").Value
.acceptedDate = row.Cells("AcceptedDate").Value
.remarks = row.Cells("Remarks").Value
.isComplete = row.Cells("IsComplete").Value
End With

Related

Variable that depends on another variable VBA

I have an interesting question about referencing another variable based on another variable in an array.
Below is my code:
Dim company, price, sdev, mean, random
Dim companies
companies = Array("mm", "tgt", "boog")
mm_price = 0
mm_mean = 0
mm_sdev = 0
tgt_price = 0
tgt_mean = 0
tgt_sdev = 0
boog_price = 0
boog_mean = 0
boog_sdev = 0
For i = 1 To 3
company = companies(i)
mean = company & "_mean"
sdev = company & "_sdev"
Next i
Now, the issue occurs when I attempt to define the "mean" and "sdev" variables, as they will not use the "0" value, but instead give it the string name "mm_mean" etc. mm_mean = 0, therefore, I want mean = 0 when i = 1. Clear?
Thanks, and let me know. It is a rather strange question, and the code is cut from many different functions, so if it doesn't make sense as to why I am doing this, my apologies. I tried to make it as simple as possible so it wouldn't confuse the answerer.
This is a good example of when custom data-structures (aka "record types", "structs") should be used to group related data together. In VBA the syntax is Type:
Type Company
Name As String
Price As Currency
Mean As Double
SDev As Double
End Type
Public Sub CalculateCompanyInfo()
Dim companies(3) As Company
companies(0).Name = "mm"
companies(0).Price = 123
companies(1).Name = "tgt"
companies(1).Price = 456
companies(2).Name = "boog"
companies(2).Price = 789
For i As Integer = 0 to UBound(companies)
companies(i).Mean = ...
companies(i).SDev = ...
Next i
End Sub
Where ... means whatever custom calculation you need to do to get that value.

Poker Hand evaluation through LINQ

I am creating a poker game - Texas Holdem (5 cards on the table and 2 cards for myself).
I've already created flush, straight and straight flush functions and I got stuck on evaluating if the hand has a:
1. Four of a kind
2. Three of a kind
3. Full house
4. Two pairs
5. One pair
I believe I can write one function for all of the above, that will return a corresponding string.
I have created a list that holds list of Cards (7 cards)
Class Card has a property cardNumber of Integer type (Ace = 1, Two = 2, Three = 3 etc)
Here is my function:
Public Shared Function ofAKind(hand As List(Of Card)) As String
Dim result As String = ""
Dim counter As Integer
Dim IntegerList As New List(Of Integer)
'creating a list of integers that are representing faces of cards
Do
IntegerList.Add(hand.Item(counter).cardNumber)
counter += 1
Loop Until counter = hand.Count
Dim groupedIntegers = From Int In IntegerList
Group By Int
Into grouping = Group, Count()
'and here is my problem: how can I make such a grouping? below is just pseudocode.
'When using a debugger, I see that it groups them well. It is just that I do not know
'how to use LINQ to extract that grouping into the below if statement and get a corresponding string.
'if grouping = 4 Then
'result = "Four of a kind"
'if grouping = 3 andAlso grouping = 2 Then
'result = "Full House"
'if grouping = 2 andAlso grouping = 2 Then
'result = "Two Pairs"
'if grouping = 2 Then
'result = "Pair"
Return result
End Function
For the lack of being able to comment.
Possibly String.Concat all of the card Values together (with whitespace in-between each) and use a Regex.Matches(...) with match code "\d" to match the Numbers
Then Array.ForEach(...) for the Groups() with an in-line If[...] to count the occurrences in each group and test if it has particular combinations of matches.
It may be a little tedious, and a long in-line Linq, but just a thought :p
I figured it out. I am sure it can be done in a cleaner way, but it worked for me. At this phase of my programming discovery - this is a next milestone achieved. Thanks to Plutonix. Appreciate it.
Public Function ofAKind(IntegerList As List(Of Integer)) As String
Dim result As String = "YES"
Dim groupedIntegerList As New List(Of Integer)
Dim groupedIntegers = From Int In IntegerList
Group By Int
Into LOL = Group, Count()
'creating another list (I am sure there is a cleaner way, but I don't know it yet)
For Each e In groupedIntegers
groupedIntegerList.Add(e.Count)
Next
If groupedIntegerList.Contains(3) And groupedIntegerList.Contains(2) Then
result = "Fullhouse!"
ElseIf groupedIntegerList.Contains(4) Then
result = "Four of a kind!"
ElseIf groupedIntegerList.Contains(3) Then
result = "Three of a kind"
ElseIf groupedIntegerList.Contains(2) Then
result = "Pair!"
End If
'ugly way to search for two pairs (but it works)
If result = "Pair!" Then
Dim searchingForTwoPairs = From int In groupedIntegerList
Where int > 1
Group By int
Into LOL2 = Group, Count()
Dim twoPairsList As New List(Of Integer)
For Each e In searchingForTwoPairs
twoPairsList.Add(e.Count)
Next
If twoPairsList.Contains(2) Or twoPairsList.Contains(3) Then
result = "Two pairs!"
End If
End If
Return result
End Function

Base data sheet form will not display calculated Field

I have a Data Sheet form which has a calculated field column. However the field will not display even though it has the correct value. The field in question is "numRisk":
Sub Calculate_Risk (Form As Object)
Dim OrderPrice, IfDonePrice, TotBrSymComm, BrComm, Risk As Double
Dim Symbol As String
Dim IntRateMult, noContracts As Integer
If MinTick = 0 OR Rate = 0 Then
Exit Sub
End If
Symbol = RTrim(Form.getByName("txtSymbol").CurrentValue)
If Symbol = "" Then
Exit Sub
End If
OrderPrice = Form.getByName("fmtOrder_Price").CurrentValue
IfDonePrice = Form.getByName("fmtIf_Done_Price").CurrentValue
noContracts = Form.getByName("fmtNo_Contracts").CurrentValue
If NOT USIntRates Then
Risk = ABS(OrderPrice - IfDonePrice) / MinTick
Else
Risk = ABS(OrderPrice\1 - IfDonePrice\1) * MinTick
IntRateMult = IIf(Symbol = "FV" OR Symbol = "TU",400, 200)
Risk = ABS(Risk - IntRateMult * ABS(OrderPrice - OrderPrice\1
IfDonePrice + IfDonePrice\1))
End If
Risk = Risk * MinTickVal / Rate
TotBrSymComm = BrSymComm + BrSymCommAud
BrComm = IIf(TotBrSymComm = 0, BrCommission, BrSymCommAud + BrSymComm/Rate)
Risk = noContracts*(Risk + BrComm * 2)
Form.getByName("numRisk").Value = Risk
End Sub
The subroutine is called from the following routine which is triggered when the form is loaded:
Sub FromListForm(Event as Object)
Dim Form As Object
Dim TodaysDate As New com.sun.star.util.Date
Dim CurrDate As Date
Form=Event.Source.getByName("MainForm_Grid")
Form.RowSet.first()
Do Until Form.RowSet.isAfterLast()
Get_Contract(Form)
Get_Broker_Comm(Form)
Calculate_Risk(Form)
If isEmpty(Form.getByName("OrderDate").Date) Then
CurrDate = Date()
TodaysDate.Day = Day(CurrDate)
TodaysDate.Month = Month(CurrDate)
TodaysDate.Year = Year(CurrDate)
Form.getByName("OrderDate").CurrentValue = TodaysDate
End If
Form.RowSet.next()
Loop
Form.RowSet.last()
End Sub
Also is there a more efficient method to cycle through the rows? As this seems so slow I can see the row pointer moving down the table as each row is processed.
If I understand correctly, you're trying to enter individual values into each cell in a column of a tablegrid control? I don't believe that's possible.
Inside a tablegrid control, all values have to come from the underlying query. I recommend writing a query to do these calculations, and using that query as the basis for the form - that would solve both the problem of displaying the calculated result as well as improving the load speed of the form (since database logic in determining query results is almost always more efficient than a macro going row-by-row).
Alternately, you could have the calculated field be standalone, showing only the calculated result for the currently selected row of the tablegrid control. In this scenario, the "form loaded" event would only do the calculation for the first row, and the calculating macro would be triggered each time the row selection changed.

Variant Join in MS Access

I am converting a spreadsheet that had over 80 Sumifs for output.
For a query, I can join 2 tables, but they depend on 6-8 factors that aren't consistent, hence, the sumifs.
I've been successful with right joins in some instances, but most of the time I have to piece meal all of the conditions.
One of my approaches is to write a function like this:
Public Function DetermineCOB_ID(strFund As String, strType As String, strMDEP As String, _
strTier1 As String, strAirGround As Variant, strAcctType As String) As Integer
If strFund = "A82AB" And strType = "Base" And strTier1 = "2 BCT" And strMDEP = "W25D" And strAcctType = "Subordinate_Cmds" Then
DetermineCOB_ID = 1
ElseIf strFund = "A82AC" And strType = "Base" And strMDEP = "W25D" And strAcctType = "Subordinate_Cmds" Then
DetermineCOB_ID = 2
ElseIf strFund = "A82AD" And strType = "Base" And strMDEP = "W25D" And strAirGround = "Ground" And strAcctType = "Subordinate_Cmds" Then
DetermineCOB_ID = 3
Else
DetermineCOB_ID = 0
End If
End Function
But I will have to write 80 separate ElseIf statements.
I'd like to hook up my logic to a control table that the user can change the factors that determine the values.
This would somehow involve a 'variant' join everywhere there is a join where one is not required. I hope I am making sense.
Is there another approach to solving this problem?
Yes, I am working with a back end that leaves a lot to be desired. In the interim, I'm probing for alternate solutions. Do you know a way to make a join respond like a variant variable i.e so it can work with null values. I've tried outer joins but it doesn't really work.

Datagridview optimization VB.Net

I just want to ask if there is another alternative for filling up the cells in the datagridview. Currently I'm using this code :
For i = DataGridView1.CurrentCell.RowIndex To x - 1
DataGridView1.Rows(i).Cells("LastName").Value = empcoll.Item(i).LastName
DataGridView1.Rows(i).Cells("FirstName").Value = empcoll.Item(i).FirstName
DataGridView1.Rows(i).Cells("MiddleName").Value = empcoll.Item(i).MiddleName
DataGridView1.Rows(i).Cells("CreatedBy").Value = empcoll.Item(i).CreatedBy
DataGridView1.Rows(i).Cells("CreateDate").Value = empcoll.Item(i).CreateDate
DataGridView1.Rows(i).Cells("Status").Value = empcoll.Item(i).Status
DataGridView1.Rows(i).Cells("DailySalary").Value = empcoll.Item(i).DailySalary
DataGridView1.Rows(i).Cells("BirthDate").Value = empcoll.Item(i).BirthDate
Next i
but when I use it for databases with a large number of records, it tends to load slow and hangs up.
You can use the SQLDataSource control (http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.sqldatasource.aspx) and then bind the DataGridView to the SQLDataSource. It is described here: http://www.vkinfotek.com/gridview/bind-gridview-sqldatasource-control.html.
In general, you should be Data Binding the columns to the properties on the objects instead of the method you're currently using.
It would look something like this
LastNameColumn.DataPropertyname = "LastName"
FirstNameColumn.DataPropertyname = "FirstName"
....
DataGridView1.DataSource = MyListofEmployeeObjects
As far as the load speed, there are two options: pagination, and virtual mode.
With pagination, you can pull X of Y records from the database at a time and display them in the grid.
Virtual mode ( http://msdn.microsoft.com/en-us/library/ms171622.aspx ) enables the DataGridView to handle automatic pulling/pushing of the records from/to the database so that you do not have to load all records at once.
Well, I prefer to use the DatagridView.Rows.Add method for unbounded DataGridViews.
Something like this:
Dim loData(7) as object
DataGridView1.Rows.Clear()
For i = DataGridView1.CurrentCell.RowIndex To x - 1
loData(0) = empcoll.Item(i).LastName
loData(1) = empcoll.Item(i).FirstName
loData(2) = empcoll.Item(i).MiddleName
loData(3) = empcoll.Item(i).CreatedBy
loData(4) = empcoll.Item(i).CreateDate
loData(5) = empcoll.Item(i).Status
loData(6) = empcoll.Item(i).DailySalary
loData(7) = empcoll.Item(i).BirthDate
DataGridView1.Rows.Add(loData)
Next i
I usually declare en enum to give a meaning name to each array element and make the code cleaner:
private enum eCols
LastName
Firstname
MiddleName
CreatedBy
CreateDate
Status
DailySalary
BirthDate
end enum
Dim loData(7) as object
DataGridView1.Rows.Clear()
For i = DataGridView1.CurrentCell.RowIndex To x - 1
loData(eCol.LastName) = empcoll.Item(i).LastName
loData(eCol.FirstName) = empcoll.Item(i).FirstName
loData(eCol.MiddleName) = empcoll.Item(i).MiddleName
loData(eCol.CreatedBy) = empcoll.Item(i).CreatedBy
loData(eCol.CreateDate) = empcoll.Item(i).CreateDate
loData(eCol.Status) = empcoll.Item(i).Status
loData(eCol.DailySalary) = empcoll.Item(i).DailySalary
loData(eCol.BirthDate) = empcoll.Item(i).BirthDate
DataGridView1.Rows.Add(loData)
Next i