Iteration using multiple named ranges - excel

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.

Related

Excel VBA Xlookup to reference worksheet containing certain date

Still a novice at VBA but learning and ran up what i believe is a pretty advanced request.
I have a workbook our managers use that has 5 worksheets created each month. Each one is suffixed by the current Month_YYYY. I am trying to add an Xlookup to the worksheet whose date is one month prior (same prefix) and fill down to the last row.
So in this example, in B2 of the Oasis_Detail_November_2022 worksheet I would have:
=IFERROR(XLOOKUP(A2,'Oasis_Detail_October_2022'!A:A,'Oasis_Detail_October_2022'!B:B),C2) In December, it would reference the November tab and so on.
Is it even possible to do this? If it helps, the order of the tabs are always the same and i'm always looking 5 back (this example I hid a column just for screenshot room).
This is my rudimentary code thusfar. Thanks for the help.
Sub Oasis_Detail_Formatting()
Rows(2).EntireRow.Delete
Columns("A").Cut
Columns("C").Insert
[A:A].Select
With Selection
.NumberFormat = "General"
.Value = .Value
End With
Columns("B").Insert
Range("B1").Value = ("Svc Rel Parent")
ActiveSheet.UsedRange.EntireColumn.AutoFit
End Sub
I tried to use a Dim Dt As String and Dt = Format(Date, "mmmm_yyyy") statement within the Xlookup code but everyway i formatted the function, i just kept getting a debug error.

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.

Copy range based on a date

I'm new to VBA, my experience is basically record macros and adapt them a little bit, and i´ve been playing with a macro to copy a filtered range in sheet 1 based on a date value located in sheet 2 range "C42", the copy part is working
I have tried a couple of solutions i found on the internet but they don't work for me and I can't find the mistake (probably very simple but my lack of knowledge prevents me from finding it)
Sub CopyPaste
If Worksheets("Costos Médicos").Range("C42") = Worksheets("CC1").Range("B101") Then 'both values are visually in date format "dd/mm/yyyy" but if changed to general give a number
Call Cost1 'This is a macro currently working
ElseIf Worksheets("Costos Médicos").Range("C42") = Worksheets("CC1").Range("B102") Then
Call Cost2 'This one also works fine
end if
End Sub
'I also tried this, I've tried declaring cm as long, string, date, but all returns error 9 (again lack of knowledge)
Dim src As Worksheet
Dim tgt As Worksheet
Dim cm0 As Range
Dim cm1 As Range
Dim cm2 As Range
Set src = ThisWorkbook.Sheets("CC1")
Set tgt = ThisWorkbook.Sheets("Costos Médicos")
Set cm0 = src.Range("C42") 'This is the given date
Set cm1 = tgt.Range("B101") 'This is a date
Set cm2 = tgt.Range("B102") 'This is another date
If cm0 = cm1 Then
Call Cost1 'this Works fine by itself
ElseIf cm0 = cm2 Then
Call Cost2 'this also Works
End If
I think the problem is simple but can't find the answer, I have tried multiple solutions online but they usually are for far more complicated things that I don't understand. Any help would be greatly appreciated.
I am quite sure that one of the Worksheet Names is typed incorrectly, as Error 9 means that you called an element by name or position which is not present, so "out of range".
Change the names of the sheets to x and y for a test.
Concerning the dates: You do not need to worry about the formatting. Every whole day is represented by a whole number. Hours, Minutes etc. are fractions thereof. Dates are stored as Floating point numbers (both in cells an in VBA) and can be compared to other dates or integers with no problems.

Copy/paste dates exactly as displayed? Not necessarily the format, but as they're displayed visually

I can't seem to figure out how to overwrite my date with what's being displayed.
For example, what's being displayed is 06/01/2016, but the actual data behind that is showing 01/06/2016. The date I want to have in there is June 1, 2016 (which is what's displayed). Changing the format of the cell doesn't help, because I'm doing some formulas with the Dates later, so actually need to have Excel have the correct date.
I have about 10,000 of such dates, where the displayed date is exactly what I want to have, but the actual formula "reversed".
Essentially, I would love to just copy that column (or run a sub) that puts what the cell literally displays into the cell.
What sort of works is doing this, but it only works on those cells with "backwards" dates...essentially passing the day as a month, and month as a day.
=DATE(YEAR(C1),DAY(C1),MONTH(C1)).
It "falls apart" though when the date is actually correct and I don't want it to change:
So, what'd be best is to just literally overwrite the cell with what's displayed.
Or, what would an IF statement be that I could use to somehow check if the date displayed is what I want, and if so keep that, otherwise use that =DATE(YEAR(),DAY(),MONTH()) "trick"?
I also tried =IF(DAY(C2)>12,DATE(YEAR(C2),DAY(C2),MONTH(C2)),C2) but that doesn't work either because it returns June 01 2016 for both 01/06/2016 and 06/01/2016.
I may be overlooking something simple, I've been staring at this for an hour or so...Any thoughts/ideas are appreciated!
Say wee have dates in column C from C1 through C100 that appear to be correct. (so if you see 06/12/2017 you want it to be June 12th and not December 6th)
Try this short macro:
Sub dateFixer()
Dim ary(1 To 100) As String
Dim rng As Range, r As Range
Dim i As Long
Set rng = Range("C1:C100")
i = 1
For Each r In rng
ary(i) = r.Text
i = i + 1
Next r
rng.Clear
rng.NumberFormat = "mm/dd/yyyy"
i = 1
For Each r In rng
r.Value = ary(i)
i = i + 1
Next r
End Sub
A really clean solution is to use the CELL() function.
=CELL("format",A1) will return "D1" for cells formatted as d/m/y, and "D4" for cells formatted m/d/y. So, with this you can conditionally flip month and day:
=IF(CELL("format",A2)="D1",DATE(YEAR(A2),DAY(A2),MONTH(A2)),A2)
The Text property of a range returns the display text: "what the cell literally displays."
Note that literal is the right word - for example, if your column is too narrow, Text will return the displayed ##### characters instead of any useful value.
The Text property will not return an array, so you'll have to loop through your range and read/write individual cells with something like this:
For Each c in rng
c.Value = c.Text
Next c
Incidentally, the documentation on this property is almost nonexistent. This blog post goes into a more detailed review of the property and how it relates to Value and Value2.

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.

Resources