Effective Error Reporting

One thing we all agree - Big IronPython codes are boomerang. They Always Come Back to Developer ๐Ÿฅบ
The real problem is there is no perfect code ☹️,
What we can do is - do a better Error Reporting to minimize time required to pin point issue. For this purpose, I usually take help of traceback and NotificationService Modules in code ✅
Have a look at example code -
import traceback
from Spotfire.Dxp.Framework.ApplicationModel import NotificationService
notif = Application.GetService[NotificationService]()

try:
a = 1/0 
#Raising Devide by Zero 
except:
tb = traceback.format_exc()
finally:
print tb
notif.AddErrorNotification("Error While Executing","IronPython Code <Name of Script> raised an Error",tb)

See, How it looks  -
Hope it helps ๐Ÿค“
Share:

Dynamic Links in Spotfire

My friend asked me recently -
"I need to trigger a URL from Spotfire, where URL should change as per User inputs"
Interesting ๐Ÿค“
Usually when people try doing it from IronPython webbrowser code, It doesn't work in Webplayer. So we need something which works everywhere ๐Ÿ™‚
To do this, I will take a generic example. I will trigger a Google search query based on an Input field. Every time search query gets updated, the Search button will also change its whole code.
Lets start -
  1. Create a HTML Text Area with an Input field Property, and a DIV for holding our search button.
    <span id="query">
    <SpotfireControl id="041866e281b24b8fa9f839f91af7a30d" />
    </span>
    <br><br>
    <div id="trigger">
    </div>
  2. Now Add some extra code to making our search button as an actual button. You can use code below -
    <style id="AlienBox">
     .buttonSpan {
    background-color:chocolate !important;
    color: white !important;
    border: 1px solid white!important;
    border-radius: 2px 3px 3px 3px !important;
        font-variant: petite-caps;
    cursor:pointer;
    }
     </style>
    As usual, here is JS code to beat HTML sanitization -
    if(!$('#AlienBox').length){
     $('body').append($(`<style id="AlienBox">
     .buttonSpan {
    background-color:chocolate !important;
    color: white !important;
    border: 1px solid white!important;
    border-radius: 2px 3px 3px 3px !important;
        font-variant: petite-caps;
    cursor:pointer;
    }
     </style>`, {
            id: 'AlienBox' 
       })); 
    }
  3. Add this JavaScript to Text Area. Feel free to modify as per your need.
    function ChangeURL(){

    var q =$('#query input').val();
    var SearchString = "<span class='buttonSpan' onclick=\"location='https://www.google.com/search?q="+q+"'\"> Search Google for '"+q+"'</span>";
    $('#trigger').html(SearchString);
    }
    setInterval(ChangeURL,500)
  4. Done
This is how it looks for different inputs -
Clicking on these buttons will open a Web Browser with Dynamic URL if the Analysis is opened in Clint. From Webplayer, it simple loads the URL populated.
Share:

Adding Styles to Date Picker

While working with date range filters, date-pickers are very helpful. They allow to select date ranges of our interest in a very convenient manner. They are nice right ??


Well what about this one ?

๐Ÿ’ก Liked it? Then add this code to a HTML Text area to have this look and feel -
<style>
.DatePicker {
    background: black;
    border: 2px solid #ffffff;
    border-radius: 8px 0px 8px 0px;
    position: absolute;
    overflow: hidden;
    z-index: 1024;
    text-align: center;
    font-size: 11px;
    color: #fff;
    width: 189px;
    font-variant-caps: small-caps;
}
.DatePicker .Header {
    height: 22px;
    padding: 2px 0 2px 0;
    background-color: brown;
    font-size: larger;
    font-weight: bold;
}
.DatePicker .Week td.CurrentMonth {
    color: brown;
}
.DatePicker .Week td {
    width: 21px;
    height: 21px;
    border-radius: 50%;
    text-align: center;
    vertical-align: middle;
    color: black;
}
 </style>
