Entering a date array on a sheet converts to American format - excel

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

Related

VBA Find & Replace Changes Date To US Format

when I run find and replace through vba it changes my dates to us format. So I have a column of dates, but they are all prefixed with text that I want to remove (like so Invoice Date:dd/mm/yyyy). When I use Ctrl + F and replace manually, it's all great. Removes the text, the date remains in it's original format dd/mm/yyyy. However, when using vba to do this it changes the dates to mm/dd/yyyy if the the day is less than 12 (ie months in a year). I've tried a number of different methods to convert it but they all seem to have the same problem. Here is my latest failure...
Sub DateConvert()
Sheets("Sheet1").Select
Dim strValue As String
Dim RowCount As Integer
Dim x As Integer
Dim DateValue As Date
RowCount = WorksheetFunction.CountA(Range("C1", Range("C1").End(xlDown)))
For x = 2 To RowCount
'changes cell value to a string
strValue = Cells(x, 3).Value
'removes unwanted text
Cells(x, 3).Replace _
What:="Invoice Date:", Replacement:=""
'changes to string to desired date format
DateValue = Cells(x, 3).NumberFormat = "dd/mm/yyyy"
Next x
End Sub
Please, someone spare me this misery before either the laptop or me go out the window.
Thanks in advance
Dates are extremely annoying to work with. Your best bet for making sure you're working with the correct date is to use the DateSerial function, and then format the output as desired:
Sub DateConvert()
Dim ws As Worksheet: Set ws = ActiveWorkbook.Worksheets("Sheet1")
Dim rData As Range: Set rData = ws.Range("C2", ws.Cells(ws.Rows.Count, "C").End(xlUp))
If rData.Row < 2 Then Exit Sub 'No data
'Load range data into an array
Dim aData() As Variant
If rData.Cells.Count = 1 Then
ReDim aData(1 To 1, 1 To 1)
aData(1, 1) = rData.Value
Else
aData = rData.Value
End If
'Loop over array and perform conversion
Dim aDateValues As Variant
Dim i As Long
For i = 1 To UBound(aData, 1)
aDateValues = Split(Replace(aData(i, 1), "Invoice Date:", vbNullString), "/") 'Remove the extra text and pull the date values
aData(i, 1) = DateSerial(aDateValues(2), aDateValues(1), aDateValues(0)) 'Use DateSerial to guarantee correct date
Next i
'Output results to sheet with desired date format
With rData
.Value = aData
.NumberFormat = "dd/mm/yyyy"
End With
End Sub

Finding a text string yyyymm based on current year and month

I need to locate all cells within column L starting from Row 10 containing yyyymm+2 (202009).
In other words, I'm looking for cells containing all dates belonging to the month 2 months in advance of the current month. Valid values would be 20200901 up until 20200930 accordingly as of July 2020.
The Column L contains values in text format such as 20201120, 20210102, etc. All the values are dates in Column L formatted as text as 'yyyymmdd'.
I'm trying to use the code below, but it is quite clearly wrong, since +2 won't show the correct year or month if the year changes.
Dim strSearchText As String
Dim y As Integer
Dim m As Integer
m = DatePart("mm", Date) + 2
y = DatePart("yyyy", Date)
strSearchText = y & m
Dim rngSearchArea As Range
Set rngSearchArea = ws.Range(Range("L10"), ws.Range("L" & ws.Range("L:L").Cells.Count).End(xlUp))
Any ideas how to solve this?
Maybe you are just looking for something like that?
String containing today + 2 months in the yyyydd format:
str = Format(DateAdd("m", 2, Now()), "yyyymm")
Please test the next code. Since you did not answer my above question, it will return the range of processed dates in the column N:N, starting from the tenth row:
Sub GetDateTwoMonthMore()
Dim sh As Worksheet, arr As Variant, arrF As Variant, lastRow As Long
Dim El As Variant, k As Long, currMonth As Long
Set sh = ActiveSheet 'use here your sheet
lastRow = sh.Range("L" & Rows.count).End(xlUp).row
currMonth = CLng(Month(Date)) 'the current month reference
arr = sh.Range("L10:L" & lastRow).Value 'load the range to be processed in an array
ReDim arrF(1 To UBound(arr, 1)) 'Redim the final array at the initial dimension of all the range rows
For Each El In arr
If CLng(Mid(El, 5, 2)) = currMonth + 2 Then
'If CLng(Month(El)) = currMonth + 2 Then 'if your cells are date formatted...
k = k + 1: arrF(k) = El 'fill the final array with the appropriate dates
End If
Next
ReDim Preserve arrF(k) 'Keep only the non empty array elements
'Drop the array content in the columnn N:N, at once:
sh.Range("N10").Resize(UBound(arrF)).Value = WorksheetFunction.Transpose(arrF)
End Sub
If your L:L range is Date formatted, you must only comment/delete the line
If CLng(Mid(El, 5, 2)) = currMonth + 2 Then
and un-comment the next one...
Rather than converting and finding the current date into text, it is more accurate to convert the data of cells based on the current date to date data to compare.
Sub testDate()
Dim y As Integer, y1 As String
Dim m As Integer, m1 As String, d1 As String
Dim sDate As Date, eDate As Date
Dim TargetDay As Date
Dim rngDB As Range, rng As Range
Dim Ws As Worksheet
Set Ws = ActiveSheet
y = Year(Date)
m = Month(Date)
sDate = DateSerial(y, m + 2, 1)
eDate = DateSerial(y, m + 3, 0) 'Last day
With Ws
Set rngDB = .Range(Range("L10"), .Range("L" & Rows.Count).End(xlUp))
End With
For Each rng In rngDB
y1 = Left(rng, 4)
m1 = Mid(rng, 5, 2)
d1 = Right(rng, 2)
TargetDay = DateSerial(y1, m1, d1)
If TargetDay >= sDate And TargetDay <= eDate Then
Debug.Print rng.Address(0, 0, xlA1)
End If
Next rng
End Sub

