Solved Calculated Controls

Does the code prevent invalid records from being saved?
Hi Pat,
My solution is designed to tackle the problem described by silversun in post #18

>>>receipts one of the values faded, other two readable<<<

Entering any 2 values calculates the obscured one.

As Bob Fitz said right at the beginning, it's not a good idea to store a calculated result.

I think that a suitable modification to the OP's database would be to remove the result field, only calculate it from the price per litre X the amount when required.

This modification would correct the issue you have spotted in that there is the possibility of invalid records being saved.
 
I think you changed the code after I commented on it.

Yes, but only cosmetically! I removed some redundant code and I added a command button to set the fields to 0 because it was impossible to change the results once all three fields had been filled.
 
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

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....
Your example works very well. I need to implement it into my db now. Since I have too many other controls and don't want them to be included in this process then how do I use the tags? Could you please show me the modifications?
In your example I noticed once a new record added it goes to the first row of the table and takes the PK= 1 rather than appending to the end of the table. Is this on purpose or I can just remove that part?
Thank you
 
Since I have too many other controls and don't want them to be included in this process then how do I use the tags?

As shown in this example, the names of the controls processed by the code are prefixed with an "F". Why can't you prefix your control names?
 
I noticed once a new record added it goes to the first row of the table and takes the PK= 1 rather than appending to the end of the table.

My assumption is you have transferred my code into your solution and you are getting this error. If you run my example, the error you describe does not occur.
 
Silverson, I am assuming Uncle Gizmo's demo which I have tested is too complex for you to use in your database.
I am still not 100% what your exact requirement is but have had another attempt .
My demo assumes that two of the three fields are blank and one field has data by entering data in one of the blank fields, the calculation in the Afterupdate event will enter the result in the remaining blank field. I am using NULL so your blank fields must not have zero .

Hope this is a pointer as to where you need to be.

Ypma
Hi,
I opened your db attached here but I couldn't save even one record properly. I guess you can see the issue on the picture. Here for instance I entered 8 as gas price in first filed and 2 for gas amount. Expecting to see 16 in total (third field) but it would display the first saved record in in first control and second control while saving the 8 in row number 8 of table. Please see the attached picture and help me to run this code once at least to see if it works for me.
1608400339017.png


Thank you
 

silversun

Please confirm that you are OK with saving records that have 1 or none of the three data fields we are talking about in them. Records do NOT need all three to be complete. Just confirm and I'll go away.
Hi Pat,
This is the situation: You have many invoices from gas stations and need to have all these in a table. Two records are necessary and enough to obtain the third one. Although user have the third one printed on the receipt but we don't use all three (to save time) because we can always calculate the third one as user enters the first two. Therefore it IS NOT OK to save a record with only one field. I need to have three fields saved in each record.
BTW, I could not find the demo you had as you mentioned "use a bounded query". Can you please link me?

Thank you very much
 
My assumption is you have transferred my code into your solution and you are getting this error. If you run my example, the error you describe does not occur.
I employed your code in my db and the only thing I changed was the name of the fields. You had F1, F2 & F3 but my names were Gprice, Gamount & Gtotal. In your code you looked the controls that have F as first letter of their name where as in my code I looked for G.
After all it is not still working. Here is your code after I changed the names:

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) = "G" 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 "Gprice"
                            Me.Gprice = Me.Gtotal / Me.Gamount
                            
                            Case "Gamount"
                            Me.Gamount = Me.Gtotal / Me.Gprice
                        
                            Case "Gtotal"
                            Me.Gtotal = Me.Gprice * Me.Gamount
                        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) = "G" 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.Gprice = 0
    Me.Gamount = 0
    Me.Gtotal = 0
End Sub

Please check and let me know whats wrong.
 
Hi,
I opened your db attached here but I couldn't save even one record properly. I guess you can see the issue on the picture. Here for instance I entered 8 as gas price in first filed and 2 for gas amount. Expecting to see 16 in total (third field) but it would display the first saved record in in first control and second control while saving the 8 in row number 8 of table. Please see the attached picture and help me to run this code once at least to see if it works for me.
View attachment 87644

Thank you
Error noted and will rectify ASP

Ypma
 
Hi,
I opened your db attached here but I couldn't save even one record properly. I guess you can see the issue on the picture. Here for instance I entered 8 as gas price in first filed and 2 for gas amount. Expecting to see 16 in total (third field) but it would display the first saved record in in first control and second control while saving the 8 in row number 8 of table. Please see the attached picture and help me to run this code once at least to see if it works for me.
View attachment 87644

