问题
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:
For reference the named range "Table24" does exist. The table has no data in it.
回答1:
Answer: If WorksheetFunction.CountA(Range("Table24")) = 1 Then
回答2:
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:
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
回答4:
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:
- If the ListObject (table) variable "Is Nothing" it generates an easy to understand error.
- 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. - 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 returnsFalse. - 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 returnsFalse.
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
来源:https://stackoverflow.com/questions/36027393/vba-excel-determine-if-table-has-data