Last active
October 18, 2023 18:36
-
-
Save KobaKhit/c4f0d3b80e2471ca027d321ce6fb4912 to your computer and use it in GitHub Desktop.
A simple class that enables you to download (workbooks) or (csv from views) from a Tableau Server.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import tableauserverclient as TSC | |
import pandas as pd | |
from io import StringIO | |
class Tableau_Server(object): | |
"""docstring for ClassName""" | |
def __init__(self,username, password,site_id,url, https = False): | |
super().__init__() # http://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods | |
# authorize | |
tableau_auth = TSC.TableauAuth(username, password, site_id) | |
server = TSC.Server(url) | |
server.add_http_options({'verify': https}) # if not https server skip warnings | |
server.auth.sign_in(tableau_auth) | |
server.use_highest_version() # make sure to use the same api version as server | |
server.server_info.get() | |
self.server = server | |
# get all workbooks in site | |
self.all_books, pagination_item = self.server.workbooks.get() | |
self.all_books_names = [wb.name for wb in self.all_books] | |
print('\nThere are {} workbooks on "{}" Tableau Server site.'.format(pagination_item.total_available,site_id)) | |
def check_wb_name(self,wb_name): | |
# check if workbook exists | |
if wb_name not in self.all_books_names: | |
print('Workbook with name {} not found.'.format(wb_name)) | |
return | |
def download_wb(self,wb_name): | |
# downlaod workbook given workbook name | |
self.check_wb_name(wb_name) | |
wb = [w for w in self.all_books if w.name == wb_name][0] | |
self.server.workbooks.download(wb.id) | |
def download_view_csv(self,wb_name, view_name = None): | |
# downlaod view csv given workbook name and view name (optional) | |
self.check_wb_name(wb_name) | |
wb = [w for w in self.all_books if w.name == wb_name][0] | |
# request views | |
self.server.workbooks.populate_views(wb) | |
views = [view for view in wb.views] | |
view_names = [view.name for view in wb.views] | |
if view_name is not None and view_name not in view_names: | |
print('View with name "{}" not found in workbook "{}". Below are available views.'.format(view_name,wb_name)) | |
print(view_names) | |
return | |
# get either first view or user defined view | |
view_item = [view for view in views][0] | |
if view_name is not None: | |
view_item = [view for view in views if view.name == view_name][0] | |
self.server.views.populate_csv(view_item) # request view csv | |
# Perform byte join on the CSV data | |
string = StringIO(b''.join(view_item.csv).decode("utf-8")) | |
df = pd.read_csv(string, sep=",") | |
# pivot view csv so its in wide format if there is "Measure Values" column | |
# if not just save to csv | |
if 'Measure Values' not in df.columns.values: | |
df.to_csv('{}.csv'.format(view_item.name), index = False) | |
return | |
df['Measure Values'] = pd.to_numeric(df['Measure Values'].str.replace('\\,|\\$|\\%', '')) | |
cols = [c for c in df.columns.values if c not in ('Measure Values','Measure Names')] | |
df = pd.pivot_table(df,values = 'Measure Values', columns = 'Measure Names', index = cols).reset_index() | |
df.to_csv('{}.csv'.format(view_item.name), index = False) | |
def main(): | |
username = '' | |
password = '' | |
site_id = '' | |
url = '' | |
ts = Tableau_Server(username,password,site_id,url) | |
# download a workbook | |
ts.download_wb('First Touch Report') | |
# download a view csv | |
ts.download_view_csv('First Touch Report','First Touch Report') | |
if __name__ == '__main__': | |
main() | |
hey @rodrigopizzano,
i need to retain columns order of the view (avoid the alphabetic order), so can you help with the case when Measure Names and Measure Values is not present. It would be great if you can share your reorganise function here in the gist comments. Thanks.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello again.
Allow me to suggest something. In order to avoid the alphabetic order for the columns you can store the original order in a list and then pass that list to the final datafarme. Also order the rows by the "cols" index would be helpfull.
Something like this:
Let me know what you think!