forked from tableau/document-api-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathworkbook.py
More file actions
119 lines (85 loc) · 3.28 KB
/
workbook.py
File metadata and controls
119 lines (85 loc) · 3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import weakref
from tableaudocumentapi import Datasource, Worksheet, xfile
from tableaudocumentapi.xfile import xml_open
class Workbook(object):
"""A class for writing Tableau workbook files."""
def __init__(self, filename):
"""Open the workbook at `filename`. This will handle packaged and unpacked
workbook files automatically. This will also parse Data Sources and Worksheets
for access.
"""
self._filename = filename
self._workbookTree = xml_open(self._filename, 'workbook')
self._workbookRoot = self._workbookTree.getroot()
# prepare our datasource objects
self._datasources = self._prepare_datasources(
self._workbookRoot) # self.workbookRoot.find('datasources')
self._datasource_index = self._prepare_datasource_index(self._datasources)
self._worksheets = self._prepare_worksheets(
self._workbookRoot, self._datasource_index
)
@property
def datasources(self):
return self._datasources
@property
def worksheets(self):
return self._worksheets
@property
def filename(self):
return self._filename
def save(self):
"""
Call finalization code and save file.
Args:
None.
Returns:
Nothing.
"""
# save the file
xfile._save_file(self._filename, self._workbookTree)
def save_as(self, new_filename):
"""
Save our file with the name provided.
Args:
new_filename: New name for the workbook file. String.
Returns:
Nothing.
"""
xfile._save_file(
self._filename, self._workbookTree, new_filename)
@staticmethod
def _prepare_datasource_index(datasources):
retval = weakref.WeakValueDictionary()
for datasource in datasources:
retval[datasource.name] = datasource
return retval
@staticmethod
def _prepare_datasources(xml_root):
datasources = []
# loop through our datasources and append
datasource_elements = xml_root.find('datasources')
if datasource_elements is None:
return []
for datasource in datasource_elements:
ds = Datasource(datasource)
datasources.append(ds)
return datasources
@staticmethod
def _prepare_worksheets(xml_root, ds_index):
worksheets = []
worksheets_element = xml_root.find('.//worksheets')
if worksheets_element is None:
return worksheets
for worksheet_element in worksheets_element:
worksheet_name = worksheet_element.attrib['name']
worksheet = Worksheet(worksheet_element)
worksheets.append(worksheet)
dependencies = worksheet_element.findall('.//datasource-dependencies')
for dependency in dependencies:
datasource_name = dependency.attrib['datasource']
datasource = ds_index[datasource_name]
for column in dependency.findall('.//column'):
column_name = column.attrib['name']
if column_name in datasource.fields:
datasource.fields[column_name].add_used_in(worksheet_name)
return worksheets