Avatar of bfuchs
bfuchs
Flag for United States of America asked on

Update Lunch column break according to schedule start/end time.

Hi Experts,

This is in reference to the following.
I would like to have the lunch column getting populated with the correct amount.

Thanks in advance.
System ProgrammingVB ScriptVBAMicrosoft ExcelMicrosoft Office

Avatar of undefined
Last Comment
bfuchs

8/22/2022 - Mon
Martin Liss

Please attach a sample workbook.
bfuchs

ASKER
Hi Martin,
Everything is included in the other thread, the sample workbook along with the current logic used for calculating times, we're just missing one column which is the lunch break.
Thanks,
Ben
Martin Liss

Please re-attach the sample workbook from that thread because I don't see it.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
bfuchs

ASKER
Attached.

Thanks,
Ben
Book4.csv
Bill Prew

Give this a try, seems to be working here...

Const ForReading = 1
Const ForWriting = 2
Const TriStateUseDefault = -2

strInFile = "B:\EE\EE29139695\Book4.csv"
strOutFile = "B:\EE\EE29139695\Book4.new"

Set objFSO = CreateObject("Scripting.FileSystemObject")
strInFile = objFSO.GetAbsolutePathname(strInFile)
strOutFile = objFSO.GetAbsolutePathname(strOutFile)

