If Row Is Visible Then Run Code

nitrammada

Board Regular
Joined
Oct 10, 2018
Messages
78
Office Version
  1. 365
Platform
  1. Windows
Hi Everyone,
I have some code that references each row with a page and row reference in column C starting at row 7, this code works fine. However, I have to filter out some unwanted rows not required for the report, so I make the unwanted row height = 0. Can someone help me to run the code only on the visible rows please. Below is the code that runs perfectly well, I figure I will have to wrap it in an If statement somehow, but I'm not sure about all the Dims and variables etc. Any help would be appreciated.
VBA Code:
Sub RunPgNoSheet1()

'Adds page numbers for the Ref column C on Sheet1
   
      Const c = 3, F1 = "=""", F2 = "/""&LEFT(ADDRESS(1,ROW()-", F3 = ",2),1+(ROW()>", F4 = "))"
            r& = 7
      With ActiveSheet
        For L& = 1 To .HPageBreaks.Count
            P& = r
            r& = .HPageBreaks(L).Location.Row
           .Columns(c).Rows(P & ":" & r - 1).Formula = F1 & L & F2 & P - 1 & F3 & P + 25 & F4
        Next
            P = r
            r = .UsedRange.Rows.Count
            If P <= r Then .Columns(c).Rows(P & ":" & r).Formula = F1 & L & F2 & P - 1 & F3 & P + 25 & F4
      End With

End Sub
 
when I programmed my TI-84 plus graphing calculator.
That reminds me I started with a TI-57 then with some Casio then a HP 15C then my favorite the Canon X-07 : memories !​
Maybe it's because you can get to the heart of the matter with precision?
I don't know how you do it, but you're clearly better at this than I am!)
I don't kwow even myself as sometimes I well aim the heart of the subject but sometimes very not …​
What is the best code : yours, mine ? In fact after years of practice, with complicated codes using arrays, loops, external ressources like Dictionary, etc …​
more on BASIC side than on Excel side, after the day a former colleague of a company I had left said they could not maintain my former codes​
so for any change they had to rewrite all the code as a more beginner way, maybe less efficient but easier to maintain,​
so the answer to this question is : the code the OP is able to understand but far above all the one he is able to maintain …​
Then after years I was able to well understand at least what a famous MVP had advised me​
since like a padawan I try to follow the TEBV & TBTO VBA main rules aka Think Excel Before VBA and Think, But Think Object !​
(Maybe more like a Mandalorian and his creed !)​
According to post #9 or after running it take a glance to the formula in cell C7 for example so you should see here​
I started to ask myself « What Excel offers first to help to solve this need ? » (TEBV rule) before to write any codeline on VBA side …​
For the second main rule, I prefer to work directly with an appropriate object (like the With statement) rather than using useless variables​
or some cumbersome code …​
The classic example is some big data must be filtered then copied to another worksheet : often I saw answers with so many codelines​
- could be fast & efficient - but too complicated for a beginner to maintain the code​
instead of just using some quick enough Excel basics like an advanced filter requiring less than five codelines !​
Maybe I'm pretty good but many are better than I am at this game …​
 
Last edited:
Upvote 0

Excel Facts

Save Often
If you start asking yourself if now is a good time to save your Excel workbook, the answer is Yes
[...] while your code works, the row lettering is not sequential, eg 1/A, 1/B, 1/C etc, starting at row 7 it returns 1/A, 1/B, 1/D where row 9 is the unwanted row and row 10 is labelled 1/D. Is there a way I could set the condition based on the row height and, for the row lettering to be sequential when it skips a row who's height is less that 10?
Although I didn't explicitly mention it, I believe the code I provided in my previous post fixed this issue. Please let me know that it is as you want (and works for you, considering that Excel from my end wanted to insert unwanted @ symbols into the 1/A column automatically. If something is wrong with it, I can modify it further.) And if you want me to remove the "Select Range" prompt, let me know. But I don't want to automatically assume that your sheet's used range's row count is also your print range, because that obviously means that your printer is going to be printing the current report + X number of additional blank pages that were in the previously largest report.

@Marc L , see this topic. I would like to continue this great discussion there! I was gong to post that here, but obviously it's off-topic (for the most part).
 
Upvote 0
Okay, looking at the result of Marc's code tells me that my above formula was wrong. That we need to keep increasing the column letters until we reach the next (printed) page.

