twb 5.1.4 → 5.2.5
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 +2 -1
- data/lib/twb/analysis/calculatedfields/calculatedfieldsanalyzer.rb +92 -128
- data/lib/twb/analysis/calculatedfields/dotanalyzer.rb +144 -0
- data/lib/twb/analysis/calculatedfields/markdownemitter.rb +2 -2
- data/lib/twb/columnfield.rb +9 -1
- data/lib/twb/fieldcalculation.rb +13 -9
- data/lib/twb/quickfilter.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 237d9d602af5e7c253e3c0df732483ecacb58d7453f88ae2037251be7ae56b52
|
4
|
+
data.tar.gz: 84da2fc81295bf1a61e6699907cf78e404b7b2f8fa6c3ce5149388608547d818
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f940edb531e4a001aa55ffeec2de8df038f7c14a34eca5eb23780cc12da1c4c7876fe61d3e4edb0c2640ee9e653dcd67073040689b39edcd424184182c6f9334
|
7
|
+
data.tar.gz: e76e453f09bf238643a8b1f12cb93390d0068450e520b7cdd3711d2cf9b9aaa217771081280d0b7ad8ad2499fdf8aa46fabfaf6059360ef1b67fd63a5e86347d
|
data/lib/twb.rb
CHANGED
@@ -54,6 +54,7 @@ require_relative 'twb/analysis/documentedfieldsmarkdownemitter'
|
|
54
54
|
require_relative 'twb/analysis/annotatedfieldscsvemitter'
|
55
55
|
require_relative 'twb/analysis/workbooksummaryanalyzer'
|
56
56
|
require_relative 'twb/analysis/calculatedfields/calculatedfieldsanalyzer'
|
57
|
+
require_relative 'twb/analysis/calculatedfields/dotanalyzer'
|
57
58
|
require_relative 'twb/analysis/calculatedfields/groupfieldsanalyzer'
|
58
59
|
require_relative 'twb/analysis/calculatedfields/markdownemitter'
|
59
60
|
require_relative 'twb/analysis/calculatedfields/csvemitter'
|
@@ -80,5 +81,5 @@ require_relative 'twb/analysis/sheets/sheetsintooltipanalyzer'
|
|
80
81
|
# Represents Tableau Workbooks, their contents, and classes that analyze and manipulate them.
|
81
82
|
#
|
82
83
|
module Twb
|
83
|
-
VERSION = '5.
|
84
|
+
VERSION = '5.2.5'
|
84
85
|
end
|
@@ -78,12 +78,12 @@ module Analysis
|
|
78
78
|
@fieldTables = {}
|
79
79
|
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
81
|
+
# @@dotHeader = <<DOTHEADER
|
82
|
+
# digraph g {
|
83
|
+
# graph [rankdir="LR" splines=line];
|
84
|
+
# node [shape="box" width="2"];
|
85
85
|
|
86
|
-
DOTHEADER
|
86
|
+
# DOTHEADER
|
87
87
|
|
88
88
|
def initialize(**args)
|
89
89
|
emit "initialize CalculatedFieldsAnalyzer args #{args}"
|
@@ -141,7 +141,7 @@ DOTHEADER
|
|
141
141
|
# end
|
142
142
|
processDataSource ds
|
143
143
|
end
|
144
|
-
mapTwb
|
144
|
+
# mapTwb
|
145
145
|
emitGml
|
146
146
|
@twbCount += 1
|
147
147
|
finis
|
@@ -195,10 +195,10 @@ DOTHEADER
|
|
195
195
|
calculatedFields.add calcField.id
|
196
196
|
dsFields[calcField.uiname] = calcField
|
197
197
|
# if @doGraph
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
198
|
+
calcFieldNode = Twb::Util::Graphnode.new(name: calcField.uiname, id: calcField.id, type: calcField, properties: {:DataSource => ds.uiname})
|
199
|
+
@nodes.add calcFieldNode
|
200
|
+
dsFieldEdge = Twb::Util::Graphedge.new(from: dataSourceNode, to: calcFieldNode, relationship: 'contains')
|
201
|
+
@edges.add dsFieldEdge
|
202
202
|
# end
|
203
203
|
calculation = calcField.calculation
|
204
204
|
if calculation.has_formula
|
@@ -265,46 +265,10 @@ DOTHEADER
|
|
265
265
|
'', # rf.id,
|
266
266
|
'', #refFieldTable
|
267
267
|
]
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
# if @doGraph
|
273
|
-
# unless rf.uiname.nil?
|
274
|
-
# properties = {'DataSource' => ds.uiname, 'DataSourceReference' => 'local', :source => rf}
|
275
|
-
# refFieldNode = Twb::Util::Graphnode.new(name: rf.uiname, id: rf.id, type: rf.type, properties: properties)
|
276
|
-
# @nodes.add refFieldNode
|
277
|
-
# fieldFieldEdge = Twb::Util::Graphedge.new(from: calcFieldNode, to: refFieldNode, relationship: 'references')
|
278
|
-
# @edges.add fieldFieldEdge
|
279
|
-
# end
|
280
|
-
# # end
|
281
|
-
# referencedFields.add rf.id
|
282
|
-
# refFieldTable = ds.fieldTable(rf.name)
|
283
|
-
# emit "refFieldTable.nil? : #{refFieldTable.nil?}"
|
284
|
-
# unless refFieldTable.nil?
|
285
|
-
# tableID = refFieldTable + ':::' + ds.uiname
|
286
|
-
# tableName = "||#{refFieldTable}||"
|
287
|
-
# # if @doGraph
|
288
|
-
# tableNode = Twb::Util::Graphnode.new(name: tableName, id: tableID, type: :DBTable, properties: properties)
|
289
|
-
# @nodes.add tableNode
|
290
|
-
# fieldFieldEdge = Twb::Util::Graphedge.new(from: refFieldNode, to: tableNode, relationship: 'is a field in')
|
291
|
-
# @edges.add fieldFieldEdge
|
292
|
-
# # end
|
293
|
-
# # fldToDsNode = tableNode
|
294
|
-
# end
|
295
|
-
# @csvFormulaFields << [
|
296
|
-
# @referencedFieldsCount += 1,
|
297
|
-
# @twb.name,
|
298
|
-
# # @modTime,
|
299
|
-
# ds.uiname,
|
300
|
-
# calcField.uiname,
|
301
|
-
# calculation.formulaFlat,
|
302
|
-
# calculation.formulaFlatResolved,
|
303
|
-
# rf.name,
|
304
|
-
# rf.uiname,
|
305
|
-
# rf.id,
|
306
|
-
# refFieldTable
|
307
|
-
# ]
|
268
|
+
refFieldNode = Twb::Util::Graphnode.new(name: rf.uiname, id: rf.id, type: rf, properties: {:DataSource => ds.uiname})
|
269
|
+
@nodes.add refFieldNode
|
270
|
+
refFieldEdge = Twb::Util::Graphedge.new(from: calcFieldNode, to: refFieldNode , relationship: 'references')
|
271
|
+
@edges.add refFieldEdge
|
308
272
|
end # resolvedFields.each do
|
309
273
|
end # if calculation.has_formula
|
310
274
|
end # ds.calculatedFields.each
|
@@ -345,49 +309,49 @@ DOTHEADER
|
|
345
309
|
emit "\t formula:: #{calculation.formulaFlat}"
|
346
310
|
end
|
347
311
|
|
348
|
-
def mapTwb
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
end
|
312
|
+
# def mapTwb
|
313
|
+
# twb = @twb.name
|
314
|
+
# rootFields = @twbRootFields
|
315
|
+
# dotStuff = initDot twb
|
316
|
+
# dotFile = dotStuff[:file]
|
317
|
+
# dotFileName = dotStuff[:name]
|
318
|
+
# dotFile.puts "\n // subgraph cluster_1 {"
|
319
|
+
# dotFile.puts " // color= grey;"
|
320
|
+
# dotFile.puts ""
|
321
|
+
# edgesAsStrings = SortedSet.new
|
322
|
+
# # this two step process coalesces the edges into a unique set, avoiding duplicating the dot
|
323
|
+
# # file entries, and can be shrunk when graph edges expose the bits necessary for management by Set
|
324
|
+
# emit "\n========================\nLoading Edges\n========================\n From DC? Referenced? Edge \n %s %s %s" % ['--------', '-----------', '-'*45]
|
325
|
+
# @edges.each do |e|
|
326
|
+
# # don't want to emit edge which is from a Data Connection to a
|
327
|
+
# # Calculated Field which is also referenced by another calculated field
|
328
|
+
# isFromDC = e.from.type == :TwbDataConnection
|
329
|
+
# isRefField = @referencedFields.include?(e.to.id)
|
330
|
+
# edgesAsStrings.add(e.dot) unless isFromDC && isRefField
|
331
|
+
# # emit " ES #{e.dot}"
|
332
|
+
# # emit " ES from #{e.from}"
|
333
|
+
# # emit " ES to #{e.to}"
|
334
|
+
# end
|
335
|
+
# emit "------------------------\n "
|
336
|
+
# edgesAsStrings.each do |es|
|
337
|
+
# dotFile.puts " #{es}"
|
338
|
+
# end
|
339
|
+
# emit "========================\n "
|
340
|
+
# dotFile.puts ""
|
341
|
+
# dotFile.puts " // }"
|
342
|
+
# dotFile.puts "\n\n // 4 NODES --------------------------------------------------------------------"
|
343
|
+
# @nodes.each do |n|
|
344
|
+
# dotFile.puts n.dotLabel
|
345
|
+
# end
|
346
|
+
# dotFile.puts "\n\n // 5--------------------------------------------------------------------"
|
347
|
+
# emitTypes( dotFile )
|
348
|
+
# closeDot( dotFile, twb )
|
349
|
+
# emit "Rendering DOT file - #{twb}"
|
350
|
+
# renderDot(twb,dotFileName,'pdf')
|
351
|
+
# renderDot(twb,dotFileName,'png')
|
352
|
+
# renderDot(twb,dotFileName,'svg')
|
353
|
+
# # emitEdges
|
354
|
+
# end
|
391
355
|
|
392
356
|
def cypher twbName
|
393
357
|
if @doGraph
|
@@ -503,44 +467,44 @@ DOTHEADER
|
|
503
467
|
dotFile.puts ' }'
|
504
468
|
end
|
505
469
|
|
506
|
-
def initDot twb
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
end
|
470
|
+
# def initDot twb
|
471
|
+
# dotFileName = docFile("#{twb}#{@@processName}.dot")
|
472
|
+
# dotFile = File.open(dotFileName,'w')
|
473
|
+
# dotFile.puts @@dotHeader
|
474
|
+
# return {:file => dotFile, :name => dotFileName}
|
475
|
+
# end
|
512
476
|
|
513
|
-
def closeDot dotFile, twb
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
end
|
477
|
+
# def closeDot dotFile, twb
|
478
|
+
# dotFile.puts ' '
|
479
|
+
# dotFile.puts '// -------------------------------------------------------------'
|
480
|
+
# dotFile.puts ' '
|
481
|
+
# dotFile.puts ' subgraph cluster_1 {'
|
482
|
+
# # dotFile.puts ' color=white;'
|
483
|
+
# dotFile.puts ' style=invis;'
|
484
|
+
# # dotFile.puts ' border=0;'
|
485
|
+
# dotFile.puts ' node [border=blue];'
|
486
|
+
# dotFile.puts ' '
|
487
|
+
# dotFile.puts ' "" [style=invis]'
|
488
|
+
# dotFile.puts " \"Tableau Tools\\nCalculated Fields Map\\nWorkbook '#{twb}'\\n#{Time.new.ctime}\" [penwidth=0]"
|
489
|
+
# # dotFile.puts " \"Tableau Tools Workbook Calculated Fields Map\\n#{Time.new.ctime}\" -> \"\" [style=invis]"
|
490
|
+
# dotFile.puts ' '
|
491
|
+
# dotFile.puts ' }'
|
492
|
+
# dotFile.puts ' '
|
493
|
+
# dotFile.puts '}'
|
494
|
+
# dotFile.close
|
495
|
+
# end
|
532
496
|
|
533
497
|
|
534
|
-
def renderDot twb, dot, format
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
end
|
498
|
+
# def renderDot twb, dot, format
|
499
|
+
# imageType = '-T' + format
|
500
|
+
# imageFile = './ttdoc/' + twb + @@processName + 'Graph.' + format
|
501
|
+
# imageParam = '-o"' + imageFile + '"'
|
502
|
+
# emit "system #{@@gvDotLocation} #{imageType} #{imageParam} \"#{dot}\""
|
503
|
+
# system "#{@@gvDotLocation} #{imageType} #{imageParam} \"#{dot}\""
|
504
|
+
# emit " - #{imageFile}"
|
505
|
+
# @imageFiles << imageFile
|
506
|
+
# return imageFile
|
507
|
+
# end
|
544
508
|
|
545
509
|
end # class
|
546
510
|
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# dotanalyzer.rb - this Ruby script Copyright 2017, 2018 Christopher Gerrard
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
|
17
|
+
module Twb
|
18
|
+
module Analysis
|
19
|
+
module CalculatedFields
|
20
|
+
|
21
|
+
class DotAnalyzer
|
22
|
+
include TabTool
|
23
|
+
|
24
|
+
attr_reader :docFileName
|
25
|
+
|
26
|
+
@@gvDotLocation = 'C:\\tech\\graphviz\\Graphviz2.38\\bin\\dot.exe'
|
27
|
+
@@imageTypes = ['pdf', 'png', 'svg']
|
28
|
+
|
29
|
+
def initialize(**args)
|
30
|
+
@args = args
|
31
|
+
init
|
32
|
+
@funcdoc = {:class=>self.class, :blurb=>'Create Dot files documenting Calculated Fields', :description=>'Analyze Calculated Fields - create Dot files' }
|
33
|
+
@metrics = {}
|
34
|
+
@imageFiles = Array.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def encode str
|
38
|
+
str.gsub('"', '\"')
|
39
|
+
end
|
40
|
+
|
41
|
+
def processTWB twb
|
42
|
+
# twb = File.basename(twb)
|
43
|
+
@twb = twb #Twb::Workbook.new twb
|
44
|
+
addDocFile @dotFile, @dotFileName, "Dot file of Calculated fields for Workbook '#{@twb.name}'"
|
45
|
+
@twb.datasources.each do |ds|
|
46
|
+
unless ds.calculatedFields.empty?
|
47
|
+
initDotFile ds.uiname
|
48
|
+
# @dotFile.puts "\n ## #{ds.uiname} \n "
|
49
|
+
# @dotFile.puts "__has #{ds.calculatedFields.length} calculated fields__\n "
|
50
|
+
@cfCnt = 0
|
51
|
+
calcFields = Set.new
|
52
|
+
refFields = Set.new
|
53
|
+
edges = Set.new
|
54
|
+
ds.calculatedFields.each do |cf|
|
55
|
+
@cfCnt += 1
|
56
|
+
calcFields << cf.uiname
|
57
|
+
edges << " \"#{encode(ds.uiname)}\" -> \"#{encode(cf.uiname)}\" [tailport=e, headport=w] "
|
58
|
+
puts " \"#{encode(ds.uiname)}\" -> \"#{encode(cf.uiname)}\" [tailport=e, headport=w] "
|
59
|
+
cf.referencedFields.each do |rf|
|
60
|
+
refFields << rf.uiname
|
61
|
+
edges << " \"#{encode(cf.uiname)}\" -> \"#{encode(rf.uiname)}\" [tailport=e, headport=w] "
|
62
|
+
end
|
63
|
+
end # ds.calculatedFields.each
|
64
|
+
# "federated.17h7owt0rsacke17cql8o0w2ittk" -> "New AO Actuals Query in PP+ (AO Variance Data)::vs Prior Year [YTD]"
|
65
|
+
# "federated.01s5lca037ted31gxs9sg0t9mnnt" [label="Controls" ]
|
66
|
+
edges.each do |edge|
|
67
|
+
@dotFile.puts "\t #{edge.strip}"
|
68
|
+
end
|
69
|
+
@dotFile.puts " "
|
70
|
+
allFields = calcFields + refFields
|
71
|
+
allFields.each do |f|
|
72
|
+
@dotFile.puts "\t \"#{encode(f)}\" [label=\"#{encode(f)}\"]"
|
73
|
+
end
|
74
|
+
endPointFields = allFields - calcFields
|
75
|
+
rankSame(endPointFields) unless endPointFields.nil? || endPointFields.empty?
|
76
|
+
closeDotFile
|
77
|
+
@@imageTypes.each do |type|
|
78
|
+
renderDot type
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end # twb.datasources.each
|
82
|
+
finis
|
83
|
+
end # def processTwb twb
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def initDotFile dsName
|
88
|
+
@dotFileName = './ttdoc/' + @twb.name + '.' + dsName + '.CalculatedFields.dot'
|
89
|
+
@dotFile = File.open(@dotFileName,'w')
|
90
|
+
# @dotFile.puts @@dotHeader
|
91
|
+
@dotFile.puts ' digraph g {'
|
92
|
+
@dotFile.puts ' graph [rankdir="LR" splines=line];'
|
93
|
+
@dotFile.puts ' node [shape="box" width="2"];'
|
94
|
+
@dotFile.puts ' '
|
95
|
+
@dotFile.puts ' subgraph cluster_0 {'
|
96
|
+
end
|
97
|
+
|
98
|
+
def closeDotFile
|
99
|
+
# @dotFile.puts "\n # counted #{@cfCnt} calculated fields\n "
|
100
|
+
# @dotFile.puts "\n }"
|
101
|
+
@dotFile.puts ' }'
|
102
|
+
@dotFile.puts ' '
|
103
|
+
@dotFile.puts '// -------------------------------------------------------------'
|
104
|
+
@dotFile.puts ' '
|
105
|
+
@dotFile.puts ' subgraph cluster_1 {'
|
106
|
+
#@dotFile.puts ' color=white;'
|
107
|
+
@dotFile.puts ' style=invis;'
|
108
|
+
#@dotFile.puts ' border=0;'
|
109
|
+
@dotFile.puts ' node [border=blue];'
|
110
|
+
@dotFile.puts ' '
|
111
|
+
@dotFile.puts ' "" [style=invis]'
|
112
|
+
@dotFile.puts " \"Tableau Tools\\nCalculated Fields Map\\nWorkbook '#{@twb.name}'\\n#{Time.new.ctime}\" [penwidth=0]"
|
113
|
+
#@dotFile.puts " \"Tableau Tools Workbook Calculated Fields Map\\n#{Time.new.ctime}\" -> \"\" [style=invis]"
|
114
|
+
@dotFile.puts ' '
|
115
|
+
@dotFile.puts ' }'
|
116
|
+
@dotFile.puts ' '
|
117
|
+
@dotFile.puts '}'
|
118
|
+
@dotFile.close
|
119
|
+
end
|
120
|
+
|
121
|
+
def rankSame fields
|
122
|
+
@dotFile.puts "\n {rank=same "
|
123
|
+
fields.each do |f|
|
124
|
+
@dotFile.puts "\t \"#{f}\" "
|
125
|
+
end
|
126
|
+
@dotFile.puts " } "
|
127
|
+
end
|
128
|
+
|
129
|
+
def renderDot format
|
130
|
+
imageType = '-T' + format
|
131
|
+
imageFile = @dotFileName + '.Graph.' + format
|
132
|
+
imageParam = '-o"' + imageFile + '"'
|
133
|
+
emit "system #{@@gvDotLocation} #{imageType} #{imageParam} \"#{@dotFileName}\""
|
134
|
+
system "#{@@gvDotLocation} #{imageType} #{imageParam} \"#{@dotFileName}\""
|
135
|
+
# emit " - #{imageFile}"
|
136
|
+
@imageFiles << imageFile
|
137
|
+
return imageFile
|
138
|
+
end
|
139
|
+
|
140
|
+
end # class DotAnalyzer
|
141
|
+
|
142
|
+
end # nodule CalculatedFields
|
143
|
+
end # module Analysis
|
144
|
+
end # module Twb
|
@@ -52,10 +52,10 @@ module CalculatedFields
|
|
52
52
|
@docFile.puts "#{l.gsub('<<','[').gsub('>>',']')}"
|
53
53
|
end
|
54
54
|
@docFile.puts "```"
|
55
|
-
if cf.
|
55
|
+
if cf.referencedFields.length > 0
|
56
56
|
fieldsRefOrder = []
|
57
57
|
fieldsSortSet = SortedSet.new
|
58
|
-
cf.
|
58
|
+
cf.referencedFields.each do |field|
|
59
59
|
fieldsRefOrder.push field.uiname
|
60
60
|
fieldsSortSet << field.uiname
|
61
61
|
end
|
data/lib/twb/columnfield.rb
CHANGED
@@ -72,7 +72,7 @@ module Twb
|
|
72
72
|
def initialize(fieldNode, datasource=nil)
|
73
73
|
@datasource = datasource
|
74
74
|
@node = fieldNode
|
75
|
-
@name = load
|
75
|
+
@name = load('name').sub(/^\[/,'').sub(/\]$/,'')
|
76
76
|
@caption = load 'caption'
|
77
77
|
@uiname = @caption.nil? ? @name : @caption
|
78
78
|
@dataType = load 'datatype'
|
@@ -227,6 +227,14 @@ module Twb
|
|
227
227
|
@name <=> other.name
|
228
228
|
end
|
229
229
|
|
230
|
+
def eql?(other)
|
231
|
+
@name == other.name
|
232
|
+
end
|
233
|
+
|
234
|
+
def hash
|
235
|
+
@name.hash
|
236
|
+
end
|
237
|
+
|
230
238
|
end # class ColumnField
|
231
239
|
|
232
240
|
end
|
data/lib/twb/fieldcalculation.rb
CHANGED
@@ -125,17 +125,21 @@ module Twb
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def resolveFormula
|
128
|
-
#
|
129
|
-
|
128
|
+
# emit "\ndef resolveFormula:\n--\n#{@formula}"
|
129
|
+
resolved = @formula
|
130
|
+
# emit "\t formula:#{resolved}:"
|
130
131
|
# parseFormFields # - extracts the fields from the formula; as persisted they're the internal names
|
131
|
-
referencedFields.each do |
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
132
|
+
referencedFields.each do |refField|
|
133
|
+
# emit "\t refField: "
|
134
|
+
resolved.gsub!(refField.techCode,refField.uiCode)
|
135
|
+
# if calcField.techUIdiff
|
136
|
+
# # puts ":::: #{calcField.techCode} // #{calcField.uiCode}"
|
137
|
+
# formula = formula.gsub(calcField.techCode,calcField.uiCode)
|
138
|
+
# # puts ":--: #{formula}"
|
139
|
+
# end
|
137
140
|
end
|
138
|
-
|
141
|
+
# emit "\t formula:#{resolved}:"
|
142
|
+
return resolved
|
139
143
|
end
|
140
144
|
|
141
145
|
def referencedFields
|
data/lib/twb/quickfilter.rb
CHANGED
@@ -120,7 +120,7 @@ module Twb
|
|
120
120
|
# filter class='relative-date' column='[Sample - Superstore].[none:Order Date:qk]' first-period='1' include-future='true' include-null='false' last-period='1' period-type='year' />
|
121
121
|
def resolveRelativeDate
|
122
122
|
emit "resolveRelativeDate"
|
123
|
-
periodType = @node['period-type']
|
123
|
+
periodType = @node['period-type'].nil? ? '' : @node['period-type']
|
124
124
|
inclFuture = @node['include-future'] == 'true'
|
125
125
|
firstPeriod = @node['first-period'].to_i
|
126
126
|
lastPeriod = @node['last-period'].to_i
|
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: 5.
|
4
|
+
version: 5.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Gerrard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: creek
|
@@ -64,6 +64,7 @@ files:
|
|
64
64
|
- lib/twb/analysis/annotatedfieldscsvemitter.rb
|
65
65
|
- lib/twb/analysis/calculatedfields/calculatedfieldsanalyzer.rb
|
66
66
|
- lib/twb/analysis/calculatedfields/csvemitter.rb
|
67
|
+
- lib/twb/analysis/calculatedfields/dotanalyzer.rb
|
67
68
|
- lib/twb/analysis/calculatedfields/fieldsaliasesanalyzer.rb
|
68
69
|
- lib/twb/analysis/calculatedfields/groupfieldsanalyzer.rb
|
69
70
|
- lib/twb/analysis/calculatedfields/markdownemitter.rb
|