complicated way of dividing data

bertusavius

Board Regular
Joined
Feb 28, 2008
Messages
82
I have a table with a list of events that have ID, two time-values and two 'trip values'.



ID
Timestart
Timestop
tripstart
tripstop
25
6:55
7:55
259010
259030
25
7:06
7:55
259011
259030
25
7:11
7:57
259013
259030
25
7:17
7:57
259014
259030
25
7:23
7:57
259015
259030
25
7:27
7:59
259017
259031
25
7:29
7:58
259017
259031
25
7:40
7:59
259025
259031
25
8:11
8:21
259038
259043
25
8:41
9:07
259049
259063
25
8:48
9:16
259054
259064
78
13:24
13:34
259116
259122
78
13:40
14:14
259122
259134
78
13:45
14:22
259124
259136
78
13:54
14:22
259127
259136
78
14:03
14:23
259130
259136
78
14:35
14:58
259144
259148
78
14:36
14:58
259144
259148
78
14:43
15:06
259145
259150
78
14:52
15:38
259146
259162
78
15:19
15:42
259155
259163
78
15:27
15:47
259157
259164
78
15:54
16:02
259165
259167

<TBODY>
</TBODY>

<TBODY>
</TBODY>


To make things less abstract:
The trip-value is the value of a trip meter in a car in kilometers.
So the top record actualy says:
car nr 25 had an event that started at 06:55 at trip value 259010 and this event stopped at 07:55 coinciding with trip value 259030
You could say this is a list of events with corresponding accumulating properties, so wether the timeID starts or stops doesnt really matter. All the matters is that a certain time corresponds with a certain trip value.




Now wat I'd like is to create a measure that transforms and divides this information like this:



ID
binID
distance travelled
25
0700-0800
(value in kms)
25
0800-0900
(value in kms)
25
0900-1000
(value in kms)
78
0700-0800
(value in kms)
78
0800-0900
(value in kms)
78
0900-1000
(value in kms)

<TBODY>
</TBODY>

<TBODY>
</TBODY>



<TBODY>
</TBODY>
I have a table to relate to which contains binID, binstart and binstop
I also have a table for dates
Is it even worth contemplating to solve this in Powerpivot, because it seems quite daunting to me atm.



<TBODY>
</TBODY>
 
I'm running your code very succesfully on my data.

But would you mind taking a look at this data:

Datum
TX start
TX stop
Ch
WP_WAGEN_NUMMER
INS_KILOMETERSTAND
UIT_KILOMETERSTAND
5-3-2012
7:31:00
8:32:00
1006
1
225421
225447
5-3-2012
7:42
8:20
1006
1
225423
225440
5-3-2012
7:49
8:20
1006
1
225426
225440
5-3-2012
7:54
8:20
1006
1
225428
225440
5-3-2012
8:20
8:20
1006
1
225440
225440
5-3-2012
9:07:00
10:43:00
53
1
225447
225564
5-3-2012
9:16
10:02
53
1
225451
225509
5-3-2012
15:00:00
15:50:00
1006
1
225564
225591
5-3-2012
15:12
15:36
1006
1
225572
225586
5-3-2012
15:12
15:30
1006
1
225572
225584
5-3-2012
15:12
15:27
1006
1
225572
225582
5-3-2012
15:12
15:42
1006
1
225572
225588

<TBODY>
</TBODY>


It seems that two overlapping shifts occur in the output, so the mileages add up while they shouldnt.
 
Upvote 0

Excel Facts

Excel Wisdom
Using a mouse in Excel is the work equivalent of wearing a lanyard when you first get to college
The Code I develope does not look at "Shifts" for each car.... Instead it looks at the Time and the respective mileage at that time for each car.

Here is a different represetation of the data you provided for Car 1006


Date</SPAN>Miles </SPAN>Differenc</SPAN>
5/3/2012 7:31</SPAN>225421</SPAN>
5/3/2012 7:42</SPAN>225423</SPAN>2</SPAN>
5/3/2012 7:49</SPAN>225426</SPAN>3</SPAN>
5/3/2012 7:54</SPAN>225428</SPAN>2</SPAN>
5/3/2012 8:20</SPAN>225440</SPAN>12</SPAN>
5/3/2012 8:20</SPAN>225440</SPAN>0</SPAN>
5/3/2012 8:20</SPAN>225440</SPAN>0</SPAN>
5/3/2012 8:20</SPAN>225440</SPAN>0</SPAN>
5/3/2012 8:20</SPAN>225440</SPAN>0</SPAN>
5/3/2012 8:32</SPAN>225447</SPAN>7</SPAN>
5/3/2012 15:00</SPAN>225564</SPAN>117</SPAN>
5/3/2012 15:12</SPAN>225572</SPAN>8</SPAN>
5/3/2012 15:12</SPAN>225572</SPAN>0</SPAN>
5/3/2012 15:12</SPAN>225572</SPAN>0</SPAN>
5/3/2012 15:12</SPAN>225572</SPAN>0</SPAN>
5/3/2012 15:27</SPAN>225582</SPAN>10</SPAN>
5/3/2012 15:30</SPAN>225584</SPAN>2</SPAN>
5/3/2012 15:36</SPAN>225586</SPAN>2</SPAN>
5/3/2012 15:42</SPAN>225588</SPAN>2</SPAN>
5/3/2012 15:50</SPAN>225591</SPAN>3</SPAN>
Total</SPAN>170</SPAN>

