twb 3.9.7 → 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,14 +28,15 @@ module Analysis
28
28
  attr_reader :twbname, :twbcount
29
29
 
30
30
  def initialize
31
+ init
31
32
  #-- set up metrics
32
33
  @twbcount = 0
33
34
  @dscount = 0
34
35
  @filecount = 0
35
36
  @sheetcount = 0
36
37
  #--
37
- @funcdoc = {:class=>self.class, :blurb=>'Analyzing Google Sheet Data Sources from Tableau Workbooks.', :description=>nil,}
38
- docFileName = docFile('TWBGoogleSheetDataSources.csv')
38
+ @funcdoc = {:class=>self.class, :blurb=>'Analyze Google Sheet Data Sources', :description=>nil,}
39
+ docFileName = docFile('GoogleSheetDataSources.csv')
39
40
  @csv = CSV.open(docFileName, 'w')
40
41
  @csv << ["Workbook",'Data Source','Connection','File Name','Type','Table Name','Field']
41
42
  @docfiles = [{:name=>docFileName,:description=>"CSV File containing the data relating Google Sheet-based Data Sources."}]
@@ -57,9 +58,9 @@ module Analysis
57
58
  conns = ds.node.xpath(".//connection[@class='google-sheets']")
58
59
  if conns.length > 0
59
60
  @relation = ds.node.at_xpath('./connection/relation')
60
- @relName = @relation.attribute('name').text
61
- @relType = @relation.attribute('type').text
62
- @fileName = ds.node.at_xpath('.//named-connection/connection').attribute('filename')
61
+ @relName = @relation.nil? ? 'n/a - no relation in connection' : @relation['name']
62
+ @relType = @relation.nil? ? 'n/a - no relation in connection' : @relation['type']
63
+ @fileName = ds.node.at_xpath('.//named-connection/connection')['filename']
63
64
  @filecount += 1
64
65
  emit "FILENAME: #{@fileName}"
65
66
  tables = ds.node.xpath(".//relation[@type='table']")
@@ -27,12 +27,12 @@ module Analysis
27
27
 
28
28
  def initialize
29
29
  init
30
- @funcdoc = {:class=>self.class, :blurb=>'Analyze Dashboard Sheets from Tableau Workbooks.', :description=>'Identifies the Worksheets present in Dashboards.',}
30
+ @funcdoc = {:class=>self.class, :blurb=>'Analyze Dashboard Worksheets', :description=>'Identifies the Worksheets present in Dashboards.',}
31
31
  #--
32
- docFileName = docFile('TwbDashboardSheets.csv')
32
+ docFileName = docFile('DashboardSheets.csv')
33
33
  @dashSheetsCSV = CSV.open(docFileName,'w')
34
- @dashSheetsCSV << ['Workbook','Dashboard','Worksheet','Hidden','Visible']
35
- addDocFile docFileName, "Workbooks, Dashboards, and Worksheets in the Dashboards"
34
+ @dashSheetsCSV << ['Workbook','Workbook Dir','Modified','Dashboard','Worksheet','Hidden','Visible']
35
+ addDocFile docFileName, "Workbooks, Dashboards, and their Worksheets"
36
36
  #--
37
37
  @twbCount = 0
38
38
  @dashCount = 0
@@ -50,6 +50,8 @@ module Analysis
50
50
  def processTWB twb
51
51
  @twb = twb
52
52
  @twbName = @twb.name
53
+ @twbDir = @twb.dir
54
+ @modTime = @twb.modtime
53
55
  emit " -- #{@twbName}"
54
56
  @twbCount += 1
55
57
  parseDashes
@@ -64,7 +66,7 @@ module Analysis
64
66
  dash.worksheets.each do |sheet|
65
67
  @sheetCount += 1
66
68
  emit "SHEET: #{sheet.name}"
67
- @dashSheetsCSV << [@twbName, dash.name, sheet.name, sheet.hidden, sheet.visible ]
69
+ @dashSheetsCSV << [@twbName, @twbDir, @modTime, dash.name, sheet.name, sheet.hidden, sheet.visible ]
68
70
  end
69
71
  end
70
72
  end
@@ -23,20 +23,36 @@ module Analysis
23
23
 
24
24
  include TabTool
25
25
 
