Find cell based on Date in Excel VBA - excel

I have a file with a few columns including one with dates and another with some integers.
I want to obtain the row number of a cell based on its date. So in column B, I want the row number of the cell containing the date 31st of December 2018. The display format in the workbook is "31-Dec-2018" and when clicking on the cell it shows 12/31/2018. I tried using
ActiveSheet.Range("B3:B500").Find(What:=CDate("Dec. 31, 2018")).Activate
and
ActiveSheet.Range("B3:B500").Find(What:=12/31/2016).Activate
But neither works as I get an error "Object Variable not set"). I have been googling a lot and couldn't find a suitable solution which activates the relevant cell. What's wrong with my approach?

This appears to work:
Sub dural2()
Dim lDate As Date, r As Range
lDate = DateSerial(2018, 12, 31)
Set r = ActiveSheet.Range("B3:B500").Find(What:=lDate)
r.Select
End Sub
Simply verify that the data in column B are real Excel dates rather than text values that resemble dates.Creating the range using FIND() will permit you to test it before you attempt to Select it and trap any errors yourself.

Related

Iteration using multiple named ranges

What I'm trying to do is create a journaling spreadsheet that records the time and date of the entry at the time its submitted from a UserForm then updates the calendar on a "Splash" worksheet to change the cell interior and font colors to show that a journal entry has been created for that specific day.
I have a module created to iterate through what has already been imported from older journal entries from earlier this year and I want to change the interior color and text color of a cell in the named ranges named after the months. In the image below, the month names are not in the named ranges, just the list of numbers.
Calendar View
Basically, I want to search the dates, select and change the color of the cell of those dates in the calendar (see above). I can make it through the first month named range just fine but when it becomes a new month, it gives me run-time error 91.
Sub updateCells()
Dim rCell As Range
Dim rRng As Range: Set rRng = Worksheets("Journals").Range("A2:A44")
Dim thisDate, thisMonth, thisDay
Dim thisMonthRange As Range
For Each rCell In rRng.Cells
thisDate = Split(rCell.Text, " ")(0)
thisMonth = MonthName(month(thisDate))
thisDay = day(thisDate)
Range(thisMonth).Find(what:=thisDay).Interior.ColorIndex = 10
Range(thisMonth).Find(what:=thisDay).Font.Color = vbWhite
Next rCell
I'm am relatively new to VBA so I don't understand what would be causing the run-time error.
This takes having named ranges that are the actual names of the month, e.g., "January" list of dates (1-31) are referenced by Range("January").
I would use the following code to highlight the "18" in my Range("May") for today's date (2022-05-18):
Sub markCurrentDate()
Cells.ClearFormats
Dim currentMonth As String
currentMonth = Format(Date, "mmmm")
Dim currentDay As Long
currentDay = Format(Date, "dd")
Dim foundDate As Range
Set foundDate = Range(currentMonth).Find(currentDay)
foundDate.Interior.ColorIndex = 27
End Sub
Since we can't tell what your source cell for the date you're referring is, based on the current post, I used Date rather than a reference to a cell. The reference can be updated through, similar to being able to use With foundDate to add multiple format changes.
I think the problem is likely to be that one of your named ranges does not cover the entire range of days. February surely doesn't, you're missing the 28th!
At any rate, as a consequence (and apparently only on the second turn (a Feb 28?)), you run into the Run-time error '91', because Range(thisMonth).Find(what:=thisDay) is resolving to Nothing instead of an expected Range object once you fail to find thisDay inside the named range.
Evidently, the code cannot execute Nothing.Interior.ColorIndex = 10.
If correct, your solution should be to double-check and fix the incorrect named ranges.
Incidentally, Range(thisMonth).Find(what:=thisDay) is also superfluous. For obvious reasons, each range simply starts at 1 and increments with 1. So we could simply use thisDay as the index. Instead of this:
Range(thisMonth).Find(what:=thisDay).Interior.ColorIndex = 10
Range(thisMonth).Find(what:=thisDay).Font.Color = vbWhite
Simply use this:
With Range(thisMonth).Cells(thisDay)
.Interior.ColorIndex = 10
.Font.Color = vbWhite
End With
Update: come to think of this, if you want to insist on using Range(thisMonth).Find(what:=thisDay), you should at the very least change the snippet to Range(thisMonth).Find(what:=thisDay, LookAt:=xlWhole).
Counterintuitively, Range.Find(...) seems to accept a partial match by default (xlPart) and it actually remembers the settings you used on your last find (in the same Excel 'session'). Also, it will not always start where you expect it to do (see further this documentation and this post: Using the .Find Function VBA - not returning the first value). E.g. a realistic error depending on your settings / active cell position might be that your code (and incidentally, also the code provided by Cyril) will change the formatting for a day 10, when in fact you were trying to change the formatting for a day 1.