<TBODY>
</TBODY><COLGROUP><COL><COL span=2></COLGROUP>


I am using the Difference (Column C) to do the Calculations.... Based on my understanding of your requirement, The 'Shift' Really does not have anything to do with the calculation, it's really a snap shot of miles at a specific time that matters.

Am I missing something?:confused:
 
Upvote 0
I think I understand what your method of mileage calculation per hour is, but in the output you seem to correctly relate this to car and driver ID. However, sometimes this relation doenst work like in the above example.

I'm really looking for an absolute relation between mileage-carID-DriverID.

BTW: Are you aware that value 1006 represents a driver ID (not car)?

This would be an explanation of the data:

datestarteventstopeventDRIVERCARstartmileagestopmileage
DatumTX startTX stopChWP_WAGEN_NUMMERINS_KILOMETERSTANDUIT_KILOMETERSTAND
5-3-20127:31:008:32:0010061225421225447Driver 1006 starts his shift in car 1 at 07:31 and stops his shift at 08:32 with associated mileages
5-3-20127:428:2010061225423225440
5-3-20127:498:2010061225426225440
5-3-20127:548:2010061225428225440Driver 1006 starts a job at 07:54 and stops at at 08:20 with associated mileages
5-3-20128:208:2010061225440225440
5-3-20129:07:0010:43:00531225447225564Driver 53 starts his shift in car 1 at 09:07 and stops his shift at 10:43 with associated mileages
5-3-20129:1610:02531225451225509Driver 53 starts a job at 9:16 and stops it at 10:02 with associated mileages
5-3-201215:00:0015:50:0010061225564225591
5-3-201215:1215:3610061225572225586
5-3-201215:1215:3010061225572225584
5-3-201215:1215:2710061225572225582
5-3-201215:1215:4210061225572225588

<tbody>
</tbody>


When you use this next piece data data for example, you see that only in the first hour there is no 'overlap':

DatumTX startTX stopChWP_WAGEN_NUMMERINS_KILOMETERSTANDUIT_KILOMETERSTAND
1-3-20128:25:0012:55:0050042200063200353
1-3-20128:419:1650042200077200106
1-3-20128:539:0550042200087200097
1-3-20128:589:1350042200091200103
1-3-20129:0010:1250042200094200170
1-3-20129:009:3650042200094200127
1-3-20129:049:2850042200096200119
1-3-20129:099:2150042200098200110
1-3-20129:209:2850042200109200119
1-3-20129:3610:0250042200127200160
1-3-20129:4010:1950042200130200181
1-3-20129:4010:1950042200130200182
1-3-20129:489:5850042200136200155
1-3-201210:1210:3850042200170200208
1-3-201210:1210:4050042200170200208
1-3-201210:3010:4150042200195200208
1-3-201210:4710:5350042200210200216
1-3-201210:5911:1750042200217200254
1-3-201211:4211:5350042200296200307
1-3-201211:4211:5450042200296200307
1-3-201211:4312:3950042200296200340
1-3-201211:4912:2050042200304200330
1-3-201212:0912:3050042200318200336
1-3-201212:1912:3350042200330200338
1-3-201212:58:0021:54:0053362200353200959
1-3-201213:1813:2353362200378200383
1-3-201213:2913:4253362200383200388
1-3-201213:2913:4253362200383200388
1-3-201213:2913:4253362200383200388
1-3-201213:3013:4253362200383200388
1-3-201213:5314:1753362200398200437
1-3-201214:0314:2353362200413200445
1-3-201214:0414:2353362200413200445
1-3-201214:3915:0853362200461200506
1-3-201214:4815:0153362200470200500
1-3-201215:0615:2953362200504200524
1-3-201215:1215:2253362200507200511
1-3-201215:2215:3753362200511200535
1-3-201216:2916:4353362200560200575
1-3-201216:5517:1653362200580200641
1-3-201217:1617:3053362200641200671
1-3-201217:5217:5853362200684200690
1-3-201218:1918:4753362200731200767
1-3-201218:3119:1653362200746200797
1-3-201218:4418:5453362200764200777
1-3-201219:0919:2053362200790200801
1-3-201219:0919:2153362200790200803
1-3-201220:0420:1853362200821200841
1-3-201220:2720:4053362200849200880
1-3-201220:5721:2153362200901200924
1-3-201220:5721:2153362200901200924
1-3-201220:5721:2153362200901200924
1-3-201220:5721:2253362200901200925
1-3-201220:5721:2153362200901200924
1-3-201220:5821:2253362200901200925
1-3-201220:5821:2253362200901200925
1-3-201221:0421:1053362200904200913