26
+ @@fieldTypeCodes = { 'DB ref' => 'Db',
27
+ 'color' => 'Clr',
28
+ 'filter' => 'F',
29
+ 'lod' => 'L',
30
+ 'page' => 'Pg',
31
+ 'path' => 'Pt',
32
+ 'shape' => 'Sh',
33
+ 'size' => 'Sz',
34
+ 'text' => 'Tx',
35
+ 'tooltip' => 'Tt',
36
+ :column => 'Cm',
37
+ :row => 'R',
38
+ }
39
+
40
+
26
41
  attr_accessor :localEmit
27
42
 
28
43
  def initialize
29
44
  init
30
- @funcdoc = {:class=>self.class, :blurb=>'Analyze Sheet Fields from Tableau Workbooks.', :description=>nil,}
45
+ @funcdoc = {:class=>self.class, :blurb=>'Analyze Worksheet Fields', :description=>nil,}
31
46
  #--
32
- docFileName = docFile('TwbWorksheetFields.csv')
47
+ docFileName = docFile('WorksheetFields.csv')
33
48
  @sheetFieldsCSV = CSV.open(docFileName,'w')
34
- @sheetFieldsCSV << ['Workbook','Worksheet','Data Source','Data Source (tech)','Field','Field (tech)']
49
+ @sheetFieldsCSV << ['Rec #', 'Workbook','Worksheet','Data Source','Data Source (tech)','Field','Field (tech)','Usage','Usage - code']
35
50
  addDocFile docFileName, "Workbooks, Worksheets, and the Sheets' Data Sources and Fields"
36
51
  #--
37
52
  @twbCnt = 0
38
53
  @sheetCnt = 0
39
54
  @fieldsCnt = 0
55
+ @recNum = 0
40
56
  end
41
57
 
42
58
  def metrics
@@ -49,27 +65,57 @@ module Analysis
49
65
 
50
66
  def processTWB twb
51
67
  @twb = twb
52
- emit " -- #{@twb.name}"
68
+ emit " -- twb:: #{@twb.name}"
53
69
  @twbCnt += 1
54
70
  @twbDomainsLoaded = false
55
71
  parseSheets
56
72
  finis
57
73
  end
58
74
 
75
+ private
76
+
59
77
  def parseSheets
60
78
  @worksheets = @twb.worksheets
61
79
  @worksheets.each do |sheet|
80
+ @sheet = sheet.name
62
81
  @sheetCnt += 1
63
- emit "SHEET: #{sheet.name}"
82
+ emit "SHEET: #{@sheet}"
64
83
  showFields sheet unless sheet.datasourceFields.nil?
65
84
  end
66
85
  end
67
86
 
68
87
  def showFields sheet
88
+ showDBFields sheet
89
+ showRCFields sheet.rowFields, :row
90
+ showRCFields sheet.colFields, :column
91
+ showEncodedFields sheet
92
+ showFilterFields sheet
93
+ showPageFields sheet
94
+ end
95
+
96
+ def showPageFields sheet
97
+ sheet.pageFields.each do |pfield|
98
+ ds = @twb.datasource pfield.dataSource
99
+ fuiname = ds.fieldUIName pfield.name
100
+ @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, ds.name, fuiname, pfield.name, 'page', ftc('filter')]
101
+ end
102
+ end
103
+
104
+ def showFilterFields sheet
105
+ filters = sheet.filters
106
+ filters.each do |filter|
107
+ dsName = filter.dataSource.name
108
+ dsUIName = filter.dataSource.uiname
109
+ # puts "Filter field: #{filter.dataSource.name} ui:'#{}'"
110
+ @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, dsUIName, dsName, filter.uiname, filter.name, 'filter', ftc('filter')]
111
+ end
112
+ end
113
+
114
+ def showDBFields sheet
69
115
  fields = sheet.datasourceFields
70
- emit " #FIELDS: #{fields.length}"
116
+ emit "def showDBFields sheet: #{sheet.name} #FIELDS: #{fields.length}"
71
117
  if fields.nil?
72
- @sheetFieldsCSV << [@twb.name, sheet.name, nil, nil, nil, nil]
118
+ @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, nil, nil, nil, nil, nil]
73
119
  end
74
120
  fields.each do |dsName, dsfields|
75
121
  ds = @twb.datasource dsName
@@ -81,12 +127,48 @@ module Analysis
81
127
  emit " f: #{sheetField}"
82
128
  emit " c: #{sheetField.class}"
83
129
  fuiName = ds.fieldUIName sheetField #Fields[sheetField]
84
- @sheetFieldsCSV << [@twb.name, sheet.name, ds.uiname, dsName, sheetField.uiname, sheetField.name]
130
+ @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, dsName, sheetField.uiname, sheetField.name, 'DB ref', ftc('DB ref')]
85
131
  # emit true, " : #{dsFields[field].class}"
