Solved Calculated Controls (1 Viewer)

silversun

Registered User.
Local time
Today, 10:14
Joined
Dec 28, 2012
Messages
204
Hi,
I have a simple bounded form. There are three controls (A, B & F) in my form bonded to three fields of a table.
A = Gas price $/litter
B = Amount of gas, litter
F = Total value of the gas
F = A x B
Assume user enters the gas price (A) in the first control and amount of gas in the second one (B). A simple VBA can calculate (multiply) these two numbers and send the result to the last control (F). My question here is how to write a VBA code or query that always calculates the third value out of any two given numbers. I mean if user enters the total amount (F) and the gas price per litter (A) then the code will calculate the amount of gas (B) which is B=F/A.
It should always calculate the third operand once two of them are entered.
F=A*B
A=F/B
B=F/A

I think it is clear enough. Please let me know if it isn't.
Masoud
Thank you for your help
 

ypma

Registered User.
Local time
Today, 18:14
Joined
Apr 13, 2012
Messages
643
I tried a command button to obtain the three different results .
Code:
Private Sub Command3_Click()
If (IsNull([ValueofGas])) Then
  ValueofGas = amountGas * Gasprice
 
ElseIf (IsNull([Gasprice])) Then
   Me.Gasprice = Me.ValueofGas / Me.amountGas

ElseIf (IsNull([amountGas])) Then
   Me.amountGas = Me.ValueofGas / Me.Gasprice
End If
End Sub

Not sure how you wish to trigger the desired outcome

Regards Ypma user not a professional
 

bob fitz

AWF VIP
Local time
Today, 18:14
Joined
May 23, 2011
Messages
4,721
Saving calculations is not usually considered to be "good practice".
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 18:14
Joined
Jul 9, 2003
Messages
16,280
I agree with Bob you shouldn't be doing this! Because you are storing data in the table, and any changes to that data will damage the integrity of your data. Having said that, I fancied a bit of a challenge this morning so I had a go and here's my solution:-
 

Attachments

  • Calculated Controls_1a.zip
    325.4 KB · Views: 244

Pat Hartman

Super Moderator
Staff member
Local time
Today, 13:14
Joined
Feb 19, 2002
Messages
43,257
The simplest solution is to bind the form to a query rather than the table and that will allow you to have a calculated field
Select A, B, A * B as F
From yourtable.

F will automagically change when you change the value of A or B. It will not be saved. It does not need to be as the others have pointed out. Just calculate it in your query whenever you need it.
 

ypma

Registered User.
Local time
Today, 18:14
Joined
Apr 13, 2012
Messages
643
Pat ,my understanding of the question was that result of any one of the three fields in question could be calculated using the data from the other two fields . You state that F will automatically change but , no mention of other scenario where F and A are given to provide B . Does your solution cover all three calculation. ? is so I would appreciate and example of how this would work without having any of the fields bound.to a table .

Respectfully Ypma
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 18:14
Joined
Jul 9, 2003
Messages
16,280
how this would work without having any of the fields bound.to a table .

Your original question, (which I must say was very clear and well written which was one of the reasons i provided an answer) stated that the controls are bound. I am now confused.
 

Gasman

Enthusiastic Amateur
Local time
Today, 18:14
Joined
Sep 21, 2011
Messages
14,264
I only store the mileage, amount of fuel and the total cost and let Excel work out the price. Access will do the same thing. ?
 

ypma

Registered User.
Local time
Today, 18:14
Joined
Apr 13, 2012
Messages
643
Your original question, (which I must say was very clear and well written which was one of the reasons i provided an answer) stated that the controls are bound. I am now confused.
Uncle Gizmo, thank you for the courtesy of replying , you are confused as I did not pose the original question but tried with my limited knowledge to provide a solution. The reasons why silverson wanted the scenario is not clear to me. Regretfully I could not get your example to work , yes you were clear about the controls being bound in your demo. Maybe I am missing something but, could this scenario be an exception to rule concerning calculated fields , we are not talking a about A * B = C , but the permutation of 3 possible results .

