Checking if Datetime is in between a given Datetime interval - vba

I have a table which looks like this:
What I am trying to do is to sum up a few values within a given datetime range. Let's say for example between 01.01.2016 00:30 and 01.01.2016 02:00.
My if clause looks like this.
If .Cells(i, 3).Value = "Samariter" And .Cells(i, 1).Value >= "01.01.2016 00:30:00" And .Cells(i, 1).Value <= "01.01.2016 02:00:00" Then
And if I run the algorithm, it runs correctly, BUT:
If I try, for example, the range from 25.1.2016 20:00 until 26.1.2016 02:00:
This is my if clause again:
If .Cells(i, 3).Value = "Samariter" And .Cells(i, 1).Value >= "25.01.2016 20:00:00" And .Cells(i, 1).Value <= "26.01.2016 02:00:00" Then
If I run this, it will start at the correct line, but will exceed the upper bound of the datetime interval.
What is the problem here?

Xabier's answer solved the problem, the if-clause should look like this in order for the algorithm to run properly:
If .Cells(i, 3).Value = "Samariter" And DateDiff("s", .Cells(i, 1).Value, "25.01.2016 00:00:00") < 0 And DateDiff("s", .Cells(i, 1).Value, "31.01.2016 23:59:59") >= 0 Then

Related

New to VBA- runtime error 6, script stops at blank cells instead of looping

Recently started working with VBA. Youtube and this forum have been excellent help so far. However, my problem is this:
Private Sub CommandButton1_Click()
Dim i As Integer
i = 1
Do While Sheet2.Cells(i, 1).Value <> 0
Sheet3.Cells(i, 1).Value = Sheet2.Cells(i, 1)
i = i + 1
Loop
Do While Sheet2.Cells(i, 10).Value <> 0
Sheet3.Cells(i, 4).Value = Sheet2.Cells(i, 10)
i = i - 1
Loop
Do While Sheet2.Cells(i, 6).Value <> 2
Sheet3.Cells(i, 3).Value = Sheet2.Cells(i, 6)
i = i + 1
Loop
End Sub
This script populates information in the correct sheet as well as the correct columns, at least until it encounters an empty cell from Sheet2. At this point is moves on to the next "Do While" instead of referring to the next non blank cell.
I've also encountered a Runtime Error 6- Overflow with this specific line:
Do While Sheet2.Cells(i, 6).Value <> 2
Sheet3.Cells(i, 3).Value = Sheet2.Cells(i, 6)
i = i + 1 <<<<----- ERROR??
I'm fairly certain that the Overflow Error is a result of Dim i as Integer vs. Dim i as String, but then again I've pretty much but working by trial and error, moving portions of script around and playing with expressions/functions.
As mentioned before I'm new to VBA. I'm also the kind of guy that learns by doing as well. I've looked all over different forums, youtube videos, etc. trying to create a script that works the way I want it to.
UPDATE
Thanks for the quick help and recommendations. I realized I didn't give near enough information in my first post.
1.) I don't need/want to leave an empty cell on sheet3. The script is now looping but not skipping over blanks if that makes sense?
For example:
doing need to do
101 101
102 102
104
104 105
105 106
106
I'm stil running off the end of the world as well so to speak. For some reason the Debug Function is bringing up this line
i = i + 1
2.) the line:
Do While Sheet2.Cells(i, 6).Value <> 2
Sheet3.Cells(i, 3).Value = Sheet2.Cells(i, 6)
is supposed to recognize a column of text not numbers. Not exactly sure if this is having an effect on anything
Thanks again everyone.
UPDATE 3:
I've got rid of the Error Messages and corrected all the expressions in the script. Also, I found that instead of using Do Until....... And........ had zero results. I had to go back to Do While and substitute an Or statement vs. the former.
So far the script is working better than I had expected. Thank You all for the help and insight.
Good news aside, I still need to figure out how to compose an "IF" statement so that the script will skip over blank cells in sheet2.cells(i, 1) and not import present values for that row in the 2 adjacent columns
Here is the current and running script:
Private Sub CommandButton1_Click()
Dim i As Long
i = 3
Do While (Not IsEmpty(Sheet2.Cells(i, 10))) Or (Sheet3.Cells(i, 4).Value <> 0)
Sheet3.Cells(i, 4).Value = Sheet2.Cells(i, 10).Value
i = i + 1
Loop
i = 3
Do While (Not IsEmpty(Sheet2.Cells(i, 1))) Or (Sheet3.Cells(i, 1).Value <> 0)
Sheet3.Cells(i, 1).Value = Sheet2.Cells(i, 1).Value
i = i + 1
Loop
i = 3
Do While (Not IsEmpty(Sheet2.Cells(i, 6))) Or (Sheet3.Cells(i, 3).Value <> 0)
Sheet3.Cells(i, 3).Value = Sheet2.Cells(i, 6).Value
i = i + 1
Loop
End Sub
Thank you again everyone. Hope I can return the favor in the near future.
A few thoughts:
As #dgorti said, make sure to set i before each Do loop to be the index of the row you want to start with.
Dim any integer value as Long, not Integer. Long is 32 bits; Integer is 16.
To skip over empty cells, use IsEmpty. For example, in your first loop: Edited
Do Until (Not IsEmpty(Sheet2.Cells(i, 1))) and (Sheet2.Cells(i, 1).Value = 0)
Edit And, as #A.S.H. points out, you should also range-check i. Since VBA doesn't have short-circuit operators, I would do that at the end of your loop:
Do ...
... 'vvvvv representable in a Long
If i = 65536 Then Exit Do ' Or If i = 1... for loops that count down
i = i + 1
Loop
That way you never run off the end.
Edit I fixed the test above — you want to run until you hit a non-empty cell with a value of 0, right? So Do Until (which is a real thing :) ) loops until exactly that condition holds. The Not IsEmpty() prevents the test against 0 from giving the wrong result on blank cells.

