How to Test if a Date Falls within a Certain Range and Copy the Entire Row if So Using VBA - excel

I have a file tjhat is serving as a log of product expirations. We track it by two dates, the date as provided by the manufacturer as well as the "Effective Expiration Date". The latter is the date in which the product would expire before someone could use it as directed.
Each year is a separate Worksheet (2022, 2023, 2024, etc.) with a table named after it (_2022, _2023, etc.).
We would like to create a Macro that will go through the the current year's table as well as the one for the next two years searching for a date that falls within the range of today's date through a week later. If it finds a match, the row should be copied over to a new sheet called "Weekly Exp" that is created by the Macro.
So if I ran it today, 12/17/2022, it will search for anything with an Effective Expiration Date between 12/17/2022 and 12/24/2022.
Here is what I have so far:
Sub weeklyExpirationSheet()
Dim dtToday As Date
Dim dtWeekOut As Date
Dim dtEffExp As Date
Dim dtTest As Date
Dim theYear As String
Dim countDays As Long
Dim ws As Worksheet
Dim srcSheet As Worksheet
Dim destSheet As Worksheet
Dim srcTable As ListObject
Dim srcRow As Range
dtToday = Date
dtWeekOut = DateAdd("ww", 1, dtToday)
countDays = DateDiff("d", dtToday, dtWeekOut)
For Each ws In ActiveWorkbook.Worksheets
If ws.Name = "Weekly Exp" Then
MsgBox "Weekly Audit Sheet Already Exists!"
Exit Sub
End If
Next ws
Sheets.Add(After:=Sheets("Incoming")).Name = "Weekly Exp"
Set destSheet = Worksheets("Weekly Exp")
With destSheet
Range("A1").Value = "UPC"
Range("B1").Value = "Brand"
Range("C1").Value = "Product"
Range("D1").Value = "Sz"
Range("E1").Value = "Expr"
Range("F1").Value = "Eff Exp"
Range("G1").Value = "Qty"
Range("H1").Value = "Location"
dtCurrentYear = CDbl(Year(Date))
dtEndYear = CDbl(dtCurrentYear + 2)
For y = dtCurrentYear To dtEndYear
Set srcSheet = Worksheets(CStr(y))
Set srcTable = srcSheet.ListObjects("_" & CStr(y))
With srcSheet
LastRow = .Cells(Rows.Count, "A").End(xlUp).Row
For p = 2 To LastRow
dtTest = .Cells(p, "F").Value
If dtTest >= dtToday And dtTest <= dtWeekOut Then
destLastRow = destSheet.Cells(Rows.Count, "A").End(xlUp).Row + 1
Rows(p).Copy Destination:=destSheet.Rows(destLastRow)
End If
Next p
End With
Next y
End With
End Sub
The code for getting the dates and such is working as is the detection/creation of the Worksheet. However when I run the Macro, it runs for a long period of time (like 3-5min) and then gives a Type Mismatch error. Nothing gets copied.
I did replace the copying code with MsgBox that would just display matches, it was going beyond the range. It reported an item that had a date of 12/31/2022 for example.
Edit:
This is what the data looks like

Your condition is missing the And operator so it always evaluates to True,
Write it like this:
If dtTest >= dtToday And dtTest <= dtWeekOut Then

Related

Obtain a list of information Pertaining to a Specific Month

