how to extend the following excel VBA code [duplicate] - excel

This question already has answers here:
Expand Start Date to End Date with Series of EOMONTHs
(2 answers)
Closed 5 years ago.
I want to generate month ending wise data for a given start and end period; number of months is varying for different applicants.
The following data is to be generated by user input and may vary in number per applicant:
Column ‘A’ -- month ending date
Column ‘B’ -- EMI
Column 'C' -- interest portion
Column ‘D’ -- principle portion
and so on.
I also want to calculate sum of each column at end and the row changing the size of sheet based on column “A” no of rows. Please help.
Sub GenerateDates()
Dim startDate As Date
Dim endDate As Date
Dim currentDate As Date
startDate = Range("b4").Value
endDate = Range("b8").Value
currentDate = startDate
Range("a17").Select
Do Until currentDate = endDate
ActiveCell.Value = currentDate
ActiveCell.Offset(1, 0).Select
'currentDate = DateAdd("m", 1, currentDate)
currentDate = DateSerial(Year(currentDate), Month(currentDate) + 2, 0)
Loop
End Sub

#Anil try this:
Sub GenerateDates()
Dim startDate As Date
Dim endDate As Date
Dim currentDate As Date
Dim cnt As Integer
startDate = Range("b2").Value
endDate = Range("b3").Value
currentDate = startDate
Range("a9").Select
cnt = ActiveSheet.Range("E3")
ActiveSheet.Range(ActiveSheet.Range("A10"), ActiveSheet.Cells(Rows.Count, Columns.Count)).ClearContents
With ActiveSheet.Range(ActiveSheet.Range("A9"), ActiveSheet.Range("A9").End(xlToRight))
.Copy
.Offset(1).Resize(cnt - 1).PasteSpecial xlPasteAll
End With
Application.CutCopyMode = False
For i = 1 To Range("A8").End(xlToRight).Column - Range("A8").Column
Range("A8").Offset(cnt + 1, i) = WorksheetFunction.Sum(Range("A8").Offset(1, i).Resize(cnt))
Next
End Sub
Click here to download the solution.
In the excel, there are 5 columns: End of month Date, EMI, Interest, Principal, Amount Outstanding. You have to 4 input fields: Start Period, End Period, Amount, Interest. The Calculate button runs the above macro. The first row, i.e. the 9th row has the formulas and are copy and pasted for the number of periods to get the dates and calculations. At the end, the summation of columns is taken. I hope this solves your problem!

Please try the following edit based on what I can understand on what you want to do:
Sub GenerateDates()
Dim startDate As Date
Dim endDate As Date
Dim currentDate As Date
Dim ws as Worksheet
Dim iRow As Long
Set ws = Worksheets("Sheet1") 'or whatever name of sheet you have
Set wbDesti = Workbooks.Open("C:\Users\...\DestinationFile.xlsx") ' <<< path to source workbook
Set sh = wbDesti.Worksheets("Sheet1") 'Sheet in destination file
'automatically find the last row in Sheet A.
iRow = ws.Cells.Find(What:="*", SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, LookIn:=xlValues).row + 1
startDate = ws.cells(1,1).Value
endDate = ws.cells(2,1).Value
currentDate = startDate
'Range("a17").Select 'removed this to avoid .Select functions
dim row as integer 'declare another variable for row...
'row = iRow
'Do Until currentDate = endDate
'ws.cells(row,1).value = currentDate
'row = row + 1
'currentDate = DateAdd("m", 1, currentDate)
'currentDate = DateSerial(Year(currentDate), Month(currentDate) + 2, 0)
'Loop
Dim col as integer
col = 2 'start with B
Do until col = 4
sh.cells(1,col) = application.worksheetfunction.sum(ws.range("B"&10&":"&"B"&":"&60))
'***other codes goes here to transfer data same as above.
col = col + 1
Loop
wbDesti.quit
Set sh = Nothing
End Sub

Related

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

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

Delete date that falls outside of inputted month