How to fetch the record that have the closest date?

Here is the excel raw data example
StaffID Date Accumulative Balance
s15 15/12/2015 31
s15 31/12/2015 64
s15 3/4/2016 65
S98 13/4/2016 65
......
Now i want to generate a report in excel .
This report i have to show every staff starting accumulative balance from 1/1/2016-31/3/2016.
Starting accumulative balance refer to the accumulative balance before 1/1/2016 .
For example , for staff S15 ,the balance should be 64 (most closest Accumulative Balance before 1/1/2016 .
Question
Any VBA function or method useful in this case to get the closest date record ,so that I can fetch that record field(Balance).
Btw, the starting date (1/1/2016) should be stored in a datetype variable-
startdate
Update
i mean is there any vba function
say , abc(1/1/2016,table1(range(A:A))
it can help me to find the date closest to 1/1/2016 and before 1/1/2016 in that column- range(A:A)
Output: 31/12/2015
Then , i can do the next step :getting the balance in that row -31/12/2015
I will deliver this answer, but I have to emphasize, that the criticism brought forward to you in the comments is still justified.
Sub findClosestDate()
Dim ws As Worksheet
Dim i, j, currDist As Long
Dim startDate As Date
Set ws = Worksheets(1)
With ws
i = 1
j = 1
closestDistLine = 1
startDate = "01.01.2016"
currDist = .Cells(i, 2) - startDate
Do While .Cells(i, 1) <> ""
newDist = .Cells(i, 2) - startDate
If newDist >= currDist Then
closestDistLine = i
currDist = newDist
End If
If .Cells(i, 1) <> .Cells(i + 1, 1) Then
.Cells(j, 5) = .Cells(i, 1)
.Cells(j, 6) = .Cells(closestDistLine, 3)
currDist = .Cells(i + 1, 2) - startDate
newDist = .Cells(i + 1, 2) - startDate
j = j + 1
End If
i = i + 1
Loop
End With
End Sub
For this code to work, you have to sort your table alphabetically after the staff-id.
How does it work
It loops through the rows, checks the distance of the current line to the startdate.
If the distance is closer to the startdate, the line of that row is saved in closestDistLine
If all entries of the current staff-id are found, staff-id and value in the row of closest distance will be written into columns 5 and 6
HTH

Excel VBA input error

I'm a business student who just started to learn VBA. I am trying to write a macro for a project but only have minimal experience actually stepping into the code. What I am trying to do is delete all row entries which have future month's dates in them, and I'd like for this to update based on the current month. I hope I am using the correct functions, but maybe just in the wrong order.
I'm trying to compare the data for each row (in this case I'm looking at cell 16 in each) and I was thinking that if the month digits for the date in that column are greater than the value of the month digits for the current month, then it should delete, but I'm receiving the error [Run-time error '5' Invalid procedure call or argument].
So here is the part of the code I am having trouble with:
If DatePart(mm, Cells(iCntr, 16)).Value > DatePart(mm, Date).Value Then
Rows(iCntr).Delete
In the code, I was only focusing on the month portion because the file I'm using only contains current year information, so I wouldn't have to worry about accidentally failing to delete something for March of next year (03/2017) due to it being June of this year (for example, technically 03/13/2017 would not be deleted since 03 < 06).
(Second question for my own learning experience--someone suggested I use iCntr in this, but what does this actually do for the formula?)
Update: Went to Code Review and they updated my code and now the problem I am running into is that the friend who sent me the file left some rows of blanks that contain a single space, which is causing an error when I run the macro. Could someone suggest how to use the trim() function to eliminate those?
Sub Remove_excess_entries()
Application.ScreenUpdating = False
Dim lRow As Long
Dim iCntr As Long
lRow = 10000
For iCntr = lRow To 1 Step -1
If Cells(iCntr, 12).Value = "Mule" Or Cells(iCntr, 11).Value = "*R1*" Or Cells(iCntr, 11).Value = "*R2*" Or Cells(iCntr, 7).Value = "*Mule*" Or Cells(iCntr, 6).Value = "*Unassigned*" Or Cells(iCntr, 12).Value = "PS" Or Cells(iCntr, 7).Value = "Marketing" Or Cells(iCntr, 12).Value = "V1" Or DatePart("m", Cells(iCntr, 16).Value) > DatePart("m", Date) Then
Rows(iCntr).Delete
End If
Next
Application.ScreenUpdating = True
End Sub
iCntr isn't a VBA command, it's likely just a declared variable (possibly a counter value for iterating over the range of rows you want to consider, based on the context of the code shown). Presumably you have it declared somewhere and defined in a For type loop?
Secondly, according to MSDN the correct parameter for "month" in DatePart is "m", not mm. That means your code should read as:
If DatePart("m", Cells(iCntr, 16).Value) > DatePart("m", Date) Then Rows(iCntr).Delete
You also have the .Value outside the closing brackets, which means you are trying to assign it to the DatePart object rather than the Cells one. Feel free to ask anything further if I've not explained it well enough
as for the correct use of DatePart() function, type:
If DatePart("m", Cells(iCntr, 16)) > DatePart("m", Now) Then Rows(iCntr).Delete

Program freezing and not working

I have written this VBA code that goes through a set of data and aligns specific rows of data together and deletes the rest. I have various columns labeled as below. Whenever "Billed" appears under the "M" column, my program records the order number associated with that row under "B". It then loops and while the order number under "B" is consistent, it moves the notes under "L" associated with "Completed" and copies it besides the column and the same under where "Billed" was found. In addition, when it also moves the date under column "D" for "Confirmed" associated with that same order number and again adds to the column beside the "Billed" row. The problem I am running into is that none of these rows appear in the same order and also there can be duplicates. If there's a duplicate like the one in second order number for "Confirmed" then the most recent one will be taken and copied over beside "Billed". Any help would be tremendously appreciated! Thanks a lot in advance. Here is an Example:-
B D L M
1.467334 4/22/2015 Confirmed
2.467334 4/17/2015 YES Tech swapped out the MGR 13, tested Completed
3.467334 4/20/2015 4/16 Maint. Billed Billed
4.537551 4/15/2015 Confirmed
5.537551 4/14/2015 YES Tech swapped out the MGR 13, tested Confirmed
6.537551 4/08/2015 4/16 Maint. Billed Billed
7.537551 4/14/2015 YES Tech swapped out equipment Completed
8.537551 4/08/2015 4/16 Maint. equip. Confirmed
Required Output:-
B D L M Q R
3.467334 4/20/2015 4/16 Maint. Billed Billed YES swapped out theMGR 13, tested 4/22/2015
6.537551 4/16/2015 4/16 Maint. Billed Billed YES Tech swapped out equipment 4/14/2015
Here is my code:
Sub Test()
Dim LR As Long
Dim Rng As Range
Dim i As Long
Dim r As Long
Dim com As Range
LR = Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To LR Step 1
''''This might be confusing but what I am doing here is copying the notes for the "Billed" row and moving to the right.
'This part works fine but the rest of the "Do While" loop doesn't.
If Cells(i, "M").Value = "Billed" Then
Cells(i, "Q").Value = Cells(i, 12).Value
Set com = Cells(i, "B")
Set num = Cells(i, "B").Row
Do While Cells(i, "B").Value = com
If Cells(i, "M") = "Completed" Then
Cells(num, "R").Value = Cells(i, 12).Value
End If
Loop
Do While Cells(i, "B").Value = com
If Cells(i, "M") = "Confirmed" Then
Cells(num, "S").Value = Cells(i, 4).Value
End If
Loop
End If
Next i
Your issue is here:
Do While Cells(i, "B").Value = com
If Cells(i, "M") = "Completed" Then
Cells(num, "R").Value = Cells(i, 12).Value
End If
Loop
Do While Cells(i, "B").Value = com will always be true, because neither i nor com are changing inside your loop. In some way shape or form, you need to adjust the value of one of those two variables within that loop. I believe that a simple i = i + 1 will do what you're after, like this:
Do While Cells(i, "B").Value = com
If Cells(i, "M") = "Completed" Then
Cells(num, "R").Value = Cells(i, 12).Value
End If
i = i + 1
Loop
Just realized that won't work, since i is the counter in your For...Next loop. Instead, try this:
r = i
Do While Cells(r, "B").Value = com
If Cells(r, "M") = "Completed" Then
Cells(num, "R").Value = Cells(r, 12).Value
End If
r = r + 1
Loop
You've declared r, but never used it, so I usurped it for this loop.
The same holds true for your next Do While...Loop block.
A couple of additional thoughts:
You're mixing reference between Cells(i, "M") and Cells(i, 12). While the compiler doesn't care and can easily interpret that, it's harder for us people types to figure out what column is being referenced - is M the 12th letter? No, it's the 13th, so that mean... oh, Column L!
Use consistent block indention - that also makes your code much easier to read and mentally parse. Again, the compiler doesn't care, but you, or the person maintaining the code after you, will appreciate it.
You mention that there's an issue with duplicate order numbers. I'm not seeing that unless the 1., 2., etc are indicating line numbers instead of decimal values. If this is the case, I'd suggest having your code sort the data in an order that makes sense for your purposes, then have your code written in that sorted order. That way, you can expressly handle the duplicate values - for example if OrderNum(row) = OrderNum(row-1) then and check the dates to pick up the newest one.

How to copy paste data based on the number of days per month?

Hi and good day everyone,
Basically I wish to extract the data based on the number of days per month. Please find the link below for better illustration:
https://drive.google.com/open?id=0B15JqLrOZtewamlRQ1ZMTmJZNWc&authuser=0
For example, D1 shows the current month is September. Therefore I will only need to extract the data from day 1-30. Also I will need to copy the ID and paste it at left column of the date for 30 times.
Any idea?
Thanks for your time!
Cheers,
Patch
I'll get you started on the macro code necessary to determine the number of days within a month when the month is spelled out as text.
Dim dys As Long
With ActiveSheet
dys = Day(Application.EoMonth(DateValue(.Cells(1, 4).Value & " 1, " & Year(Date)), 0))
.Cells(2, 7).CurrentRegion.ClearContents
.Cells(2, 7) = "ID"
.Cells(2, 8).Resize(1, 4) = .Cells(2, 1).Resize(1, 4).Value
.Cells(3, 7).Resize(dys, 1) = .Cells(1, 2).Value
.Cells(3, 8).Resize(dys, 4) = .Cells(5, 1).Resize(dys, 4).Value
Debug.Print dys
End With
With the last day of the month determined, it is a small matter to use that to resize the source/target regions of cells. I tried to determine the best guess for the cell addresses from your sample but the merged areas may have fouled things up.