<tbody>
</tbody>
 
Upvote 0
Very interesting. I understand the issue and I need to take a closer look at it. I was creating the list based on an Key consisting of Car and Driver. the list, as I showed previouly just constisted of Time and Miles. Once the sorted lists were created for each "Key", I world move thru each list to seperate the miles in Hourly to buckets. It is now clear that I have create the List based on Cars. When I pocess each of the Car List, I need to apply special logic if the driver changes. Do this sound right?
 
Upvote 0
This following code accounts for the change in drivers for a single car...

The Code produces the follow results for the data you provided

Datum</SPAN>Ch</SPAN>WP_Wagen</SPAN>Hr</SPAN>Km</SPAN>
5/3/2012</SPAN>1006</SPAN>1</SPAN>07:00 ~ 07:59</SPAN>10</SPAN>
5/3/2012</SPAN>1006</SPAN>1</SPAN>08:00 ~ 08:59</SPAN>16</SPAN>
5/3/2012</SPAN>1006</SPAN>1</SPAN>15:00 ~ 15:59</SPAN>27</SPAN>
5/3/2012</SPAN>53</SPAN>1</SPAN>09:00 ~ 09:59</SPAN>59</SPAN>
5/3/2012</SPAN>53</SPAN>1</SPAN>10:00 ~ 10:59</SPAN>58</SPAN>

<TBODY>
</TBODY><COLGROUP><COL span=3><COL><COL></COLGROUP>




Code:
Option Explicit
Const DateCol As Integer = 1
Const StartTimeCol As Integer = 2
Const EndTimeCol As Integer = 3
Const DriverCol As Integer = 4
Const CarNoCol As Integer = 5
Const StartMileCol As Integer = 6
Const EndMileCol As Integer = 7
Type typDt_MilesRec
    Driver As Integer
    Dt As Date
    Miles As Long
End Type
Type typMstRec
    Car As Integer
    DT_Miles() As typDt_MilesRec
End Type
Type typBin
    Dt_Hr As Date
    Miles As Long
End Type
Type typDriver
    Driver As Integer
    Bin() As typBin
End Type
Sub Process()
    Dim ws As Worksheet
    Dim ws3 As Worksheet
    
    Dim MstRec() As typMstRec
    Dim RowNo As Long
    Dim LastRow As Long
    
    Dim I As Long
    Dim Car As Integer
    Dim Driver As Integer
    Dim CarIdx As Integer
    
    Dim tempStartTime As Date
    
    ReDim MstRec(0)
    
    Set ws = ThisWorkbook.Worksheets(1)
    LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    For RowNo = 2 To LastRow
        If Len(Trim(ws.Cells(RowNo, StartTimeCol))) > 1 Then
            Car = Trim(ws.Cells(RowNo, CarNoCol))
            Driver = Trim(ws.Cells(RowNo, DriverCol))
            CarIdx = FindCarIdx(Car, MstRec)
            
            I = UBound(MstRec(CarIdx).DT_Miles) + 1
            ReDim Preserve MstRec(CarIdx).DT_Miles(I)
            
            MstRec(CarIdx).DT_Miles(I).Driver = Driver
            MstRec(CarIdx).DT_Miles(I).Miles = Val(ws.Cells(RowNo, StartMileCol))
            MstRec(CarIdx).DT_Miles(I).Dt = CDate(ws.Cells(RowNo, DateCol) & " " & CDate(ws.Cells(RowNo, StartTimeCol)))
            tempStartTime = MstRec(CarIdx).DT_Miles(I).Dt
            Call InsertRec(MstRec, CarIdx)
            
            I = UBound(MstRec(CarIdx).DT_Miles) + 1
            ReDim Preserve MstRec(CarIdx).DT_Miles(I)
            
            MstRec(CarIdx).DT_Miles(I).Driver = Driver
            MstRec(CarIdx).DT_Miles(I).Miles = Val(ws.Cells(RowNo, EndMileCol))
            MstRec(CarIdx).DT_Miles(I).Dt = CDate(ws.Cells(RowNo, DateCol) & " " & CDate(ws.Cells(RowNo, EndTimeCol)))
            If tempStartTime > MstRec(CarIdx).DT_Miles(I).Dt Then
                MstRec(CarIdx).DT_Miles(I).Dt = DateAdd("D", 1, MstRec(CarIdx).DT_Miles(I).Dt)
            End If
            Call InsertRec(MstRec, CarIdx)
        End If
    Next RowNo
    
    Call OutputAll(MstRec)
    
    MsgBox "Complete", vbInformation
