twb 4.5.5 → 4.5.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/twb/analysis/calculatedfields/calculatedfieldsanalyzer.rb +42 -0
  3. data/lib/twb/analysis/{CalculatedFields → calculatedfields}/csvemitter.rb +0 -0
  4. data/lib/twb/analysis/{CalculatedFields → calculatedfields}/groupfieldsanalyzer.rb +0 -0
  5. data/lib/twb/analysis/{CalculatedFields → calculatedfields}/markdownemitter.rb +0 -0
  6. data/lib/twb/analysis/{DataSources → datasources}/categoricalcolorcodinganalyzer.rb +0 -0
  7. data/lib/twb/analysis/{DataSources → datasources}/datasourcefieldscsvemitter.rb +0 -0
  8. data/lib/twb/analysis/{DataSources → datasources}/datasourceoriginsanalyzer.rb +0 -0
  9. data/lib/twb/analysis/{DataSources/dataSourcesLocationsAnalyzer.rb → datasources/datasourceslocationsanalyzer.rb} +0 -0
  10. data/lib/twb/analysis/{DataSources → datasources}/datasourcetablefieldscsvemitter.rb +0 -0
  11. data/lib/twb/analysis/{DataSources → datasources}/googlesheetdatasourcesanalyzer.rb +0 -0
  12. data/lib/twb/analysis/{DataSources → datasources}/parametersanalyzer.rb +0 -0
  13. data/lib/twb/analysis/{DocumentedFieldsCSVEmitter.rb → documentedfieldscsvemitter.rb} +0 -0
  14. data/lib/twb/analysis/{Sheets/analyzeDashboardSheets.rb → sheets/analyzedashboardsheets.rb} +0 -0
  15. data/lib/twb/analysis/{Sheets → sheets}/dashsheetsanalyzer.rb +0 -0
  16. data/lib/twb/analysis/{Sheets → sheets}/sheetfieldsanalyzer.rb +0 -0
  17. data/lib/twb/analysis/{Sheets → sheets}/sheetfiltersanalyzer.rb +0 -0
  18. data/lib/twb/analysis/{Sheets/sheetfiltersanalyzerA.rb → sheets/sheetfiltersanalyzera.rb} +0 -0
  19. data/lib/twb/analysis/{Sheets → sheets}/sheetsourcesanalyzer.rb +0 -0
  20. data/lib/twb/analysis/{Sheets → sheets}/worksheetdatastructurecsvemitter.rb +0 -0
  21. data/lib/twb/{findDSFields.rb → finddsfields.rb} +0 -0
  22. data/lib/twb/{identifyFields.rb → identifyfields.rb} +0 -0
  23. data/lib/twb/tabtool.rb +12 -10
  24. data/lib/twb/{TwbTest.rb → twbtest.rb} +0 -0
  25. data/lib/twb/util/{ftpPublisher.rb → ftppublisher.rb} +0 -0
  26. data/lib/twb/util/{joinUtilities.rb → joinutilities.rb} +0 -0
  27. data/lib/twb/util/{twbDashesSheetDataDotBuilder.rb → twbdashessheetdatadotbuilder.rb} +0 -0
  28. data/lib/twb/util/{twbDashSheetDataDotRenderer.rb → twbdashsheetdatadotrenderer.rb} +0 -0
  29. data/lib/twb.rb +2 -3
  30. data/t.rb +18 -65
  31. metadata +27 -27
  32. data/lib/twb/analysis/CalculatedFields/calculatedfieldsanalyzer.rb +0 -524
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7049c47a51982f0de1d215e3d2091e559b56346f1e9f1c74b7cbe2464dfcf0c9
4
- data.tar.gz: d7f01f024dea265c8405dc141be50171ac5883d952f38f6128980f949c45cd72
3
+ metadata.gz: 7eb9fb34a75d4869a2ba63a575e532e3fa0c0a9595e454d33574685bd0083ab6
4
+ data.tar.gz: ac54f86e1b09b352dcb6052010ba0486a26860aa74ea294ea8872475a05cd509
5
5
  SHA512:
6
- metadata.gz: 8b56aa09e7dcf6e2d3cfc2e063929066584c5c213dca405d73ccd11862831ce4a69e37e302b8cd41811254bd060e871a4b423b35d0904d84c5cf95a2e87ceaef
7
- data.tar.gz: abfd00faf2f0727ff5839f7662be0a3499fbcd6a315d1670701071720e305eeb68feb9fd4aff9699a9cce7c6410012f43849f94b46cf114bc7f0f0e81828e78d
6
+ metadata.gz: e1d3ee029ca7dc00e9bef48f80fa6b14e52a9ccf5877fa42ae1be1990f8140dc57a819eb84695b580f1564d6cd3e53b76d5a373ad0103feaec138147ac0844e7
7
+ data.tar.gz: 0037410ebe36ae0a2f77f671e7d33d004240b486a2999a8ce118c2876e6665e9d9bd267f14b2fe4bdaee981e1b435d808ff7f7af54cc4b71b2355d2ae03f6ec7
@@ -0,0 +1,42 @@
1
+ # calculatedfieldsanalyzer.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
+ require 'twb'
17
+
18
+ module Twb
19
+ module Analysis
20
+
21
+
22
+ class CalculatedFieldsAnalyzer
23
+
24
+ include TabTool
25
+
26
+ def initialize(**args)
27
+ end
28
+
29
+ def processTWB workbook
30
+ end
31
+
32
+ def metrics
33
+ Array.new
34
+ end
35
+
36
+ #-- private methods begin here, to end of class
37
+
38
+
39
+ end # class
40
+
41
+ end # module Analysis
42
+ end # module Twb
File without changes
File without changes
data/lib/twb/tabtool.rb CHANGED
@@ -112,7 +112,7 @@ module TabTool
112
112
  end