I'm creating a sub that formats a new time sheet. I need it to delete dates that fall outside of the inputted month (in this case, June, 2020). The code autofills the next 30 days after the first day, which covers the maximum days in a month (31 days), but also adds date for the first day(s) in the next month if the inputted month has less than 31 days. Here is my code:
Sub Calendar_Genorator3()
Dim WS As Worksheet
Dim MyInput As Variant
Dim StartDay As Variant
Dim DayofWeek As Variant
Dim CurYear As Variant
Dim CurMonth As Variant
Dim FinalDay As Variant
Dim Cell As Range
Dim RowCell As Long
Dim ColCell As Long
Dim Day1 As Range
Set WS = ActiveWorkbook.ActiveSheet
WS.Range("A1:R100").Clear
MyInput = InputBox("Type in Month and year for Calendar ")
If MyInput = "" Then Exit Sub
' Get the date value of the beginning of inputted month.
StartDay = DateValue(MyInput)
' Check if valid date but not the first of the month
' -- if so, reset StartDay to first day of month.
If Day(StartDay) <> 1 Then
StartDay = DateValue(Month(StartDay) & "/1/" & _
Year(StartDay))
End If
'Set headers
Range("a1").Value = Application.Text(MyInput, "mmmm") & " Time Sheet"
Range("a2") = "Day"
Range("c2") = "Time In"
Range("d2") = "Time Out"
Range("e2") = "Hours"
Range("f2") = "Notes"
Range("g2") = "Overtime"
'Set weekdays
Range("a3") = "Sunday"
Range("a4") = "Monday"
Range("a5") = "Tuesday"
Range("a6") = "Wednesday"
Range("a7") = "Thursday"
Range("a8") = "Friday"
Range("a9") = "Saturday"
DayofWeek = Weekday(StartDay)
' Set variables to identify the year and month as separate variables.
CurYear = Year(StartDay)
CurMonth = Month(StartDay)
' Set variable and calculate the first day of the next month.
FinalDay = DateSerial(CurYear, CurMonth + 1, 1)
' Place a "1" in cell position of the first day of the chosen month based on DayofWeek.
Select Case DayofWeek
Case 1
Range("b3").Value = 1
Case 2
Range("b4").Value = 1
Case 3
Range("b5").Value = 1
Case 4
Range("b6").Value = 1
Case 5
Range("b7").Value = 1
Case 6
Range("b8").Value = 1
Case 7
Range("b9").Value = 1
End Select
'Loop through range b3:b44 incrementing each cell after the "1" cell.
For Each Cell In Range("b3:b44")
RowCell = Cell.Row
ColCell = Cell.Column
'Do if "1" is in column B or 2.
If Cell.Row = 1 And Cell.Column = 2 Then
' Do if current cell is not in 1st column.
ElseIf Cell.Row <> 1 Then
If Cell.Offset(-1, 0).Value >= 1 Then
Cell.Value = Cell.Offset(-1, 0).Value + 1
' Stop when the last day of the month has been entered.
If Cell.Value > (FinalDay - StartDay) Then
Cell.Value = ""
' Exit loop when calendar has correct number of days shown.
Exit For
End If
End If
End If
Next
For Each Cell In Range("b3:b9")
If Cell.Value = "" Then
Cell.EntireRow.Clear
End If
Next
'Clears rows without dates
For Each Cell In Range("b3:b9")
If Cell.Value = "" Then
Cell.EntireRow.Delete
End If
Next
'Deletes top rows without dates; needs a loop to successfully delete all empty rows
Range("b2") = "Date"
'Added "Date" in later so date insert works
Set Day1 = WS.Cells.Find(What:="1", LookIn:=xlValues, _
lookat:=xlWhole, searchorder:=xlByColumns, searchdirection:=xlNext, _
MatchCase:=True, SearchFormat:=False)
'Find start day, which is day 1
If Not Day1 Is Nothing Then
Day1.Value = Application.Text(MyInput, "mmm-d")
End If
With Day1
Day1.AutoFill Destination:=Range("B3:B33"), Type:=xlFillDefault
End With
'These final lines of code don't delete ranges with dates that fall outside of the inputted month, because FinalDay doesn't refer to the last day of the month. I need to come up with something that refers to the last day of the month.
FinalDay.Select
With Selection
Cell.Offset(-1).End(xlDown).EntireRow.Delete
End With
End Sub
Here's the output of this code. Any ideas on how to delete the rows that have dates that fall outside of the inputted month? I'm also open to writing this sub an entirely different way; I did it this way because I'm basing it on MS template code.
Yours is a very nice effort. With the code below I have taken a different approach. I hope you will like to study it. I've added lots of comments.
Sub Calendar_Generator()
' 046
Dim Ws As Worksheet
Dim MyInput As String ' InputBox generates a string
Dim StartDay As Date ' this must be date
Dim Sp() As String ' working array
Dim i As Integer ' looping index
Dim R As Long ' row counter
Set Ws = ActiveWorkbook.ActiveSheet ' not a good idea. Always specify the tab by name!
Ws.Range("A1:R100").Clear
Do
MyInput = InputBox("Enter the start date for the Calendar:")
If MyInput = "" Then Exit Sub
Loop While Not IsDate(MyInput) ' repeat if entry isn't recognized as a date
' Set the date value of the beginning of inputted month.
' -- regardless of the day the user entered, even if missing
StartDay = DateSerial(Year(CDate(MyInput)), Month(CDate(MyInput)), 1)
'Set headers
Range("a1").Value = Format(StartDay, "mmmm") & " Time Sheet"
Sp = Split("Day,Date,Time In,Time Out,Hours,Notes,Overtime", ",")
For i = 0 To UBound(Sp)
Ws.Cells(2, 1 + i).Value = Sp(i) ' always specify the worksheet
Next i
' fill the days for the selected month
' == the last day of a month is always the day before the first of the next
' here deducting 2 to count from 0
For R = 0 To Day(DateAdd("m", 1, StartDay) - 2)
With Ws.Cells(3 + R, 2)
.Value = StartDay + R
.NumberFormat = "d-mmm"
.Offset(, -1).Value = StartDay + R
.Offset(, -1).NumberFormat = "dddd"
End With
Next R
End Sub
If you look at the declarations, four out of six - two thirds of their total - are used for code management. That shows where my focus was, and the result is shorter, more efficient code. Much of this was achieved by following a simple rule (which the macro recorder doesn't seem to know): Use cell addressing syntax for addressing cells and range addressing syntax only for addressing ranges of cells. Cell coordinates are easy to calculate and use in loops.

VBA for Extracting Data Between 2 Dates From Different Product Sheets to Main sheet

I'm trying to Extract Products Sales From Different Sheets depends on DATES( Between Two Dates), In the mainsheet, I have Two Columns : A for Dates; B for Sales Numbers. I'm new to VBA and trying to write code from learnt Youtube Videos, So far I can be able retrieve Only Column A values i.e, Only Dates, But I could not get the Sales values along with the Dates. I'm writing the Code Down here, Could you please check it once and let me know where and what exactly the mistake arise, your Suggestion Could helpful to me. Thank you in Advance. :)
Private Sub CommandButton1_Click()
Dim sh As Worksheet, Psh As String, x As Date, y As Date
Sheet8.Columns("A").NumberFormat = "m/d/yyyy"
Psh = Me.Shproducts ' Shproducts is Command Button Name
Set sh = Worksheets(Psh)
x = CDate(Me.TextBox1) ' Start Date
y = CDate(Me.TextBox2) ' End Date
Dim i As Long, Myrange As Range, Lastrow As Long
For i = 3 To sh.Range("F" & Rows.Count).End(xlUp).Row
If sh.Cells(i, 1) >= x And sh.Cells(i, 1) <= y Then
Sheet8.Range("A1000").End(xlUp).Offset(1, 0) = sh.Cells(i, 1)
Sheet8.Range("B1000").End(xlUp).Offset(1, 0) = sh.Cells(i, 2)
End If
Next i
End Sub
i haven't tested it, but you might want to do something like this. so this is based on your code:
Private Sub CommandButton1_Click()
Dim sh As Worksheet, Psh As String, x As Date, y As Date
Dim i As Long, Myrange As Range, Lastrow As Long
Dim destinationRange As Range, c As Range, sourceRange As Range
Dim counter As Long
Dim currentDate As Date, currentSales As Double
Sheet8.Columns("A").NumberFormat = "m/d/yyyy"
Psh = Me.Shproducts ' Shproducts is Command Button Name
Set sh = Worksheets(Psh)
x = CDate(Me.TextBox1) ' Start Date
y = CDate(Me.TextBox2) ' End Date
Set destinationRange = Sheet8.Range("A100000").End(xlUp).Offset(1, 0)
Set sourceRange = Range(sh.Range("F3"), sh.Range("F3").End(xlDown))
For Each c In sourceRange
currentDate = c.Value
currentSales = c.Offset(0, 1).Value
If currentDate >= x And currentDate <= y Then
destinationRange.Offset(counter, 0).Value = currentDate
destinationRange.Offset(counter, 1).Value = currentSales
counter = counter + 1
End If
Next i
End Sub

Entering a date array on a sheet converts to American format

I have an array of dates in VBA. If I print it to the sheet one date at a time everything is perfect. However, when I print the entire array to a column in bulk, the date format changes from (dd/mm/yy) to (mm/dd/yy). So May 7th is converted to July 5th and May 25th is not formatted as date on the sheet.
Here is my code.
(Another smaller problem: how can I get rid of the need to transpose when printing to a column? This piece of "pseudo code" is executed 30K times.)
Public Sub test05()
Dim dt As Date, fromDate As Date, toDate As Date
Dim dayCounter As Integer
Dim sheet As Worksheet
Dim dtArr() As Date
Set sheet = Sheets("Sheet1")
fromDate = DateSerial(2018, 8, 6)
toDate = DateSerial(2023, 8, 5)
sheet.Cells.ClearContents
dayCounter = 0
For dt = fromDate To toDate
wd = Weekday(dt)
If wd = 1 Or wd = 7 Then
'skip weekends
GoTo NextDayIteration
End If
dayCounter = dayCounter + 1
ReDim Preserve dtArr(1 To dayCounter)
dtArr(dayCounter) = dt
'print the dates (one by one) to the sheet in column 1
sheet.Cells(dayCounter, 1).Value2 = dt
NextDayIteration:
Next 'end of each day
'print all the dates array to the sheet in bulk, in column 2
Dim rng As Range
With sheet
Set rng = .Range(.Cells(1, 2), .Cells(UBound(dtArr) - LBound(dtArr) + 1, 2))
End With
rng.Value2 = Application.Transpose(dtArr)
End Sub
Don't use Transpose or Preserve. You can do something like this instead:
Public Sub test05()
Dim dt As Date, fromDate As Date, toDate As Date
Dim dayCounter As Long
Dim sheet As Worksheet
Dim dtArr() As Date
Set sheet = Sheets("Sheet1")
fromDate = DateSerial(2018, 8, 6)
toDate = DateSerial(2023, 8, 5)
ReDim dtArr(1 To toDate - fromDate + 1, 1 To 1)
sheet.Cells.ClearContents
dayCounter = 0
For dt = fromDate To toDate
wd = Weekday(dt)
Select Case wd
Case 1, 7
'skip weekends
Case Else
dayCounter = dayCounter + 1
dtArr(dayCounter, 1) = dt
'print the dates (one by one) to the sheet in column 1
sheet.Cells(dayCounter, 1).Value2 = dt
End Select
Next 'end of each day
'print all the dates array to the sheet in bulk, in column 2
Dim rng As Range
With sheet
Set rng = .Range(.Cells(1, 2), .Cells(dayCounter, 2))
End With
rng.Value2 = dtArr
End Sub

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.)

Resources