I have trouble running this script to obtain Summary information for a specific month. I am explaining below the details of my workbook.
Tab 1 called "Schedule"
Tab 2 called "Results"
Tab 3 called "Sheet3"
I would like to obtain info from column C (Summary) in tab1 for the month of July. I am entering the month in tab2 and would like to run the macro and obtain all the results pertaining to the month of July.
Sub schedule()
Dim sch As Workbook
Dim schTot As Worksheet
Dim schRes As Worksheet
Dim i As Long
Dim j As Long
Let sch = Thisworkbook
Let schRes = sch.Worksheets("Results")
Let schTot = sch.Worksheets("Schedule")
For i = 1 To schTot.Range("A1").End(xlDown)
For j = 3 To schRes.Range("B3").End(xlDown)
If schTot.Cells(i, 1).Value = schRes.Cells(1, 2).Value Then
If schRes.Cells(j, 1).Value = "" Then
schTot.Rows(i).Copy
schRes.Cells(j, 1).Paste
Application.CutCopyMode = False
'Exit For
End If
End If
Next j
Next i
End Sub
Try this:
Option Explicit
Sub schedule()
Dim sch As Workbook
Dim schTot As Worksheet
Dim schRes As Worksheet
Dim i As Long
Dim j As Long
Dim strMonth As String
With ThisWorkbook
Set schRes = .Worksheets("Results")
Set schTot = .Worksheets("Schedule")
End With
schRes.Range("A3:C" & schRes.Cells(3, 1).End(xlDown).Row).ClearContents
strMonth = schRes.Cells(1, 2).Value
i = 2
j = 3
With schTot
Do Until .Cells(i, 1).Value = ""
If .Cells(i, 1).Value = strMonth Then
schRes.Range("A" & j & ":C" & j).Value = .Range("A" & i & ":C" & i).Value
j = j + 1
End If
i = i + 1
Loop
End With
End Sub
For your code, you just need to change following things to get it run:
-use "Set" instead of "Let"
Set sch = Thisworkbook
Set schRes = sch.Worksheets("Results")
Set schTot = sch.Worksheets("Schedule")
-return row's number in for loop condition
For i = 1 To schTot.Range("A1").End(xlDown).Row
For j = 3 To schRes.Range("B3").End(xlDown).Row
Then your code will be ok to run, but if your B3 cell in Results worksheet don't have value or following cells(i.e. B4,B5,B6...) doesn't have vale, your code will run infinitely and crush eventually.
Also, you copy a entire row in loop every single time which contain unnecessary cells. This will horribly slow down your code.
To speed up the code, I recommend to use auto filter to solve the problem:
Sub sechedule()
Dim sch As Workbook: Set sch = ThisWorkbook
Dim schTot As Worksheet: Set scTot = sch.Worksheets("Schedule")
Dim schRes As Worksheet: Set schRes = sch.Worksheets("Results")
Dim month As String
month = Range("B1").Value 'The month you inputted in Results worksheet
'I suppose you want to paste the result to Results worksheet starting from Cell A3, so the contents will be cleared first each time if somethings are in the result area:
If Range("A3").Value = "" Then Range("A3:C" & Range("A" & Rows.Count).End(xlUp).Row).ClearContents
With schTot
.Activate
.Range("A:C").AutoFilter Field:=1, Criterial:=month 'Choose data for specific month with auto filter
.Range("A2:C" & Range("A" & Rows.Count).End(xlUp).Row).SpecialCells(xlCellTypeVisible).Copy Destination:=schRes.Range("A3") '<--You can change the paste destination here
.ShowAllData
.Range("A:C").AutoFilter 'Cancel auto filter
End With
schRes.Activate
End Sub

VBA for loop only returning one value when there are more that meet the criteria

I am trying to transfer stock transactions from a transaction workbook to another book that has the formatting i want. I want to be able to change the client name and stock at the top of the code so it makes it easier to run for multiple people. the problem is that when i run this it only returns one date in my formatted worksheet when i can see that there are 3 stock trades for the given ticker with different dates in the transaction book. it seems like the FOR function isn't looping through all the rows in the transaction book but im not sure why
Sub SortTransactionData()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = Workbooks("Allen Smith Transactions.xlsx")
Set ws = wb.Sheets("Sheet1")
Dim wb1 As Workbook
Dim ws1 As Worksheet
Set wb1 = Workbooks("Allen Smith HI.xlsm")
Set ws1 = wb1.Sheets("MO")
Dim ticker As String
ticker = ws1.Range("A2")
Dim a As Integer
a = ws.Cells(Rows.Count, 6).End(xlUp).Row
Dim b As Integer
b = Application.WorksheetFunction.CountIf(ws1.Range("B1:B7"), "*")
For i = 2 To a
'copy date for stock transaction'
If ws.Cells(i, 6).Value = ticker Then
ws1.Cells(b + 1, 2).Value = ws.Cells(i, 1)
End If
Next
End Sub
As mentioned in comments, the problem is that cell ws1.Cells(b + 1, 2) never changes, so you keep overwriting old values as you go through your loop
Change your code to increment the index, b, each time through the loop:
For i = 2 To a
'copy date for stock transaction'
If ws.Cells(i, 6).Value = ticker Then
ws1.Cells(b + 1, 2).Value = ws.Cells(i, 1)
b = b + 1
End If
Next i

