Excel VBA Course
Excel VBA Course - From Beginner to Expert

200+ Video Lessons
50+ Hours of Video
200+ Excel Guides

Become a master of VBA and Macros in Excel and learn how to automate all of your tasks in Excel with this online course. (No VBA experience required.)

View Course

Sum of Time spent, Average, % in Userform Textboxes

0

Hello everyone.

Can you help me with the following please:

I created 3 sets of textboxes:

T1...T12 for Time spent, T13 for the sum of time spent, T14 for Average of time spent

D1...D12 for number of devices, D13 for the sum of devices, D14 for Average of devices

D1Perc ...D10Perc to display % of Devices compared to D13

What I've been able to do:

- Sum of the devices in D13

- Format Time Textboxes to display hh:mm. Ex 130=01:30

Textbox input mask to show time as I'm typing would be great but it's too hard for me.

What I can't do :

 - Automatically calculate the averages counting "non blank" textboxes       

 - Automatically calculate the percentages of Time spent and the percentages of Devices

 - Sum of the "Time spent" during twelve months to make de devices in T13.

   Ex. 2:30 + 2:30 = 5:00 instead of 4:60

   Ex. 23:30 + 1:30 = 25:00 instead of 24:60 

Attached is the file

HELP ME PLEASE

Answer
Discuss

Answers

0
Selected Answer

Carlo.

In the revised file attached, I modifed your sub for changes to D1 as follows (changes in bold):

Private Sub D1_Change()
    Me.TotalDevices = Val(Me.D1) + Val(Me.D2) + Val(Me.D3) + Val(Me.D4) + Val(Me.D5) + Val(Me.D6) + _
                                      Val(Me.D7) + Val(Me.D8) + Val(Me.D9) + Val(Me.D10) + Val(Me.D11) + Val(Me.D12)

Call AvDevices
End Sub

which calls this (commented for your guidance):

Private Sub AvDevices()

Dim Ctrl As Control, Vl As Variant, Nm As String
Dim AvNo As Integer, AvTot As Double

' reset variables for average
AvNo = 0
AvTot = 0
' loop through controls
For Each Ctrl In Me.Controls
    'check if name contains Perc
    Pos = InStr(Ctrl.Name, "Perc")
    If Pos > 0 Then
    'get value of matching control (without Perc)
        Vl = UserForm1.Controls(Left(Ctrl.Name, Pos - 1)).Value
        If Vl <> "" Then
            'write to this control as a percentage
            Ctrl.Text = Format(Vl / Me.TotalDevices.Value, "#.0%")
            'increase count and total for avarage
            AvNo = AvNo + 1
            AvTot = AvTot + Vl
        End If
    End If
Next Ctrl
' calculate and display average of non-blank values
Me.AverageDevices = Format(AvTot / AvNo, "#.00")

End Sub

That gets the device total and percentages c.f that.

For the time total and average, T1 to T12 update subs have the additions in bold (which avoid odd values when text is deleted and now allows values >24 hrs) whilst leaving your input feature where 2 digits are converted to that many hours.

Private Sub T1_AfterUpdate()
    Dim a As String
    a = Len(Me.T1)
    ' don't convert if value delted but update total/ average
    If a = 0 Then
        Call TotalTime_AfterUpdate
        Exit Sub
    End If
    If a <= 2 Then
        On Error Resume Next
        Me.T1 = Left(Me.T1, a) & ":" & "00"
    'allow any number of hours
    Else
        Me.T1 = Left(T1, a - 2) & ":" & Right(Me.T1, 2)
    End If
    Call TotalTime_AfterUpdate
End Sub

which then calls this macro which converts the values in T1 etc. to a numer of minutes (so they can be added correctly as times):

Private Sub TotalTime_AfterUpdate()
    