Assuming that at least one cell has some value in the column that you want to insert the 1/A fractions into (or a column to the right of it, the following code will:
  • Ask you to select the print range. (If you already selected it before with this code and/or did so with the print menu, just press the [Esc] key to continue . . . keep the previous print range.)
  • Insert formulas or values in three helper columns. These helper column letters to be filled will be those which are outside of your used range. For example, if the last column you have ever typed anything into is column K, the first helper column to be filled is column L. (And then the other two will be columns M and N.)
  • Clear the entire column where you previously put the #/columnLetter fractions (1/A) starting from the first cell where it needs to be placed (which you . . . at the moment, I can change it if you want . . . manually type into the beginning of the code in place of where I currently have "B7") and ending in the very last used cell in that row. So if you choose to put the 1/A fractions in column B, and your print range goes only to row 1000, but you have data in cell B1001, the content in cell B1001 will also be cleared.
  • Fill it.
  • Remove @ symbols in that column (that Excel is mysteriously putting in, causing a #Value error!)
  • Convert the formulas in that column to values only.
  • Clear the contents that was placed into the three helper columns such that the number of used columns (your horizontal scroll scope range) will remain the same.
    • (If you want to see the formulas that this code puts into the helper columns, uncomment Line #1 and Line #2 at the end.
VBA Code:
Option Explicit

Sub Place_Fractions_On_Visible_Rows_To_Print()

'Assumes that the 1/A fractions are placed starting at row 2 or greater!!!

Dim printRange As String
Dim totalVisibleRowsToBePrintedSoFar As Integer
Dim firstRowOnNextPrintedPage As Long
Dim numOfVisRowsOnCurrentPrintedPage As Integer
Dim currentPageBreakRowNumber As Long
Dim topCellToPlaceFractions As String
Dim lastUsedColumnNumber As Integer
Dim firstRow As Long
Dim lastRow As Long
Dim lastusedRowInSheet As Long
Dim visibleRowIndicator_ColumnLetter As String
Dim numberOfPrintedRowsPerPage_ColumnLetter As String
Dim letterNumberOnCurrentPrintedPage_ColumnLetter As String
Dim columnToPut_Fractions_ColumnLetter As String

'___________________________________
'Input
topCellToPlaceFractions = "B7"
'___________________________________

firstRow = Range(topCellToPlaceFractions).Row

printRange = RangeSelectionPrompt("Select Print Range (Pres [Esc] to keep previous)")

With ActiveSheet
    If printRange <> "" Then
        .PageSetup.PrintArea = printRange
    Else
        printRange = .PageSetup.PrintArea
    End If

    lastRow = Range(printRange).Rows.Count + firstRow - 1

    'Place the helper columns in the columns to the RIGHT of the right-most used column of the data.
    lastUsedColumnNumber = .UsedRange.Columns.Count + .UsedRange.Column - 1 'The actual right-most column.

    '****************************************************************
    'Fill helper column that identifies rows with a row height >= 10.
    '****************************************************************

        lastUsedColumnNumber = lastUsedColumnNumber + 1 'a new column to the right of that.
        visibleRowIndicator_ColumnLetter = Split(Cells(1, lastUsedColumnNumber).Address, "$")(1)

        '=IF(@RowHeight(A7)>=10,H6+1,H6)
        .Range(visibleRowIndicator_ColumnLetter & firstRow & ":" & visibleRowIndicator_ColumnLetter & lastRow).Formula = _
            "=IF(RowHeight(M7)>=10," & visibleRowIndicator_ColumnLetter & firstRow - 1 & "+1," & visibleRowIndicator_ColumnLetter & firstRow - 1 & ")"


    '*******************************************************************************************************
    'Fill helper column that marks the VISIBLE row that is the last row on the current (to be) printed page.
    '*******************************************************************************************************

        lastUsedColumnNumber = lastUsedColumnNumber + 1 'a new column to the right of that.
        numberOfPrintedRowsPerPage_ColumnLetter = Split(Cells(1, lastUsedColumnNumber).Address, "$")(1)

        totalVisibleRowsToBePrintedSoFar = 0
        For currentPageBreakRowNumber = 1 To .HPageBreaks.Count

            firstRowOnNextPrintedPage = .HPageBreaks(currentPageBreakRowNumber).Location.Row

            numOfVisRowsOnCurrentPrintedPage = Range(visibleRowIndicator_ColumnLetter & firstRowOnNextPrintedPage - 1).Value - totalVisibleRowsToBePrintedSoFar

            .Range(numberOfPrintedRowsPerPage_ColumnLetter & firstRowOnNextPrintedPage - 1).Value = numOfVisRowsOnCurrentPrintedPage

            totalVisibleRowsToBePrintedSoFar = totalVisibleRowsToBePrintedSoFar + numOfVisRowsOnCurrentPrintedPage
        Next

    '*****************************************************************************************
    'Fill helper column that signifies the "increment" of the Column Letters in the fractions.
    '*****************************************************************************************

        lastUsedColumnNumber = lastUsedColumnNumber + 1 'a new column to the right of that.
        letterNumberOnCurrentPrintedPage_ColumnLetter = Split(Cells(1, lastUsedColumnNumber).Address, "$")(1)

        '=IF(I7<>"",J6+1,H7-SUM($I$7:I7))
        .Range(letterNumberOnCurrentPrintedPage_ColumnLetter & firstRow & ":" & letterNumberOnCurrentPrintedPage_ColumnLetter & lastRow).Formula = _
        "=IF(" & numberOfPrintedRowsPerPage_ColumnLetter & firstRow & "<>" & Chr(34) & Chr(34) & _
        "," & letterNumberOnCurrentPrintedPage_ColumnLetter & firstRow - 1 & "+1," & visibleRowIndicator_ColumnLetter _
        & firstRow & "-SUM($" & numberOfPrintedRowsPerPage_ColumnLetter & "$" & firstRow & ":" & numberOfPrintedRowsPerPage_ColumnLetter & firstRow & "))"

    '*********************************************************************
    'Fill the column specified by user with the #/column letter fractions.
    '*********************************************************************

        lastusedRowInSheet = .UsedRange.Rows.Count + .UsedRange.Row - 1

        columnToPut_Fractions_ColumnLetter = Split(Cells(1, Range(topCellToPlaceFractions).Column).Address, "$")(1)

        'Clear previous contents in the column of focus (even beneath the print range if the print range doesn't go all the way to the end).
        .Range(columnToPut_Fractions_ColumnLetter & firstRow & ":" & columnToPut_Fractions_ColumnLetter & lastusedRowInSheet).Formula = ""

        With .Range(columnToPut_Fractions_ColumnLetter & firstRow & ":" & columnToPut_Fractions_ColumnLetter & lastRow)
            .Formula = ""
            '=SUM(IF($I$6:I6<>"",1,0))+1&"/"&SUBSTITUTE(SUBSTITUTE(ADDRESS(1,J7),"$",""),"1","")
            .Formula = _
            "=SUM(IF(" & "$" & numberOfPrintedRowsPerPage_ColumnLetter & "$" & firstRow - 1 & ":" & numberOfPrintedRowsPerPage_ColumnLetter & firstRow - 1 & "<>" _
            & Chr(34) & Chr(34) & ",1,0))+1&" & Chr(34) & "/" & Chr(34) & "&SUBSTITUTE(SUBSTITUTE(ADDRESS(1," & letterNumberOnCurrentPrintedPage_ColumnLetter _
            & firstRow & ")," & Chr(34) & "$" & Chr(34) & "," & Chr(34) & Chr(34) & ")," & Chr(34) & "1" & Chr(34) & "," & Chr(34) & Chr(34) & ")"
            .Replace What:="@", Replacement:="", LookAt:=xlPart, FormulaVersion:=xlReplaceFormula2
            ActiveSheet.Calculate
            .Formula = .Value 'Line #1
        End With

    '***********************************************
    'Clear the formulas in all three helper columns.
    '***********************************************
        .Range(visibleRowIndicator_ColumnLetter & firstRow & ":" & letterNumberOnCurrentPrintedPage_ColumnLetter & lastRow).Value = "" 'Line #2

End With

End Sub


Function RowHeight(MR As Range) As Double
RowHeight = MR.RowHeight
End Function


Sub Test__RangeSelectionPrompt()
MsgBox RangeSelectionPrompt("Choose Cells")
End Sub
Function RangeSelectionPrompt(titleOfRangeSelectionPromptBox As String)
'Code is from http://www.vbaexpress.com/forum/showthread.php?763-Solved-Inputbox-Cell-Range-selection-Nothing-selected-or-Cancel&p=6680&viewfull=1#post6680

Dim Selectedarea As Range
On Error Resume Next
Set Selectedarea = Application.InputBox(prompt:="Left click on the top-left cell and drag to the botSomething-right cell.", _
Title:=titleOfRangeSelectionPromptBox, Default:=Selection.Address, Type:=8)

'If the user clicked on cancel,
If Selectedarea Is Nothing Then Exit Function

RangeSelectionPrompt = Selectedarea.Address

End Function

Maybe it's because you can get to the heart of the matter with precision? But I see a few regular contributers on here who prefer to use a single letter to name a variable. I actually remember doing that when I programmed my TI-84 plus graphing calculator.

Anyway, I was actually curious to see what my sub above would look like if I condensed it (I substituted the previously descriptive variable names with single letters and removed helpful comments). If I looked at this code in 6 months, I bet I would know exactly what it does. (Just kidding . . . I don't know how you do it, but you're clearly better at this than I am!)
VBA Code:
Sub Demo1r2()
Dim A$, B%, C&, D%, E&, F$, G%, H&, I&, J&, K$, L$, M$, N$, O$, P$
F = "B7"
O = Chr(34)
P = O & O
H = Range(F).Row
A = RangeSelectionPrompt("Select Print Range (Pres [Esc] to keep previous)")
With ActiveSheet
    If A <> "" Then
        .PageSetup.PrintArea = A
    Else
        A = .PageSetup.PrintArea
    End If
    I = Range(A).Rows.Count + H - 1
    G = .UsedRange.Columns.Count + .UsedRange.Column - 1
        G = G + 1
        K = Split(Cells(1, G).Address, "$")(1)
        .Range(K & H & ":" & K & I).Formula = "=IF(RowHeight(A7)>=10," & K & H - 1 & "+1," & K & H - 1 & ")"
        G = G + 1
        L = Split(Cells(1, G).Address, "$")(1)
        B = 0
        For E = 1 To .HPageBreaks.Count
            C = .HPageBreaks(E).Location.Row
            D = Range(K & C - 1).Value - B
            .Range(L & C - 1).Value = D
            B = B + D
        Next
        G = G + 1
        M = Split(Cells(1, G).Address, "$")(1)
        .Range(M & H & ":" & M & I).Formula = "=IF(" & L & H & "<>" & P & "," & M & H - 1 & "+1," & K & H & "-SUM($" & L & "$" & H & ":" & L & H & "))"
        J = .UsedRange.Rows.Count + .UsedRange.Row - 1
        N = Split(Cells(1, Range(F).Column).Address, "$")(1)
        .Range(N & H & ":" & N & J).Formula = ""
        With .Range(N & H & ":" & N & I)
            .Formula = ""
            .Formula = _
            "=SUM(IF(" & "$" & L & "$" & H - 1 & ":" & L & H - 1 & "<>" _
            & P & ",1,0))+1&" & O & "/" & O & "&SUBSTITUTE(SUBSTITUTE(ADDRESS(1," & M _
            & H & ")," & O & "$" & O & "," & P & ")," & O & "1" & O & "," & P & ")"
            .Replace What:="@", Replacement:="", LookAt:=xlPart, FormulaVersion:=xlReplaceFormula2
            ActiveSheet.Calculate
            .Formula = .Value
        End With
        .Range(K & H & ":" & M & I).Value = ""
End With
End Sub
Gentlemen, what can I say. This is amazing. Thank you both cmowla and Marc, great to touch base with you again Marc. I had a chance this morning to run through what you both had posted and both work fantastically. Let me explain my process.
First, I ran cmowla's code from post #7, it ran fine, but didn't change the page numbering at the page breaks, but I could understand how you were using the helper column B.
Second, I ran Marc's code from Post #8, [Sub Demo1r()], this too ran fine, page numbering changed perfectly at the page breaks however, I noticed from letters 'O' through to 'Z', irrespective of the page number, the letters were suffixed with a '$' sign after it. I couldn't work out why. After (page number)/Z$ the next line was (page number)/AA which was perfect.
Third, I ran Marc's code from Post #9, [Sub Demo1r2d2()], this too ran perfectly, very quick, however, still had the $ sign appearing in same location as mentioned above.
Forth, I ran cmowla's code from post #10, 1st part. Thanks so much for explaining so clearly step by step what you were doing, this has helped me no end. The code ran fine but ended up in a continuous loop, I think trying to delete the helper columns but not too sure, I am an amateur at this as you can see.
Fifth, I ran cmowla's code from post #10, 2nd part only this time [Sub Demo1r2()]. I commented out this line:

A = RangeSelectionPrompt("Select Print Range (Pres [Esc] to keep previous)")

as I do already have a dynamic print range set up. It ran perfectly, took about 5 seconds to run over 900 rows. I added
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
at the beginning of the code, and then reversed it a the end of the code and it took less than 1 second. Amazing stuff.
I would be interested Marc to know how to remove the $ signs that appear on the end of letters 'O' through to 'Z' but you have already been so helpful, if you don't have time, no worries.
Thank you both once again for the time and effort you have both put in to solving my problem, it is greatly appreciated.
Kind regards
Adam
 
Upvote 0
Forth, I ran cmowla's code from post #10, 1st part. Thanks so much for explaining so clearly step by step what you were doing, this has helped me no end. The code ran fine but ended up in a continuous loop, I think trying to delete the helper columns but not too sure, I am an amateur at this as you can see.
Fifth, I ran cmowla's code from post #10, 2nd part only this time [Sub Demo1r2()]. I commented out this line:

A = RangeSelectionPrompt("Select Print Range (Pres [Esc] to keep previous)")

as I do already have a dynamic print range set up. It ran perfectly, took about 5 seconds to run over 900 rows. I added
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
at the beginning of the code, and then reversed it a the end of the code and it took less than 1 second. Amazing stuff.
You're quite welcome! So that (my code in post #10) is what you wanted to do, exactly, correct?

EDIT: Okay, I guess so!

And, out of curiosity, if you comment out the line:
VBA Code:
.Replace What:="@", Replacement:="", LookAt:=xlPart, FormulaVersion:=xlReplaceFormula2

Do you get #Value errors in the column where the 1/A fractions are supposed to be? (I am wondering if it's just me. I wonder why Excel is putting in @ symbols!)
 
Upvote 0
You're quite welcome! So that (my code in post #10) is what you wanted to do, exactly, correct?

EDIT: Okay, I guess so!

And, out of curiosity, if you comment out the line:
VBA Code:
.Replace What:="@", Replacement:="", LookAt:=xlPart, FormulaVersion:=xlReplaceFormula2

Do you get #Value errors in the column where the 1/A fractions are supposed to be? (I am wondering if it's just me. I wonder why Excel is putting in @ symbols!)
Yes, I do. I thought it might be because all my data is generated from a pivot table that in turn is generated from a query. I know that when referencing tables the "@" sign appears but I'm guessing this may not be the reason in this instance.
 
Upvote 0
Oh, okay! I don't like to use Range.Replace like that, but I had no choice. (There is no reason for it from what I can tell.)

Also, just in case you were thrown off of why I used the column letter M in RowHeight(M7), you can use any column letter for that. So there is no particular reason! FYI. (I used a different letter in my "condensed version" in the same post.
VBA Code:
 "=IF(RowHeight(M7)>=10," & visibleRowIndicator_ColumnLetter & firstRow - 1 & "+1," & visibleRowIndicator_ColumnLetter & firstRow - 1 & ")"
 
Upvote 0
Oh, okay! I don't like to use Range.Replace like that, but I had no choice. (There is no reason for it from what I can tell.)

Also, just in case you were thrown off of why I used the column letter M in RowHeight(M7), you can use any column letter for that. So there is no particular reason! FYI. (I used a different letter in my "condensed version" in the same post.
OK, got it. As it happens column M is fine as it's out of my print range, but good to know, thanks.
 
Upvote 0
OK, got it. As it happens column M is fine as it's out of my print range, but good to know, thanks.
I should have said the reason why! RowHeight can be determined by any cell in the row! (So that means any interection of any column letter with that row (cell with columnLetter & row.)

Glad I could help. Best.
 
Upvote 0

Forum statistics

Threads
1,224,819
Messages
6,181,153
Members
453,021
Latest member
Justyna P

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top