⚽ To beat HTML Sanitization, use below JavaScript code - 
if(!$('#AlienBox').length){
 $('body').append($(`<style id="AlienBox">
.DatePicker {
    background: black;
    border: 2px solid #ffffff;
    border-radius: 8px 0px 8px 0px;
    position: absolute;
    overflow: hidden;
    z-index: 1024;
    text-align: center;
    font-size: 11px;
    color: #fff;
    width: 189px;
    font-variant-caps: small-caps;
}
.DatePicker .Header {
    height: 22px;
    padding: 2px 0 2px 0;
    background-color: brown;
    font-size: larger;
    font-weight: bold;
}
.DatePicker .Week td.CurrentMonth {
    color: brown;
}
.DatePicker .Week td {
    width: 21px;
    height: 21px;
    border-radius: 50%;
    text-align: center;
    vertical-align: middle;
    color: black;
}
 </style>`, {
        id: 'AlienBox' 
   })); 
}
Share:

Styles for Tooltip

Tooltips in Spotfire are great for showing insights on mouse over. We use them a lot for showing information which should appear only when we need. But what if you feel that their look and feel is not matching with you theme ?
Question here is - How to add Style to tooltips ? ๐Ÿค”๐Ÿค”
Answer is, below code in a HTML TextArea -
<style id="AlienBox">
 .sf-tooltip {
background-color:chocolate !important;
color: white !important;
border: 2px solid white!important;
border-radius: 8px 0px 8px 0px !important;
    font-variant: petite-caps;
    font-style: italic;
    font-weight: lighter;
    font-size: x-small;
}
 </style>
If you are victim of HTML Sanitization issue, use JavaScript below -
if(!$('#AlienBox').length){
 $('body').append($(`<style id="AlienBox">
 .sf-tooltip {
background-color:chocolate !important;
color: white !important;
border: 2px solid white!important;
border-radius: 8px 0px 8px 0px !important;
    font-variant: petite-caps;
    font-style: italic;
    font-weight: lighter;
    font-size: x-small;
}
 </style>`, {
        id: 'AlienBox' 
   })); 
}
This is what I was able to achieve so far -

Share:

Conditional Coloring of Spotfire Buttons

