twb 4.6.3 → 4.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29ec473a3ccc02db6111d652d70245be94d4dc3f70b949efddfa2bf34ab992d1
4
- data.tar.gz: ffc10036c2e17663a6626cdb7cbc525da061971321c11ed09939e87cbe8f3000
3
+ metadata.gz: 9ba8a4bcf6b220aaf9d3b94a91a903ec055a1637d7d78c063a58a5def3027844
4
+ data.tar.gz: a7f76a9e0fb057cf7aee2c38c82b974e0a59575eb955bd41636e79a38a251f65
5
5
  SHA512:
6
- metadata.gz: f1078e523985681ed1ce0a209cec2c5826733c3147f8c418d576b8844e58df9adf87eed923289047f8fac037d212b4adffdd3f6316fa93f4e172c6119b86c0ce
7
- data.tar.gz: 325066960bf31e5fc0b0cc90bbad7affc5128481e864e388408b78cf1e534b515f629eddc87e89478bdc309be2a29e5731342cec8c7b83526629ef41baad6990
6
+ metadata.gz: 685229ff4ae9181176c42fb85cf9900e64823fa2cbcf4a8ef49a48b0ebbfa96ecf491e27e88c545478a2e4ccad0ba314f648baa28406964032d39e3daefe0904
7
+ data.tar.gz: 86eb832a11d3bb87a66835f29d5eb312477f55421e007dea39c8178568573d39f0ff5d529ab22dfbfe53128b6a1b1145948b5f92bd785cc780b57c3df76d7137
data/lib/twb.rb CHANGED
@@ -57,6 +57,7 @@ require_relative 'twb/analysis/calculatedfields/groupfieldsanalyzer'
57
57
  require_relative 'twb/analysis/calculatedfields/markdownemitter'
58
58
  require_relative 'twb/analysis/calculatedfields/csvemitter'
59
59
  # require_relative 'twb/analysis/datasources/datasourcefieldscsvemitter'
60
+ require_relative 'twb/analysis/datasources/datasourcesenumerator.rb'
60
61
  require_relative 'twb/analysis/datasources/datasourcefieldsanalyzer'
61
62
  require_relative 'twb/analysis/datasources/datasourcetablefieldscsvemitter'
62
63
  require_relative 'twb/analysis/datasources/categoricalcolorcodinganalyzer'
@@ -67,10 +68,11 @@ require_relative 'twb/analysis/sheets/worksheetdatastructurecsvemitter'
67
68
  require_relative 'twb/analysis/sheets/sheetfiltersanalyzer'
68
69
  require_relative 'twb/analysis/sheets/sheetfieldsanalyzer'
69
70
  require_relative 'twb/analysis/sheets/dashsheetsanalyzer'
71
+ require_relative 'twb/analysis/sheets/sheetsintooltipanalyzer'
70
72
 
71
73
 
72
74
  # Represents Tableau Workbooks, their contents, and classes that analyze and manipulate them.
73
75
  #
74
76
  module Twb
75
- VERSION = '4.6.3'
77
+ VERSION = '4.7.1'
76
78
  end
@@ -43,7 +43,8 @@ module Analysis
43
43
  'Data Type', 'Role', 'Type',
44
44
  'Class',
45
45
  'Scope Isolation',
46
- 'Formula Length',
46
+ 'Formula # Chars',
47
+ 'Formula # Lines',
47
48
  'Formula',
48
49
  'Formula (tech)',
49
50
  'Formula Comments',
@@ -51,7 +52,7 @@ module Analysis
51
52
  ]
52
53
 
53
54
  @@calcLinesCSVFileName = 'CalculatedFieldsFormulaLines.csv'
