I have a date in cell A1 for example: 12/08/22
I want create a list with all days of the month (1-31) in column E using the month and year of the cell A1 as parameter.
Sub TESTEEEEEEE()
Dim r As Range, i As String, j As Long
i = Range("A1").Offset(0, 1).Value = Left(cell.Value, 3)
'k = ????
j = 31
For Each r In Range("E1:E31")
r.NumberFormat = "#"
r.Value = Format(DateSerial(k, i, j), "dd/m/yy")
j = j + 1
Next r
End Sub
I'm stucked in how to extract the the month and year. I was trying using the position of the characteres as parameter, but i'm not getting it work.
i should extract the 4,5 and characterer returning 08 (ok, the code is wrong i was making some tests).
k should extract the 7,8 charachter returning 22.
Someone can help me?
Please, try using the next way. It does not need iteration:
Sub testCreateWholeMonth()
Dim D As Date, lastD As Long
D = Range("A1").value
lastD = Day(WorksheetFunction.EoMonth(DateSerial(Year(D), Month(D), 1), 0))
With Range("E1:E" & lastD)
.value = Evaluate("date(" & Year(D) & "," & Month(D) & ",row(1:" & lastD & "))")
.NumberFormat = "mm.dd.yyyy"
End With
End Sub
You are probably after calendar functions like YEAR, MONTH, EOMONTH
Sub DebugDate()
Dim rg As Range
Set rg = Range("A1") ' should contain a date
Dim dt As Date
dt = rg.Value
Debug.Print Year(dt), Month(dt), CDate(WorksheetFunction.EoMonth(dt, 0))
' End of month not using worksheet function EOMONTH
Debug.Print DateSerial(Year(dt), Month(dt) + 1, 1) - 1
End Sub
Further reading on How to create a calendar with VBA
Related
When I enter a second date in a cell, I want the initial date to be strikethrough and keep the both date in the same cell
I have a range of cells from column E to H, in which each cell has date.
Your help would be highly appreciated
Sub ColorMeElmo()
'
Dim count As Long
count = ActiveSheet.Cells(Rows.count, "D").End(xlUp).Row
'
Dim i As Long, r1 As Range, r2 As Range
For i = 2 To count
Set r1 = Range("D" & i)
Set r2 = Range("E" & i)
Dim diff1 As Long
diff1 = DateDiff("D", r2.Value, r1.Value)
If diff1 <= 5 Then r2.Interior.Color = vbRed
If diff1 > 5 Then r2.Interior.Color = vbYellow
Next i
For ii = 2 To count
Set r1 = Range("D" & ii)
Set r2 = Range("F" & ii)
Dim diff2 As Long
diff2 = DateDiff("D", r2.Value, r1.Value)
If diff2 <= 5 Then r2.Interior.Color = vbRed
If diff2 > 5 Then r2.Interior.Color = vbYellow
End Sub
Range will change from D, E, F, G, H. But here I give only E
Assuming your dates are already recognized as dates by Excel, you could use the following procedure:
Sub StrikethroughAndNewDate(ByRef rng As Range, ByVal NewDate As Date)
'You can change this value if you need a different date format
Const DateFormat As String = "YYYY-MM-DD"
'Combine dates
rng.Value2 = Format(rng.Value2, DateFormat) & " " & Format(NewDate, DateFormat)
'Add Formatting
rng.Characters(Start:=1, Length:=Len(Format(rng.Value2, DateFormat))).Font.Strikethrough = True
End Sub
Which would give you something like this :
If your dates are both stored as string inside the cells, you could do a simple concatenation instead:
Sub StrikethroughAndNewDate2(ByRef rng As Range, ByVal NewDate As Variant)
'Combine dates
rng.Value2 = rng.Value2 & " " & NewDate
'Add Formatting
rng.Characters(Start:=1, Length:=Len(rng.Value2)).Font.Strikethrough = True
End Sub
So I have a list of dates that I am trying to search through and check if they need to be corrected or not. The yellow highlighted cells are examples of changes needed to be made. Wether the date needs fixing or not I want the result of the code to place it in the "Date Fixed" column as shown in the first cell. If the date is not listed as the 30/31st of a month or the 1st then I need to change the day part of the date to either the beginning or end of the month. I have written what I thought would work but I keep receiving a Run Time Error 11 code. Any ideas on how to fix this and keep going through all the dates?
Private Sub FormatDate_Click()
Dim myrow As Integer
Dim startrow As Integer
Dim Dates As Date
Dim Datesfixed As Date
Dim dateTwo As Date
Dim dateEnd As Date
myrow = 2
startrow = 2
Dates = Cells(myrow, 2)
Datesfixed = Cells(myrow, 3)
dateTwo = mm / 1 / yyyy
dateEnd = mm / 31 / yyyy
Do Until Cells(myrow, 1) = ""
If Dates = dateTwo Or dateEnd Then
Datesfixed = Dates
ElseIf Dates <> dateTwo Or dateEnd Then
Dates = dateTwo
myrow = myrow + 1
End If
myrow = myrow + 1
Loop
myrow = 2
startrow = 2
End Sub
Try something like this:
Private Sub FormatDate_Click()
Dim c As Range, dt, d As Long, m As Long, y As Long, dLast As Long
Set c = ActiveSheet.Range("B2") 'first date
Do While Len(c.Value) > 0
dt = c.Value
d = Day(dt) 'extract the parts of the date
m = Month(dt)
y = Year(dt)
dLast = Day(DateAdd("m", 1, DateSerial(y, m, 1)) - 1) 'last day of the month
If d <> 1 And d <> dLast Then
c.Offset(0, 1) = DateSerial(y, m, dLast) 'set to last day of the month
End If
Set c = c.Offset(1, 0) 'next date
Loop
End Sub
I am new to VBA in Excel. I have looked through through the forum, but have not found an answer for my specific date VBA I am looking for. I have three date ranges in excel cells per row of data elements representing testing dates. Each of the three ranges has a start date and an end date columns A-F.
For each row of test date ranges, I would one cell in column G to calculate the month and year "MMMYY" for any months covered in any of the three date ranges. If the date ranges over three months, the resulting cell would list all three months.
Any help would be greatly appreciated. Thank you in advance.
Marc
Calculated VBA column G
A B C D E F G
1 T1 Start T1 End T2 Start T2 End T3 Start T3 End Months
2 02Nov20 16Nov20 17Nov20 19Nov20 02Nov20 1Jan21 Nov20
Dec20
Jan21
3 28Oct19 15Nov19 28Oct19 01Nov19 28Oct19 1Nov19 Oct20
Nov20
4 20Jul20 21Aug20 Jul20
Aug20
5 11Sep20 29Sep20 20Sep20 22Sep20 20Sep20 Sep20
Here is a macro that outputs ALL of the included month/year.
In order to find the data table, I used the .CurrentRegion property of the cell that contains T1 Start. Because of this, if the output were adjacent to the table, the second run would include that column. Accordingly, I wrote the results one column over (and hid the intervening column. But you could make any number of changes in determining the source table size if that is undesireable.
I also was not certain, from your screenshot, if the Dates were "real Excel Dates" formatted to look like ddmmmyy (except for Column F in your text table) or if they are strings. So there is code to account for the different things I see. Code could be simplified if the data is in a known format.
The output is text strings and the column is formatted as text. If you want the output to be real dates formatted as mmmyy, then code will need to be added so Excel does not erroneously convert 2 digit years to day of the month.
Be sure to read the notes in the macro, as it will help you understand what's going on.
Option Explicit
Sub mthList()
Dim cM As Collection
Dim rg As Range, dStart As Date, dEnd As Date
Dim vSrc As Variant, vRes As Variant
Dim i As Long, J As Long, K As Long
Dim d1 As Double, d2 As Double 'start and end dates
Dim WS As Worksheet, rRes As Range
'Find the table and read it into VBA array
Set WS = ThisWorkbook.Worksheets("Sheet1")
With WS
Set rg = .Cells.Find(what:="T1 Start", after:=.Cells(.Rows.Count, .Columns.Count), _
LookIn:=xlFormulas, lookat:=xlWhole, searchorder:=xlByRows, searchdirection:=xlNext, MatchCase:=False)
If rg Is Nothing Then
MsgBox "No Data Table"
Exit Sub
End If
vSrc = rg.CurrentRegion
ReDim vRes(1 To UBound(vSrc, 1), 1 To 1)
End With
'Collect all the included dates
'Convert date strings to real dates if they are strings
For i = 2 To UBound(vSrc, 1)
Set cM = New Collection
For J = 1 To UBound(vSrc, 2) Step 2 'can have N pairs of dates
If vSrc(i, J) <> "" Then
d1 = theDate(vSrc(i, J)) ' need to make sure this is a date and not a text string
If vSrc(i, J + 1) = "" Then
d2 = d1
Else
d2 = theDate(vSrc(i, J + 1))
End If
On Error Resume Next 'remove duplicates since Collection cannot have two entries with same key
For K = d1 To d2
cM.Add Format(K, "mmmyy"), Format(K, "mmmyy")
Next K
On Error GoTo 0
End If
Next J
'Output the data to results array
For K = 1 To cM.Count
vRes(i, 1) = vRes(i, 1) & vbLf & cM(K)
Next K
vRes(i, 1) = Mid(vRes(i, 1), 2)
Next i
'write the results
'formatting is optional, and Styles may not work with non-English versions
Set rRes = rg.Offset(0, rg.CurrentRegion.Columns.Count + 1)
Set rRes = rRes.Resize(UBound(vRes, 1), UBound(vRes, 2))
With rRes
.EntireColumn.Clear
.EntireColumn.NumberFormat = "#"
.Value = vRes
.WrapText = True
.EntireRow.AutoFit
.EntireColumn.AutoFit
.Style = "output"
.Offset(0, -1).EntireColumn.Hidden = True
End With
With rg.CurrentRegion
.VerticalAlignment = xlCenter
.HorizontalAlignment = xlCenter
.Style = "Input"
End With
End Sub
Private Function theDate(d) As Double
If Not IsDate(d) Then
theDate = CDate(Left(d, Len(d) - 5) & " " & Mid(d, Len(d) - 4, 3) & " " & Right(d, 2))
Else
theDate = d
End If
End Function
EDIT:
To use my algorithm as a function, just need to remove all that stuff with regard to finding the table and writing results back to the worksheet:
Option Explicit
Function mthList(rg As Range) As String
Dim cM As Collection
Dim dStart As Date, dEnd As Date
Dim vSrc As Variant
Dim I As Long, J As Long, K As Long
Dim d1 As Double, d2 As Double 'start and end dates
Dim S As String
'Collect all the included dates
'Convert date strings to real dates if they are strings
vSrc = rg
Set cM = New Collection
For J = 1 To UBound(vSrc, 2) Step 2 'can have N pairs of dates
If vSrc(1, J) <> "" Then
d1 = theDate(vSrc(1, J)) ' need to make sure this is a date and not a text string
If vSrc(1, J + 1) = "" Then
d2 = d1
Else
d2 = theDate(vSrc(1, J + 1))
End If
On Error Resume Next 'remove duplicates since Collection cannot have two entries with same key
For K = d1 To d2
cM.Add Format(K, "mmmyy"), Format(K, "mmmyy")
Next K
On Error GoTo 0
End If
Next J
'Output the data to a string
For K = 1 To cM.Count
S = S & vbLf & cM(K)
Next K
mthList = Mid(S, 2)
End Function
Private Function theDate(d) As Double
If Not IsDate(d) Then
theDate = CDate(Left(d, Len(d) - 5) & " " & Mid(d, Len(d) - 4, 3) & " " & Right(d, 2))
Else
theDate = d
End If
End Function
As said in the comments one could use a dictionary
Function listMthYear(rg As Range) As String
' Goto Tools/Reference and check Microsoft Scripting Runtime
Dim dict As Dictionary
Set dict = New Dictionary
Dim sngCell As Range
For Each sngCell In rg
If IsDate(sngCell.Value) Then
Dim mth As Long
Dim yr As Long
Dim dte As Date
dte = sngCell.Value
mth = VBA.Month(dte)
yr = VBA.year(dte)
dte = VBA.DateSerial(yr, mth, 1)
' This will create an unique entry in the dictionary if not already created
dict(dte) = dte
End If
Next sngCell
Dim output As Variant, i As Long
output = dict.Keys
For i = LBound(output) To UBound(output)
output(i) = Format(output(i), "MMMYY")
Next i
listMthYear = Join(output, vbLf)
End Function
You could use the function as an UDF or like that
Sub TestIt()
Dim rg As Range
Set rg = Range("A3:E3")
MsgBox listMthYear(rg)
End Sub
This the data I have.
I just want its month name and year.
For example 201804: Apr 2018
Try this UDF
Sub Test()
Debug.Print FormatDate("201804")
End Sub
Function FormatDate(sInput As String)
sInput = "1/" & Right(sInput, 2) & "/" & Left(sInput, 4)
FormatDate = Format(CDate(sInput), "mmm yyyy")
End Function
Try
Sub test()
Dim vDB
Dim i As Long
Dim s As String, y As String, m As String
vDB = Range("a1", Range("a" & Rows.Count).End(xlUp))
For i = 2 To UBound(vDB, 1)
s = vDB(i, 1)
y = Left(s, 4)
m = Right(s, 2)
vDB(i, 1) = Format(DateSerial(y, m, 1), "mmm yyyy")
Next i
With Range("b1").Resize(UBound(vDB, 1), 1)
.NumberFormatLocal = "#"
.Value = vDB
End With
End Sub
Here is the worksheet formula, converting the date in A1. Copy the formula down as required.
=DATE(LEFT(A1,4),RIGHT(A1,2),1)
The result is a proper date set for the first day of the month, in this case April 1, 2018. The format in which this result is displayed depends entirely upon your system settings. However, you can over-ride the system by setting a custom date format in Format > Cells > Numbers > Custom*. Set Type as mmm yyyy to display Apr 2018 in the cell.
I have a problem I hope I can get some help with. In a summary report I need to use date criterias: today's date compared to months in B1:M1 (all cells are date formatted using a userdefined date format to only display the monthname) to sum the rows of data only if an account number is listed in column A. (pls. see below example)
I.E. if todays date is Feb. 7th the VBA code should loop through all rows and only sum the numbers for January and february where an account # is present (it must be in VBA)
Here is what I have so far:
Sub Test()
Dim today, lastdayinmonth As Date
Dim i, ii As Integer
Dim months As Range
today = DateSerial(Year(Date), Month(Date), Day(Date))
lastdayinmonth = DateSerial(Year(Date), Month(Date) + 1, 0)
months = Sheet2.Range("B2:M2")
If idag <= lastdayinmonth Then
For i = 3 To 20
If Not IsEmpty(Sheet2.Range("B" & i)) Then
End If
Next ii
End If
End Sub
Try this code, please. It works based on the assumption that your columns header are Date formatted (no matter if they show only month...), and the sum will be returned in Imediate Window:
Sub TestSumMonth()
Dim arrM As Variant, i As Long, j As Long
Dim nSum As Long, lastRow As Long, sh As Worksheet
Set sh = sheet2
lastRow = sh.Range("A" & sh.Rows.count).End(xlUp).Row
arrM = sh.Range("A1:M" & lastRow).Value
sh.Range("O2:O" & lastRow).Interior.ColorIndex = xlNone ' clear the existing interior color
For i = 1 To UBound(arrM, 1)
If arrM(i, 1) <> Empty Then
nSum = 0
For j = 2 To UBound(arrM, 2)
If Month(Date) >= Month(arrM(1, j)) Then
nSum = nSum + arrM(i, j)
If Month(Date) = Month(arrM(1, j)) Then
With sh.Range("O" & i)
.Value = nSum
.Interior.Color = vbYellow ' interior colored in yellow
End With
Exit For
End If
End If
Next j
End If
Next i
End Sub
The code firstly clears "O:O" range interior color, then returns the sum on the appropriate row of this column and colors the cell interior in yellow...
Now, it would summarize all the passed month values plus the active month.