86
132
  end
87
133
  end
88
134
  end
89
135
 
136
+ def showRCFields fields, usage
137
+ emit "def showRCFields #fields: #{fields.length} \t #{fields}"
138
+ if fields.nil?
139
+ @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, nil, nil, nil, nil, nil]
140
+ else
141
+ fields.each do |cf|
142
+ emit "coded field: #{cf}"
143
+ fldName = cf.name
144
+ dsName = cf.dataSource
145
+ ds = @twb.datasource dsName
146
+ emit "DATASOURCE : #{ds.class} " #{ }" #{ds}"
147
+ fuiName = ds.fieldUIName cf.name
148
+ emit " ds: #{dsName}"
149
+ emit " - #{ds.uiname}"
150
+ emit " : #{ds.class}"
151
+ @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, dsName, fuiName, fldName, usage, ftc(usage)]
152
+ end
153
+ end
154
+ end
155
+
156
+ def showEncodedFields sheet
157
+ unless sheet.encodedFields.nil?
158
+ sheet.encodedFields.each do |type,fields|
159
+ fields.each do |field|
160
+ dsName = field.dataSource
161
+ ds = @twb.datasource dsName
162
+ fuiName = ds.fieldUIName field.name
163
+ @sheetFieldsCSV << [@recNum+=1, @twb.name, @sheet, ds.uiname, dsName, fuiName, field.name, type, ftc(type)]
164
+ end
165
+ end
166
+ end
167
+ end #def showEncodedFields
168
+
169
+ def ftc type # ftc : abbr for fieldTypeCode, for brevity
170
+ @@fieldTypeCodes[type].nil? ? type : @@fieldTypeCodes[type]
171
+ end
90
172
 
91
173
  end #class SheetFieldsAnalyzer
92
174
 
@@ -27,11 +27,11 @@ module Analysis
27
27
 
28
28
  def initialize
29
29
  init
30
- @funcdoc = {:class=>self.class, :blurb=>'Analyze Worksheet filters.', :description=>'Documents Quick Filters and the values they employ, if any. Work in progess.',}
30
+ @funcdoc = {:class=>self.class, :blurb=>'Analyze Worksheet Filters', :description=>'Documents Quick Filters and the values they employ, if any. Work in progess.',}
31
31
  #--
32
32
  docFileName = docFile('WorksheetFilters.csv')
33
33
  $sheetFieldsCSV = CSV.open( docFileName ,'w')
34
- $sheetFieldsCSV << ['Workbook','Worksheet','Filter Type','Operation','Data Source','Field','Value','Alias', 'Alias?','Operation Mode','Include Null?']
34
+ $sheetFieldsCSV << ['Workbook','Workbook Dir','Worksheet','Filter Type','Operation','Data Source','Field','Value','Alias', 'Alias?','Operation Mode','Include Null?','Kind']
35
35
  addDocFile docFileName, "Workbooks, Worksheets and the sheets' Quick Filters"
36
36
  #--
37
37
  @sheetCount = 0
@@ -48,6 +48,7 @@ module Analysis
48
48
  def processTWB twb
49
49
  @twb = twb
50
50
  @twbName = @twb.name
51
+ @twbDir = @twb.dir
51
52
  emit " -- #{@twbName}"
52
53
  @twbDomainsLoaded = false
53
54
  parseFilters
@@ -62,14 +63,14 @@ module Analysis
62
63
  filter.emit "-----------------------------\nWORKSHEET:: #{sheet.name}\n-----------------------------"
63
64
  if filter.values.empty?
64
65
  # $sheetFieldsCSV << ['Workbook','Worksheet','Filter Type','Operation' ,'Data Source','Field','Value','Alias', 'Alias?']
65
- $sheetFieldsCSV << [@twbName ,sheet.name, filter.type ,filter.inexclude, filter.dataSource.uiname, filter.uiname,nil,nil,nil,filter.inexMode,filter.includeNull]
66
+ $sheetFieldsCSV << [@twbName, @twbDir, sheet.name, filter.type ,filter.inexclude, filter.dataSource.uiname, filter.uiname,nil,nil,nil,filter.inexMode,filter.includeNull,filter.kind]
66
67
  end
67
68
  filter.values.each do |valueMap|
68
69
  value = valueMap[:value]
69
70
  valias = valueMap[:alias]
70
71
  same = value.eql? valias
