twb 4.4.1 → 4.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/twb.rb +1 -1
- data/lib/twb/analysis/CalculatedFields/CalculatedFieldsAnalyzer.rb +3 -2
- data/lib/twb/analysis/CalculatedFields/MarkdownEmitter.rb +23 -19
- data/lib/twb/analysis/DataSources/dataSourceOriginsAnalyzer.rb +3 -2
- data/lib/twb/analysis/DataSources/googlesheetdatasourcesanalyzer.rb +1 -0
- data/lib/twb/analysis/Sheets/dashsheetsanalyzer.rb +3 -2
- data/lib/twb/analysis/Sheets/sheetfieldsanalyzer.rb +99 -38
- data/lib/twb/analysis/Sheets/sheetfiltersanalyzer.rb +28 -10
- data/lib/twb/codedfield.rb +3 -3
- data/lib/twb/datasource.rb +37 -19
- data/lib/twb/quickfilter.rb +4 -0
- data/lib/twb/worksheet.rb +91 -137
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8330ec06a3076b01a2e2f6958b630ae2312c74d1fd0fdb6a575d2271ffdb745d
|
4
|
+
data.tar.gz: 7db555e49b52c9f0bc218aff47ab4a1af2b6a03064d5ce5f8fe04ee7323d3b4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 801ed0a3f287f170f1d6f477641fa9c8ee761eb879a317ec779be9a9c4886a1f4dd78145b26b9e7dec9534d353ad583a3e4ceaaf8d9cf3f0781be657c364c19c
|
7
|
+
data.tar.gz: 22e0fc10a913f1fe27a0aac56c2230d35d8483dfeeea7ee8a8d28d1d8b67c05073eb1f925b5abda8e3dd8de98d1c704b0b1b93f242b3ad73b1aafaaf7987a9b9
|
data/lib/twb.rb
CHANGED
@@ -82,10 +82,11 @@ module Analysis
|
|
82
82
|
DOTHEADER
|
83
83
|
|
84
84
|
def initialize(**args)
|
85
|
+
@args = args
|
85
86
|
@csvAdd = args[:csvMode] == :add
|
86
87
|
@csvMode = @csvAdd ? 'a' : 'w'
|
87
|
-
emit true, "@csvAdd : #{@csvAdd}"
|
88
|
-
emit true, "@csvMode: #{@csvMode}"
|
88
|
+
# emit true, "@csvAdd : #{@csvAdd}"
|
89
|
+
# emit true, "@csvMode: #{@csvMode}"
|
89
90
|
init
|
90
91
|
@funcdoc = {:class=>self.class, :blurb=>'Analyze Calculated Fields', :description=>'Calculated fields can be complex, this tool provides robust coverage.',}
|
91
92
|
#-- CSV records collectors
|
@@ -24,30 +24,14 @@ module CalculatedFields
|
|
24
24
|
|
25
25
|
attr_reader :docFileName
|
26
26
|
|
27
|
-
def initialize
|
27
|
+
def initialize(**args)
|
28
|
+
@args = args
|
28
29
|
init
|
30
|
+
puts "RECORD DOC: "
|
29
31
|
@funcdoc = {:class=>self.class, :blurb=>'Create Markdown files (one per Workbook) documenting Calculated Fields', :description=>'Create Markdown files (one per Workbook) documenting Calculated Fields' }
|
30
32
|
@metrics = {}
|
31
33
|
end
|
32
34
|
|
33
|
-
def kramdownAvailable
|
34
|
-
gem_name, *gem_ver_reqs = 'kramdown', '~> 1.17.0'
|
35
|
-
gdep = Gem::Dependency.new(gem_name, *gem_ver_reqs)
|
36
|
-
# find latest that satisifies
|
37
|
-
found_gspec = gdep.matching_specs.max_by(&:version)
|
38
|
-
# instead of using Gem::Dependency, you can also do:
|
39
|
-
# Gem::Specification.find_all_by_name(gem_name, *gem_ver_reqs)
|
40
|
-
# if found_gspec
|
41
|
-
# puts "Requirement '#{gdep}' already satisfied by #{found_gspec.name}-#{found_gspec.version}"
|
42
|
-
# else
|
43
|
-
# puts "Requirement '#{gdep}' not satisfied; could be installing..."
|
44
|
-
# # reqs_string will be in the format: "> 1.0, < 1.2"
|
45
|
-
# # reqs_string = gdep.requirements_list.join(', ')
|
46
|
-
# # multi-arg is safer, to avoid injection attacks
|
47
|
-
# # system('gem', 'install', gem_name, '-v', reqs_string)
|
48
|
-
# end
|
49
|
-
end
|
50
|
-
|
51
35
|
def processTWB twb
|
52
36
|
# twb = File.basename(twb)
|
53
37
|
@twb = twb #Twb::Workbook.new twb
|
@@ -103,6 +87,26 @@ module CalculatedFields
|
|
103
87
|
finis
|
104
88
|
end # def processTwb twb
|
105
89
|
|
90
|
+
private
|
91
|
+
|
92
|
+
def kramdownAvailable
|
93
|
+
gem_name, *gem_ver_reqs = 'kramdown', '~> 1.17.0'
|
94
|
+
gdep = Gem::Dependency.new(gem_name, *gem_ver_reqs)
|
95
|
+
# find latest that satisifies
|
96
|
+
found_gspec = gdep.matching_specs.max_by(&:version)
|
97
|
+
# instead of using Gem::Dependency, you can also do:
|
98
|
+
# Gem::Specification.find_all_by_name(gem_name, *gem_ver_reqs)
|
99
|
+
# if found_gspec
|
100
|
+
# puts "Requirement '#{gdep}' already satisfied by #{found_gspec.name}-#{found_gspec.version}"
|
101
|
+
# else
|
102
|
+
# puts "Requirement '#{gdep}' not satisfied; could be installing..."
|
103
|
+
# # reqs_string will be in the format: "> 1.0, < 1.2"
|
104
|
+
# # reqs_string = gdep.requirements_list.join(', ')
|
105
|
+
# # multi-arg is safer, to avoid injection attacks
|
106
|
+
# # system('gem', 'install', gem_name, '-v', reqs_string)
|
107
|
+
# end
|
108
|
+
end
|
109
|
+
|
106
110
|
end # class MarkdownEmitter
|
107
111
|
|
108
112
|
end # nodule CalculatedFields
|
@@ -28,11 +28,12 @@ module Analysis
|
|
28
28
|
attr_accessor :localEmit
|
29
29
|
|
30
30
|
def initialize(**args)
|
31
|
+
@args = args
|
31
32
|
#-- TODO move @csvAdd * #csvMode resolution to TabTool
|
32
33
|
@csvAdd = args[:csvMode] == :add
|
33
34
|
@csvMode = @csvAdd ? 'a' : 'w'
|
34
|
-
emit "@csvAdd : #{@csvAdd}"
|
35
|
-
emit "@csvMode: #{@csvMode}"
|
35
|
+
# emit "@csvAdd : #{@csvAdd}"
|
36
|
+
# emit "@csvMode: #{@csvMode}"
|
36
37
|
#--
|
37
38
|
init
|
38
39
|
@funcdoc = {:class=>self.class, :blurb=>'Analyze Data Source Origins, i.e. where the data comes from', :description=>nil,}
|
@@ -27,10 +27,11 @@ module Analysis
|
|
27
27
|
|
28
28
|
def initialize(**args)
|
29
29
|
#-- TODO move @csvAdd * #csvMode resolution to TabTool
|
30
|
+
@args = args
|
30
31
|
@csvAdd = args[:csvMode] == :add
|
31
32
|
@csvMode = @csvAdd ? 'a' : 'w'
|
32
|
-
emit "@csvAdd : #{@csvAdd}"
|
33
|
-
emit "@csvMode: #{@csvMode}"
|
33
|
+
# emit "@csvAdd : #{@csvAdd}"
|
34
|
+
# emit "@csvMode: #{@csvMode}"
|
34
35
|
#--
|
35
36
|
init
|
36
37
|
@funcdoc = {:class=>self.class, :blurb=>'Analyze Dashboard Worksheets', :description=>'Identifies the Worksheets present in Dashboards.',}
|
@@ -25,34 +25,42 @@ module Analysis
|
|
25
25
|
|
26
26
|
@@fieldTypeCodes = { 'DB ref' => 'Db',
|
27
27
|
'color' => 'Clr',
|
28
|
-
'filter' => '
|
29
|
-
'lod' => '
|
30
|
-
'page' => '
|
31
|
-
'path' => '
|
32
|
-
'shape' => '
|
33
|
-
'size' => '
|
34
|
-
'text' => '
|
35
|
-
'tooltip' => '
|
36
|
-
:column => '
|
37
|
-
:row => '
|
28
|
+
'filter' => 'Flt',
|
29
|
+
'lod' => 'LoD',
|
30
|
+
'page' => 'Pge',
|
31
|
+
'path' => 'Pth',
|
32
|
+
'shape' => 'Shp',
|
33
|
+
'size' => 'Siz',
|
34
|
+
'text' => 'Tex',
|
35
|
+
'tooltip' => 'TTp',
|
36
|
+
:column => 'Clm',
|
37
|
+
:row => 'Row',
|
38
|
+
'slice' => 'Slc',
|
38
39
|
}
|
39
40
|
|
40
41
|
|
41
42
|
attr_accessor :localEmit
|
42
43
|
|
43
44
|
def initialize(**args)
|
44
|
-
@
|
45
|
-
@
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
@args = args
|
46
|
+
@csvAdd = args[:csvMode] == :add
|
47
|
+
@recordDir = !@args.nil? && @args[:recordDir] == true
|
48
|
+
# puts " args: #{@args}"
|
49
|
+
# puts " @recordDir: #{@recordDir}"
|
50
|
+
# @csvMode = @csvAdd ? 'a' : 'w'
|
51
|
+
# emit true, "@csvAdd : #{@csvAdd}"
|
52
|
+
# emit true, "@csvMode: #{@csvMode}"
|
49
53
|
init
|
50
54
|
@funcdoc = {:class=>self.class, :blurb=>'Analyze Worksheet Fields', :description=>nil,}
|
51
55
|
#--
|
52
56
|
docFileName = docFile('WorksheetFields.csv')
|
53
57
|
@sheetFieldsCSV = CSV.open(docFileName,'w')
|
54
58
|
unless @csvAdd
|
55
|
-
@
|
59
|
+
if @recordDir
|
60
|
+
@sheetFieldsCSV << ['Rec #', 'Workbook','Worksheet','Data Source','Data Source (tech)','Field','Field (tech)','Usage','Usage - code','Workbook Dir']
|
61
|
+
else
|
62
|
+
@sheetFieldsCSV << ['Rec #', 'Workbook','Worksheet','Data Source','Data Source (tech)','Field','Field (tech)','Usage','Usage - code' ]
|
63
|
+
end
|
56
64
|
end
|
57
65
|
addDocFile @sheetFieldsCSV, docFileName, "Workbooks, Worksheets, and the Sheets' Data Sources and Fields"
|
58
66
|
#--
|
@@ -92,37 +100,65 @@ module Analysis
|
|
92
100
|
end
|
93
101
|
|
94
102
|
def showFields sheet
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
103
|
+
recordDBFields sheet
|
104
|
+
recordRCFields sheet.rowFields, :row
|
105
|
+
recordRCFields sheet.colFields, :column
|
106
|
+
recordEncodedFields sheet
|
107
|
+
recordFilterFields sheet
|
108
|
+
recordPageFields sheet
|
109
|
+
recordSlicesFields sheet
|
110
|
+
recordDSFilterFields sheet
|
101
111
|
end
|
102
112
|
|
103
|
-
def
|
113
|
+
def recordPageFields sheet
|
104
114
|
sheet.pageFields.each do |pfield|
|
105
115
|
ds = @twb.datasource pfield.dataSource
|
106
|
-
fuiname = ds.fieldUIName pfield.name
|
107
|
-
|
116
|
+
fuiname = ds.fieldUIName pfield.name
|
117
|
+
# if @recordDir
|
118
|
+
# @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, ds.name, fuiname, pfield.name, 'page', ftc('filter'), @twb.dir]
|
119
|
+
# else
|
120
|
+
# @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, ds.name, fuiname, pfield.name, 'page', ftc('filter') ]
|
121
|
+
# end
|
122
|
+
recordCSV [@twb.name, @sheet, ds.uiname, ds.name, fuiname, pfield.name, 'page', ftc('page')]
|
108
123
|
end
|
109
124
|
end
|
110
125
|
|
111
|
-
def
|
126
|
+
def recordFilterFields sheet
|
112
127
|
filters = sheet.filters
|
113
128
|
filters.each do |filter|
|
114
129
|
dsName = filter.dataSource.name
|
115
130
|
dsUIName = filter.dataSource.uiname
|
116
131
|
# puts "Filter field: #{filter.dataSource.name} ui:'#{}'"
|
117
|
-
|
132
|
+
# if @recordDir
|
133
|
+
# @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, dsUIName, dsName, filter.uiname, filter.name, 'filter', ftc('filter'), @twb.dir]
|
134
|
+
# else
|
135
|
+
# @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, dsUIName, dsName, filter.uiname, filter.name, 'filter', ftc('filter') ]
|
136
|
+
# end
|
137
|
+
recordCSV [@twb.name, @sheet, dsUIName, dsName, filter.uiname, filter.name, 'filter', ftc('filter')]
|
118
138
|
end
|
119
139
|
end
|
120
140
|
|
121
|
-
def
|
141
|
+
def recordDSFilterFields sheet
|
142
|
+
sheet.slicesFields.each do |field|
|
143
|
+
dsName = field.dataSource
|
144
|
+
ds = @twb.datasource dsName
|
145
|
+
dsUIName = ds.uiname
|
146
|
+
ds.filters.each do |filter|
|
147
|
+
recordCSV [@twb.name, @sheet, dsUIName, dsName, filter.uiname, filter.name, 'dsfilter', ftc('dsfilter')]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def recordDBFields sheet
|
122
153
|
fields = sheet.datasourceFields
|
123
|
-
emit "def
|
154
|
+
emit "def recordDBFields sheet: #{sheet.name} #FIELDS: #{fields.length}"
|
124
155
|
if fields.nil?
|
125
|
-
|
156
|
+
# if @recordDir
|
157
|
+
# @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, nil, nil, nil, nil, nil, @twb.dir]
|
158
|
+
# else
|
159
|
+
# @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, nil, nil, nil, nil, nil]
|
160
|
+
# end
|
161
|
+
recordCSV [@twb.name, @sheet, nil, nil, nil, nil, nil]
|
126
162
|
end
|
127
163
|
fields.each do |dsName, dsfields|
|
128
164
|
ds = @twb.datasource dsName
|
@@ -134,16 +170,18 @@ module Analysis
|
|
134
170
|
emit " f: #{sheetField}"
|
135
171
|
emit " c: #{sheetField.class}"
|
136
172
|
fuiName = ds.fieldUIName sheetField #Fields[sheetField]
|
137
|
-
@sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, dsName, sheetField.uiname, sheetField.name, 'DB ref', ftc('DB ref')]
|
173
|
+
# @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, dsName, sheetField.uiname, sheetField.name, 'DB ref', ftc('DB ref')]
|
174
|
+
recordCSV [@twb.name, @sheet, ds.uiname, dsName, sheetField.uiname, sheetField.name, 'DB ref', ftc('DB ref')]
|
138
175
|
# emit true, " : #{dsFields[field].class}"
|
139
176
|
end
|
140
177
|
end
|
141
178
|
end
|
142
179
|
|
143
|
-
def
|
144
|
-
emit "def
|
180
|
+
def recordRCFields fields, usage
|
181
|
+
emit "def recordRCFields #fields: #{fields.length} \t #{fields}"
|
145
182
|
if fields.nil?
|
146
|
-
@sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, nil, nil, nil, nil, nil]
|
183
|
+
# @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, nil, nil, nil, nil, nil]
|
184
|
+
recordCSV [@twb.name, @sheet, nil, nil, nil, nil, nil]
|
147
185
|
else
|
148
186
|
fields.each do |cf|
|
149
187
|
emit "coded field: #{cf}"
|
@@ -155,23 +193,46 @@ module Analysis
|
|
155
193
|
emit " ds: #{dsName}"
|
156
194
|
emit " - #{ds.uiname}"
|
157
195
|
emit " : #{ds.class}"
|
158
|
-
@sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, dsName, fuiName, fldName, usage, ftc(usage)]
|
196
|
+
# @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, dsName, fuiName, fldName, usage, ftc(usage)]
|
197
|
+
recordCSV [@twb.name, @sheet, ds.uiname, dsName, fuiName, fldName, usage, ftc(usage)]
|
159
198
|
end
|
160
199
|
end
|
161
200
|
end
|
162
201
|
|
163
|
-
def
|
202
|
+
def recordEncodedFields sheet
|
164
203
|
unless sheet.encodedFields.nil?
|
165
204
|
sheet.encodedFields.each do |type,fields|
|
166
205
|
fields.each do |field|
|
167
206
|
dsName = field.dataSource
|
168
207
|
ds = @twb.datasource dsName
|
169
208
|
fuiName = ds.fieldUIName field.name
|
170
|
-
@sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, dsName, fuiName, field.name, type, ftc(type)]
|
209
|
+
# @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, dsName, fuiName, field.name, type, ftc(type)]
|
210
|
+
recordCSV [@twb.name, @sheet, ds.uiname, dsName, fuiName, field.name, type, ftc(type)]
|
171
211
|
end
|
172
212
|
end
|
173
213
|
end
|
174
|
-
end #def
|
214
|
+
end #def recordEncodedFields
|
215
|
+
|
216
|
+
def recordSlicesFields sheet
|
217
|
+
# puts "recordSlicesFields"
|
218
|
+
unless sheet.slicesFields.nil?
|
219
|
+
sheet.slicesFields.each do |field|
|
220
|
+
dsName = field.dataSource
|
221
|
+
ds = @twb.datasource dsName
|
222
|
+
fuiName = ds.fieldUIName field.name
|
223
|
+
recordCSV [@twb.name, @sheet, ds.uiname, dsName, fuiName, field.name, 'slice', ftc('slice')]
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def recordCSV record
|
229
|
+
numberedRec = [@recNum+=1] + record
|
230
|
+
if @recordDir
|
231
|
+
@sheetFieldsCSV << numberedRec.push(@twb.dir)
|
232
|
+
else
|
233
|
+
@sheetFieldsCSV << numberedRec
|
234
|
+
end
|
235
|
+
end
|
175
236
|
|
176
237
|
def ftc type # ftc : abbr for fieldTypeCode, for brevity
|
177
238
|
@@fieldTypeCodes[type].nil? ? type : @@fieldTypeCodes[type]
|
@@ -26,22 +26,29 @@ module Analysis
|
|
26
26
|
attr_accessor :localEmit
|
27
27
|
|
28
28
|
def initialize(**args)
|
29
|
-
@
|
30
|
-
@
|
31
|
-
|
32
|
-
|
29
|
+
@args = args
|
30
|
+
@recordDir = !@args.nil? && @args[:recordDir] == true
|
31
|
+
@csvAdd = args[:csvMode] == :add
|
32
|
+
# @csvMode = @csvAdd ? 'a' : 'w'
|
33
|
+
# emit "@csvAdd : #{@csvAdd}"
|
34
|
+
# emit "@csvMode: #{@csvMode}"
|
33
35
|
init
|
34
36
|
@funcdoc = {:class=>self.class, :blurb=>'Analyze Worksheet Filters', :description=>'Documents Quick Filters and the values they employ, if any. Work in progess.',}
|
35
37
|
#--
|
36
38
|
docFileName = docFile('WorksheetFilters.csv')
|
37
|
-
|
39
|
+
@sheetFieldsCSV = CSV.open( docFileName ,'w')
|
38
40
|
unless @csvAdd
|
39
|
-
|
41
|
+
if @recordDir
|
42
|
+
@sheetFieldsCSV << ['Rec #','Workbook','Worksheet','Filter Type','Operation','Data Source','Field','Value','Alias', 'Alias?','Operation Mode','Include Null?','Kind','Workbook Dir']
|
43
|
+
else
|
44
|
+
@sheetFieldsCSV << ['Rec #','Workbook','Worksheet','Filter Type','Operation','Data Source','Field','Value','Alias', 'Alias?','Operation Mode','Include Null?','Kind']
|
45
|
+
end
|
40
46
|
end
|
41
|
-
addDocFile
|
47
|
+
addDocFile @sheetFieldsCSV, docFileName, "Workbooks, Worksheets and the sheets' Quick Filters"
|
42
48
|
#--
|
43
49
|
@sheetCount = 0
|
44
50
|
@filterCount = 0
|
51
|
+
@recNum = 0
|
45
52
|
end
|
46
53
|
|
47
54
|
def metrics
|
@@ -68,20 +75,31 @@ module Analysis
|
|
68
75
|
filters.each do |filter|
|
69
76
|
filter.emit "-----------------------------\nWORKSHEET:: #{sheet.name}\n-----------------------------"
|
70
77
|
if filter.values.empty?
|
71
|
-
#
|
72
|
-
|
78
|
+
# @sheetFieldsCSV << ['Workbook','Worksheet','Filter Type','Operation' ,'Data Source','Field','Value','Alias', 'Alias?']
|
79
|
+
recordCSV [@twbName, sheet.name, filter.type, filter.inexclude, filter.dataSource.uiname, filter.uiname, nil, nil, nil, filter.inexMode, filter.includeNull, filter.kind]
|
73
80
|
end
|
74
81
|
filter.values.each do |valueMap|
|
75
82
|
value = valueMap[:value]
|
76
83
|
valias = valueMap[:alias]
|
77
84
|
same = value.eql? valias
|
78
85
|
emit "RECORDING FILTER VALUES: %-35s -- %-25s same? %s " % [value,valias,same]
|
79
|
-
|
86
|
+
recordCSV [@twbName, sheet.name, filter.type, filter.inexclude, filter.dataSource.uiname, filter.uiname, value, valias, same, filter.inexMode, filter.includeNull, filter.kind]
|
80
87
|
end
|
81
88
|
end
|
82
89
|
end
|
83
90
|
end
|
84
91
|
|
92
|
+
private
|
93
|
+
|
94
|
+
def recordCSV record
|
95
|
+
numberedRec = [@recNum+=1] + record
|
96
|
+
if @recordDir
|
97
|
+
@sheetFieldsCSV << numberedRec.push(@twbDir)
|
98
|
+
else
|
99
|
+
@sheetFieldsCSV << numberedRec
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
85
103
|
end # class SheetFiltersAnalyzerA
|
86
104
|
|
87
105
|
end # module Twb
|
data/lib/twb/codedfield.rb
CHANGED
@@ -27,10 +27,10 @@ module Twb
|
|
27
27
|
attr_reader :name, :techCode, :function, :rawCode
|
28
28
|
|
29
29
|
def initialize code
|
30
|
-
|
30
|
+
# puts "...CodedField :: #{code}"
|
31
31
|
@rawCode = code
|
32
|
-
trimmed = code.gsub(/^['"]|['"]$/,'').gsub(/^\[|\]$/,'')
|
33
|
-
# puts "trimmed
|
32
|
+
trimmed = code.gsub(/^['"]|['"]$/,'').gsub(/^\[|\]$/,'').gsub(/:[0-9]+$/,'')
|
33
|
+
# puts " trimmed :: #{trimmed}"
|
34
34
|
parts = trimmed.split('].[')
|
35
35
|
#puts "Field: #{code} parts: #{parts.length} - #{parts.inspect}"
|
36
36
|
#puts " p1: #{parts[0]}"
|
data/lib/twb/datasource.rb
CHANGED
@@ -70,7 +70,7 @@ module Twb
|
|
70
70
|
@uiname = @caption.nil? ? @name : @caption
|
71
71
|
# puts "DATASOURCE: #{@uiname}"
|
72
72
|
processConnection
|
73
|
-
processFilters
|
73
|
+
# processFilters
|
74
74
|
loadTableFields
|
75
75
|
loadFieldUINames
|
76
76
|
return self
|
@@ -503,10 +503,16 @@ module Twb
|
|
503
503
|
end
|
504
504
|
end
|
505
505
|
|
506
|
+
def filters
|
507
|
+
@filters ||= loadFilters
|
508
|
+
end
|
509
|
+
|
506
510
|
def groups
|
507
511
|
@groups ||= loadGroups
|
508
512
|
end
|
509
513
|
|
514
|
+
private
|
515
|
+
|
510
516
|
def loadGroups
|
511
517
|
@groups = []
|
512
518
|
groupNodes = @node.xpath('.//group')
|
@@ -517,25 +523,37 @@ module Twb
|
|
517
523
|
return @groups
|
518
524
|
end
|
519
525
|
|
520
|
-
def processFilters
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
memberNodes = fn.xpath('.//groupfilter/@member')
|
528
|
-
unless memberNodes.nil?
|
529
|
-
members = []
|
530
|
-
memberNodes.each do |m|
|
531
|
-
members.push m.text
|
532
|
-
end
|
533
|
-
@filters[columnN.text] = members
|
534
|
-
end
|
535
|
-
end
|
536
|
-
end
|
526
|
+
# def processFilters
|
527
|
+
def loadFilters
|
528
|
+
@filters = []
|
529
|
+
sharedFilters = @workbook.node.xpath('./shared-views/shared-view[@name="excel.41269.481293159719"]//filter')
|
530
|
+
sharedFilters.each do |sf|
|
531
|
+
filter = QuickFilter.new(sf,@workbook)
|
532
|
+
@filters << filter
|
537
533
|
end
|
538
|
-
|
534
|
+
return @filters
|
535
|
+
end
|
536
|
+
|
537
|
+
# @filters <<
|
538
|
+
# if @filters.nil?
|
539
|
+
# @filters = {}
|
540
|
+
# fnodes = @node.xpath('./filter')
|
541
|
+
# fnodes.each do |fn|
|
542
|
+
# columnN = fn.attribute('column')
|
543
|
+
# unless columnN.nil?
|
544
|
+
# memberNodes = fn.xpath('.//groupfilter/@member')
|
545
|
+
# unless memberNodes.nil?
|
546
|
+
# members = []
|
547
|
+
# memberNodes.each do |m|
|
548
|
+
# members.push m.text
|
549
|
+
# end
|
550
|
+
# @filters[columnN.text] = members
|
551
|
+
# end
|
552
|
+
# end
|
553
|
+
# end
|
554
|
+
# end
|
555
|
+
# end
|
556
|
+
|
539
557
|
|
540
558
|
end # class DataSource
|
541
559
|
|
data/lib/twb/quickfilter.rb
CHANGED
data/lib/twb/worksheet.rb
CHANGED
@@ -28,7 +28,7 @@ module Twb
|
|
28
28
|
|
29
29
|
attr_reader :node, :name, :datasourcenames, :datasources
|
30
30
|
attr_reader :panesCount
|
31
|
-
attr_reader :fields, :rowFields, :colFields, :paneFields, :datasourceFields, :pageFields, :encodedFields
|
31
|
+
attr_reader :fields, :rowFields, :colFields, :paneFields, :datasourceFields, :pageFields, :encodedFields, :slicesFields
|
32
32
|
attr_reader :filters
|
33
33
|
attr_reader :tooltip
|
34
34
|
attr_accessor :hidden, :visible
|
@@ -38,8 +38,7 @@ module Twb
|
|
38
38
|
@node = sheetNode
|
39
39
|
@name = @node['name']
|
40
40
|
emit "########################## Worksheet initialize name: #{@name}"
|
41
|
-
|
42
|
-
loadDataSourceNames
|
41
|
+
loadDataSources
|
43
42
|
loadFields
|
44
43
|
return self
|
45
44
|
end
|
@@ -48,15 +47,6 @@ module Twb
|
|
48
47
|
@id ||= @name.hash
|
49
48
|
end
|
50
49
|
|
51
|
-
def loadDataSourceNames
|
52
|
-
@datasources = {}
|
53
|
-
dsNodes = @node.xpath('.//datasource')
|
54
|
-
dsNodes.each do |dsn|
|
55
|
-
ds = WorksheetDataSource.new dsn
|
56
|
-
@datasources[ds.name] = ds
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
50
|
def workbook
|
61
51
|
@workbook ||= @node.at_xpath('/').root
|
62
52
|
end
|
@@ -78,6 +68,10 @@ module Twb
|
|
78
68
|
# @fields.nil? ? loadFields : @fields
|
79
69
|
end
|
80
70
|
|
71
|
+
def slicesFields
|
72
|
+
@slicesFields ||= loadSlicesFields
|
73
|
+
end
|
74
|
+
|
81
75
|
def filters
|
82
76
|
@filters ||= loadFilters
|
83
77
|
end
|
@@ -94,6 +88,36 @@ module Twb
|
|
94
88
|
@visible ||= !hidden
|
95
89
|
end
|
96
90
|
|
91
|
+
def addDSFields fields, usage
|
92
|
+
fields.each do
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def panesCount
|
97
|
+
@panesCount ||= @node.xpath('.//panes/pane').length
|
98
|
+
end
|
99
|
+
|
100
|
+
def paneFields
|
101
|
+
@paneFields ||= loadPaneFields
|
102
|
+
end
|
103
|
+
|
104
|
+
def pageFields
|
105
|
+
@pageFields ||= loadpageFields
|
106
|
+
end
|
107
|
+
|
108
|
+
def datasourcenames
|
109
|
+
@datasources.keys
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# def resolveHidden
|
115
|
+
# xpath = "//windows/window[@name=\"#{@name}\"]"
|
116
|
+
# emit true, "resolveHidden: #{xpath}"
|
117
|
+
# windowNode = @node.at_xpath(xpath)
|
118
|
+
# @hidden = !windowNode.nil? && 'true' == windowNode['hidden']
|
119
|
+
# end
|
120
|
+
|
97
121
|
def loadFields
|
98
122
|
# puts "WORKSHEET loadFields"
|
99
123
|
@fields = {}
|
@@ -117,43 +141,29 @@ module Twb
|
|
117
141
|
loadFieldEncodings
|
118
142
|
end
|
119
143
|
|
120
|
-
def
|
121
|
-
@
|
122
|
-
|
123
|
-
enodes.each do |enode|
|
124
|
-
enode.children.each do |child|
|
125
|
-
unless child['column'].nil?
|
126
|
-
@encodedFields[child.name] << CodedField.new(child['column'])
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
@encodedFields.each do |type, fields|
|
131
|
-
@fields[type] = fields
|
132
|
-
end
|
144
|
+
def loadPaneFields
|
145
|
+
@paneFields = Set.new
|
146
|
+
panes = @node.xpath('.//pane')
|
133
147
|
end
|
134
148
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
# end
|
143
|
-
# end
|
144
|
-
# end
|
145
|
-
# $encodedFields.each do |type, fields|
|
146
|
-
# $fields[type] = fields
|
147
|
-
# end
|
148
|
-
# end
|
149
|
-
|
150
|
-
def addDSFields fields, usage
|
151
|
-
fields.each do
|
149
|
+
def loadFilters
|
150
|
+
emit ""########################## loadFilters"
|
151
|
+
@filters = []
|
152
|
+
filterNodes = @node.xpath('./table/view//filter[@column]')
|
153
|
+
filterNodes.each do |fnode|
|
154
|
+
filter = QuickFilter.new(fnode,@twb)
|
155
|
+
@filters << filter
|
152
156
|
end
|
157
|
+
return @filters
|
153
158
|
end
|
154
159
|
|
155
|
-
def
|
156
|
-
@
|
160
|
+
def loadDataSources
|
161
|
+
@datasources = {}
|
162
|
+
dsNodes = @node.xpath('.//datasource')
|
163
|
+
dsNodes.each do |dsn|
|
164
|
+
ds = WorksheetDataSource.new dsn
|
165
|
+
@datasources[ds.name] = ds
|
166
|
+
end
|
157
167
|
end
|
158
168
|
|
159
169
|
def loadRowColFields(type)
|
@@ -174,17 +184,8 @@ module Twb
|
|
174
184
|
return fields
|
175
185
|
end
|
176
186
|
|
177
|
-
def
|
178
|
-
@
|
179
|
-
end
|
180
|
-
|
181
|
-
def loadPaneFields
|
182
|
-
@paneFields = Set.new
|
183
|
-
panes = @node.xpath('.//pane')
|
184
|
-
end
|
185
|
-
|
186
|
-
def pageFields
|
187
|
-
@pageFields ||= loadpageFields
|
187
|
+
def loadTooltip
|
188
|
+
@tooltip = @node.xpath('./table/panes/pane/customized-tooltip')
|
188
189
|
end
|
189
190
|
|
190
191
|
def loadpageFields
|
@@ -196,33 +197,47 @@ module Twb
|
|
196
197
|
return @pageFields
|
197
198
|
end
|
198
199
|
|
199
|
-
def
|
200
|
-
@
|
200
|
+
def loadSlicesFields
|
201
|
+
@slicesFields = []
|
202
|
+
nodes = @node.xpath('./table/view/slices//column')
|
203
|
+
nodes.each do |node|
|
204
|
+
# puts "Slice field: #{node.text}"
|
205
|
+
@slicesFields << CodedField.new(node.text)
|
206
|
+
end
|
207
|
+
return @slicesFields
|
201
208
|
end
|
202
209
|
|
203
|
-
|
210
|
+
def loadFieldEncodings
|
211
|
+
@encodedFields = Hash.new { |h,k| h[k] = [] }
|
212
|
+
enodes = @node.xpath('.//table/panes/pane/encodings')
|
213
|
+
enodes.each do |enode|
|
214
|
+
enode.children.each do |child|
|
215
|
+
unless child['column'].nil?
|
216
|
+
@encodedFields[child.name] << CodedField.new(child['column'])
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
@encodedFields.each do |type, fields|
|
221
|
+
@fields[type] = fields
|
222
|
+
end
|
223
|
+
end
|
204
224
|
|
205
|
-
# def
|
206
|
-
#
|
207
|
-
#
|
208
|
-
#
|
209
|
-
#
|
225
|
+
# def loadFieldEncodings node
|
226
|
+
# $encodedFields = Hash.new { |h,k| h[k] = [] }
|
227
|
+
# enodes = node.xpath('.//table/panes/pane/encodings')
|
228
|
+
# enodes.each do |enode|
|
229
|
+
# enode.children.each do |child|
|
230
|
+
# unless child['column'].nil?
|
231
|
+
# $encodedFields[child.name] << CodedField.new(child['column'])
|
232
|
+
# end
|
233
|
+
# end
|
234
|
+
# end
|
235
|
+
# $encodedFields.each do |type, fields|
|
236
|
+
# $fields[type] = fields
|
237
|
+
# end
|
210
238
|
# end
|
211
239
|
|
212
|
-
def loadFilters
|
213
|
-
emit ""########################## loadFilters"
|
214
|
-
@filters = []
|
215
|
-
filterNodes = @node.xpath('./table/view//filter[@column]')
|
216
|
-
filterNodes.each do |fnode|
|
217
|
-
filter = QuickFilter.new(fnode,@twb)
|
218
|
-
@filters << filter
|
219
|
-
end
|
220
|
-
return @filters
|
221
|
-
end
|
222
240
|
|
223
|
-
def loadTooltip
|
224
|
-
@tooltip = @node.xpath('./table/panes/pane/customized-tooltip')
|
225
|
-
end
|
226
241
|
|
227
242
|
end # class Worksheet
|
228
243
|
|
@@ -273,65 +288,4 @@ module Twb
|
|
273
288
|
end # class RowsColsSplitter
|
274
289
|
|
275
290
|
|
276
|
-
|
277
|
-
class CodedField
|
278
|
-
|
279
|
-
include Comparable
|
280
|
-
|
281
|
-
attr_reader :code, :dataSource, :prefix, :name, :suffix
|
282
|
-
|
283
|
-
def initialize incode
|
284
|
-
# puts "CF: #{incode}"
|
285
|
-
@code = incode
|
286
|
-
trimCode = code.gsub(/^\[/,'').gsub(/\]$/,'')
|
287
|
-
# puts " : '#{trimCode}'"
|
288
|
-
@dataSource = nil
|
289
|
-
dsFldBits = trimCode.split('].[')
|
290
|
-
if dsFldBits.length == 2
|
291
|
-
@dataSource = dsFldBits[0]
|
292
|
-
fieldCode = dsFldBits[1]
|
293
|
-
else
|
294
|
-
fieldCode = dsFldBits[0]
|
295
|
-
end
|
296
|
-
# puts "fc: #{fieldCode}"
|
297
|
-
parts = fieldCode.split(':')
|
298
|
-
bits =
|
299
|
-
if ':Measure Names'.eql?(fieldCode)
|
300
|
-
{:prefix => nil, :name => fieldCode, :suffix => nil }
|
301
|
-
else
|
302
|
-
case parts.length
|
303
|
-
when 1
|
304
|
-
bits = {:prefix => nil, :name => parts[0], :suffix => nil}
|
305
|
-
when 3
|
306
|
-
bits = {:prefix => parts[0], :name => parts[1], :suffix => parts[2]}
|
307
|
-
when 4
|
308
|
-
if parts[-1].match(/^(\d)+$/)
|
309
|
-
bits = {:prefix => parts[0], :name => parts[1], :suffix => "#{parts[2]}:#{parts[3]}"}
|
310
|
-
else
|
311
|
-
bits = {:prefix => "#{parts[0]}:#{parts[1]}", :name => parts[2], :suffix => parts[3]}
|
312
|
-
end
|
313
|
-
when 5
|
314
|
-
bits = {:prefix => "#{parts[0]}:#{parts[1]}", :name => parts[2], :suffix => "#{parts[3]}:#{parts[4]}"}
|
315
|
-
else
|
316
|
-
bits = {:prefix => "OOPS #{parts.inspect}", :name => '', :suffix => '' }
|
317
|
-
end
|
318
|
-
end
|
319
|
-
@prefix = bits[:prefix]
|
320
|
-
@name = bits[:name]
|
321
|
-
@suffix = bits[:suffix]
|
322
|
-
# puts " l: #{parts.length} == #{bits}"
|
323
|
-
# bits.each { |k,v| puts " l: %-7s %s" % [k,v] }
|
324
|
-
end
|
325
|
-
# --
|
326
|
-
def to_s
|
327
|
-
@code
|
328
|
-
end
|
329
|
-
|
330
|
-
def <=>(other)
|
331
|
-
@code <=> other.code
|
332
|
-
end
|
333
|
-
|
334
|
-
end #class CodedField
|
335
|
-
|
336
|
-
|
337
291
|
end # module Twb
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.4.
|
4
|
+
version: 4.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Gerrard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-02-
|
11
|
+
date: 2019-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: creek
|