Variable equal to formula with a declared variable

Sorry if the title is confusing, not sure how to phrase this. Basically I want to write a formula which takes a date from a cell specified by the user (myDate) and the address of a starting cell (FirstCell) and based on that:
Sets a range (myArea) which starts from the specified cell and extends for a number of cells equal to the number of days in the month and year of the date we selected (numDays).
Counts cells in that range that do not have a blank interior (there is no conditional formatting in the sheet) and returns that number.
For example let's say I have the date 1/4/2022 and April in 2022 has 5 days but my table has 6 columns. I want to define a range based on the length of this specific month so that the number of cells which do not have a blank interior is equal to 1 and not 2. And I want this to be reproducible for different months.
The 2nd point is done and works with a simple user-specified range, the 1st point is the one giving me trouble because I don't want it to return anything in the sheet. The specific issue is setting numDays but there may be other errors I didn't catch - basically I tried to transplant the excel function solution to counting this into VBA but I'm pretty sure I'm getting the syntax wrong and/or this is not doable. Couldn't find anything that would answer my question on here, when I try to use the function it returns #VALUE! in the spreadsheet.
Function SPECIALDAYS (FirstCell as Range, myDate as Date)
Dim myCell as Range
Dim myArea as Range
Dim numDays as Integer
numDays = Application.Evaluate("Day(Eomonth(" & myDate & ",0))")
Set myArea = Range(FirstCell, FirstCell.Offset(0, numDays-1))
For Each myCell In myArea
If myCell.Interior.ColorIndex <> -4142 Then
SPECIALDAYS=SPECIALDAYS+1
End If
Next myCell
End Function
Instead of using Evaluate and formula use a pure VBA solution with WorksheetFunctions:
numDays = Day(Application.WorksheetFunction.EoMonth(Date, 0))
See WorksheetFunction.EoMonth method.

excel vba range.find not finding date

I'm trying to establish the minimum date and its associated row for later use in a subroutine.
I'm hitting an error and i've spent the last few hours isolating the issue and searching for the solution to no avail.
I have a spreadsheet where column B contains a range of dates arranged in order. I can find the minimum date (the message box correctly returns 11/14/2015), but when I try use that date value to identify the row number I get error 91. Here is my code:
Sub testing()
ThisWorkbook.Worksheets("Burn Curve Data").Activate
Dim rDateColumn As Range
Dim dMinDate As Date
Set rDateColumn = ActiveSheet.Range("B:B")
dMinDate = Application.WorksheetFunction.Min(rDateColumn)
MsgBox dMinDate
Dim rMinCell As Range
Dim intMinRow As Integer
Set rMinCell = rDateColumn.Find(dMinDate, LookIn:=xlValues, LookAt:=xlWhole)
intMinRow = rMinCell.Row
MsgBox intMinRow
End Sub
I tried inserting an If Not statement after Set rMinCell and determined that range.find is not finding the date. Here is the statement I used to identify the error, but I deleted it to clean up the code for this posting.
If Not rMinCell is Nothing Then
intMinRow = rMinCell.Row
Else
MsgBox "error finding rMinCell"
End If
I also tried re-saving dMinDate into a string then using that string in the range.find but I encountered the same error of not finding the date.
Another nuance that may or may not be relevant is that this data exists within a named range on the worksheet. What am I doing wrong with my range.find line?!?
As discussed in the comments it appears the issue arises when the column is formatted as something other than Date.
To do this via code you can add this line after you set the rDateColumn variable:
rDateColumn.NumberFormat = "m/d/yyyy"
This should format the column as a date and your Find method should work appropriately.
Alternatively you can select the column, click 'Format Cells' and then ensure 'Date' is selected under Category.

How can I keep the date format from a VLookup returned value?

