twb 3.7.5 → 3.9.3

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.
@@ -21,10 +21,11 @@ module Twb
21
21
  class CalculatedField < TabClass
22
22
 
23
23
  attr_reader :dataSource
24
- attr_reader :node, :properties
25
- attr_reader :caption, :name, :uiname
26
- attr_reader :datatype, :role, :propType
27
- attr_reader :calculation, :calcFields
24
+ attr_reader :node, :properties
25
+ attr_reader :caption, :name, :uiname
26
+ attr_reader :datatype, :role, :propType
27
+ attr_reader :calculation, :calcFields
28
+ attr_reader :isGroup, :groupMembers
28
29
  attr_reader :hidden
29
30
 
30
31
  def initialize(calcNode, datasource=nil)
@@ -42,6 +43,7 @@ module Twb
42
43
  @calculation = Twb::FieldCalculation.new(self, datasource)
43
44
  # --
44
45
  @hidden = true if calcNode.has_attribute?('caption')
46
+ @isGroup = !@node.at_xpath('./calculation[@class="categorical-bin"]').nil?
45
47
  end
46
48
 
47
49
  def properties
@@ -64,6 +66,22 @@ module Twb
64
66
  @calculation.formulaResolved
65
67
  end
66
68
 
69
+ def groupMembers
70
+ @groupMembers ||= loadgroupmembers
71
+ end
72
+
73
+ def binValues binName
74
+ values = []
75
+ binValue = "\"#{binName}\""
76
+ binNode = @node.at_xpath("./calculation[@class='categorical-bin']/bin[@value='#{binValue}']")
77
+ unless binNode.nil?
78
+ binNode.xpath('.//value').each do |v|
79
+ values << v.text.gsub(/^['"]|['"]$/,'')
80
+ end
81
+ end
82
+ return values
83
+ end
84
+
67
85
  def loadProperties
68
86
  @properties= {}
69
87
  @node.attributes.each do |name,attr|
@@ -91,5 +109,25 @@ module Twb
91
109
  "%s(%s) => %s" % [uiname, name, @calculation.formulaFlat]
92
110
  end
93
111
 
112
+ private
113
+
114
+ def loadgroupmembers
115
+ @groupMembers = Hash.new { |h,k| h[k] = [] }
116
+ if @isGroup
117
+ groupLeads = @node.xpath('./calculation[@class="categorical-bin"]//bin')
118
+ groupLeads.each do |gl|
119
+ lead = gl['value']
120
+ groupAlias = @node.at_xpath("./aliases/alias[@key='#{lead}']")
121
+ groupNamex = groupAlias.nil? ? lead : groupAlias['value']
122
+ groupName = groupNamex.gsub(/^['"]|['"]$/,'')
123
+ values = gl.xpath('./value')
124
+ values.each do |v|
125
+ @groupMembers[groupName] << v.text.gsub(/^['"]|['"]$/,'').gsub('\"','"')
126
+ end
127
+ end
128
+ end
129
+ return @groupMembers
130
+ end
131
+
94
132
  end # class
95
133
  end # module
@@ -24,12 +24,13 @@ module Twb
24
24
  include Comparable
25
25
 
26
26
  attr_reader :dataSource
27
- attr_reader :name, :techCode, :rawCode
27
+ attr_reader :name, :techCode, :function, :rawCode
28
28
 
29
29
  def initialize code
30
30
  #puts "\n\nCodedField :: #{code}"
31
31
  @rawCode = code
32
- trimmed = code.gsub(/^"|"$/,'').gsub(/^\[|\]$/,'')
32
+ trimmed = code.gsub(/^['"]|['"]$/,'').gsub(/^\[|\]$/,'')
33
+ # puts "trimmed: #{trimmed}"
33
34
  parts = trimmed.split('].[')
34
35
  #puts "Field: #{code} parts: #{parts.length} - #{parts.inspect}"
35
36
  #puts " p1: #{parts[0]}"
@@ -38,12 +39,12 @@ module Twb
38
39
  #puts '==1'
39
40
  @name = parts[0]
40
41
  @techCode = "[#{@name}]"
41
- else # parts.length <> 1
42
+ elsif # parts.length <> 1
42
43
  #puts '<>1'
43
44
  #puts "p[0]: #{parts[0]}"
44
45
  #puts "p[1]: #{parts[1]}"
45
- @dataSource = parts[0]
46
- fldName = parts[1]
46
+ @dataSource = parts[0]
47
+ fldName = parts[1]
47
48
  if fldName.start_with?(':') && fldName.count(':') == 1
48
49
  @name = fldName
49
50
  else
@@ -56,21 +57,21 @@ module Twb
56
57
  def parseField str
57
58
  # puts "parseField: #{str}"
58
59
  parts = str.split(':')
59
- # puts "parseField: #{str}"
60
- # puts " parts : #{parts}"
61
- # puts " partsl: #{parts.length}"
62
- # puts " p[0]: #{parts[0]}"
63
- # puts " p[1]: #{parts[1]}"
64
60
  case parts.length
65
61
  when 1
66
- @name = parts[0]
62
+ @name = parts[0]
67
63
  else
68
- @name = parts[1]
64
+ @name = parts[-2]
65
+ @function = parts[0]
69
66
  end
70
67
  end
71
68
 
72
69
  def id
73
- @id ||= @id = "#{@dataSourceName}::#{@uiname}"
70
+ @id ||= @id = "#{@dataSource}::#{@uiname}"
71
+ end
72
+
73
+ def to_s
74
+ "ds:#{dataSource}|n:#{name}|tc:#{techCode}"
74
75
  end
75
76
 
76
77
  def <=>(other)
@@ -432,6 +432,10 @@ module Twb
432
432
  dbFieldsMap.has_key? fieldName
433
433
  end
434
434
 
435
+ def field fieldName
436
+ dbFieldsMap[fieldName]
437
+ end
438
+
435
439
  def fieldTable fieldName
436
440
  loadTableFields if @tableFieldsMap.nil?
437
441
  dbField = @tableFieldsMap[fieldName]
@@ -17,29 +17,63 @@ require 'logger'
17
17
 
18
18
  module TabTool
19
19
 
20
- attr_accessor :ttdocdir, :logger, :loglevel, :logfilename
21
- attr_reader :funcdoc, :docfiles, :metrics
20
+ @@licensed = false
21
+
22
+ TTDOCDIR = './ttdoc'
22
23
 
23
- TTDOCDIR = './ttdoc'
24
+ attr_accessor :ttdocdir, :logger, :loglevel, :logfilename
25
+ attr_reader :licensed, :funcdoc, :docfiles, :metrics, :alerts
24
26
 
25
27
  @funcdoc = {:class=>nil, :blurb=>nil, :description=>nil,}
26
28
  @docfiles = [] # should be of form [{:name=>'docFileName',:description=>'doc file description'}]
27
29
 
28
- @ttdocdir = './ttdoc'
29
- @logfilename = 'TabTools.ttlog'
30
- @loglevel = Logger::DEBUG
31
- @localEmit = false
32
- @docDirSet = false
30
+ # @logfilename = 'TabTools.ttlog'
31
+ @@loglevel = Logger::INFO
32
+ # @localEmit = false
33
+ # @docDirSet = false
33
34
 
34
- def funcdoc
35
- @funcdoc.nil? ? {:class=>'n/a', :blurb=>'generic TabTool blurb', :description=>'A useful Tableau Tool.'} : @funcdoc
35
+ def init
36
+ @alerts = []
37
+ initDocDir
38
+ # initLogger
39
+ end
40
+
41
+ def initDocDir
42
+ # return if TTDOCDIR.nil?
43
+ # return if ''.eql?($ttdocdir) && ''.eql?(TTDOCDIR)
44
+ @docDir = TTDOCDIR
45
+ return if Dir.exists?(@docDir)
46
+ if File.exists? @docDir
47
+ @docDir = ''
48
+ else
49
+ Dir.mkdir @docDir
50
+ end
51
+ return @docDir
52
+ end
53
+
54
+ def initLogger
55
+ logFileName = docFile("#{self.class.to_s.split('::').last}.ttlog")
56
+ @logger = Logger.new(logFileName, 2, 100*1024)
57
+ @logger.level = Logger::INFO
58
+ return @logger
36
59
  end
37
60
 
38
61
  def docFile name
39
- initDocDir unless @docDirSet
40
62
  @docDir.nil? ? name : "#{@docDir}/#{name}"
41
63
  end
42
64
 
65
+ def license= fileName
66
+ @@licensed = fileName.is_a?(String) && File.exist?(fileName)
67
+ end
68
+
69
+ def licensed?
70
+ @@licensed
71
+ end
72
+
73
+ def funcdoc
74
+ @funcdoc.nil? ? {:class=>'n/a', :blurb=>'generic TabTool blurb', :description=>'A useful Tableau Tool.'} : @funcdoc
75
+ end
76
+
43
77
  def docfiles
44
78
  @docfiles ||= @docfiles = []
45
79
  end
@@ -66,16 +100,18 @@ module TabTool
66
100
  lines << " - %-#{nameLen}s %-s " % [ dfi[:name], dfi[:description] ]
67
101
  end
68
102
  end
69
- docLines = lines.empty? ? [] : [' ','For documentation and generated data see the following:',' ']
103
+ docLines = lines.empty? ? [] : [' ',' For documentation and generated data see the following:',' ']
70
104
  lines.each do |l|
71
105
  docLines << l
72
106
  end
73
107
  return docLines
74
108
  end
75
109
 
110
+ # def metrics
111
+ # {}
112
+ # end
113
+
76
114
  def initCSV(fileName, desc=nil, header=nil)
77
- # puts 'initCSV'
78
- # puts " @docDirSet: #{@docDirSet} "
79
115
  csvName = docFile(fileName)
80
116
  emit "init CSV #{csvName}"
81
117
  csvFile = CSV.open(csvName, 'w')
@@ -85,48 +121,28 @@ module TabTool
85
121
  end
86
122
 
87
123
  def emit(local=@localEmit, stuff)
88
- initDocDir if @docDirSet.nil? || !@docDirSet
89
- initLogger if @logger.nil?
124
+ # if @logger.closed?
125
+ # @logger.reopen
126
+ # end
90
127
  if stuff.is_a? String then
91
128
  lines = stuff.split(/\n/)
92
129
  lines.each do |line|
93
- @logger.debug "#{@emitPrefix}#{line}"
130
+ @logger.debug "#{@emitPrefix}#{line}" unless @logger.nil?
94
131
  puts "#{@emitPrefix}#{line}" if local
95
132
  end
96
133
  else
97
- @logger.debug "#{@emitPrefix}#{stuff}"
134
+ @logger.debug "#{@emitPrefix}#{stuff}" unless @logger.nil?
98
135
  puts "#{@emitPrefix}#{stuff}" if local
99
136
  end
100
137
  end
101
138
 
102
- def initLogger
103
- initDocDir unless @docDirSet
104
- initDocDir
105
- logFileName = docFile("#{self.class.to_s.split('::').last}.ttlog")
106
- @logger = Logger.new(logFileName)
107
- @logger.level = Logger::DEBUG
139
+ def alert str
140
+ @alerts << str
141
+ emit "#{self.class} :: #{str}"
108
142
  end
109
143
 
110
- def initDocDir
111
- # puts 'initDocDir - begin'
112
- # puts " @docDirSet: #{@docDirSet} "
113
- # puts " TTDOCDIR : #{TTDOCDIR} "
114
- # puts " $ttdocdir : #{$ttdocdir} "
115
- # puts " @docDir : #{@docDir} "
116
- return if @docDirSet
117
- return if TTDOCDIR.nil? && $ttdocdir.nil?
118
- return if ''.eql?($ttdocdir) && ''.eql?(TTDOCDIR)
119
- @docDir = $ttdocdir.nil? ? TTDOCDIR : $ttdocdir
120
- return if Dir.exists?(@docDir)
121
- if File.exists? @docDir
122
- @docDir = nil
123
- return
124
- end
125
- Dir.mkdir @docDir
126
- @docDirSet = true
127
- # puts " @docDirSet: #{@docDirSet} "
128
- # puts " @docDir : #{@docDir} "
129
- # puts 'initDocDir - end'
144
+ def finis
145
+ # @logger.close unless @logger.nil? || @logger.closed?
130
146
  end
131
147
 
132
148
 
@@ -20,6 +20,7 @@ require 'creek'
20
20
  require 'csv'
21
21
 
22
22
  class FieldDomainLoader
23
+ include TabTool
23
24
 
24
25
  @@xmlLocation = './ttdoc'
25
26
 
@@ -27,6 +28,7 @@ require 'csv'
27
28
  attr_accessor :xmllocation, :workboook, :datasource, :csvOption
28
29
 
29
30
  def initialize
31
+ init
30
32
  reset
31
33
  end
32
34
 
@@ -82,7 +84,7 @@ require 'csv'
82
84
  end
83
85
  end
84
86
  else
85
- puts "#### ALERT #### XLSX file does not exist: #{fileName}"
87
+ alert "#### ALERT #### Twb:'#{@workbook}' DS: '#{@datasource}' DomRef: #{fileName}' file does not exist."
86
88
  end
87
89
  return fieldDomains
88
90
  end
@@ -25,6 +25,7 @@ module Twb
25
25
  attr_reader :node, :name, :datasourcenames, :datasources
26
26
  attr_reader :panesCount
27
27
  attr_reader :fields, :rowFields, :colFields, :paneFields, :datasourceFields
28
+ attr_reader :hidden, :visible
28
29
 
29
30
  def initialize sheetNode
30
31
  @node = sheetNode
@@ -64,6 +65,14 @@ module Twb
64
65
  # @fields.nil? ? loadFields : @fields
65
66
  end
66
67
 
68
+ def hidden
69
+ @hidden ||= resolveHidden
70
+ end
71
+
72
+ def visible
73
+ @visible ||= !hidden
74
+ end
75
+
67
76
  def loadFields
68
77
  # puts "WORKSHEET loadFields"
69
78
  @fields = {}
@@ -121,7 +130,13 @@ module Twb
121
130
  def datasourcenames
122
131
  @datasources.keys
123
132
  end
124
- end
133
+
134
+ def resolveHidden
135
+ windowNode = node.at_xpath("//windows/window[@name='#{@name}']")
136
+ @hidden = !windowNode.nil? && 'true' == windowNode['hidden']
137
+ end
138
+
139
+ end # class Worksheet
125
140
 
126
141
  class WorksheetDataSource
127
142
  # --
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: 3.7.5
4
+ version: 3.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Gerrard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-31 00:00:00.000000000 Z
11
+ date: 2018-08-31 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A sollection of Ruby classes designed for accessing and recording information
14
14
  about, and for manipulating, Tableau Workbooks and their contents.
@@ -27,12 +27,15 @@ files:
27
27
  - lib/twb/analysis/CalculatedFields/CSVEmitter.rb
28
28
  - lib/twb/analysis/CalculatedFields/CalculatedFieldsAnalyzer.rb
29
29
  - lib/twb/analysis/CalculatedFields/MarkdownEmitter.rb
30
+ - lib/twb/analysis/CalculatedFields/groupfieldsanalyzer.rb
30
31
  - lib/twb/analysis/DataSources/DataSourceFieldsCSVEmitter.rb
31
32
  - lib/twb/analysis/DataSources/DataSourceTableFieldsCSVEmitter.rb
32
33
  - lib/twb/analysis/DataSources/googlesheetdatasourcesanalyzer.rb
33
34
  - lib/twb/analysis/DocumentedFieldsCSVEmitter.rb
34
35
  - lib/twb/analysis/DocumentedFieldsMarkdownEmitter.rb
35
36
  - lib/twb/analysis/Sheets/WorksheetDataStructureCSVEmitter.rb
37
+ - lib/twb/analysis/Sheets/analyzeDashboardSheets.rb
38
+ - lib/twb/analysis/Sheets/dashsheetsanalyzer.rb
36
39
  - lib/twb/analysis/Sheets/sheetfieldsanalyzer.rb
37
40
  - lib/twb/analysis/Sheets/sheetfiltersanalyzer.rb
38
41
  - lib/twb/calculatedfield.rb