VBA Subtract two dates - excel

I have this problem, I want to subtract two dates from myself, but I still have Run Time Error 13, Type mismarch
The task is to subtract the date from the cell (cell format: Date) today. I can create a cell with today's date but I would prefer not to.
Dim i As Long, j As Long
Dim ark5 As Worksheet
Set ark5 = Worksheets("Zalegle")
Dim LastRow5 As Long
Dim a As Date
LastRow5 = ark5.Cells(Rows.Count, 2).End(xlUp).Row
a = DateDiff("d", Now, ark5.Cells(2, "G"))
For i = LastRow5 To 2 Step (-1)
If Date - a < 7 Then
Rows(i).EntireRow.Delete
i = i - 1
End If
Next i
End Sub```

Using CDate might solve your issue, give this a try :
Dim i As Long, j As Long
Dim ark5 As Worksheet
Set ark5 = Worksheets("Zalegle")
Dim LastRow5 As Long
Dim a As Date
LastRow5 = ark5.Cells(Rows.Count, 2).End(xlUp).Row
a = DateDiff("d", Now, CDate(ark5.Cells(2, "G").value))
For i = LastRow5 To 2 Step (-1)
If Date - a < 7 Then
Rows(i).EntireRow.Delete
End If
Next i
End Sub```

Related

Excel VBA - Using for/to/step generate list of dates between start/stop dates

I have written a macro to expand a range of start/stop dates by 5 minute increments and assigning a "campaign" number to each set of dates. For example, I have a table of dates:
Start
Stop
8/19/15 17:20
8/20/15 2:20
12/13/16 7:30
12/14/16 18:00
5/29/20 22:00
5/31/20 1:00
I want to expand each date range into a table at 5 minute increments (ie, 8/19/15 17:20, 8/19/15 17:25) then assign a label to each set (everything between 8/16/15 17:20 - 8/20/15 2:20 would be considered Campaign 1). I wrote the following code that works as planned, but when the macro gets to the 23:55 hour, the subsequent date is midnight of the previous day:
Date
8/19/15 23:50
8/19/15 23:55
8/19/15 00:00
8/20/15 00:05
Any thoughts on how to prevent the previous day showing up here?
Thanks
The code:
Sub campaignpull()
Dim ROWID As Integer
Dim LASTROW As Long
Dim rng As Range
Dim StartRng As Range
Dim EndRng As Range
ThisWorkbook.Sheets("Sheet1").Activate
LASTROW = ActiveSheet.UsedRange.Rows.Count
For ROWID = 2 To LASTROW
Set StartRng = Cells(ROWID, 1)
Set EndRng = Cells(ROWID, 2)
For i = StartRng To EndRng Step 1 / 24 / 12
ThisWorkbook.Sheets("Sheet2").Cells(Rows.Count, "A").End(xlUp).Offset(1, 0) = i
ThisWorkbook.Sheets("Sheet2").Cells(Rows.Count, "B").End(xlUp).Offset(1, 0) = ROWID - 1
Next
Next ROWID
End Sub
it seems Excel handles Date/Time in a different way than VBA. The solution I found was to use Excel formulas to create the 5 minutes increments. Please take a look at the code below:
Sub CampaignPull()
Dim rowCount As Integer
rowCount = Evaluate("COUNTA(Sheet1!A:A)")
Dim i As Integer
Dim j As Integer
j = 2
Dim startDateTime As Date
Dim endDateTime As Date
For i = 2 To rowCount
startDateTime = Sheets("Sheet1").Range("A" & i)
endDateTime = Sheets("Sheet1").Range("B" & i)
Sheets("Sheet2").Range("A" & j) = startDateTime
Do
j = j + 1
Sheets("Sheet2").Range("A" & j).Formula = "=A" & (j - 1) & "+1/12/24"
Loop While Sheets("Sheet2").Range("A" & j) <= endDateTime
Next i
End Sub
My take, although prior answer was good.
Do as you like with columns:
Sub campaignpull()
Dim rowId As Integer
Dim lastRow As Long
Dim rng As Range
Dim currentTime As Date
Dim endTime As Date
Dim i As Date
Dim rw As Integer
Sheet1.Activate
lastRow = ActiveSheet.UsedRange.Rows.Count
For rowId = 2 To lastRow
currentTime = Sheet1.Cells(rowId, 1).Value
endTime = Sheet1.Cells(rowId, 2).Value
rw = 1
Do Until currentTime > endTime
currentTime = currentTime + 1 / 24 / 12
Sheet2.Cells(rw, rowId) = currentTime
rw = rw + 1
Loop
Next rowId
End Sub

VBA to copy data from one sheet and paste against a range and repeat using LOOP or any other method

