twb 4.9.4 → 5.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9bf5871fe93aaf4afc19f4c4b789d18db29545c43f77c6ae1d2c901dc23cd142
4
- data.tar.gz: e529613db65063341cde12d6393201765f3a53b680e4fbc7fe21707b9ff83681
3
+ metadata.gz: 786d3cb3bde8d6d6db0ee5c4063e998df008b5ca1354ba8fb4fc77c06aa7e10d
4
+ data.tar.gz: f9e73b1494d4d3946749f03e045caf6db221d4750ac12d99a5af037a77ca955a
5
5
  SHA512:
6
- metadata.gz: 7fb310fd663173d925df07488ec1f8d147651ca6588b725f03acaa99e88cfbcc07bb5aed2b797a8e70afd57143466a06ca0857bab0e4bdad99fda42423093652
7
- data.tar.gz: 460b6aee7fe9bf62baa9611a350dc3b7fe671ae18c03b8943431506a43bf0598247e92e784604cf35450bdc1f3dc09c04380ae43ff35c33344877885f16ca191
6
+ metadata.gz: 1ed3f0c9dfd61b8accd948ac10f29382f16c0fc8b15c415c8f5de55ab5a2739b6e7991e82c02ec953fd1507cb27079b59a5a15785da4a44b2fbe57f5e08eb083
7
+ data.tar.gz: 6171c5e6615b4d426690fca14bc92fea5e7325ee143985bd2fd4fd178833c41085a9e0b9f75a219884fdc900ab4d04a56ccd12d69580636e85b30855dd5f7792
@@ -0,0 +1,311 @@
1
+
2
+ # Copyright (C) 2014, 2020 Chris Gerrard
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'nokogiri'
18
+ require 'zip'
19
+
20
+ module Flow
21
+
22
+
23
+ ##
24
+ # A Tableau Prep Flow file.
25
+ #
26
+ class Flow < TabClass
27
+
28
+ attr_reader :name, :dir, :type, :modtime
29
+ attr_reader :version, :build, :platform, :base
30
+ attr_reader :root
31
+ #--
32
+ attr_reader :datasources, :datasource
33
+ attr_reader :datasourceNames, :datasourceUINames, :dataSourceNamesMap
34
+ # attr_reader :orphanDataSources # i.e. not referenced in any Worksheet
35
+ #--
36
+ # attr_reader :dashboards, :storyboards, :worksheets
37
+ # attr_reader :parameters, :actions
38
+ # attr_reader :valid
39
+
40
+ ##
41
+ # Creates a Flow from its file name.
42
+ #
43
+ # == Parameters:
44
+ # flowWithDir
45
+ # The Flow's file name, the Flow can be a TWB or TWBX file.
46
+ #
47
+ def initialize tflWithDir
48
+ raise ArgumentError.new("ERROR in Flow creation: '#{tflWithDir}' must be a String, is a #{tflWithDir.class} \n ") unless tflWithDir.is_a? String
49
+ raise ArgumentError.new("ERROR in Flow creation: '#{tflWithDir}' must have an extension of .tfl or .tflx \n ") unless tflWithDir.upcase.end_with?(".TFL", ".TFLX")
50
+ raise ArgumentError.new("ERROR in Flow creation: '#{tflWithDir}' must must be a file, is a Directory\\Folder \n ") if File.directory?(tflWithDir)
51
+ raise ArgumentError.new("ERROR in Flow creation: '#{tflWithDir}' cannot be found, must be a Tableau Flow file. \n ") unless File.file?(tflWithDir)
52
+ @valid = false
53
+ if File.file?(tflWithDir) then
54
+ @name = File.basename(tflWithDir)
55
+ @dir = File.dirname(File.expand_path(tflWithDir))
56
+ @modtime = File.new(tflWithDir).mtime.strftime("%Y-%m-%d %H:%M:%S")
57
+ case File.extname(tflWithDir).downcase
58
+ when '.tlf' then processTFL(tflWithDir)
59
+ when '.tflx' then processTFLX(flowWithDir)
60
+ end
61
+ end
62
+ end
63
+
64
+ def id
65
+ @id ||= @id = @name.hash
66
+ end
67
+
68
+ def build
69
+ @build ||= loadBuild
70
+ end
71
+
72
+ def release
73
+ @build ||= loadBuild
74
+ end
75
+
76
+ def worksheets
77
+ @worksheets.values
78
+ end
79
+
80
+ def worksheet name
81
+ @worksheets[name]
82
+ end
83
+
84
+ def worksheetNames
85
+ @worksheets.keys
86
+ end
87
+
88
+ def dashboards
89
+ @dashboards.values
90
+ end
91
+
92
+ def dashboardNames
93
+ @dashboards.keys
94
+ end
95
+
96
+ def dashboard name
97
+ @dashboards[name]
98
+ end
99
+
100
+ def actions
101
+ @actions.values
102
+ end
103
+
104
+ def actionNames
105
+ @actions.keys
106
+ end
107
+
108
+ def datasource name
109
+ @dataSourceNamesMap[name]
110
+ end
111
+
112
+ def parameters
113
+ @parameters ||= loadParameters
114
+ end
115
+
116
+ def orphanDataSources
117
+ @orphanDataSources ||= identifyOrphandatasoUrceS
118
+ end
119
+
120
+ def storyboards
121
+ @storyboards.values
122
+ end
123
+
124
+ def storyboardNames
125
+ @storyboards.keys
126
+ end
127
+
128
+ def storyboard name
129
+ @storyboards[name]
130
+ end
131
+
132
+ private
133
+
134
+ def processTFLX(twbxWithDir)
135
+ Zip::File.open(twbxWithDir) do |zip_file|
136
+ twb = zip_file.glob('*.twb').first
137
+ @ndoc = Nokogiri::XML(twb.get_input_stream)
138
+ @type = :twbx
139
+ processDoc
140
+ end
141
+ end
142
+
143
+ def processTFL(twbFile)
144
+ @ndoc = Nokogiri::XML(open(twbFile))
145
+ @type = :twb
146
+ processDoc
147
+ end
148
+
149
+ def processDoc
150
+ @valid = true
151
+ end
152
+
153
+ def loadBuild
154
+ # - earlier Version, need to confirm when source-build began
155
+ # @build = @ndoc.xpath('/flow/comment()').text.gsub(/^[^0-9]+/,'').strip
156
+ @build = if !@ndoc.at_xpath('/flow/@source-build').nil?
157
+ @ndoc.at_xpath('/flow/@source-build').text
158
+ else
159
+ if @ndoc.at_xpath('/flow/comment()').nil?
160
+ 'not found'
161
+ else
162
+ @ndoc.at_xpath('/flow/comment()').text.gsub(/^[^0-9]+/,'').strip
163
+ end
164
+ end
165
+ end
166
+
167
+ def loaddatasources
168
+ # puts "LOAD DATA SOURCES"
169
+ # @dataSourcesNode = @ndoc.at_xpath('//flow/datasources')
170
+ @datasources = Set.new
171
+ @datasourceNames = SortedSet.new
172
+ @datasourceUINames = SortedSet.new
173
+ @dataSourceNamesMap = {}
174
+ datasourceNodes = @ndoc.xpath('//flow/datasources/datasource')
175
+ # puts "DATASOURCENODES : #{@datasourceNodes.length}"
176
+ datasourceNodes.each do |node|
177
+ datasource = Twb::DataSource.new(node,self)
178
+ @datasources << datasource
179
+ @datasourceNames << datasource.name
180
+ @datasourceNames << datasource.uiname
181
+ @datasourceUINames << datasource.uiname
182
+ @dataSourceNamesMap[datasource.name] = datasource
183
+ @dataSourceNamesMap[datasource.uiname] = datasource
184
+ end
185
+ # puts "DATASOURCES : #{@datasources.length}"
186
+ end
187
+
188
+ def loadWorksheets
189
+ @worksheets = {}
190
+ hiddenSheets = []
191
+ @ndoc.xpath('//flow/windows/window[@hidden="true"]').each do |hs|
192
+ hiddenSheets << hs['name']
193
+ end
194
+ sheets = @ndoc.xpath('//flow/worksheets/worksheet' ).to_a
195
+ sheets.each do |node|
196
+ sheet = Twb::Worksheet.new(node, self)
197
+ sheet.hidden = hiddenSheets.include? sheet.name
198
+ @worksheets[sheet.name] = sheet
199
+ end
200
+ end
201
+
202
+ def loadDashboards
203
+ @dashesNode = @ndoc.at_xpath('//flow/dashboards')
204
+ @dashboards = {}
205
+ dashes = @ndoc.xpath('//flow/dashboards/dashboard').to_a
206
+ dashes.each do |node|
207
+ unless node.attr('type') == 'storyboard' then
208
+ dashboard = Twb::Dashboard.new(node, @worksheets)
209
+ @dashboards[dashboard.name] = dashboard
210
+ end
211
+ end
212
+ end
213
+
214
+ def loadStoryboards
215
+ @storyboards = {}
216
+ boards = @ndoc.xpath("//flow/dashboards/dashboard[@type='storyboard']" ).to_a
217
+ boards.each do |node|
218
+ sheet = Twb::Storyboard.new(node)
219
+ @storyboards[sheet.name] = sheet
220
+ end
221
+ end
222
+
223
+ def loadWindows
224
+ @windowsnode = @ndoc.at_xpath("//flow/windows")
225
+ @windows = {}
226
+ windows = @ndoc.xpath("//flow/windows/window[@name]")
227
+ windows.each do |node|
228
+ window = Twb::Window.new(node)
229
+ @windows[window.name] = window
230
+ end
231
+ end
232
+
233
+ def loadActions
234
+ @actions = {}
235
+ actionNodes = @ndoc.xpath("//flow/actions/action")
236
+ actionNodes.each do |anode|
237
+ action = Twb::Action.new(anode, @flownode)
238
+ @actions[action.uiname] = action
239
+ end
240
+ end
241
+
242
+ def identifyOrphandatasoUrceS
243
+ sheetDataSources = Set.new
244
+ @worksheets.values.each do |sheet|
245
+ sheet.datasources.each do |ds|
246
+ sheetDataSources << ds.uiname
247
+ end
248
+ end
249
+ @orphanDataSources = @datasourceUINames - sheetDataSources
250
+ end
251
+
252
+ def writeTwb(name=@name)
253
+ $f = File.open(name,'w')
254
+ if $f
255
+ $f.puts @ndoc
256
+ $f.close
257
+ end
258
+ return name
259
+ end
260
+
261
+ def writeTwbx(name=@name)
262
+ emit "Writing the Workbook, need implementation"
263
+ end
264
+
265
+ # Make sure that the TWB has a <dashboards> node.
266
+ # It's possible for a TWB to have no dashboards, and therefore no <dashboards> node.
267
+ def ensureDashboardsNodeExists
268
+ if @dashesNode.nil?
269
+ @dashesNode = Nokogiri::XML::Node.new "dashboards", @ndoc
270
+ # TODO fix this @dataSourcesNode.add_next_sibling(@dashesNode)
271
+ end
272
+ end
273
+
274
+ def ensureWindowsNodeExists
275
+ if @windowsnode.nil?
276
+ @windowsnode = Nokogiri::XML::Node.new "windows", @ndoc
277
+ # TODO fix this @dataSourcesNode.add_next_sibling(@windowsnode)
278
+ end
279
+ end
280
+
281
+ def getNewDashboardTitle(t)
282
+ title = t
283
+ if @datasources.include?(title)
284
+ inc = 0
285
+ loop do
286
+ inc+=1
287
+ title = t + ' ' + inc.to_s
288
+ if !@datasources.include?(title)
289
+ break
290
+ end
291
+ end
292
+ end
293
+ return title
294
+ end
295
+
296
+ def loadParameters
297
+ @parameters = {}
298
+ paramsDS = ndoc.at_xpath('./flow/datasources/datasource[@name="Parameters"]')
299
+ unless paramsDS.nil?
300
+ paramNodes = paramsDS.xpath('.//column')
301
+ paramNodes.each do |pn|
302
+ parameter = Twb::Parameter.new pn
303
+ @parameters[parameter.name] = parameter
304
+ end
305
+ end
306
+ return @parameters
307
+ end
308
+
309
+ end # class Flow
310
+
311
+ end # module Twb
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'
@@ -73,12 +74,12 @@ require_relative 'twb/analysis/sheets/worksheetsummarizer'
73
74
  require_relative 'twb/analysis/sheets/worksheetdatastructurecsvemitter'
74
75
  require_relative 'twb/analysis/sheets/sheetfiltersanalyzer'
75
76
  require_relative 'twb/analysis/sheets/sheetfieldsanalyzer'
77
+ require_relative 'twb/analysis/sheets/dashboardsummarizer'
76
78
  require_relative 'twb/analysis/sheets/dashsheetsanalyzer'
77
79
  require_relative 'twb/analysis/sheets/sheetsintooltipanalyzer'
78
80
 
79
-
80
81
  # Represents Tableau Workbooks, their contents, and classes that analyze and manipulate them.
81
82
  #
82
83
  module Twb
83
- VERSION = '4.9.4'
84
+ VERSION = '5.2.1'
84
85
  end
@@ -78,12 +78,12 @@ module Analysis
78
78
  @fieldTables = {}
79
79
 
80
80
 
81
- @@dotHeader = <<DOTHEADER
82
- digraph g {
83
- graph [rankdir="LR" splines=line];
84
- node [shape="box" width="2"];
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
- 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
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
@@ -249,47 +249,26 @@ DOTHEADER
249
249
  ]
250
250
  end
251
251
  #-- collect fields referenced in formula
252
- emit "# Calculated Fields: #{calculation.calcFields.length}"
253
- calculation.calcFields.each do |rf|
254
- emit " referenced field ::'#{rf}'"
255
- emit " referenced field.name ::'#{rf.name.nil?}' :: '#{rf.name}'"
256
- emit " referenced field.uiname::'#{rf.uiname}'"
257
- # if @doGraph
258
- unless rf.uiname.nil?
259
- properties = {'DataSource' => ds.uiname, 'DataSourceReference' => 'local', :source => rf}
260
- refFieldNode = Twb::Util::Graphnode.new(name: rf.uiname, id: rf.id, type: rf.type, properties: properties)
261
- @nodes.add refFieldNode
262
- fieldFieldEdge = Twb::Util::Graphedge.new(from: calcFieldNode, to: refFieldNode, relationship: 'references')
263
- @edges.add fieldFieldEdge
264
- end
265
- # end
266
- referencedFields.add rf.id
267
- refFieldTable = ds.fieldTable(rf.name)
268
- emit "refFieldTable.nil? : #{refFieldTable.nil?}"
269
- unless refFieldTable.nil?
270
- tableID = refFieldTable + ':::' + ds.uiname
271
- tableName = "||#{refFieldTable}||"
272
- # if @doGraph
273
- tableNode = Twb::Util::Graphnode.new(name: tableName, id: tableID, type: :DBTable, properties: properties)
274
- @nodes.add tableNode
275
- fieldFieldEdge = Twb::Util::Graphedge.new(from: refFieldNode, to: tableNode, relationship: 'is a field in')
276
- @edges.add fieldFieldEdge
277
- # end
278
- # fldToDsNode = tableNode
279
- end
252
+ emit "# Calculated Fields: #{calculation.referencedFields.length}"
253
+ calculation.referencedFields.each do |rf|
254
+ emit " referenced field :: %12s %s " % [ rf.dataSourceName, rf.uiname ]
280
255
  @csvFormulaFields << [
281
256
  @referencedFieldsCount += 1,
282
257
  @twb.name,
283
258
  # @modTime,
284
- ds.uiname,
259
+ rf.dataSourceName, # ds.uiname,
285
260
  calcField.uiname,
286
261
  calculation.formulaFlat,
287
262
  calculation.formulaFlatResolved,
288
263
  rf.name,
289
- rf.uiname,
290
- rf.id,
291
- refFieldTable
264
+ rf.uiname, #.uiname,
265
+ '', # rf.id,
266
+ '', #refFieldTable
292
267
  ]
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
293
272
  end # resolvedFields.each do
