[更新]:我的问题末尾使用的最终代码。
我的问题涉及使用VBA在Microsoft Excel中进行图形自定义。
我正在尝试将图形的标签颜色自定义为红色(如果标签包含括号),并且设置为黑色。 查找下面的图形以供参考(具有4个标签)。
所需结果如下所示:
到目前为止,我已经基于其他示例获得了代码,但没有达到我的目标。
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
答案 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
请注意,If
和Else
语句中的语句以句点(.
)开头。这告诉编译器“在我在那儿的With
语句中调用的对象的末尾开始寻找缩短的函数/方法/属性”。即它将.Font.Color
转换为Qtr.Points(i).DataLabel.Font.Color
,这就是您要设置为vbBlack
或vbRed
的内容。
再次,我不确定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:Left
和Left$
几乎相同。但是Left
返回一个变量,该变量需要隐式转换为string
才能与“(”进行比较,而Left$
返回一个不需要隐式转换的string
答案 1 :(得分:2)
存在两个三个问题:(根据评论)
当您在Then
之后的同一行中输入文字时,您的If
语句被视为单行代码,不需要End If
。因此,在您的代码中有一个End If
没有对应的If
。有关示例,请参见Microsoft docs
有一个With
没有相应的End With
。
您的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