Class: Twb::Workbook

Inherits:
Object
  • Object
show all
Defined in:
lib/twb/workbook.rb

Overview

A Tableau Workbook and its parts.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(twbWithDir) ⇒ Workbook

Creates a Workbook from its file name.

Parameters:

twbWithDir

The Workbook's file name, the Workbook can be a TWB or TWBX file.

Raises:

  • (ArgumentError)


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/twb/workbook.rb', line 42

def initialize twbWithDir
  raise ArgumentError.new("ERROR in Workbok creation: '#{twbWithDir}' must be a String, is a #{twbWithDir.class} \n ")        unless twbWithDir.is_a? String
  raise ArgumentError.new("ERROR in Workbok creation: '#{twbWithDir}' must have an extension of .twb or .twbx \n ") unless twbWithDir.upcase.end_with?(".TWB", ".TWBX")
  raise ArgumentError.new("ERROR in Workbok creation: '#{twbWithDir}' cannot be found, must be a Tableau Workbook file. \n ") unless File.file?(twbWithDir)
  @valid = false
  if File.file?(twbWithDir) then
    @name    = File.basename(twbWithDir)
    @dir     = File.dirname(File.expand_path(twbWithDir))
    @modtime = File.new(twbWithDir).mtime.strftime("%Y-%m-%d %H:%M:%S")
    case File.extname(twbWithDir)
      when '.twb'  then processTWB(twbWithDir)
      when '.twbx' then processTWBX(twbWithDir)
    end
  end
end

Instance Attribute Details

#actionsObject (readonly)

Returns the value of attribute actions.



32
33
34
# File 'lib/twb/workbook.rb', line 32

def actions
  @actions
end

#buildObject (readonly)

Returns the value of attribute build.



29
30
31
# File 'lib/twb/workbook.rb', line 29

def build
  @build
end

#dashboardsObject (readonly)

def datasources

# puts "ACCESSING DATASOURCES - #{@datasources.class} - #{@datasources.length} - #{@datasources.values.length}"
return @datasources.values

end



180
181
182
# File 'lib/twb/workbook.rb', line 180

def dashboards
  @dashboards
end

#datasource(name) ⇒ Object (readonly)

Returns the value of attribute datasource.



30
31
32
# File 'lib/twb/workbook.rb', line 30

def datasource
  @datasource
end

#datasourceNamesObject (readonly)

Returns the value of attribute datasourceNames.



31
32
33
# File 'lib/twb/workbook.rb', line 31

def datasourceNames
  @datasourceNames
end

#dataSourceNamesMapObject (readonly)

Returns the value of attribute dataSourceNamesMap.



31
32
33
# File 'lib/twb/workbook.rb', line 31

def dataSourceNamesMap
  @dataSourceNamesMap
end

#datasourcesObject (readonly)

Returns the value of attribute datasources.



30
31
32
# File 'lib/twb/workbook.rb', line 30

def datasources
  @datasources
end

#datasourceUINamesObject (readonly)

Returns the value of attribute datasourceUINames.



31
32
33
# File 'lib/twb/workbook.rb', line 31

def datasourceUINames
  @datasourceUINames
end

#dirObject (readonly)

Returns the value of attribute dir.



28
29
30
# File 'lib/twb/workbook.rb', line 28

def dir
  @dir
end

#modtimeObject (readonly)

Returns the value of attribute modtime.



29
30
31
# File 'lib/twb/workbook.rb', line 29

def modtime
  @modtime
end

#nameObject (readonly)

Returns the value of attribute name.



28
29
30
# File 'lib/twb/workbook.rb', line 28

def name
  @name
end

#ndocObject (readonly)

Returns the value of attribute ndoc.



33
34
35
# File 'lib/twb/workbook.rb', line 33

def ndoc
  @ndoc
end

#storyboardsObject (readonly)

Returns the value of attribute storyboards.



32
33
34
# File 'lib/twb/workbook.rb', line 32

def storyboards
  @storyboards
end

#validObject (readonly)

Returns the value of attribute valid.



33
34
35
# File 'lib/twb/workbook.rb', line 33

def valid
  @valid
end

#versionObject (readonly)

Returns the value of attribute version.



29
30
31
# File 'lib/twb/workbook.rb', line 29

def version
  @version
end

#workbooknodeObject (readonly)

Returns the value of attribute workbooknode.



27
28
29
# File 'lib/twb/workbook.rb', line 27

