0

I've searched and searched the internet and all of the forums and I've been piecing together code and still can't figure this out. I've tried For loops and For Each loops and still can't get it right. In my sheet, I have all of my dates in Column D. I want to hide rows by month. I want to be able to click a macro button and only show dates in January, or February, or etc.

This is what I currently have:

Sub January()
'
'
'
Dim cell As Range
For Each cell In Range("Date")
    If cell.Value = "" Then
        cell.EntireRow.Hidden = False
    End If
    If cell.Value < "1/1/2018" Or cell.Value > "1/31/2018" Then
        cell.EntireRow.Hidden = True
    End If
Next cell
End Sub

When I run this, it just hides anything that isn't an empty cell. I've cycled between defining cell as a Range and as a Variant and it's the same either way.

ETA:

It is working now and it took help from everybody. I really appreciate it! Here's what I ended with..

Sub January()
'
'
'
Dim cell As Range
For Each cell In Range("Date")
    If cell.Value = "" Then
        cell.EntireRow.Hidden = False
    ElseIf cell.Value < CDate("1/1") Or cell.Value > CDate("1/31") Then
        cell.EntireRow.Hidden = True
    End If
Next cell
End Sub

I removed the years from the code so that I don't have to change any coding for future years.

5 Answers5

1

Your current setup would qualify all dates as either < or > the respective date comparison.

If you are trying to hide rows for January in this code, then you need to use AND instead of OR

And be sure you use >= & <= to include those first and last dates.

If cell >= "1/1/2018" AND cell <= "1/31/2018" Then

If you are trying to hide rows not January then your < and > are transposed:

If cell < "1/1/2018" OR cell > "1/31/2018" Then
Brent
  • 98
  • 9
1

Alternative approach: If you've got Excel 2013 or later, simply add a Table Slicer and filter on a MONTH column generated with =DATE(YEAR([@Date]),MONTH([@Date]),1) as shown below:

enter image description here

Or otherwise use a PivotTable and a Slicer: enter image description here

To see how easy it is to set up a PivotTable, see VBA to copy data if multiple criteria are met

jeffreyweir
  • 4,668
  • 1
  • 16
  • 27
  • Thanks Jeffrey. I am trying to avoid tables and slicers for this as I want to keep it as clean as possible and tables have not been my friend in the past. – Katie Sharp Aug 06 '18 at 20:30
  • Cool. Note that Tables used to be crap back in 2007. They are much improved a decade later. – jeffreyweir Aug 06 '18 at 22:02
  • My main issue with tables is when I want to duplicate a row, move a row, or delete multiple, non-consecutive rows, which I do regularly, it doesn't work as smoothly as cut and insert and it screws up my formatting. I use Excel for keeping records of current reservations. Things move regularly, so I'm trying to make it as fluid as possible. – Katie Sharp Aug 07 '18 at 02:43
1

Ultimately, I believe this is the code you're looking for:

Sub January()
Dim cell As Range

Application.ScreenUpdating = False

For Each cell In Range("Date")
 'If date falls on or after January 1, AND on or before January 31, don't hide the row
  If cell.Value >= CDate("1/1/2018") And cell.Value <= CDate("1/31/2018") Then
    cell.EntireRow.Hidden = False
  Else
   'If the cell doesn't contain anything or isn't in January, hide the row
    cell.EntireRow.Hidden = True
  End If
Next cell

Application.ScreenUpdating = True
End Sub

You need to use And logic, not Or logic. Or logic always returns TRUE unless both expressions are false or there is a null involved. Because of this, the code stopped looking at your logical statement once it evaluated to true since every date you had - I'm assuming - fell after January 1, 2018. This in turn caused the rows to hide unexpectedly.

Additionally, I would convert the strings you have into dates using CDate. It helps Excel understand what is going on a bit better and makes your code easier to understand to outsiders. Another good practice to work on is adding comments to code. I think we've all learned the hard way by leaving comments out of code at some point or another.

One last thing: if you're planning to have buttons for each month, consider doing one procedure for all of them and having variables populate the date ranges, potentially using input boxes to get the values from the user. It'll save you a lot of headaches if you ever decide to change things up in the future.