71
- # puts "RECORDING FILTER VALUES: %-25s -- %-25s same? %s " % [value,valias,same]
72
- $sheetFieldsCSV << [@twbName ,sheet.name, filter.type ,filter.inexclude, filter.dataSource.uiname, filter.uiname, value, valias, same,filter.inexMode,filter.includeNull]
72
+ emit "RECORDING FILTER VALUES: %-35s -- %-25s same? %s " % [value,valias,same]
73
+ $sheetFieldsCSV << [@twbName, @twbDir, sheet.name, filter.type ,filter.inexclude, filter.dataSource.uiname, filter.uiname, value, valias, same,filter.inexMode,filter.includeNull,filter.kind]
73
74
  end
74
75
  end
75
76
  end
@@ -0,0 +1,122 @@
1
+ # sheetfieldsanalyzer.rb Copyright (C) 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
+
22
+ class SheetSourcesAnalyzer
23
+
24
+ include TabTool
25
+
26
+ attr_accessor :localEmit
27
+
28
+ def initialize
29
+ init
30
+ @funcdoc = {:class=>self.class, :blurb=>'Analyze Worksheet Fields', :description=>nil,}
31
+ #--
32
+ docFileName = docFile('WorksheetFields.csv')
33
+ @sheetFieldsCSV = CSV.open(docFileName,'w')
34
+ @sheetFieldsCSV << ['Workbook','Worksheet','Data Source','Data Source (tech)','Field','Field (tech)','Usage']
35
+ addDocFile docFileName, "Workbooks, Worksheets, and the Sheets' Data Sources and Fields"
36
+ #--
37
+ @twbCnt = 0
38
+ @sheetCnt = 0
39
+ @fieldsCnt = 0
40
+ end
41
+
42
+ def metrics
43
+ {
44
+ '# of Workbooks' => @twbcount,
45
+ '# of Worksheets' => @sheetCnt,
46
+ '# of Worksheet Fields' => @fieldsCnt
47
+ }
48
+ end
49
+
50
+ def processTWB twb
51
+ @twb = twb
52
+ emit " -- twb:: #{@twb.name}"
53
+ @twbCnt += 1
54
+ @twbDomainsLoaded = false
55
+ parseSheets
56
+ finis
57
+ end
58
+
59
+ private
60
+
61
+ def parseSheets
62
+ @worksheets = @twb.worksheets
63
+ @worksheets.each do |sheet|
64
+ @sheet = sheet.name
65
+ @sheetCnt += 1
66
+ emit "SHEET: #{@sheet}"
67
+ showFields sheet unless sheet.datasourceFields.nil?
68
+ end
69
+ end
70
+
71
+ def showFields sheet
72
+ showDBFields sheet
73
+ showRCFields sheet.rowFields, :row
74
+ showRCFields sheet.colFields, :column
75
+ end
76
+
77
+ def showDBFields sheet
78
+ fields = sheet.datasourceFields
79
+ emit "def showDBFields sheet: #{sheet.name} #FIELDS: #{fields.length}"
80
+ if fields.nil?
81
+ @sheetFieldsCSV << [@twb.name, @sheet, nil, nil, nil, nil, nil]
82
+ end
83
+ fields.each do |dsName, dsfields|
84
+ ds = @twb.datasource dsName
85
+ emit " ds: #{dsName}"
86
+ emit " - #{ds.uiname}"
87
+ emit " : #{ds.class}"
88
+ dsfields.each do |sheetField|
89
+ @fieldsCnt += 1
90
+ emit " f: #{sheetField}"
91
+ emit " c: #{sheetField.class}"
92
+ fuiName = ds.fieldUIName sheetField #Fields[sheetField]
93
+ @sheetFieldsCSV << [@twb.name, @sheet, ds.uiname, dsName, sheetField.uiname, sheetField.name, 'DB ref']
94
+ # emit true, " : #{dsFields[field].class}"
95
+ end
96
+ end
97
+ end
98
+
99
+ def showRCFields fields, usage
100
+ emit "def showRCFields #fields: #{fields.length} \t #{fields}"
101
+ if fields.nil?
102
+ @sheetFieldsCSV << [@twb.name, @sheet, nil, nil, nil, nil, nil]
103
+ else
104
+ fields.each do |cf|
105
+ emit "coded field: #{cf}"
106
+ fldName = cf.name
107
+ dsName = cf.dataSource
108
+ ds = @twb.datasource cf.dataSource
109
+ emit "DATASOURCE : #{ds.class} " #{ }" #{ds}"
110
+ fuiName = ds.fieldUIName cf.name
111
+ emit " ds: #{dsName}"
112
+ emit " - #{ds.uiname}"
113
+ emit " : #{ds.class}"
114
+ @sheetFieldsCSV << [@twb.name, @sheet, ds.uiname, dsName, fuiName, fldName, usage]
115
+ end
116
+ end
117
+ end
118
+
119
+ end #class SheetFieldsAnalyzer
120
+
121
+ end # module Analysis
122
+ end # module Twb
@@ -83,6 +83,6 @@ module Twb
83
83
  @fqName <=> other.techCode