If Not objFSO.FileExists(strInFile) Then
   Wscript.Echo "ERROR: Input file """ & strInFile & """ does not exist."
   Wscript.Quit
End If

Set objFile = objFSO.OpenTextFile(strInFile, ForReading, False, TriStateUseDefault)
strData = objFile.ReadAll
objFile.Close

arrData = Split(strData, vbCrLf)

For i = 1 To UBound(arrData)

    If arrData(i) <> "" Then
        ' Split this input line into it's fields
        arrFields = Split(arrData(i), ",")
        
        ' Make sure we have at least 101 fields
        If UBound(arrFields) > 6 Then

            If arrFields(4) <> "" And arrFields(5) <> "" And arrFields(7) <> "" Then

                ' Look for matching field value and perform needed edit
                If Right(UCase(arrFields(4)), 1) <> "M" And Right(UCase(arrFields(5)), 1) <> "M" Then
                    strAmPm = GetAmPm(arrFields(4), arrFields(5), arrFields(7))
                    If strAmPm <> "" Then
                        arrFields(4) = arrFields(4) & " " & Left(strAmPm, 2)
                        arrFields(5) = arrFields(5) & " " & Right(strAmPm, 2)
                    End If
                End If

                ' Calculate lunch hours
                arrFields(6) = CalcLunchTime(arrFields(4), arrFields(5), arrFields(7))
                arrData(i) = Join(arrFields, ",")

            End If

        End If

    End If

Next

Set objFile = objFSO.OpenTextFile(strOutFile, ForWriting, True)
objFile.Write Join(arrData, vbCrLf)
objFile.Close


Function GetAmPm(strStartTime, strEndTime, strTotalHours)
    Dim dblTotalHours, i, j, datStartTime, datEndTime, arrAmPm
    arrAmPm = Array("AM", "PM")

    dblTotalHours = CDbl(strTotalHours)
    GetAmPm = ""

    For i = 0 To 1
        For j = 0 To 1
            datStartTime = CDate("1/1/1900 " & strStartTime & " " & arrAmPm(i))
            datEndTime = CDate("1/1/1900 " & strEndTime & " " & arrAmPm(j))
            If datStartTime > datEndTime Then
                datEndTime = DateAdd("d", 1, datEndTime)
            End If
            If Abs(DateDiff("h", datStartTime, datEndTime) - dblTotalHours) <= 2 Then
                GetAmPm = arrAmPm(i) & arrAmPm(j)
                Exit Function
            End If
        Next
    Next
End Function

Function CalcLunchTime(strStartTime, strEndTime, strTotalHours)
    Dim dblTotalHours, datStartTime, datEndTime

    dblTotalHours = CDbl(strTotalHours)
    datStartTime = CDate("1/1/1900 " & strStartTime)
    If Right(strStartTime, 2) = "PM" And Right(strEndTime, 2) = "AM" Then
        datEndTime = CDate("1/2/1900 " & strEndTime)
    Else
        datEndTime = CDate("1/1/1900 " & strEndTime)
    End If
    CalcLunchTime = DateDiff("h", datStartTime, datEndTime) - dblTotalHours
End Function

Open in new window


»bp
bfuchs

ASKER
Hi,

Mostly are fine.
However some numbers are negative, see below.

StartTime      EndTime      Lunch      TotalHours      
9:00 AM      6:30 PM      -0.5      9.5       
7:00 AM      7:30 PM      -0.5      12.5       
7:15 AM      12:15 AM      -21      14       
8:00 AM      12:00 AM      -22      14       
8:00 AM      3:15 PM      -0.25      7.25       
8:00 AM      3:30 PM      -0.5      7.5       
8:00 AM      4:15 PM      -0.25      8.25       
7:00 AM      11:45 AM      -0.75      4.75       

Thanks,
Ben
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Bill Prew

Okay, give this adjustment a try:

Const ForReading = 1
Const ForWriting = 2
Const TriStateUseDefault = -2

strInFile = "B:\EE\EE29139695\Book4.csv"
strOutFile = "B:\EE\EE29139695\Book4.new"

Set objFSO = CreateObject("Scripting.FileSystemObject")
strInFile = objFSO.GetAbsolutePathname(strInFile)
strOutFile = objFSO.GetAbsolutePathname(strOutFile)

If Not objFSO.FileExists(strInFile) Then
   Wscript.Echo "ERROR: Input file """ & strInFile & """ does not exist."
   Wscript.Quit
End If

Set objFile = objFSO.OpenTextFile(strInFile, ForReading, False, TriStateUseDefault)
strData = objFile.ReadAll
objFile.Close

arrData = Split(strData, vbCrLf)

For i = 1 To UBound(arrData)

    If arrData(i) <> "" Then
        ' Split this input line into it's fields
        arrFields = Split(arrData(i), ",")
        
        ' Make sure we have at least 101 fields
        If UBound(arrFields) > 6 Then

            If arrFields(4) <> "" And arrFields(5) <> "" And arrFields(7) <> "" Then

                ' Look for matching field value and perform needed edit
                If Right(UCase(arrFields(4)), 1) <> "M" And Right(UCase(arrFields(5)), 1) <> "M" Then
                    strAmPm = GetAmPm(arrFields(4), arrFields(5), arrFields(7))
                    If strAmPm <> "" Then
                        arrFields(4) = arrFields(4) & " " & Left(strAmPm, 2)
                        arrFields(5) = arrFields(5) & " " & Right(strAmPm, 2)
                    End If
                End If

                ' Calculate lunch hours
                arrFields(6) = CalcLunchTime(arrFields(4), arrFields(5), arrFields(7))
                arrData(i) = Join(arrFields, ",")

            End If

        End If

    End If

Next

Set objFile = objFSO.OpenTextFile(strOutFile, ForWriting, True)
objFile.Write Join(arrData, vbCrLf)
objFile.Close


Function GetAmPm(strStartTime, strEndTime, strTotalHours)
    Dim dblTotalHours, i, j, datStartTime, datEndTime, arrAmPm
    arrAmPm = Array("AM", "PM")

    dblTotalHours = CDbl(strTotalHours)
    GetAmPm = ""

    For i = 0 To 1
        For j = 0 To 1
            datStartTime = CDate("1/1/1900 " & strStartTime & " " & arrAmPm(i))
            datEndTime = CDate("1/1/1900 " & strEndTime & " " & arrAmPm(j))
            If datStartTime > datEndTime Then
                datEndTime = DateAdd("d", 1, datEndTime)
            End If
            If Abs(DateDiff("h", datStartTime, datEndTime) - dblTotalHours) <= 2 Then
                GetAmPm = arrAmPm(i) & arrAmPm(j)
                Exit Function
            End If
        Next
    Next
End Function

Function CalcLunchTime(strStartTime, strEndTime, strTotalHours)
    Dim dblTotalHours, datStartTime, datEndTime

    dblTotalMins = CDbl(strTotalHours) * 60
    datStartTime = CDate("1/1/1900 " & strStartTime)
    If Right(strStartTime, 2) = "PM" And Right(strEndTime, 2) = "AM" Then
        datEndTime = CDate("1/2/1900 " & strEndTime)
    Else
        datEndTime = CDate("1/1/1900 " & strEndTime)
    End If
    CalcLunchTime = (DateDiff("n", datStartTime, datEndTime) - dblTotalMins) / 60
    Wscript.Echo strStartTime & ", " & strEndTime & ", " & datStartTime & ", " & datEndTime  & ", " & DateDiff("n", datStartTime, datEndTime) & ", " & dblTotalMins & ", " & CalcLunchTime
End Function


'====================================================================================


Sub SavedCode()
    Set objFSO = CreateObject("Scripting.FileSystemObject")

    If (WScript.Arguments.Count > 0) Then
       strInFile = objFSO.GetAbsolutePathname(WScript.Arguments(0))
    Else
       WScript.Echo "No input filename specified."
       WScript.Quit
    End If

    If (WScript.Arguments.Count > 1) Then
       strOutFile = WScript.Arguments(1)
       strOutFile = objFSO.GetAbsolutePathname(WScript.Arguments(1))
    Else
       strOutFile = strInFile
    End If

    If Not objFSO.FileExists(strInFile) Then
       Wscript.Echo "ERROR: Input file """ & strInFile & """ does not exist."
       Wscript.Quit
    End If
End Sub

Open in new window


»bp
bfuchs

ASKER
Hi Bill,
Not in the office.
Will do it on Monday.
Have a nice weekend.
Thanks,
Ben
bfuchs

ASKER
Hi Bill,

We are still getting negative values for lunch (3rd column), see below.

7:15 AM      12:15 AM      -21      14
8:00 AM      12:00 AM      -22      14
7:30 AM      12:00 AM      -23      15.5

Thanks,
Ben
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
bfuchs

ASKER
In addition, the following records didn't get lunch, neither did they got AM/PM...

3:00      11:30            7.5
11:30      7:30            6

Thanks,
Ben
Bill Prew

Okay, I'll have to revisit the logic I'm using and shake out the issues...


»bp
Bill Prew

So can we clarify something?  Will the input start and end times in the file being read have AM and PM already on all values?  Or will there be no AM and PM on any values?  Or is there a mix?

The way you have the data structured with a start date but no end date makes this a challenging question, and some assumptions have to be made.  I want to make sure I know what the incoming data will always look like so I make the right assumptions.


»bp
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER CERTIFIED SOLUTION
Bill Prew

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
bfuchs

ASKER
Hi,

Will the input start and end times in the file being read have AM and PM already on all values?  Or will there be no AM and PM on any values?  Or is there a mix?
There will be a mix as original data comes from from two sources, one with AM/PM and one w/o them.
The way you have the data structured with a start date but no end date
Are you referring to Start/End times? In cases where there is no start or end time I guess you can ignore them and no need to do anything.
...makes this a challenging question
If that turns out to be quite challenging perhaps would close the question and open another one on the remaining issues so you can be awarded properly.
if you want to try it there...
I can test for errors or just randomly but real testing would have to wait for users tom.

Thanks,
Ben
bfuchs

ASKER
while testing this new version I came across these records.

7:00 PM      12:00      -12      5      

which should be filled with 12AM and no lunch.

and
 11:45      8:00      -10      6.25
which should be either AM or PM, and lunch 2 hours.

P.S. I might be wrong, so perhaps lets wait for users to say their input.

Thanks,
Ben
Bill Prew

When I ran these two test case through the latest version I sent you:

,a,b,2/1/2019,7:00 PM,12:00,,5,,,
,a,b,2/1/2019,11:45,8:00,,6.25,,,

Open in new window

I got the correct output I believe of:

,a,b,2/1/2019,7:00:00 PM,12:00:00 AM,0,5,,,
,a,b,2/1/2019,11:45:00 AM,8:00:00 PM,2,6.25,,,

Open in new window


»bp
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
bfuchs

ASKER
Hi Bill,
Not sure why it didn't show on mine yesterday but now it works.
Thank you!
Bill Prew

Welcome.


»bp
bfuchs

ASKER
Hi Bill,

Would prefer to add something to this script.
Are you avail for a new Q?

Thanks,
Ben
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Bill Prew

Yes, I'm still around...


»bp
bfuchs

ASKER
Hi,

Here you go..

Thanks,
Ben