Leading zero vba excel wrong dates - excel

I have this dates from DB and I want to fix the date in VBA excel because excel switch the date with month when filter the column
27/08/2018
31/08/2018
12/9/2018
2/8/2018 wrong date reported at filter in excel need 02/08/2018
6/8/2018 wrong date reported at filter in excel need 06/08/2018
13/08/2018
17/08/2018
20/08/2018
20/08/2018
I have tried this
For i = 2 To lastRow
Dim fDate As Date
Dim dayF As String
Dim monthF As String
Dim yearF As String
Set r = Cells(i, Column_DateStamp)
strDate = Split(r.Text, "/")
dayF = CStr(Format(strDate(0), "00"))
monthF = CStr(Format(strDate(1), "00"))
yearF = CStr(Format(strDate(2), "0000"))
fDate = Format(DateSerial(strDate(2), CStr(Format(strDate(1), "00")), CStr(Format(strDate(0), "00"))), "dd/mm/yyyy")
r.Clear
r.Value = fDate
Next i

The date formats do not match your local date format and as such Excel is trying to convert.
You need to either put the date in and format it appropriately or make the cell text so excel does not try to convert.
Dim i As Long
For i = 2 To lastRow
Dim fDate As Date
Dim r As Range
Set r = Cells(i, Column_DateStamp)
strDate = Split(r.Text, "/")
fDate = DateSerial(strDate(2), strDate(1), strDate(0))
r.Clear
'True date - comment out if you want string
r.NumberFormat = "dd/mm/yyyy"
r.Value2 = fDate
'String - Uncomment if you want string
' r.NumberFormat = "#"
' r.Value2 = Format(fDate, "dd/mm/yyyy")
Next i

Examining your screenshot, the problem is consistent with your Windows Regional Settings being MDY and the Database settings being DMY. This will always result in incorrect action by Excel.
Whoever wrote the ERP application should be able to make the change to input, to Excel, an unambiguous date format; or trigger the excel text import wizard at the time of import.
You can try this macro in the meantime. It should work, but read the notes carefully for possible pitfalls:
Option Explicit
Sub ConvertDates()
'converts dates that have been mismatched MDY / DMY
'Assumes dates are all in selected column
' Only need to select a single cell in the column
' will place results in a column next to original data
' If adjacent column is not blank, a column will be inserted
'Figures out the original format by analyzing a "text" date
'Time components are converted directly. This might be OK unless
' in a non standard format such as 1400Z
Dim R As Range, C As Range
Dim sDelim As String
Dim FileDateFormat As String * 3
Dim i As Long, j As Long, V As Variant
Dim vDateParts As Variant
Dim YR As Long, MN As Long, DY As Long
Dim TM As Double
Dim vRes As Variant 'to hold the results of conversion
Set R = Selection
'Test that selected cell contains a date
If Not IsDate(R(1)) Then
MsgBox "Select a cell containing a date"
Exit Sub
End If
Set R = Intersect(R.EntireColumn, ActiveSheet.UsedRange)
ReDim vRes(1 To R.Rows.Count, 1 To 1)
'Find a "text date" cell to analyze
For Each C In R
With C
If IsDate(.Value) And Not IsNumeric(.Value2) Then
'find delimiter
For i = 1 To Len(.Text)
If Not Mid(.Text, i, 1) Like "#" Then
sDelim = Mid(.Text, i, 1)
Exit For
End If
Next i
'split off any times
V = Split(.Text & " 00:00")
vDateParts = Split(V(0), sDelim)
If vDateParts(0) > 12 Then
FileDateFormat = "DMY"
Exit For
ElseIf vDateParts(1) > 12 Then
FileDateFormat = "MDY"
Exit For
Else
MsgBox "cannot analyze data"
Exit Sub
End If
End If
End With
Next C
If sDelim = "" Then
MsgBox "cannot find problem"
Exit Sub
End If
'Check that analyzed date format different from Windows Regional Settings
Select Case Application.International(xlDateOrder)
Case 0 'MDY
If FileDateFormat = "MDY" Then
MsgBox "File Date Format and Windows Regional Settings match" & vbLf _
& "Look for problem elsewhere"
Exit Sub
End If
Case 1 'DMY
If FileDateFormat = "DMY" Then
MsgBox "File Date Format and Windows Regional Settings match" & vbLf _
& "Look for problem elsewhere"
Exit Sub
End If
End Select
'Process dates
'Could shorten this segment but probably more understandable this way
j = 0
Select Case FileDateFormat
Case "DMY"
For Each C In R
With C
If IsDate(.Value) And IsNumeric(.Value2) Then
'Reverse the day and the month
YR = Year(.Value2)
MN = Day(.Value2)
DY = Month(.Value2)
TM = .Value2 - Int(.Value2)
ElseIf IsDate(.Value) And Not IsNumeric(.Value2) Then
V = Split(.Text & " 00:00") 'remove the time
vDateParts = Split(V(0), sDelim)
YR = vDateParts(2)
MN = vDateParts(1)
DY = vDateParts(0)
TM = TimeValue(V(1))
Else
YR = 0
End If
j = j + 1
If YR = 0 Then
vRes(j, 1) = C.Value
Else
vRes(j, 1) = DateSerial(YR, MN, DY) + TM
End If
End With
Next C
Case "MDY"
For Each C In R
With C
If IsDate(.Value) And IsNumeric(.Value2) Then
'Reverse the day and the month
YR = Year(.Value2)
MN = Day(.Value2)
DY = Month(.Value2)
TM = .Value2 - Int(.Value2)
ElseIf IsDate(.Value) And Not IsNumeric(.Value2) Then
V = Split(.Text & " 00:00") 'remove the time
vDateParts = Split(V(0), sDelim)
YR = vDateParts(2)
MN = vDateParts(0)
DY = vDateParts(1)
TM = TimeValue(V(1))
Else
YR = 0
End If
j = j + 1
If YR = 0 Then
vRes(j, 1) = C.Value
Else
vRes(j, 1) = DateSerial(YR, MN, DY) + TM
End If
End With
Next C
End Select
With R.Offset(0, 1).EntireColumn
Set C = .Find(what:="*", LookIn:=xlFormulas)
If Not C Is Nothing Then .EntireColumn.Insert
End With
R.Offset(0, 1).Value = vRes
End Sub