84
84
  end
85
85
 
86
- end # class CalculationField
86
+ end # class CodedField
87
87
 
88
88
  end # module Twb
@@ -17,15 +17,117 @@ require 'nokogiri'
17
17
 
18
18
  module Twb
19
19
 
20
- class Connection < TabClass
20
+ class Connection
21
21
 
22
- attr_reader :xmlType
22
+ include TabTool
23
+
24
+ def self.attributeNames
25
+ @@attributeNames ||= [
26
+ 'authentication',
27
+ 'authentication-type',
28
+ 'auto-extract',
29
+ 'channel',
30
+ 'character-set',
31
+ 'class',
32
+ 'cleaning',
33
+ 'compat',
34
+ 'compressed-responses',
35
+ 'compressed-responses-bulk',
36
+ 'compressed-responses-rest',
37
+ 'compressed-responses-soap',
38
+ 'connection-type',
39
+ 'dataRefreshTime',
40
+ 'dbname',
41
+ 'directory',
42
+ 'disable-unicode',
43
+ 'driver',
44
+ 'enum-with-permissions',
45
+ 'expected-driver-version',
46
+ 'filename',
47
+ 'force-character-set',
48
+ 'force-header',
49
+ 'force-separator',
50
+ 'header',
51
+ 'imex',
52
+ 'interpretationMode',
53
+ 'maxfieldlength',
54
+ 'mdwpath',
55
+ 'odbc-connect-string-extras',
56
+ 'odbc-native-protocol',
57
+ 'one-time-sql',
58
+ 'pagesize',
59
+ 'password',
60
+ 'port',
61
+ 'prefer-ind-semantics',
62
+ 'query-band-spec',
63
+ 'REDIRECT_URI',
64
+ 'salesforce-api-version',
65
+ 'schema',
66
+ 'SCOPE',
67
+ 'separator',
68
+ 'server',
69
+ 'server-oauth',
70
+ 'service',
71
+ 'sf-total-requestor-buffer-size-in-mb',
72
+ 'show',
73
+ 'tableau-ri',
74
+ 'tablename',
75
+ 'temporary',
76
+ 'update-time',
77
+ 'updated-database',
78
+ 'use-nonemptycrossjoin',
79
+ 'userLanguage',
80
+ 'username',
81
+ 'validate',
82
+ 'workgroup-auth-mode'
83
+ ]
84
+ end
85
+
86
+ attr_reader :node, :xmlType, :attributes
23
87
 
24
88
  # node: XML element
25
89
  def initialize node
90
+ @node = node
26
91
  @xmlType = node.type
92
+ @path = node.path.gsub(/\[[0-9]+\]/,'')
93
+ @pathNum = /(\d+)/.match(@path)
94
+ @name = nil
95
+ end
96
+
97
+ def processConnection path
98
+ conns = @node.xpath(path)
99
+ conns.each do |connNode|
100
+ connClass = @dsclass
101
+ cpath = conn.path
102
+ connPath = cpath.
103
+ connPNum =
104
+ # puts cpath, connPath
105
+ # puts "CPATH: #{cpath}"
106
+ conn.attributes.each do |name,value|
107
+ # puts "\n\t\t - %-15s -> %-s" % [name, value]
108
+ $csvFile << [ $recCount += 1,
109
+ $twbName, $dir, $build, $version,
110
+ $dsName, $dstype, $dsuiname, connClass,
111
+ connPath, connPNum,
112
+ name, value.value
113
+ ]
114
+ end
115
+ end
116
+ end
117
+
118
+ def attributes
119
+ @attributes ||= loadAttributes
120
+ end
27
121
 
122
+ private
28
123
 
124
+ def loadAttributes
125
+ @attributes = {}
126
+ nodeAttrs = @node.attributes
127
+ @@attributeNames.each do |a|
128
+ @attributes[a] = nodeAttrs[a]
129
+ end
130
+ return @attributes
29
131
  end
30
132
 
31
133
  end # class