Thank you
I am in the process of modelling my example on Uncle's solution. I have got it to work ,it only a demo so error handling not yet completed, also i have placed the call of the function in the after update event ,you might move to to the before update event as suggest by Pat. Let me know how you get on.
Have updated my demo
Regards Ypma
 

Attachments

Last edited:
Silverman, you didn't understand my question. I've said this more than once but I'll say it again. The code you are using will NOT prevent you from saving incomplete records. ARE YOU OK WITH THAT???????
@ Pat
I am not OK with that. I need complete and valid data being saved in my table.
Sorry if I was not in the right track. I knew what you were asking but didn't answer properly.
Thank you for following up anyways
 
Last edited:
You have a typos in your code your case statement is incorrect...

Code:
                        Select Case fGetCtrlZero
                            Case "G_price"
                            Me.G_price = Me.G_total / Me.G_amount
                            
                            Case "G_amount"
                            Me.G_amount = Me.G_total / Me.G_price
                        
                            Case "G_total"
                            Me.G_total = Me.G_price * Me.G_amount
                        End Select
 
Case name not correct

Case "Gprice"
Me.G_price = Me.G_total / Me.G_amount

change all the case names

Regards Ypma Uncle beat me to it .
 
You need to call the function from the FORM's BeforeUpdate event AND you need to cancel the event if the data is not valid. As I said, I would have done this differently. Uncle should be able to fix the problem now that he knows there is one.
Pat, in my demo post 36 I have call the function in the after update event and entered the following in the FORMS before the update event , should this suffice or am I missing something ? As a user and not a professional I am keen to improve my best practices


Code:
If (IsNull(Me.Gasprice) Or IsNull(Me.amountGas) Or (IsNull(Me.ValueofGas))) Then
MsgBox " data  is required for all fields "
If MsgBox("Do you wish to save this incomplete record", vbYesNo + vbQuestion) = vbYes Then

Cancel = False
Else
MsgBox " Record not saved re-enter the correct details"
Cancel = True
End If
 
Last edited by a moderator:
You MUST use the BeforeUpdate event because you cannot cancel the AfterUpdate event. Last time I looked, the code is not written to be cancelled. I've mentioned this several times. I would have done this differently. I have tried to stay out but I wanted to make sure you weren't accepting a solution that didn't actually work.

You can continue to run the code as it is from what ever event you prefer. Then in the FORM's BeforeUpdate event, check all three fields.

Code:
If Me.Miles & "" = "" OR Me.Price & "" = "" OR Me.Total & "" = "" Then
    Msgbox "Please enter at least two of the three gas fields", vbOKOnly
    Cancel = True
    Me.Miles.SetFocus
    Exit Sub
End If

The values may not be null. Concatenating a ZLS caters to both null and ZLS.
Pat, thank you for your response, I fully except Concatenating a ZLS caters to both null and ZLS and will take it on board , however not withstanding that, my code gave the user the option to ignore any changes or save the record , yours code does not give him that option. I requested that you look at my Post 36 , however it does not appear to have been viewed . It looks a though the originator of the post is opting for Uncle's solution so I will move on.

Regards Ypma
 
You have a typos in your code your case statement is incorrect...

Code:
                        Select Case fGetCtrlZero
                            Case "G_price"
                            Me.G_price = Me.G_total / Me.G_amount
                           
                            Case "G_amount"
                            Me.G_amount = Me.G_total / Me.G_price
                       
                            Case "G_total"
                            Me.G_total = Me.G_price * Me.G_amount
                        End Select
Your solution works fine now.
I am sorry to make such simple mistake and couldn't catch it.
Now I am wondering about error handling. Please explain the best approach and how to implement it. I have never done this part.
Thank you
Happy Holidays and Merry Christmas
Wish you all the best in new year 2021, healthy and safe.
 
Pat, thank you for your clarification, I misunderstood the posters needs and tried to give him an out in the Forms before update event , plus the fact that if the function is called from the records Before update event, which you have been advocating from day one , no incorrect record should be saved ..
In my Post 36 demo, I entered some error handling code for the function and will leave it to others who are better qualified than me,
As an eighty year old my effort was liken to the "blind leading the blind", but it was simulating plus a learning curve.
I hope you and the people you love have a safe Christmas and a happy New Year
Ypma
 

Users who are viewing this thread

Back
Top Bottom