My friend was willing to color Spotfire Action buttons based on a value. 
It is a small but effective way of representation. You will actually come to know what are your expectations even before clicking on a color coded button.
Challenge here, This color should be picked automatically  
Challenge Accepted !
Lets Start -
  1. Create a calculated value or Label property which evaluates into a single color (e.g. red) or into a color code value (e.g. #454545). Enclose it is a span with id property-
    <span id='property' style="display:none">
       <SpotfireControl id="c281364f0af947c38752561b38be631e" />
    </span>
  2. Now enclose your action button inside another span with id ConditionalButtonColor like below. This way you are letting your code know - which button you are going to style ๐Ÿง
    <span id='ConditionalButtonColor'>
    <SpotfireControl id="edf0f3c8a1b945cb840cd0235fce8d66" />
    </span>
  3. Now you simply need this JavaScript code to be added to the text area. It retrieves value from property and set it a background color of action button inside ConditionalButtonColor .
    var flag=0
    function conditionalColor() {  
     colorValue=$("#property").text()
     if(flag!=colorValue){
      $('#ConditionalButtonColor .sfc-action-button').css({
        background:colorValue,
    color:"white"
        ,textAlign:"center"
        ,margin:"10px"
        ,padding:"5px"
        ,borderStyle:"outset"
        ,width:"100px"
      });
     }
      flag=colorValue
    }

    setInterval(conditionalColor,500)
  4. Save the text are and you are done ✅
For demonstration, I am updating color value a drop down property. You can update it via a Label Document Property, Calculated value or even from simple sting as well. Here is a screenshot with results -
Share:

Show/Hide Pages with a Button

A friend from Community asked for a Button to toggle visibility of a Spotfire page.  
So, this post is about same ๐Ÿ˜Ž
Lets Start -


  1. Create a button in TextArea with id Hider. If you are suffering from HTML Sanitization, you can use my alternative code. This one re-purposes span as button ๐Ÿ˜œ
    <span id="Hider" style="background-color:chocolate;
    color:white;
    display:inline-block;
    border: 1px solid rgb(128,128,128);
    border-radius : 8px;
    padding     : 8px;
    line-height : 24px;
    text-shadow : 0 0 2px black;
    font-size:larger;
    margin:5px;
    cursor: pointer;">Toggle Visibility
    </span>
  2. Add below JavaScript to TextArea. Here [1] is page index of Second page. You can adjust it as you need.
    $('#Hider').click(function(){
    var state =$('.sf-element-page-tab')[1].style.display;
    console.log(state);
    if(state =='none') {
    $('.sf-element-page-tab')[1].style.display = "";}
    else{$('.sf-element-page-tab')[1].style.display = "none";}
    });
  3. Save TextArea and you are done ✅
This is a Before vs After comparison of Page Navigation Area -

Share:

Capturing Hierarchy Axis Changes to Document Property

My friend recently asked an Interesting Question -
I have a chart where I am using a Hierarchy as Category Axis. I want to capture changes in that Axis (Hierarchy) to a Property Control. Is there a way to do this ?
Sounds interesting  ๐Ÿ™ƒ
Well , Let's start doing it !
  1. Add a Input field property enclosed in a span like below. Code in red is optional based on whether you need to display document property on not.
    <span id='AxisTracker' style='display:none;'>
      <SpotfireControl id="635a7ae743a14feb865833e75f3e9b4d" />
    </span>
  2. Add below JavaScript to capture changes. Here code in red indicates the possible states of Hierarchy Axis of interest

    function updateProperty(){
    $('.sf-element-text-box').each(function(index){
    //console.log($(this).text());
    switch($(this).text()){
        case "Geo (Region)":
        case "Geo (State)":
        case "Geo (City)":
    console.log($(this).text());
    $('#AxisTracker input').val($(this).text()).blur()
    break;
    }
    });}
    setInterval(updateProperty,500)
  3. This is pretty much all ๐Ÿค“ 
Using this approach helps in tracking changes to the Axis and we can trigger IronPython code as well on Document property change. 
Share:

Adding some styles to Notifications

Default Notifications Dialog is boring!

Agree?
If yes, then this post is for you. Try Adding below code to a text area and then have a look at notifications again-
<style id="AlienBox">
.sf-modal-dialog-content textarea {
    color: azure;
    background-color: brown;
}
.sfc-default-theme.sf-element-modal-dialog .sf-element-modal-dialog-footer {
    font-size: 14.5px;
    background-color: #1e264e;
    color: #BDBFC3;

}
.sfc-default-theme.sf-element-modal-dialog .sf-element-modal-dialog-header {
    background-color: #134373;
}
.sfc-default-theme.sf-element-modal-dialog {
    background-color: #772323;
}
.sf-element-modal-dialog .sf-element-modal-dialog-header-title-text {
    font-size: x-large;
    color: blanchedalmond;
}
.sfc-default-theme.sf-element-modal-dialog .sf-element-modal-dialog-header .sf-element-modal-dialog-header-close {
    color: #ffffff;
    font-size: xx-large;
}
.sfc-default-theme.sf-element-modal-dialog .sf-element-button.sfpc-secondary {
    background-image: linear-gradient(to bottom, #7b3939, #206bb7);
    border-top-color: #234996;
    border-right-color: #4d6ba7;
    border-bottom-color: #AFB2B7;
    border-left-color: #586d96;
    border-bottom-color: #546580;
    color: #ffffff;
    font-size: large;
}
.sfc-default-theme.sf-element-modal-dialog .sf-element-button {
    background-image: linear-gradient(to bottom, #7b3939, #206bb7);
    border-top-color: #234996;
    border-right-color: #4d6ba7;
    border-bottom-color: #AFB2B7;
    border-left-color: #586d96;
    border-bottom-color: #546580;
    color: #ffffff;
    font-size: large;
}
</style>
For HTML Sanitization, I have a JavaScript code too -

if(!$('#AlienBox').length){
$('body').append($(`<style id="AlienBox">
.sf-modal-dialog-content textarea {
    color: azure;
    background-color: brown;
}
.sfc-default-theme.sf-element-modal-dialog .sf-element-modal-dialog-footer {
    font-size: 14.5px;
    background-color: #1e264e;
    color: #BDBFC3;

}
.sfc-default-theme.sf-element-modal-dialog .sf-element-modal-dialog-header {
    background-color: #134373;
}
.sfc-default-theme.sf-element-modal-dialog {
    background-color: #772323;
}
.sf-element-modal-dialog .sf-element-modal-dialog-header-title-text {
    font-size: x-large;
    color: blanchedalmond;
}
.sfc-default-theme.sf-element-modal-dialog .sf-element-modal-dialog-header .sf-element-modal-dialog-header-close {
    color: #ffffff;
    font-size: xx-large;
}
.sfc-default-theme.sf-element-modal-dialog .sf-element-button.sfpc-secondary {
    background-image: linear-gradient(to bottom, #7b3939, #206bb7);
    border-top-color: #234996;
    border-right-color: #4d6ba7;
    border-bottom-color: #AFB2B7;
    border-left-color: #586d96;
    border-bottom-color: #546580;
    color: #ffffff;
    font-size: large;
}
.sfc-default-theme.sf-element-modal-dialog .sf-element-button {
    background-image: linear-gradient(to bottom, #7b3939, #206bb7);
    border-top-color: #234996;
    border-right-color: #4d6ba7;
    border-bottom-color: #AFB2B7;
    border-left-color: #586d96;
    border-bottom-color: #546580;
    color: #ffffff;
    font-size: large;
}
</style>`, {
        id: 'AlienBox' 
   }));
}
This is what I got with my code -

Share:

Interacting with Subsets with IronPython

What if you have to compare All Data with current Selections (Marking, Filtering etc.) ?
What if you have to compare your two selections?

I know answer will be - using (Subsets).
But, What If you want to make this comparison on-Demand only ?

My Answer is below IronPython code -
from Spotfire.Dxp.Application.Visuals import *
vsc = v.As[VisualContent]().Data.Subsets
vsc.Clear()# To Clear all subsets except defaults
#Use below 2 rows if you need to add additional Subsets
#vsc.AddDataSelection(Document.Data.Markings["Marking Name"])
#vsc.AddDataSelection(Document.Data.Filterings["Filtering Scheme Name"])
for ss in vsc:
print ss.DisplayName,"\n\tEnabled ? ",ss.Enabled,"\n\tInteractive? ",ss.Interactive
if ss.DisplayName =='All data':#Toggle between one selection Enabled status
ss.Enabled = not ss.Enabled
ss.Interactive=False
With above code, we are expecting these results -

Share:

Adding Styles to Legend Area

Recently I have posted a few ways to style different Spotfire elements. Now I have one more, for Legends this time.
This is what I have been able to achieve so far -
Here is the code you need to Add to one of the HTML Text Area -
<style id="AlienBox">
.StyledScrollbar.LegendScroll {
    background-color: darkcyan;
    border: 2px solid darkmagenta;
    border-radius: 12px;
}
.sfc-style-root .sf-element-legend-item {
    padding-top: 1px;
    padding-right: 10px;
    padding-bottom: 6px;
    padding-left: 10px;
    background-color: blueviolet;
    border: 2px solid blue;
    border-radius: 12px;
}
.sf-element.sf-element-title.sf-legend-item-elem {
    background-color: darkblue;
    border-radius: 12px;
}
.sf-element-document .sf-element-axis-tray .sf-element-text-box {
    vertical-align: top;
    color: deepskyblue;
    font-weight: bold;
    font-size: x-small;
}
.sf-element.sf-element-sub-item-section.sf-legend-item-elem {
    font-variant: petite-caps;
    font-style: italic;
    font-weight: lighter;
    font-size: x-small;
}
</style>
For HTML Sanitization issue, we have a solution as always as a JavaScript code -
if(!$('#AlienBox').length){
$('body').append($(`<style id="AlienBox">
.StyledScrollbar.LegendScroll {
    background-color: darkcyan;
    border: 2px solid darkmagenta;
    border-radius: 12px;
}
.sfc-style-root .sf-element-legend-item {
    padding-top: 1px;
    padding-right: 10px;
    padding-bottom: 6px;
    padding-left: 10px;
    background-color: blueviolet;
    border: 2px solid blue;
    border-radius: 12px;
}
.sf-element.sf-element-title.sf-legend-item-elem {
    background-color: darkblue;
    border-radius: 12px;
}
.sf-element-document .sf-element-axis-tray .sf-element-text-box {
    vertical-align: top;
    color: deepskyblue;
    font-weight: bold;
    font-size: x-small;
}
.sf-element.sf-element-sub-item-section.sf-legend-item-elem {
    font-variant: petite-caps;
    font-style: italic;
    font-weight: lighter;
    font-size: x-small;
}
</style>`, {
        id: 'AlienBox' 
   }));
}

Share:

Display Current User Information on Menu Bar

I recently posted about how to add Information to Menu Bar . I have been asked on LinkedIn - "How to display Current Logged in Username here ?"
I will not say it is difficult, but involves a little more number of steps, because we have to use some extra steps to get current user details as well.
So, Lets Start !
  1. Create 2 Document Properties time and UserName . We will use time to trigger a IronPython Script to get current user details.
  2. Add script to Document Property time .
    You can use any script to get user information. I used approach from my post on LinkedIn-
    from Spotfire.Dxp.Framework.ApplicationModel import UserContext
    r=Application.GetService[UserContext]()
    Document.Properties["UserName"] = r.Username
  3. Now, create a Data Function with Simple script.
    output=input
  4. Define Output Parameter to Document Property time to trigger IronPython code from step 2.
  5. Define Input Parameter to expression below-
    String(DateTimeNow())
  6. In HTML Text Area, create a Div with Property User enclosed -
    <span id='userDet' style="visibility:hidden;">
    <SpotfireControl id="52ea70f998bb46c985e49a1d0ca03ada" />
    </span>
  7. Add JavaScript for final touch-
    if(!$('#AlienBox').length){
     $('body').append($(`<style id="AlienBox">
     #Brand {
        position: absolute;
        top: 0px;
        right: 40%;
        height: 30px;
        width: 100px;
        z-index: 99;
        border: 1px solid chocolate;
        border-radius :5px;
        color:chocolate;
    }
     </style>`, {
            id: 'AlienBox' 
       })); 
    }
    innerHTML=`<div id="Brand">
     <center> Current User is <br><b>`;
    innerHTML+=$("#userDet").text();
    innerHTML+=`</b> </center>
     </div>`;

    if(!$('#Brand').length){
     $('body').append($(innerHTML, {
            id: 'Brand' 
       })); 
    }
  8. Save the Analysis and Close.
  9. Open Analysis again to see the desired output.
I am not including any screenshot this time, Just give a try and see the results yourself. 

Share:

Utilizing Space under Legends for Additional Information

Have you ever struggled for little space for placing information and Just observed -"Hey! I have some under Legends!". But, That area is not available for editing
What to do ?
Well, Remember I have shared a post about adding Information to Menu bar ? I have customized that to add some extra stuffs. We will create a button on Menu bar, which will bring some extra information under selected legend (eq(2)in code is 3rd legend item of the page here).

Add this code to a JavaScript -
if(!$('#AlienBox').length){
$('body').append($(`<style id="AlienBox">
#Brand {
    position: absolute;
    top: 0px;
    right: 40%;
    height: 30px;
    width: 150px;
    z-index: 99;
border: 1px solid chocolate;
border-radius :5px;
color:chocolate;
}

</style>`, {
        id: 'AlienBox' 
   }));
}

if(!$('#Brand').length){
$('body').append($(`<div id="Brand">
<center> For Information  <br> <button onclick="alienLegendFn()" style="background-color: chocolate;border: none;  color: white;   text-decoration: none;  display: inline-block; ">Click Here</button> </center>
<script >
  function alienLegendFn() {
  if(!$('#AlienLegend').length){
$('.sf-element-legend-item:eq(2)').append($('<div id="AlienLegend" style = "border: 1px solid chocolate; border-radius :5px; color:chocolate;"> You can place addional information here </div>', {
        id: 'AlienLegend' 
   }));
}

   </script>
</div>
`, {
        id: 'Brand' 
   }));  
}

Here is what you expect after clicking newly created button -
Share:

Add a Little Information to the Menu Bar

When I launched Spotfire today, I saw this menu bar-
Everything is right, but I felt I should add a little fun to this space. I tried to to add some information to it, and I think we can use same for Adding Dashboard Title as well (Anyways this bar remains there regardless of we use it or not) -

Here is how to achieve this -

  1. Add JavaScript to text area.
  2. Customize segment <div id="Brand"> as per your need.
  3. Paste below code (after customization) and save.

if(!$('#AlienBox').length){
$('body').append($(`<style id="AlienBox">
#Brand {
    position: absolute;
    top: 0px;
    right: 40%;
    height: 30px;
    width: 100px;
    z-index: 99;
border: 1px solid chocolate;
border-radius :5px;
color:chocolate;
}

</style>`, {
        id: 'AlienBox' 
   }));
}

if(!$('#Brand').length){
$('body').append($(`<div id="Brand">
<center> Designed by <br><b>Vivek Kumar</b> </center>
</div>`, {
        id: 'Brand' 
   }));
}
Share:

Deleting All visualizations meeting a Specific Condition

How to remove all visualizations meeting one criteria ?
Deleting Visualizations may be very useful in many situations. One example is, if we want to remove all Line Charts (may be I am not interested in trends at the moment). This is how it can be achieved -
from Spotfire.Dxp.Application.Visuals import *
for p in Document.Pages:
for v in p.Visuals:
if str(v.TypeId) == "TypeIdentifier:Spotfire.LineChart": # Criteria
print v.Title
p.Visuals.Remove(v)
In case you want to keep it restricted to currently active page only,code is more simple -
from Spotfire.Dxp.Application.Visuals import *
for v in Document.ActivePageReference.Visuals:
if str(v.TypeId) == "TypeIdentifier:Spotfire.LineChart": # Criteria
print v.Title
Document.ActivePageReference.Visuals.Remove(v)
Share:

Search within column - Limiting values in Property Control

Before we begin, I have a question. Why List Box filter is so special ?
Yes, you got it right! The search within column values. What if we want to implement something similar for List Box Property Control ?
We are going to do it today !!
Let's Start.

  1. We are going to create a Input Field property first to capture our search string. In this example, I am going to call it - ${CountrySearch}. This is going to search values in [Country Name] column.
  2. Create a Calculated column [Country] to hold search results with expression below -If(Len('${CountrySearch}')>0,
         If(Find(Lower('${CountrySearch}'),Lower([Country Name]))>0,
                 [Country Name]) ,
         [Country Name])
  3. Now create your Property Control using column [Country]. I have given a search button, just to move focus out of search box; however hitting enter also works well.
Here is what we have in the end -
Share:

Removing Duplicates - Efficient Way

Duplicates in any source are always painful. We are expecting unique records and we get a lot of duplicates there.

How to deal with them ?
Well, there are many ways bur most of the times they involve a lot of steps.
Here, I am going to give you an approach which involves just one Filter Rows Transformation ๐Ÿ‘Š . For this use below expression in transformation after replacing columns according to your data -
If(
Rank(Rowid(),"asc",[Primary Key])=1
,TRUE 
,FALSE 
)
Here, if you want to identify unique rows based on more than one columns - Just add them like this :
If(
Rank(Rowid(),"asc",[Primary Key],[Data])=1
,TRUE 
,FALSE 
)
Want to see what happens ? Have a look -

Share:

Tracing Data Transformations from IronPython

Have you ever needed to gather details about transformations used in all Data Tables ? I know, you will go to Data Panel ๐Ÿ‘ด
Now a twist - What If you have 20+ Data Tables ? Now you are getting irritated !
That's why we have IronPython ✌.
Although it is programmed to look for very basic details, but can be customized for more stuffs ๐Ÿ’ช

from Spotfire.Dxp.Data import *
from Spotfire.Dxp.Data.Transformations import *
from Spotfire.Dxp.Data.DataOperations import *
from System.Collections.Generic import List

for table in Document.Data.Tables:
    sourceview=table.GenerateSourceView()
    for op in sourceview.GetAllOperations[DataTransformationsOperation]():
        for t in op.GetTransformations():
            print t.Name
            #print t.GetType() #Un-comment & Google for this row's output for Documentation when you need
            if t.Name=='Filter rows':
                print "\tExpression : ",t.Expression
            if t.Name=='Replace value':
                print "\tColumn :",t.Column
                print "\tOriginal Value : ",t.OriginalValue
                print "\tNew Value : ",t.NewValue
Share:

Executing IronPython Codes with Progress Bar

I had a code to reload data table (which takes long time) and end users were keep on hitting Action button as they were not sure if something is happening. Sounds familiar to you as well ?
What to do ?
Probably if they see a progress bar it will be better, right ? Well TIBCO Community already have a post about it. Then why this post ?
Because you need keep a few things in mind -

  1. I don't like code - fewer lines would have done the thing ๐Ÿ‘ฒ
  2. No error stack-trace 
  3. Some extra precautions needed.๐Ÿ’€
Let's start. First of all, my code -

from Spotfire.Dxp.Framework.ApplicationModel import *
import traceback , time

proc=Application.GetService[ProgressService]()
def ex():
try:
# Wait for 5 seconds, Just to keep progress screen up for demo - remove from actual code
time.sleep(5)
proc.CurrentProgress.ExecuteSubtask("Refreshing Data")
Document.Data.Tables.ReloadAllData()
proc.CurrentProgress.ExecuteSubtask("Refresh is Complete")
except:
traceback.print_exc()
proc.ExecuteWithProgress("Refreshing Data Manually","Trying to refresh all Data Tables with a progress bar", ex)

Now coming back to precautions; this thing should be unchecked if you don't want to struggle with an error -
Also, please handle the exceptions wisely, using default except block may help in debug; but a well handled code brings robustness.
Regarding additional wait- do not use if you don't need it.
This is what you can expect in client -

Share:

Be Fair with Filters Panel

I was looking at custom theme option in Spotfire -

Wait, What  ?? I cannot customize Filters Panel from here !!
But, You already know I will ๐Ÿ‘ฝ

With CSS code

<style>
.VirtualListBox .sf-element-list-box-item {
    background-color: cadetblue;
    color: floralwhite;
    border-left: 3px solid chocolate;
}
.sfc-style-root .sf-element-panel-content.sfc-filter-panel .sf-element-search-field .sf-element-input {
    padding-left: 5px;
    padding-right: 18px;
    color: #72eca6;
    background-color: blueviolet;
    border: 2px solid #72eca6;
    border-radius: 4px;
}
.sf-element-panel-content.sfc-filter-panel .sf-element-filter {
    position: absolute;
    overflow: hidden;
    color: #e0ec3b;
    background-color: #454545;
    border-color: darkorange;
    border-radius: 18px 0px 0px 0px;
}
.sf-element-panel-content.sfc-filter-panel .sfpc-active .ContextButton {
    visibility: visible;
    background: #26a2ed;
    border: 1px solid white;
}
</style>

JavaScript For HTML Sanitization Victims๐Ÿ’ƒ

if(!$('#AlienFilter').length){
$('body').append($(`<style id="AlienFilter">
.VirtualListBox .sf-element-list-box-item {
    background-color: cadetblue;
    color: floralwhite;
    border-left: 3px solid chocolate;
}
.sfc-style-root .sf-element-panel-content.sfc-filter-panel .sf-element-search-field .sf-element-input {
    padding-left: 5px;
    padding-right: 18px;
    color: #72eca6;
    background-color: blueviolet;
    border: 2px solid #72eca6;
    border-radius: 4px;
}
.sf-element-panel-content.sfc-filter-panel .sf-element-filter {
    position: absolute;
    overflow: hidden;
    color: #e0ec3b;
    background-color: #454545;
    border-color: darkorange;
    border-radius: 18px 0px 0px 0px;
}
.sf-element-panel-content.sfc-filter-panel .sfpc-active .ContextButton {
    visibility: visible;
    background: #26a2ed;
    border: 1px solid white;
}
</style>`, {
        id: 'AlienFilter' 
   }));
}
I got this so far -

Share: