doing a calculation on a time formatted cell in excel vba - vba

I have three cells IN , OUT& OverTime all formatted as [h]:mm,
The OT cell has this forumla,
=ROUND(IF(((D10-C10)+(D11-C11))*24>7,((D10-C10)+(D11-C11))*24-7,0)/24*96,0)/96
that calculates OT to the 1/4 hr
8 C D E F
9 IN OUT O/T C/T
10 7:30 AM 12:15 PM 1:45
11 1:00 PM 5:00 PM
  
When the employee clockes out for the day, I would like the following
code to run;
Dim CT As Date
Title = "Add to CompTime from OverTime"
If Range("E10") > 0 Then
CT = InputBox("Add Hours to CompTime?", Title)
If CT > 0 Then Range("F10").Value = ("E10" - CT)
Else: Range("F10").Value = " "
End If
End Sub
Everthing seems to work except;
If CT > 0 Then Range("F10").Value = ("E10" - CT)
I know it is a formatting issue but I am unable resolve the issue.

Always try to do the explicit referencing to ranges whether they are on sheets or modules. Use proper properties of the objects - in your case you have a range E10 which is not qualified. Assuming you are working in Sheet 1:
Option Explicit
'--Beginning of your Subroutine...
Dim Title as String '-- assuming
Dim CT As Date '-- are you sure you want to have a date here?
Title = "Add to CompTime from OverTime"
If Sheets(1).Range("E10").Value > 0 Then '-- assuming it's a valid date here...
CT = InputBox("Add Hours to CompTime?", Title)
'-- assume your CT = 2:45 and OT = 75:30
'-- use the following as mentioned in my comment
If CT > 0 Then
Application.Text( Sheets(1).Range("F10").Value ,"[h]:mm") =
Application.Text(Sheets(1).Range("E10").Value, "[h]:mm") - Application.Text(CT, "[h]:mm")
Else
Sheets(1).Range("F10").Value = " "
End If
End If
End Sub
PS: If you are trying to calculate hours, you may have just use VBA to do the entire calculations.. =)

Related

Add month to previous cells date For each loop

All,
I have written a little procedure which I would like a for each loop to insert the current month into the first cell "01"/MM/YY and then add one month to the date as it goes through the loop. Using the example below;
K1 = 01/06/2018
L1 = 01/07/2018
M1 = 01/08/2018 etc
The code I am using is below - The error is on the DateAdd line.
Sub test()
Dim dt As date
dt = "01/" & Application.Text(Now(), "MM/YY")
Dim i As Double
i = 1
For Each c In Range("K1:XFD1")
If c.Value = "" Then Exit For
c.Value = dt
'change date to one months time
dt = DateAdd(m, i, dt)
i = i + 1
Next c
End Sub
Any help regarding this would be much appreciated.
Put "m" not m. m would be a variable. "m" is a literal string representing the argument being "month".
dt = DateAdd("m", i, dt)

Convert 24 hour Clock to 12 hour clock and add 6 hours

I have infinite rows with with a single column assigned to define date and time in the following 'General Format' "2016.08.10 06:00:00.066". I am aware that you can't convert every single cell in this column "mm/dd/yyyy hh:mm:ss.000 AM/PM". Therefore I would a single column assigned to "mm/dd/yyyy" and another column assigned to "hh:mm:ss.000 AM/PM". The time is currently 6 hours behind as well so I would like to add 6 hours to it.
I am struggling with this as although the cells are in general or text format the time and date is being displayed as "yyyy.mm.dd hh:mm:ss.000". And can't find a way to split the two in this format
Any help is appreciated
To convert the text to a format that Excel will change to a data/time use this:
=--SUBSTITUTE(SUBSTITUTE(A1,".","/",1),".","/",1)
Then to add 6 hours you would use:
+ TIME(6,0,0)
So to get the date/time is:
=--SUBSTITUTE(SUBSTITUTE(A1,".","/",1),".","/",1) + TIME(6,0,0)
Then simply format the new cell:
mm/dd/yyyy hh:mm:ss.000 AM/PM
You can also split it into the date and time:
Date:
=INT(--SUBSTITUTE(SUBSTITUTE(A1,".","/",1),".","/",1) + TIME(6,0,0))
And format it mm/dd/yyyy
Time:
=MOD(--SUBSTITUTE(SUBSTITUTE(A1,".","/",1),".","/",1) + TIME(6,0,0)),1)
And format it hh:mm:ss.000 AM/PM
use text: =concatenate(text(a1,"MM"),text(a1,"DD"),text(a1,"YYYY") do the same for the other column =concatenate(text(a1,"HH"),text(a1,"MM"),text(a1,"SS")
That's pretty strange that you Excel will round off the milliseconds if you try and use a Date-Time format.
Enum DTValues
ReturnDate
ReturnTime
ReturnDateTime
End Enum
Function getDateTime(yyyymmdd_hh_mm_ss_000 As String, ReturnValue As DTValues) As Single
Dim arr
Dim mSecs As Single
yyyymmdd_hh_mm_ss_000 = Replace(yyyymmdd_hh_mm_ss_000, " ", ".")
yyyymmdd_hh_mm_ss_000 = Replace(yyyymmdd_hh_mm_ss_000, ":", ".")
arr = Split(yyyymmdd_hh_mm_ss_000, ".")
mSecs = arr(6) / 24 / 60 / 60 / 100
Select Case ReturnValue
Case ReturnDate
getDateTime = CSng(DateSerial(arr(0), arr(1), arr(2)))
Case ReturnTime
getDateTime = CSng(TimeSerial(arr(3), arr(4), arr(5))) + mSecs
Case ReturnDateTime
getDateTime = CSng(DateSerial(arr(0), arr(1), arr(2))) + CSng(TimeSerial(arr(3), arr(4), arr(5))) + mSecs
End Select
End Function
Sub ProcessDates()
Const WORKSHEET_NAME = "Sheet1"
Const FIRST_ROW = 2
Const SOURE_COLUMN = 1
Const DATE_COLUMN = 2
Const TIME_COLUMN = 3
Dim Target As Range
Dim arDate, arTime
Dim y As Long
With Worksheets(WORKSHEET_NAME)
Set Target = .Range(.Cells(FIRST_ROW, SOURE_COLUMN), .Cells(Rows.Count, SOURE_COLUMN).End(xlUp))
End With
arDate = Target.Value
arTime = Target.Value
For y = 1 To UBound(arDate)
arDate(y) = getDateTime(arDate(y), ReturnDate)
arTime(y) = getDateTime(arTime(y), ReturnTime)
Next
Target.EntireRow.Columns(DATE_COLUMN).Value = arDate
Target.EntireRow.Columns(TIME_COLUMN).Value = arTime
End Sub

Piece of Code works as expected only when run multiple times

Currently I am debugging a piece of code. Currently my code works as intended it assigns a date of to the finaldate variable then looks in the code to delete all dates that are higher than the finaldate variable. Only problem is that the sub procedure needs to be run multiple times in order for this to take effect. For instance when I run through it once it removes about half of the dates, run through it again and it does the same, I usually F5 it about 5 times to confirm its complete. While this is fine in debugging I need to know this will work perfectly everytime.
Sub Remove_Unecessary_Data_1()
Dim ALLCs As Worksheet
Dim DS As Worksheet
Dim finaldate As Date
Set DS = Sheets("Data Summary")
Set ALLCs = Sheets("Asset LLC (Input)")
ALLCs.Select
For y = 1 To 40
If InStr(1, Cells(13, y), "Timestamp of Execution") Then
finaldate = ALLCs.Cells(50, y)
End If
Next
ALLCs.Select
For u = 1 To 40
If InStr(1, Cells(13, u), "Start Date") Then
For p = 2 To 69584
If Cells(p + 14, u) > finaldate Then
Cells(p + 14, u).EntireRow.Delete
End If
Next
End If
Next
end sub
EDIT: Sample Data
Cells(50,y) = 1/12/15
finaldate = Cells(50,Y)
the column headed Start date contains dates that range anywhere from 1/05/15 to 1/30/15.
When working properly all dates after 1/12/15 should have their entire row eliminated.
When deleting rows, you have to work your way from bottom to top, otherwise you end up skipping rows.
For example, you have:
Line 1
>Line 2
Line 3
Line 4
When your code deletes, Line 2, what was "Row" 3 now becomes "Row "2, but you code moves on to see Line 4. Your data now looks like this:
Line 1
Line 3
>Line 4
If you change this bit of your code:
For p = 2 To 69584
If Cells(p + 14, u) > finaldate Then
Cells(p + 14, u).EntireRow.Delete
End If
Next
to this:
For p = 69598 to 16 step - 1
If Cells(p, u) > finaldate Then
Cells(p, u).EntireRow.Delete
End If
Next
Everything should be fine.
*Note: I adjusted your start & end points up by 14, and removed the + 14 from the Cells() reference. No sense in doing the extra math in there...
When you delete a row using:
Cells(p + 14, u).EntireRow.Delete
the row below the deleted row moves up to occupy that space. If that row contains a date that should be deleted it will be ignored because the counter automatically moves onto the next row. For example, say we wish to delete any rows with C or D in the Data column:
Row Number Data
1 A
2 B
3 C
4 D
5 E
becomes:
Row Number Data
1 A
2 B
3 D
4 E
Tthe row counter moves onto 4 without checking the new value in 3 so the D will not be deleted.
You can solve this by changing your If...Then statement to a Do...While loop:
Sub Remove_Unecessary_Data_1()
Dim ALLCs As Worksheet
Dim DS As Worksheet
Dim finaldate As Date
Set DS = Sheets("Data Summary")
Set ALLCs = Sheets("Asset LLC (Input)")
ALLCs.Select
For y = 1 To 40
If InStr(1, Cells(13, y), "Timestamp of Execution") Then
finaldate = ALLCs.Cells(50, y)
End If
Next
ALLCs.Select
For u = 1 To 40
If InStr(1, Cells(13, u), "Start Date") Then
For p = 2 To 69584
Do While (Cells(p + 14, u) > finaldate)
Cells(p + 14, u).EntireRow.Delete
Loop
Next
End If
Next
End sub
This should keep checking that cell after it has deleted the previous row to ensure the replacement row should not be deleted also.
The fact that you delete a row while going increasingly in row's number, you will miss to analyze every rows right after the one you just delete because it (rows(i+1)) has become the rows(i) and yet you increased with the next.
Here is your code taking that into account (and got rid of the useless Select)
Sub Remove_Unecessary_Data_1()
Dim ALLCs As Worksheet, _
DS As Worksheet, _
FinalDate As Date
Set DS = Sheets("Data Summary")
Set ALLCs = Sheets("Asset LLC (Input)")
For y = 1 To 40
If InStr(1, ALLCs.Cells(13, y), "Timestamp of Execution") Then
FinalDate = ALLCs.Cells(50, y)
End If
Next
For u = 1 To 40
If InStr(1, ALLCs.Cells(13, u), "Start Date") Then
For p = 69584 To 2 Step -1
If Cells(p + 14, u) > FinalDate Then
Cells(p + 14, u).EntireRow.Delete
End If
Next
End If
Next
End Sub

Count of days that have at least 1 job open using SQL

I have a MS Access table that has a list of jobs that were executed (Job ID, StartDate, EndDate) I need to find the count of days in a specified date range (e.g. between 1st Jan and 30 Jun) that a user selects using textboxes that have at least 1 job open ie between StartDate and EndDate. I have some experience with VBA and with SQL (not very good with grouping).
Could anyone assist me with a suggestion of how I could get this count?
JobID| StartDate| EndDate
1142| 03-Jan-14| 04-Feb-14|
1143| 13-Mar-14| 18-May-14|
1144| 03-Jan-14| 29-Jan-14|
1145| 20-Jan-14| 13-Apr-14|
1146| 03-Jan-14| 07-Jan-14|
You could create a calendar table as suggested in the comments and add a button called cmdCountJobDays to your form.
The below code will check all possible dates in the selected date range against the job dates. A bit clunky but it will get you there :-)
Private Sub cmdCountJobDays_Click()
Dim StartDate as Date
Dim EndDate as Date
StartDate = me.txtYourStartDateTextBox
EndDate = me.txtYourEndDateTextBox
SQLGetJobCountPeriod = SQLGetJobCountPeriod & "Select CalendarDate from tblCalendarDates where CalendarDate >=" & cdbl(StartDate)
SQLGetJobCountPeriod = SQLGetJobCountPeriod & " and CalendarDate <= " & cdbl(EndDate)
Set dateschecked = CurrentDb.OpenRecordset(SQLGetJobCountPeriod)
If dateschecked.EOF = False Then
dateschecked.MoveFirst
CountOpenJobDays = 0
CountAllDays = 0
Do While dateschecked.EOF = False
CurrentCheckDate = CDbl(dateschecked.Fields("CalendarDate"))
SQLJobDates = "Select StartDate, EndDateDate from jobdetails "
Set Jobdates = CurrentDb.OpenRecordset(SQLJobDates)
If Jobdates.EOF = False Then
Jobdates.MoveFirst
Do While Jobdates.EOF = False
Jobstartdate = CDbl(Jobdates.Fields("StartDate"))
Jobenddate = CDbl(Jobdates.Fields("EndDate"))
If (CurrentCheckDate > Jobstartdate - 1) And (CurrentCheckDate < Jobenddate + 1) Then
CountJobOpen = CountJobOpen + 1
Exit Do
End If
Jobdates.MoveNext
Loop
End If
CountAllDays = CountAllDays + 1
dateschecked.MoveNext
Loop
End If
msgbox CountJobOpen
End Sub
The count is using a datediff function.
datediff(dd,startdate, enddate)
"dd" tells it to find days, start date would be 1/03/2014, and end date would be 2/04/2014 as an example for your first line

Time Difference in VBA

I have written a program which calculates the time difference between two times.
It calculates the time difference between upto some extent (or few cells appropriately). After few cells it writes garbage values to the rest of the cells.
Please help me.
See the code below.
Sub Average()
Dim LogIn As String
Dim LogOff As String
Dim Row As Integer
Dim Col As Integer
Dim InTime As Date
Dim OffTime As Date
Row = 1
Col = 2
While (Cells(Row, Col) <> "")
Workbooks("Log-In-Time.xlsm").Activate
InTime = Cells(Row, Col)
Workbooks("Log-Off-Time.xlsm").Activate
OffTime = Cells(Row, Col)
Workbooks("Log-In-Time.xlsm").Activate
Cells(Row, Col + 1) = CDate(OffTime) - CDate(InTime)'<- Without CDate also I have tried but output was same.
Row = Row + 1
Wend
End Sub
My Log-In-Time.xls content is,
OUTPUT
7/11/2013 11:35:41 AM 7:14:15 AM
7/15/2013 11:05:22 AM 10:03:00 AM
7/16/2013 9:58:25 AM 11:11:31 AM
7/17/2013 10:33:20 AM 10:39:25 AM
7/18/2013 11:10:33 AM 6:58:35 AM
7/19/2013 12:18:59 AM 7:18:09 PM <-----Here onwadrs
7/22/2013 11:58:26 AM 0.370185185
7/23/2013 11:27:14 AM 0.418645833
7/24/2013 10:59:36 AM 0.439953704
7/25/2013 11:20:16 AM 0.382650463
7/26/2013 11:09:14 AM 0.373171296
Log-Off-Time.xls contents are,
7/11/2013 6:49:56 PM
7/15/2013 9:08:22 PM
7/16/2013 9:09:56 PM
7/17/2013 9:12:45 PM
7/18/2013 6:09:08 PM
7/19/2013 7:37:08 PM
7/22/2013 8:51:30 PM
7/23/2013 9:30:05 PM
7/24/2013 9:33:08 PM
7/25/2013 8:31:17 PM
7/26/2013 8:06:36 PM
Finally got the answer...
Just added the code below.
Dim Diff As Date
Diff = CDate(OffTime) - CDate(InTime)
Find the complete code below.
Sub Average()
Dim LogIn As String
Dim LogOff As String
Dim Diff As Date
Dim Row As Integer
Dim Col As Integer
Dim InTime As Date
Dim OffTime As Date
Row = 1
Col = 2
While (Cells(Row, Col) <> "")
Workbooks("Log-In-Time.xlsm").Activate
InTime = Cells(Row, Col)
Workbooks("Log-Off-Time.xlsm").Activate
OffTime = Cells(Row, Col)
Workbooks("Log-In-Time.xlsm").Activate
Diff = CDate(OffTime) - CDate(InTime)
Cells(Row, Col + 1) = Diff
Row = Row + 1
Wend
End Sub