/
ChartMacro.vb
256 lines (170 loc) · 7.06 KB
/
ChartMacro.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
Sub Left_Scroll()
Scroll ("left")
End Sub
Sub Right_Scroll()
Scroll ("right")
End Sub
Sub Scroll(direction As String)
'reference the scroll amount
Dim scroll_amount As Integer
scroll_amount = CInt(ActiveSheet.Range("Scroll_Amount"))
'MsgBox ("scrolling " & scroll_amount)
If ActiveChart Is Nothing Then
MsgBox ("No chart is selected")
Exit Sub
End If
'only adjust the x range once
Dim firstIteration As Boolean
firstIteration = True
For Each ser In ActiveChart.SeriesCollection
' Perform desired processing on each item.
'The following code uses the split function because VBA does seem to have lookbehind/lookahead in
'its regex library
Dim newFormula As String
If (StrComp(direction, "left") = 0) Then
'left scroll
newFormula = ChangeFormulaXRange(ser.formula, -1 * scroll_amount, -1 * scroll_amount, "adjust", firstIteration)
Else
'right scroll
newFormula = ChangeFormulaXRange(ser.formula, scroll_amount, scroll_amount, "adjust", firstIteration)
End If
'MsgBox (newFormula)
ser.formula = newFormula
firstIteration = False
Next ser
End Sub
Sub Zoom_In()
Zoom ("in")
End Sub
Sub Zoom_Out()
Zoom ("out")
End Sub
Sub Zoom(direction As String)
'reference the scroll amount
Dim zoom_amount As Integer
zoom_amount = CInt(Worksheets("analysis").Range("Zoom_Amount"))
'MsgBox ("zooming " & zoom_amount)
If ActiveChart Is Nothing Then
MsgBox ("No chart is selected")
Exit Sub
End If
'only adjust the x range once
Dim firstIteration As Boolean
firstIteration = True
'loop all series for the active chart
For Each ser In ActiveChart.SeriesCollection
' Perform desired processing on each item.
'The following code uses the split function because VBA does seem to have lookbehind/lookahead in
'its regex library
Dim newFormula As String
If (StrComp(direction, "in") = 0) Then
'zoom in
newFormula = ChangeFormulaXRange(ser.formula, zoom_amount, -1 * zoom_amount, "adjust", firstIteration)
Else
'zoom out
newFormula = ChangeFormulaXRange(ser.formula, -1 * zoom_amount, zoom_amount, "adjust", firstIteration)
End If
'assign adjusted formula to the series of this loop iteration
ser.formula = newFormula
firstIteration = False
Next ser
End Sub
Sub Go_To_X_Range()
'reference the scroll amount
Dim set_x_start As Integer
set_x_start = CInt(Worksheets("analysis").Range("Set_X_Start"))
Dim set_x_end As Integer
set_x_end = CInt(Worksheets("analysis").Range("Set_X_End"))
If ActiveChart Is Nothing Then
MsgBox ("No chart is selected")
Exit Sub
End If
Dim firstIteration As Boolean
firstIteration = True
'loop all series for the active chart
For Each ser In ActiveChart.SeriesCollection
' Perform desired processing on each item.
'The following code uses the split function because VBA does seem to have lookbehind/lookahead in
'its regex library
Dim newFormula As String
newFormula = ChangeFormulaXRange(ser.formula, set_x_start, set_x_end, "set", firstIteration)
'assign adjusted formula to the series of this loop iteration
ser.formula = newFormula
firstIteration = False
Next ser
End Sub
Sub Set_Series_Thickness()
'reference the thickness amount
Dim set_thickness As Double
set_thickness = CDbl(Worksheets("analysis").Range("Set_Thickness"))
If ActiveChart Is Nothing Then
MsgBox ("No chart is selected")
Exit Sub
End If
'loop all series for the active chart
For Each ser In ActiveChart.SeriesCollection
' Perform desired processing on each item.
ser.Format.Line.Weight = set_thickness
Next ser
End Sub
Function ChangeFormulaXRange(formula As String, dStart As Integer, dEnd As Integer, operation As String, adjustXValues As Boolean) As String
Dim majorParts() As String
Dim xValues() As String
Dim yValues() As String
Dim hasXValues As Boolean
'default false
'hasXValues = False
majorParts = Split(formula, ",")
'x values are only set on one series (if all series have same x range)
'this seems to have changed with MS Excel 2013
xValues = Split(majorParts(1), "$")
Dim xStart As Integer
Dim xEnd As Integer
xStart = CInt(Left(xValues(2), Len(xValues(2)) - 1))
xEnd = CInt(xValues(4))
'perform operation (only if this is the adjustXValues is true, i.e. first series in chart)
If (StrComp(operation, "adjust") = 0) Then
xStart = xStart + IIf(adjustXValues, dStart, 0)
xEnd = xEnd + IIf(adjustXValues, dEnd, 0)
ElseIf (StrComp(operation, "set") = 0) Then
xStart = IIf(adjustXValues, dStart, xStart)
xEnd = IIf(adjustXValues, dEnd, xEnd)
End If
'coerce xStart to be at least 2, so user doesn't zoom past the beginning and cause an error
If (xStart < 2) Then
xStart = 2
End If
'coerce xEnd isn't neccessary to avoid runtime errors but just needs to examine the sheet's value at that record
'TODO: implement xEnd coercion
yValues = Split(majorParts(2), "$")
Dim yStart As Integer
Dim yEnd As Integer
yStart = CInt(Left(yValues(2), Len(yValues(2)) - 1))
yEnd = CInt(yValues(4))
'perform operation
If (StrComp(operation, "adjust") = 0) Then
yStart = yStart + dStart
yEnd = yEnd + dEnd
ElseIf (StrComp(operation, "set") = 0) Then
yStart = dStart
yEnd = dEnd
End If
'coerce yStart to be at least 2, so user doesn't zoom past the beginning and cause an error
If (yStart < 2) Then
yStart = 2
End If
'check if start is greater than end, in case of user mistake (i.e zoom too much)
'just return the current formula
If (yStart > yEnd) Then
ChangeFormulaXRange = formula
Exit Function
End If
'coerce yEnd isn't neccessary to avoid runtime errors but just needs to examine the sheet's value at that record
'TODO: implement yEnd coercion
'put it all back together
ChangeFormulaXRange = _
majorParts(0) _
& "," & xValues(0) & "$" & xValues(1) & "$" & xStart & ":$" & xValues(3) & "$" & xEnd & "," _
& yValues(0) & "$" & yValues(1) & "$" & yStart & ":$" & yValues(3) & "$" & yEnd _
& "," & majorParts(3)
End Function