Related

Strikethrough in Excel VBA

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

Create a days of month using a date as parameter

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

VBA Excel: comparison of dates under different locale settings

I have a column in "dd-mm-yy hh:mm" format that formed as a result of some action on UserForm:
Dim ws as Worksheet
Set ws = Worksheets("Logs")
With ws
For i = 1 to Me.ListBox1.ListCount - 1
.Cells(lRow + 1 + i, 10).Value = CDate(VBA.Format(Me.ListBox1.List(i), "dd-mm-yy hh:mm"))
Next i
End With
I save the column to Variant variable to use later (to be used multiple times):
Dim arrTimeD As Variant
arrTimeD = Application.Transpose(.Range(TCL & "2:" & TCL & lRow).Value)
The locale date settings are European: "dd-mmm-yyyy"
The spreadsheet are used by different users, some have "dd-mmm" setting, others "mm-dd" etc.
I need to compare the dates in several uses. For, e.g.
Dim bDate as Date
bDate = CDate(VBA.Format(Me.lblCheckin.Caption,"dd-mm-yyyy"))
Do While CDate(arrTimeD(bIndex)) < bDate
If bIndex = lRow - 1 Then Exit Do
bIndex = bIndex + 1
Loop
When the user with US locale ("mm-dd") uses the spreadsheet, CDate(arrTimeD(bIndex)) throws error. CDate(VBA.Format(arrTimeD(bIndex))) and CDate(DateValue(arrTimeD(bIndex)) didn't help. What is the best way to do it?
Is it possible to set workbook's own date setting regardless of OS's?
Or I need to convert variant to string then concatenate?
The date string should be converted into a numeric date value.
Function DDMMYYYFormatToDateTimeValue(DateString As String) As Date
Dim Parts() As String
Parts = Split(DateString, "-")
DDMMYYYFormatToDateTimeValue = CDate(Parts(1) & "/" & Parts(0) & "/" & Parts(2))
End Function
Usage
Private Sub UserForm_Initialize()
Dim n As Long
For n = 1 To 100
ListBox1.AddItem Format(Date + n / 24, "MM-DD-YY HH:MM")
Next
End Sub
Public Function ListBoxDateValues()
Dim Data As Variant
ReDim Data(1 To Me.ListBox1.ListCount, 1 To 1)
Dim DateString As String
Dim r As Long
For r = 1 To Me.ListBox1.ListCount
DateString = Me.ListBox1.List(r - 1)
Data(r, 1) = DDMMYYYFormatToDateTimeValue(DateString)
Next
ListBoxDateValues = Data
End Function
Public Function wsLogs() As Worksheet
Set wsLogs = ThisWorkbook.Sheets("Logs")
End Function
Function DDMMYYYFormatToDateTimeValue(DateString As String) As Date
Dim Parts() As String
Parts = Split(DateString, "-")
DDMMYYYFormatToDateTimeValue = CDate(Parts(1) & "/" & Parts(0) & "/" & Parts(2))
End Function
First, true date values carry no format, so convert your text dates from the listbox directly to true date values:
.Cells(lRow + 1 + i, 10).Value = CDate(Me.ListBox1.List(i))
These you can apply the format you prefer for display.
The comparison is now straight:
Dim bDate As Date
bDate = CDate(Me.lblCheckin.Caption)
Do While arrTimeD(bIndex) < bDate
If bIndex = lRow - 1 Then
Exit Do
Else
bIndex = bIndex + 1
End If
Loop

VBA code to list all months between a range of dates

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

How to extract date time from an excel cell?

I have an excel file with cells containing some comments like:
txxxxx:10/15/2019 11:38:48 AM - Customer ID: xxxxx
) 1st contact - Text only sent to Mob TN xxxxxxw/Ref &TN
Txxxxxx:10/18/2019 1:34:12 PM -
Called BEST CBR xxxxxx, Spoke to Mr, he said they have been busy & unable to review/discuss yet. Offered to text him our direct info, they will check online &/or call us soon.
An SMS message has been successfully sent to Gull Family at xxxxxx
OK WITH FINAL CB next week.
The text could be anything potentially containing multiple date time fields.
I am trying to extract all such date occurrences from each cell and put them in different columns
I tried using =regExFind and =regExExtract. For instance:
=RegExFind($Cell,"\d{2}/\d{2}/\d{4}")
I also tried =Text($cell, dd/mm/yyyy)
However, neither approach is working.
Is there a way in excel to do a RegEx Extract and if so how to achieve that?
If not, what is the best way to extract all datetime fields?
UPDATE:
This is the code I have used:
Function RegexExtract(ByVal text As String, _
ByVal extract_what As String, _
Optional separator As String = ", ") As String
Dim allMatches As Object
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
Dim i As Long, j As Long
Dim result As String
RE.pattern = extract_what
RE.Global = True
Set allMatches = RE.Execute(text)
For i = 0 To allMatches.count - 1
For j = 0 To allMatches.Item(i).submatches.count - 1
result = result & (separator & allMatches.Item(i).submatches.Item(j))
Next
Next
If Len(result) <> 0 Then
result = Right$(result, Len(result) - Len(separator))
End If
RegexExtract = result
End Function
But no Output.
As your post is not very explicit, my answer can not be more too.
Try this one:
Dim regex As Object, str As String
Set regex = CreateObject("VBScript.RegExp")
With regex
.Pattern = "([0-9]+)/([0-9]+)/([0-9]+)"
.Global = True
End With
str = "Whatever string you have"
Set matches = regex.Execute(str)
For Each match In matches
Debug.Print match.Value
Next match
So you will need to loop it in your range. str should be your cell on the loop and instead of Debug.Print you should bring this value to whatever cell like Worksheet("?").Cells(i,j).Value = match.Value.
Hope it helps
A bit of a workaround...instead of using RegEx the idea is to find the "AM"s and "PM"s in the cell and copy paste the string of 19/20 characters before them in the column "Date Extraction". One of the limitations of this method is clearly that could work only if AM and PM are always present in the date format of your messages.
Sub ExtractDates()
Dim myRange, cell As Range
Dim StringInCell, MyDate As String
Dim DateExtrColNum, i, j As Integer
Set myRange = Worksheets("YourSheetName").UsedRange
DateExtrColNum = myRange.Columns(myRange.Columns.Count).Column
Cells(1, DateExtrColNum + 1).Value = "Date Extraction"
j = 2
For Each cell In myRange
If Not cell.Find("AM") Is Nothing Or Not cell.Find("PM") Is Nothing Then
StringInCell = cell.Value
i = 1
Do While InStr(i, StringInCell, "AM") <> 0 Or InStr(i, StringInCell, "PM") <> 0
If InStr(i, StringInCell, "AM") <> 0 Then
MyDate = Mid(StringInCell, InStr(i, StringInCell, "AM") - 20, 20)
If InStr(1, MyDate, ":") = 1 Then
MyDate = Right(MyDate, 19)
End If
i = InStr(i, StringInCell, "AM") + 1
Else: MyDate = Mid(StringInCell, InStr(i, StringInCell, "PM") - 20, 20)
If InStr(1, MyDate, ":") = 1 Then
MyDate = Right(MyDate, 19)
End If
i = InStr(i, StringInCell, "PM") + 1
End If
Cells(j, DateExtrColNum + 1).Value = MyDate
j = j + 1
Loop
End If
Next
End Sub

Resources