View Full Version : Solved: Find Last Row With Border
zoom38
03-15-2007, 06:49 PM
Can someone help me find the last row that has a border.  I can find the last row with data but not the last row that has no data but does have a border.
 
Thanks
Gary
geekgirlau
03-15-2007, 10:20 PM
Sub FindLastBorderRow()
    Dim rng As Range
    Dim rngEnd As Range
    Dim lngRowLast As Long
    Dim lngRow As Long
    Dim r As Long
    Dim intCol As Integer
    Dim c As Integer
    
    
        ' find the last cell
    Set rng = ActiveSheet.UsedRange
    Set rngEnd = Range(Mid(rng.Address, InStr(1, rng.Address, ":") + 1))
    
    intCol = rngEnd.Column
    lngRow = rngEnd.Row
    
        ' loop backwards through the used range
    For r = lngRow To 1 Step -1
        For c = intCol To 1 Step -1
                ' only testing for border at bottom of cell
            If Cells(r, c).Borders(xlEdgeBottom).LineStyle <> xlNone Then
                lngRowLast = r
                GoTo FoundEnd
            End If
        Next c
    Next r
    
    
ExitHere:
    Exit Sub
    
FoundEnd:
    MsgBox "The last row with a border is " & lngRowLast
End Sub
zoom38
03-16-2007, 05:52 PM
Thankyou GG, I thought there would've been an easier way, but it works great.   Below is what i used it for.  Could you perhaps explain why my printsetup sub takes so long to complete.  It took at least 1 minute for your sub with my printsetup sub to complete.  Seems like forever. 
Sub FindLastBorderRow()
    Dim rng         As Range
    Dim rngEnd      As Range
    Dim lngRowLast  As Long
    Dim lngRow      As Long
    Dim r           As Long
    Dim intCol      As Integer
    Dim c           As Integer
    Dim Sheet       As Integer
         
For Sheet = 9 To 36
    Sheets(Sheet).Activate
     ' find the last cell
    Set rng = ActiveSheet.UsedRange
    Set rngEnd = Range(Mid(rng.Address, InStr(1, rng.Address, ":") + 1))
     
    intCol = rngEnd.Column
    lngRow = rngEnd.Row
     
     ' loop backwards through the used range
    For r = lngRow To 1 Step -1
        For c = intCol To 1 Step -1
             ' only testing for border at bottom of cell
            If Cells(r, c).Borders(xlEdgeBottom).LineStyle <> xlNone Then
                lngRowLast = r
                Call PrintSetup(lngRowLast)
            End If
        Next c
    Next r
Next Sheet
End Sub
Sub PrintSetup(lngRowLast)
With ActiveSheet.PageSetup
    .Orientation = xlLandscape
    .LeftMargin = Application.InchesToPoints(0.21)
    .RightMargin = Application.InchesToPoints(0.21)
    .TopMargin = Application.InchesToPoints(0.15)
    .BottomMargin = Application.InchesToPoints(0.15)
    .HeaderMargin = Application.InchesToPoints(0)
    .FooterMargin = Application.InchesToPoints(0)
    .Zoom = 70
    .PaperSize = xlPaperLetter
    .PrintArea = "$a$1:$l" & lngRowLast
End With
End Sub
 
Although the speed isn't really that critical I was just wondering why it takes so long to execute.  Maybe my way is the long way. 
Thanks 
Gary
mudraker
03-17-2007, 06:13 AM
Your FindLastBorderRow loops through every cell in the ActiveSheet.UsedRange. It continues to loop even after calling PrintSetup. Also activating a sheet slows the process down.
 
I have modified your code to:-
Remove code that appeared to be doing nothing.
Merginging some lines of code into 1 line of code
Add code to break out of the for loops after PrintSetup has been called
changes made to PrintSetup macro so the sheet to be setup does not have to be active
Overall you should see a speed increase
 
 Sub FindLastBorderRow()
   Dim bPrint      As Boolean
   Dim lngRow      As Long
   Dim r           As Long
   Dim intCol      As Integer
   Dim c           As Integer
   Dim Sheet       As Integer
     
   For Sheet = 9 To 36
      bPrint = False
      With Sheets(Sheet)
         intCol = .Cells.Find(What:="*", SearchOrder:=xlByColumns, _
            SearchDirection:=xlPrevious).Column
         lngRow = .Cells.Find(What:="*", SearchOrder:=xlByRows, _
            SearchDirection:=xlPrevious).Row
       
         ' loop backwards through the used range
         For r = lngRow To 1 Step -1
             For c = intCol To 1 Step -1
                  ' only testing for border at bottom of cell
                 If .Cells(r, c).Borders(xlEdgeBottom).LineStyle <> xlNone Then
                     Call PrintSetup(r, Sheet)
                     bPrint = True
                     Exit For
                 End If
             Next c
             If bPrint = True Then
               Exit For
            End If
         Next r
      End With
   Next Sheet