Sumif Returning Same Value

I got below table that I need to fill with data based on current month (Worksheet "PR"):
An example of the raw data looks like (Worksheet "CSV Data PR"):
I have two issues:
SumIF only works for the first region, all the others take the same data. As example, correct data shows below Feb.
For some reason it pulls the formula down all the way..., whilst it should stop at Western Europe. I am not sure why that is the case.
Based on the following piece of code:
Sub TableDataTest()
Dim rngHdrFound, rngHdrFound2, findrng, USDRng, RegionRNG, rngHeaders, RngHeadersOutPut As Range
Dim x, y As Worksheet
Dim ThisMonth As Date
Dim index As Variant
Application.ScreenUpdating = False
'Set Worksheets
Set x = ThisWorkbook.Sheets("CSV Data PR")
Set y = ThisWorkbook.Sheets("PR")
index = y.Range("D8")
ThisMonth = Format(Date, "MM/YYYY")
'Set HeaderRow
Const ROW_HEADERS As Integer = 1
Set rngHeaders = Intersect(Worksheets("CSV Data PR").UsedRange, Worksheets("CSV Data PR").Rows(ROW_HEADERS))
Set RngHeadersOutPut = y.Range("6:6")
Set rngHdrFound = rngHeaders.Find("In USD")
Set rngHdrFound2 = rngHeaders.Find("Region")
Set findrng = RngHeadersOutPut.Find(What:=ThisMonth, LookIn:=xlFormulas, lookat:=xlWhole)
Set USDRng = Range(rngHdrFound.Offset(1), rngHdrFound.End(xlDown))
Set RegionRNG = Range(rngHdrFound2.Offset(1), rngHdrFound2.End(xlDown))
'Find CurrentMonth + Range
With y
If findrng Is Nothing Then
MsgBox "Error, unable to match " & ThisMonth & " in the specified range", vbCritical
Exit Sub
Else
findrng.Offset(2, 0).Resize(Selection.Rows.Count + 8).Value = Application.WorksheetFunction.SumIf(RegionRNG, "=" & index, USDRng)
End If
End With
Application.ScreenUpdating = True
End Sub
You could try this:
Option Explicit
Sub TableDataTest()
Dim ws As Worksheet, wsData As Worksheet, MonthCol As Integer, ThisMonth As Date, C As Range, _
x As Integer, y As Integer
x = 2 'Number of the column with the region
y = 3 'Number of the column with the data to sum
With ThisWorkbook
Set ws = .Sheets("PR")
Set wsData = .Sheets("CSV Data PR")
End With
ThisMonth = Format(wsData.Range("C2"), "MM/YYYY")
With ws
MonthCol = .Cells.Find(ThisMonth, LookIn:=xlFormulas, lookat:=xlWhole).Column
For Each C In .Range(.Cells(3, Col), .Cells(11, Col))
C = Application.SumIf(wsData.Columns(x), .Cells(C.Row, 1), wsData.Columns(y))
Next C
End With
End Sub
You only need to find the column where the month is on the table, and then hardcode the rows you wanna work in because as for I can see, they are always the same and unlikely to grow.
PS: I'm assuming the table starts on row 3 and column A, otherwise change the starting row 3 on the For Each C range and the criteria inside the sumif taking column 1.

EXCEL VBA copy data from a week into a different sheet

