How to display only year in vba? - excel

I have the following data set in general formatting.
Bunch of years with no day nor months provided.
What I want to achieve, is to display the date in yyyy format.
I made a standard DateSerial function to convert the data to date properly.
Private Function toDate(ByVal text As String) As Date
toDate = DateSerial(Int(text), 1, 1)
End Function
For Each cell in ws.Range("A21:A" & lr)
cell = toDate(cell)
cell.NumberFormat = "yyyy"
Next cell
Now, technically this works, but if you click inside the cell, it
obviously shows the date only as 01-01-year - that is to be expected
with usage of dateserial
But I was wondering, would it be possible given my data to somehow
omit the Days and Months and only display the result as a year?
Basically, I need want to convert the data to a Date data-type without specifying days and months

Entering the years and formatting the date as "YYYY" could be done like this:
Sub TestMe()
With ThisWorkbook.Worksheets(1)
.Range("A1") = 2011
.Range("A2") = 2013
.Range("A3") = 2011
Dim myCell As Range
For Each myCell In .Range("A1:A3")
myCell = DateSerial(myCell, 1, 1)
myCell.NumberFormat = "yyyy"
Next myCell
End With
End Sub
The "trick", is that DateSerial(myCell, 1, 1) takes the year from the cell and adds 1 for day and January for month. Thus, every year is represented as the date 1.January from that year.
More about the Date in VBA and Excel - VBA doesn't return the correct Date with Now()

Related

Excel VBA set date to nearest day, is there a better way to do it?

Recently I needed to set some dates in Excel to the nearest Wednesday for a scheduling process.
I found some answers here in stackoverflow and other sites but none were giving the desired result at all times. So, I wrote a little sub to achieve this for any day you need, but it got me wondering if there was a better way to achieve this, if not then I hope you find it helpful.
EDIT: This sub is part of a large process run by a macro by clicking a custom ribbon button, the input dates come from an array, therefore, I have to use vba to change them.
Here is the matrix with results:
And the code is this:
Sub SetNextWed()
Range("A6").Activate
Do Until ActiveCell.Value = ""
SetToNextDate ActiveCell.Value, vbWednesday, 2
ActiveCell.Offset(1, 0).Activate
Loop
End Sub
Sub SetToNextDate(MyDate As Date, DayOfWeek As Integer, Column As Integer)
Dim dNext_Wednesday As Date
dNext_Wednesday = MyDate
Select Case Weekday(MyDate)
Case DayOfWeek
dNext_Wednesday = MyDate
Case Else
dNext_Wednesday = MyDate + DayOfWeek - Weekday(MyDate)
If MyDate > dNext_Wednesday Then
dNext_Wednesday = MyDate + ((DayOfWeek + 7) - Weekday(MyDate))
End If
End Select
I've tried this solutions:
https://vbaf1.com/date-time/next-wednesday-date/
https://www.mrexcel.com/board/threads/determine-date-of-next-and-most-recent-monday-vba.983467/
How do I find out what the Date is for Next Saturday or the current Saturday?
In Excel, dates are just numbers, and the date number modulo 7 gives you the day of the week, with 0 as Saturday through 6 as Friday. So you don't need VBA. The following cell formula calculates the Wednesday date you desire: =7*INT((A1+2)/7)+4, assuming the original date is in A1.

Converting Dates Format into the Time Format