Essentially I tried doing using using Macro and see how it records in VBA. I have this dataset where I want to copy company names from a sheet and paste it next to years ranging from 1994-2014. And then repeat the same process for more roughly 800 companies.
I tried doing one with this code but I believe I need to loop the code. Not really a VBA expert just trying to saving time and error using VBA
Sub CopyPaste()
CopyPaste Macro
Sheets("Name").SelectRange("C3").Select
Selection.Copy
Sheets("Stata").Select
Range("B2:B22").PasteSpecial xlPasteValues
ActiveCell.Offset(1, 0).Range("A1").Select
End Sub
This is going to be very crude but the following code will accomplish what you want. Especially if you only need to do this exercise once.
In my example the companies list starts in cell A2 and the output starts in cell D2. I have used 3 years (2019 - 2021)
For the code below, the location (row & col) of the first company are placed in the variables copyRow & copyCol as integers (ie A2 = Row: 2, Col: 1) The first cell of the output location is set in the pasteRow & pasteCol (ie D2 = Row: 2, Col: 4) variables. Also the start year and end year are also set in the startYear and endYear variables.
Basically, from there it is just two nested loops. A while for the companies that allows any number of companies as long as there are no empty cells in the list. The for loop to cycle through each year between startYear and endYear for each company.
Sub copyPaste()
Dim copyWb As Workbook
Dim copySht As Worksheet
Dim pasteRow As Integer
Dim pasteCol As Integer
Dim copyRow As Integer
Dim copyCol As Integer
Dim startYear As Integer
Dim endYear As Integer
Set copyWb = ActiveWorkbook
Set copySht = copyWb.ActiveSheet
copySht.Activate
pasteRow = 2
pasteCol = 4
copyRow = 2
copyCol = 1
startYear = 2019
endYear = 2021
While copySht.Cells(copyRow, copyCol).Value <> ""
For curYear = startYear To endYear
copySht.Cells(pasteRow, pasteCol).Value = curYear
copySht.Cells(pasteRow, pasteCol + 1).Value = copySht.Cells(copyRow, copyCol).Value
pasteRow = pasteRow + 1
Next curYear
copyRow = copyRow + 1
Wend
End Sub
I am trying to make some changes to the code as I want to copy from one and paste in another sheet. I added the variable pasteSht, but when referencing to the pasteSht.pasteRow it's throwing me an error.
Sub copyPaste()
Dim copyWb As Workbook
Dim copySht As Worksheet
Dim pasteSht As Worksheet
Dim pasteRow As Integer
Dim pasteCol As Integer
Dim copyRow As Integer
Dim copyCol As Integer
Dim startYear As Integer
Dim endYear As Integer
Set copyWb = ActiveWorkbook
Set copySht = copyWb.Worksheets("Sheet1")
Set pasteSht = copyWb.Worksheets("Sheet2")
copySht.Activate
pasteRow = 2
pasteCol = 4
copyRow = 2
copyCol = 1
startYear = 2019
endYear = 2021
While copySht.Cells(copyRow, copyCol).Value <> ""
For curYear = startYear To endYear
copySht.Cells(pasteRow, pasteCol).Value = curYear
copySht.Cells(pasteRow, pasteCol + 1).Value = copySht.Cells(copyRow, copyCol).Value
pasteRow = pasteRow + 1
Next curYear
copyRow = copyRow + 1
Wend
End Sub

Finding timedifference in vba

i want to find the time difference in a range. I tried my code below and it didnt return the time difference in seconds but it only generate a value of "0" from the first row to fourth row in column D.
Dim StartDate As Date, EndDate As Date
Dim LastRowOfB As Long, LastRowOfD As Long
Dim ColumnBRngData As Range, ColumnDRngData As Range
LastRowOfB = ActiveSheet.Cells(Rows.Count, 3).End(xlUp).Row
LastRowOfD = ActiveSheet.Cells(Rows.Count, 4).End(xlUp).Row
Set ColumnBRngData = ActiveSheet.Range("B4:B" & LastRowOfB)
Set ColumnDRngData = ActiveSheet.Range("D4:D" & LastRowOfD)
For i = 4 To LastRowOfB
StartDate = ActiveSheet.Cells(i, 2).Value
EndDate = ActiveSheet.Cells(i + 1, 2).Value
ColumnDRngData.Cells = (StartDate - EndDate) * 86400
Next i
I want the time difference to be shown in range D4 and ownwards.
Summarizing the comments:
You can use a formula to do this, no need to use DateDiff here. 1 day = 1 and there are 86400 seconds in a day.
You can write the formula to the entire range without looping:
With ActiveSheet
Dim LastRowOfB As Long
LastRowOfB = .Cells(.Rows.Count, "B").End(xlUp).Row
.Range("D4:D" & LastRowOfB - 1).Formula = "=ROUND((B5-B4)*86400,0)"
End With

Increment date column by VBA excel

if i have a column in excel in following format:
"dd/mm/yyyy hh:mm:ss" and i want to increase the hour value by 1.
I add 1/24 to that cell and is done.
my problem is that files where i need this correction have around 15000 rows and operation is taking around 2 minutes.
the code i use is:
Set rngSel = .Range("A2:A10000")
For Each cell In rngSel
cell.Value = cell.Value + dif / 24
Next cell
is it possible somehow to do it faster?
You could try:
Option Explicit
Sub test()
Dim arr As Variant
Dim Initial_DateTime As Date
Dim i As Long
With ThisWorkbook.Worksheets("Sheet1")
arr = .Range("A2:A10000")
For i = LBound(arr) To UBound(arr)
Initial_DateTime = arr(i, 1)
arr(i, 1) = DateAdd("h", 1, Initial_DateTime)
Next i
.Range("A2:A1000").Value = arr
End With
End Sub
As mentioned in the comments, it is much quicker to load the range into a matrix and handle the incrementation of the dates in memory. I have built upon your code for the following example.
Sub IncrementDateColumnByVBA()
Dim rngSel As Range
Dim DateArray() As Variant
Dim i As Long
Dim dif As Byte
dif = 1
Set rngSel = ActiveSheet.Range("A2:A10")
'Write range to a matrix
DateArray = rngSel.Value
'Loop matrix
For i = LBound(DateArray) To UBound(DateArray)
DateArray(i, 1) = DateArray(i, 1) + dif / 24
Next i
'Write matrix to worksheet
rngSel.Value = DateArray
End Sub

How to make a loop that deletes rows that contain previous dates

I'm creating a loop that is supposed to find cells that have dates before 01/01/2019 and if they find they delete the entire row.
The problem is that if they delete per example row number 2, the code is passing to row 3, but since row 2 was deleted previously the original row 3 would be skipped.
I wrote the loop and tried to add "i = 1 - 1" but the excel never stops running the code and blocks the program
Dim ws As Worksheet
Dim Ldate As Date
Dim N As Long
Ldate = "01/01/2019"
N = ws.Cells(Rows.Count, 8).End(xlUp).Offset(0, 0).Row
For i = 1 To N
If ws.Cells(i, 8).Value < Ldate Then
ws.Rows(i).Delete
' i = 1 - 1
End If
Next i
Don't let Excel guess if this string "01/01/2019" is mm/dd/yyyy or dd/mm/yyyy Never use strings to write a date, instead always use real dates: Ldate = DateSerial(2019, 1, 1) to create dates. String-Dates are very evil! The only use case to cast a real date into a string is to print it on paper or screen. All other cases must use real dates (number formats) to be reliable.
.Offset(0, 0) is usless remove it. Moving 0 rows and 0 columns from current cell will not change current cell at all.
If you delete/add rows then your loops must be backwards in order to row count correctly: For iRow = LastRow To 1 Step - 1
So you end up with something like this
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
Dim Ldate As Date
Ldate = DateSerial(2019, 1, 1)
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, 8).End(xlUp).Row
Dim iRow As Long
For iRow = LastRow To 1 Step - 1
If ws.Cells(iRow , 8).Value < Ldate Then
ws.Rows(iRow).Delete
End If
Next iRow
Alternative if you use a forward loop, you need to collect the rows to delete in a Range variable and delete it at once after the loop is finished. This way deleting doesn't affect the row counting inside the loop (because we delete after the loop):
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
Dim Ldate As Date
Ldate = DateSerial(2019, 1, 1)
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, 8).End(xlUp).Row
Dim RowsToDelete As Range
Dim iRow As Long
For iRow = 1 To LastRow
If ws.Cells(iRow , 8).Value < Ldate Then
If RowsToDelete Is Nothing Then
Set RowsToDelete = ws.Rows(iRow)
Else
Set RowsToDelete = Union(RowsToDelete, ws.Rows(iRow))
End If
End If
Next iRow
If Not RowsToDelete Is Nothing Then
RowsToDelete.Delete
End If
Actually this approach should be faster because it only performs one delete action in the end (instead of one per deleted row).
Edit according comments:
Test if a worksheet exists before you use it.
Option Explicit
Function WorksheetExists(ByVal WorksheetName As String, Optional ByVal InWorkbook As Workbook) As Boolean
'default workbook is ThisWorkbook
If InWorkbook Is Nothing Then
Set InWorkbook = ThisWorkbook
End If
Dim ws As Worksheet
On Error Resume Next
Set ws = InWorkbook.Worksheets(WorksheetName)
On Error GoTo 0
WorksheetExists = Not ws Is Nothing
End Function
Then use it like
If WorksheetExists("Sheet1") Then …
'or to test for a worksheet in a different workbook
If WorksheetExists("Sheet1", Workbooks("OtherWorkbook.xlsx")) Then
The simplest way is to change
For i = 1 To N
to
For i = N To 1 step -1
This way when your row is deleted it will not change the number of the following rows as these will be lower numbered rows.

Resources