113
113
 
114
114
  def docfiles
115
- @docfiles ||= @docfiles = []
115
+ @docfiles ||= @docfiles = {}
116
116
  end
117
117
 
118
118
  def addDocFile file, name, description
@@ -121,15 +121,17 @@ module TabTool
121
121
  end
122
122
 
123
123
  def closeDocFiles
124
- emit true, "Closing doc files"
125
- @docfiles.each do |dfh|
126
- docfile = dfh[:file]
127
- fileName = dfh[:name]
128
- emit " -- #{dfh}"
129
- # system "ls -l '#{fileName}'"
130
- docfile.close unless docfile.nil?
131
- # system "ls -l '#{fileName}'"
132
- # emit true, " -- #{dfh[:name]}"
124
+ emit "Closing doc files"
125
+ unless @docfiles.nil?
126
+ @docfiles.each do |dfh|
127
+ docfile = dfh[:file]
128
+ fileName = dfh[:name]
129
+ emit " -- #{dfh}"
130
+ # system "ls -l '#{fileName}'"
131
+ docfile.close unless docfile.nil?
132
+ # system "ls -l '#{fileName}'"
133
+ # emit true, " -- #{dfh[:name]}"
134
+ end
133
135
  end
134
136
  emit "-----------------"
135
137
  end
File without changes
File without changes
File without changes
data/lib/twb.rb CHANGED
@@ -52,6 +52,7 @@ require_relative 'twb/util/docprep'
52
52
  require_relative 'twb/analysis/documentedfieldsmarkdownemitter'
53
53
  require_relative 'twb/analysis/annotatedfieldscsvemitter'
54
54
  require_relative 'twb/analysis/workbooksummaryanalyzer'
55
+ require_relative 'twb/analysis/calculatedfields/calculatedfieldsanalyzer'
55
56
  require_relative 'twb/analysis/calculatedfields/groupfieldsanalyzer'
56
57
  require_relative 'twb/analysis/calculatedfields/markdownemitter'
57
58
  require_relative 'twb/analysis/calculatedfields/csvemitter'
@@ -66,11 +67,9 @@ require_relative 'twb/analysis/sheets/sheetfiltersanalyzer'
66
67
  require_relative 'twb/analysis/sheets/sheetfieldsanalyzer'
67
68
  require_relative 'twb/analysis/sheets/dashsheetsanalyzer'
68
69
 
69
- # require_relative 'twb/analysis/calculatedfields/calculatedfieldsanalyzer'
70
-
71
70
 
72
71
  # Represents Tableau Workbooks, their contents, and classes that analyze and manipulate them.
73
72
  #
74
73
  module Twb
75
- VERSION = '4.5.5'
74
+ VERSION = '4.5.7'
76
75
  end
data/t.rb CHANGED
@@ -1,71 +1,24 @@
1
+ system 'cls'
2
+
1
3
  def checkfile fileName
2
- # puts "--"
3
- qfn = "./lib/#{fileName}.rb"
4
- exists = File.exists? qfn
4
+ exists = File.exists? fileName
5
5
  hasCap = !!(fileName =~ /[A-Z]/)
6
- qfn_tmp = "#{qfn.downcase}.tmp"
7
- qfn_lc = qfn.downcase
8
- puts " %-6s %-13s %-s " % [' ' , ' ' , fileName]
9
- puts " %-6s %-7s %-s " % [exists, hasCap, qfn]
10
- puts " %-6s %-7s %-s " % [exists, hasCap, qfn_tmp]
11
- puts " %-6s %-7s %-s " % ['-' , '-' , qfn_lc]
12
- puts " "
13
- File.rename qfn, qfn_tmp
14
- File.rename qfn_tmp, qfn_lc
6
+ isTest = !!(fileName =~ /test/i)
7
+ if hasCap && !isTest
8
+ fn_tmp = "#{fileName}.tmp"
9
+ fn_lc = fileName.downcase
10
+ puts "-- #{fileName}"
11
+ puts " %-6s t? %-6s %-7s %-s " % [' ' , isTest, ' ' , fileName]
12
+ puts " %-6s %-6s %-7s %-s " % [exists, ' ', hasCap, fileName]
13
+ puts " %-6s %-6s %-7s %-s " % [exists, ' ', hasCap, fn_tmp]
14
+ puts " %-6s %-6s %-7s %-s " % ['-' , '-', '-' , fn_lc]
15
+ # File.rename fileName, fn_tmp
16
+ # File.rename fn_tmp, fn_lc
17
+ puts " "
18
+ end
15
19
  end
16
20
 
17
21
 