I have 2 sheets in a workbook, one has all the data ("hdagarb") and the other is "summary". In the data sheet, column 2 has names and column 5 has dates. These are the columns I'm concerned with. I want to get all the rows which fall within say week ending 9th of June, and copy the name in column 2 and the date in column 5 and paste it into my summary sheet. At the moment I can't even get it to copy and paste the column 2 names. Here is my code:
Sub finddata()
Dim todaysdate As Date
Dim thisweek As Date
Dim lastweek As Date
Dim finalrow As Long
Dim Rdate As Date
Dim i As Long
Sheets("Summary").Range("H5:H1000").ClearContents
todaysdate = Date
thisweek = (7 - Weekday(todaysdate, vbSaturday)) + todaysdate
lastweek = (7 - Weekday(todaysdate, vbSaturday)) + todaysdate - 7
finalrow = Sheets("HDAGarb").Range("A100000").End(xlUp).Row
For i = 2 To finalrow
Rdate = Sheets("hdagarb").Cells(i, 5)
If Rdate > lastweek Then
Sheets("hdagarb").Cells(i, 2).Copy
Sheets("Summary").Range("H100").End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats
End If
Next i
Worksheets("summary").Activate
Worksheets("summary").Range("H5").Select
End Sub
The source data in column 5 is like this
02-Jun-2017
-
-
-
-
12-Apr-2017
01-May-2017
I want the script to ignore the entries without dates ("-").
The following code will only perform the copy if there is a valid date in column E:
Sub finddata()
Dim todaysdate As Date
Dim thisweek As Date
Dim lastweek As Date
Dim finalrow As Long
Dim newRow As Long
Dim Rdate As Date
Dim i As Long
Dim srcSheet As Worksheet
Dim dstSheet As Worksheet
todaysdate = Date
thisweek = (7 - Weekday(todaysdate, vbSaturday)) + todaysdate
lastweek = (7 - Weekday(todaysdate, vbSaturday)) + todaysdate - 7
Set srcSheet = Worksheets("HDAGarb")
Set dstSheet = Worksheets("Summary")
finalrow = srcSheet.Range("A" & srcSheet.Rows.Count).End(xlUp).Row
dstSheet.Range("H5:H" & dstSheet.Cells(dstSheet.Rows.Count, "H").End(xlUp).Row).ClearContents
newRow = 4
For i = 2 To finalrow
If IsDate(srcSheet.Cells(i, "E").Value) Then
Rdate = CDate(srcSheet.Cells(i, 5).Value)
If Rdate > lastweek Then 'or If Rdate > lastweek And Rdate <= thisweek Then '???
newRow = newRow + 1
srcSheet.Cells(i, "B").Copy
dstSheet.Cells(newRow, "H").PasteSpecial xlPasteFormulasAndNumberFormats
'Not sure whether you wanted the next two lines
srcSheet.Cells(i, "E").Copy
dstSheet.Cells(newRow, "I").PasteSpecial xlPasteFormulasAndNumberFormats
End If
End If
Next i
dstSheet.Activate
dstSheet.Range("H5").Select
End Sub
I also changed it to keep track of the row being written to in the Summary sheet so that, if one of the names in the HDAGarb sheet was blank, it would still copy it and the associated date. (It's also faster if you don't have to keep recalculating which is the last row.)

How do I create code in VBA/macros for birthday notice?

For instance, I have a sheet which contains names of 100+ people. In column H I have their birth dates. What will the code look like if I want to find out which friend's birthday is today? Of course the macro will need to run through that column and see if today's date matches one with in column H. I have very little experience with VBA/Macros. Please and thank you for your help.
This code will put a message on I column if someone' birthday is today as per H column. (Assuming G column has person's name.
Sub BirthdayAlert()
Dim lastRow As Long
Dim ws As Worksheet
Dim varArray As Variant
Dim lb As Long
Dim i As Integer
Set ws = Sheets("Sheet1")
lastRow = ws.Range("H" & Rows.Count).End(xlUp).Row
varArray = Application.Transpose(ws.Range("H2:H" & lastRow).Value)
lb = LBound(varArray)
For i = LBound(varArray) To UBound(varArray)
If IsDate(varArray(i)) Then
If CDate(varArray(i)) = Date Then
varArray(i) = "Today is Your Birthday " & Range("G2").Offset(i).Value
Else
varArray(i) = ""
End If
End If
Next i
If UBound(varArray) > 0 Then
ws.Range("I2:I" & lastRow).Value = Application.Transpose(varArray)
End If
End Sub
Here's something simple for it:
Sub birthdayThing()
Dim rng As Range
For Each rng In Range("H2:H100")
If CDate(rng) = Date Then rng.Offset(0, 1).Value = "Birthday"
Next rng
End Sub

Resources