54
- @@calcLinesCSVFileHeader = ['Record #',
55
+ @@calcLinesCSVFileHeader = ['Calc Field #',
55
56
  'Workbook',
56
57
  # 'Workbook Modified',
57
58
  'Data Source', 'Data Source Caption', 'Data Source Name (tech)',
@@ -94,9 +95,8 @@ DOTHEADER
94
95
  init
95
96
  @funcdoc = {:class=>self.class, :blurb=>'Analyze Calculated Fields', :description=>'Calculated fields can be complex, this tool provides robust coverage.',}
96
97
  #-- CSV records collectors
97
- @csvCalculatedFields = Array.new
98
- @csvFormulaFields = Array.new
99
- @csvFormulaLines = Array.new
98
+ @csvFormulaFields = Set.new
99
+ @csvFormulaLines = Set.new
100
100
  #-- Counters setup --
101
101
  @twbCount = 0
102
102
  @dataSourcesCount = 0
@@ -153,7 +153,6 @@ DOTHEADER
153
153
 
154
154
  def loadMetrics
155
155
  @metrics = {
156
- '# of Workbooks' => @twbCount,
157
156
  '# of Data Sources' => @dataSourcesCount,
158
157
  '# of Calculated Fields' => @calculatedFieldsCount,
159
158
  '# of Referenced Fields' => @referencedFieldsCount,
@@ -166,7 +165,7 @@ DOTHEADER
166
165
 
167
166
  def emitGml
168
167
  gml = Twb::Util::GML.new
169
- gml.fileName = @twb.name
168
+ gml.fileName = "#{@twb.name}.calculatedFields"
170
169
  gml.nodes = @nodes
171
170
  gml.edges = @edges
172
171
  gmlFile = gml.render # resets gml.fileName in preparing it for output
@@ -182,6 +181,8 @@ DOTHEADER
182
181
  calculatedFields = SortedSet.new
183
182
  fieldFormulaLines = Array.new
184
183
  referencedFields = SortedSet.new
184
+ @csvCalculatedFields = Set.new
185
+
185
186
  # if @doGraph
186
187
  dataSourceNode = Twb::Util::Graphnode.new(name: ds.uiname, id: ds.id, type: ds, properties: {workbook: @twb.name})
187
188
  @nodes.add dataSourceNode
@@ -200,28 +201,32 @@ DOTHEADER
200
201
  calculation = calcField.calculation
201
202
  if calculation.has_formula
202
203
  #-- collect field formulas as single lines
203
- @csvCalculatedFields.push [
204
- @calculatedFieldsCount += 1,
205
- @twb.name,
206
- # @modTime,
207
- ds.uiname,
208
- ds.caption,
209
- ds.name,
210
- calcField.uiname,
211
- calcField.caption,
212
- calcField.name,
213
- ds.name + '::' + calcField.name,
214
- calcField.datatype,
215
- calcField.role,
216
- calcField.type,
217
- calculation.class,
218
- calculation.scopeIsolation,
219
- calculation.formulaFlat.length,
220
- calculation.formulaFlatResolved,
221
- calculation.formulaFlat,
222
- calculation.comments,
223
- calculation.is_lod
224
- ]
204
+ csvRec = [
205
+ @calculatedFieldsCount += 1,
206
+ @twb.name,
207
+ # @modTime,
208
+ ds.uiname,
209
+ ds.caption,
210
+ ds.name,
211
+ calcField.uiname,
212
+ calcField.caption,
213
+ calcField.name,
214
+ ds.name + '::' + calcField.name,
215
+ calcField.datatype,
216
+ calcField.role,
217
+ calcField.type,
218
+ calculation.class,
219
+ calculation.scopeIsolation,
220
+ calculation.formulaFlat.length,
221
+ calculation.formulaLinesCount,
222
+ calculation.formulaFlatResolved,
223
+ calculation.formulaFlat.strip,
224
+ calculation.comments,
225
+ calculation.is_lod
226
+ ]
227
+ # puts csvRec.to_s
228
+ # puts "incl? #{@csvCalculatedFields.include?(csvRec)}"
229
+ @csvCalculatedFields << csvRec
225
230
  #-- collect individual formula lines
226
231
  flnum = 0
227
232
  emit "@@ calcField.uiname: #{calcField.uiname}"
@@ -42,7 +42,7 @@ module Analysis
42
42
 
43
43
  def metrics
44
44
  {
45
- '# of Workbooks' => @twbCount,
45
+ # '# of Workbooks' => @twbCount,
46
46
  '# of Data Sources' => @dsCount,
47
47
  '# of Group Fields' => @gfCount,
48
48
  '# of Group Field Members' => @gfmCount
@@ -41,7 +41,7 @@ module Analysis
41
41
 
42
42
  def metrics
43
43
  {
44
- '# of Workbooks' => @twbcount,
44
+ # '# of Workbooks' => @twbcount,
45
45
  '# of data sources' => @dscnt,
46
46
  '# of Worksheet Fields' => @fieldsCnt
47
47
  }
@@ -49,6 +49,7 @@ module DataSources
49
49
  'Workbook',
50
50
  'Data Source',
51
51
  'Field',
52
+ 'Field - tech',
52
53
  'Field - source',
53
54
  'Field - class',
54
55
  'Field - path',
@@ -56,21 +57,31 @@ module DataSources
56
57
  'Property - Value'
57
58
  ]
58
59
 
59
- # @@techFileType = 'TwbDataSourceFieldsTech'
60
- # @@techFileName = @@techFileType + '.csv'
61
- # @@techHeader = ['Field #',
62
- # 'Workbook',
63
- # 'Workbook Dir',
64
- # 'Data Source',
65
- # 'Field',
66
- # 'Field Type',
67
- # 'Property - Name',
68
- # 'Property - Value'
69
- # ]
60
+ @@colsFileType = 'DataSourceFields'
61
+ @@colsFileName = @@colsFileType + '.csv'
62
+ @@colsHeader = [
63
+ 'Field #',
64
+ 'Workbook',
65
+ 'Data Source',
66
+ 'Field - tech',
67
+ 'Caption',
68
+ 'Field',
69
+ 'Alias',
70
+ 'Datatype',
71
+ 'Datatype-customized',
72
+ 'Default Format',
73
+ 'Param-domain-type',
74
+ 'Role',
75
+ 'Type',
76
+ 'Calculated?',
77
+ 'Value',
78
+ 'Hidden',
79
+ 'Path'
80
+ ]
70
81
 
71
82
  def initialize(**args)
83
+ emit "DataSourceFieldsAnalyzer initialize(**args) args: #{args}"
72
84
  @args = args
73
- # puts "@args: #{@args}"
74
85
  @recordDir = !@args.nil? && @args[:recordDir] == true
75
86
  @ttdocdir = @args[:ttdocdir]
76
87
  @csvAdd = args[:csvMode] == :add
@@ -78,36 +89,28 @@ module DataSources
78
89
  init
79
90
  @funcdoc = {:class=>self.class, :blurb=>'Analyze Data Source Fields', :description=>'Documents Data Source fields, with (some) technical information.',}
80
91
  #--
81
- docFileName = docFile(@@fullFileName)
82
- @csvFile = CSV.open( docFileName,@csvMode)
92
+ detailsFileName = docFile(@@fullFileName)
93
+ @csvFile = CSV.open( detailsFileName,@csvMode )
94
+ #--
95
+ colsFileName = docFile(@@colsFileName)
96
+ @colsFile = CSV.open( colsFileName, @csvMode )
97
+
98
+ #--
83
99
  unless @csvAdd
84
100
  if @recordDir
85
101
  @csvFile << @@fullHeader + ['Workbook Dir']
102
+ @colsFile << @@colsHeader + ['Workbook Dir']
86
103
  else
87
104
  @csvFile << @@fullHeader
105
+ @colsFile << @@colsHeader
88
106
  end
89
107
  end
90
- addDocFile @csvFile, docFileName, "Workbooks, Data Sources, and Fields."
108
+ addDocFile @csvFile, detailsFileName, "Workbooks, Data Sources, and Fields' details (technical use)."
109
+ addDocFile @colsFile, colsFileName, "Workbooks, Data Sources, and Column Fields."
91
110
  #--
92
- # --
93
111
  @dsCount = 0
94
112
  @recNum = 0
95
- end
96
-
97
- def initializeX
98
- # @csvFile = CSV.open(@@csvFileName,'w')
99
- # @csvFile << @@csvHeader
100
- # @csvRecords = Set.new
101
- # puts "Opened: #{!@csvFile.nil?} - #{@@csvFileName}"
102
- # --
103
- @csvFileFull = CSV.open(@@fullFileName,'w')
104
- @csvFileFull << @@fullHeader
105
- puts "Opened: #{!@csvFileFull.nil?} - #{@@fullFileName} "
106
- # --
107
- # @csvFileTech = CSV.open(@@techFileName,'w')
108
- # @csvFileTech << @@techHeader
109
- # puts "Opened: #{!@csvFileTech.nil?} - #{@@techFileName}"
110
- # --
113
+ @colFldNum = 0
111
114
  end
112
115
 
113
116
  def self.csvHeader
@@ -126,12 +129,15 @@ module DataSources
126
129
  @twb = nil
127
130
  @twb = twb if twb.instance_of? Twb::Workbook
128
131
  @twb = Twb::Workbook.new(twb) if twb.instance_of? String
132
+ @twbName = @twb.name
133
+ @twbDir = @twb.dir
129
134
  raise ArgumentError.new("ERROR in Workbok processing: '#{twb}' must be a Workbook (class) or the name of a Workbook (String), is a #{twb.class} \n ") unless @twb.is_a? Twb::Workbook
130
135
  # --
131
136
  dss = @twb.datasources
132
137
  @fieldCnt = 0
133
138
  dss.each do |ds|
134
139
  @dsname = ds.uiname
140
+ processColumnFields ds
135
141
  # puts "\n -- #{ds.uiname} "
136
142
  # tables = Set.new
137
143
  # fields = {}
@@ -178,6 +184,44 @@ module DataSources
178
184
  end
179
185
  end # def processTwb twb
180
186
 
187
+ def processColumnFields ds
188
+ deepFields = {}
189
+ recordedFields = {}
190
+ ds.columnFields.each do |field|
191
+ if field.pathbare.eql? '/workbook/datasources/datasource/column'
192
+ recordColField field
193
+ recordedFields[field.name] = field
194
+ # print '.'
195
+ else
196
+ deepFields[field.name] = field
197
+ # print '-'
198
+ end
199
+ end
200
+ deepFields.each do |name,field|
201
+ unless recordedFields.has_key? name
202
+ recordColField(field)
203
+ recordedFields[field.name] = field
204
+ # print ':'
205
+ end
206
+ end
207
+ end
208
+
209
+ # @@colsHeader = ['Field #',
210
+ # 'Workbook',
211
+ # 'Data Source',
212
+ # 'Field - tech',
213
+ # 'caption',
214
+ # 'uiname',
215
+ # 'alias',
216
+ # 'datatype',
217
+ # 'datatype-customized',
218
+ # 'default-format',
219
+ # 'param-domain-type',
220
+ # 'role',
221
+ # 'type',
222
+ # 'value'
223
+ # ]
224
+
181
225
  def metrics
182
226
  {
183
227
  '# of Data Sources' => @dsCount,
@@ -185,8 +229,47 @@ module DataSources
185
229
  }
186
230
  end
187
231
 
232
+
233
+
188
234
  private
189
235
 
236
+ # def recordCSV record
237
+ # numberedRec = [@recNum+=1] + record
238
+ # if @recordDir
239
+ # @csvFile << numberedRec.push(@twb.dir)
240
+ # else
241
+ # @csvFile << numberedRec
242
+ # end
243
+ # end
244
+
245
+ def recordColField field
246
+ numberedRec = [
247
+ @colFldNum +=1,
248
+ @twbName,
249
+ @dsname,
250
+ field.name,
251
+ field.caption,
252
+ field.uiname,
253
+ field.alias,
254
+ field.dataType,
255
+ field.datatypeCustomized,
256
+ field.defaultFormat,
257
+ field.paramDomainType,
258
+ field.role,
259
+ field.type,
260
+ !field.calcField.nil?,
261
+ field.value,
262
+ field.hidden,
263
+ field.pathbare
264
+ ]
265
+ #--
266
+ if @recordDir
267
+ @colsFile << numberedRec.push(@twb.dir)
268
+ else
269
+ @colsFile << numberedRec
270
+ end
271
+ end
272
+
190
273
  def recordFieldFull field, source
191
274
  # print field.properties.nil? ? '-' : ":#{field.properties.length}"
192
275
  # puts field.properties
@@ -198,13 +281,14 @@ module DataSources
198
281
  # @twb.dir,
199
282
  @dsname,
200
283
  field.uiname,
284
+ field.name,
201
285
  source,
202
286
  field.class,
203
287
  field.node.path.to_s.gsub(/[0-9]/,'').gsub('[]',''),
204
288
  name,
205
289
  value
206
290
  ]
207
- csvRec << @twb.dir if @recordDir
291
+ csvRec << @twb.dir if @recordDir
208
292
  @csvFile << csvRec
209
293
  end
210
294
  end
@@ -51,7 +51,7 @@ module Analysis
51
51
 
52
52
  def metrics
53
53
  {
54
- '# of Workbooks' => @twbcount,
54
+ # '# of Workbooks' => @twbcount,
55
55
  '# of Data Sources' => @dsCnt,
56
56
  }
57
57
  end
@@ -0,0 +1,103 @@
1
+ # WorksheetFields.rb Copyright (C) 2017, 2018 Chris 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
+ require 'csv'
18
+
19
+ module Twb
20
+ module Analysis
21
+ module DataSources
22
+
23
+
24
+ class DataSourcesEnumerator
25
+
26
+ include TabTool
27
+
28
+ attr_accessor :localEmit
29
+
30
+ def initialize(**args)
31
+ @args = args
32
+ @recordDir = !@args.nil? && @args[:recordDir] == true
33
+ @ttdocdir = @args[:ttdocdir]
34
+ @csvAdd = args[:csvMode] == :add
35
+ @csvMode = @csvAdd ? 'a' : 'w'
36
+ init
37
+ @funcdoc = {:class=>self.class, :blurb=>"Enumerate Workbooks' Data Sources", :description=>'Documents Data Sources, recoring their names.',}
38
+ #--
39
+ docFileName = docFile('DataSources.csv')
40
+ @sheetFieldsCSV = CSV.open( docFileName,@csvMode)
41
+ unless @csvAdd
42
+ if @recordDir
43
+ @sheetFieldsCSV << ['Rec #','Workbook','Data Source','Data Source (tech)','Class','Extract?','# Connections','# Fields','Published?', '# Tables', '# Aliases', '# Groups', 'Workbook Dir']
44
+ else
45
+ @sheetFieldsCSV << ['Rec #','Workbook','Data Source','Data Source (tech)','Class','Extract?','# Connections','# Fields','Published?', '# Tables', '# Aliases', '# Groups']
46
+ end
47
+ end
48
+ addDocFile @sheetFieldsCSV, docFileName, "Workbooks and the Data Sources they contain."
49
+ #--
50
+ @dsCount = 0
51
+ @recNum = 0
52
+ end
53
+
54
+ def metrics
55
+ {
56
+ '# of Data Sources' => @dsCount,
57
+ }
58
+ end
59
+
60
+ def processTWB twb
61
+ @twb = twb
62
+ @twbName = @twb.name
63
+ @twbDir = @twb.dir
64
+ emit " -- #{@twbName}"
65
+ parseDataSources
66
+ end
67
+
68
+ def parseDataSources
69
+ @dataSources = @twb.datasources
70
+ @dataSources.each do |ds|
71
+ @dsCount += 1
72
+ recordCSV [ @twbName,
73
+ ds.uiname,
74
+ ds.name,
75
+ ds.dsclass,
76
+ ds.isExtract,
77
+ ds.connections.length,
78
+ ds.allFields.length,
79
+ ds.isPublished,
80
+ ds.tables.length,
81
+ ds.aliases.length,
82
+ ds.groups.length
83
+ ]
84
+ # [@twbName, @modTime, sheet.name, filter.type, filter.inexclude, filter.dataSource.uiname, filter.uiname, nil, nil, nil, filter.inexMode, filter.includeNull, filter.kind]
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def recordCSV record
91
+ numberedRec = [@recNum+=1] + record
92
+ if @recordDir
93
+ @sheetFieldsCSV << numberedRec.push(@twbDir)
94
+ else
95
+ @sheetFieldsCSV << numberedRec
96
+ end
97
+ end
98
+
99
+ end # class DataSourcesEnumeratorA
100
+
101
+ end # module DataSources
102
+ end # module Analysis
103
+ end # module Twb
@@ -41,7 +41,7 @@ module Analysis
41
41
 
42
42
  def metrics
43
43
  {
44
- '# of Workbooks' => @twbcount,
44
+ # '# of Workbooks' => @twbcount,
45
45
  '# of Worksheets' => @sheetCnt,
46
46
  '# of Worksheet Fields' => @fieldsCnt
47
47
  }
@@ -93,7 +93,7 @@ module Analysis
93
93
 
94
94
  def metrics
95
95
  {
96
- '# of Workbooks' => @twbcount,
96
+ # '# of Workbooks' => @twbcount,
97
97
  '# of Data Sources' => @dscount,
98
98
  '# of Google Docs' => @filecount,
99
99
  '# of Worksheets' => @sheetcount
@@ -38,9 +38,9 @@ module Analysis
38
38
  @dashSheetsCSV = CSV.open(docFileName,@csvMode)
39
39
  unless @csvAdd
40
40
  if @recordDir
41
- @dashSheetsCSV << ['Rec #','Workbook','Workbook Modified','Workbook Modified','Dashboard','Worksheet','Hidden','Visible', 'Workbook Dir']
41
+ @dashSheetsCSV << ['Rec #','Workbook','Dashboard','Worksheet','Hidden','Visible', 'Workbook Dir']
42
42
  else
43
- @dashSheetsCSV << ['Rec #','Workbook','Workbook Modified','Dashboard','Worksheet','Hidden','Visible' ]
43
+ @dashSheetsCSV << ['Rec #','Workbook','Dashboard','Worksheet','Hidden','Visible' ]
44
44
  end
45
45
  end
46
46
  addDocFile @dashSheetsCSV, docFileName, "Workbooks, Dashboards, and their Worksheets"
@@ -53,7 +53,7 @@ module Analysis
53
53
 
54
54
  def metrics
55
55
  {
56
- '# of Workbooks' => @twbCount,
56
+ # '# of Workbooks' => @twbCount,
57
57
  '# of Dashboards' => @dashCount,
58
58
  '# of Worksheets' => @sheetCount
59
59
  }
@@ -77,8 +77,9 @@ module Analysis
77
77
  @dashCount += 1
78
78
  dash.worksheets.each do |sheet|
79
79
  @sheetCount += 1
80
- emit "SHEET: #{sheet.name}"
81
- recordCSV [@twbName, @modTime, dash.name, sheet.name, sheet.hidden, sheet.visible ]
80
+ # puts "SHEET: #{sheet} -> #{sheet.name}"
81
+ recordCSV [@twbName, dash.name, sheet.name, sheet.hidden, sheet.visible ]
82
+ # recordCSV [@twbName, @modTime, dash.name, sheet.name, sheet.hidden, sheet.visible ]
82
83
  end
83
84
  end
84
85
  end
@@ -47,6 +47,7 @@ module Analysis
47
47
  @ttdocdir = @args[:ttdocdir]
48
48
  @csvAdd = args[:csvMode] == :add
49
49
  @csvMode = @csvAdd ? 'a' : 'w'
50
+ # @localEmit = true
50
51
  init
51
52
  @funcdoc = {:class=>self.class, :blurb=>'Analyze Worksheet Fields', :description=>nil,}
52
53
  #--
@@ -69,7 +70,7 @@ module Analysis
69
70
 
70
71
  def metrics
71
72
  {
72
- '# of Workbooks' => @twbcount,
73
+ # '# of Workbooks' => @twbcount,
73
74
  '# of Worksheets' => @sheetCnt,
74
75
  '# of Worksheet Fields' => @fieldsCnt
75
76
  }
@@ -0,0 +1,114 @@
1
+ # sheetfieldsanalyzer.rb Copyright (C) 2019 Chris 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
+ require 'csv'
18
+
19
+ module Twb
20
+ module Analysis
21
+
22
+ class SheetsInTooltipAnalyzer
23
+
24
+ include TabTool
25
+
26
+ def initialize(**args)
27
+ @args = args
28
+ @recordDir = !@args.nil? && @args[:recordDir] == true
29
+ @ttdocdir = @args[:ttdocdir]
30
+ @csvAdd = !@args.nil? && args[:csvMode] == :add
31
+ @csvMode = @csvAdd ? 'a' : 'w'
32
+ init
33
+ @funcdoc = {:class=>self.class, :blurb=>'Tooltip Vizzes', :description=>'Identifies the vizzes used in tooltips.',}
34
+ #--
35
+ docFileName = docFile('SheetsInTooltips.csv')
36
+ @csvFile = CSV.open(docFileName,@csvMode)
37
+ unless @csvAdd
38
+ if @recordDir
39
+ @csvFile << ['Rec #','Workbook','Worksheet - Host','Worksheet - Toolip viz','Max Width','Max Height', 'Workbook Dir']
40
+ else
41
+ @csvFile << ['Rec #','Workbook','Worksheet - Host','Worksheet - Toolip viz','Max Height','Max Width']
42
+ end
43
+ end
44
+ addDocFile @csvFile, docFileName, "Workbooks, Worksheets with Vizzes in their Tooltips"
45
+ #--
46
+ @twbCount = 0
47
+ @sheetCount = 0
48
+ @ttvizCount = 0
49
+ @recNum = 0
50
+ end
51
+
52
+ def metrics
53
+ {
54
+ # '# of Workbooks' => @twbCount,
55
+ '# of Worksheets' => @sheetCount,
56
+ '# of Worksheets in Tooltips' => @ttvizCount
57
+ }
58
+ end
59
+
60
+ def processTWB twb
61
+ @twb = twb
62
+ @twbName = @twb.name
63
+ @twbDir = @twb.dir
64
+ @modTime = @twb.modtime
65
+ emit " -- #{@twbName}"
66
+ @twbCount += 1
67
+ parseSheets
68
+ finis
69
+ end
70
+
71
+ def parseSheets
72
+ @sheets = @twb.worksheets
73
+ puts " #Sheets: #{@sheets.length}"
74
+ @sheetCount += @sheets.length
75
+ @sheets.each do |sheet|
76
+ puts "SHEET:: #{sheet.name}"
77
+ # @dashCount += 1
78
+ ttip = sheet.tooltip
79
+ runs = ttip.xpath('.//run')
80
+ runs.each do |run|
81
+ # puts run.text
82
+ text = run.text
83
+ isViz = text =~ /.*<Sheet[ ]+name=.*>.*/
84
+ puts "\t #{text}"
85
+ if isViz
86
+ vizCode = text.gsub(/^[^<]*/,'').gsub(/[^>]*$/,'')
87
+ vizNode = Nokogiri::XML(vizCode).at_xpath('./Sheet')
88
+ puts "\t #{vizCode}"
89
+ puts "\t #{vizNode.class} \t #{vizNode}"
90
+ recordCSV [@twbName, sheet.name, vizNode['name'], vizNode['maxwidth'], vizNode['maxheight']]
91
+ end
92
+
93
+ # @sheetCount += 1
94
+ # recordCSV [@twbName, dash.name, sheet.name, sheet.hidden, sheet.visible ]
95
+ end
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ def recordCSV record
102
+ numberedRec = [@recNum+=1] + record
103
+ if @recordDir
104
+ @csvFile << numberedRec.push(@twbDir)
105
+ else
106
+ @csvFile << numberedRec
107
+ end
108
+ end
109
+
110
+
111
+ end #class SheetFieldsAnalyzer
112
+
113
+ end # module Analysis
114
+ end # module Twb
@@ -41,7 +41,7 @@ module Analysis
41
41
 
42
42
  def metrics
43
43
  {
44
- '# of Workbooks' => @twbcount,
44
+ # '# of Workbooks' => @twbcount,
45
45
  '# of Worksheets' => @sheetCnt,
46
46
  '# of Worksheet Fields' => @fieldsCnt
47
47
  }
@@ -54,7 +54,7 @@ module Analysis
54
54
 
55
55
  def metrics
56
56
  {
57
- '# of Workbooks' => @twbCount,
57
+ # '# of Workbooks' => @twbCount,
58
58
  '# of Data Sources' => @dsCount,
59
59
  '# of Dashboards' => @dashCount,
60
60
  '# of Worksheets' => @sheetCount
@@ -21,6 +21,16 @@ module Twb
21
21
 
22
22
  include Comparable
23
23
 
24
+ @@dataTypeRoleMap = {
25
+ 'date' => :dimension,
26
+ 'datetime' => :dimension,
27
+ 'boolean' => :dimension,
28
+ 'integer' => :measure,
29
+ 'float' => :measure,
30
+ 'real' => :measure,
31
+ 'string' => :dimension,
32
+ }
33
+
24
34
  # XML Attributes known to exist in TWB xml
25
35
  # ----------------------------------------
26
36
  # aggregation
@@ -48,15 +58,15 @@ module Twb
48
58
  # visual-totals
49
59
 
50
60
  attr_reader :node, :properties
51
- attr_reader :name, :caption, :uiname
61
+ attr_reader :name, :caption, :uiname, :alias
52
62
  attr_reader :dataType, :defaultFormat, :paramDomainType
53
63
  attr_reader :role, :type, :value
54
64
  attr_reader :alias, :semanticRole, :aggregation
55
65
  attr_reader :autoColumn, :hidden, :datatypeCustomized
56
66
  attr_reader :calcField
67
+ attr_reader :path
57
68
  attr_reader :aliases
58
69
 
59
-
60
70
  def initialize(fieldNode, datasource=nil)
61
71
  @datasource = datasource
62
72
  @node = fieldNode
@@ -67,16 +77,14 @@ module Twb
67
77
  @userDataType = load 'user-datatype'
68
78
  @defaultFormat = load 'default-format'
69
79
  @paramDomainType = load 'param-domain-type'
70
- @role = load 'role'
71
80
  @type = load 'type'
72
81
  @value = load 'value'
73
82
  @alias = load 'alias'
74
83
  @semanticRole = load 'semantic-role'
75
84
  @aggregation = load 'aggregation'
76
85
  @autoColumn = load 'auto-column'
77
- @hidden = load 'hidden'
78
86
  @datatypeCustomized = load 'datatype-customized'
79
- @calcField = loadCalcField
87
+ # @calcField = loadCalcField
80
88
  end
81
89
 
82
90
  def id
@@ -89,10 +97,26 @@ module Twb
89
97
  return val
90
98
  end
91
99
 
100
+ def role
101
+ @role ||= loadRole
102
+ end
103
+
104
+ def loadRole
105
+ role = @node['role']
106
+ if role.nil?
107
+ role = @@dataTypeRoleMap[@dataType].nil? ? @dataType : @@dataTypeRoleMap[@dataType]
108
+ end
109
+ return role
110
+ end
111
+
92
112
  def calcField
93
113
  @calcField ||= loadCalcField
94
114
  end
95
115
 
116
+ def hidden
117
+ @hidden ||= load('hidden').nil? ? false : true
118
+ end
119
+
96
120
  def loadCalcField
97
121
  if !@node.at_xpath('./calculation').nil?
98
122
  @calcField = Twb::CalculatedField.new @node, @datasource
@@ -101,6 +125,14 @@ module Twb
101
125
  end
102
126
  end
103
127
 
128
+ def path
129
+ @path ||= @node.path.gsub(/\[[0-9]+\]/,'[]')
130
+ end
131
+
132
+ def pathbare
133
+ @pathbare ||= path().gsub(/\[\]/,'')
134
+ end
135
+
104
136
  def comment
105
137
  @commentLines ||= loadComment
106
138
  end
@@ -69,7 +69,7 @@ module Twb
69
69
  @caption = @node.attr('caption')
70
70
  @uiname = @caption.nil? ? @name : @caption
71
71
  # puts "DATASOURCE: #{@uiname}"
72
- processConnection
72
+ # processConnection
73
73
  # processFilters
74
74
  loadTableFields
75
75
  loadFieldUINames
@@ -111,41 +111,44 @@ module Twb
111
111
  end
112
112
 
113
113
  def processConnections
114
- processConnection ds, './/connection'
115
- processConnection ds, './/named-connection'
114
+ @connections = Array.new
115
+ processConnection './/connection'
116
+ processConnection './/named-connection'
117
+ return @connections
116
118
  end
117
119
 
118
120
  def processConnection path
119
121
  conns = @node.xpath(path)
120
122
  conns.each do |connNode|
121
- connClass = @dsclass
122
- cpath = conn.path
123
- connPath = cpath.gsub(/\[[0-9]+\]/,'')
124
- connPNum = /(\d+)/.match(cpath)
125
- # puts cpath, connPath
126
- # puts "CPATH: #{cpath}"
127
- conn.attributes.each do |name,value|
128
- # puts "\n\t\t - %-15s -> %-s" % [name, value]
129
- $csvFile << [ $recCount += 1,
130
- $twbName, $dir, $build, $version,
131
- $dsName, $dstype, $dsuiname, connClass,
132
- connPath, connPNum,
133
- name, value.value
134
- ]
135
- end
123
+ @connections << connNode
124
+ # connClass = @dsclass
125
+ # cpath = connNode.path
126
+ # connPath = cpath.gsub(/\[[0-9]+\]/,'')
127
+ # connPNum = /(\d+)/.match(cpath)
128
+ # # puts cpath, connPath
129
+ # # puts "CPATH: #{cpath}"
130
+ # conn.attributes.each do |name,value|
131
+ # # puts "\n\t\t - %-15s -> %-s" % [name, value]
132
+ # $csvFile << [ $recCount += 1,
133
+ # $twbName, $dir, $build, $version,
134
+ # $dsName, $dstype, $dsuiname, connClass,
135
+ # connPath, connPNum,
136
+ # name, value.value
137
+ # ]
138
+ # end
136
139
  end
137
140
  end
138
141
 
139
- def processConnection
140
- @connection = @node.at_xpath('./connection')
141
- @dsclass = @name # handles 'Parameters' data source, which has no connection element (& others if so)
142
- unless @connection.nil?
143
- @dsclass = @connection.attribute('class').text
144
- # note: must use "dsclass" as "class" would override Rubys ".class" Kernel method
145
- setConnectionHash
146
- loadTables @connection
147
- end
148
- end
142
+ # def processConnection
143
+ # @connection = @node.at_xpath('./connection')
144
+ # @dsclass = @name # handles 'Parameters' data source, which has no connection element (& others if so)
145
+ # unless @connection.nil?
146
+ # @dsclass = @connection.attribute('class').text
147
+ # # note: must use "dsclass" as "class" would override Rubys ".class" Kernel method
148
+ # setConnectionHash
149
+ # loadTables @connection
150
+ # end
151
+ # end
149
152
 
150
153
  # Notes:
151
154
  # - TODO: need to determine which, if any, of the connection attributes should be
@@ -174,12 +177,19 @@ module Twb
174
177
  @isPublished = !node.at_xpath('./repository-location').nil?
175
178
  end
176
179
 
177
- def loadTables connection
180
+ def tables
181
+ @tables ||= loadTables
182
+ end
183
+
184
+ def loadTables
178
185
  @tables = {}
179
- nodes = connection.xpath(".//relation[@type='table']")
180
- nodes.each do |node|
181
- @tables[node.attr('name')] = node.attr('table')
186
+ connections.each do |conn|
187
+ nodes = conn.xpath(".//relation[@type='table']")
188
+ nodes.each do |node|
189
+ @tables[node.attr('name')] = node.attr('table')
190
+ end
182
191
  end
192
+ return @tables
183
193
  end
184
194
 
185
195
  def joinPairs
@@ -237,7 +247,7 @@ module Twb
237
247
  def loadColumnFields
238
248
  @columnFields = Set.new
239
249
  @columnFieldsMap = {}
240
- nodes = @node.xpath('./column')
250
+ nodes = @node.xpath('.//column')
241
251
  nodes.each do |n|
242
252
  field = Twb::ColumnField.new n, self
243
253
  @columnFields << field
@@ -467,7 +477,7 @@ module Twb
467
477
  def loadAllFields
468
478
  @allFields = SortedSet.new
469
479
  dbf = dbFields
470
- @allFields << dbf.keys
480
+ @allFields << dbf
471
481
  @allFields << calculatedFieldNames
472
482
  end
473
483
 
@@ -31,7 +31,7 @@ module Twb
31
31
  attr_reader :formulaResolved
32
32
  attr_reader :formulaFlat
33
33
  attr_reader :formulaFlatResolved
34
- attr_reader :formulaLines, :formulaResolvedLines
34
+ attr_reader :formulaLines, :formulaResolvedLines, :formulaLinesCount
35
35
  attr_reader :is_tableCalc
36
36
  attr_reader :is_lod, :lodCodePos
37
37
  attr_reader :class, :scopeIsolation
@@ -176,6 +176,10 @@ module Twb
176
176
  formulaResolved.split(/\n|\r\n/)
177
177
  end
178
178
 
179
+ def formulaLinesCount
180
+ @formulaLinesCount ||= formulaLines.length
181
+ end
182
+
179
183
  def enlineResolvedFormula
180
184
  end
181
185
 
@@ -194,7 +198,7 @@ module Twb
194
198
  # line.strip
195
199
  formula += ' ' + line.gsub(/\/\/.*/, '') # unless line =~ /^[ ]*\/\//
196
200
  end
197
- return formula # .strip
201
+ return formula.strip
198
202
  end
199
203
 
200
204
 
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.6.3
4
+ version: 4.7.1
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-28 00:00:00.000000000 Z
11
+ date: 2019-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: creek
@@ -69,6 +69,7 @@ files:
69
69
  - lib/twb/analysis/datasources/datasourcefieldsanalyzer.rb
70
70
  - lib/twb/analysis/datasources/datasourcefieldscsvemitter.rb
71
71
  - lib/twb/analysis/datasources/datasourceoriginsanalyzer.rb
72
+ - lib/twb/analysis/datasources/datasourcesenumerator.rb
72
73
  - lib/twb/analysis/datasources/datasourceslocationsanalyzer.rb
73
74
  - lib/twb/analysis/datasources/datasourcetablefieldscsvemitter.rb
74
75
  - lib/twb/analysis/datasources/googlesheetdatasourcesanalyzer.rb
@@ -80,6 +81,7 @@ files:
80
81
  - lib/twb/analysis/sheets/sheetfieldsanalyzer.rb
81
82
  - lib/twb/analysis/sheets/sheetfiltersanalyzer.rb
82
83
  - lib/twb/analysis/sheets/sheetfiltersanalyzera.rb
84
+ - lib/twb/analysis/sheets/sheetsintooltipanalyzer.rb
83
85
  - lib/twb/analysis/sheets/sheetsourcesanalyzer.rb
84
86
  - lib/twb/analysis/sheets/worksheetdatastructurecsvemitter.rb
85
87
  - lib/twb/analysis/workbooksummaryanalyzer.rb