294
273
  end # if calculation.has_formula
295
274
  end # ds.calculatedFields.each
@@ -298,8 +277,8 @@ DOTHEADER
298
277
  @referencedFields.merge referencedFields
299
278
  @twbRootFields.merge dsRootFields
300
279
  if @doGraph
301
- cypher @twb.name
302
- cypherPy @twb.name
280
+ # cypher @twb.name
281
+ # cypherPy @twb.name
303
282
  end
304
283
  emit "#######################"
305
284
  #--
@@ -330,49 +309,49 @@ DOTHEADER
330
309
  emit "\t formula:: #{calculation.formulaFlat}"
331
310
  end
332
311
 
333
- def mapTwb
334
- twb = @twb.name
335
- rootFields = @twbRootFields
336
- dotStuff = initDot twb
337
- dotFile = dotStuff[:file]
338
- dotFileName = dotStuff[:name]
339
- dotFile.puts "\n // subgraph cluster_1 {"
340
- dotFile.puts " // color= grey;"
341
- dotFile.puts ""
342
- edgesAsStrings = SortedSet.new
343
- # this two step process coalesces the edges into a unique set, avoiding duplicating the dot
344
- # file entries, and can be shrunk when graph edges expose the bits necessary for management by Set
345
- emit "\n========================\nLoading Edges\n========================\n From DC? Referenced? Edge \n %s %s %s" % ['--------', '-----------', '-'*45]
346
- @edges.each do |e|
347
- # don't want to emit edge which is from a Data Connection to a
348
- # Calculated Field which is also referenced by another calculated field
349
- isFromDC = e.from.type == :TwbDataConnection
350
- isRefField = @referencedFields.include?(e.to.id)
351
- edgesAsStrings.add(e.dot) unless isFromDC && isRefField
352
- # emit " ES #{e.dot}"
353
- # emit " ES from #{e.from}"
354
- # emit " ES to #{e.to}"
355
- end
356
- emit "------------------------\n "
357
- edgesAsStrings.each do |es|
358
- dotFile.puts " #{es}"
359
- end
360
- emit "========================\n "
361
- dotFile.puts ""
362
- dotFile.puts " // }"
363
- dotFile.puts "\n\n // 4 NODES --------------------------------------------------------------------"
364
- @nodes.each do |n|
365
- dotFile.puts n.dotLabel
366
- end
367
- dotFile.puts "\n\n // 5--------------------------------------------------------------------"
368
- emitTypes( dotFile )
369
- closeDot( dotFile, twb )
370
- emit "Rendering DOT file - #{twb}"
371
- renderDot(twb,dotFileName,'pdf')
372
- renderDot(twb,dotFileName,'png')
373
- renderDot(twb,dotFileName,'svg')
374
- # emitEdges
375
- 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
376
355
 