def workbooknode
  @workbooknode
end

#worksheetsObject (readonly)

Returns the value of attribute worksheets.



32
33
34
# File 'lib/twb/workbook.rb', line 32

def worksheets
  @worksheets
end

Instance Method Details

#actionNamesObject



171
172
173
# File 'lib/twb/workbook.rb', line 171

def actionNames
  @actions.keys
end

#addDocDashboard(docDashboard) ⇒ Object

Add a new Documentation Dashboard to the TWB. Ensure that the TWB has a <dashboards> node (it may not). Make sure that the new Doc Dashboard’s name doesn’t conflict with an existing Dashboard - increment the incoming name if necessary. Add Doc Dashboard’s <dashboard> and <window> nodes to the TWB; there’s always a <windows> node in the TWB.



231
232
233
234
235
236
237
238
# File 'lib/twb/workbook.rb', line 231

def addDocDashboard docDashboard
  ensureDashboardsNodeExists
  ensureWindowsNodeExists
  title = getNewDashboardTitle(docDashboard.title)
  docDashboard.title=(title) unless title == docDashboard.title
  @dashesNode.add_child(docDashboard.dashnode)
  @windowsnode.add_child(docDashboard.winnode)
end

#dashboard(name) ⇒ Object



188
189
190
# File 'lib/twb/workbook.rb', line 188

def dashboard name
  @dashboards[name]
end

#dashboardNamesObject



184
185
186
# File 'lib/twb/workbook.rb', line 184

def dashboardNames
  @dashboards.keys
end

#ensureDashboardsNodeExistsObject

Make sure that the TWB has a <dashboards> node. It’s possible for a TWB to have no dashboards, and therefore no <dashboards> node.



242
243
244
245
246
247
# File 'lib/twb/workbook.rb', line 242

def ensureDashboardsNodeExists
  if @dashesNode.nil?
    @dashesNode = Nokogiri::XML::Node.new "dashboards", @ndoc
    # TODO fix this @dataSourcesNode.add_next_sibling(@dashesNode)
  end
end

#ensureWindowsNodeExistsObject



220
221
222
223
224
225
# File 'lib/twb/workbook.rb', line 220

def ensureWindowsNodeExists
  if @windowsnode.nil?
    @windowsnode = Nokogiri::XML::Node.new "windows", @ndoc
    # TODO fix this @dataSourcesNode.add_next_sibling(@windowsnode)
  end
end

#getNewDashboardTitle(t) ⇒ Object



249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/twb/workbook.rb', line 249

def getNewDashboardTitle(t)
  title = t
  if @datasources.include?(title)
    inc = 0
    loop do
      inc+=1
      title = t + ' ' + inc.to_s
      if !@datasources.include?(title)
        break
      end
    end
  end
  return title
end

#loadActionsObject



158
159
160
161
162
163
164
165
# File 'lib/twb/workbook.rb', line 158

def loadActions
  @actions = {}
  actionNodes = @ndoc.xpath("//workbook/actions/action")
  actionNodes.each do |anode|
    action = Twb::Action.new(anode, @workbooknode)
    @actions[action.uiname] = action
  end
end

#loadBuildObject



87
88
89
90
91
92
93
94
95
# File 'lib/twb/workbook.rb', line 87

def loadBuild
  # - earlier Version, need to confirm when source-build began 
  #   @build   = @ndoc.xpath('/workbook/comment()').text.gsub(/^[^0-9]+/,'').strip
  @build = if !@ndoc.xpath('/workbook/@source-build').nil?
               @ndoc.xpath('/workbook/@source-build').first.text
           else 
               @ndoc.xpath('/workbook/comment()').text.gsub(/^[^0-9]+/,'').strip
           end
end

#loadDashboardsObject



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/twb/workbook.rb', line 127

def loadDashboards
  @dashesNode = @ndoc.at_xpath('//workbook/dashboards')
  @dashboards = {}
  dashes = @ndoc.xpath('//workbook/dashboards/dashboard').to_a
  dashes.each do |node|
    unless node.attr('type') == 'storyboard' then
      dashboard = Twb::Dashboard.new(node, @worksheets)
      @dashboards[dashboard.name] = dashboard
    end
  end
end

#loaddatasourcesObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/twb/workbook.rb', line 97

