The Embedding API v3 provides methods that you can use to access the data in an embedded view. The data you can access includes the summary or aggregated data, and also the underlying data (or full data). In addition, the Tableau data model has two layers, a logical layer and the underlying physical layer.
For information about the structure of the data model, see The Tableau Data Model.
In the embedded view, there are three sources of data that you can query.
The following section describes how to obtain data from the worksheet and the data source. For information about how to get data from selected marks, see Select Marks in the View.
In this section
Before you access data in a view, it might be helpful to understand how Tableau structures the data. To that end this section provides a brief description of some of the key components that you need to use to retrieve data using the Embedding API v3.
Starting in Tableau 2020.2, with the introduction of the new data model and logical tables, you need to use the Worksheet.getUnderlyingTablesAsync
method or the Datasource.getLogicalTablesAsync
method to first return the array of LogicalTable
objects. The LogicalTable
objects returned are determined by the measures in the worksheet. The LogicalTable
objects correspond to the tables shown in the default view on the Data Source page in Tableau. These tables make up the logical layer. You can retrieve the underlying or logical data from each LogicalTable
in the worksheet or data source.
Object/Property | Description |
---|---|
LogicalTable |
Object that represents a logical table in a data source, or logical table used in a worksheet |
LogicalTable.caption |
The name of the logical table as it appears in Tableau. |
LogicalTable.id |
The identifier used to specify the logical table. Use this value to call Worksheet.getUnderlyingTableDataAsync and Worksheet.getUnderlyingTableDataReaderAsync , or Datasource.getLogicalTableDataAsync and Datasource.getLogicalTableDataReaderAsync . |
In the Embedding API v3, the data is returned from an embedded view in a DataTable
object. The DataTable
object contains the columns and data values, and information about the data, whether it is underlying or summary data, and in the case of underlying data, whether there is more data than can be returned in a single call. If there are more rows of data than can be returned (10,000 rows for getUnderlyingTableDataAsync
and getLogicalTableDataAsync
), you can use a method that returns a DataTableReader
. The DataTableReader
makes it easy to page through and retrieve a large amount of data.
The DataTableReader
returns information about the total number of rows of data, and the number of pages of data available. Each page is a DataTable
. You can use the DataTableReader
to get all pages or to get specific pages. For more information, see DataTableReader.
Note: The DataTableReader method, Worksheet.getSummaryDataReaderAsync()
, returns the DataTable
with its colunms sorted in alphabetical (ascending) order and not in the order the fields (columns) appear in the Tableau view. For more information, see Sort order and the DataTableReader.
When you embed a Tableau view into your web application, you need to consider whether users will have permission to see that view and have access to the underlying data. The Embedding API allows access to the data in the embedded view based upon a user’s role (creator, explorer, viewer) and permissions granted to that role. When someone accesses the Tableau view embedded in your web application, the same authentication and permissions apply as if they were accessing the view on Tableau directly.
Data Methods | Viewer | Explorer | Creator |
---|---|---|---|
Worksheet.getSummaryDataReaderAsync |
x | x | x |
Worksheet.getSummaryDataAsync |
x | x | x |
Worksheet.getUnderlyingDataAsync |
x | x | |
Worksheet.getUnderlyingTableDataAsync |
x | x | |
Worksheet.getUnderlyingTableDataReaderAsync |
x | x | |
Worksheet.getUnderlyingTablesAsync |
x | x | |
Datasource.getLogicalTableDataAsync , Datasource.getLogicalTableDataReaderAsync |
x | x |
The Embedding API v3 provides several methods for accessing data from an embedded view. The method you use depends in part upon how you want to use the data. When you have the worksheet object, you can get the summary data (aggregated data) or the full data (underlying data) directly from the worksheet using these methods:
Method | Tableau Version | Embedding API v3 Library | Returns | Status |
---|---|---|---|---|
Worksheet.getSummaryDataAsync() |
2022.3 and later | 3.3 and later | DataTable | Deprecated |
Worksheet.getSummaryDataReaderAsync() |
2022.4 and later | 3.4 and later | DataTableReader | Current |
Worksheet.getUnderlyingDataAsync() |
2022.3 | 3.3 | DataTable | Deprecated |
Worksheet.getUnderlyingTableDataAsync |
2022.3 and later | 3.3 and later | DataTable | Current |
Worksheet.getUnderlyingTableDataReaderAsync |
2022.4 and later | 3.3 and later | DataTableReader | Current |
Worksheet.getUnderlyingTablesAsync |
2022.3 and later | 3.3 and later | LogicalTable | Current |
Summary data, or aggregated data, is the data visible in a worksheet. To get the summary data you must first access the worksheet object. After you have the worksheet, you can call the methods to retrieve the data. Starting with Tableau 2022.4 and with Embedding API 3.4.0 library, you should use the getSummaryDataReaderAsync()
method.
getSummaryDataAsync
is deprecated, as it could fail when called on a worksheet that has many rows of data. Use the getSummaryDataReaderAsync()
method instead.
getAllPagesAsync
for summary data (less than 4M)If your summary data is less than 4,000,000 rows, you can use the getAllPagesAsync()
method to retrieve a single DataTable
from the DataTableReader
. The following example shows how to do this.
Get the currently active worksheet.
From the worksheet, use the getSummaryDataReaderAsync
method to create the DataTableReader
.
Call the getAllPagesAsync
method to return all of the summary data (up to 4,000,000 rows, or 400 pages).
After you have retrieved the summary data, call the releaseAsync
method to free up the DataTableReader
.
// Use `await` only inside an `async` method
let vizActiveSheet = viz.workbook.activeSheet;
if (vizActiveSheet.sheetType === "worksheet") {
const dataTableReader = await vizActiveSheet.getSummaryDataReaderAsync();
const dataTable = await dataTableReader.getAllPagesAsync();
await dataTableReader.releaseAsync();
// ... process data table ...
}
getSummaryDataReaderAsync
for summary data (greater than 4M)If your summary data contains more than 4,000,000 rows (or 400 pages), use the summary DataTableReader
to iterate through the pages of data for all rows in the worksheet. In this case, you process each DataTable
sequentially. You can control the page size, using the optional pageRowCount
parameter when you call getSummaryDataReaderAsync
. The default page size is 10,000 rows.
Get the currently active worksheet.
From the worksheet, use the getSummaryDataReaderAsync
method to create the DataTableReader
.
Create a loop to retrieve each page of summary data, using DataTableReader.pageCount
or DataTableReader.totalRowCount
property of the summary DataTableReader
to determine the number of pages to process.
Use the getPageAsync
method to get the DataTable from each page.
After you have retrieved all pages of the summary data, call the releaseAsync
method to free up memory from the DataTableReader
.
// Use `await` only inside an `async` method
let vizActiveSheet = viz.workbook.activeSheet;
if (vizActiveSheet.sheetType === "worksheet") {
const dataTableReader = await vizActiveSheet.getSummaryDataReaderAsync();
for (let currentPage = 0; currentPage < dataTableReader.pageCount; currentPage++) {
const dataTablePage = await dataTableReader.getPageAsync(currentPage);
// ... process current page ....
}
// free up resources
await dataTableReader.releaseAsync();
}
Underlying data, or full data, is all the data in the workbook, not just the data available in the current view. There are two methods you can use to retrieve this data. Which one you use depends upon the amount of underlying data there is. If you have less than 10,000 rows of data, use Worksheet.getUnderlyingTableDataAsync
. If you have more, you can use the DataTableReader (getUnderlyingTableDataReaderAsync
) to retrieve pages of data.
Use getUnderlyingTableDataAsync
for less than 10K rows of data
Use getUnderlyingTableDataReaderAsync
for more than 10K rows of data
getUnderlyingTableDataAsync
for less than 10K rows of dataIf the data doesn’t contain more than 10,000 rows, you can use the getUnderlyingTableDataAsync
method to get data from a worksheet. The basic steps are as follows:
From the worksheet, call the getUnderlyingTablesAsync
method to return the array of logical tables.
Using the logicalTable.id
, call the getUnderlyingTableDataAsync
method to return a DataTable
containing the underlying data (up to 10,000 rows) for the logical table. Repeat this step for each logical table.
You can specify the number of rows of data to return by setting GetUnderlyingDataOptions.maxRows
property. If unspecified (maxRows == '0'
), the call to getUnderlyingTableDataAsync
requests all rows in the logical table. Note that the maximum number of rows returned from the getUnderlyingTableDataAsync
method is limited to 10,000 rows. You can use the DataTable
property, isTotalRowCountLimited
, to test whether there is more data. A value of true indicates that the calling function requested more rows than the limit (10,000) and the underlying data source contains more rows than can be returned. If the data contains more than 10,000 rows, use getUnderlyingTableDataReaderAsync
method instead.
// assumes this code is in an async method
const sheet = viz.workbook.activeSheet.worksheets.find(sheet => sheet.name === "Storm Map Sheet");
const tables = await sheet.getUnderlyingTablesAsync();
const options = {
maxRows: 1000, // Max rows to return. Use 0 to return all rows.
ignoreAliases: false,
ignoreSelection: true,
includeAllColumns: false
}
const underlyingTableData = await sheet.getUnderlyingTableDataAsync(tables[0].id, options);
getUnderlyingTableDataReaderAsync
for more than 10K rows of dataIf the data contains more than 10,000 rows, use the getUnderlyingTableDataReaderAsync
method to get data from a worksheet. In this case, you create a DataTableReader
to iterate through the pages of data. You process each DataTable
sequentially. You can control the page size, using the optional pageRowCount
parameter when you call getUnderlyingTableDataReaderAsync
. The default page size is 10,000 rows.
The basic steps are as follows:
From the worksheet, call the getUnderlyingTablesAsync
method to return the array of logical tables.
Using the logicalTable.id
, call the getUnderlyingTableDataReaderAsync
method to create the DataTableReader
.
Create a loop to retrieve each page of underlying data, using DataTableReader.pageCount
or DataTableReader.totalRowCount
property of the DataTableReader
to determine the number of pages to process.
Use the getPageAsync
method to get the DataTable from each page.
After you have retrieved all pages of the summary data, call the releaseAsync()
method to free up memory from the DataTableReader
.
// assumes this code is in an async method
let vizActiveSheet = viz.workbook.activeSheet;
if (vizActiveSheet.sheetType === "worksheet") {
// Call to get the underlying logical tables used by the worksheet
const underlyingTablesData = await vizActiveSheet.getUnderlyingTablesAsync();
const logicalTableId = underlyingTablesData[0].id;
// Use the above logicalTableId to get the underlying data reader on the active sheet
const dataTableReader = await vizActiveSheet.getUnderlyingTableDataReaderAsync(logicalTableId);
// loop through the pages
const pageNumber = 0;
while (pageNumber < dataTableReader.pageCount) {
let currentPageDataTable = await dataTableReader.getPageAsync(pageNumber);
// process page ...
console.log(currentPageDataTable);
pageNumber++;
}
// free up resources
await pageReader.releaseAsync();
}
The getUnderlyingTableDataReaderAsync
method attempts to prepare all the rows of the table to be read as pages. There is a limit to the number of rows that can be prepared to conserve computing resources. The default limit is 1 million rows of data. You can change this default row limit with the Tableau Server and Tableau Cloud ExtensionsAndEmbeddingReaderRowLimit
option.
If the underlying table has many columns, getUnderlyingTableDataReaderAsync
can be sped up by only requesting native data values (IncludeDataValuesOption.OnlyNativeValues
) in the GetUnderlyingDataOptions
.
The Embedding API v3 provides methods for accessing data from the data sources used by a worksheet. To get the data sources, you call the getDataSourcesAsync
method from the worksheet. The method returns an array of data sources. The first data source in the array is the primary data source, additional data sources, if any, are secondary sources. Note that calling getDataSourcesAsync
might negatively impact performance and responsiveness of the view that you are embedding. The method is partly asynchronous but includes some serial operations.
To get data from a data source, you can use a couple of different methods. Which one you use depends upon the amount of data there is. If you have less than 10,000 rows of data, use Datasource.getLogicalTableDataAsync
. If you have more, use the DataTableReader (Datasource.getLogicalTableDataReaderAsync
) to retrieve pages of data.
Method | Tableau Version | Embedding API v3 Library | Status |
---|---|---|---|
Datasource.getLogicalTableDataAsync |
Tableau 2022.4 and later | version 3.4 and later | Current |
Datasource.getLogicalTableDataReaderAsync |
Tableau 2022.4 and later | version 3.4 and later | Current |
Datasource.getLogicalTablesAsync |
Tableau 2022.3 and later | version 3.3 and later | Current |
Datasource.getUnderlyingDataAsync |
Tableau 2022.3 and later | version 3.3 and later | Deprecated |
getLogicalTableDataAsync
for less than 10K rows in the data sourceIf the data doesn’t contain more than 10,000 rows, you can use the getLogicalTableDataAsync
method to get data from a data source. The basic steps are as follows:
From the data source, call the geLogicalTablesAsync
method to return the array of logical tables.
Using the logicalTable.id
, call the getLogicalTableDataAsync
method to return a DataTable
containing the underlying data (up to 10,000 rows) for the logical table. Repeat this step for each logical table.
You can specify the number of rows of data to return by setting DataSourceUnderlyingDataOptions.maxRows
property. If unspecified (maxRows == '0'
), the call to getLogicalTableDataAsync
requests all rows in the logical table. Note that the maximum number of rows returned from the getLogicalTableDataAsync
method is limited to 10,000 rows. You can use the DataTable
property, isTotalRowCountLimited
, to test whether there is more data. A value of true indicates that the calling function requested more rows than the limit (10,000) and the logical data source contains more rows than can be returned. If the data contains more than 10,000 rows, use getLogicalTableDataReaderAsync
method instead.
The following example shows use of the getLogicalTableDataAsync
method to get the data from a specific logical table in a data source. The example uses the JavaScript find()
method to select the workbook, and uses the getLogicalTablesAsync
method to get the array of data tables. This example gets the data from the first logical table.
// assumes that this code is in an async function
const dataSources = await worksheet.getDataSourcesAsync();
const dataSource = dataSources.find(datasource => datasource.name === "Sample - Superstore");
const logicalTables = await dataSource.getLogicalTablesAsync()
const dataTable = await dataSource.getLogicalTableDataAsync(logicalTables[0].id);
console.log(dataTable);
getLogicalTableDataReaderAsync
for more than 10K rows in the data sourceIf the data contains more than 10,000 rows, use the getLogicalTableDataReaderAsync
method to get data from a data source. In this case, you create a DataTableReader
to iterate through the pages of data for all rows in the worksheet. You process each DataTable
sequentially. You can control the page size, using the optional pageRowCount
parameter when you call getLogicalTableDataReaderAsync
. The default page size is 10,000 rows.
The basic steps are as follows:
From the worksheet, call the getLogicalTablesAsync
method to return the array of logical tables.
Using the logicalTable.id
, call the getLogicalTableDataReaderAsync
method to create the DataTableReader
.
Create a loop to retrieve each page of logical data, using DataTableReader.pageCount
or DataTableReader.totalRowCount
property of the summary DataTableReader
to determine the number of pages to process.
Use the getPageAsync()
method to get the DataTable
from each page.
After you have retrieved all pages of the data, call the releaseAsync()
method to free up memory from the DataTableReader
.
// assumes this code is in an async method
const pageRowCount = 1000; // default is 10,000
const dataSources = await worksheet.getDataSourcesAsync();
const dataSource = dataSources.find(datasource => datasource.name === "Sample - Superstore");
const logicalTables = await dataSource.getLogicalTablesAsync()
const dataTableReader = await dataSource.getLogicalTableDataReaderAsync(logicalTables[0].id, pageRowCount);
const pageNumber = 0;
while (pageNumber < dataTableReader.pageCount) {
let currentPageDataTable = await dataTableReader.getPageAsync(pageNumber);
// process page ...
console.log(currentPageDataTable);
pageNumber++;
}
// release resources
await pageReader.releaseAsync();
getLogicalTableDataReaderAsync
to retrieve selected data from the data sourceThe following example shows how you could use the getLogicalTableDataReaderAsync
and getAllPagesAsync
methods to prepare pages of 10,000 rows each, and then how to get a maximum of 150,000 rows of native data from a specific logical table in a data source.
const dataSources = await worksheet.getDataSourcesAsync();
const dataSource = dataSources.find(datasource => datasource.name === "Sample - Superstore");
const logicalTables = await dataSource.getLogicalTablesAsync()
const dataTableReader = await dataSource.getLogicalTableDataReaderAsync(logicalTables[0].id, 10000,
{ includeDataValuesOption: tableau.IncludeDataValuesOption.OnlyNativeValues });
const dataTable = await dataTableReader.getAllPagesAsync(150000);
console.log(dataTable);
// release resources
await dataTableReader.releaseAsync();
The getLogicalTableDataReaderAsync
method attempts to prepare all the rows of the table to be read as pages. There is a limit to the number of rows that can be prepared to conserve computing resources. The default limit is approximately 32 million cells (rows * columns).
However, if the data source has many columns, this number will be adjusted downward. You can change the default limit with the Tableau Server and Tableau Cloud ExtensionsAndEmbeddingReaderCellLimit
option.
If the data source has many columns, you can improve the performance of getLogicalTableDataReaderAsync
by only requesting native data values. This is shown in the example by specifying tableau.IncludeDataValuesOption.OnlyNativeValues
as one of the GetUnderlyingDataOptions
.
The DataTableReader
sorts columns in alphabetical (ascending) order. If you use the getSummaryDataReaderAsync()
method be aware that the columns in the summary data are not sorted in the order they appear in the Tableau view or in the View Data dialog box. If you want the summary data sorted as it appears in the Tableau view or the View Data dialog box, you’ll want to map the indices of columns as you read from the pages of the DataTable
. If you want to use each page to construct a larger data table, you can use the index map and rearrange the data as you’re constructing the larger data table.
The following example code shows how you might use the getSummaryColumnsInfoAsync()
method to create an index map that you can use to read the data in the order the columns appear in the view. When you call the getSummaryDataReaderAsync()
method it returns a DataTableReader
. In the example, the DataTableReader
gets the first page of summary data. The example then creates an index map (using the column fieldId
) that is used to iterate over the rows of data in the DataTable
, reading the columns of data in view order. If you had multiple pages of summary data, you could add code to loop through those.
Note that you can specify the columns to include when you call getSummaryDataReaderAsync()
, but you can’t specify the sort order.
Example showing how to read from the summary data table in view order
let dataTableReader;
try {
// Gets an array of columns with the same order as the columns in the Tableau view.
const columns = await worksheet.getSummaryColumnsInfoAsync();
// Get the DataTableReader and the first DataTable page (assumes dataTableReader.pageCount > 0).
dataTableReader = await worksheet.getSummaryDataReaderAsync();
let dataTablePage = await dataTableReader.getPageAsync(0);
// DataTable is sorted in alphabetical (ascending) order.
const sortedColumns = dataTablePage.columns;
// To read the DataTable's columns in the Tableau view order we must map the 'columns' array to the
// indices of the 'sortedColumns' array using the 'fieldId' identifier.
const indexMap = [];
columns.forEach((column) => {
// find index of 'column' in 'sortedColumns' array
for (let index = 0; index < sortedColumns.length; index++) {
if (column.fieldId === sortedColumns[index].fieldId) {
indexMap.push(index);
break;
}
}
});
// Process first DataTable page, iterating over each row.
for (let rowIndex = 0; rowIndex < dataTablePage.totalRowCount; rowIndex++) {
let row = dataTablePage.data[rowIndex];
// For a given row, iterate over the columns in order of Tableau view using the 'indexMap'.
for (let columnIndex = 0; columnIndex < indexMap.length; columnIndex++) {
let mappedIndex = indexMap[columnIndex];
let dataValue = row[mappedIndex];
// Process data value here.
}
}
// Iterate over the remaining DataTable pages.
for (let currentPage = 1; currentPage < dataTableReader.pageCount; currentPage++) {
dataTablePage = await dataTableReader.getPageAsync(currentPage);
// Process remaining DataTable pages here
// (similarly to how the first DataTable page was processed in the code above).
}
} finally {
// free up allocated resources
if (dataTableReader) {
await dataTableReader.releaseAsync();
}
}