End Sub
Function InsertRec(Rec() As typMstRec, CarIdx As Integer)
    Dim I As Long
    Dim xRec As typDt_MilesRec
    Dim MaxIdx As Integer
    
    MaxIdx = UBound(Rec(CarIdx).DT_Miles)
    
    '*****  This function sorts the last record into the correct location
    For I = MaxIdx - 1 To 1 Step -1
        If Rec(CarIdx).DT_Miles(I).Dt > Rec(CarIdx).DT_Miles(I + 1).Dt Then
            xRec = Rec(CarIdx).DT_Miles(I + 1)
            Rec(CarIdx).DT_Miles(I + 1) = Rec(CarIdx).DT_Miles(I)
            Rec(CarIdx).DT_Miles(I) = xRec
        Else
            Exit Function
        End If
    Next I
End Function
Function OutputAll(MstRec() As typMstRec)
    Dim ws As Worksheet
    Dim RowNo  As Integer
    Dim CarIdx As Integer
    
    Dim v As Variant
    Dim I As Integer
    
    Set ws = ThisWorkbook.Worksheets(2)
    ws.Cells.ClearContents
    RowNo = 1
    
    ws.Cells(RowNo, 1) = "Datum"
    ws.Cells(RowNo, 2) = "Ch"
    ws.Cells(RowNo, 3) = "WP_Wagen"
    ws.Cells(RowNo, 4) = "Hr"
    ws.Cells(RowNo, 5) = "Km"
    
    For CarIdx = 1 To UBound(MstRec)
        Call OutputData(ws, MstRec(CarIdx), MstRec(CarIdx).Car)
        'Debug.Print MstRec(CarIdx).Car
    Next CarIdx
End Function
Function OutputData(ws As Worksheet, MstRec As typMstRec, Car As Integer)
    Dim I As Integer
    Dim RowNo As Long
    
    Dim v As Variant
    Dim J As Integer
    
    Dim Perc As Single
    Dim tempMins As Integer
    Dim tempMiles As Long
    
    Dim ElapsedMins As Integer
    Dim ElapsedMiles As Long
    
    Dim StartTime As Date
    Dim EndTime As Date
    
    Dim DriverIdx As Integer
    Dim BinIdx As Integer
    Dim StartHr As Integer
    Dim EndHr As Integer
    Dim HourDiff As Integer
    
    Dim tempTime As Date
    
    Dim Drivers() As typDriver
    ReDim Drivers(0)
    ReDim Drivers(0).Bin(0)
    
    RowNo = ws.Cells(ws.Rows.Count, "C").End(xlUp).Row + 1
    For I = 2 To UBound(MstRec.DT_Miles)
        If MstRec.DT_Miles(I).Driver <> MstRec.DT_Miles(I - 1).Driver Then
            GoTo NextRec
        End If
        
        DriverIdx = FindDriverIdx(MstRec.DT_Miles(I).Driver, Drivers)
        
        StartTime = MstRec.DT_Miles(I - 1).Dt
        EndTime = MstRec.DT_Miles(I).Dt
        ElapsedMiles = MstRec.DT_Miles(I).Miles - MstRec.DT_Miles(I - 1).Miles
        
        If ElapsedMiles > 0 Then
            ElapsedMins = DateDiff("n", MstRec.DT_Miles(I - 1).Dt, MstRec.DT_Miles(I).Dt)
            HourDiff = DateDiff("h", StartTime, EndTime)
            Select Case HourDiff
                Case 0
                    BinIdx = FindBin_DT_HR(StartTime, Drivers(DriverIdx).Bin)
                    Drivers(DriverIdx).Bin(BinIdx).Miles = Drivers(DriverIdx).Bin(BinIdx).Miles + ElapsedMiles
                Case Else
                    '***** Determine fractional time for 1st hour
                    BinIdx = FindBin_DT_HR(StartTime, Drivers(DriverIdx).Bin)
                    tempTime = CDate(Format(StartTime, "MM/DD/YY HH:00:00"))
                    tempMins = DateDiff("n", StartTime, DateAdd("h", 1, tempTime))
                    Perc = tempMins / ElapsedMins
                    Drivers(DriverIdx).Bin(BinIdx).Miles = Drivers(DriverIdx).Bin(BinIdx).Miles + (ElapsedMiles * Perc)
                    
                    'Determine Full hour mileage between Start and End Time
                    Perc = 60 / ElapsedMins
                    tempTime = DateAdd("h", 1, StartTime)
                    Do While Hour(tempTime) < Hour(EndTime)
                        BinIdx = FindBin_DT_HR(tempTime, Drivers(DriverIdx).Bin)
                        Drivers(DriverIdx).Bin(BinIdx).Miles = Drivers(DriverIdx).Bin(BinIdx).Miles + (ElapsedMiles * Perc)
                        tempTime = DateAdd("h", 1, tempTime)
                    Loop
                    
                    '***** Determine fractional time for Last hour
                    BinIdx = FindBin_DT_HR(EndTime, Drivers(DriverIdx).Bin)
                    tempTime = CDate(Format(EndTime, "MM/DD/YY HH:00:00"))
                    tempMins = DateDiff("n", tempTime, EndTime)
                    Perc = tempMins / ElapsedMins
                    Drivers(DriverIdx).Bin(BinIdx).Miles = Drivers(DriverIdx).Bin(BinIdx).Miles + (ElapsedMiles * Perc)
            End Select
        End If
        