how to extend the following excel VBA code [duplicate]

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

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

Sum up data per row based on dates

I've got some data as seen below from row 2-7.
I would like to combine all the data from previous months into one row, so from the picture below, I would like to combine the data from 05/05/2014-07/09/2014, but leave the most recent month 's data untouched and not combined. So I need to sum up the data in column G and column H, for rows 2-4, the other columns don't matter.
Rows 11-14 is what I would like to achieve. How would I do that (macro or otherwise)?
See if this will get you started:
Sub Summary()
Dim FirstDataRow As Long
Dim LastDataRow As Long
Dim DataRow As Long
Dim cDates As Long
Dim cAmounts As Long
Dim CutoffDate As Date
Dim EarliestOldDate As Date
Dim LatestOldDate As Date
Dim SumOfOld As Long
Dim OldMonthsRow As Long
Dim OffSetToSummaryTable As Long
Dim InputRow As Long
Dim OutputRow As Long
Dim TheDate As Date
Dim TheAmount As Long
Dim ws As Worksheet
' INITIALIZE
' Assume we're operating on the activesheet
Set ws = ActiveSheet
' Assume data starts in Row 2
FirstDataRow = 2
' Assume data is a contiguous block
LastDataRow = ws.Range("F" & CStr(FirstDataRow)).End(xlDown).Row
' Assume 3 empty rows between input and summary table
OffSetToSummaryTable = 3
' Calculate row where sum of old months goes
OldMonthsRow = LastDataRow + OffSetToSummaryTable + 1
' Calculate the cutoff date = first date of current month
CutoffDate = DateSerial(2015, 1, 1)
' CutoffDate = DateSerial(Year(Date), Month(Date), 1)
' Column where dates are
cDates = 6
' Column where amounts are
cAmounts = 7
' Initialize earliest and latest old dates, and sum of old
EarliestOldDate = DateSerial(3000, 12, 31) ' Way out in the future
LatestOldDate = DateSerial(1904, 1, 1) ' Way back in the past
SumOfOld = 0
' PROCESS THE DATA
OutputRow = OldMonthsRow
For InputRow = FirstDataRow To LastDataRow
TheDate = ws.Cells(InputRow, cDates)
TheAmount = ws.Cells(InputRow, cAmounts)
If TheDate >= CutoffDate Then
' Add at the bottom of the summary table
OutputRow = OutputRow + 1
ws.Cells(OutputRow, cDates).Formula = TheDate
ws.Cells(OutputRow, cAmounts).Formula = TheAmount
Else
' Update results for previous months
EarliestOldDate = IIf(TheDate < EarliestOldDate, TheDate, EarliestOldDate)
LatestOldDate = IIf(TheDate > LatestOldDate, TheDate, LatestOldDate)
SumOfOld = SumOfOld + TheAmount
End If
Next InputRow
' WRITE RESULTS TO SUMMARY ROW
ws.Cells(OldMonthsRow, cDates).Formula = Format(EarliestOldDate, "dd/mm/yyyy") & " - " & Format(LatestOldDate, "dd/mm/yyyy")
ws.Cells(OldMonthsRow, cAmounts).Formula = SumOfOld
Set ws = Nothing
End Sub

Resources