Search code examples
vbaexcel-2013

Finding the address of a table range using vba


I am working with an excel sheet that has a bunch of sheets with data in tables. I am trying to consolidate the sheets. I do not want the copied data to be in tables. I am able to find the tables range address for all the sheets except one, which is retunring an address of $1:$104. All the other ranged are like this "$A$1:$J$43" . When I try to copy this table using the address it returns , I get the runtime error "1004". For now , the code rewrite all the tables in the same place, but I will be changing the code to copy the tables into different places in the destination sheet. Here is my code:

  Sub mergeWorksheets()
   Dim wrk As Workbook 'Workbook object - Always good to work with 
 object variables
   Dim sht As Worksheet 'Object for handling worksheets in loop
   Dim trg As Worksheet 'Master Worksheet
   Dim rng As Range 'Range object
   Dim colCount As Integer 'Column count in tables in the worksheets
   Dim mLastRow As Integer
   Dim LastRow As Integer
   Dim rngFound As Range
   Dim i As Integer

Set wrk = ActiveWorkbook 'Working in active workbook

'We don't want screen updating
Application.ScreenUpdating = False

' would rather not do a loop but using a function to check and delete sheet renders error
For Each Sheet In ActiveWorkbook.Worksheets
 If Sheet.Name = "Master" Then
    Application.DisplayAlerts = False
    Sheets("Master").Delete
    Application.DisplayAlerts = True
 End If
Next Sheet
 ' Add new worksheet as the last worksheet
  Set trg = wrk.Worksheets.Add(Before:=wrk.Worksheets(1))
 ' Rename the new worksheet
  trg.Name = "Master"

 'We can start loop
 For Each sht In wrk.Worksheets
    'If worksheet in loop is the last one, stop execution (it is Master worksheet)
    If sht.Name Like "*Attri*" Then
           Debug.Print sht.Name
           'Find the last row of the master sheet
           Set rngFound = trg.UsedRange.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious)
           If Not rngFound Is Nothing Then
           'you found the value - do something
               mLastRow = rngFound.Row
               Debug.Print "Last row of master " & rngFound.Address, mLastRow
           Else
           ' you didn't find anything becasue sheet is empty - first pass
              mLastRow = 0
           End If
           For Each tbl In sht.ListObjects
               'Do something to all the tables...
                Debug.Print tbl.Name
                Debug.Print tbl.Range.Address
                'Put data into the Master worksheet
                    tbl.Range.Copy Destination:=trg.Range("B1")
                 Next tbl

       '    trg.Cells(mLastRow + 1, 1).Value = "Tab Name"
        '   trg.Cells(mLastRow + 1, 1).Font.Bold = "True"
         '  trg.Range("A" & mLastRow + 1).Value = sht.Name

        Debug.Print "-------"
        Else
           ' Debug.Print "error " & sht.Name & " is missing header "
        End If

Next sht

Solution

  • That funny range is obviously there. What you can do is to control the size of the data to be copied. If you can set a meaningful maximum value for table width then you can limit size like this:

    const MAXWID = 1000
    Dim r As Range
    
    If tbl.Range.Columns.Count > MAXWID Then
        Set r = tbl.Range.Resize(, MAXWID)
    Else
        Set r = tbl.Range
    End If
    
    r.Copy Destination:=trg.Range("B1")
    

    Funny things can happen to the height of the table(s), too, so you may want to implement this for the other dimension. For appending the tables you need to know where the first empty row is:

    FirstEmptyRow = trg.Range("B1").SpecialCells(xlCellTypeLastCell).Row + 1
    r.Copy Destination:=trg.Cells(FirstEmptyRow, "B")
    

    For sheet manipulation you need to use On Error ... like this:

    Application.DisplayAlerts = False
    On Error Resume Next
    Set trg = wrk.Sheets("Master")
    If Err.Number = 0 Then    ' sheet exists
        trg.Usedrange.Delete  ' delete all existing data -> have a clean sheet
    Else   ' sheet doesn't exist, Add new worksheet as the first worksheet
        Set trg = wrk.Worksheets.Add(Before:=wrk.Worksheets(1))
        If Err.Number <> 0 Then <  sheet is not added, handle error...>
        trg.Name = "Master"
    End If
    On Error Goto 0
    Application.DisplayAlerts = True
    

    It's worth taking the time to learn how error handling works in VBA.

    And finally: use Option Explicit. It pays.