NextRec:
    Next I
    
    For DriverIdx = 1 To UBound(Drivers)
    
        For I = 1 To UBound(Drivers(DriverIdx).Bin)
            ws.Cells(RowNo, 1) = CDate(Format(Drivers(DriverIdx).Bin(I).Dt_Hr, "MM/DD/YY"))
            ws.Cells(RowNo, 2) = Drivers(DriverIdx).Driver
            ws.Cells(RowNo, 3) = Car
            
            ws.Cells(RowNo, 4) = Format(Drivers(DriverIdx).Bin(I).Dt_Hr, "HH:MM") & " ~ " & Format(Drivers(DriverIdx).Bin(I).Dt_Hr, "HH:59")
            ws.Cells(RowNo, "E") = Drivers(DriverIdx).Bin(I).Miles
            RowNo = RowNo + 1
        Next I
    Next DriverIdx
End Function
Function FindBin_DT_HR(ByVal Dt As Date, Rec() As typBin) As Integer
    Dim I As Integer
    Dim tempDT As Date
    
    tempDT = Format(Dt, "MM/DD/YY HH:00:00")
    
    For I = 1 To UBound(Rec)
        If tempDT = Rec(I).Dt_Hr Then
            FindBin_DT_HR = I
            Exit Function
        End If
    Next I
    
    ReDim Preserve Rec(I)
    Rec(I).Dt_Hr = tempDT
    
    FindBin_DT_HR = I
End Function
Function FindDriverIdx(ByVal Driver As String, Drivers() As typDriver) As Integer
    Dim I As Integer
    
    For I = 1 To UBound(Drivers)
        If Driver = Drivers(I).Driver Then
            FindDriverIdx = I
            Exit Function
        End If
    Next I
    
    ReDim Preserve Drivers(I)
    Drivers(I).Driver = Driver
    
    ReDim Preserve Drivers(I).Bin(0)
    FindDriverIdx = I
End Function
Function FindCarIdx(ByVal Car As String, Rec() As typMstRec) As Integer
    Dim I As Integer
    
    For I = 1 To UBound(Rec)
        If Car = Rec(I).Car Then
            FindCarIdx = I
            Exit Function
        End If
    Next I
    
    ReDim Preserve Rec(I)
    Rec(I).Car = Car
    
    ReDim Preserve Rec(I).DT_Miles(0)
    
    FindCarIdx = I
End Function
 
Upvote 0
By the way you explain it, I think you get the essence.
The output is also exactly what I'm looking for.

(I'm running this code on a different machine than usual (I don't know if that matters)) but I receive an overflow error.

This line is highlighted:
tempMins = DateDiff("n", StartTime, DateAdd("h", 1, tempTime))

I treid redefining Dim tempMins As Integer to no avail
 
Upvote 0
this error beacuse the Minutes difference between StartTime and TempTime exceeds the Size of an Interger.

What Data Set are you using?
 
Upvote 0

Forum statistics

Threads
1,215,438
Messages
6,124,873
Members
449,192
Latest member
MoonDancer

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top