From 21bfff35e907d78206603fd4fa61c3214c54dc93 Mon Sep 17 00:00:00 2001 From: d45 <3d.hagen@gmail.com> Date: Thu, 15 Dec 2022 15:12:01 -0800 Subject: [PATCH 1/4] Updating release notes 1.10; getdata with DataTableReader --- docs/trex_getdata.md | 179 +++++++++++++++++++++++++++++++------ docs/trex_release-notes.md | 24 ++++- 2 files changed, 173 insertions(+), 30 deletions(-) diff --git a/docs/trex_getdata.md b/docs/trex_getdata.md index d208f319..cfb300aa 100644 --- a/docs/trex_getdata.md +++ b/docs/trex_getdata.md @@ -3,8 +3,7 @@ title: Get Data from the Dashboard layout: docs --- -The Extensions API provides methods that you can use to access the data in a dashboard. -The data you can access includes the summary or aggregated data, that is, the data visible in the worksheet, and also to the underlying data (or full data), which can include data from all fields and tables in the data source. If your extension needs to access the full data, there are security implications and your extension needs to declare its intent, so that users of your extension can choose to allow or deny the extension access. See [Accessing Underlying Data]({{ site.baseurl }}/docs/trex_data_access.html) for more information. +The Dashboard Extensions API provides methods that you can use to access the data in a dashboard. The data you can access includes the summary or aggregated data, and also the underlying data (or full data). If your extension needs to access the full data, there are security implications and your extension needs to declare its intent, so that users of your extension can choose to allow or deny the extension access. See [Accessing Underlying Data]({{ site.baseurl }}/docs/trex_data_access.html) for more information.

Note Tableau 2020.2 introduced a new data model. To support that model, the Extensions API provides new methods and data structures starting with version 1.4 of the Extensions API library. In the new data model, a data source could have multiple logical tables, and logical tables can contain one or more physical tables. If you have an existing extension that uses one of the deprecated methods to get underlying data, the method call could fail if the data source contains more than one logical table. You should update your extensions to use these new methods. The new methods are backward compatible with previous versions of Tableau. @@ -25,20 +24,22 @@ The Extensions API provides several methods for accessing data from a dashboard. | Method | Tableau Version | Extensions API Library | Status | |:------ | :---------------| :--------------------- | -| `Worksheet.getSummaryDataAsync()` | Tableau 2018.2 and later | version 1.1 and later | Current | +| `Worksheet.getSummaryDataReaderAsync()` | Tableau 2022.4 and later | version 1.10 and later | Current | +| `Worksheet.getSummaryDataAsync()` | Tableau 2018.2 and later | version 1.1 and later | Deprecated | | `Worksheet.getUnderlyingDataAsync()` | Tableau 2018.2 to 2020.1 | version 1.1 to 1.3 | Deprecated | -| `Worksheet.getUnderlyingTablesAsync` | Tableau 2018.2 and later | version 1.4 and later | Current | -| `Worksheet.getUnderlyingTableDataAsync` | Tableau 2018.2 and later | version 1.4 and later | Current | +| `Worksheet.getUnderlyingTablesAsync()` | Tableau 2018.2 and later | version 1.4 and later | Current | +| `Worksheet.getUnderlyingTableDataAsync()` | Tableau 2018.2 and later | version 1.4 and later | Current | +| `Worksheet.getUnderlyingTableDataReaderAsync()` | Tableau 2022.4 and later | version 1.10 and later | Current | -The data is returned in a `DataTable` object. The 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. +The data is returned in a `DataTable` object. The `getSummaryDataReaderAsync` and `getUnderlyingTableDataReaderAsync` methods return a `DataTableReader` object, which you can use to return the pages of `DataTable` objects. 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. -Starting in Tableau 2020.2, with the introduction of the new data model and logical tables, you need to use the `Worksheet.getUnderlyingTablesAsync` method to first return the array of `LogicalTable` objects. The `LogicalTable` objects returned are determined by the measures in the worksheet. +Starting in Tableau 2020.2, with the introduction of the new data model and logical tables, you need to use the `Worksheet.getUnderlyingTablesAsync` 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 `getUnderlyingTableDataAsync`. | +| `LogicalTable.id` | The identifier used to specify the logical table. Use this value to call `getUnderlyingTableDataAsync` or `getUnderlyingTableDataReaderAsync`. | You can also get the data from the selected marks in the worksheet, or the marks that are currently highlighted in the worksheet. The following two functions return a `MarksCollection`, which is an array of `DataTable` objects. @@ -72,15 +73,53 @@ After you have a worksheet object, you can call one of the methods to access the ## Get summary data from a worksheet +Starting with Tableau 2022.4 and the Dashboard Extensions API library v1.10, you should use the `getSummaryDataReaderAsync()` method to get data from a worksheet. This method returns a `DataTableReader` object that you can use to access the data. + +If your summary data is less than 4,000,000 rows (400 pages), you can use the `DataTableReader.getAllPagesAsync()` method to retrieve a single `DataTable` from the `DataTableReader`. The following example shows how to do this. + +```javascript + +// 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 ... +} + +``` + +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. Using the `DataTableReader` you can create a loop to retrieve each page of summary data, using `DataTableReader.pageCount` or `DataTableReader.totalRowCount` property 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`. + ```javascript +// 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(); +} + +``` + +#### Deprecated method + +Prior to Tableau 2022.4 and the Dashboard Extensions API library v1.10, you would use the `getSummaryDataAsync` method. This method could fail if there is a large amount of summary data. Use the `getSummaryDataReaderAsync` method if you can instead. + +```javascript // get the summary data for the sheet worksheet.getSummaryDataAsync().then(function (sumdata) { - const worksheetData = sumdata; // The getSummaryDataAsync() method returns a DataTable // Map the DataTable (worksheetData) into a format for display, etc. - }); ``` @@ -95,7 +134,7 @@ Starting in Tableau 2020.2, and using version 1.4 of the Extensions API v1.4 lib ### Get full data using the v1.4 library (and later) -Starting in Tableau 2020.2 and later, where the underlying data could include multiple logical tables, you first need to identify the logical table (or tables) you want data from. In previous versions of Tableau, logical tables did not exist. When you use the `getUnderlyingTablesAsync` in Tableau 2020.1 and earlier, the method returns a single table. You can use this single table identifier to call `getUnderlyingTablesAsync`. +Starting in Tableau 2020.2 and later, where the underlying data could include multiple logical tables, you first need to identify the logical table (or tables) you want data from. In previous versions of Tableau, logical tables did not exist. When you use the `getUnderlyingTablesAsync` in Tableau 2020.1 and earlier, the method returns a single table. You can use this single table identifier to call `getUnderlyingTableDataAsync` and `getUnderlyingTableDataReaderAsync`. #### 1. Get the logical table(s) using getUnderlyingTablesAsync() @@ -112,14 +151,19 @@ worksheet.getUnderlyingTablesAsync().then(logicalTables => { const logicalTableId = logicalTables[0].id; // Use the logicalTableId to then get worksheet's underlying data - // by calling worksheet.getUnderlyingTableDataAsync(logicalTableId) + // by calling worksheet.getUnderlyingTableDataAsync(logicalTableId) or + // worksheet.getUnderlyingTableDataReaderAsync(logicalTableId) }); ``` -#### 2. Get data from the logical table(s) using getUnderlyingTableDataAsync() +#### 2a. Get data from the logical table(s) (less than 10,000 rows) + +If the data doesn't contain more than 10,000 rows, you can use the `getUnderlyingTableDataAsync` method to get data from a worksheet. + +Using the `logicalTable.id`, you 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. The following example returns data for the first logical table that is used by a worksheet called *"Sale Map"*. @@ -133,6 +177,51 @@ The following example returns data for the first logical table that is used by a }); ``` + +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. + + +#### 2b. Get data from the logical table(s) (more than 10,000 rows) + +Starting with Tableau 2022.4 and the Dashboard Extensions API library v1.10, if 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: + +1. Using the `logicalTable.id`, call the `getUnderlyingTableDataReaderAsync` method to create the `DataTableReader`. + +1. 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. + +1. Use the `getPageAsync` method to get the DataTable from each page. + +1. After you have retrieved all pages of the summary data, call the `releaseAsync()` method to free up memory from the `DataTableReader`. + +```javascript + +// assumes this code is in an async method + +const worksheet = tableau.extensions.dashboardContent.dashboard.worksheets.find(w => w.name === "Sale Map"); +// Call to get the underlying logical tables used by the worksheet +const underlyingTablesData = await worksheet.getUnderlyingTablesAsync(); +const logicalTableId = underlyingTablesData[0].id; +// Use the above logicalTableId to get the underlying data reader on the active sheet +const dataTableReader = await worksheet.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, {{site.tol}}, or Tableau Desktop option: `ExtensionsAndEmbeddingReaderRowLimit`. For Tableau Desktop, you can set this with a command line option **`-DExtensionsAndEmbeddingReaderRowLimit=`***value*. + +If the underlying table has many columns, `getUnderlyingTableDataReaderAsync` can be sped up by only requesting native data values (`IncludeDataValuesOption.OnlyNativeValues`) in the `GetUnderlyingDataOptions`. + --- ### Deprecated: Get full data (library v1.3 and earlier) @@ -144,7 +233,8 @@ If you want your extension to work in all versions of Tableau, you should use th ```javascript -// the following example uses the Superstore workbook and gets the underlying data // for a specific worksheet. +// the following example uses the Superstore workbook and gets the underlying data +// for a specific worksheet. // The example writes the values for a single column (states names) to the console. tableau.extensions.dashboardContent.dashboard.worksheets.find(w => w.name === "Sale Map").getUnderlyingDataAsync().then(dataTable => { let field = dataTable.columns.find(column => column.fieldName === "State"); @@ -156,9 +246,10 @@ tableau.extensions.dashboardContent.dashboard.worksheets.find(w => w.name === "S console.log(values) }); - ``` +--- + # Get data from a data source You can also get the underlying data from the data sources for the worksheet. To do that, you must acquire the data sources for the worksheet with a call to the `getDataSourcesAsync()` method, which returns an array of the primary and all the secondary data sources of a worksheet. Once you have the data source object, you can access the underlying data and access information about the data source, such as the names of tables and fields and information about the connection. @@ -174,6 +265,7 @@ Just like worksheet methods that access full data, the following methods for the | `Datasource.getUnderlyingDataAsync()` | Tableau 2018.2 to 2020.1 | version 1.1 to 1.3 | Deprecated | | `Datasource.getLogicalTablesAsync()` | Tableau 2018.2 and later | version 1.4 and later | Current | | `Datasource.getLogicalTableDataAsync()` | Tableau 2018.2 and later | version 1.4 and later | Current | +| `Datasource.getLogicalTableDataReaderAsync()` | Tableau 2022.4 and later | version 1.10 and later | Current | @@ -188,7 +280,6 @@ tableau.extensions.dashboardContent.dashboard.worksheets.find(w => w.name === "S // return dataSource for further processing }); - ``` ## Get full data from a worksheet using the v1.4 library (and later) @@ -199,7 +290,7 @@ After you have the data source object, you can query the data source for the und The first step in getting the underlying data is to call the `Datasource.getLogicalTablesAsync` method to return the array of `LogicalTable` objects. -To get the underlying data for each logical table, use the `LogicalTable.id` property of the table to call `Datasource.getLogicalTableDataAsync()`. Note that when you use the `getLogicalTablesAsync` in Tableau 2020.1 and earlier, the method will only return a single table, and that table uses `single-table-id-sentinel` as the `LogicalTable.id`. +To get the underlying data for each logical table, use the `LogicalTable.id` property of the table to call `Datasource.getLogicalTableDataAsync()`. Note that when you use the `getLogicalTablesAsync` in Tableau 2020.1 and earlier, the method will only return a single table, and that table uses the `single-table-id-sentinel` as the `LogicalTable.id`. Example using a single table: @@ -216,7 +307,6 @@ dataSource.getLogicalTablesAsync().then(logicalTables => { }); - ``` Example that writes the names of all the logical tables in the data source to the console: @@ -231,14 +321,15 @@ dataSource.getLogicalTablesAsync().then(logicalTables => { }); }); - ``` -#### 2. Get data from the logical table(s) using getLogicalTableDataAsync() +#### 2a. Get data from the logical table(s) for less than 10,000 rows -After you have identified the logical tables you want, use the `LogicalTable.id` property of the table to call `Datasource.getLogicalTableDataAsync()` -The following example returns the column names of the first logical table that is in the data source. +If the data doesn't contain more than 10,000 rows, you can use the `getLogicalTableDataAsync` method to get data from a data source. +After you have identified the logical tables you want, use the `LogicalTable.id` property of the table to call `Datasource.getLogicalTableDataAsync()`. You can then process the data for that logical table. + +The following example returns the column names of the first logical table that is in the data source. ```javascript @@ -256,6 +347,36 @@ The following example returns the column names of the first logical table that i ``` +#### 2b. Get data from the logical table(s) for more than 10,000 rows + +Starting with Tableau 2022.4 and the Dashboard Extensions API library v1.10, if 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: + +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`. + +```javascript + +// 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(); + +``` ## Deprecated: Get data from a data source using the v1.3 library (and earlier) @@ -278,21 +399,26 @@ tableau.extensions.dashboardContent.dashboard.worksheets.find(w => w.name === "S # Compatibility: methods for accessing underlying data -To support the data model that was introduced in Tableau 2020.2, where a data source can have logical tables, the Tableau Dashboard Extensions API provides new methods for getting data. The new methods are available starting with version 1.4 of the Extensions API library. The following table shows the compatibility between the methods and the different versions of the Extensions API library and Tableau. +To support the data model that was introduced in Tableau 2020.2, where a data source can have logical tables, the Tableau Dashboard Extensions API provides new methods for getting data. The new methods are available starting with version 1.4 of the Extensions API library. Starting with version 1.10 of the library, there are new methods that provide pagination using a `DataTableReader`. The following table shows the compatibility between the methods and the different versions of the Extensions API library and Tableau. -If you have an existing Dashboard Extension that accesses underlying data, and you want your extension to work with Tableau 2020.2 or later, you should upgrade to version 1.4 of the library +If you have an existing Dashboard Extension that accesses underlying data, and you want your extension to work with Tableau 2020.2 or later, you should upgrade to the latest version of the library supported by your version of Tableau. | Methods | API Version | Tableau 2020.1 and earlier | Tableau 2020.2 (single logical table) | Tableau 2020.2 (multiple logical tables) | | :-------- | :---------- | :---------- | :--------- | :-------- | | `Datasource.getUnderlyingDataAsync` `Worksheet.getUnderlyingDataAsync` | v1.3 and earlier | Works as expected | Works, column order will be different | Fails with an exception: Not Supported (2) | | `Datasource.getUnderlyingDataAsync` `Worksheet.getUnderlyingDataAsync` | v1.4 | Works as expected | Works, column order will be different | Fails with an exception: Not Supported (2) | | `Datasource.getLogicalTablesAsync` `Datasource.getLogicalTableDataAsync` `Worksheet.getUnderlyingTablesAsync` `Worksheet.getUnderlyingTableDataAsync` | v1.4 and earlier | Works, maps to existing commands | Works, column order will be different | Works as expected | +| `Datasource.getLogicalTableDataReaderAsync`, `Worksheet.getUnderlyingTableDataReaderAsync` | v1.10 and later | -- | -- | Works as expected | --- # When there is more data than can be returned -Some data sources can be very large and could contain thousands and thousands of rows. To minimize the impact of requests for data on Tableau performance, the `getUnderlyingDataAsync()`, `Worksheet.getUnderlyingTableDataAsync()`, and `Datasource.getLogicalTableDataAsync` methods are currently limited to returning 10,000 rows. If the method can't return the full number of rows in your data, the `DataTable` property `isTotalRowCountLimited` is set to TRUE. You can use this property to test whether there is more data than can be returned. Note that the limits do not apply to `getSummaryDataAsync()`. +Some data sources can be very large and could contain thousands and thousands of rows. To minimize the impact of requests for data on Tableau performance, the `getUnderlyingDataAsync()`, `Worksheet.getUnderlyingTableDataAsync()`, and `Datasource.getLogicalTableDataAsync` methods are currently limited to returning 10,000 rows. If the method can't return the full number of rows in your data, the `DataTable` property `isTotalRowCountLimited` is set to TRUE. You can use this property to test whether there is more data than can be returned. + +If there are more than 10,000 rows of data, use one of the pagination methods, `Datasource.getLogicalTableDataReaderAsync`, `Worksheet.getUnderlyingTableDataReaderAsync`. These methods return a `DataTableReader` that you can use to page through and retrieve the data. + +Note that the limits do not apply to `getSummaryDataAsync()`. The `getSummaryDataAsync()` method could fail if there is a very large amount of summary data. You should use `getSummaryDataReaderAsync()` instead, the method is available starting with Tableau 2022.4 and the version 1.10 library. The following table illustrates what happens to calls to `getUnderlyingDataAsync()`, `Worksheet.getUnderlyingTableDataAsync()`, and `Datasource.getLogicalTableDataAsync()` for various sizes of data (shown as **Data Rows**). @@ -323,7 +449,8 @@ The following table illustrates what happens to calls to `getUnderlyingDataAsync When an extension needs full data access and the user does not have full data permission on the workbook, Tableau currently allows the extension to run, but Tableau will call the promise failure function if the extension calls `getUnderlyingData()`, `Worksheet.getUnderlyingTableDataAsync()`, and `Datasource.getLogicalTableDataAsync()`. This is shown in the following example. -```Javascript +```javascript + Worksheet.getUnderlyingTableDataAsync(logicalTables[0].id).then(function(success) { // called on success }, function (err) { diff --git a/docs/trex_release-notes.md b/docs/trex_release-notes.md index 6f08bd8d..04a5d2d5 100644 --- a/docs/trex_release-notes.md +++ b/docs/trex_release-notes.md @@ -3,12 +3,14 @@ title: Release Notes for the Tableau Extensions API layout: docs --- +[All Releases](#all-releases) + ---- ### Tableau Dashboard Extensions API version 1.10.0 *December 2022* -* Tableau Dashboard Extensions API library: `tableau.extensions.1.9.0.js`
(download or clone the Extensions API repository on [GitHub](https://github.com/tableau/extensions-api){:target="_blank"}.)
+* Tableau Dashboard Extensions API library: `tableau.extensions.1.10.0.js`
(download or clone the Extensions API repository on [GitHub](https://github.com/tableau/extensions-api){:target="_blank"}.)
* Certain features in this release are only available in Tableau 2022.4 or later. Download [Tableau Desktop](https://www.tableau.com/support/releases){:target="_blank"} or [Tableau Server](https://www.tableau.com/support/releases/server){:target="_blank"}. @@ -16,16 +18,30 @@ layout: docs About this release: -This release contains updates for Tableau Viz, an easy way for you to add visualizations to your dashboard extensions using a declarative description. This release includes support for combination charts, charts with multiple mark types in the same visualization. Tableau Viz has a new input specification that support these new visualizations, see the [Tableau Viz v2 inputSpec]({{site.baseurl}}/docs/trex_tableau_viz_ref_v2.html). For information about using Tableau Viz in your extensions, see [Add Tableau Viz to your Dashboard Extensions]({{site.baseurl}}/docs/trex_tableau_viz.html). +* Updates for Tableau Viz, an easy way for you to add visualizations to your dashboard extensions using a declarative description. This release includes support for combination charts, charts with multiple mark types in the same visualization. Tableau Viz has a new input specification that support these new visualizations, see the [Tableau Viz v2 inputSpec]({{site.baseurl}}/docs/trex_tableau_viz_ref_v2.html). For information about using Tableau Viz in your extensions, see [Add Tableau Viz to your Dashboard Extensions]({{site.baseurl}}/docs/trex_tableau_viz.html). + + ![Tableau Viz v2 SVG image]({{site.baseurl }}/assets/vizapiV2.svg) + +---- + +* Adds support for a [DataTableReader]({{site.baseurl}}/docs/interfaces/datatablereader.html) to support pagination. Created with [Worksheet.getSummaryDataReaderAsync]({{site.baseurl}}/docs/interfaces/worksheet.html#getsummarydatareaderasync), +[Worksheet.getUnderlyingTableDataReaderAsync]({{site.baseurl}}/docs/interfaces/worksheet.html#getunderlyingtabledatareaderasync), and [DataSource.getLogicalTableDataReaderAsync]({{site.baseurl}}/docs/interfaces/datasource.html#getlogicaltabledatareaderasync). +For more information, see [Get Data from the View]({{site.baseurl}}/docs/trex_getdata.html). + +* Deprecated `getSummaryDataAsync`. Use [Worksheet.getSummaryDataReaderAsync]({{site.baseurl}}/reference/interfaces/worksheet.html#getsummarydatareaderasync) instead. + +* The [UI.displayDialogAsync]({{site.baseurl}}docs/interfaces/ui.html#displaydialogasync) now supports different dialog styles (window, modal or modeless dialog boxes). + +* Adds support for annotating marks with [Worksheet.annotateMarkAsync]({{site.baseurl}}/docs/interfaces/worksheet.html#annotatemarkasync), [Worksheet.getAnnotationsAsync]({{site.baseurl}}/docs/interfaces/worksheet.html#getannotationsasync), and [Worksheet.removeAnnotationAsync]({{site.baseurl}}/docs/interfaces/worksheet.html#removeannotationasync). See the code sample, [Annotation](https://github.com/tableau/extensions-api/tree/dev/Samples/Annotation) (on GitHub). + -![Tableau Viz v2 SVG image]({{site.baseurl }}/assets/vizapiV2.svg) ---- See also: [Known Issues]({{site.baseurl}}/docs/trex_known_issues.html) ---- -**All Releases** +#### All Releases * TOC {:toc} From 53f1aabbfcc5b2722ba4f7a9ebdac135546f315e Mon Sep 17 00:00:00 2001 From: d45 <3d.hagen@gmail.com> Date: Thu, 15 Dec 2022 17:07:05 -0800 Subject: [PATCH 2/4] content and code fixes --- docs/trex_getdata.md | 76 +++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/docs/trex_getdata.md b/docs/trex_getdata.md index cfb300aa..f8380765 100644 --- a/docs/trex_getdata.md +++ b/docs/trex_getdata.md @@ -81,13 +81,10 @@ If your summary data is less than 4,000,000 rows (400 pages), you can use the `D // Use `await` only inside an `async` method -let vizActiveSheet = viz.workbook.activeSheet; -if (vizActiveSheet.sheetType === "worksheet") { - const dataTableReader = await vizActiveSheet.getSummaryDataReaderAsync(); + const dataTableReader = await worksheet.getSummaryDataReaderAsync(); const dataTable = await dataTableReader.getAllPagesAsync(); await dataTableReader.releaseAsync(); // ... process data table ... -} ``` @@ -97,22 +94,24 @@ If your summary data contains more than 4,000,000 rows (or 400 pages), use the s // 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(); +const dataTableReader = await vizActiveSheet.getSummaryDataReaderAsync(); +try { + for (let currentPage = 0; currentPage < dataTableReader.pageCount; currentPage++) { + const dataTablePage = await dataTableReader.getPageAsync(currentPage); + // ... process current page .... + } +} catch (e) { + console.error(e); +} finally { + // free up resources + await dataTableReader.releaseAsync(); } ``` #### Deprecated method -Prior to Tableau 2022.4 and the Dashboard Extensions API library v1.10, you would use the `getSummaryDataAsync` method. This method could fail if there is a large amount of summary data. Use the `getSummaryDataReaderAsync` method if you can instead. +Prior to Tableau 2022.4 and the Dashboard Extensions API library v1.10, you would use the `getSummaryDataAsync` method. This method could fail if there is a large amount of summary data. Modify your code to use the `getSummaryDataReaderAsync` method instead. ```javascript // get the summary data for the sheet @@ -203,18 +202,21 @@ const worksheet = tableau.extensions.dashboardContent.dashboard.worksheets.find( // Call to get the underlying logical tables used by the worksheet const underlyingTablesData = await worksheet.getUnderlyingTablesAsync(); const logicalTableId = underlyingTablesData[0].id; -// Use the above logicalTableId to get the underlying data reader on the active sheet +// Use the above logicalTableId to get the underlying data reader on the specified worksheet const dataTableReader = await worksheet.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++; +try { + // loop through and process the pages + for (let pageNumber = 0; pageNumber < dataTableReader.pageCount; pageNumber++) { + let currentPageDataTable = await dataTableReader.getPageAsync(pageNumber); + // process page ... + console.log(currentPageDataTable); + } +} catch(e) { + console.error(e); +} finally { + // free up resources + await pageReader.releaseAsync(); } -// free up resources -await pageReader.releaseAsync(); ``` @@ -230,7 +232,6 @@ If you were using 1.3 version of the Extensions API library (or earlier), you ha If you want your extension to work in all versions of Tableau, you should use the latest library (version 1.4 or later) and the `getUnderlyingTablesAsync` and `getUnderlyingTableDataAsync` methods. - ```javascript // the following example uses the Superstore workbook and gets the underlying data @@ -292,7 +293,7 @@ The first step in getting the underlying data is to call the `Datasource.getLogi To get the underlying data for each logical table, use the `LogicalTable.id` property of the table to call `Datasource.getLogicalTableDataAsync()`. Note that when you use the `getLogicalTablesAsync` in Tableau 2020.1 and earlier, the method will only return a single table, and that table uses the `single-table-id-sentinel` as the `LogicalTable.id`. -Example using a single table: +Example that uses a single table: ```javascript @@ -341,7 +342,7 @@ The following example returns the column names of the first logical table that i for (let col of dataTable.columns) { list.push(col.fieldName); } - console.log(list); + console.log(list); }); }); @@ -365,16 +366,19 @@ 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++; - } +try { + // loop through and process each page + for (let pageNumber = 0; pageNumber < dataTableReader.pageCount; pageNumber++;) { + let currentPageDataTable = await dataTableReader.getPageAsync(pageNumber); + // process page ... + console.log(currentPageDataTable); + } +} catch (e) { + console.error(e); +} finally { // release resources -await pageReader.releaseAsync(); + await pageReader.releaseAsync(); +} ``` From 88f444fb7b27aa4680cd7bb2c7d77628f470ef5c Mon Sep 17 00:00:00 2001 From: d45 <3d.hagen@gmail.com> Date: Thu, 15 Dec 2022 17:48:24 -0800 Subject: [PATCH 3/4] removed an activeSheet reference I missed --- docs/trex_getdata.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/trex_getdata.md b/docs/trex_getdata.md index f8380765..de94c8c6 100644 --- a/docs/trex_getdata.md +++ b/docs/trex_getdata.md @@ -94,7 +94,7 @@ If your summary data contains more than 4,000,000 rows (or 400 pages), use the s // Use `await` only inside an `async` method -const dataTableReader = await vizActiveSheet.getSummaryDataReaderAsync(); +const dataTableReader = await worksheet.getSummaryDataReaderAsync(); try { for (let currentPage = 0; currentPage < dataTableReader.pageCount; currentPage++) { const dataTablePage = await dataTableReader.getPageAsync(currentPage); From 407daf6292452410ae8917d9bd1fa47f03476364 Mon Sep 17 00:00:00 2001 From: d45 <3d.hagen@gmail.com> Date: Thu, 15 Dec 2022 23:57:23 -0800 Subject: [PATCH 4/4] fixing formatting --- docs/trex_getdata.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/trex_getdata.md b/docs/trex_getdata.md index de94c8c6..1d988583 100644 --- a/docs/trex_getdata.md +++ b/docs/trex_getdata.md @@ -101,7 +101,7 @@ try { // ... process current page .... } } catch (e) { - console.error(e); + console.error(e); } finally { // free up resources await dataTableReader.releaseAsync();