Solved

How can I split the Maximum Value of a NumericUpDown Control over several controls?

Posted on 2007-08-03
368 Views
This is something that, when I first undertook it, I thought would be extremely easy.  Now, I've been working on it for 14 hours straight, I've tried dozens, if not hundreds of different ways to accomplish it, and it's still not working.    I'm about ready to throw my computer at something big and solid.

Ok, now that I'm done ranting (for now), here's my problem.  I have eight NumericUpDown Controls.  Each of these controls has a maximum value of 100.  However, only one control can actually have a value of 100.  (If this is confusing, let me know. It's confusing me as I try to type it.)  All of the controls can have a value of 60, but then there are only 40 points which can be split between the controls.  (i.e. on control's value = 100, and all other controls' values = 60, or two controls = 80, and all other controls = 60, or one control = 65, one control = 70, one control = 75, and five controls = 60 with 10 points left to distribute.)  The maximum value does not have to be met.  I can have 5 controls with a value of 0, and one control with a value of 10 if I want.

The numberupdown controls names are:  WWlvl, CClvl, GSlvl, BSlvl, BClvl, LClvl, Cooklvl, and Alclvl

The closest I've come to accomplishing this so far has been to have the numericupdowns call the following procedure on the ValueChanged event:

Private Sub LevelValues()

Dim MaxValue As Integer = 40

If GSlvl.Value <= 60 And WWlvl.Value <= 60 And BSlvl.Value <= 60 And Cooklvl.Value <= 60 And Alclvl.Value <= 60 _
And BClvl.Value <= 60 And LClvl.Value <= 60 And CClvl.Value <= 60 Then

gslvl.

GSlvl.Maximum = 100
WWlvl.Maximum = 100
BSlvl.Maximum = 100
Cooklvl.Maximum = 100
Alclvl.Maximum = 100
BClvl.Maximum = 100
LClvl.Maximum = 100
CClvl.Maximum = 100

Else
If GSlvl.Value > 60 Then
WWlvl.Maximum = MaxValue - (100 - GSlvl.Value)
BClvl.Maximum = 60 + MaxValue
BSlvl.Maximum = 60 + MaxValue
LClvl.Maximum = 60 + MaxValue
CClvl.Maximum = 60 + MaxValue
Alclvl.Maximum = 60 + MaxValue
Cooklvl.Maximum = 60 + MaxValue
End If
If WWlvl.Value > 60 Then
MaxValue = MaxValue - (100 - WWlvl.Value)
GSlvl.Maximum = 60 + MaxValue
BClvl.Maximum = 60 + MaxValue
BSlvl.Maximum = 60 + MaxValue
LClvl.Maximum = 60 + MaxValue
CClvl.Maximum = 60 + MaxValue
Alclvl.Maximum = 60 + MaxValue
Cooklvl.Maximum = 60 + MaxValue
End If
If BClvl.Value > 60 Then
MaxValue = MaxValue - (100 - BClvl.Value)
WWlvl.Maximum = 60 + MaxValue
GSlvl.Maximum = 60 + MaxValue
BSlvl.Maximum = 60 + MaxValue
LClvl.Maximum = 60 + MaxValue
CClvl.Maximum = 60 + MaxValue
Alclvl.Maximum = 60 + MaxValue
Cooklvl.Maximum = 60 + MaxValue
End If
If BSlvl.Value > 60 Then
MaxValue = MaxValue - (100 - BSlvl.Value)
WWlvl.Maximum = 60 + MaxValue
BClvl.Maximum = 60 + MaxValue
GSlvl.Maximum = 60 + MaxValue
LClvl.Maximum = 60 + MaxValue
CClvl.Maximum = 60 + MaxValue
Alclvl.Maximum = 60 + MaxValue
Cooklvl.Maximum = 60 + MaxValue
End If
If LClvl.Value > 60 Then
MaxValue = MaxValue - (100 - LClvl.Value)
'WWlvl.Maximum = 60 + MaxValue
'BClvl.Maximum = 60 + MaxValue
'BSlvl.Maximum = 60 + MaxValue
'GSlvl.Maximum = 60 + MaxValue
'CClvl.Maximum = 60 + MaxValue
'Alclvl.Maximum = 60 + MaxValue
'Cooklvl.Maximum = 60 + MaxValue
End If
If CClvl.Value > 60 Then
MaxValue = MaxValue - (100 - CClvl.Value)
WWlvl.Maximum = 60 + MaxValue
BClvl.Maximum = 60 + MaxValue
BSlvl.Maximum = 60 + MaxValue
LClvl.Maximum = 60 + MaxValue
GSlvl.Maximum = 60 + MaxValue
Alclvl.Maximum = 60 + MaxValue
Cooklvl.Maximum = 60 + MaxValue
End If
If Cooklvl.Value > 60 Then
MaxValue = MaxValue - (100 - Cooklvl.Value)
WWlvl.Maximum = 60 + MaxValue
BClvl.Maximum = 60 + MaxValue
BSlvl.Maximum = 60 + MaxValue
LClvl.Maximum = 60 + MaxValue
CClvl.Maximum = 60 + MaxValue
Alclvl.Maximum = 60 + MaxValue
GSlvl.Maximum = 60 + MaxValue
End If
If Alclvl.Value > 60 Then
MaxValue = MaxValue - (100 - Alclvl.Value)
WWlvl.Maximum = 60 + MaxValue
BClvl.Maximum = 60 + MaxValue
BSlvl.Maximum = 60 + MaxValue
LClvl.Maximum = 60 + MaxValue
CClvl.Maximum = 60 + MaxValue
GSlvl.Maximum = 60 + MaxValue
Cooklvl.Maximum = 60 + MaxValue
End If
End If

End Sub

This sub seems to work ok at first, If I have one control at 100, and change another to 61, the first one drops to 99.  but then it doesn't drop to 98 until the second is at 63, which exceeds the 100 total.

I know there has to be an easier way to do this, and probably with a lot less code.  I'm very open to suggestions right now.

Thank you,
~Skid
0
Question by:Skidwiz

LVL 53

Expert Comment

I've got some questions:
Is there a maximum value for all controls together ?
Fe: 100 + 60 + 60 + 60 + 60 + 60 = 400
100 + 80 + 80 + 60 + 40 + 40 = 400
...
0

LVL 6

Expert Comment

I'm not 100% sure I understood your goal, but this might just do it(make sure the NumericUpDown Controls have their Maximum set to 100, and their Minimum set to 0:

Private Const MAX_VALUE As Integer = 520

Private Sub Counter_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles WWlvl.ValueChanged, CClvl.ValueChanged, GSlvl.ValueChanged, BSlvl.ValueChanged, BClvl.ValueChanged, LClvl.ValueChanged, Cooklvl.ValueChanged, Alclvl.ValueChanged

Dim allocated, available As Integer

allocated = WWlvl.Value + CClvl.Value + GSlvl.Value + BSlvl.Value + BClvl.Value + LClvl.Value + Cooklvl.Value + Alclvl.Value
available = MAX_VALUE - allocated

If allocated >= MAX_VALUE Then
FreezeCounters()
Else
UnfreezeCounters()
End If

End Sub

Private Sub FreezeCounters()
WWlvl.Maximum = WWlvl.Value
CClvl.Maximum = CClvl.Value
GSlvl.Maximum = GSlvl.Value
BSlvl.Maximum = BSlvl.Value
BClvl.Maximum = BClvl.Value
LClvl.Maximum = LClvl.Value
Cooklvl.Maximum = Cooklvl.Value
Alclvl.Maximum = Alclvl.Value
End Sub

Private Sub UnfreezeCounters()
WWlvl.Maximum = 100
CClvl.Maximum = 100
GSlvl.Maximum = 100
BSlvl.Maximum = 100
BClvl.Maximum = 100
LClvl.Maximum = 100
Cooklvl.Maximum = 100
Alclvl.Maximum = 100
End Sub
0

LVL 6

Expert Comment

A couple of notes:

- The MAX_VALUE variable is a constant global integer. I assumed that the maximum allowed sum of all the NumericUpDown Controls was 520.
- I recommend setting the ReadOnly Property of the controls to True(because keyboard input limits need to be handled separately, did the user type in a value which was too big)
- Counter_ValueChanged handles the ValueChanged Event of all the NumericUpDownControls. There is no need to know which one was changed.
0

LVL 5

Accepted Solution

Does this do what you want ?

Private Sub upd_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles WWlvl.ValueChanged, CClvl.ValueChanged, GSlvl.ValueChanged, BSlvl.ValueChanged, BClvl.ValueChanged, LClvl.ValueChanged, Cooklvl.ValueChanged, Alclvl.ValueChanged
If Not m_blnChanging Then LevelValues(sender)
End Sub

Private Sub LevelValues(ByVal sender As System.Windows.Forms.NumericUpDown)
m_blnChanging = True

Dim intAbove60 As Integer = 0

If GSlvl.Value <= 60 And WWlvl.Value <= 60 And BSlvl.Value <= 60 And Cooklvl.Value <= 60 And Alclvl.Value <= 60 _
And BClvl.Value <= 60 And LClvl.Value <= 60 And CClvl.Value <= 60 Then
' Do nothing
Else
For Each ctrControl As System.Windows.Forms.Control In Me.Controls
If TypeOf ctrControl Is System.Windows.Forms.NumericUpDown Then
If CType(ctrControl, System.Windows.Forms.NumericUpDown).Value > 60 And ctrControl.Name <> sender.Name Then
intAbove60 += CType(ctrControl, System.Windows.Forms.NumericUpDown).Value - 60
End If
End If
Next

If sender.Value > 60 Then
If sender.Value > 100 - intAbove60 Then
sender.Value = 100 - intAbove60
End If
End If
End If

m_blnChanging = False
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
GSlvl.Maximum = 100
WWlvl.Maximum = 100
BSlvl.Maximum = 100
Cooklvl.Maximum = 100
Alclvl.Maximum = 100
BClvl.Maximum = 100
LClvl.Maximum = 100
CClvl.Maximum = 100
End Sub
0

LVL 1

Author Comment

There isn't a maximum value for all controls together.  Each control can equal any number 1-60.  But, above 60, there are only 40 points available to be split among all the controls, are be assigned to just one.  No control can equal more then 100.

So, using an example, let's say the user clicks the first control, and takes it's value to 60.  At this point all controls still have a max value of 100.  User then takes the second control to 65.  Now, because that control is 5 points over 60, it takes 5 points away from 100.  So, now all other controls' max value is set to 95.  The user then takes the third controls' value to 72.  Now all other controls' max value is 83, because user used 12 more points.  User then takes controls four and five both to 66, using the last 12 available points.  Now, the five controls' values (60, 65, 72, 66, and 66 are set at their maximum values.  However, the last three controls, which are still set at 0, can be adjusted anywhere from 0 - 60, with their max value set at 60.

From here, user decides that the third control (72) is to high, and lowers it to 69.  Now three points just became available for the other 7 controls to use, thereby raising their max value by three.  The control that was 72, and is now 69, doesn't need three points added to it's max, because they are already there.

Does that make it more clear?  I know it's a little confusing, and I'm sorry for it.
0

LVL 1

Author Comment

Ok, I just looked at that last post, and my math sucks for that example.  ok, user takes first control to 60, which doesn't effect the max value, because it isn't above 60, so all controls still have max of 100.

User takes second control to 65.  This is 5 points above 60, which takes 5 points away from the total 40 points available above 60, making 40 = 35.  So now, each control's max is 95, except for the first one, which still has a max value of 100 (because it also still has those 35 points available, plus the 5 points already used.)

User takes third control to 75.  This uses 15 points of the max value above 60, taking the 35 down to 20.  So now, the control set to 65 has a max value of 85 (because of it's 5 points used, plus the still available 20 points.), the control set to 75 has a max value of 95 (because of it's 15 used, plus the available 20), and all other controls have a max of 80 (because they haven't used any points yet, and there are 20 of the 40 points still un-used.)

If the user then lowers the 75 control to 65, 10 points are given back to the max available points above 60, which raises the max of the second control (value of 65) to 95, leaves the third control value at 95, and takes all other controls max from 80 to 90.

It shouldn't round up or down, because there's 40 points, period.  Not 41, and not 39.

Once again, sorry about the lousy math in my last post.  I just woke up.
0

LVL 1

Author Comment

Bart-De-Bal,

I'm sorry, I posted the above comments before I had the opportunity to check the code.  I was just answering the questions from the other posters.  You're code did exactly what I needed.  It's perfect.  Thank you.
0

Featured Post

The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
Enums (shorthand for ‘enumerations’) are not often used by programmers but they can be quite valuable when they are.  What are they? An Enum is just a type of variable like a string or an Integer, but in this case one that you create that contains…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…