Regards Ypma
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 18:14
Joined
Jul 9, 2003
Messages
16,280
Regretfully I could not get your example to work

I'm not sure why the solution I provide doesn't work for you. Possibly you are using an earlier version of Microsoft Access. If that's the case, these are the instructions for recreating my solution.

You need a table with the following Fields, as number - double format, (accept for "ID" which is an auto number)

ID F1 F2 F3
1 1000 3 3000
2 5 5 25
3 4 2.5 1
4 56 67 3752
5 6 6 36
6 30 100 3000
7 8 1000 8000

You need a form with 3 text boxes named F1 F2 and F3. These text boxes should be linked to the corresponding fields in the table.

Then you will need the following code in the forms code module:-

Code:
Option Compare Database
Option Explicit

Private Function fFill_MT_Field()

Dim intCtrlFilledCount As Integer
Dim Ctrl As Control

    For Each Ctrl In Me.Controls
        Select Case Ctrl.ControlType
            Case acTextBox
            If Left(Ctrl.Name, 1) = "F" Then
                          
                If Ctrl.Value > 0 Then
                    intCtrlFilledCount = intCtrlFilledCount + 1
                End If

            End If
        End Select
    Next Ctrl

        If intCtrlFilledCount = 1 Then
            MsgBox ">>> " & "Need to Fill Another"
            Exit Function
        End If

            If intCtrlFilledCount = 3 Then
                MsgBox ">>> " & "DO Nothing, ALL Filled"
                Exit Function
            End If
          
                If intCtrlFilledCount = 2 Then
              
                        Select Case fGetCtrlZero
                            Case "F1"
                            Me.F1 = Me.F3 / Me.F2
                          
                            Case "F2"
                            Me.F2 = Me.F3 / Me.F1
                      
                            Case "F3"
                            Me.F3 = Me.F1 * Me.F2
                        End Select
              
                    Exit Function
                End If
              
End Function      'fFill_MT_Field

Private Function fGetCtrlZero() As String

Dim Ctrl As Control

    For Each Ctrl In Me.Controls
        Select Case Ctrl.ControlType
            Case acTextBox
            If Left(Ctrl.Name, 1) = "F" Then
                          
                If Ctrl.Value = 0 Then
                    fGetCtrlZero = Ctrl.Name
                End If

            End If
        End Select
    Next Ctrl

End Function      'fGetCtrlZero

Private Sub btnReset_Click()
    Me.F1 = 0
    Me.F2 = 0
    Me.F3 = 0
End Sub      'btnReset_Click

If you were to recreate this example in your particular version of MS Access and post it on the forum, it would be most helpful to others..

Update:-
I've cleaned up the code, added a reset button, changed the afterupdate events to call the function directly ..

See updated example attached....
 

Attachments

  • Calculated Controls_2a.zip
    318.6 KB · Views: 244
Last edited:

ypma

Registered User.
Local time
Today, 18:14
Joined
Apr 13, 2012
Messages
643
I'm not sure why the solution I provide doesn't work for you. Possibly you are using an earlier version of Microsoft Access. If that's the case, these are the instructions for recreating my solution.

You need a table with the following Fields, as number - double format, (accept for "ID" which is an auto number)

ID F1 F2 F3
1 1000 3 3000
2 5 5 25
3 4 2.5 1
4 56 67 3752
5 6 6 36
6 30 100 3000
7 8 1000 8000

You need a form with 3 text boxes named F1 F2 and F3. These text boxes should be linked to the corresponding fields in the table.

Then you will need the following code in the forms code module:-

Code:
Option Compare Database
Option Explicit

Private Function fFill_MT_Field(oText As TextBox) As String

Dim conAppName As String
conAppName = "(Replace this Local Variable with a Global One) "

Dim strSubName As String
Dim strModuleName As String