End Sub
 
 
Sub PrintSetup(lngRowLast As Long, iSheet As Integer)
     
    With Sheets(iSheet).PageSetup
        .Orientation = xlLandscape
        .LeftMargin = Application.InchesToPoints(0.21)
        .RightMargin = Application.InchesToPoints(0.21)
        .TopMargin = Application.InchesToPoints(0.15)
        .BottomMargin = Application.InchesToPoints(0.15)
        .HeaderMargin = Application.InchesToPoints(0)
        .FooterMargin = Application.InchesToPoints(0)
        .Zoom = 70
        .PaperSize = xlPaperLetter
        .PrintArea = "$a$1:$l" & lngRowLast
    End With
End Sub
mdmackillop
03-17-2007, 06:31 AM
Hi Mudraker,
Highlight the code and click the VBA button to do the formatting, rather than [Code] tags.
BTW, I noticed that GG had an exit from the loop which was omitted by Zoom.
zoom38
03-17-2007, 09:38 AM
Yes MD that was a mistake of mine to eliminate the exit.  I have added that back in but the routine still takes over a minute to complete.  Mudraker your find routine locates the last cell with data.  I am looking for a routine that finds the last row with a bottom border which GG created.   I replaced your:
         intCol = .Cells.Find(What:="*", SearchOrder:=xlByColumns, _
         SearchDirection:=xlPrevious).Column
         lngRow = .Cells.Find(What:="*", SearchOrder:=xlByRows, _
         SearchDirection:=xlPrevious).Row
 
with GG's code: 
      Set rng = ActiveSheet.UsedRange
      Set rngEnd = Range(Mid(rng.Address, InStr(1, rng.Address, ":") + 1))
      intCol = rngEnd.Column
      lngRow = rngEnd.Row
 
which finds the last row with a bottom border.  I changed from activating sheets to using your isheet code.  Overall I don't see a difference in the length of time it takes for your code versus GG's code to complete.  I timed your code a 1:46 and GG's code at 1:47.
Here is GG's code modified for my use:
Sub FindLastBorderRow()
Dim rng             As Range
Dim rngEnd          As Range
Dim LastBorderRow   As Long
Dim lngRow          As Long
Dim r               As Long
Dim intCol          As Integer
Dim c               As Integer
Dim Sheet           As Integer
         
For Sheet = 9 To 36
    Sheets(Sheet).Activate
     ' find the last cell
    Set rng = ActiveSheet.UsedRange
    Set rngEnd = Range(Mid(rng.Address, InStr(1, rng.Address, ":") + 1))
     
    intCol = rngEnd.Column
    lngRow = rngEnd.Row
     
     ' loop backwards through the used range
    For r = lngRow To 1 Step -1
        For c = intCol To 1 Step -1
             ' only testing for border at bottom of cell
            If Cells(r, c).Borders(xlEdgeBottom).LineStyle <> xlNone Then
                LastBorderRow = r
                Call PrintSetup(LastBorderRow)
                GoTo FoundEnd
            End If
        Next c
    Next r
FoundEnd: Next Sheet
End Sub
Sub PrintSetup(LastBorderRow)
Application.ScreenUpdating = False
With ActiveSheet.PageSetup
    .Orientation = xlLandscape
    .LeftMargin = Application.InchesToPoints(0.21)
    .RightMargin = Application.InchesToPoints(0.21)
    .TopMargin = Application.InchesToPoints(0.15)
    .BottomMargin = Application.InchesToPoints(0.15)
    .HeaderMargin = Application.InchesToPoints(0)
    .FooterMargin = Application.InchesToPoints(0)
    .Zoom = 70
    .PaperSize = xlPaperLetter
    .PrintArea = "$a$1:$l" & LastBorderRow
End With
End Sub
 
