Sisense Community logo
    • Community Feedback
    • Chapters
    • Events
    • Forums
      • Help and How To
      • Product Feedback Forum
      • Strategy & Use Cases
    • Blogs
    • KB Docs
      • KB Docs
      • Add-Ons & Plug-Ins
      • APIs
      • Best Practices
      • Blox
      • CDT
      • Cloud Managed Service
      • Data Models
      • Data Sources
      • Embedding Analytics
      • How-Tos & FAQs
      • Onboarding
      • PySisense
      • Security
      • Sisense Administration
      • Sisense Intelligence & AI
      • Troubleshooting
      • Widget & Dashboard Scripts
    • Support
    • Learning
      • Sisense Academy: Free Courses and Certifications
      • Official Developer Documentation
      • Official Product Documentation
      • Official Sisense Youtube Channel
      • Sisense Compose SDK Playground
      • Official Sisense Discord
    • Use Case Gallery
    Discussions
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    Discussions
    • TagsChevronRightIcon
    Migration: Jumpstart
      • Data ModelsChevronRightIcon

      Reading multiple excel files into Sisense data model

                                                       

      Reading multiple Excel files into Sisense data model Introduction: If you are migrating from Windows to a Sisense Linux-hosted solution, on the Sisense Windows machine you may use an SFTP client that moves Excel files placed in a remote server's folder to a folder on the Sisense Windows server. With this, it is used as a source folder for Excel file import to an ElastiCube. Since this is not possible with your hosted Linux, we could use the CDATA SFTP Connector to import these files.  In your existing connection string, you will get just the names of the files. When connecting to an Excel sheet stored in an SFTP server, the URI must be  sftp://<server>:<port>/<path to file> , as shown below. If the connection string does not contain this, you will just get the names of the files.   Additionally, the  ConnectionType  and  AuthScheme  must be set to  SFTP , and the SSHAuthMode must be set to either  None ,  Password , or  Public_Key  depending on your SFTP server. If the issue still persists, it would be helpful to have a log file. To generate a log file, in your connection string to Excel, please set the Log file to the path where the log file will be generated (such as C:/Logs/log.txt) and Verbosity to 3.  Then reproduce the error. Additional Resources: Sisense Docs: https://docs.sisense.com/win/SisenseWin/introduction-to-data-sources.htm Sisense Academy:  https://academy.sisense.com/sisense-data-designer-web-application  

      Vicki786
      Vicki786Posted 1 year ago
      0
               
    • Blog banner
      • Widget & Dashboard ScriptsChevronRightIcon

      Advanced Scripting for Sisense’s Simply Ask NLQ: Adding Currency Symbols to Pivot Tables

                                                                                       

      Advanced Scripting for Sisense’s Simply Ask NLQ: Adding Currency Symbols to Pivot Tables Sisense’s Simply Ask feature empowers users to create visualizations instantly by asking natural language questions, simplifying data exploration without needing technical expertise or manual widget configuration. This Natural Language Query (NLQ) capability accelerates insights generation without the need to manually create new Sisense widgets through the standard UI for each question or data relationship of interest.   User interface of the 'Simply Ask - Sample ECommerce' dashboard in the Sisense data analytics tool. A central search bar at the top allows users to 'Ask a question about your data.' Below the search bar is a large icon with a plus symbol, inviting users to ask questions about dashboard data. On the right, there is a list of 'Available fields' categorized under Commerce, Category, Country, and Formulas, with individual fields like Brand ID, Amount, Age Range, and Revenue. A 'Done' button is highlighted at the bottom. A previously published article discussed how to customize Simply Ask NLQ-generated widgets using scripting, providing multiple examples of basic modifications and more detail on the basic mechanics of scripting Simply Ask widgets. This article will share a more complex example to show how NLQ widgets can be customized in more complex conditional ways, in this example: programmatically adding currency symbols to specific data columns in pivot table widgets generated by Simply Ask. Enhancing NLQ Widgets with Currency Symbols When dealing with financial data, it’s can be important to display currency symbols alongside numeric values for clarity, especially if multiple currency may be used in a datasource. However, Simply Ask NLQ-generated widgets may not automatically include these symbols, especially if they are dynamically generated based on natural language user queries. The following script demonstrates how to: Detect when a new NLQ widget is rendered. Identify specific data columns based on their titles using purely HTML based Javascript observation. Append a currency symbol to the numeric text values in those columns. Full Script:   const addCurrencySignToValues = () => { // Column keywords to match (case-insensitive) const currencySignColumns = ['Revenue', 'Cost']; // Replace with actual column keywords as needed // Shared constants for selectors and class patterns const NLQ_MAIN_CONTENT_SELECTOR = 'div.nlq-widget__main-content'; const DATA_CELL_SELECTOR = 'td.table-grid__cell--data'; const HEADER_CELL_SELECTOR = 'td.table-grid__cell--row-0'; const INNER_CONTENT_SELECTOR = 'div.table-grid__content__inner'; const ROW_CLASS_PREFIX = 'table-grid__cell--row-'; const COLUMN_CLASS_PREFIX = 'table-grid__cell--col-'; const NUMBER_PATTERN = /^[0-9,.]*$/; // Determine the default symbol to use let symbol = '$'; // Function to get the cell's row and column indices const getCellPosition = (cell) => { let classList = cell.classList; // Find row and column classes let rowClass = Array.from(classList).find(cls => cls.startsWith(ROW_CLASS_PREFIX)); let columnClass = Array.from(classList).find(cls => cls.startsWith(COLUMN_CLASS_PREFIX)); // If both classes are found, extract indices if (rowClass && columnClass) { let rowIndex = rowClass.split(ROW_CLASS_PREFIX)[1]; let columnIndex = columnClass.split(COLUMN_CLASS_PREFIX)[1]; return { row: parseInt(rowIndex, 10), column: parseInt(columnIndex, 10) }; } // Return null if not found return null; }; // Build a mapping of column indices to titles let columnHeaders = {}; // Collect header cells (row 0) $(HEADER_CELL_SELECTOR).each(function () { let cellPosition = getCellPosition(this); if (cellPosition) { let headerText = $(this).text().trim(); columnHeaders[cellPosition.column] = headerText; } }); // Process data cells $(`${NLQ_MAIN_CONTENT_SELECTOR} ${DATA_CELL_SELECTOR}`).each(function () { let cellText = $(this).text(); let cellPosition = getCellPosition(this); if (cellPosition) { let columnIndex = cellPosition.column; let columnTitle = columnHeaders[columnIndex]; // Check if column title includes any of the keywords (case-insensitive) if ( currencySignColumns.some(keyword => columnTitle.toLowerCase().includes(keyword.toLowerCase()) ) && NUMBER_PATTERN.test(cellText) ) { let changedText = `${cellText}${symbol}`; // Modify the text within the inner div $(this).find(INNER_CONTENT_SELECTOR).text(changedText); } } }); }; // Set up the MutationObserver to detect when new NLQ widgets are rendered dashboard.on('domready', function () { $('button.nlq-main-button').click(function () { setTimeout(function () { // Observe changes in the widget container const elementToObserve = $('div.nlq-widget__main-content')[0]; const observer = new MutationObserver(function () { addCurrencySignToValues(); }); observer.observe(elementToObserve, { subtree: true, childList: true }); }, 1000); }); }); ​   How It Works Define Column Keywords : The currencySignColumns array variable contains the keywords for column titles to target (in this example, ‘Revenue’ and ‘Cost’). The script will search for these keywords in the pivot column headers to determine which columns should have the currency symbol appended. Set Up Constants for CSS Class Names : Constants for selectors and class prefixes are defined for easy maintenance and readability. Determine the Currency Symbol : By default, in this example the symbol is set to '$'. It can be modified to any symbol required. If needed this can be be read from a Javascript variable set by a plugin or other script, to determine the correct currency symbol to use for a dashboard and datasource. Get Cell Position Function : The getCellPosition function extracts the row and column indices from a cell’s class list, which follows a naming convention contained in class names. Build a Column Headers Map : The script builds a mapping (columnHeaders) of column indices to their respective header titles by iterating over header cells. This same concept and code can be used in other scripts that customize pivots based on header titles. Process Data Cells : Iterates over all data cells, checks if cell's column title matches any of the keywords, and if the cell content is numeric. Append Currency Symbol : If both conditions are met, the script appends the currency symbol to the cell’s text within the inner content div. Set Up Mutation Observer : The script uses a MutationObserver to detect when a new NLQ widget is rendered in the Simply Ask modal. It observes the main widget content element for changes and triggers addCurrencySignToValues when mutations occur. Customization Tips Updating Keywords : Modify the currencySignColumns array to include any keywords relevant to the data columns in question. Changing the Currency Symbol : Change the symbol variable to use a different currency symbol or to dynamically set it based on user preferences or locale. Adjusting Number Pattern : The NUMBER_PATTERN regex can be adjusted to match different numeric data includes different formats (e.g., decimal points, thousand separators). Use as Template:  This example can be used as a template for completely different types of custom scripting of Simply Ask NLQ widgets. Integrating the Script into a Dashboard To use this script in a Sisense environment: Add the Script to the Dashboard : Place the script within the dashboard’s JavaScript editor. This will ensure it runs when the dashboard is loaded.   Considerations CSS Class Updates : CSS class names can change between Sisense versions; keeping CSS selector strings as variables allows for easy updating if needed. Conclusion By leveraging standard JavaScript, and dashboard scripting NLQ-generated widgets can be enhanced in Sisense’s Simply Ask feature with advanced customizations like appending currency symbols to specific data columns. This approach allows for maintaining consistency and clarity in data presentations, providing a better experience for users interacting with dynamically generated visualizations. This example shows that complex widget scripting customizations are possible with Simply Ask NLQ generated widgets. Related Content: For more details on scripting with Simply Ask NLQ and additional examples, refer to the previous article Modifying Simply Ask Natural Language Query Generated Widgets with Scripting .

      Jeremy Friedel
      Jeremy FriedelPosted 1 year ago
      0
               
    • Blog banner
      • Widget & Dashboard ScriptsChevronRightIcon

      Modifying Simply Ask Natural Language Query Generated Widgets with Scripting

                                                                                       

      Modifying Simply Ask Natural Language Query Generated Widgets with Scripting Sisense's Simply Ask  feature empowers users to create visualizations instantly by asking natural language questions, simplifying data exploration without needing technical expertise or manual widget configuration. This Natural Language Query (NLQ) capability accelerates data exploration and insights generation without needing to manually create new Sisense widgets through the standard UI for each question or data relationship of interest.   User interface of the 'Simply Ask - Sample ECommerce' dashboard in the Sisense data analytics tool. A central search bar at the top allows users to 'Ask a question about your data.' Below the search bar is a large icon with a plus symbol, inviting users to ask questions about dashboard data. On the right, there is a list of 'Available fields' categorized under Commerce, Category, Country, and Formulas, with individual fields like Brand ID, Amount, Age Range, and Revenue. A 'Done' button is highlighted at the bottom. However, these automatically generated widgets differ from standard widgets in that they do not trigger typical widget scripting events , which poses a challenge for applying custom modifications. This limitation can hinder the application of standard dashboard and widget scripting customizations directly to these widgets. Fortunately, it is possible to modify NLQ-generated widgets programmatically by using JavaScript to manipulate the HTML of the fully rendered widgets without relying on Sisense-specific widget scripting events. This approach involves observing changes in the Simply Ask modal DOM and applying custom code when new widgets are rendered. This article explores how to implement such customizations, providing code examples and notes to help customize NLQ-generated Simply Ask widgets.   Understanding the Context Standard Sisense widgets support a variety of events (such as `beforequery` , `processquery` , `ready` , etc.) that run custom code at specific points in the widget’s query and rendering lifecycle, allowing developers to inject functionality and modifications seamlessly. However, NLQ-generated widgets within the Simply Ask modal do not trigger these events. This means that any scripts using these events will not directly apply to NLQ widgets until they are pinned (added) to the dashboard as standard Sisense widgets. When an NLQ widget is pinned using the dashboard pin UI button in the Simply Ask modal, it becomes a native Sisense dashboard widget, fully compatible with standard scripting. However, for scenarios where it is desired to apply customizations immediately within the Simply Ask modal for new generated NLQ widgets, without pinning the widget, code-based customization is still possible.   Solution Overview To modify NLQ-generated widgets within the Simply Ask modal, JavaScript provides an effective solution through the use of `MutationObserver` and direct manipulation of HTML elements. Specifically, you can: Use JavaScript to observe changes in the DOM Element : By setting up a standard JavaScript `MutationObserver` , you can detect when new widgets are rendered in the Simply Ask modal DOM. Apply custom modifications to the widget's HTML : Once the observer detects a new widget, you can manipulate the HTML elements using standard JavaScript or jQuery, including adjusting the styling. Implementing the Solution Setting Up a Mutation Observer First, the code must detect when a new widget is rendered in the Simply Ask modal. You can do this by observing changes in the modal's main content area using a Javascript  MutationObserver . The code for this MutationObserver  can run within the dashboard script, like all dashboard scripts, this will be specific to the current dashboard. This MutationObserver  could also exist in plugin code if this customization is designed to run on all dashboards with Simply Ask enabled, without modifying the dashboard script for each dashboard. This flexibility allows custom modifications to be reusable across different dashboards by placing the `MutationObserver` in plugin code or specific to one dashboard by placing it in that dashboard's script.   dashboard.on('domready', function () { // Listen for clicks on the Simply Ask button $('button.nlq-main-button').click(function () { setTimeout(function () { // Select the widget container area of the Simply Ask modal const elementToObserve = $('div.nlq-widget__main-content')[0]; // Create a MutationObserver instance const observer = new MutationObserver(function () { // Call your custom function when a change in DOM is detected customizeNLQWidget(); }); // Start observing the DOM for mutations observer.observe(elementToObserve, { subtree: true, childList: true }); }, 1000); // Delay to ensure the modal is fully rendered }); }); ​     Explanation : Event Listener : The script runs on the click event using an event listener on the Simply Ask UI button ( `nlq-main-button` ) which opens the Simply Ask NLQ modal. Delay with setTimeout : A short delay ensures that the Simply Ask modal is fully rendered before setting up the observer. MutationObserver:  Observes the NLQ-generated widget HTML element using the selector `nlq-widget__main-content` for any changes, specifically when new child nodes are added (i.e., when a new widget is generated on an NLQ query). subtree : Ensures that mutations to child elements of the main content area are also detected. childList : Watches for changes in the direct children of the observed element (e.g., when new widgets are added). Callback Function : When a mutation is observed, the `customizeNLQWidget` function is called to apply custom modifications. This can be any function or series of functions.   Example Customization Function The function that applies the desired modifications to the NLQ widget can be defined with any valid JavaScript. In this example, the function will modify the pivot header cells' styling.   const customizeNLQWidget = () => { const NLQ_MAIN_CONTENT_SELECTOR = 'div.nlq-widget__main-content'; const HEADER_CELL_SELECTOR = 'td.table-grid__cell--row-0'; // Apply CSS styles to the pivot table header cells $(`${NLQ_MAIN_CONTENT_SELECTOR} ${HEADER_CELL_SELECTOR}`).css({ 'background-color': 'blue', 'color': 'white', }); }; ​   Explanation : Selectors : The function targets the pivot table header cells within the NLQ modal. These can be any valid CSS selector, in this example they are: `NLQ_MAIN_CONTENT_SELECTOR` : Selects the main content area of the NLQ widget. `HEADER_CELL_SELECTOR` : Selects the header cells of a pivot table type widget. CSS Styling : Applies custom CSS styling to change the background color to blue and the text color to white.   Combining the Code   For clarity, here's the combined code that brings together the observer setup and the example custom code customization function:   dashboard.on('domready', function () { $('button.nlq-main-button').click(function () { setTimeout(function () { const elementToObserve = $('div.nlq-widget__main-content')[0]; const observer = new MutationObserver(function () { customizeNLQWidget(); }); observer.observe(elementToObserve, { subtree: true, childList: true }); }, 1000); }); }); const customizeNLQWidget = () => { const NLQ_MAIN_CONTENT_SELECTOR = 'div.nlq-widget__main-content'; const HEADER_CELL_SELECTOR = 'td.table-grid__cell--row-0'; $(`${NLQ_MAIN_CONTENT_SELECTOR} ${HEADER_CELL_SELECTOR}`).css({ 'background-color': 'blue', 'color': 'white', }); };   Customization Examples The example above modifies the header cells of a pivot table. However, you can extend the `customizeNLQWidget` function to perform various other customizations, such as: Adding Icons or Indicators : Inject visual cues for critical data points or thresholds directly into cells. Conditional Formatting: Automatically highlight data cells based on values (e.g., flagging negative values in red). Interactive Elements : Add clickable elements, like links or buttons, to enable dynamic user interactions, such as drilling into specific data. Content Modification : Alter or append units, currency symbols, or other data-specific indicators to ensure clarity and consistency in data presentation. Example: Conditional Formatting Based on Values   const customizeNLQWidget = () => { const NLQ_MAIN_CONTENT_SELECTOR = 'div.nlq-widget__main-content'; const DATA_CELL_SELECTOR = 'td.table-grid__cell--data'; $(`${NLQ_MAIN_CONTENT_SELECTOR} ${DATA_CELL_SELECTOR}`).each(function () { const cellValue = parseFloat($(this).text()); if (cellValue < 0) { $(this).css('color', 'red'); } else if (cellValue > 0) { $(this).css('color', 'green'); } }); }; ​   Explanation : Data Cells Selector : Targets all data cells in the pivot table. Value Parsing : Converts the cell text to a numeric value. Conditional Styling : Applies red color to negative values and green color to positive values. Considerations and Best Practices Scope : Ensure your selectors are specific enough to avoid unintended modifications to other parts of the dashboard. Compatibility Testing : Regularly test your customizations across different Sisense versions to ensure that changes in CSS classes or HTML structures don't break the functionality. CSS Class Updates : CSS class names can change between Sisense versions; keeping CSS selector strings as variables allows for easy updating if needed. Conclusion While NLQ-generated widgets in Sisense's Simply Ask feature do not support standard widget scripting events, the ability to observe DOM changes and manipulate HTML allows for extensive customizations. With JavaScript, you can enhance widget appearance, add interactive functionality, and more—all within the Simply Ask modal, providing a tailored user experience. This approach allows maintaining consistency in dashboards and provides a more customizable experience for users interacting with NLQ-generated visualizations.   Further Reading Sisense Javascript Reference   Sisense Scripting Sisense Simply Ask NLQ

      Jeremy Friedel
      Jeremy FriedelPosted 1 year ago
      0