strSubName = "fFill_MT_Field"
strModuleName = "Form - " & Me.Name
'strModuleName = "Module - basModuleName"

On Error GoTo Error_Handler

Dim intCtrlFilledCount As Integer
Dim Ctrl As Control

    For Each Ctrl In Me.Controls
        Select Case Ctrl.ControlType
            Case acTextBox
            If Left(Ctrl.Name, 1) = "F" Then
                           
                If Ctrl.Value > 0 Then
                    intCtrlFilledCount = intCtrlFilledCount + 1
                End If

            End If
        End Select
    Next Ctrl

        If intCtrlFilledCount = 1 Then
            MsgBox ">>> " & "Need to Fill Another"
            Exit Function
        End If

            If intCtrlFilledCount = 3 Then
                MsgBox ">>> " & "DO Nothing, ALL Filled"
                Exit Function
            End If
           
                If intCtrlFilledCount = 2 Then
               
                        Select Case fGetCtrlZero
                            Case "F1"
                            Me.F1 = Me.F3 / Me.F2
                           
                            Case "F2"
                            Me.F2 = Me.F3 / Me.F1
                       
                            Case "F3"
                            Me.F3 = Me.F1 * Me.F2
                        End Select
               
                    Exit Function
                End If
       
Exit_ErrorHandler:
    'adoCon.Close
    'Set adoCon = Nothing
    'Set adoCmd = Nothing
   
    Exit Function

Error_Handler:  'Version - 1a
    Dim strErrFrom As String
    Dim strErrInfo As String
       
        strErrFrom = "Error From:-" & vbCrLf & strModuleName & vbCrLf & "Subroutine >>>>>>> " & strSubName
        strErrInfo = "" & vbCrLf & "Error Number >>>>> " & Err.Number & vbCrLf & "Error Descscription:-" & vbCrLf & Err.Description
           
            Select Case Err.Number
                Case 0.123 'When Required, Replace Place Holder (0.123) with an Error Number
                    MsgBox "Error produced by Place Holder please check your code!" & vbCrLf & vbCrLf & strErrFrom & strErrInfo, , conAppName
                Case Else
                    MsgBox "Case Else Error" & vbCrLf & vbCrLf & strErrFrom & strErrInfo, , conAppName
            End Select
        Resume Exit_ErrorHandler

End Function      'fFill_MT_Field

Private Function fGetCtrlZero() As String

Dim conAppName As String
conAppName = "(Replace this Local Variable with a Global One) "

Dim strSubName As String
Dim strModuleName As String

strSubName = "fGetCtrlZero"
strModuleName = "Form - " & Me.Name
'strModuleName = "Module - basModuleName"

On Error GoTo Error_Handler

Dim Ctrl As Control

    For Each Ctrl In Me.Controls
        Select Case Ctrl.ControlType
            Case acTextBox
            If Left(Ctrl.Name, 1) = "F" Then
                           
                If Ctrl.Value = 0 Then
                    fGetCtrlZero = Ctrl.Name
                End If

            End If
        End Select
    Next Ctrl
       
Exit_ErrorHandler:
    'adoCon.Close
    'Set adoCon = Nothing
    'Set adoCmd = Nothing
   
    Exit Function

Error_Handler:  'Version - 1a
    Dim strErrFrom As String
    Dim strErrInfo As String
       
        strErrFrom = "Error From:-" & vbCrLf & strModuleName & vbCrLf & "Subroutine >>>>>>> " & strSubName
        strErrInfo = "" & vbCrLf & "Error Number >>>>> " & Err.Number & vbCrLf & "Error Descscription:-" & vbCrLf & Err.Description
           
            Select Case Err.Number
                Case 0.123 'When Required, Replace Place Holder (0.123) with an Error Number
                    MsgBox "Error produced by Place Holder please check your code!" & vbCrLf & vbCrLf & strErrFrom & strErrInfo, , conAppName
                Case Else
                    MsgBox "Case Else Error" & vbCrLf & vbCrLf & strErrFrom & strErrInfo, , conAppName
            End Select
        Resume Exit_ErrorHandler