I have two dates in cell "A1" (Start Date) and "B1" (End Date). I change the date to get the real figures between the dates using SUMIFS formula.
There is Date Column in the Sheet with Time.
So what i want is that whenever the "A1" (Start Date) changes its time should always be initial like 00:00:00 and when i change the date for "B1" (End Date) it should always be like 23:59:59 is there any way to achieve this using VBA.
Your help will be appreciated.
If Not Intersect(Target, Range("A1:B1")) Is Nothing Then
With Range("A1")
.Value = Now()
.NumberFormat = "mm/dd/yyyy h:mm:ss AM/PM"
End With
With Range("B1")
.Value = Now()
.NumberFormat = "mm/dd/yyyy h:mm:ss AM/PM"
End With
End If
Numeric time 23:59:59 is not equal to 0.9999999, it is 0.999988425925926
But use native date/time handling for this and avoid smart numbers:
Range("A1").Value = DateValue(Range("A1").Value)
Range("B1").Value = DateValue(Range("B1").Value) + TimeSerial(23, 59, 59)
I think this could work, if i understood your question correct.
It will make sure A1 is integer and make B1 integer then add 0.99999.
If Not Intersect(Target, Range("A1:B1")) Is Nothing Then
Range("A1").value = cint(range("A1").value)
Range("B1").value = cint(range("B1").value) + 0.99999999
End if
Just make sure the cells is set up to display as date and time.
If I understand you correctly, you don't need to bother with the time portion of the dates or go throught the mechanics of trying to change it.
You just need to properly construct your SUMIFS formula.
Range to sum: sumRange
Dates in your table: myDates
When you enter a date in A1 or B1, it will be entered as if it were at the beginning of the day.
If your dates in myDates are just dates, you can use the formula:
=SUMIFS(sumRange,myDates,">=" & startDate,myDates,"<=" & endDate)
However, if your dates in myDates also include a time, then you can modify the formula slightly:
=SUMIFS(sumRange,myDates,">=" & startDate,myDates,"<" & endDate+1)
And you can use the 2nd formula in either instance
Edit: I just noticed you posting your formula as a comment
I assume you have entered JUST the date (no time) in I1 and J1
Your formula as posted will work UNLESS C:C includes times with the dates. If it does include times with the dates, then try:
=SUMIFS(D:D,E:E,"<>Pending for Payment",B:B,H2,C:C,">="&$I$1,C:C,"<"&$J$1+1)
By adding 1 to the date, we move it to the start of the day after; so we change the <= to just < and encompass the full range of dates you desire.

Attempting to run a specific macro based on the current value of a cell

I'm attempting to set up a workbook that allows me to log data in cells on one sheet to other sheets based on the day of the week. Basically it's a weekly tracker with a separate sheet for each day of the week. I have separate macros to move the desired data from the "current" sheet to any other day of the week, and each of those work as desired.
Edit: I'm binding this macro to a button on the primary sheet, rather than using a hotkey or list.
Sub Lookup()
Dim day As String
day = ThisWorkbook.Sheets("Data").Cells(2, "x").Value2
If day = "Mon" Then
Call Mon
ElseIf day = "Tue" Then
Call Tue
ElseIf day = "Wed" Then
Call Wed
ElseIf day = "Thu" Then
Call Thu
ElseIf day = "Fri" Then
Call Fri
End If
End Sub
I'm trying to make a separate macro that looks at the data in a specific cell in a specific sheet (using the "Now()" function in a specific cell, formatted to show the day of the week only) and just want it to look at that data and run the corresponding macro. As it is now, it stops on the first step with the error
"Compile error: Expected function or variable"
Edit: I realized that if I have it reference a cell where I've manually typed in any given day, it works. So it looks like the macro is only looking at the formula rather than the result. Changing the formula in the cell to
=TEXT(NOW(),"ddd")
resolved the issue. Thank you for all of your help!
My guess is that you need to format the output you're comparing against in order to run the macro. You state you have =NOW() in the cell, and that will not return Mon for example. So you can use the Format method to get the output you're looking for.
Here's a way to validate that what's in cell X2 is actually a date, and that the date falls on a Mon-Fri (exclude weekends), so that you can call your Mon-Fri macros by passing it to Application.Run:
Sub Lookup()
Dim lWeekday As Long
With ThisWorkbook.Worksheets("Data").Range("X2")
On Error Resume Next
lWeekday = WorksheetFunction.Weekday(.Value, 16)
On Error GoTo 0
Select Case (IsDate(.Value)) And (lWeekday > 2) 'Verify date and that it is Mon-Fri
Case True: Application.Run Format(.Value, "ddd")
Case Else: MsgBox "Invalid date: [" & .Value & "]", , "Error"
End Select
End With
End Sub
You can pass a String value to Application.Run so you could shorten your code to
Sub Lookup()
Dim day As String
day = ThisWorkbook.Sheets(8).Cells(2, "x").Value
Application.Run day
End Sub
and then with your Sheets(8).cells(2,"x") add data validation to the cell with a list value of Mon, Tue, Wed, Thu, Fri or whatever your macro names are so that the user can only select from a defined list of choices.
Also, you need to explicitly reference your sheet instead of referencing its position.
i.e.
day = ThisWorkbook.Sheets(8).Cells(2, "x").Value
becomes
day = ThisWorkbook.Sheets("YourSheetNameHere").Cells(2, "x").Value2
or handle it in your macro
Sub Lookup()
Dim day As String
Dim ValidSubs As Variant
Dim RunSub As Boolean: RunSub = False
Dim c
ValidSubs = Array("Mon", "Tue", "Wed", "Thu", "Fri")
day = ThisWorkbook.Sheets(8).Cells(2, "x").Value
For Each c In ValidSubs
If c = day Then
RunSub = True
Exit For
End If
Next c
If RunSub Then
Application.Run day
Else
MsgBox "You have selected an invalid choice - only the following are allowed:" & vbNewLine & Join(ValidSubs, vbNewLine)
End If
End Sub