18
- checkfile 'twb/tabclass'
19
- checkfile 'twb/tabtool'
20
- checkfile 'twb/dashboard'
21
- checkfile 'twb/datasource'
22
- checkfile 'twb/connection'
23
- checkfile 'twb/docdashboard'
24
- checkfile 'twb/dbfield'
25
- checkfile 'twb/localfield'
26
- checkfile 'twb/metadatafield'
27
- checkfile 'twb/storyboard'
28
- checkfile 'twb/window'
29
- checkfile 'twb/workbook'
30
- checkfile 'twb/worksheet'
31
- checkfile 'twb/parameter'
32
- checkfile 'twb/action'
33
- checkfile 'twb/columnfield'
34
- checkfile 'twb/calculatedfield'
35
- checkfile 'twb/codedfield'
36
- checkfile 'twb/groupfield'
37
- checkfile 'twb/fieldcalculation'
38
- checkfile 'twb/quickfilter'
39
- checkfile 'twb/docdashboardimagevert'
40
- checkfile 'twb/docdashboardwebvert'
41
- checkfile 'twb/util/twbDashSheetDataDotBuilder'
42
- checkfile 'twb/util/dotFileRenderer'
43
- checkfile 'twb/util/htmllistcollapsible'
44
- checkfile 'twb/util/xraydashboards'
45
- checkfile 'twb/util/graph'
46
- checkfile 'twb/util/graphnode'
47
- checkfile 'twb/util/graphedge'
48
- checkfile 'twb/util/graphedges'
49
- checkfile 'twb/util/gml'
50
- checkfile 'twb/util/cypher'
51
- checkfile 'twb/util/cypherpython'
52
- checkfile 'twb/util/fielddomainloader'
53
- checkfile 'twb/util/docprep'
54
- checkfile 'twb/analysis/documentedfieldsmarkdownemitter'
55
- checkfile 'twb/analysis/annotatedfieldscsvemitter'
56
- checkfile 'twb/analysis/WorkbookSummaryAnalyzer'
57
- checkfile 'twb/analysis/calculatedfields/calculatedfieldsanalyzer'
58
- checkfile 'twb/analysis/calculatedfields/groupfieldsanalyzer'
59
- checkfile 'twb/analysis/calculatedfields/markdownemitter'
60
- checkfile 'twb/analysis/calculatedfields/csvemitter'
61
- checkfile 'twb/analysis/datasources/DataSourceFieldsCSVEmitter'
62
- checkfile 'twb/analysis/datasources/DataSourceTableFieldsCSVEmitter'
63
- checkfile 'twb/analysis/datasources/categoricalColorCodingAnalyzer'
64
- checkfile 'twb/analysis/datasources/googlesheetdatasourcesanalyzer'
65
- checkfile 'twb/analysis/datasources/parametersanalyzer'
66
- checkfile 'twb/analysis/datasources/DataSourceOriginsAnalyzer'
67
- checkfile 'twb/analysis/Sheets/WorksheetDataStructureCSVEmitter'
68
- checkfile 'twb/analysis/Sheets/sheetfiltersanalyzer'
69
- checkfile 'twb/analysis/Sheets/sheetfieldsanalyzer'
70
- checkfile 'twb/analysis/Sheets/dashsheetsanalyzer'
22
+ Dir.glob('**/*.rb') { |file| puts file if file =~ /[A-Z]/ }
23
+
71
24
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twb
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.5.5
4
+ version: 4.5.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Gerrard
@@ -59,29 +59,28 @@ extra_rdoc_files: []
59
59
  files:
60
60
  - lib/t.rb
61
61
  - lib/twb.rb
62
- - lib/twb/TwbTest.rb
63
62
  - lib/twb/action.rb
64
- - lib/twb/analysis/CalculatedFields/calculatedfieldsanalyzer.rb
65
- - lib/twb/analysis/CalculatedFields/csvemitter.rb
66
- - lib/twb/analysis/CalculatedFields/groupfieldsanalyzer.rb
67
- - lib/twb/analysis/CalculatedFields/markdownemitter.rb
68
- - lib/twb/analysis/DataSources/categoricalcolorcodinganalyzer.rb
69
- - lib/twb/analysis/DataSources/dataSourcesLocationsAnalyzer.rb
70
- - lib/twb/analysis/DataSources/datasourcefieldscsvemitter.rb
71
- - lib/twb/analysis/DataSources/datasourceoriginsanalyzer.rb
72
- - lib/twb/analysis/DataSources/datasourcetablefieldscsvemitter.rb
73
- - lib/twb/analysis/DataSources/googlesheetdatasourcesanalyzer.rb
74
- - lib/twb/analysis/DataSources/parametersanalyzer.rb
75
- - lib/twb/analysis/DocumentedFieldsCSVEmitter.rb
76
- - lib/twb/analysis/Sheets/analyzeDashboardSheets.rb
77
- - lib/twb/analysis/Sheets/dashsheetsanalyzer.rb
78
- - lib/twb/analysis/Sheets/sheetfieldsanalyzer.rb
79
- - lib/twb/analysis/Sheets/sheetfiltersanalyzer.rb
80
- - lib/twb/analysis/Sheets/sheetfiltersanalyzerA.rb
81
- - lib/twb/analysis/Sheets/sheetsourcesanalyzer.rb
82
- - lib/twb/analysis/Sheets/worksheetdatastructurecsvemitter.rb
83
63
  - lib/twb/analysis/annotatedfieldscsvemitter.rb