End Function      'fGetCtrlZero

Private Sub F1_AfterUpdate()
    Call fFill_MT_Field(F1)
End Sub

Private Sub F2_AfterUpdate()
    Call fFill_MT_Field(F2)
End Sub

Private Sub F3_AfterUpdate()
    Call fFill_MT_Field(F3)
End Sub

If you were to recreate this example in your particular version of MS Access and post it on the forum, it would be most helpful to others..
Uncle Gizmo, I revisited your demo and when I tabbed to a new record it produce the required results , I was trying change the figures on the records your created , with no results and assumed it was not liking my version. I was impressed with your script and will learn from it, for any of my future endeavours . Thank again and keep safe.

Regards Ypma
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 13:14
Joined
Feb 19, 2002
Messages
43,257
I ignored the over-the-top situation. Unless there is some really strange situation, pick two of the three values, make those required, and always calculate the third. I would be surprised if the user actually needed this flexibility. If he does, Uncle was very kind and provided code which I'm assuming works.
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 18:14
Joined
Jul 9, 2003
Messages
16,280
Uncle was very kind and provided code

I think I've got lockdown itis. I'm bored out of my skull, I am snapping at everybody for no reason. I have to be careful what I say to people, even on the forum here! I find it necessary to answer the interesting questions here because it helps me maintain what little sanity I have left.
 

silversun

Registered User.
Local time
Today, 10:14
Joined
Dec 28, 2012
Messages
204
The simplest solution is to bind the form to a query rather than the table and that will allow you to have a calculated field
Select A, B, A * B as F
From yourtable.

F will automagically change when you change the value of A or B. It will not be saved. It does not need to be as the others have pointed out. Just calculate it in your query whenever you need it.
Can you please explain with an example. I was not able to create the desired query.
Thank you
 

silversun

Registered User.
Local time
Today, 10:14
Joined
Dec 28, 2012
Messages
204
I ignored the over-the-top situation. Unless there is some really strange situation, pick two of the three values, make those required, and always calculate the third. I would be surprised if the user actually needed this flexibility. If he does, Uncle was very kind and provided code which I'm assuming works.
Lets assume user needs to enter hundreds of gas receipts into a table. Some of them are old enough to have faded one of the values but other two are readable. In this situation one solution is to use a calculator and always obtain two operands and let a simple VBA calculate the total or have the form to do that in a smart way. That's why I need to find the simplest and most efficient way.
Thank you for helping me
 

silversun

Registered User.
Local time
Today, 10:14
Joined
Dec 28, 2012
Messages
204
I tried a command button to obtain the three different results .
Code:
Private Sub Command3_Click()
If (IsNull([ValueofGas])) Then
  ValueofGas = amountGas * Gasprice

ElseIf (IsNull([Gasprice])) Then
   Me.Gasprice = Me.ValueofGas / Me.amountGas

ElseIf (IsNull([amountGas])) Then
   Me.amountGas = Me.ValueofGas / Me.Gasprice
End If
End Sub

Not sure how you wish to trigger the desired outcome

Regards Ypma user not a professional
To trigger the function my goal was to use "GotFocus" or "AfterUpdate" or "Change" or similar attributes of three controls. Once user starts writing the number of any of three controls function should start in the background and as soon as he enters the second value (total or one of the operands) it calculates the third one. It is best if it displays the third value in its according control simultaneously. At the end when user moves to the next new record all numbers should be saved in the table.
Thank you for your help
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 18:14
Joined
Jul 9, 2003
Messages
16,280
Once user starts writing the number of any of three controls function should start in the background and as soon as he enters the second value (total or one of the operands) it calculates the third one
See post number #13 (updated version)... I provided a solution that does exactly this.
 
Last edited:

Users who are viewing this thread

Top Bottom