TotsieMae
  • 835
  • 6
  • 17
  • Thanks. This all makes sense looking at it. I'll have to double check when I get back on my work computer. – Katie Sharp Aug 07 '18 at 02:42
  • Good luck, Katie. Please let us know what your solution ultimately ends up being. – TotsieMae Aug 07 '18 at 02:46
  • This worked to hide all of January, but as Brent pointed out, I had the symbols transposed. My intent was to hide everything not in January. I tried transposing the numbers and it goes back to doing nothing. – Katie Sharp Aug 07 '18 at 12:33
  • I edited my answer. I haven't been able to test it, but it should look at everything in your `Date` range and hide anything that isn't in January. – TotsieMae Aug 07 '18 at 13:06
  • Thanks Totsie! Unfortunately, This didn't work for me. I did adjust my format to CDate. However, the And logic does not work for this statement, as something can't be before January and After January. – Katie Sharp Aug 07 '18 at 13:53
0

Untested, written on mobile. I am just providing an alternative approach which tries to use MONTH and YEAR. Some may find this approach easier to understand.

Option Explicit

Sub January()

Dim cell As Range

For Each cell In Range("Date")
    If cell.Value = "" Then
        cell.EntireRow.Hidden = False
    Else
    cell.EntireRow.Hidden = (Month(cell.Value) = 1) and (year(cell.Value) = 2018)
End if

Next cell

End sub
chillin
  • 4,391
  • 1
  • 8
  • 8
  • Thanks for your help! I tried this out, and it worked to hide all of January, but it also come up with an error in the Else line. – Katie Sharp Aug 07 '18 at 12:58
0

I will actually go with Slicers and Table.
But if you call VBA your neat solution then I'd say abandon the loop.
Have nothing against it but if Excel already have the functionality, then use it.
It is like a discount or a promotion that we need to take advantage of.
So instead of loop, why not just filter?

Dim lr As Long, r As Range
With Sheet1 '/* sheet where data reside */
    .AutoFilterMode = False '/* reset any filtering already applied */
    lr = .Range("D" & .Rows.Count).End(xlUp).Row '/* get the target cells */
    Set r = .Range("D1:D" & lr) '/* explicitly set target object */
    '/* filter without showing the dropdown, see the last argument set to false */
    r.AutoFilter 1, ">=2/1/2018", xlAnd, "<=2/28/2018", False 
End With

Above is for February of this year, you can tweak it to be dynamic.
You can create separate sub procedure for each month of you can just have a generic one.

L42
  • 19,427
  • 11
  • 44
  • 68
  • Tables and Slicers do not work for what I am using Excel for. This worked to hide all but February, but it also hid my heading, the row where I keep my macro buttons, and all of my blank rows which are used as separators. It also locked my page from un-hiding rows and running any other macros. – Katie Sharp Aug 07 '18 at 13:05
  • Why did you edit my original post and remove "Any help is greatly appreciated." There is nothing in the Code of Conduct regarding Thanks. – Katie Sharp Aug 07 '18 at 20:15
  • @KatieSharp This is not a direct solution to your problem but a pointer on what you can accomplish using `Excel-built-in` functionalities. As for removing the thanks part, see [*how to ask question page*](https://stackoverflow.com/help/how-to-ask) under *Writing the perfect question*. – L42 Aug 07 '18 at 23:55
  • Wow. So because it's not necessary in the perfect question, you've decided it's just not going to be included in MY question at all. That is so rude. – Katie Sharp Aug 08 '18 at 03:15
  • @KatieSharp I share the same view with the author regarding sign-offs and greetings, plain and straight. Let us focus on the issue / question per se. If you find that my edit is irrelevant, you can always roll it back since that is your question. I am just trying to help not only me but others focus on relevant information. I apologize too if that seem rude to you. – L42 Aug 08 '18 at 05:33
  • If you see something that doesn't necessarily pertain to the question, just pass over it... I'm so terribly sorry for trying to be friendly. – Katie Sharp Aug 08 '18 at 12:31
  • @KatieSharp `If you see something that doesn't necessarily pertain to the question, just pass over it`. Exactly our point. If you have something that doesn't pertain to the question, just do not include it. Providing sufficient details and formatting your question well is *friendly* enough. – L42 Aug 09 '18 at 00:55