377
356
  def cypher twbName
378
357
  if @doGraph
@@ -488,44 +467,44 @@ DOTHEADER
488
467
  dotFile.puts ' }'
489
468
  end
490
469
 
491
- def initDot twb
492
- dotFileName = docFile("#{twb}#{@@processName}.dot")
493
- dotFile = File.open(dotFileName,'w')
494
- dotFile.puts @@dotHeader
495
- return {:file => dotFile, :name => dotFileName}
496
- 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
497
476
 
498
- def closeDot dotFile, twb
499
- dotFile.puts ' '
500
- dotFile.puts '// -------------------------------------------------------------'
501
- dotFile.puts ' '
502
- dotFile.puts ' subgraph cluster_1 {'
503
- # dotFile.puts ' color=white;'
504
- dotFile.puts ' style=invis;'
505
- # dotFile.puts ' border=0;'
506
- dotFile.puts ' node [border=blue];'
507
- dotFile.puts ' '
508
- dotFile.puts ' "" [style=invis]'
509
- dotFile.puts " \"Tableau Tools\\nCalculated Fields Map\\nWorkbook '#{twb}'\\n#{Time.new.ctime}\" [penwidth=0]"
510
- # dotFile.puts " \"Tableau Tools Workbook Calculated Fields Map\\n#{Time.new.ctime}\" -> \"\" [style=invis]"
511
- dotFile.puts ' '
512
- dotFile.puts ' }'
513
- dotFile.puts ' '
514
- dotFile.puts '}'
515
- dotFile.close
516
- 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
517
496
 
518
497
 
519
- def renderDot twb, dot, format
520
- imageType = '-T' + format
521
- imageFile = './ttdoc/' + twb + @@processName + 'Graph.' + format
522
- imageParam = '-o"' + imageFile + '"'
523
- emit "system #{@@gvDotLocation} #{imageType} #{imageParam} \"#{dot}\""
524
- system "#{@@gvDotLocation} #{imageType} #{imageParam} \"#{dot}\""
525
- emit " - #{imageFile}"
526
- @imageFiles << imageFile
527
- return imageFile
528
- 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
529
508
 
530
509
  end # class
531
510