【问题标题】:Formatting chart data labels with VBA使用 VBA 格式化图表数据标签
【发布时间】:2016-10-26 12:12:40
【问题描述】:

我正在开发一个包含大量图表的仪表板,并且随着这些图表上显示的数据发生变化,数字的格式也会发生变化。就我现在而言,在循环遍历图表中的所有系列的过程中,我遇到了一个问题,试图从数据所基于的电子表格中检索预期的格式代码。 到目前为止的代码如下:

Sub FixLabels(whichchart As String)
Dim cht As Chart
Dim i, z As Variant
Dim seriesname, seriesfmt As String
Dim seriesrng As Range

Set cht = Sheets("Dashboard").ChartObjects(whichchart).Chart

    For i = 1 To cht.SeriesCollection.Count
        If cht.SeriesCollection(i).name = "#N/D" Then
            cht.SeriesCollection(i).DataLabels.ShowValue = False
            Else
            cht.SeriesCollection(i).DataLabels.ShowValue = True
                seriesname = cht.SeriesCollection(i).name
                Debug.Print seriesname

这样,我可以检索不会导致错误的系列名称,并隐藏会导致错误的系列。到现在为止还挺好。 现在开始格式化:有一列存储了该工作簿的所有可能的系列名称,左边一列是我的格式化代码,“int”表示整数,“#,#”表示带有重要小数大小写的数字,“%”表示百分比。这些以纯文本形式存储。所以最后一段代码看起来像:

Select Case seriesfmt
   Case "int"
      Cht.SeriesCollection(i).DataLabels.NumberFormat = "#"
   Case "#,#"
      Cht.SeriesCollection(i).DataLabels.NumberFormat = "#,###"
   Case "%"
      Cht.SeriesCollection(i).DataLabels.NumberFormat = "#.0%"
End Select
End If
Next i

最后,真正的问题在这里:介于两者之间。我无法检索系列格式!我的最佳猜测是:

With Sheets("CxC").Range("K22:K180")
seriesfmt = .Find(seriesname).Offset(0, -1).Value
End With

我收到错误,告诉我 With 块没有定义。我尝试了同一命令的几种组合,有或没有 With 方法,有和没有 Set 方法,我尝试了 WorksheetFunction Match,但无济于事。非常感谢任何解决此问题的帮助!

【问题讨论】:

    标签: vba excel charts


    【解决方案1】:

    您可以通过其Formula 属性爬升到系列源范围。

    因为它有格式:

    =SERIES(,,sheetname!sheetRange,)
    

    那么你对它的“第三个元素”感兴趣,如果你用“,”作为分隔符将它拆分成一个数组

    所以你可以编码:

    Sub FixLabels(whichchart As String)
        Dim cht As Chart
        Dim i As Long
    
        With Sheets("Dashboard").ChartObjects(whichchart).Chart '<--| reference your chart
            For i = 1 To .SeriesCollection.Count '<--| loop through all series
                With .SeriesCollection(i) '<--| reference current series
                    If .Name = "#N/D" Then
                        .DataLabels.ShowValue = False
                    Else
                        .HasDataLabels = True '<--| be sure labels are "activated"
                        .DataLabels.ShowValue = True '<--| show data labels
                        .DataLabels.NumberFormat = GetFormat(Split(.Formula, ",")(2)) '<-- set data label format
                    End If
                End With
            Next i
        End With
    End Sub
    
    
    Function GetFormat(dataSource As Variant) As String
        With Range(dataSource).Cells(1, 1) '<-- reference the first cell of the data source
            Select Case True
                Case InStr(.Text, "%") > 0
                    GetFormat = "#.0%"
                Case Int(CDbl(.Text)) = CDbl(.Text)
                    GetFormat = "#"
                Case Else
                    GetFormat = "#,###"
            End Select
        End With
    End Function
    

    【讨论】:

    • 感谢您的帮助!我收到运行时错误 6:Case CInt(.Text) = CDbl(.Text) 行的溢出由于我不熟悉这些方法,我不得不问。这个 Range(dataSource).Cells(1, 1) 是查看图表值还是格式名称?因为如果它正在查看格式,我认为它不会起作用,因为值是由查找公式确定的。如果它正在查看名称,则格式代码在一个单元格之前(偏移量(0,-1))。
    • .Text 超出范围–32,768 到32,767 时,溢出一定是由于CInt(.Text) 造成的(我用little 整数进行了测试...)。请参阅编辑后的答案,其中 .Text 首先转换为 Double(范围从 –1.79769313486232E+308 到 1.79769313486232E308,应该足够大......)然后通过 Int() 函数向下舍入到最接近的整数
    • Range(dataSource).Cells(1, 1) 引用数据源的第一个单元格。在我的测试中,我假设了一个“折线图”,因此Sheets("Dashboard").ChartObjects(whichchart).Chart.SeriesCollection(i).Formula 返回了一个类似=SERIES(,,sheetname!sheetRange,1) 的字符串,其第三个“元素”(即sheetname!sheetRange)是 values 范围的“完整”地址
    • 我使用条件格式将格式直接应用于数据源,并将'CInt(.Text)'更改为'CLng(.Text)',问题解决了!!非常感谢,user3598756!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多