VBA Excel Determine if “Table##” has data

2020-07-16 09:07发布

I have the following code developed to create a chart from a named Range "Table24". However, there will be times when this table has no valid data and then I want the range of my dataset to be a cell with 0 and populate the chart with no data.

This is for the 4th out of 5 charts- using the debug module I've determined that this is the code which crashes my excel file everytime it's run:

'//////////////////CHART 4 Creation //////////////////////////////
Set myChtRange = ws.Range("L43:R63")
' What range contains data for chart

If ws.Range("Table24").Rows.Count > 0 Then

Set myDataRange = ws.ListObjects("Table24").ListColumns(3).DataBodyRange

Else

Set myDataRange = ws.Range("K1")

End If

' Cover chart range with chart
Set objChart = .ChartObjects.Add( _
    Left:=myChtRange.Left, Top:=myChtRange.Top, _
    Width:=myChtRange.Width, Height:=myChtRange.Height)
' Put all the right stuff in the chart
With objChart.Chart
    .ChartArea.AutoScaleFont = False
    .ChartType = xlColumnClustered
    .ChartStyle = 214
    .SetSourceData Source:=myDataRange
    .Parent.Name = "Chart4"
    .HasTitle = True
    .HasLegend = False
    .ChartTitle.Characters.Text = "Most Tolerance Holds"
    .ChartTitle.Font.Bold = True
    .ChartTitle.Font.Size = 15

If ws.Range("Table24").Rows.Count > 0 Then

     .SeriesCollection(1).XValues = ws.ListObjects("Table24").ListColumns(2).DataBodyRange
Else
    .SeriesCollection(1).XValues = ws.Range("K1")

End If
    With .Axes(xlCategory, xlPrimary)
        .HasTitle = True
        With .AxisTitle
            .Characters.Text = " "
            .Font.Size = 10
            .Font.Bold = True
        End With
    End With
    With .Axes(xlValue, xlPrimary)
        .HasTitle = True
        .DisplayUnit = none
        .HasDisplayUnitLabel = False
        .TickLabels.NumberFormat = "#,##0.0"
        With .AxisTitle
            .Characters.Text = "Lines"
            .Font.Size = 15
            .Font.Bold = True
        End With
    End With
End With

I have tried:

If ws.ListObjects("Table24").DataBodyRange.Rows.Count > 0 Then

If NOT ws.ListObjects("Table24").DataBodyRange Is Nothing Then

And even the IS Empty

I need help in creating the correct argument when the table looks like this:

enter image description here

For reference the named range "Table24" does exist. The table has no data in it.

enter image description here

标签: excel vba
4条回答
虎瘦雄心在
2楼-- · 2020-07-16 09:19

The databodyrange property of a listobject represents the range of data. if there is no data in the list object, then the range has nothing

if ws.ListObjects("Table24").DataBodyRange is Nothing then
  'Do something if there is no data
Else
  'Do something if there is data
end if
查看更多
别忘想泡老子
3楼-- · 2020-07-16 09:34

Add this function (taken from here):

Function DBRRangeTest(rng1 As Range, Optional rng2 As Range)
    ' DataBodyRange Range Test

    ' Test if rng1 and rng2 intersect
    If rng2 Is Nothing Then
        ' Either no argument was supplied or the supplied argument was empty
        DBRRangeTest = False
        Exit Function
    End If

    If (rng1.Parent.Name = rng2.Parent.Name) Then
        Dim ints As Range
        Set ints = Application.Intersect(rng1, rng2)
        If (Not (ints Is Nothing)) Then
            DBRRangeTest = True
        End If
    End If
End Function

Then, replace this:

If ws.Range("Table24").Rows.Count > 0 Then

Set myDataRange = ws.ListObjects("Table24").ListColumns(3).DataBodyRange

Else

Set myDataRange = ws.Range("K1")

End If

with this:

Dim tbl As ListObject
Set tbl = ws.ListObject("Table24")

If DBRRangeTest(tbl.HeaderRowRange.Offset(1), tbl.DataBodyRange) Then
    ' If this test returns true, it means that there is a valid databodyrange _
    ' but we have no guarantee whether the cell is empty or not, because DataBodyRange _
    ' will return with an address if there *has* been a value in its range.
    ' So we'll test manually.
    If tbl.HeaderRowRange.Offset(1).Value <> "" Then
        Set myDataRange = tbl.ListColumns(3).DataBodyRange
    Else
        Set myDataRange = ws.Range("K1")
    End If
Else
    ' The test returned false, which essentially is the same as _
    ' DataBodyRange Is Nothing.
    Set myDataRange = ws.Range("K1")
End If
查看更多
Ridiculous、
4楼-- · 2020-07-16 09:39

I'll share the function I use. It returns TRUE if a ListObject (table) is empty below the header row and above total row. (It still works if the table isn't displaying either the header or total row.)

This function checks for 1 of 4 possibilities:

  1. If the ListObject (table) variable "Is Nothing" it generates an easy to understand error.
  2. If the table doesn't have a DataBodyRange (no data was added below the header and above the total row and no blank rows were added to the table except for the row automatically created when the table was created) then it returns False.
  3. If the table has a DataBodyRange but every cell below the header and above the total row is Empty (does not contain a value, not even a zero length vbNullString character) then it returns False.
  4. If (a) the table has a DataBodyRange and (b) at least one cell below the header and above the total row is NOT Empty (contains any value, including a zero length vbNullString character) then it returns False.

Function IsEmptyTable()

Public Function IsEmptyTable(ByVal target As Excel.ListObject) As Boolean        

    Const APPNAME As String = "IsEmptyTable()"

    If target Is Nothing Then
        ' The parameter doesn't contain a ListObject (table).
        Err.Raise 2310, _
                  APPNAME, _
                  APPNAME & String$(2, vbNewLine) & "Parameter 'target' must refer to a valid ListObject (table)."

    ElseIf target.DataBodyRange Is Nothing Then
        ' The table doesn't have a databody range and therefore has no data below
        '   the header row and above the total row.
        IsEmptyTable = True

    Else
        ' The table has a DataBodyRange.
        '   Check it for any non-empty cells (including zero-length
        '   vbNullString).  Return TRUE if any are found.
        IsEmptyTable = Excel.WorksheetFunction.CountA(target.DataBodyRange) = 0

    End If
End Function
查看更多
在下西门庆
5楼-- · 2020-07-16 09:40

Answer: If WorksheetFunction.CountA(Range("Table24")) = 1 Then

查看更多
登录 后发表回答