def loaddatasources
  # puts "LOAD DATA SOURCES"
  # @dataSourcesNode = @ndoc.at_xpath('//workbook/datasources')
  @datasources        = Set.new
  @datasourceNames    = SortedSet.new
  @datasourceUINames  = SortedSet.new
  @dataSourceNamesMap = {}
  datasourceNodes     = @ndoc.xpath('//workbook/datasources/datasource')
  # puts "DATASOURCENODES : #{@datasourceNodes.length}"
  datasourceNodes.each do |node|
    datasource = Twb::DataSource.new(node,self)
    @datasources << datasource
    @datasourceNames    << datasource.name
    @datasourceNames    << datasource.uiname
    @datasourceUINames  << datasource.uiname
    @dataSourceNamesMap[datasource.name]   = datasource 
    @dataSourceNamesMap[datasource.uiname] = datasource 
  end
  # puts "DATASOURCES    : #{@datasources.length}"
end

#loadStoryboardsObject



139
140
141
142
143
144
145
146
# File 'lib/twb/workbook.rb', line 139

def loadStoryboards
  @storyboards = {}
  boards = @ndoc.xpath("//workbook/dashboards/dashboard[@type='storyboard']" ).to_a
  boards.each do |node|
    sheet = Twb::Storyboard.new(node)
    @storyboards[sheet.name] = sheet
  end
end

#loadWindowsObject



148
149
150
151
152
153
154
155
156
# File 'lib/twb/workbook.rb', line 148

def loadWindows
  @windowsnode = @ndoc.at_xpath("//workbook/windows")
  @windows = {}
  windows  = @ndoc.xpath("//workbook/windows/window[@name]")
  windows.each do |node|
    window = Twb::Window.new(node)
    @windows[window.name] = window
  end
end

#loadWorksheetsObject



118
119
120
121
122
123
124
125
# File 'lib/twb/workbook.rb', line 118

def loadWorksheets
  @worksheets = {}
  sheets = @ndoc.xpath('//workbook/worksheets/worksheet' ).to_a
  sheets.each do |node|
    sheet = Twb::Worksheet.new(node)
    @worksheets[sheet.name] = sheet
  end
end

#processDocObject



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/twb/workbook.rb', line 71

def processDoc
  @workbooknode  = @ndoc.at_xpath('//workbook')
  @version = @ndoc.xpath('/workbook/@version').first.text
  loaddatasources
  loadWorksheets
  loadDashboards
  loadStoryboards
  loadWindows
  loadActions
  @valid = true
end

#processTWB(twbFile) ⇒ Object



66
67
68
69
# File 'lib/twb/workbook.rb', line 66

def processTWB(twbFile)
  @ndoc    = Nokogiri::XML(open(twbFile))
  processDoc
end

#processTWBX(twbxWithDir) ⇒ Object



58
59
60
61
62
63
64
# File 'lib/twb/workbook.rb', line 58

def processTWBX(twbxWithDir)
  Zip::File.open(twbxWithDir) do |zip_file|
    twb   = zip_file.glob('*.twb').first
    @ndoc = Nokogiri::XML(twb.get_input_stream)
    processDoc
  end
end

#storyboard(name) ⇒ Object



212
213
214
# File 'lib/twb/workbook.rb', line 212

def storyboard name
  @storyboards[name]
end

#storyboardNamesObject



200
201
202
# File 'lib/twb/workbook.rb', line 200

def storyboardNames
  @storyboards.keys
end

#worksheet(name) ⇒ Object



216
217
218
# File 'lib/twb/workbook.rb', line 216

def worksheet name
  @worksheets[name]
end

#worksheetNamesObject



204
205
206
# File 'lib/twb/workbook.rb', line 204

def worksheetNames
  @worksheets.keys
end

#write(name = @name) ⇒ Object

Write the TWB to a file, with an optional name. Can be used to write over the existing TWB (dangerous), or to a new file (preferred).



266
267
268
269
270
271
272
273
# File 'lib/twb/workbook.rb', line 266

def write(name=@name)
  $f = File.open(name,'w')
  if $f
      $f.puts @ndoc
      $f.close
  end
  return name
end

#writeAppend(str) ⇒ Object

Write the TWB to a file, appending the base name with the provided string. Intended for use when making adjustments to the TWB without overwriting the original.



277
278
279
280
# File 'lib/twb/workbook.rb', line 277

def writeAppend(str)
  newName = @name.sub(/[.]twb$/,'') + str.gsub(/^[.]*/,'.') + '.twb'
  write newName
end