I have a sheet whit mixed format data (dates, double, strings, etc.).
I search the value (my_index) in the lookup_range and I want to retrieve the data to change with it a cell in other sheet. It works fine, but when the value returned by VLookup is a date and I set it to the other sheet it looses its date format.
Dim lookup_range As Range
Dim my_index, my_value As Variant
my_value = Application.VLookup(my_index, lookup_range, num_col, False)
Sheets(3).Cells(num_row, last_col_s1 + num_col - 1).Value = my_value
So, when the data in the lookup_range is 02/05/2014 the data showed at sheet-3 looks like 41761.
I need to keep the original data format of the data in the lookup_range.
VLOOKUP doesn't care about the formatting of the data it's returning - it returns data, not formats.
The only way to ensure the same format as the source, is to copy/paste that format, either manually or programmatically.
use this
Sheets(3).Cells(num_row, last_col_s1 + num_col - 1).Value = cdate(my_value)
I had the same problem, and simply reformatted the VLOOKUP cell to also be in date-time format. That fixed my issue. I am not sure how date-time gets translated into a number, but it does.
i faced the same issue. After vlookup, change the format to "ShortDate" format. This will give you what you are looking for.
Excel Formula :
=TEXT(VLOOKUP(Lookup_value,table_array,col_index_num,0),"dd-mm-yyyy")
VBA :
Sub vlookup_code()
Dim table_rng As Range
'FOR THE TIME BEING GIVING A LOOKUP VALUE
look_up_value = "sekar"
'SETTING THE TABLE ARRAY RANGE
Set table_rng = Sheet1.Range("C3").CurrentRegion
'SINCE VLOOKUP WILL GIVE AN ERROR, IF THE LOOKUP VALUE IS NOT PRESENT
'TO HANDLE THIS ERROR, WE USE THE ISERROR STATEMENT
If IsError(Application.vlookup(look_up_value, table_rng, 2, 0)) = False Then
vlook_value = WorksheetFunction.vlookup(look_up_value, table_rng, 2, False)
'CHANGING THE VLOOKUP VALUE FORMAT TO DATE FORMAT
date_format = WorksheetFunction.Text(vlook_value, "dd-mm-yyyy")
End If
End Sub
In Microsoft Office 2016.
Once data copied to the cell. Select the column which needs to be in date format. Right click->format cells, go to Number tab and select date from the drop-down and choose the required date format, data will be converted to date format.

Excel Formula which places date/time in cell when data is entered in another cell in the same row

Hoping there is a way this can be done with a formula since I will be putting this on SharePoint as a shared workbook.
Column B contains Tasks, while Column E contains the Date and Time of when the Task was assigned. Is there a formula that would automatically enter the current date and time in Column E whenever someone entered data into column B?
Any assistance would be greatly appreciated.
Another way to do this is described below.
First, turn on iterative calculations on under File - Options - Formulas - Enable Iterative Calculation. Then set maximum iterations to 1000.
The 1000 iterations doesn't matter for this formula, but it stops excel getting stuck in an infinite loop for other circular references.
After doing this, use the following formula.
=If(D55="","",IF(C55="",NOW(),C55))
Once anything is typed into cell D55 (for this example) then C55 populates today's date and/or time depending on the cell format. This date/time will not change again even if new data is entered into cell C55 so it shows the date/time that the data was entered originally.
This is a circular reference formula so you will get a warning about it every time you open the workbook. Regardless, the formula works and is easy to use anywhere you would like in the worksheet.
This can be accomplished with a simple VBA function. Excel has support for a Worksheet Change Sub which can be programmed to put a date in a related column every time it fires.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 2 And Target.Offset(0, 3).Value = "" Then
Target.Offset(0, 3) = Format(Now(), "HH:MM:SS")
End If
End Sub
A quick explanation. The following "if" statement checks for two things: (1) if it is the second column that changed (Column B), and (2) if the cell 3 columns over (Column E) is currently empty.
If Target.Column = 2 And Target.Offset(0, 3).Value = "" Then
If both conditions are true, then it puts the date into the cell in Column E with the NOW() function.
Target.Offset(0, 3) = Format(Now(), "HH:MM:SS")
Range.Offset
Range.Column
Not sure if this works for cells with functions but I found this code elsewhere for single cell entries and modified it for my use. If done properly, you do not need to worry about entering a function in a cell or the file changing the dates to that day's date every time it is opened.
open Excel
press "Alt+F11"
Double-click on the worksheet that you want to apply the change to (listed on the left)
copy/paste the code below
adjust the Range(:) input to correspond to the column you will update
adjust the Offset(0,_) input to correspond to the column where you would like the date displayed (in the version below I am making updates to column D and I want the date displayed in column F, hence the input entry of "2" for 2 columns over from column D)
hit save
repeat steps above if there are other worksheets in your workbook that need the same code
you may have to change the number format of the column displaying the date to "General" and increase the column's width if it is displaying "####" after you make an updated entry
Copy/Paste Code below:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Range("D:D")) Is Nothing Then Exit Sub
Target.Offset(0, 2) = Date
End Sub
Good luck...
I'm afraid there is not such a function. You'll need a macro to acomplish this task.
You could do something like this in column E(remember to set custom format "dd/mm/yyyy hh:mm"):
=If(B1="";"";Now())
But it will change value everytime file opens.
You'll need save the value via macro.
You can use If function
Write in the cell where you want to input the date the following formula:
=IF(MODIFIED-CELLNUMBER<>"",IF(CELLNUMBER-WHERE-TO-INPUT-DATE="",NOW(),CELLNUMBER-WHERE-TO-INPUT-DATE),"")
Here is the solution that worked for me
=IF(H14<>"",NOW(),"")

Resources