64
+ - lib/twb/analysis/calculatedfields/calculatedfieldsanalyzer.rb
65
+ - lib/twb/analysis/calculatedfields/csvemitter.rb
66
+ - lib/twb/analysis/calculatedfields/groupfieldsanalyzer.rb
67
+ - lib/twb/analysis/calculatedfields/markdownemitter.rb
68
+ - lib/twb/analysis/datasources/categoricalcolorcodinganalyzer.rb
69
+ - lib/twb/analysis/datasources/datasourcefieldscsvemitter.rb
70
+ - lib/twb/analysis/datasources/datasourceoriginsanalyzer.rb
71
+ - lib/twb/analysis/datasources/datasourceslocationsanalyzer.rb
72
+ - lib/twb/analysis/datasources/datasourcetablefieldscsvemitter.rb
73
+ - lib/twb/analysis/datasources/googlesheetdatasourcesanalyzer.rb
74
+ - lib/twb/analysis/datasources/parametersanalyzer.rb
75
+ - lib/twb/analysis/documentedfieldscsvemitter.rb
84
76
  - lib/twb/analysis/documentedfieldsmarkdownemitter.rb
77
+ - lib/twb/analysis/sheets/analyzedashboardsheets.rb
78
+ - lib/twb/analysis/sheets/dashsheetsanalyzer.rb
79
+ - lib/twb/analysis/sheets/sheetfieldsanalyzer.rb
80
+ - lib/twb/analysis/sheets/sheetfiltersanalyzer.rb
81
+ - lib/twb/analysis/sheets/sheetfiltersanalyzera.rb
82
+ - lib/twb/analysis/sheets/sheetsourcesanalyzer.rb
83
+ - lib/twb/analysis/sheets/worksheetdatastructurecsvemitter.rb
85
84
  - lib/twb/analysis/workbooksummaryanalyzer.rb
86
85
  - lib/twb/calculatedfield.rb
87
86
  - lib/twb/codedfield.rb
@@ -95,14 +94,14 @@ files:
95
94
  - lib/twb/docdashboardwebvert.rb
96
95
  - lib/twb/field.rb
97
96
  - lib/twb/fieldcalculation.rb
98
- - lib/twb/findDSFields.rb
97
+ - lib/twb/finddsfields.rb
99
98
  - lib/twb/graph.rb
100
99
  - lib/twb/graphedges.rb
101
100
  - lib/twb/graphnode.rb
102
101
  - lib/twb/groupfield.rb
103
102
  - lib/twb/hashtohtml.rb
104
103
  - lib/twb/htmllistcollapsible.rb
105
- - lib/twb/identifyFields.rb
104
+ - lib/twb/identifyfields.rb
106
105
  - lib/twb/localfield.rb
107
106
  - lib/twb/mappedfield.rb
108
107
  - lib/twb/metadatafield.rb
@@ -114,12 +113,13 @@ files:
114
113
  - lib/twb/tabtool.rb
115
114
  - lib/twb/there.rb
116
115
  - lib/twb/twbcodedfield.rb
116
+ - lib/twb/twbtest.rb
117
117
  - lib/twb/util/cypher.rb
118
118
  - lib/twb/util/cypherpython.rb
119
119
  - lib/twb/util/docprep.rb
120
120
  - lib/twb/util/dotfilerenderer.rb
121
121
  - lib/twb/util/fielddomainloader.rb
122
- - lib/twb/util/ftpPublisher.rb
122
+ - lib/twb/util/ftppublisher.rb
123
123
  - lib/twb/util/gml.rb
124
124
  - lib/twb/util/gmledge.rb
125
125
  - lib/twb/util/graph.rb
@@ -128,11 +128,11 @@ files:
128
128
  - lib/twb/util/graphnode.rb
129
129
  - lib/twb/util/hashtohtml.rb
130
130
  - lib/twb/util/htmllistcollapsible.rb
131
- - lib/twb/util/joinUtilities.rb
131
+ - lib/twb/util/joinutilities.rb
132
132
  - lib/twb/util/tabgraph.rb
133
- - lib/twb/util/twbDashSheetDataDotRenderer.rb
134
- - lib/twb/util/twbDashesSheetDataDotBuilder.rb
133
+ - lib/twb/util/twbdashessheetdatadotbuilder.rb
135
134
  - lib/twb/util/twbdashsheetdatadotbuilder.rb
135
+ - lib/twb/util/twbdashsheetdatadotrenderer.rb
136
136
  - lib/twb/util/xraydashboards.rb
137
137
  - lib/twb/window.rb
138
138
  - lib/twb/workbook.rb