Here is Mudraker's code modified for my use:
Sub FindLastBorderRow()
    Dim bPrint      As Boolean
    Dim lngRow      As Long
    Dim r           As Long
    Dim intCol      As Integer
    Dim c           As Integer
    Dim Sheet       As Integer
     
    For Sheet = 9 To 36
        bPrint = False
        With Sheets(Sheet)
            Set rng = ActiveSheet.UsedRange
            Set rngEnd = Range(Mid(rng.Address, InStr(1, rng.Address, ":") + 1))
            intCol = rngEnd.Column
            lngRow = rngEnd.Row
             
             ' loop backwards through the used range
            For r = lngRow To 1 Step -1
                For c = intCol To 1 Step -1
                     ' only testing for border at bottom of cell
                    If .Cells(r, c).Borders(xlEdgeBottom).LineStyle <> xlNone Then
                        Call PrintSetup(r, Sheet)
                        bPrint = True
                        Exit For
                    End If
                Next c
                If bPrint = True Then
                    Exit For
                End If
            Next r
        End With
    Next Sheet
End Sub
Sub PrintSetup(r, isheet As Integer)
Application.ScreenUpdating = False
With Sheets(isheet).PageSetup
        .Orientation = xlLandscape
        .LeftMargin = Application.InchesToPoints(0.21)
        .RightMargin = Application.InchesToPoints(0.21)
        .TopMargin = Application.InchesToPoints(0.15)
        .BottomMargin = Application.InchesToPoints(0.15)
        .HeaderMargin = Application.InchesToPoints(0)
        .FooterMargin = Application.InchesToPoints(0)
        .Zoom = 70
        .PaperSize = xlPaperLetter
        .PrintArea = "$A$1:$L" & r
End With
End Sub
 
They both take an extremely long time to execute.  I was hoping to slim 30 seconds or so off, but again it not that critical.
Thanks
Gary
mdmackillop
03-17-2007, 11:34 AM
A different methodology, timed at 4 - 5 seconds.
Option Explicit
Sub DoSetup()
    Dim Rw As Long, Rw1 As Long, Rw2 As Long
    Dim i As Long, ws As Worksheet
    'Set format to find
    With Application.FindFormat.Borders(xlEdgeBottom)
        .LineStyle = xlContinuous
        .Weight = xlThin
        .ColorIndex = xlAutomatic
    End With
    On Error Resume Next
    For i = 9 To 36
        Rw1 = 0: Rw2 = 0
        Set ws = Sheets(i)
        With ws
            'Data cells
            Rw1 = .Cells.Find(What:="*", After:=.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
                        xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, _
                        SearchFormat:=True).Row
            'Blank cells
            Rw2 = .Cells.Find(What:="", After:=.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
                        xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, _
                        SearchFormat:=True).Row
        End With
        'Last formatted cell
        Rw = Application.WorksheetFunction.Max(Rw1, Rw2)
        
        PrintSetup ws, Rw
    Next
End Sub
Sub PrintSetup(ws As Worksheet, Rw As Long)
    With ws.PageSetup
        .Orientation = xlLandscape
        .LeftMargin = Application.InchesToPoints(0.21)
        .RightMargin = Application.InchesToPoints(0.21)
        .TopMargin = Application.InchesToPoints(0.15)
        .BottomMargin = Application.InchesToPoints(0.15)
        .HeaderMargin = Application.InchesToPoints(0)
        .FooterMargin = Application.InchesToPoints(0)
        .Zoom = 70
        .PaperSize = xlPaperLetter
        .PrintArea = "$A$1:$L$" & Rw
    End With
End Sub
mudraker
03-18-2007, 05:02 AM
zoom38
 
I guess I should not try and solve problems when I should be sleeping
 
MD
2 other excel sites that I'm a memebr of use the Wrap Code for posting the VBA code In. I will try & remember when on this site to use the VBA button & not the #
zoom38
03-18-2007, 06:53 AM
MD I get a "Compile Error: Named Argument Not Found"  and it highlights SearchFormat=
I'm working with Excel 2000 and the "SearchFormat" argument is not listed in the help file under Find method.  Is that in a newer version or do I need to download an addin?
mdmackillop
03-18-2007, 09:12 AM
I guess that SearchFormat is a 2003 addition, which means you're stuck with the loop.:(
mdmackillop
03-18-2007, 09:13 AM
2 other excel sites that I'm a memebr of use the Wrap Code for posting the VBA code In. I will try & remember when on this site to use the VBA button & not the #
Hi Mudraker,
I've heard that before. Trust us to be different!
zoom38
03-18-2007, 09:39 AM
Thank you.
Gary
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.