Calculate stop time, runtime etc. with VBA
On the page Calculating time I show various ways to calculate time using date and string functions.
This page shows a sample macro for calculating number of stops, starts, stop time, runtime, meantime between stops and more. Stuff that is often used to measure process efficiency.
Being able to calculate time is useful, and by doing it in Excel you can tailor it the way you like. You just need to get the times etc. into an Excel spreadsheet - e.g. by importing a CSV-file.
The example on this page uses the VBA function DateDiff to calculate the time differences, and it also uses loops, ranges, arrays and a collection.
You can download a spreadsheet (zip compressed and Excel 2003) with the example here, or you can copy the code below into a VBA module.
In the example the "log" is a simple table with 3 columns. The oldest entry/post is at the top, and I have made it future-proof by using the year 2020.
Motor Date Status
MOTOR1 01-01-2020 02:40:04 STOP
MOTOR1 01-01-2020 02:42:04 START
MOTOR1 01-01-2020 11:31:44 STOP
MOTOR1 01-01-2020 12:21:24 START
MOTOR1 01-01-2020 18:56:14 STOP
MOTOR1 01-01-2020 18:58:14 START
MOTOR2 02-01-2020 09:47:24 STOP
MOTOR2 02-01-2020 10:45:24 START
Etc.
There can be more columns, the order can be different, there can be more motors or production lines - this is just a simple example.
In cell G2 and down you must write the name of the motor(s) in question (here MOTOR1 and/or MOTOR2).
For each motor the macro will find the total number of stops, number of starts, total stop time, total runtime, meantime between stops and the total time from the first to the last row.
To calculate the time difference in seconds the macro uses the DateDiff function:
Time difference = DateDiff("s", Oldest time, Newer time)
The macro has 3 nested loops. The outer loop loops the log for each motor in cell G2 and down. If there is only 1 motor, there will be just one loop.
The inner loop loops the rows from the top until the cell in column A matches the motor and the status in column C is "STOP".
When that happens, we start a new loop downwards, until there is a motor match and the status in column C is "START".
Then we calculate the time difference between stop and start.
As we go along, the macro counts the number of stops and starts. At the end seconds are converted to hours, and a table (or tables) is copied to Sheet2.
For faster execution we copy the table with log data into an array with the same dimensions. One could use the table range instead, but it is faster to operate on an array.
Enough talk, let's go!
Sub Calculate()
Dim bStart As Boolean
Dim bStop As Boolean
Dim rCell As Range
Dim rTable As Range
Dim arInput()
Dim lCount As Long
Dim lRow As Long
Dim lRow2 As Long
Dim lDualStart As Long
Dim lDualStop As Long
Dim lLastRow As Long
Dim lTimeDiff As Long
Dim lStarts As Long
Dim lStops As Long
Dim lTotaltime As Long
Dim dStopTime As Double
Dim colMotor As New Collection
On Error GoTo ErrorHandle
Worksheets(1).Activate
Set rTable = Range("A2", Range("A2").End(xlToRight))
If Len(Range("A3").Value) = 0 Then
MsgBox "There is only one row in the table."
GoTo BeforeExit
End If
Set rTable = Range(rTable, rTable.End(xlDown))
arInput = rTable.Value
Set rTable = Range("G2")
If Len(rTable.Value) = 0 Then
MsgBox "Cell G2 and down must hold the name(s) of the motor(s)."
GoTo BeforeExit
End If
If Len(rTable.Offset(1, 0).Value) > 0 Then
Set rTable = Range(rTable, rTable.End(xlDown))
End If
On Error Resume Next
For Each rCell In rTable
colMotor.Add rCell.Value
Next
On Error GoTo ErrorHandle
lLastRow = UBound(arInput)
lTotaltime = DateDiff("s", arInput(1, 2), arInput(lLastRow, 2))
With colMotor
For lCount = 1 To .Count
lStarts = 0
lStops = 0
dStopTime = 0
lDualStop = 0
lDualStart = 0
For lRow = 1 To lLastRow
If arInput(lRow, 1) = .Item(lCount) Then
If arInput(lRow, 3) = "START" And lStops = 0 Then
bStart = True
lStops = 1
lStarts = 1
If lRow > 1 Then
lTimeDiff = DateDiff("s", arInput(lRow, 2), arInput(1, 2))
dStopTime = lTimeDiff
End If
End If
If arInput(lRow, 3) = "START" And bStart Then
lDualStart = lDualStart + 1
lStarts = lStarts + 1
End If
If arInput(lRow, 3) = "STOP" Then
bStop = True
bStart = False
lStops = lStops + 1
For lRow2 = lRow + 1 To lLastRow
If arInput(lRow2, 3) = "START" And _
arInput(lRow2, 1) = .Item(lCount) Then
lTimeDiff = DateDiff("s", arInput(lRow, 2), _
arInput(lRow2, 2))
dStopTime = dStopTime + lTimeDiff
lRow = lRow2
bStop = False
bStart = True
lStarts = lStarts + 1
Exit For
End If
If arInput(lRow2, 3) = "STOP" And _
arInput(lRow2, 1) = .Item(lCount) Then
lDualStop = lDualStop + 1
End If
If lRow2 = lLastRow And bStart = False And bStop Then
lTimeDiff = DateDiff("s", arInput(lRow, 2), _
arInput(lLastRow, 2))
dStopTime = dStopTime + lTimeDiff
End If
Next
End If
End If
Next
WriteResult lStops, lStarts, dStopTime, _
lTotaltime, lCount, .Item(lCount)
If lDualStart > 0 Then
If lDualStart = 1 Then
MsgBox "There are 2 START logs with no stop in between." _
& vbNewLine & _
"The calculated times for " & .Item(lCount) & " are unreliable."
Else
MsgBox "There are " & lDualStart * 2 & _
" START logs with no stops in between." _
& vbNewLine & _
"The calculated times for " & .Item(lCount) & " are unreliable."
End If
End If
If lDualStop > 0 Then
If lDualStop = 1 Then
MsgBox "There are 2 STOP logs with no start in between." _
& vbNewLine & _
"The calculated times for " & .Item(lCount) & " are unreliable."
Else
MsgBox "There are " & lDualStop * 2 & _
" STOP logs with no start in between." & vbNewLine & _
"The calculated times for " & .Item(lCount) & " are unreliable."
End If
End If
Next
End With
BeforeExit:
On Error Resume Next
Erase arInput
Set colMotor = Nothing
Set rTable = Nothing
Set rCell = Nothing
Exit Sub
ErrorHandle:
MsgBox Err.Description & " Procedure Calculate"
Resume BeforeExit
End Sub
Sub WriteResult(ByVal lStops As Long, ByVal lStarts As Long, _
ByVal dStopTime As Double, ByVal lTotaltime As Long, _
ByVal lCount As Long, ByVal sMotor As String)
Dim arOutput(1 To 6, 1 To 3)
Dim rInsert As Range
Dim lStep As Long
Dim lRow As Long
On Error GoTo ErrorHandle
Application.ScreenUpdating = False
arOutput(1, 1) = "Stops " & sMotor
arOutput(2, 1) = "Starts " & sMotor
arOutput(3, 1) = "Total stoptime"
arOutput(4, 1) = "Total runtime"
arOutput(5, 1) = "Meantime between stops"
arOutput(6, 1) = "Total time logged"
arOutput(1, 2) = lStops
arOutput(2, 2) = lStarts
arOutput(3, 2) = dStopTime / 3600
arOutput(4, 2) = (lTotaltime - dStopTime) / 3600
arOutput(5, 2) = lTotaltime / 3600 / lStops
arOutput(6, 2) = lTotaltime / 3600
arOutput(3, 3) = "Hours"
arOutput(4, 3) = "Hours"
arOutput(5, 3) = "Hours"
arOutput(6, 3) = "Hours"
Worksheets(2).Activate
If lCount = 1 Then
Cells.ClearContents
Set rInsert = Range("A1")
Else
For lStep = 1 To lCount
lRow = lStep + 6
Next
Set rInsert = Range("A" & lRow)
End If
Set rInsert = Range(rInsert, rInsert.Offset(5, 2))
rInsert.Value = arOutput
BeforeExit:
On Error Resume Next
Erase arOutput
Set rInsert = Nothing
Application.ScreenUpdating = True
Exit Sub
ErrorHandle:
MsgBox Err.Description & " Procedure WriteResult"
Resume BeforeExit
End Sub
That was it - a sample macro with conditions for calculating time. You can easily change or add things and tailor it to your needs. For instance you can ignore stops that are below 3 minutes.
It is all up to you, and Excel VBA macros make it possible.
Related:
|