twb 4.7.1 → 4.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/twb.rb +8 -2
- data/lib/twb/analysis/calculatedfields/fieldsaliasesanalyzer.rb +110 -0
- data/lib/twb/analysis/datasources/datasourcefilesanalyzer.rb +83 -0
- data/lib/twb/analysis/datasources/datasourcetablefieldsanalyzer.rb +117 -0
- data/lib/twb/analysis/datasources/extractsanalyzer.rb +199 -0
- data/lib/twb/analysis/datasources/fieldsaliasesanalyzer.rb +117 -0
- data/lib/twb/analysis/sheets/sheetsintooltipanalyzer.rb +5 -5
- data/lib/twb/analysis/sheets/worksheetsummarizer.rb +118 -0
- data/lib/twb/columnfield.rb +22 -2
- data/lib/twb/datasource.rb +7 -1
- data/lib/twb/tabtool.rb +1 -1
- data/lib/twb/util/atomizecsvrecords.rb +105 -0
- data/lib/twb/util/csvrecordsatomizer.rb +114 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39d006e0c059121c7c53795a7b2c7b90c425a3809bb0287b215f5950ac4187b8
|
4
|
+
data.tar.gz: a49a8f7fb9cbf9a206def1cdc1faf649455dea27d180c88d64e518ae1da3b4e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f2983b81057ba13bfa029b4103fac22728f0fe34a7e41346373019161d7f6dc9857a54f67f071ae23f531e6a2a140448bc3c8e9ed95577b0c35ec4bd2e560d8
|
7
|
+
data.tar.gz: 9397a53a76c078a36dbfffa170c4a8f91b85a76d5c288e20c38e5a84ea9a3f78d9e7e01488f85d1c917dc6ce4f371671066367550723bd13ba79afa7f98b2b1c
|
data/lib/twb.rb
CHANGED
@@ -37,6 +37,7 @@ require_relative 'twb/quickfilter'
|
|
37
37
|
# require_relative 'twb/docdashboardimagevert'
|
38
38
|
# require_relative 'twb/docdashboardwebvert'
|
39
39
|
require_relative 'twb/util/twbdashsheetdatadotbuilder'
|
40
|
+
require_relative 'twb/util/csvrecordsatomizer'
|
40
41
|
require_relative 'twb/util/dotfilerenderer'
|
41
42
|
# require_relative 'twb/util/htmllistcollapsible'
|
42
43
|
require_relative 'twb/util/xraydashboards'
|
@@ -59,11 +60,16 @@ require_relative 'twb/analysis/calculatedfields/csvemitter'
|
|
59
60
|
# require_relative 'twb/analysis/datasources/datasourcefieldscsvemitter'
|
60
61
|
require_relative 'twb/analysis/datasources/datasourcesenumerator.rb'
|
61
62
|
require_relative 'twb/analysis/datasources/datasourcefieldsanalyzer'
|
62
|
-
require_relative 'twb/analysis/datasources/
|
63
|
+
require_relative 'twb/analysis/datasources/datasourcefilesanalyzer'
|
64
|
+
# require_relative 'twb/analysis/datasources/datasourcetablefieldscsvemitter'
|
65
|
+
# require_relative 'twb/analysis/datasources/datasourcetablefieldsanalyzer'
|
63
66
|
require_relative 'twb/analysis/datasources/categoricalcolorcodinganalyzer'
|
64
67
|
require_relative 'twb/analysis/datasources/googlesheetdatasourcesanalyzer'
|
65
68
|
require_relative 'twb/analysis/datasources/parametersanalyzer'
|
66
69
|
require_relative 'twb/analysis/datasources/datasourceoriginsanalyzer'
|
70
|
+
require_relative 'twb/analysis/datasources/fieldsaliasesanalyzer'
|
71
|
+
require_relative 'twb/analysis/datasources/extractsanalyzer'
|
72
|
+
require_relative 'twb/analysis/sheets/worksheetsummarizer'
|
67
73
|
require_relative 'twb/analysis/sheets/worksheetdatastructurecsvemitter'
|
68
74
|
require_relative 'twb/analysis/sheets/sheetfiltersanalyzer'
|
69
75
|
require_relative 'twb/analysis/sheets/sheetfieldsanalyzer'
|
@@ -74,5 +80,5 @@ require_relative 'twb/analysis/sheets/sheetsintooltipanalyzer'
|
|
74
80
|
# Represents Tableau Workbooks, their contents, and classes that analyze and manipulate them.
|
75
81
|
#
|
76
82
|
module Twb
|
77
|
-
VERSION = '4.
|
83
|
+
VERSION = '4.9.0'
|
78
84
|
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# fieldsaliasesanalyzer.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 'csv'
|
17
|
+
|
18
|
+
module Twb
|
19
|
+
module Analysis
|
20
|
+
|
21
|
+
class FieldsAliasesAnalyzer
|
22
|
+
|
23
|
+
include TabTool
|
24
|
+
|
25
|
+
attr_reader :calculatedFieldsCount, :referencedFieldsCount, :metrics
|
26
|
+
|
27
|
+
@@csvFileName = 'FieldAliases.csv'
|
28
|
+
@@csvFileHeader = [
|
29
|
+
'Record #',
|
30
|
+
"Record Number",
|
31
|
+
"Workbook",
|
32
|
+
"Data Source",
|
33
|
+
'Data Source Caption',
|
34
|
+
'Data Source (tech)',
|
35
|
+
'Field',
|
36
|
+
'Field Caption',
|
37
|
+
'Field Name (tech)',
|
38
|
+
'Data Type',
|
39
|
+
'Role',
|
40
|
+
'Type',
|
41
|
+
'Field Value',
|
42
|
+
'Field Alias'
|
43
|
+
]
|
44
|
+
|
45
|
+
|
46
|
+
def initialize(**args)
|
47
|
+
emit "initialize FieldsAliasesAnalyzer args #{args}"
|
48
|
+
@args = args
|
49
|
+
@recordDir = !@args.nil? && @args[:recordDir] == true
|
50
|
+
@ttdocdir = @args[:ttdocdir]
|
51
|
+
@csvAdd = @args[:csvMode] == :add
|
52
|
+
@csvMode = @csvAdd ? 'a' : 'w'
|
53
|
+
init
|
54
|
+
@funcdoc = {:class=>self.class, :blurb=>"Analyze Fields' Aliases", :description=>'Understanding the aliases for field values can be important and useful.',}
|
55
|
+
#-- CSV records collectors
|
56
|
+
# @csvFormulaFields = Set.new
|
57
|
+
# @csvFormulaLines = Set.new
|
58
|
+
#-- Counters setup --
|
59
|
+
# @twbCount = 0
|
60
|
+
@dataSourcesCount = 0
|
61
|
+
@aliasedFieldsCount = 0
|
62
|
+
@aliasessCount = 0
|
63
|
+
#--
|
64
|
+
# @referencedFields = SortedSet.new
|
65
|
+
#--
|
66
|
+
twbdirLabel = @recordDir.nil? ? nil : 'Workbook Dir'
|
67
|
+
@csvFile = initCSV(@@calcFieldsCSVFileName, 'Calculated fields and their formulas.', @@csvFileHeader )
|
68
|
+
#--
|
69
|
+
@localEmit = false
|
70
|
+
# @imageFiles = Array.new
|
71
|
+
#--
|
72
|
+
# @doGraph = config(:dograph)
|
73
|
+
end
|
74
|
+
|
75
|
+
def processTWB twb
|
76
|
+
twb.datasources.each do |ds|
|
77
|
+
processDS ds
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def processDS ds
|
82
|
+
@dsUIName = ds.uiname
|
83
|
+
@dsCaption = ds.caption
|
84
|
+
@dsName = ds.name
|
85
|
+
#--
|
86
|
+
aliasesNodes = ds.node.xpath('.//aliases')
|
87
|
+
aliasesNodes.each do |an|
|
88
|
+
processAliases an
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def processAliases aliasesNode
|
93
|
+
#-- Field --
|
94
|
+
caption = d.xpath('../../@caption').text
|
95
|
+
techName = d.xpath('../../@name').text
|
96
|
+
name = if caption == '' then getName(techName) else caption end
|
97
|
+
dataType = d.xpath('../../@datatype').text
|
98
|
+
role = d.xpath('../../@role').text
|
99
|
+
type = d.xpath('../../@type').text
|
100
|
+
|
101
|
+
#-- Alias --
|
102
|
+
aliasKey = d.xpath('./@key').text
|
103
|
+
aliasValue = d.xpath('./@value').text
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
end # class FieldsAliasesAnalyzer
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# datasourcefilesanalyzer.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 'csv'
|
17
|
+
|
18
|
+
module Twb
|
19
|
+
module Analysis
|
20
|
+
module DataSources
|
21
|
+
|
22
|
+
class DataSourceFilesAnalyzer
|
23
|
+
|
24
|
+
include TabTool
|
25
|
+
|
26
|
+
attr_reader :filesCount
|
27
|
+
|
28
|
+
@@csvFileName = 'DataSourceFiles.csv'
|
29
|
+
@@csvFileHeader = [ 'Record #',
|
30
|
+
'Workbook',
|
31
|
+
'Workbook Dir',
|
32
|
+
'Data Source',
|
33
|
+
'File Name',
|
34
|
+
'File Dir',
|
35
|
+
'File Modified',
|
36
|
+
'File Size'
|
37
|
+
]
|
38
|
+
|
39
|
+
def initialize(**args)
|
40
|
+
emit "initialize DataSourceFilesAnalyzer args #{args}"
|
41
|
+
@args = args
|
42
|
+
@recordDir = !@args.nil? && @args[:recordDir] == true
|
43
|
+
@ttdocdir = @args[:ttdocdir]
|
44
|
+
@csvAdd = @args[:csvMode] == :add
|
45
|
+
@csvMode = @csvAdd ? 'a' : 'w'
|
46
|
+
init
|
47
|
+
@funcdoc = {:class=>self.class, :blurb=>"Analyze Data Sources' Files", :description=>'Identifying the files accessed by Data Sources.',}
|
48
|
+
@dataSourcesCount = 0
|
49
|
+
@recNum = 0
|
50
|
+
#--
|
51
|
+
@csvFile = initCSV(@@csvFileName, 'Data Sources and the Files they access.', @@csvFileHeader )
|
52
|
+
#--
|
53
|
+
@localEmit = false
|
54
|
+
end
|
55
|
+
|
56
|
+
def processTWB twb
|
57
|
+
@twbName = twb.name
|
58
|
+
@twDir = twb.dir
|
59
|
+
twb.datasources.each do |ds|
|
60
|
+
processFiles ds
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def processFiles ds
|
65
|
+
dirFiles = Hash.new { |d,fs| d[fs] = Set.new }
|
66
|
+
ds.node.xpath('.//connection[@filename]').each do |fnode|
|
67
|
+
twbFileDir = fnode['directory']
|
68
|
+
twbFileName = fnode['filename']
|
69
|
+
fqFileName = twbFileDir.nil? ? twbFileName : twbFileDir + '/' + twbFileName
|
70
|
+
fileName = File.basename fqFileName
|
71
|
+
fileDir = File.dirname fqFileName
|
72
|
+
modtime = File.mtime fqFileName
|
73
|
+
size = File.size fqFileName
|
74
|
+
data = [$recNum+=1, twbName, twb.dir, ds.uiname, fileName, fileDir, modtime, size]
|
75
|
+
@csvFile << data
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end # class DataSourceFilesAnalyzer
|
80
|
+
|
81
|
+
end # module DataSources
|
82
|
+
end # module Analysis
|
83
|
+
end # module Twb
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# datasourcetablefieldsanalyzer.rb - this Ruby script Copyright 2019 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
|
+
module DataSources
|
21
|
+
|
22
|
+
class require_relative DataSourceTableFieldsAnalyzer
|
23
|
+
|
24
|
+
attr_reader :csvFileName, :csvRecords
|
25
|
+
attr_reader :dsCount, :tablesCount, :fieldsCount
|
26
|
+
|
27
|
+
@@csvFileName = 'DataSourceTableFields.csv'
|
28
|
+
@csvFileDescription = 'Contains CSV records, each containing the details for an individual Field contained in a table in the Data Source. Data Sources are identified within their host Workbook. '
|
29
|
+
|
30
|
+
@@csvHeader = ['Record #',
|
31
|
+
'Workbook',
|
32
|
+
'Workbook Dir',
|
33
|
+
'Data Source',
|
34
|
+
'Data Source (tech)',
|
35
|
+
'Table',
|
36
|
+
'Field',
|
37
|
+
'Field (code)',
|
38
|
+
'Field (table)',
|
39
|
+
]
|
40
|
+
|
41
|
+
|
42
|
+
def initialize
|
43
|
+
@csvFile = CSV.open(@@csvFileName, 'w')
|
44
|
+
@csvFile << @@csvHeader
|
45
|
+
@outputs = Set.new
|
46
|
+
@outputs << @@csvFileName
|
47
|
+
@dsCount = 0
|
48
|
+
@tablesCount = 0
|
49
|
+
@fieldsCount = 0
|
50
|
+
@csvRecords = Set.new
|
51
|
+
end
|
52
|
+
|
53
|
+
def doc
|
54
|
+
{
|
55
|
+
:filedoc => [
|
56
|
+
{ :file => @@csvFileName,
|
57
|
+
:description => @csvFileDescription,
|
58
|
+
:header => @@csvHeader
|
59
|
+
}
|
60
|
+
],
|
61
|
+
:outputs => @outputs
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.csvHeader
|
66
|
+
@@csvHeader
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.csvFileType
|
70
|
+
@@csvFileName
|
71
|
+
end
|
72
|
+
|
73
|
+
def outputs
|
74
|
+
@outputs
|
75
|
+
end
|
76
|
+
|
77
|
+
def processTwb twb
|
78
|
+
@recNum = 0
|
79
|
+
@twb = twb if twb.instance_of? Twb::Workbook
|
80
|
+
@twb = Twb::Workbook.new(twb) if twb.instance_of? String
|
81
|
+
# --
|
82
|
+
dss = @twb.datasources
|
83
|
+
dss.each do |ds|
|
84
|
+
tables = Set.new
|
85
|
+
@dsCount += 1
|
86
|
+
ds.node.xpath('./connection/cols/map').each do |cnode|
|
87
|
+
# puts cnode
|
88
|
+
key = cnode.attribute('key').text
|
89
|
+
codename = key.gsub(/^\[|\]$/,'')
|
90
|
+
fielduiname = ds.fieldUIName(codename)
|
91
|
+
value = cnode.attribute('value').text.gsub(/^\[|\]$/,'')
|
92
|
+
parts = value.split('].[')
|
93
|
+
# puts "%-30s %-45s %s \n " % [fielduiname, value, parts]
|
94
|
+
csvRecord = [ @fieldsCount += 1,
|
95
|
+
@twb.name,
|
96
|
+
@twb.dir,
|
97
|
+
ds.uiname,
|
98
|
+
ds.name,
|
99
|
+
parts[0],
|
100
|
+
fielduiname,
|
101
|
+
codename,
|
102
|
+
parts[1]
|
103
|
+
]
|
104
|
+
tables.add parts[0]
|
105
|
+
@csvRecords.add csvRecord
|
106
|
+
@csvFile << csvRecord
|
107
|
+
end
|
108
|
+
@tablesCount += tables.length
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end # class CSVEmitter
|
113
|
+
|
114
|
+
|
115
|
+
end # module DataSources
|
116
|
+
end # module Analysis
|
117
|
+
end # module Twb
|
@@ -0,0 +1,199 @@
|
|
1
|
+
# worksheetsummarizer.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
|
+
module DataSources
|
22
|
+
|
23
|
+
class ExtractsAnalyzer
|
24
|
+
|
25
|
+
include TabTool
|
26
|
+
|
27
|
+
attr_accessor :localEmit
|
28
|
+
|
29
|
+
def initialize(**args)
|
30
|
+
@args = args
|
31
|
+
@recordDir = !@args.nil? && @args[:recordDir] == true
|
32
|
+
@ttdocdir = @args[:ttdocdir]
|
33
|
+
@csvAdd = !@args.nil? && args[:csvMode] == :add
|
34
|
+
@csvMode = @csvAdd ? 'a' : 'w'
|
35
|
+
init
|
36
|
+
@funcdoc = {:class=>self.class, :blurb=>'Analyze Extracts', :description=>'Identifies Data Source Extracts & records relevant data.',}
|
37
|
+
#--
|
38
|
+
docFileName = docFile('Extracts.csv')
|
39
|
+
@extractsCSV = CSV.open(docFileName,@csvMode)
|
40
|
+
#--
|
41
|
+
# <extract count='-1' enabled='true' units='records'>
|
42
|
+
# <connection access_mode='readonly'
|
43
|
+
# authentication='auth-none'
|
44
|
+
# author-locale='en_US'
|
45
|
+
# class='hyper'
|
46
|
+
# dbname='C:/tech/Tableau/Tableau Tools/Ruby/gems/twb/lib/twb/analysis/datasources/data/Sample - World Bank Indicators (Excel).hyper'
|
47
|
+
# default-settings='yes'
|
48
|
+
# schema='Extract'
|
49
|
+
# sslmode=''
|
50
|
+
# update-time='05/17/2019 10:39:21 PM'
|
51
|
+
# username='tableau_internal_user'>
|
52
|
+
# <relation name='Extract' table='[Extract].[Extract]' type='table' />
|
53
|
+
# <refresh>
|
54
|
+
# <refresh-event add-from-file-path='Sample - World Bank Indicators (Excel)' increment-value='%null%' refresh-type='create' rows-inserted='2354' timestamp-start='2019-05-17 22:39:21.474' />
|
55
|
+
# </refresh>
|
56
|
+
# </connection>
|
57
|
+
# </extract>
|
58
|
+
#--
|
59
|
+
unless @csvAdd
|
60
|
+
@csvHeader = [ 'Rec #',
|
61
|
+
'Workbook',
|
62
|
+
'Data Source',
|
63
|
+
'Enabled',
|
64
|
+
'Units',
|
65
|
+
'Access Mode',
|
66
|
+
'Authentication',
|
67
|
+
'Class',
|
68
|
+
'Extract Name (FQ)',
|
69
|
+
'Extract Name',
|
70
|
+
'Extract Directory',
|
71
|
+
'Default Settings',
|
72
|
+
'Schema',
|
73
|
+
'SSL Mode',
|
74
|
+
'Updated (UTC)',
|
75
|
+
'User Name'
|
76
|
+
]
|
77
|
+
if @recordDir
|
78
|
+
@csvHeader.push 'Workbook Dir'
|
79
|
+
end
|
80
|
+
@extractsCSV << @csvHeader
|
81
|
+
end
|
82
|
+
addDocFile @extractsCSV, docFileName, "Workbooks and their Data Source Extracts."
|
83
|
+
#--
|
84
|
+
@twbCount = 0
|
85
|
+
@dsCount = 0
|
86
|
+
@extractCount = 0
|
87
|
+
@recNum = 0
|
88
|
+
end
|
89
|
+
|
90
|
+
def metrics
|
91
|
+
{
|
92
|
+
'# of Data Sources' => @dsCount,
|
93
|
+
'# of Extracts' => @extractCount
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
def processTWB twb
|
98
|
+
@twb = twb
|
99
|
+
@twbName = @twb.name
|
100
|
+
@twbDir = @twb.dir
|
101
|
+
emit " -- #{@twbName}"
|
102
|
+
@twbCount += 1
|
103
|
+
parseDataSources
|
104
|
+
finis
|
105
|
+
end
|
106
|
+
|
107
|
+
def parseDataSources
|
108
|
+
@dataSources = @twb.datasources
|
109
|
+
@dataSources.each do |ds|
|
110
|
+
@dsCount += 1
|
111
|
+
emit "DATA SOURCE:: #{ds.name}"
|
112
|
+
dsNode = ds.node
|
113
|
+
exnode = ds.node.at_xpath('./extract')
|
114
|
+
unless exnode.nil?
|
115
|
+
cnNode = exnode.at_xpath('./connection')
|
116
|
+
# emit true, cnNode
|
117
|
+
unless cnNode.nil?
|
118
|
+
@extractCount += 1
|
119
|
+
dbName = cnNode['dbname']
|
120
|
+
# emit true, "cnNode['dbname'] :: #{cnNode['dbname']}"
|
121
|
+
# unless dbName.nil?
|
122
|
+
exName = File.basename dbName
|
123
|
+
exDir = File.dirname dbName
|
124
|
+
# end
|
125
|
+
recordCSV [ @twbName,
|
126
|
+
ds.uiname,
|
127
|
+
exnode['enabled'],
|
128
|
+
exnode['units'],
|
129
|
+
cnNode['access_mode'],
|
130
|
+
cnNode['authentication'],
|
131
|
+
cnNode['class'],
|
132
|
+
dbName,
|
133
|
+
exName,
|
134
|
+
exDir,
|
135
|
+
cnNode['default-settings'],
|
136
|
+
cnNode['schema'],
|
137
|
+
cnNode['sslmode'],
|
138
|
+
cnNode['update-time'],
|
139
|
+
cnNode['username']
|
140
|
+
]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# <extract count='-1' enabled='true' units='records'>
|
147
|
+
# <connection access_mode='readonly'
|
148
|
+
# authentication='auth-none'
|
149
|
+
# author-locale='en_US'
|
150
|
+
# class='hyper'
|
151
|
+
# dbname='C:/tech/Tableau/Tableau Tools/Ruby/gems/twb/lib/twb/analysis/datasources/data/Sample - World Bank Indicators (Excel).hyper'
|
152
|
+
# default-settings='yes'
|
153
|
+
# schema='Extract'
|
154
|
+
# sslmode=''
|
155
|
+
# update-time='05/17/2019 10:39:21 PM'
|
156
|
+
# username='tableau_internal_user'>
|
157
|
+
# <relation name='Extract' table='[Extract].[Extract]' type='table' />
|
158
|
+
# <refresh>
|
159
|
+
# <refresh-event add-from-file-path='Sample - World Bank Indicators (Excel)' increment-value='%null%' refresh-type='create' rows-inserted='2354' timestamp-start='2019-05-17 22:39:21.474' />
|
160
|
+
# </refresh>
|
161
|
+
# </connection>
|
162
|
+
# </extract>
|
163
|
+
#--
|
164
|
+
# unless @csvAdd
|
165
|
+
# @csvHeader = [ 'Rec #',
|
166
|
+
# 'Workbook',
|
167
|
+
# 'Data Source',
|
168
|
+
# 'Enabled',
|
169
|
+
# 'Units',
|
170
|
+
# 'Access Mode',
|
171
|
+
# 'Authentication',
|
172
|
+
# 'Class',
|
173
|
+
# 'Db Name',
|
174
|
+
# 'Default Settings',
|
175
|
+
# 'Schema',
|
176
|
+
# 'SSL Mode',
|
177
|
+
# 'Updated',
|
178
|
+
# 'User Name'
|
179
|
+
# ]
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def recordCSV record
|
187
|
+
numberedRec = [@recNum+=1] + record
|
188
|
+
if @recordDir
|
189
|
+
@extractsCSV << numberedRec.push(@twbDir)
|
190
|
+
else
|
191
|
+
@extractsCSV << numberedRec
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end # class ExtractsAnalyzer
|
196
|
+
|
197
|
+
end # module DataSources
|
198
|
+
end # module Analysis
|
199
|
+
end # module Twb
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# fieldsaliasesanalyzer.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 'csv'
|
17
|
+
|
18
|
+
module Twb
|
19
|
+
module Analysis
|
20
|
+
module DataSources
|
21
|
+
|
22
|
+
class FieldsAliasesAnalyzer
|
23
|
+
|
24
|
+
include TabTool
|
25
|
+
|
26
|
+
attr_reader :calculatedFieldsCount, :referencedFieldsCount, :metrics
|
27
|
+
|
28
|
+
@@csvFileName = 'FieldAliases.csv'
|
29
|
+
@@csvFileHeader = [
|
30
|
+
'Record #',
|
31
|
+
"Workbook",
|
32
|
+
"Data Source",
|
33
|
+
'Field',
|
34
|
+
'Value - Db',
|
35
|
+
'Value - Alias'
|
36
|
+
]
|
37
|
+
|
38
|
+
|
39
|
+
def initialize(**args)
|
40
|
+
emit "initialize FieldsAliasesAnalyzer args #{args}"
|
41
|
+
@args = args
|
42
|
+
@recordDir = !@args.nil? && @args[:recordDir] == true
|
43
|
+
@ttdocdir = @args[:ttdocdir]
|
44
|
+
@csvAdd = @args[:csvMode] == :add
|
45
|
+
@csvMode = @csvAdd ? 'a' : 'w'
|
46
|
+
init
|
47
|
+
@funcdoc = {:class=>self.class, :blurb=>"Analyze Fields' Aliases", :description=>'Understanding the aliases for field values can be important and useful.',}
|
48
|
+
#-- CSV records collectors
|
49
|
+
# @csvFormulaFields = Set.new
|
50
|
+
# @csvFormulaLines = Set.new
|
51
|
+
#-- Counters setup --
|
52
|
+
# @twbCount = 0
|
53
|
+
@dataSourcesCount = 0
|
54
|
+
@aliasedFieldsCount = 0
|
55
|
+
@aliasessCount = 0
|
56
|
+
@recNum = 0
|
57
|
+
#--
|
58
|
+
# @referencedFields = SortedSet.new
|
59
|
+
#--
|
60
|
+
@csvFile = initCSV(@@csvFileName, 'Fields and their aliased values.', @@csvFileHeader )
|
61
|
+
#--
|
62
|
+
@localEmit = false
|
63
|
+
# @imageFiles = Array.new
|
64
|
+
#--
|
65
|
+
# @doGraph = config(:dograph)
|
66
|
+
end
|
67
|
+
|
68
|
+
def processTWB twb
|
69
|
+
@twbName = twb.name
|
70
|
+
@twDir = twb.dir
|
71
|
+
twb.datasources.each do |ds|
|
72
|
+
processDS ds
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def processDS ds
|
77
|
+
@dsUIName = ds.uiname
|
78
|
+
@dsCaption = ds.caption
|
79
|
+
@dsName = ds.name
|
80
|
+
#--
|
81
|
+
ds.columnFields.each do |fld|
|
82
|
+
if fld.hasaliases
|
83
|
+
@fieldName = fld.name
|
84
|
+
@fieldCaption = fld.caption
|
85
|
+
@fieldUIName = fld.uiname
|
86
|
+
processAliases(fld)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def processAliases field
|
92
|
+
aliasNodes = field.node.xpath('./aliases//alias')
|
93
|
+
aliasNodes.each do |anode|
|
94
|
+
key = anode['key']
|
95
|
+
value = anode['value']
|
96
|
+
numberedRec = [
|
97
|
+
@recNum +=1,
|
98
|
+
@twbName,
|
99
|
+
@dsUIName,
|
100
|
+
@fieldName,
|
101
|
+
anode['key'].to_s.gsub(/^["]+/,'').gsub(/["]+$/,''),
|
102
|
+
anode['value']
|
103
|
+
]
|
104
|
+
#--
|
105
|
+
if @recordDir
|
106
|
+
@csvFile << numberedRec.push(@twbDir)
|
107
|
+
else
|
108
|
+
@csvFile << numberedRec
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end # class FieldsAliasesAnalyzer
|
114
|
+
|
115
|
+
end # module DataSources
|
116
|
+
end # module Analysis
|
117
|
+
end # module Twb
|
@@ -70,10 +70,10 @@ module Analysis
|
|
70
70
|
|
71
71
|
def parseSheets
|
72
72
|
@sheets = @twb.worksheets
|
73
|
-
puts " #Sheets: #{@sheets.length}"
|
73
|
+
# puts " #Sheets: #{@sheets.length}"
|
74
74
|
@sheetCount += @sheets.length
|
75
75
|
@sheets.each do |sheet|
|
76
|
-
puts "SHEET:: #{sheet.name}"
|
76
|
+
# puts "SHEET:: #{sheet.name}"
|
77
77
|
# @dashCount += 1
|
78
78
|
ttip = sheet.tooltip
|
79
79
|
runs = ttip.xpath('.//run')
|
@@ -81,12 +81,12 @@ module Analysis
|
|
81
81
|
# puts run.text
|
82
82
|
text = run.text
|
83
83
|
isViz = text =~ /.*<Sheet[ ]+name=.*>.*/
|
84
|
-
puts "\t #{text}"
|
84
|
+
# puts "\t #{text}"
|
85
85
|
if isViz
|
86
86
|
vizCode = text.gsub(/^[^<]*/,'').gsub(/[^>]*$/,'')
|
87
87
|
vizNode = Nokogiri::XML(vizCode).at_xpath('./Sheet')
|
88
|
-
puts "\t #{vizCode}"
|
89
|
-
puts "\t #{vizNode.class} \t #{vizNode}"
|
88
|
+
# puts "\t #{vizCode}"
|
89
|
+
# puts "\t #{vizNode.class} \t #{vizNode}"
|
90
90
|
recordCSV [@twbName, sheet.name, vizNode['name'], vizNode['maxwidth'], vizNode['maxheight']]
|
91
91
|
end
|
92
92
|
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# worksheetsummarizer.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 WorksheetSummarizer
|
23
|
+
|
24
|
+
include TabTool
|
25
|
+
|
26
|
+
attr_accessor :localEmit
|
27
|
+
|
28
|
+
# Worksheet attributes; from Worksheet.rb
|
29
|
+
# attr_reader :node, :name, :datasourcenames, :datasources
|
30
|
+
# attr_reader :panesCount
|
31
|
+
# attr_reader :fields, :rowFields, :colFields, :paneFields, :datasourceFields, :pageFields, :encodedFields, :slicesFields
|
32
|
+
# attr_reader :filters
|
33
|
+
# attr_reader :tooltip
|
34
|
+
# attr_accessor :hidden, :visible
|
35
|
+
|
36
|
+
def initialize(**args)
|
37
|
+
@args = args
|
38
|
+
@recordDir = !@args.nil? && @args[:recordDir] == true
|
39
|
+
@ttdocdir = @args[:ttdocdir]
|
40
|
+
@csvAdd = !@args.nil? && args[:csvMode] == :add
|
41
|
+
@csvMode = @csvAdd ? 'a' : 'w'
|
42
|
+
init
|
43
|
+
@funcdoc = {:class=>self.class, :blurb=>'Summarize Worksheets', :description=>'Identifies Worksheets & summarizes them.',}
|
44
|
+
#--
|
45
|
+
docFileName = docFile('WorkheetSummaries.csv')
|
46
|
+
@worksheetsCSV = CSV.open(docFileName,@csvMode)
|
47
|
+
unless @csvAdd
|
48
|
+
@csvHeader = [ 'Rec #',
|
49
|
+
'Workbook',
|
50
|
+
'Worksheet',
|
51
|
+
'Hidden', 'Visible',
|
52
|
+
'# Data Sources',
|
53
|
+
'# Fields - Data', '# Fields - Rows', '# Fields - Cols',
|
54
|
+
'Tooltip?', 'Filters?'
|
55
|
+
]
|
56
|
+
if @recordDir
|
57
|
+
@csvHeader.push 'Workbook Dir'
|
58
|
+
end
|
59
|
+
@worksheetsCSV << @csvHeader
|
60
|
+
end
|
61
|
+
addDocFile @worksheetsCSV, docFileName, "Workbooks and their Worksheets' summaries."
|
62
|
+
#--
|
63
|
+
@twbCount = 0
|
64
|
+
@sheetCount = 0
|
65
|
+
@recNum = 0
|
66
|
+
end
|
67
|
+
|
68
|
+
def metrics
|
69
|
+
{
|
70
|
+
'# of Worksheets' => @sheetCount
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def processTWB twb
|
75
|
+
@twb = twb
|
76
|
+
@twbName = @twb.name
|
77
|
+
@twbDir = @twb.dir
|
78
|
+
@modTime = @twb.modtime
|
79
|
+
emit " -- #{@twbName}"
|
80
|
+
@twbCount += 1
|
81
|
+
parseSheets
|
82
|
+
finis
|
83
|
+
end
|
84
|
+
|
85
|
+
def parseSheets
|
86
|
+
@worksheets = @twb.worksheets
|
87
|
+
@worksheets.each do |sheet|
|
88
|
+
emit "SHEET:: #{sheet.name}"
|
89
|
+
@sheetCount += 1
|
90
|
+
recordCSV [ @twbName,
|
91
|
+
sheet.name,
|
92
|
+
sheet.hidden,
|
93
|
+
sheet.visible,
|
94
|
+
sheet.datasources.length,
|
95
|
+
sheet.datasourceFields.length,
|
96
|
+
sheet.rowFields.length,
|
97
|
+
sheet.colFields.length,
|
98
|
+
!sheet.tooltip.nil?,
|
99
|
+
!sheet.filters.nil?,
|
100
|
+
]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def recordCSV record
|
107
|
+
numberedRec = [@recNum+=1] + record
|
108
|
+
if @recordDir
|
109
|
+
@worksheetsCSV << numberedRec.push(@twbDir)
|
110
|
+
else
|
111
|
+
@worksheetsCSV << numberedRec
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end #class WorksheetSummarizer
|
116
|
+
|
117
|
+
end # module Analysis
|
118
|
+
end # module Twb
|
data/lib/twb/columnfield.rb
CHANGED
@@ -58,7 +58,8 @@ module Twb
|
|
58
58
|
# visual-totals
|
59
59
|
|
60
60
|
attr_reader :node, :properties
|
61
|
-
attr_reader :name, :caption, :uiname
|
61
|
+
attr_reader :name, :caption, :uiname
|
62
|
+
attr_reader :hasaliases, :alias
|
62
63
|
attr_reader :dataType, :defaultFormat, :paramDomainType
|
63
64
|
attr_reader :role, :type, :value
|
64
65
|
attr_reader :alias, :semanticRole, :aggregation
|
@@ -109,7 +110,7 @@ module Twb
|
|
109
110
|
return role
|
110
111
|
end
|
111
112
|
|
112
|
-
def
|
113
|
+
def calcField
|
113
114
|
@calcField ||= loadCalcField
|
114
115
|
end
|
115
116
|
|
@@ -137,6 +138,25 @@ module Twb
|
|
137
138
|
@commentLines ||= loadComment
|
138
139
|
end
|
139
140
|
|
141
|
+
def hasaliases
|
142
|
+
@hasaliases ||= !@node.at_xpath('./aliases').nil?
|
143
|
+
end
|
144
|
+
|
145
|
+
def aliases
|
146
|
+
@aliases ||= loadAliases
|
147
|
+
end
|
148
|
+
|
149
|
+
def loadAliases
|
150
|
+
@aliases = {}
|
151
|
+
if hasaliases
|
152
|
+
@node.at_xpath('./aliases//alias').each do |an|
|
153
|
+
dbvalue = an['key'].to_s.gsub(/^["]+/,'').gsub(/["]+$/,'')
|
154
|
+
@aliases[ dbvalue ] = an['value']
|
155
|
+
end
|
156
|
+
end
|
157
|
+
return @aliases
|
158
|
+
end
|
159
|
+
|
140
160
|
# COMMENTED FIELDS
|
141
161
|
# --------------------------------------
|
142
162
|
# <column caption='Calculation1' datatype='real' name='[Calculation_821344020759588865]' role='measure' type='quantitative'>
|
data/lib/twb/datasource.rb
CHANGED
@@ -235,8 +235,14 @@ module Twb
|
|
235
235
|
'Parameters'.eql? @name
|
236
236
|
end
|
237
237
|
|
238
|
+
def columnField fieldName
|
239
|
+
loadColumnFields if @columnFieldsMap.nil?
|
240
|
+
@columnFieldsMap[ fieldName ]
|
241
|
+
end
|
242
|
+
|
243
|
+
|
238
244
|
def columnFields
|
239
|
-
@columnFields ||=
|
245
|
+
@columnFields ||= loadColumnFields
|
240
246
|
end
|
241
247
|
|
242
248
|
def columnFieldsMap
|
data/lib/twb/tabtool.rb
CHANGED
@@ -0,0 +1,105 @@
|
|
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 Util
|
23
|
+
|
24
|
+
class AtomizeCSVRecords
|
25
|
+
|
26
|
+
include TabTool
|
27
|
+
# include Graph
|
28
|
+
|
29
|
+
attr_reader :metrics
|
30
|
+
attr_accessor :ttdocdir
|
31
|
+
|
32
|
+
@@ttlogfile = 'AtomizeCSVRecords.ttlog'
|
33
|
+
@@csvFileName = 'AtomizedCSVRecords.csv'
|
34
|
+
|
35
|
+
def initialize(**args)
|
36
|
+
@ttdocdir = @args[:ttdocdir]
|
37
|
+
@csvAdd = @args[:csvMode] == :add
|
38
|
+
@csvMode = @csvAdd ? 'a' : 'w'
|
39
|
+
init
|
40
|
+
@funcdoc = {:class=>self.class, :blurb=>'Analyze Calculated Fields', :description=>'Calculated fields can be complex, this tool provides robust coverage.',}
|
41
|
+
# --
|
42
|
+
@executed = false
|
43
|
+
end
|
44
|
+
|
45
|
+
def loadFields fileName
|
46
|
+
fields = Set.new
|
47
|
+
file = File.open(fileName)
|
48
|
+
unless file.nil?
|
49
|
+
file.each_line { |line|
|
50
|
+
fields.add line.chomp
|
51
|
+
}
|
52
|
+
end
|
53
|
+
return fields
|
54
|
+
end
|
55
|
+
|
56
|
+
def processTWB workbook
|
57
|
+
puts "\n\t ALERT: Utility tool: #{self.class} - does not implement Workbook processing"
|
58
|
+
puts "\t - deferring to single execution"
|
59
|
+
processData fileName
|
60
|
+
end
|
61
|
+
|
62
|
+
def processData fileName
|
63
|
+
unless @executed
|
64
|
+
emit true, "initialize AtomizeCSVRecords args #{args}"
|
65
|
+
@atomicCSV = CSV.open(@@csvFileName, 'w')
|
66
|
+
# --
|
67
|
+
inputFileName = fileName.nil? ? 'csvData.csv' : fileName
|
68
|
+
keyFields = loadFields 'key.fields'
|
69
|
+
excludeFields = loadFields 'exclude.fields'
|
70
|
+
puts "\t Using these key fields: #{$keyFields.inspect}"
|
71
|
+
puts "\t Excluding these fields: #{$excludeFields.inspect}"
|
72
|
+
|
73
|
+
$fieldValsCSV = '.csv'
|
74
|
+
$atomicCSV = CSV.open($fieldValsCSV, 'w')
|
75
|
+
$atomicFields = $keyFields.to_a + [ 'Rec #', 'Field', 'Value' ]
|
76
|
+
puts "\n\t CSV output fields: #{$atomicFields.inspect}"
|
77
|
+
$atomicCSV << $atomicFields
|
78
|
+
|
79
|
+
|
80
|
+
$recCnt, $fldsCnt = 0, 0
|
81
|
+
|
82
|
+
$recNum = 0
|
83
|
+
|
84
|
+
@executed = true
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def metrics
|
89
|
+
@metrics ||= loadMetrics
|
90
|
+
end
|
91
|
+
|
92
|
+
def loadMetrics
|
93
|
+
@metrics = {
|
94
|
+
'# of Data Sources' => @dataSourcesCount,
|
95
|
+
'# of Calculated Fields' => @calculatedFieldsCount,
|
96
|
+
'# of Referenced Fields' => @referencedFieldsCount,
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
#-- private methods begin here, to end of class
|
101
|
+
|
102
|
+
end # class
|
103
|
+
|
104
|
+
end # module Analysis
|
105
|
+
end # module Twb
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# CSVRecordsAtomizer.rb - this Ruby script Copyright 2019 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 'csv'
|
17
|
+
|
18
|
+
module Twb
|
19
|
+
module Util
|
20
|
+
|
21
|
+
class CSVRecordsAtomizer
|
22
|
+
|
23
|
+
include TabTool
|
24
|
+
|
25
|
+
attr_reader :metrics
|
26
|
+
attr_accessor :ttdocdir
|
27
|
+
|
28
|
+
@@ttlogfile = 'AtomizeCSVRecords.ttlog'
|
29
|
+
@@csvFileName = 'AtomizedCSVRecords.csv'
|
30
|
+
@@atomFields = ['Record #', 'Field Name', 'Field Value']
|
31
|
+
|
32
|
+
def initialize(**args)
|
33
|
+
@args = args
|
34
|
+
@ttdocdir = @args[:ttdocdir]
|
35
|
+
@csvAdd = @args[:csvMode] == :add
|
36
|
+
@csvMode = @csvAdd ? 'a' : 'w'
|
37
|
+
init
|
38
|
+
@funcdoc = {:class=>self.class, :blurb=>'Analyze Calculated Fields', :description=>'Calculated fields can be complex, this tool provides robust coverage.'}
|
39
|
+
# --
|
40
|
+
@executed = false
|
41
|
+
end
|
42
|
+
|
43
|
+
def processFile fileName
|
44
|
+
emit true, "#{self.class} - processFile: #{fileName} :: #{fileName.class}"
|
45
|
+
# --
|
46
|
+
srcFields = Set.new CSV.open(fileName, 'r:bom|utf-8', &:readline)
|
47
|
+
emit true, "\t Inspecting these #{srcFields.length} #{srcFields.class} fields: "
|
48
|
+
keyFields = loadFields(fileName, :keyfields)
|
49
|
+
excludeFields = loadFields(fileName, :excludefields)
|
50
|
+
recordFields = (srcFields - keyFields - excludeFields).to_a
|
51
|
+
emit true, "\t Using these key fields: #{keyFields.inspect}"
|
52
|
+
emit true, "\t Excluding these fields: #{excludeFields.inspect}"
|
53
|
+
emit true, "\t Recording these fields: #{recordFields.inspect}"
|
54
|
+
# --
|
55
|
+
atomizedFields = keyFields.to_a + @@atomFields
|
56
|
+
dataBaseName = File.basename(fileName, ".*")
|
57
|
+
atomizedCSVFile = "#{dataBaseName}.Atomized.csv"
|
58
|
+
atomizedCSVFile = CSV.open(atomizedCSVFile,'w')
|
59
|
+
atomizedCSVFile << keyFields.to_a + @@atomFields
|
60
|
+
# --
|
61
|
+
@recNum = 0
|
62
|
+
CSV.open(fileName, 'r:bom|utf-8', headers: true) do |csv|
|
63
|
+
csv.each do |row|
|
64
|
+
@recNum += 1
|
65
|
+
atomRec = []
|
66
|
+
keyFields.each do |kf|
|
67
|
+
atomRec << row.fetch(kf)
|
68
|
+
end
|
69
|
+
atomRec << @recNum
|
70
|
+
recordFields.each do |rf|
|
71
|
+
atomizedCSVFile << atomRec + [rf, row.fetch(rf)]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def loadFields fileName, type
|
80
|
+
puts "\n\n\t loadFields -#{fileName}- -#{type}-"
|
81
|
+
fields = Set.new
|
82
|
+
auxFile = "#{fileName}.#{type}"
|
83
|
+
isAuxFile = File.exist?(auxFile)
|
84
|
+
emit true, "\t\t Loading auxilary data: %-12s %7s %-s" % [type, isAuxFile, auxFile]
|
85
|
+
if isAuxFile
|
86
|
+
# file = File.open(fileName)
|
87
|
+
File.open(auxFile).each_line { |line|
|
88
|
+
fields.add line.chomp
|
89
|
+
}
|
90
|
+
end
|
91
|
+
return fields.to_a
|
92
|
+
end
|
93
|
+
|
94
|
+
def processData fileName
|
95
|
+
end
|
96
|
+
|
97
|
+
def metrics
|
98
|
+
@metrics ||= loadMetrics
|
99
|
+
end
|
100
|
+
|
101
|
+
def loadMetrics
|
102
|
+
@metrics = {
|
103
|
+
'# of Data Sources' => @dataSourcesCount,
|
104
|
+
'# of Calculated Fields' => @calculatedFieldsCount,
|
105
|
+
'# of Referenced Fields' => @referencedFieldsCount,
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
#-- private methods begin here, to end of class
|
110
|
+
|
111
|
+
end # class
|
112
|
+
|
113
|
+
end # module Analysis
|
114
|
+
end # module Twb
|
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.
|
4
|
+
version: 4.9.0
|
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-
|
11
|
+
date: 2019-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: creek
|
@@ -63,15 +63,20 @@ files:
|
|
63
63
|
- lib/twb/analysis/annotatedfieldscsvemitter.rb
|
64
64
|
- lib/twb/analysis/calculatedfields/calculatedfieldsanalyzer.rb
|
65
65
|
- lib/twb/analysis/calculatedfields/csvemitter.rb
|
66
|
+
- lib/twb/analysis/calculatedfields/fieldsaliasesanalyzer.rb
|
66
67
|
- lib/twb/analysis/calculatedfields/groupfieldsanalyzer.rb
|
67
68
|
- lib/twb/analysis/calculatedfields/markdownemitter.rb
|
68
69
|
- lib/twb/analysis/datasources/categoricalcolorcodinganalyzer.rb
|
69
70
|
- lib/twb/analysis/datasources/datasourcefieldsanalyzer.rb
|
70
71
|
- lib/twb/analysis/datasources/datasourcefieldscsvemitter.rb
|
72
|
+
- lib/twb/analysis/datasources/datasourcefilesanalyzer.rb
|
71
73
|
- lib/twb/analysis/datasources/datasourceoriginsanalyzer.rb
|
72
74
|
- lib/twb/analysis/datasources/datasourcesenumerator.rb
|
73
75
|
- lib/twb/analysis/datasources/datasourceslocationsanalyzer.rb
|
76
|
+
- lib/twb/analysis/datasources/datasourcetablefieldsanalyzer.rb
|
74
77
|
- lib/twb/analysis/datasources/datasourcetablefieldscsvemitter.rb
|
78
|
+
- lib/twb/analysis/datasources/extractsanalyzer.rb
|
79
|
+
- lib/twb/analysis/datasources/fieldsaliasesanalyzer.rb
|
75
80
|
- lib/twb/analysis/datasources/googlesheetdatasourcesanalyzer.rb
|
76
81
|
- lib/twb/analysis/datasources/parametersanalyzer.rb
|
77
82
|
- lib/twb/analysis/documentedfieldscsvemitter.rb
|
@@ -84,6 +89,7 @@ files:
|
|
84
89
|
- lib/twb/analysis/sheets/sheetsintooltipanalyzer.rb
|
85
90
|
- lib/twb/analysis/sheets/sheetsourcesanalyzer.rb
|
86
91
|
- lib/twb/analysis/sheets/worksheetdatastructurecsvemitter.rb
|
92
|
+
- lib/twb/analysis/sheets/worksheetsummarizer.rb
|
87
93
|
- lib/twb/analysis/workbooksummaryanalyzer.rb
|
88
94
|
- lib/twb/calculatedfield.rb
|
89
95
|
- lib/twb/codedfield.rb
|
@@ -118,6 +124,8 @@ files:
|
|
118
124
|
- lib/twb/there.rb
|
119
125
|
- lib/twb/twbcodedfield.rb
|
120
126
|
- lib/twb/twbtest.rb
|
127
|
+
- lib/twb/util/atomizecsvrecords.rb
|
128
|
+
- lib/twb/util/csvrecordsatomizer.rb
|
121
129
|
- lib/twb/util/cypher.rb
|
122
130
|
- lib/twb/util/cypherpython.rb
|
123
131
|
- lib/twb/util/docprep.rb
|