-
Notifications
You must be signed in to change notification settings - Fork 0
/
incell.bas
197 lines (138 loc) · 5.87 KB
/
incell.bas
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
Attribute VB_Name = "Module1"
Option Explicit
Function incell(analyzed_cell As Range)
Dim Regex As Object, eachcell, rangeobj As Object
Dim indcol As New Collection
Dim operators As Object, operator
Dim i As Integer, j As Integer
Dim maindict As Object, arraydict As Object
Dim midstr As String, refmidstr As String, midtxt As String
Dim pivMatches As Object, pivMatch As Object
Dim nextoperator As Integer, leftstr As String
Set maindict = CreateObject("Scripting.Dictionary")
Set arraydict = CreateObject("Scripting.Dictionary")
Set Regex = CreateObject("VBScript.RegExp")
Regex.pattern = "[\+\-=/\*\(\),<>&]"
Regex.Global = True
Set operators = Regex.Execute(analyzed_cell.Formula)
For Each operator In operators
indcol.Add operator.firstindex
Next
If indcol.count = 0 Then indcol.Add 0 'in case there is nothing except the first "=", assume it to be 0
If indcol(indcol.count) < Len(analyzed_cell.Formula) Then indcol.Add Len(analyzed_cell.Formula)
For i = 1 To indcol.count - 1
midstr = Mid(analyzed_cell.Formula, indcol(i) + 1, indcol(i + 1) - indcol(i))
refmidstr = Mid(midstr, 2, Len(midstr) - 1)
midtxt = ""
If InStr(1, refmidstr, "GETPIVOTDATA") Then
Regex.pattern = "[\+\-=/\*<>]"
Regex.Global = False
leftstr = Mid(analyzed_cell.Formula, indcol(i) + 2, Len(analyzed_cell.Formula))
If Regex.test(leftstr) Then
Set pivMatches = Regex.Execute(leftstr)
For Each pivMatch In pivMatches
nextoperator = pivMatch.firstindex
Next
Else
nextoperator = Len(analyzed_cell.Formula)
End If
leftstr = Mid(analyzed_cell.Formula, indcol(i) + 2, nextoperator)
midtxt = getpivotdataval(leftstr)
'now we need to skip all the mathches inside GETPIVOTDATA function
Regex.pattern = "[\+\-=/\*\(\),<>&]"
Regex.Global = True
Set pivMatches = Regex.Execute(leftstr)
j = 0
For Each pivMatch In pivMatches
j = j + 1
Next
i = i + j 'move i forward by num of mathches inside GETPIVOTDATA
Set pivMatches = Nothing
GoTo nexti
End If
If InStr(1, refmidstr, "[@") > 0 Then 'if reference is part of list
If analyzed_cell.ListObject Is Nothing Then 'if analyzed cell is not in listobject
midtxt = Replace(refmidstr, "@", "[#Headers],") 'get address of the table header above the referenced cell
Else
midtxt = Replace(refmidstr, "[@", analyzed_cell.ListObject.Name & "[[#Headers],") 'get address of the table header above the referenced cell
End If
refmidstr = Range(midtxt).Offset(analyzed_cell.Row() - Range(midtxt).Row(), 0).Address 'get the address relative to the analyzed cell
midtxt = ""
End If
If InStr(1, refmidstr, "[#Totals]") > 0 Then 'if reference is part of totals of the list
j = InStr(indcol(i) + 1, analyzed_cell.Formula, "]]")
midstr = Mid(analyzed_cell.Formula, indcol(i) + 1, j - indcol(i) + 1)
refmidstr = Trim(Mid(midstr, 2, Len(midstr) - 1))
refmidstr = Range(refmidstr).Address
i = i + 1 'move i forward to skip next [
End If
On Error Resume Next
Set rangeobj = Range(refmidstr)
If rangeobj Is Nothing Then
midtxt = refmidstr
Else
If IsArray(rangeobj.Value) Then
j = 1
For Each eachcell In rangeobj
Select Case eachcell.NumberFormat
Case "General"
arraydict.Add j, eachcell.Value
Case Else
arraydict.Add j, format(eachcell.Value, eachcell.NumberFormat)
End Select
j = j + 1
Next
midtxt = Join(arraydict.items, ",")
arraydict.RemoveAll
Else
Select Case rangeobj.NumberFormat
Case "General"
midtxt = rangeobj.Value
Case Else
midtxt = format(rangeobj.Value, rangeobj.NumberFormat)
End Select
End If
End If
nexti:
maindict.Add i, left(midstr, 1) & midtxt
Set rangeobj = Nothing 'required to clear existing, otherwise will not return to nothing in the set above
Err.Clear
Next i
incell = Join(maindict.items, "")
Set rangeobj = Nothing
Set maindict = Nothing
Set arraydict = Nothing
Set Regex = Nothing
End Function
Function getpivotdataval(inistring)
Dim resstring As String
Dim Regex As Object
Dim MatchRes As Object
Dim eachMatch As Object
Set Regex = CreateObject("VBScript.RegExp")
With Regex
.pattern = "(\(.*\)$)"
.Global = True
.IgnoreCase = True
End With
Set MatchRes = Regex.Execute(inistring)
resstring = ""
For Each eachMatch In MatchRes
resstring = eachMatch.Value
Next
With Regex
.pattern = "[\(\)]"
.Global = True
.IgnoreCase = True
End With
Set MathesBrackets = Regex.Execute(inistring)
If MathesBrackets.count Mod 2 <> 0 Then 'if num of closing brackets <> opening brackets than there is extra closing bracket that should be removed
resstring = Mid(resstring, 1, Len(resstring) - 1)
getpivotdataval = Evaluate("=GetPivotData" & resstring) & ")"
Else
getpivotdataval = Evaluate("=GetPivotData" & resstring)
End If
Set MatchRes = Nothing
Set Regex = Nothing
Set MathesBrackets = Nothing
End Function