Excel VBA图表-如果包含“括号”,将图表的标签设置为红色吗?

时间:2019-04-26 11:34:07

标签: excel vba

[更新]:我的问题末尾使用的最终代码。

我的问题涉及使用VBA在Microsoft Excel中进行图形自定义。

我正在尝试将图形的标签颜色自定义为红色(如果标签包含括号),并且设置为黑色。 查找下面的图形以供参考(具有4个标签)。 graph

所需结果如下所示:

graph

到目前为止,我已经基于其他示例获得了代码,但没有达到我的目标。

Sub Labels_graph_Test()

Dim Qrts As Series

Set ChtObj = ActiveSheet.ChartObjects("Q_Graph")
Set Qrts = ChtObj.Chart.SeriesCollection(1)

For i = 1 To 4

     With Qrts.Points(i).DataLabel

     If InStr(1, currentcell, "(*") Then With Selection.Font.Color = vbRed
     Else: Selection.Font.Color = vbBlack

     End If   

Next i

End Sub

此代码不起作用,并显示“编译错误:如果没有块则结束,如果结束”。

请不要告诉我使用条件格式,因为在这种情况下,标签来自单元格,因此条件格式不起作用。

非常感谢您

如果不清楚,请告诉我

最好的问候, 马蒂姆·平托

最终密码:

(有关更多的见解,请查看Luuklag和FreeMan的答案-都给出了非常有用的见解和解释)

Sub Labels_graph_Test()

Dim Qrts As Series

Set ChtObj = ActiveSheet.ChartObjects("Q_Graph")
Set Qrts = ChtObj.Chart.SeriesCollection(1)

    For i = 1 To 4
        With Qrts.Points(i).DataLabel

            If Left(.Text, 1) = "(" Then
                .Font.Color = vbRed
            Else
                .Font.Color = vbBlack
            End If
        End With
    Next i

End Sub

2 个答案:

答案 0 :(得分:4)

您在For循环中进行的格式化使非常难以阅读,因此非常容易 搞砸。

如果您像这样解决缩进问题:

Sub Labels_graph_Test()

  Dim Qrts As Series

  Set ChtObj = ActiveSheet.ChartObjects("Q_Graph")
  Set Qrts = ChtObj.Chart.SeriesCollection(1)

  For i = 1 To 4

    With Qrts.Points(i).DataLabel
      If InStr(1, currentcell, "(*") Then
        With Selection.Font.Color = vbRed
      Else
        Selection.Font.Color = vbBlack
      End If

  Next i

End Sub

很容易看到您有两个With未被End With封闭的块。

此外,您没有正确使用With。我相信(在我的头上,请不要在此引用我,您可能需要做一些其他研究)。它应该看起来像这样:

    With Qrts.Points(i).DataLabel
      If InStr(1, currentcell, "(*") Then
        .Font.Color = vbRed
      Else
        .Font.Color = vbBlack
      End If
    End With

请注意,IfElse语句中的语句以句点(.)开头。这告诉编译器“在我在那儿的With语句中调用的对象的末尾开始寻找缩短的函数/方法/属性”。即它将.Font.Color转换为Qtr.Points(i).DataLabel.Font.Color,这就是您要设置为vbBlackvbRed的内容。

再次,我不确定100%是设置颜色的确切位置-您应该能够在MS上的SO上轻松找到该位置文档,或使用宏记录器手动设置颜色,然后告诉您要设置的确切属性。 (Macro Recorder是优秀,是懒惰的人找到这些属性的方法。它在编写漂亮,可读,高效,可维护的代码时 糟透了 。)

currentcell:我最初的假设是这是模块或整个项目的全局变量,其中包含您要查看的内容。似乎我错了(假设您就是这样)...

我相信您要替换为currentcell的{​​{1}}是Qrts.Points(i).DataLabel.Text,因此您可以查看此特定点的实际标签。但是,您在那里有该With语句,因此可以将其缩短为.Text。您的If语句如下:

If Left$(.Text, 1) = "(" Then

有关此If语句其余部分的重写,请参阅“另一种思想”部分。

同样,我不能100%地确定.Text是确切的财产,但是,我认为,仅此而已。如果没有,则可以在VBE的立即窗口中键入ChartObjects.Points(i).DataLabel.,并且IntelliSense应该会为您提供所有可能选项的列表。滚动列表以查找可能的候选人。如果仍然不确定,请在代码运行时执行此操作(逐步执行If语句,然后执行上述过程)。如果您在立即窗口中使用?进行操作,它将打印您要查询的值,以便您进行检查。注意-这只是解决此问题的多种方法之一(MS Docs,SO,Google等是其他选项)。

另一种想法:您可以执行以下操作,而不是使用不太可读的InStr函数来检查字符串的第一个字符是否为左括号:

If Left$(currentcell, 1) = "(" Then

我不确定性能水平的差异,可能还很短,但是下一个人必须维护此代码(可能是将来的您)所需的精力会低得多,因此更易于维护

NB:LeftLeft$几乎相同。但是Left返回一个变量,该变量需要隐式转换为string才能与“(”进行比较,而Left$返回一个不需要隐式转换的string

代码

答案 1 :(得分:2)

存在两个三个问题:(根据评论)

  1. 当您在Then之后的同一行中输入文字时,您的If语句被视为单行代码,不需要End If。因此,在您的代码中有一个End If没有对应的If。有关示例,请参见Microsoft docs

  2. 有一个With没有相应的End With

  3. 您的currentcell未声明,因此不保存任何值。您正在寻找datalabel的文本。由于您已经在数据标签的With循环内,因此可以将currentcell替换为.Text,以引用当前Datalabel的文本值。

您的代码应类似于:(未经测试)

For i = 1 To 4

     With Qrts.Points(i).DataLabel

         If InStr(1, currentcell, "(*") Then 
             .Font.Color = vbRed
         Else 
             .Font.Color = vbBlack
         End If   
     End With
Next i