The Tableau Hyper API is an amazingly powerful tool for building out Extracts that, for whatever reason, cannot be built or maintained using the standard Tableau Server extract refresh process. You can publish a Hyper file directly to a Tableau Server, but there are several drawbacks:
- Tableau Server will build out an automatic TDS file, taking a rough guess at any type of metadata categorization (Measure vs. Dimensions, Hierarchies, Geographic info, etc.)
- The only use for this data source will be creating Ad Hoc reports using Web Edit (or hoping someone in Desktop now knows that it exists). You can’t integrate it easily in an existing Workbook
- It only works with Single-Table Extracts, and in older versions of Tableau, the single table must be named “Extract” or you will encounter errors.
What is missing is a TDS file to pair up with the Hyper file, describing the exact metadata that you want to go along with the Extracted data. In this article, I’ll describe a workflow that result in a fully controlled TDSX file with a newly generated Hyper file.
Building a TDSX/TWBX in Desktop, then Dropping in a New Hyper file
This recommended workflow gives you full control of how the metadata will appear to any end users. You set up a template TDSX/TWBX:
- Create the initial .hyper file via the Hyper API
- Open the Hyper file as your Data Source in Tableau Desktop
- Make any changes to the Data Source you would like
- Use the “Add to Saved Data Sources” option to save as a TDSX file OR save the Workbook as a TWBX file.
- For any updates or replacements, programmatically open up the original TDSX or TWBX file and drop in a new .hyper file, then publish using the Tableau Server REST API.
The one requirement for this method is that the schema of your Hyper file should not change after you have built out your template TDSX/TWBX, or things might break.
tableau_tools 5 has a facility designed for this process:
def substitute_an_existing_extract(tableau_packaged_filename: str, new_extract_filename: str, previous_extract_flename_in_packaged_file: Optional[str] = None) -> str: t_file = TableauFileManager.open(filename=tableau_packaged_filename) # See what files might be in there if you need files_in_there = t_file.get_filenames_in_package() if previous_extract_flename_in_packaged_file is not None: existing_hyper_filename = previous_extract_flename_in_packaged_file else: existing_hyper_filename = None # This is simple test on expectation of single Hyper file but you could probably do more for file in files_in_there: if file.lower().find('.hyper') != -1: existing_hyper_filename = file break # Make sure we actually found a Hyper file to replace if existing_hyper_filename is None: print('No Hyper file found to replace, breaking') exit() t_file.set_file_for_replacement(filename_in_package=existing_hyper_filename, replacement_filname_on_disk=new_extract_filename) newly_saved_filename = t_file.save_new_file(filename_no_extension='Swapped Out Hyper') return newly_saved_filename