Dim TTime As Double, n As Integer, TCount As Integer
Dim HrPart As Double, Minpart As Double
    ' loop through Time entries
    For n = 1 To 12
        'If value exists...
        If (Me.Controls("T" & n).Value) > "" Then
            '... up variables, converting values to minutes
            With Me.Controls("T" & n)
                HrPart = CDbl(Left(.Value, InStr(.Value, ":") - 1))
                Minpart = CDbl(Right(.Value, Len(.Value) - InStr(.Value, ":")))
                TTime = TTime + 60 * HrPart + Minpart
                TCount = TCount + 1
            End With
        End If
    Next n
    ' convert minutes to hh mm
    HrPart = Application.WorksheetFunction.RoundDown(TTime / 60, 0)
    Minpart = TTime - HrPart * 60
    Me.TotalTime.Text = HrPart & ":" & Format(Minpart, "0#")
    ' pass values to other sub for averages
    Call AvTime(TTime, TCount)

End Sub

which in turn sends the collected values TTime and TCount to this macro:

Private Sub AvTime(TTime As Double, TCount As Integer)
    Dim Av As Double
    
    'Avoid Div0 error if no values entered or all values deleted
    If TCount = 0 Then TCount = 1
    ' calculate average minutes
    Av = TTime / TCount
    ' convert to hh mm
    HrPart = Application.WorksheetFunction.RoundDown(Av / 60, 0)
    Minpart = Round((Av - HrPart * 60), 0)
    Me.AverageTime.Text = HrPart & ":" & Format(Minpart, "0#")
    
End Sub

which gives the average time in your userform.

Hope this works for you..

Discuss

Discussion

Wow. Thank you so much. I'm going to try it.
Carlo (rep: 6) Mar 4, '22 at 10:47 pm
If it answers your question Carlo (I think it does), please remember to mark the Answer as Selected.
John_Ru (rep: 6142) Mar 5, '22 at 1:51 am
Thank you for being patient. I have at lot to learn.

The average for the Devices and the % work perfectly.  

Here are some issues that I noticed
:0 appears after deleting a time and Click Enter
:0:0 appears when I click in the textbox holding
:0 Run-time erro 6 appears when I click in :0:0  

Test1
T1 = 20:00 (20 hours)
T2 = 03:30(3 hours and 30 mn)
Total= 23 :30 ok AV= 11:45 instead of 12 :05 (11 :65)  

Test 2
T1 = 20:00 (20 hours)
T2 = 03:30 (3 hours and 30mn)
T3 = 00:30 (30 mn)
Total = 00:00 instead of 24:00 which leads to incorrect AV  

Test 3
T1 = 20:00 (20hours)
T2 = 03:30 (3hours and 30mn)
T3 = 00:30 (30mn)
T4=01:00 (1 hour)
Total=01:00 instead of 25:00 which leads to incorrect AV  

How it should work:
00:60(60mn) should turn 1:00(1hour)
23:00+00:60 =24:00
24:00+00:60 = 25:00(25hours)

I’m trying to sum the hours and mn(duration) no matter how big the number of Hours is.  

Any suggestion will be appreciated
Carlo (rep: 6) Mar 6, '22 at 8:04 pm
Carlo   Please see my revised Answer/file.  

Note that in your point above, Test 1, AV= 11:45 is the correct answer (for 23 hrs 30 divided by 2 month values).  

You say ":0 appears after deleting a time and Click Enter" but that was a feature of your original file which I've avoided that by the lines starting:     
Private Sub T1_AfterUpdate()
    Dim a As String
    a = Len(Me.T1)
    ' don't convert if value deleted but update total/ average
    If a = 0 Then
        Call TotalTime_AfterUpdate
        Exit Sub
    I haven't changed those time conversion routines to make an entry of 00:60 become 1:00 (although my TotalTime code allows for that).
John_Ru (rep: 6142) Mar 7, '22 at 9:36 am
Did you try the new file yet, Carlo?
John_Ru (rep: 6142) Mar 8, '22 at 8:22 am
Thanks for selecting my answer, Carlo. I'd completely forgotten about answering you!
John_Ru (rep: 6142) Nov 15, '22 at 3:27 pm
Add to Discussion


Answer the Question

You must create an account to use the forum. Create an Account or Login