Converting all dates in a year into multiple strings using Excel VBA

I have to write a vba code that convert all dates in a year into days in a week eg. Monday, Tuesday, Wednesday....Sunday and the value of all days in a week eg.Monday must be in a string format. (See image inserted)
I tried using the .NumberFormat function but it does not work since the format is still under the date format although the values displayed are correct (please look at the formula bar of F10). Below is the code I have written:
Sub convertdate()
Range("A7:A371").Copy
'copy all the dates throughout the year'
Range("F7:F371").PasteSpecial xlPasteFormulasAndNumberFormats
'paste it into F column'
Worksheets("Sheet1").Range("F7:F371").NumberFormat = "dddd"
'convert the dates into days'
Sum1 = Application.SumIf(Range("F7:F371"), "Monday", Range("B7:B371"))
'example of calculating the total rainfall of all Mondays throughout the year'
Worksheets("Sheet1").Range("G22").FormulaArray = Sum1
End Sub
The formula bar from cell F7:F371 should display the string value "Monday","Tuesday" etc depending on the dates rather than the date itself.The reason of converting it into a string is so that it could be use in a SUMIF function later on to calculate the total rainfall of all Mondays,Tuesday etc.
Appreciate if anyone could help. Thank you.
A formula can do this.
In cell F7 enter =TEXT(A7,"dddd") and drag down.
This will format the date to show the full day name as a string.
https://support.office.com/en-us/article/TEXT-function-20d5ac4d-7b94-49fd-bb38-93d29371225c
Try something like this. It will loop through all the dates in Column A (starting in row 7) and put the associated Weekday name in Column F:
Sub test()
Dim i As Long
Dim lRow As Long
With ActiveSheet
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row
For i = 7 To lRow
.Cells(i, 6).Value = WeekdayName(Weekday(.Cells(i, 1).Value, 1), False, 1)
Next i
End With
End Sub

Cannot convert date string to datevalue in Excel

I have some dates in a string in a column.
Because the format seems to be M/DD/YYYY I sometimes get a VALUE error when using DATEVALUE.
How can I convert a column to make sure all dates are correct.
For example, the following 2 cells
9/29/2006 12:49:58.956 AM DATEVALUE gives an error
9/12/2008 5:36:59.356 PM DATEVALUE converts to 39791
You need to select the range (just one colunm) with the dates... Go to:
(in Excel 2010)
Data >>> Text to Columns
Inside the dialog box select:
Delimited >>> Next
Just select Tab checkbox.
And heres is the magic!
You need to define the arrangement for your dates...
In the Date field:
Choose the what you need (as you say in your question is M/D/Y)
Destination field:
Make sure that is the same of the data you want to format.
And finish.
The problem you are having is probably that the data is getting interpreted as a general field, and shows up as, say 49:59.0 - which isn't text, which is what Datevalue() expects as input; for both inputs, Datevalue(CellID) words if you prepend the text with a ' - which ensures it is treated as text.
it seems that your system settings use dd/mm/yyyy for short date format. and datevalue function uses this settings, so its try to read the day from the first part of the string and the month from the second part. as in your example 9/29/2006 12:49:58.956 AM there is no month with 29 then it gives error, and in the second example it gives 39791 = 9 december 2008 and NOT 12 september 2008.
If you change the short date format in your system settings to mm/dd/yyyythen datevalue function will work correctly, but this not acceptable, so we need to replace month with day and day with month to get correct date.
I don't know if we can do this with Excel formula but we can do that simply with VBA.
So try this code:
Sub Test()
Dim d1 As Variant, d2 As Variant, td As Date
Dim Rng As Range, CL As Range
Set Rng = Range("A1:A2") ' change this to your range
For Each CL In Rng
d1 = Split(CL.Value, " ")
d2 = Split(d1(0), "/")
td = DateSerial(d2(2), d2(0), d2(1))
CL.Offset(0, 1) = td
CL.Offset(0, 1).NumberFormat = "mm/dd/yyyy" ' change the Date format as you need
'CL.Offset(0, 1).NumberFormat = "dd/mm/yyyy"
Next
End Sub

Resources