@@ -1,524 +0,0 @@
1
- # calculatedfieldsanalyzer.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
- # require 'nokogiri'
17
- # require 'twb'
18
- # require 'set'
19
- require 'csv'
20
-
21
- module Twb
22
- module Analysis
23
-
24
- class CalculatedFieldsAnalyzer
25
-
26
- include TabTool
27
- include Graph
28
-
29
- attr_reader :calculatedFieldsCount, :referencedFieldsCount, :metrics
30
- attr_accessor :ttdocdir
31
-
32
- @@ttlogfile = 'CalculatedFieldsAnalyzer.ttlog'
33
- @@gvDotLocation = 'C:\\tech\\graphviz\\Graphviz2.38\\bin\\dot.exe'
34
- @@processName = '.CalculatedFields'
35
-
36
- @@calcFieldsCSVFileName = 'CalculatedFields.csv'
37
- @@calcFieldsCSVFileHeader = ['Record #',
38
- 'Workbook',
39
- 'Workbook Modified',
40
- 'Data Source', 'Data Source Caption', 'Data Source Name (tech)',
41
- 'Field Name', 'Field Caption', 'Field Name (tech)',
42
- 'Data Source + Field Name (tech)',
43
- 'Data Type', 'Role', 'Type',
44
- 'Class',
45
- 'Scope Isolation',
46
- 'Formula Length',
47
- 'Formula',
48
- 'Formula (tech)',
49
- 'Formula Comments',
50
- 'Formula LOD?'
51
- ]
52
-
53
- @@calcLinesCSVFileName = 'CalculatedFieldsFormulaLines.csv'
54
- @@calcLinesCSVFileHeader = ['Record #',
55
- 'Workbook',
56
- 'Workbook Modified',
57
- 'Data Source', 'Data Source Caption', 'Data Source Name (tech)',
58
- 'Field Name', 'Field Caption', 'Field Name (tech)',
59
- 'Formula', 'Formula Line #', 'Formula Line'
60
- ]
61
-
62
- @@formFieldsCSVFileName = 'CalculatedFieldsReferenced.csv'
63
- @@formFieldsCSVFileHeader = ['Record #',
64
- 'Workbook',
65
- 'Workbook Modified',
66
- 'Data Source',
67
- 'Field - Calculated',
68
- 'Formula (tech)',
69
- 'Formula',
70
- 'Field - Referenced (tech)',
71
- 'Field - Referenced',
72
- 'Data Source + Field - Referenced',
73
- 'Table'
74
- ]
75
-
76
- @techUINames = {}
77
- @fieldTables = {}
78
-
79
-
80
- @@dotHeader = <<DOTHEADER
81
- digraph g {
82
- graph [rankdir="LR" splines=line];
83
- node [shape="box" width="2"];
84
-
85
- DOTHEADER
86
-
87
- def initialize(**args)
88
- @args = args
89
- @recordDir = !@args.nil? && @args[:recordDir] == true
90
- @ttdocdir = @args[:ttdocdir]
91
- @csvAdd = @args[:csvMode] == :add
92
- @csvMode = @csvAdd ? 'a' : 'w'
93
- init
94
- @funcdoc = {:class=>self.class, :blurb=>'Analyze Calculated Fields', :description=>'Calculated fields can be complex, this tool provides robust coverage.',}
95
- #-- CSV records collectors
96
- @csvCalculatedFields = Array.new
97
- @csvFormulaFields = Array.new
98
- @csvFormulaLines = Array.new
99
- #-- Counters setup --
100
- @twbCount = 0
101
- @dataSourcesCount = 0
102
- @calculatedFieldsCount = 0
103
- @referencedFieldsCount = 0
104
- #--
105
- @referencedFields = SortedSet.new
106
- #--
107
- twbdirLabel = @recordDir.nil? ? nil : 'Workbook Dir'
108
- @csvCF = initCSV(@@calcFieldsCSVFileName, 'Calculated fields and their formulas.', @@calcFieldsCSVFileHeader )
109
- @csvCFLs = initCSV(@@calcLinesCSVFileName, "Calculated fields and their formulas' individual lines.", @@calcLinesCSVFileHeader )
110
- @csvFF = initCSV(@@formFieldsCSVFileName, 'Calculated fields and the fields their formulas reference.', @@formFieldsCSVFileHeader )
111
- # TODO migrate addition of 'Workbook Dir' to CSV header to TabTool
112
- #--
113
- @localEmit = false
114
- @imageFiles = Array.new
115
- #--
116
- @doGraph = config(:dograph)
117
- end
118
-
119
- def processTWB workbook
120
- @twb = workbook.is_a?(String) ? Twb::Workbook.new(workbook) : workbook
121
- throw Exception unless @twb.is_a? Twb::Workbook
122
- emit "- Workbook: #{workbook}"
123
- emit " version: #{@twb.version}"
124
- @twbDir = @twb.dir #File.dirname(File.expand_path(workbook))
125
- @modTime = @twb.modtime
126
- @edges = Set.new
127
- #-- processing
128
- dss = @twb.datasources
129
- # puts " # data sources: #{dss.length}"
130
- @twbRootFields = Set.new
131
- @twbFields = Hash.new { |h,k| h[k] = [] }
132
- @nodes = Set.new
133
- dss.each do |ds|
134
- @dataSourcesCount += 1
135
- # puts "\t\t - #{ds.uiname} \t\t #{ds.calculatedFields.length}"
136
- next if ds.Parameters? # don't process the Parameters data source - Parameters' fields aren't Calculated fields for our purposes
137
- # dataSourceNode = Twb::Util::Graphnode.new(name: ds.uiname, id: ds.id, type: ds, properties: {workbook: workbook})
138
- # @nodes.add dataSourceNode
139
- # ds.calculatedFields.each do |calcField|
140
- # end
141
- processDataSource ds
142
- end
143
- mapTwb
144
- emitGml
145
- @twbCount += 1
146
- finis
147
- end
148
-
149
- def metrics
150
- @metrics ||= loadMetrics
151
- end
152
-
153
- def loadMetrics
154
- @metrics = {
155
- '# of Workbooks' => @twbCount,
156
- '# of Data Sources' => @dataSourcesCount,
157
- '# of Calculated Fields' => @calculatedFieldsCount,
158
- '# of Referenced Fields' => @referencedFieldsCount,
159
- }
160
- end
161
-
162
- #-- private methods begin here, to end of class
163
-
164
- private
165
-
166
- def emitGml
167
- gml = Twb::Util::GML.new
168
- gml.fileName = @twb.name
169
- gml.nodes = @nodes
170
- gml.edges = @edges
171
- gml.render
172
- end
173
-
174
- def processDataSource ds
175
- emit "======= DATA SOURCE: #{ds.uiname} ====== "
176
- dsNodes = Set.new
177
- dsEdges = Set.new
178
- dsFields = {}
179
- @twbFields[ds.uiname] = dsFields
180
- calculatedFields = SortedSet.new
181
- fieldFormulaLines = Array.new
182
- referencedFields = SortedSet.new
183
- # if @doGraph
184
- dataSourceNode = Twb::Util::Graphnode.new(name: ds.uiname, id: ds.id, type: ds, properties: {workbook: @twb.name})
185
- @nodes.add dataSourceNode
186
- # end
187
- #-- process Calculatred Fields
188
- ds.calculatedFields.each do |calcField|
189
- emit "Calculated Field: #{calcField}"
190
- calculatedFields.add calcField.id
191
- dsFields[calcField.uiname] = calcField
192
- # if @doGraph
193
- calcFieldNode = Twb::Util::Graphnode.new(name: calcField.uiname, id: calcField.id, type: calcField, properties: {:DataSource => ds.uiname})
194
- @nodes.add calcFieldNode
195
- dsFieldEdge = Twb::Util::Graphedge.new(from: dataSourceNode, to: calcFieldNode, relationship: 'contains')
196
- @edges.add dsFieldEdge
197
- # end
198
- calculation = calcField.calculation
199
- if calculation.has_formula
200
- #-- collect field formulas as single lines
201
- @csvCalculatedFields.push [
202
- @calculatedFieldsCount += 1,
203
- @twb.name,
204
- @modTime,
205
- ds.uiname,
206
- ds.caption,
207
- ds.name,
208
- calcField.uiname,
209
- calcField.caption,
210
- calcField.name,
211
- ds.name + '::' + calcField.name,
212
- calcField.datatype,
213
- calcField.role,
214
- calcField.type,
215
- calculation.class,
216
- calculation.scopeIsolation,
217
- calculation.formulaFlat.length,
218
- calculation.formulaFlatResolved,
219
- calculation.formulaFlat,
220
- calculation.comments,
221
- calculation.is_lod
222
- ]
223
- #-- collect individual formula lines
224
- flnum = 0
225
- emit "@@ calcField.uiname: #{calcField.uiname}"
226
- calculation.formulaResolvedLines.each do |fl|
227
- emit "@@ resolved line:: => '#{fl}'"
228
- fieldFormulaLines << [ @calculatedFieldsCount, # 'Calc Field #',
229
- @twb.name, # 'Workbook',
230
- @modTime,
231
- ds.uiname, # 'Data Source',
232
- ds.caption, # 'Data Source Caption',
233
- ds.name, # 'Data Source Name (tech)',
234
- calcField.uiname, # 'Field Name',
235
- calcField.caption, # 'Field Caption',
236
- calcField.name, # 'Field Name (tech)',
237
- calcField.calculation.formulaFlatResolved, # 'Formula'
238
- flnum += 1, # 'Formula Line #',
239
- fl.start_with?(" ") ? "'#{fl}" : fl # 'Formula Line' - THIS IS A STUPID HACK NEEDED BECAUSE TABLEAU STRIPS LEADING BLANKS FROM CSV VALUES
240
- ]
241
- end
242
- #-- collect fields referenced in formula
243
- emit "# Calculated Fields: #{calculation.calcFields.length}"
244
- calculation.calcFields.each do |rf|
245
- emit " referenced field ::'#{rf}'"
246
- emit " referenced field.name ::'#{rf.name.nil?}' :: '#{rf.name}'"
247
- emit " referenced field.uiname::'#{rf.uiname}'"
248
- # if @doGraph
249
- unless rf.uiname.nil?
250
- properties = {'DataSource' => ds.uiname, 'DataSourceReference' => 'local', :source => rf}
251
- refFieldNode = Twb::Util::Graphnode.new(name: rf.uiname, id: rf.id, type: rf.type, properties: properties)
252
- @nodes.add refFieldNode
253
- fieldFieldEdge = Twb::Util::Graphedge.new(from: calcFieldNode, to: refFieldNode, relationship: 'references')
254
- @edges.add fieldFieldEdge
255
- end
256
- # end
257
- referencedFields.add rf.id
258
- refFieldTable = ds.fieldTable(rf.name)
259
- emit "refFieldTable.nil? : #{refFieldTable.nil?}"
260
- unless refFieldTable.nil?
261
- tableID = refFieldTable + ':::' + ds.uiname
262
- tableName = "||#{refFieldTable}||"
263
- # if @doGraph
264
- tableNode = Twb::Util::Graphnode.new(name: tableName, id: tableID, type: :DBTable, properties: properties)
265
- @nodes.add tableNode
266
- fieldFieldEdge = Twb::Util::Graphedge.new(from: refFieldNode, to: tableNode, relationship: 'is a field in')
267
- @edges.add fieldFieldEdge
268
- # end
269
- # fldToDsNode = tableNode
270
- end
271
- @csvFormulaFields << [
272
- @referencedFieldsCount += 1,
273
- @twb.name,
274
- @modTime,
275
- ds.uiname,
276
- calcField.uiname,
277
- calculation.formulaFlat,
278
- calculation.formulaFlatResolved,
279
- rf.name,
280
- rf.uiname,
281
- rf.id,
282
- refFieldTable
283
- ]
284
- end # resolvedFields.each do
285
- end # if calculation.has_formula
286
- end # ds.calculatedFields.each
287
-
288
- dsRootFields = calculatedFields - referencedFields
289
- @referencedFields.merge referencedFields
290
- @twbRootFields.merge dsRootFields
291
- if @doGraph
292
- cypher @twb.name
293
- cypherPy @twb.name
294
- end
295
- emit "#######################"
296
- #--
297
- #-- record calculated fields
298
- twbDirCSV = @recordDir.nil? ? nil : @twbDir
299
- emit "@@ record calculated fields ds: #{ds.uiname}"
300
- @csvCalculatedFields.each do |r|
301
- @csvCF << r
302
- end
303
- #-- record individual formula lines
304
- emit "@@ individual formula lines ds: #{ds.uiname}"
305
- fieldFormulaLines.each do |ffl|
306
- @csvCFLs << ffl
307
- end
308
- #-- record formula-referenced fields
309
- emit "@@ formula-referenced fields ds: #{ds.uiname}"
310
- @csvFormulaFields.each do |r|
311
- @csvFF << r
312
- end
313
- #--
314
- return @imageFiles
315
- end # def processDataSource
316
-
317
- def emitCalcfield calcField
318
- emit "\t FIELD cap :: #{calcField.caption} "
319
- emit "\t tname:: #{calcField.name}"
320
- emit "\t uiname:: #{calcField.uiname}"
321
- emit "\t formula:: #{calculation.formulaFlat}"
322
- end
323
-
324
- def mapTwb
325
- twb = @twb.name
326
- rootFields = @twbRootFields
327
- dotStuff = initDot twb
328
- dotFile = dotStuff[:file]
329
- dotFileName = dotStuff[:name]
330
- dotFile.puts "\n // subgraph cluster_1 {"
331
- dotFile.puts " // color= grey;"
332
- dotFile.puts ""
333
- edgesAsStrings = SortedSet.new
334
- # this two step process coalesces the edges into a unique set, avoiding duplicating the dot
335
- # file entries, and can be shrunk when graph edges expose the bits necessary for management by Set
336
- emit "\n========================\nLoading Edges\n========================\n From DC? Referenced? Edge \n %s %s %s" % ['--------', '-----------', '-'*45]
337
- @edges.each do |e|
338
- # don't want to emit edge which is from a Data Connection to a
339
- # Calculated Field which is also referenced by another calculated field
340
- isFromDC = e.from.type == :TwbDataConnection
341
- isRefField = @referencedFields.include?(e.to.id)
342
- edgesAsStrings.add(e.dot) unless isFromDC && isRefField
343
- # emit " ES #{e.dot}"
344
- # emit " ES from #{e.from}"
345
- # emit " ES to #{e.to}"
346
- end
347
- emit "------------------------\n "
348
- edgesAsStrings.each do |es|
349
- dotFile.puts " #{es}"
350
- end
351
- emit "========================\n "
352
- dotFile.puts ""
353
- dotFile.puts " // }"
354
- dotFile.puts "\n\n // 4 NODES --------------------------------------------------------------------"
355
- @nodes.each do |n|
356
- dotFile.puts n.dotLabel
357
- end
358
- dotFile.puts "\n\n // 5--------------------------------------------------------------------"
359
- emitTypes( dotFile )
360
- closeDot( dotFile, twb )
361
- emit "Rendering DOT file - #{twb}"
362
- renderDot(twb,dotFileName,'pdf')
363
- renderDot(twb,dotFileName,'png')
364
- renderDot(twb,dotFileName,'svg')
365
- # emitEdges
366
- end
367
-
368
- def cypher twbName
369
- if @doGraph
370
- cypher = Twb::Util::Cypher.new
371
- cypher.fileName = "#{twbName}.calcFields"
372
- cypher.nodes = @nodes
373
- cypher.edges = @edges
374
- cypher.render
375
- end
376
- end
377
-
378
- def cypherPy twbName
379
- if @doGraph
380
- cypher = Twb::Util::CypherPython.new
381
- cypher.fileName = "#{twbName}.calcFields"
382
- cypher.nodes = @nodes
383
- cypher.edges = @edges
384
- cypher.render
385
- end
386
- end
387
-
388
- # def graphEdges twb
389
- # # graphFile = File.new(twb + '.cypher', 'w')
390
- # # # graphFile.puts "OKEY DOKE, graphing away"
391
- # # cypherCode = Set.new
392
- # # @edges.each do |edge|
393
- # # cypherCode.add edge.from.cypherCreate
394
- # # cypherCode.add edge.to.cypherCreate
395
- # # cypherCode.add edge.cypherCreate
396
- # # end
397
- # # cypherCode.each do |cc|
398
- # # graphFile.puts cc
399
- # # end
400
- # # graphFile.puts "\nreturn *"
401
- # # graphFile.close unless graphFile.nil?
402
- # # @imageFiles << File.basename(graphFile)
403
- # end
404
-
405
- def emitEdges
406
- emit " %-15s %s" % ['type', 'Edge']
407
- emit " %-15s %s" % ['-'*15, '-'*35]
408
- @edges.each do |edge|
409
- emit " %-15s %s" % [edge.from.type, edge.from]
410
- emit " %-15s %s" % [edge.to.type, edge.to]
411
- emit "\n "
412
- end
413
- end
414
-
415
- def emitTypes dotFile
416
- typedNodes = {}
417
- dotFile.puts "\n\n // 2--------------------------------------------------------------------"
418
- @edges.each do |edge|
419
- emit " EDGE :: #{edge}"
420
- loadNodeType typedNodes, edge.from
421
- loadNodeType typedNodes, edge.to
422
- end
423
- typedNodes.each do |type, nodes|
424
- # emit "+++++++++ typedNodes of '#{type}'' "
425
- # nodes.each do |node|
426
- # emit " -n- #{node}"
427
- # end
428
- rankSame(dotFile, type, nodes) unless type.eql? 'CalculatedField' # == :CalculatedField
429
- end
430
- # labelTypes dotFile, edges
431
- end
432
-
433
- def loadNodeType set, node
434
- type = node.type
435
- set[type] = Set.new unless set.include? type
436
- set[type].add node
437
- end
438
-
439
- @@unrankedTypes = ['CalculationField']
440
- def rankSame dotFile, type, nodes
441
- return if @@unrankedTypes.include? type.to_s
442
- @lines = SortedSet.new
443
- nodes.each do |node|
444
- @lines << node.id
445
- end
446
- dotFile.puts "\n // '#{type}' --------------------------------------------------------------------"
447
- dotFile.puts "\n {rank=same "
448
- @lines.each do |line|
449
- dotFile.puts " \"#{line}\""
450
- end
451
- dotFile.puts " }"
452
- end
453
-
454
- def rankRootFields dotFile, dsRootFields
455
- dotFile.puts "\n // Unreferenced (root) Calculated Fields -----------------------------------------"
456
- dotFile.puts "\n {rank=same "
457
- dsRootFields.each do |rf|
458
- emit "ROOT FIELD: #{rf.class} :: #{rf}"
459
- dotFile.puts " \"#{rf}\""
460
- end
461
- dotFile.puts " }"
462
- end
463
-
464
- def labelTypes dotFile
465
- fromTos = Set.new
466
- @edges.each do |edge|
467
- # fromTos.add "\"Alien Data Source\" -> \"Alien Data Source\""
468
- fromTos.add "\"#{edge.from.type}\""
469
- fromTos.add "\"#{edge.to.type}\""
470
- end
471
- return if fromTos.empty?
472
- dotFile.puts "\n // 3--------------------------------------------------------------------"
473
- dotFile.puts ' subgraph cluster_0 {'
474
- dotFile.puts ' color=white;'
475
- dotFile.puts ' node [shape="box3d" style="filled" ];'
476
- fromTos.each do |ft|
477
- dotFile.puts " #{ft}"
478
- end
479
- dotFile.puts ' }'
480
- end
481
-
482
- def initDot twb
483
- dotFileName = docFile("#{twb}#{@@processName}.dot")
484
- dotFile = File.open(dotFileName,'w')
485
- dotFile.puts @@dotHeader
486
- return {:file => dotFile, :name => dotFileName}
487
- end
488
-
489
- def closeDot dotFile, twb
490
- dotFile.puts ' '
491
- dotFile.puts '// -------------------------------------------------------------'
492
- dotFile.puts ' '
493
- dotFile.puts ' subgraph cluster_1 {'
494
- # dotFile.puts ' color=white;'
495
- dotFile.puts ' style=invis;'
496
- # dotFile.puts ' border=0;'
497
- dotFile.puts ' node [border=blue];'
498
- dotFile.puts ' '
499
- dotFile.puts ' "" [style=invis]'
500
- dotFile.puts " \"Tableau Tools\\nCalculated Fields Map\\nWorkbook '#{twb}'\\n#{Time.new.ctime}\" [penwidth=0]"
501
- # dotFile.puts " \"Tableau Tools Workbook Calculated Fields Map\\n#{Time.new.ctime}\" -> \"\" [style=invis]"
502
- dotFile.puts ' '
503
- dotFile.puts ' }'
504
- dotFile.puts ' '
505
- dotFile.puts '}'
506
- dotFile.close
507
- end
508
-
509
-
510
- def renderDot twb, dot, format
511
- imageType = '-T' + format
512
- imageFile = './ttdoc/' + twb + @@processName + 'Graph.' + format
513
- imageParam = '-o"' + imageFile + '"'
514
- emit "system #{@@gvDotLocation} #{imageType} #{imageParam} \"#{dot}\""
515
- system "#{@@gvDotLocation} #{imageType} #{imageParam} \"#{dot}\""
516
- emit " - #{imageFile}"
517
- @imageFiles << imageFile
518
- return imageFile
519
- end
520
-
521
- end # class
522
-
523
- end # module Analysis
524
- end # module Twb