Skip to Content

Change Log

  • 02/26/2016 – All improvements now bundled for download.
  • 02/26/2016 – Major optimizations on compression of data payload.  Data sent to BIAL layer is no longer enlarged with URIEncoded bloat, which eats into the 200k property limit.  I am now compressing using LZString compression on frontend (client) and decompressing on backend (BIAL engine).  Compression rate on average is right at 200%.
  • 02/25/2016 – Pushed flattening of data to the ZTL layer.  This means larger data volumes can be used.  (See Restrictions for details)
  • 02/09/2016 – New containing() method for row filtering, now you can create trellis-like/grouping-like logic, as well as cascading filters.  See Grouped Scorecard example at bottom.
  • 02/08/2016 – Blog posted

Planned Enhancements

  • Up for discussion!
  • Iterate via columns?

Restrictions

  • Requires 1 or more Measures to be present
  • Data ‘payload’ cannot be higher than 200KB to server.  I’ve optimized this to use the compressed ‘tuple’ payload and perform the flattening there.  (Feb 25)  This means a previously flattened payload of flat data (226 rows) in one example of 49,075 bytes can now be relayed in 12,726 bytes.  The compression is not linear, meaning the higher the amount of rows and also the cardinality of your dimension members will play into how compressed it can be.  There is still the potential to hit the 200KB limit but these would be for quite large sets of data.  I cannot overcome this Design Studio limit, so use reasonable volumes of data.

Description

Use Case:

Design Studio, being a multi-dimensional client, likes to decompose data into ‘tuples’ which basically defines each measure as a cell value that is represented by indexed tuples that map back to a dimension member.  There’s not really anything “wrong” with this, except that at least in my opinion, this is not the easiest way for me to work with the data in a 2D tabular form.  There have been many SCN threads where people have struggled with basically looping through (aka iterating over) the rows in order to apply some script logic.  Even in my other extensions, the first thing I do is “flatten” the dataset into a 2-dimensional (or table-like) form to work with.  I start thinking about why couldn’t I just open this convenience up to BIAL scripting?  This is what I have written this component called ‘Data Iterator’.

Welcome to the Data Iterator

The Data Iterator is a Technical Component available to add to your Design Studio application.  It is very simple to configure, in that you simply assign it a Data Source, and you are ready to use it in your script.

Step 1: Add a Data Iterator Component

/wp-content/uploads/2016/02/di1_883513.png

Step 2: Assign it a Data Source

/wp-content/uploads/2016/02/di2_883544.png

Optional Event to note is ‘On Data Change’ – This essentially fires an event any time the Data Source changes (via filtering, navigation, etc.)

That’s it.  You’re done configuring it.  But what does it do?  It’s time to see what we can do with this at script-time!

Script-Time Methods

Before explaining the methods, I need to explain conceptually what it is doing with the data.  Let’s start with a typical Data Source’s result set:

/wp-content/uploads/2016/02/di3_883545.png

As mentioned in the use case, the first thing I do is ‘flatten’ the data internally into an easier to use form.  This means I have some of my own conventions going forward:

  • getDimensions – Returns a list of dimensions currently in Rows.  This is a simple call that you can do today with DS_1.getDimensions(Axis.ROWS); but there are some subtle differences in some cases.  See example below:/wp-content/uploads/2016/02/di4_883546.png
  • getMeasures – Returns a list of items in columns.  Most of the time this is usually Key Figures/Measure selection members, however it will go ahead and flatten in cases where you add a dimension in your Columns as well.  This is where you would begin to struggle using standard BIAL calls to pull this off:/wp-content/uploads/2016/02/di5_883556.png
  • getRows(optional offset, optional maxRows) – Returns rows optionally from a given row offset, and optionally a maximum amount of rows.  This is where things can get interesting!  Example:/wp-content/uploads/2016/02/di6_883557.png
    So, let’s consider the rows here… we have a rows.forEach loop, which returns an element (named row in my example and an index that just comes with forEach, starting at 0…)  The row element itself has some BIAL methods we must explain:

    /wp-content/uploads/2016/02/di7_883558.png

    • getDimensionValueKey(dimensionKey) – Returns the member key for a given dimension key.
    • getDimensionValueText(dimensionKey) – Returns the member text for a given dimension key.Example:
      (In this case, key and text was the same.)
      /wp-content/uploads/2016/02/di8_883574.png
    • getMeasureValue(measureKey) – Returns value in float format for the current row’s column for the passed measureKey.
    • getMeasureFormattedValue(measureKey) – Returns formatted value in String format for the current row’s column for the passed measureKey.

      Example:/wp-content/uploads/2016/02/di9_883575.png
      A few things to note above.  On the 3rd line, you see that we can dynamically determine in this case, the measure “key” in the first column position by saying getMeasures().atIndex(index) where ‘index’ indicates the column you want (beginning at 0).  This is also available for getDimensions().atIndex(index).  This means that you don’t HAVE to hard-code a key (like we are doing with 0D_MATERIAL) and have it adapt to whatever the contents are in the result set.  Also note that I switched the output from ‘Formatted Text’ component to my ‘Rapid Prototyping’ component.  This is because ‘Formatted Text’ was stripping out certain HTML markup and I wanted to show some conditional formatting quickly.
  • getRows().containing(options) – Filters rows and returns subset based on selection criteria (See Grouped Scorecard example)
    This is a really cool method.  It allows you to select a subset of data and even chain them together as such:Any filters in each containing clause are treated as an OR, with subsequent containing clauses operating as an AND.

    var rows = DATAITERATOR_1.getRows().containing({  "dimensions": [
      { "key" : "0D_CO_CODE", "value" : "1000" },  { "key" : "0D_CO_CODE", "value" : "2000" }
      ]
      }).containing({
    "dimensions" : [{ key : "0CALMONTH", "value" : "04/2004"}]
    }) ;

Putting it all together:

After seeing these basic, fundamental methods, what else can you do?  You can go as wild as you want!  If you are accustomed to writing in languages such as JSP, BSP, ASP, etc, the use cases are endless when using Data Iterator along with Rapid Prototyping, as an example.  Below are two proof-of concept examples.  With some additional CSS-clean up and more time, you could come up with some super-easy to create visuals!

Simple Table showing only first 10 rows (Could enhance to paginate with buttons etc):


// Get flattened rows from Data Iterator
var rows = DATAITERATOR_1.getRows(0,10);
// Get dimensions (Rows) and Measures (Cols)
var dimensions = DATAITERATOR_1.getDimensions();
var measures = DATAITERATOR_1.getMeasures();
// Start a simple HTML table
var html = "<div style='height:400px;overflow:scroll'><table class='example'><tr>";
// Draw headers for dimensions and measures
dimensions.forEach(function(element, index) {
  html = html + "<th>" + element.text + "</th>";
});
measures.forEach(function(element, index) {
  html = html + "<th>" + element.text + "</th>";
});
html = html + "</tr>";
// Loop through the rows...
rows.forEach(function(row, index) {
  // Draw a new row
  html = html + "<tr>";
  // Write out the dimension texts
  dimensions.forEach(function(member, index) {
  var dimText = row.getDimensionValueText(member.key);
  html = html + "<td class='dimension'>" + dimText + "</td>";
  });
  // Row striping example
  var stripe = "even";
  if(index/2 == Math.floor(index/2)) {
  stripe = "odd";
  }
  // Write out the measure formatted values
  measures.forEach(function(measure, index) {
  var measureVal = row.getMeasureValue(measure.key);
  var measureText = row.getMeasureFormattedValue(measure.key);
  html = html + "<td class='measure " + stripe +" '>" + measureText + "</td>";
  });
  html = html + "</tr>";
});
html = html + "</table></div>";
RAPIDPROTOTYPE_1.setHTML(html);





Simple Table/Micro Chart:


// Get flattened rows from Data Iterator
var rows = DATAITERATOR_1.getRows(0,250);
// Get dimensions (Rows) and Measures (Cols)
var dimensions = DATAITERATOR_1.getDimensions();
var measures = DATAITERATOR_1.getMeasures();
var firstMeasureKey = measures.atIndex(0).key;
// Figure out Max in BIAL for rendering chart bars
var max = 0.0;
rows.forEach(function(row, index) {
  var v = row.getMeasureValue(firstMeasureKey);
  if(v>max){ max = v; }
});
// Start a simple HTML table
var html = "<div style='height:400px;overflow:scroll'><table class='chart'><tr>";
// Draw headers for dimensions and measures
dimensions.forEach(function(element, index) {
  html = html + "<th>" + element.text + "</th>";
});
// Draw first measure header
html = html + "<th>" + measures.atIndex(0).text+"</th>";
var w = 300;
html = html + "</tr>";
// Loop through the rows...
rows.forEach(function(row, index) {
  html = html + "<tr>";
  // Draw a new row
  dimensions.forEach(function(member, index) {
  var dimText = row.getDimensionValueText(member.key);
  html = html + "<td class='dimension'>" + dimText + "</td>";
  });
  var measureVal = row.getMeasureValue(firstMeasureKey);
  var measureFVal = row.getMeasureFormattedValue(firstMeasureKey);
  var barWidth = w * (measureVal / max);
  html = html + "<td style = 'width:" + (w+200) +";'>";
  html = html + "<div style = 'display:inline-block;width:" + barWidth + "px;background-color:#006699;'> </div>" + measureFVal;
  html = html + "</td></tr>";
});
html = html + "</table></div>";
RAPIDPROTOTYPE_2.setHTML(html);





Runtime Example of both:

/wp-content/uploads/2016/02/di10_883576.png

Super Goofy Scorecard Example:


// Get flattened rows from Data Iterator
var rows = DATAITERATOR_1.getRows(0,10);
// Get dimensions (Rows) and Measures (Cols)
var dimensions = DATAITERATOR_1.getDimensions();
var measures = DATAITERATOR_1.getMeasures();
// Start a simple HTML table
var html = "<table class='example scorecard'><tr>";
// Draw headers for dimensions and measures
dimensions.forEach(function(element, index) {
  if(element.text != "Key Figures"){
  html = html + "<th>" + element.text + "</th>";
  }
});
measures.forEach(function(element, index) {
  html = html + "<th>" + element.text + "</th>";
});
html = html + "</tr>";
// Loop through the rows...
rows.forEach(function(row, index) {
  // Draw a new row
  html = html + "<tr>";
  var priorValue = DATAITERATOR_1.makeNull();
  // Write out the dimension texts
  dimensions.forEach(function(member, index) {
  var dimText = row.getDimensionValueText(member.key);
  if(member.text!="Key Figures"){
  html = html + "<td class='dimension'>" + dimText + "</td>";
  }
  });
  // Row striping example
  var stripe = "even";
  if(index/2 == Math.floor(index/2)) {
  stripe = "odd";
  }
  // Write out the measure formatted values
  measures.forEach(function(measure, index) {
  var trend = "";
  var measureVal = row.getMeasureValue(measure.key);
  var measureText = row.getMeasureFormattedValue(measure.key);
  if(index>0 && !DATAITERATOR_1.isNull(priorValue) && !DATAITERATOR_1.isNull(measureVal)){
  var delta = Math.round(measureVal / priorValue * 100) + "%";
  var icon = "";
  if(priorValue > measureVal){ // Down
  trend = "downward";
  }else{ // Up
  trend = "upward";
  }
  measureText = "<div class='icon'></div><br />(" + delta + ")</span><br />" + measureText;
  }
  if(!DATAITERATOR_1.isNull(measureVal)){
  priorValue = measureVal;
  }else{
  priorValue = DATAITERATOR_1.makeNull();
  measureText = " - ";
  }
  html = html + "<td class='measure " + stripe + " " + trend + "'>" + measureText + "</td>";
  });
  html = html + "</tr>";
});
html = html + "</table>";
RAPIDPROTOTYPE_3.setHTML(html);




/wp-content/uploads/2016/02/di11_883658.png

Grouped Scorecard (webi-like sections and blocks)


var members = DS_2.getMembers("0D_CO_CODE", 100);
var html = "<div style='height:100%;overflow:scroll'>";
members.forEach(function(member, index) {
  var item = member.externalKey;
  // Get flattened rows from Data Iterator containing certain company code
  var rows = DATAITERATOR_1.getRows().containing({
  "dimensions": [
  { "key" : "0D_CO_CODE", "value" : item }
  ]
  });
  html = html + "<h2>" + member.text + "</h2>";
  // Get dimensions (Rows) and Measures (Cols)
  var dimensions = DATAITERATOR_1.getDimensions();
  var measures = DATAITERATOR_1.getMeasures();
  // Start a simple HTML table
  html = html + "<table class='example scorecard'><tr>";
  // Draw headers for dimensions and measures
  dimensions.forEach(function(element, index) {
  if(element.text != "Key Figures" && element.key !="0D_CO_CODE"){
  html = html + "<th>" + element.text + "</th>";
  }
  });
  measures.forEach(function(element, index) {
  html = html + "<th>" + element.text + "</th>";
  });
  html = html + "</tr>";
  // Loop through the rows...
  rows.forEach(function(row, index) {
  // Draw a new row
  html = html + "<tr>";
  var priorValue = DATAITERATOR_1.makeNull();
  // Write out the dimension texts
  dimensions.forEach(function(member, index) {
  var dimText = row.getDimensionValueText(member.key);
  if(member.text!="Key Figures" && member.key !="0D_CO_CODE"){
  html = html + "<td class='dimension'>" + dimText + "</td>";
  }
  });
  // Row striping example
  var stripe = "even";
  if(index/2 == Math.floor(index/2)) {
  stripe = "odd";
  }
  // Write out the measure formatted values
  measures.forEach(function(measure, index) {
  var trend = "";
  var measureVal = row.getMeasureValue(measure.key);
  var measureText = row.getMeasureFormattedValue(measure.key);
  if(index>0 && !DATAITERATOR_1.isNull(priorValue) && !DATAITERATOR_1.isNull(measureVal)){
  var delta = Math.round(measureVal / priorValue * 100) + "%";
  var icon = "";
  if(priorValue > measureVal){ // Down
  trend = "downward";
  }else{ // Up
  trend = "upward";
  }
  measureText = "<div class='icon'></div><br />(" + delta + ")</span><br />" + measureText;
  }
  if(!DATAITERATOR_1.isNull(measureVal)){
  priorValue = measureVal;
  }else{
  priorValue = DATAITERATOR_1.makeNull();
  measureText = " - ";
  }
  html = html + "<td class='measure " + stripe + " " + trend + "'>" + measureText + "</td>";
  });
  html = html + "</tr>";
  });
  html = html + "</table>";
});
html = html + "</div>";
RAPIDPROTOTYPE_4.setHTML(html);


Runtime Example:

/wp-content/uploads/2016/02/di12_884356.png

Oh, and PS here’s the CSS for my examples:


.example {
  border-collapse : collapse;
}
.example .dimension {
  background-color : #006699;
  color : #FFFFFF;
}
.example th {
  background-color : #006699;
  color : #FFFFFF;
  font-weight : bold;
}
.example.scorecard th {
  /*white-space: nowrap;*/
  padding : 20px;
  background-color : #0099CC;
  color : #FFFFFF;
  font-weight : bold;
  font-size : 20pt;
}
.example .measure {
  text-align : center;
}
.example .icon {
  display : inline-block;
  width : 48px;
  height : 48px;
}
.example .downward .icon{
  background-image : url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABmJLR0QA/wD/AP+gvaeTAAAAB3RJTUUH2QcVCAsthDpI/AAABQ9JREFUaIHtV0tsG0UY/ma9XnudJq1Tp2ppRRMeF6jopVKFEIWq9NACogipQE9wQEgc4AYmAqkXWpUb0CvigopED1CqJgdSFBCoIFBJk5YWEhKnjR/JOonf+5wZDrEbs971ay0liHzSL8+u5//n++af+WcW2MAGNrCBDfyfQbw49x89zTtBQjDIlumRaLYdX9Hr4CdeeBIoy+AAOOcrjxxgnCOTLa6+A8D5Sp9K+/ufxnQv43sWAA6M/Z12/otzKIs5V9eH+rd6Hl7wGoDx9lcR9+BbgWcBXjh4EV/BGmfA6+gdEOAF62IJMdY+CQ+ud7G2e6ADCtZ0D3QCHciAlyW0LjLgwXc9LCEvWB9VyMs54HVwrPUe6MAScr3M9R89tR8gPwMACEqOnbi3Mlq+mQYgEaX/6dOmQ/wQAAggj0wPRSecYtT9Hhh45tRrASlw9sBjeyVBEEAZW70Ws5Vfvyji9kLehWD92+i2cAiU0ruTwCsZIYBlUsRisxQMJ2aGol+6xfDVE5D56/LV7vsOkXxe3b9je8SfzurIFk0UVAtFbcVyJaNuFkqq+3Vf1S1oBr1ruslAGYcoEMzdiReYyd6eGY5+Vo9jXQEAkJkc+SGw6/E9Jd144N6dEX9JM0EZL6e/8RKqJ4DbjAgEoaCIZDxZ0E3zXOxS9P1G/JraxHJIfSWRUMZmYwlja48MQjx9iToTIQRdQT8WkoquqfqVWHDgjab8mul04/xJg2j8yOTMXFxRFlm4O+CNrQ2EAHJARHYpYxaKxSldUI/h/HHajG/TZXR6JJoVKTlw42ZsuVgs8c1dUvuMbQhKIkrFAltaWlJESg8mLp50rnoOaOkcmBp+Z44wdnB84s8Csyx0Bb1/Ugf8PliGgfS8UoLADk0NDyqt+Ld8kE0PRScsgx67Nnar6PetEGgXkiiAMIpUMqEyxp+LXRy81WqMtkbPTl2e6bn/YGpxKXd4184+P+Xup6pbFfIJBKIgIBlPqJzS12PDgxfa4dL29C1PXv5908ATvYWCunfH9ohkUuZYUp0ECIQg4BegJJMFy6JnZobe/aRdHu3nH0BmcuTb0O7v9pkmHeiLhEXTYjV97AIIAQKSiMWFhaKh69/MXIq+5YWDx8sc4bKsvTQ/nx5PJhaMUEBEoyNCEn3IpNO6pqoTsqy96m381jNAyj4VE5U/Rokk9X1VIvKLXaFQd1dIFiy6monqDEiigFI+T3PZbLw0O/5UbPSsXo4jlK3lE7IZAZXgYtl8VW0RgL+4cJ0GN22/mDcDL/ds6ZYDkp/Q8qauCBB9Akxd40uLi8ta4vrh+fFzy1XkfbZ2RQxBg8+GegKqA4u2do2QQmpCDfbcM5ozfMfDvWG/KPrAGEdJ1eETCLhlQZlPqVrq5vOpq5/P2khXW4V4dRtuQtwE2INWi3GyFRHJa8ty5MHJvIbDka29fggEqmqAcIp0KqHpmdtvJn/59FfUzrKTOaFGhJOAivp65jRzAgBf/s5vsdC2PYWiRh/t7QuLqqohnUpqRkb5MP7jx1/XIedIsBHcMlBvZhoSyM1euSbv3BfWVOvhfC5n6MXsF3OjZz4CwMrGq9rM9r6R1RB1g9PadHu2r1sAsjBw5L0LDFyYHf7gWUCtlKYKeY5/C7GLchJZg2bKlhNZt81WnSESiuyWeGCzT42Pq1idPfuM2sU4iXJFq3XXjXANeRd/NxFOgpom1Ak0Q74Cu4gN/KfxDxmvmYQNdjkRAAAAAElFTkSuQmCC)
}
.example .upward .icon{
  background-image : url(data:image/png;base64,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)
}
.example .downward {
  color : #FF0000;
}
.example .upward {
  color : #009966;
}
.example .measure.even {
  background-color : #FFFFFF;
}
.example .measure.odd {
  background-color : #DFDFDF;
}



What you have seen is available for download in the usual spot (details here: SCN Design Studio 1.6 SDK Components (ver 3.0)). 

 

 

Questions/Comments/Feedback always welcomed!

To report this post you need to login first.

91 Comments

You must be Logged on to comment or reply to a post.

  1. Franck Blais

    Come on Mike … You have to slow down or we won’t have anything to develop for Ds …

    Again, a lot of use-cases for this one, even if, if I am not mistaken, you can (with a lot of scripting) reproduce the same behavior with getDimensions and getData.

    Your solution is definitely better 😛

    Looking forward to my next dashboard to use it 🙂 Nice work !

    PS: Do you support hierarchies ? (Call me Mr Hierarchy please).

    (0) 
    1. Mike Howles Post author

      you can (with a lot of scripting) reproduce the same behavior with getDimensions and getData

      I think even then, getData will throw Warnings if you issue a getData command where you request a selection that there is no data value.  Imagine if Calendar Year were in columns and you had Division and Key Figures in rows and if a Division did not have a certain key figure for a certain year, it will generate an ugly warning.  I never liked that.


      Also, yes a TON of scripting even at that 🙂


      PS: Do you support hierarchies ? (Call me Mr Hierarchy please).


      It supports hierarchy leafs/collapsed nodes, with an option of ignoring/including expanded nodes.  Not sure if it’ll fit your use case or not, but let me know!



      (0) 
      1. Mustafa Bensan

        Also, even with the scripting approach, I’m not sure that you can reproduce the exact dimension sort order of the result set either, so I expect this would be another benefit of the Data Iterator.

        (0) 
      1. Franck Blais

        Hi Ali,

        You would have to use nested forEach with a getMembers on each dimension in your datasource, and then use enough getDatas for each measure.

        Something like that:

        var dim1_members = DS_1.getMembers(DIM1).

        var dim2_members = DS_1.getMembers(DIM2).

        dim1_members.forEach(dim1_mem, dim1_index)  {

            dim2_members.forEach(dim2_mem, dim2_index)  {

               var measure_value1 = DS_1.getData(“Measure1”, [“DIM1”;dim1_mem.internalKey, “DIM2”;dim2_mem.internalKey ].

        }

        Note that as pointed out by Mike, you’ll have to hide the warning on the application (if the measure value is not available, a warning will be thrown).

        If you have 4 dimensions, you’ll need 4 nested. If you have 5 key figures, you’ll need 5 getData statements.

        (0) 
  2. koteswararao gandu

    Hi Mike,

    Thanks for sharing. We are planning to use this approach to achieve our tabular requirement with conditional formatting. we are able to meet the requirement (table with sections and conditional formatting) using above approach).

    out next step is to evaluate if we can interact with (filter data in) any other component in the dashboard based on the selection of a value from this table. if it doesn’t work, I think we will have to forgo the option.

    Any input would be appreciated.

    Thanks in advance,

    Kotesh.

    (0) 
    1. Mike Howles Post author

      I don’t have any plans to port this back down to 1.5, but it’s open source, feel free to do so with modifications where needed.

      (0) 
  3. Alfons Gonzalez Comas

    Hi Mike,

    Just a collateral question regardin the above sample. I am trying to use the HTML prototype component but I don’t see (it sounds me have seen it in the past) it in the list of components installed on 3.0 release.

    Am I missing something or the component is not longer supported?

    /wp-content/uploads/2016/02/kk_893346.jpg

    (0) 
      1. Karol Kalisz

        Hi Mike,

        we currently do not package prototypes in 3.0 as we have not cleaned it up. I am currently using the HTML prototype for me (starting from dev env). so, wither we clean up a bit in prototypes and release it (then only this one component will stay basically) or move this one as it is more usable than prototype into basics.

        Karol

        (0) 
        1. Mike Howles Post author

          Karol,

          Each time I’ve built the package, I’ve included Prototypes plugin.

          EDIT: Reason I’ve not moved the ‘Rapid Prototyping’ out of the ‘Prototypes’ feature, is the issue of namespaces.  Currently it’s inside the prototyping plugin, which wouldn’t that mean if we were to “graduate” it to ‘basics’, that it would break existing people’s dashboard references?

          (0) 
  4. Alfons Gonzalez Comas

    Hi Mike,

    I am having some issues when using the data iterator components in the following scenario:

    Data iterator (DS_ITERATOR) is binded to a data source (DS_1) that contains prompts variables and that is defined to be loaded on script (load in script = true).

    When the datasorce is loaded and the the prompts answered in the BIAL code seems that data iterator is not updating its content with new loaded datasource.

    My question is: does data iterator component support this scenario (binding to data source loaded on script with prompt variables answered on script). If yes, do we need to do something to make him aware of changes in datasource it is linked to (I haven’t found any method)

    Thx

    (0) 
    1. Mike Howles Post author

      Hmm good question. This is either a bug on my side or some sort of SDK limitation. (Probably a simple bug though on my side.) I never use prompts so it never occurred to me to check. I will check.

      (0) 
      1. Alfons Gonzalez Comas

        Hi Mike,

        We have performed additional tests to clarify if the issue was caused by the use of prompts or the Data source property load in script.

        We can confirm that prompts work fine with iterator (at least on our case). Problem seems to be clearly focused on the background processing and the “load in script” data source property.

        When load in script property is set to true and load source is deferred to the onbackground processing event following error message appears

        Message: org.mozilla.javascript.EcmaError: TypeError: Cannot read property “key” from undefined (getRows#20)

        Note: we are currently calling getRows method on data Iterator “On Data Change” event.

        Our question is: Would be possible to use the data iterator component on this scenario (data source background processing)?  we use it very frequently to optmize the app performance.

        thx

        (0) 
        1. Mike Howles Post author

          Hey Alfons – That helps narrow it down.  I’m quite frankly surprised how much interest this particular component got so quickly, so let me see if I can nail down this fix for you.

          (0) 
        2. Mike Howles Post author

          Just an update –

          A BW data source works fine for me using Load in Script = true during ‘On Startup’ but not during ‘On Background Processing’.

          I’ve not tested a UNX, nor can I reproduce the error you get.  Can you provide a snippet of the BIAL?

          (0) 
          1. Alfons Gonzalez Comas

            Hi Mike,

            When using UNX data sources and Load is script = True the situation is the same you describe above with BW’s one. Data iterator works fine when data source is loaded on startup phase but fails when it is loaded on “background processing”

            the BIAL code is very simple. Scenario summary (to reproduce the error)

            1) Data source (e.g: DS_1) with property Load in script = true

            2) On Startup Event: APPLICATION.doBackgroundProcessing();

            3) On Background processing: DS_1.loadDataSource();

            4) Data Iterator (e.g: DI_1) binded to DS_1

            5) Data Iterator on Data Change Event:   DI_1.getRows()

            where steps 2-3 are the standard implementation of background processing data load (best practice described on this link)

            We have noticed that with this approach the Data Change event (on data iterator) is triggered 2 times when DS_1.loadDataSource() is executed The first call is  the one that cause the error to appears, so we have found that a workaround is to process the code on Data Change event after the first call (this skips the error allows us to execute the getRows statement properly)

            Therefore the question that appears to you is: why the Data Change event is called 2 times in this scenario when data source is loaded? It is the expected behavior at this situation or a bug on the component?

            Note: Frankly, this interest  on the component does not surprise me. From my own experience on UNX data sources, this component fills the gap that prevented migrating definitely tons of Xcelsius into DS, so you are a hero!

            Thanks,

            (0) 
    2. koteswararao gandu

      I had similar issue to update Data Iterator after initial load. on selection of a different value (Date) from drop down Data source getting refreshed but Data Iterator is not being updated Or atleast a click (date) lag for update of Data Itetrator.

      (0) 
        1. koteswararao gandu

          Workaround mentioned by Alfons worked perfectly in my case. Thanks a lot!!

          Just one more question, Is there a straight way of capturing selected values from Rapidprototype after assigning html data (through Data Iterator) to it ? Just checking before going in a tough route.

          Thanks again Mike!! This component is such a value add to DS.

          (0) 
          1. Mike Howles Post author

            Just one more question, Is there a straight way of capturing selected values from Rapidprototype after assigning html data (through Data Iterator) to it ? Just checking before going in a tough route.

            I might not be totally following the question here (sorry!) – But the Rapid Prototyping component basically lets you write out HTML/JS and has some find/replace placeholder properties and 10 single cell data selection options to replace with, but that stuff is entirely optional, and probably doesn’t make sense to use in conjunction with the Data Iterator.  (However I’ve been surprised in the past with some creative applications of the Rapid Prototyping one, so who knows 🙂 ?)

            If you could give a little more detail I might be able to answer but I’m not sure.

            BTW – I’ve also considered for maybe in future a “merged” Data Iterator + Rapid Prototyping (Data Writer has a nice ring to it) component that just allows you to do it all in one component instead of two.  All the same scripting APIs would be available, but in one place instead of two.  This would come after any kinks are worked out of this current, though.

            (0) 
  5. Tobias Schleich

    Hi Mike,

    the data iterator sounds great. Would it be possible to apply a logic that only returns records that are selected by the user in a crosstab component? That would be a great option for planning application purposes where I often have the requirement to filer planning functions based on selected rows.

    Best Regards,

    Tobias

    (0) 
    1. Mike Howles Post author

      You could either use standard scripting logic to filter a second data source/data selection to perform that filtering, or incorporate that filtering logic in the getRows().forEach loop.

      (0) 
  6. Mike Howles Post author

    Update:

    02/25/2016 – Pushed flattening of data to the ZTL layer.  This means larger data volumes can be used.  (See Restrictions for details)

    (0) 
    1. Alfons Gonzalez Comas

      Hi Mike,

      I was preparing a question that you have maybe fixed with the latest version (it seems we think on the same 🙂 ). I have noticed that for large volumes of data (e.g: 6000 rows with 2 dimensions a 1 column) data iteratore crashes with errors such this one

      Message: Form too large: 2111213 > 200000

      Stack trace: java.lang.IllegalStateException: Form too large: 2111213 > 200000

      Reading restriction details I understand that you have improved the compression to allow putting more rows on this 200kb. There is some way to roughly estimate the number of rows that may be included on this limit?

      In other words, can we assume that the limit of rows using the data iterator will be the same we have currently on DS data sources (20.000 rows / 200.000 cells) ?

      Thanks

      (0) 
      1. Mike Howles Post author

        Hey Alfons – I’ve not pushed the update into a feature bundle yet – Whoever does that next (me or Karol), it’ll show up then, though.

        To answer your question, yes the error you are getting is a hard limit imposed by Design Studio, I cannot increase it, only “shrink” the overhead.

        By the way, there’s a “safety belt” warning for now that will tell you that your data is too big instead of it trying to send it, so this will stop crashes.  I may actually turn this warning into its own BIAL event like ‘On Data Overflow’ or something – What do you think?

        I cannot estimate how small/large the tuple payload will be on rows alone, and not even rows times columns, because it depends on the dimension cardinality also.  I could, if you like, expose a property called ‘payload size’ to give you a sense of how close you are getting, if that’s of value to you…

        (0) 
        1. Alfons Gonzalez Comas

          Hi Mike,

          I am impatient to have the bundle available to test the flattening of data on data iterator component!

          I am confident that this “shrink” may help us a lot to workaround our current issues managing medium volumes of data (very common on data sets with lots of potential dimensions of analysis).

          With regards the features you mention:

          – On data overflow event: It could be useful to display some kind of widows box dialog asking user to reduce the number of rows to be selected (when data source result comes from a combination of selections, as it usuall on our case)

          – payload size property:good to have, but only if the value does not longer appear on trace logs in order to have an estimation about how much value exceed from the limit.

          Alfons

          (0) 
    2. Alfons Gonzalez Comas

      Hi Mike,

      Just another annotion: in the restrictions details paragraph you state that data set can not overcome DS limit (200k). Following blog shows that the limit may be largely exceeded if any measures is included on the dataset.

      On the other hand the list of components requirements specify that the data source binded to data iterator component must contain 1 or more measures.

      My question is: would be possible to enhance the data iterator to support data sets with no measures? By removing this restriction it would be possible to bypass the aformentioned limit (200k) in some cases (e.g: cascade filters)

      Regards,

      (0) 
      1. Mustafa Bensan

        Hi Alfons,

        I suspect what Mike is referring to here by the 200K limit is related to SDK component custom properties rather than the data result set itself.  My understanding from Mike is that a single SDK component property cannot exceed a length of 200K (although the data result set itself may) and I guess the row iteration data is being returned via a custom property, hence the restriction.

        Regards,

        Mustafa.

        (0) 
        1. Alfons Gonzalez Comas

          Hi Mustafa,

          I see…..Definitely we are on dead end. I will explain you our current situation.

          We are developing a DS application where the iterator component is used in combination with the custom data source component (another Mike’s brilliant contribution) to complete a merging of 2 UNX data sources

          Biggest of 2 data sources involved on merge may frequently retrieve up to 20.000 rows (2 dimensions/1 fact by row = 20.000 cells). This amount of data may be comfortably managed on DS data sources (it is still far away of 50.000 rows limit) but from my rough estimations will be impossible that fits into the 200 KB limit established by the SDK component limit.

          Do you think that could take sense promote an entry on SAP Idea site to allow SDK Component property to exceeds this value?

          Thx

          (0) 
          1. Franck Blais

            Hi Alfons,

            How many characteristics are you reading from your datasource ?

            If not much, you could probably use getData with a loop on the members. It’s not the best solution but it could help you. Thoughts ?

            As proposed, It could be quite useful to be able to read the data without the measures. getData (with its good and bad) could be used afterwards to access those measures.

            (0) 
          2. Mustafa Bensan

            Hi Alfons,

            There’s certainly no harm in raising an idea to request this, although I think a property size limit exceeding 200K may be considered an exception case.  Just to clarify, as I understand it there is a difference between the limit for a data-bound result set property vs a custom property.  The data-bound result set property limit is configurable.  It used to be 10,000 CELLS but can now be set to virtually no limit, as I understand it.  However, separate to this, there is a 200K non-configurable limit on regular custom properties.  So, I believe the issue in this case is not that we are exceeding the data-bound property limit of the data source but since an array of rows is being returned, presumably via a regular custom property, this is where we hit the limit.

            In any case, if your scenario is related to a custom D3 chart, I’m not sure how you plan to apply the Data Iterator to this.  Doesn’t your custom chart connect directly to a data source, in which case you would perform any necessary data manipulation within the chart component itself?

            Regards,

            Mustafa.

            (0) 
          3. Mike Howles Post author

            Hi Alfons,

            Please try the newest version, I’ve employed compression to get about 200% compression ratio, and you can optionally drop formatted values for even more space savings.  I’ve also increased the cell limit from 10k to 1 million (however you’d probably hit the property limit well before that, anyway).

            Let me know if you see better results.

            (0) 
            1. Alfons Gonzalez Comas

              Hi Mike,

              Thanks for your update. We have been checking your latest release. Effectively your latest changes (improving data compression) seems that allows to initialize the data iterator on scenarios with large volume of data (our tests with about 20.000 rows). Therefore the previous Message: Form too large:  error does not longer appear.

              On the other hand a new issue seems to appear now on the iteration phase.When we began to iterate over the iterator (using the for each clause) following error appears after around 2650 iterations (I suspect that the number will depend of the amount of info contained on each row).

              Do you think this issue may be fixed?

              Note: We have also noticed that now the iterator events are called only one time when datasources load in script property is set to true.

              —————————————————–

              !ENTRY com.sap.ip.bi.zen 2 0 2016-02-29 15:35:59.037

              !MESSAGE Error during script processing. Contact the Application Designer to resolve the issue

              !ENTRY com.sap.ip.bi.base.application 4 0 2016-02-29 15:35:59.037

              !MESSAGE Error during script processing: “onDataChange” “com.sap.ip.bi.zen.rt.framework.jsengine.JsEngineTimeoutException: com.sap.ip.bi.zen.rt.framework.jsengine.rhino.RhinoJsEngineError

                at com.sap.ip.bi.zen.rt.framework.jsengine.rhino.RhinoJsEngine.doRunScript(RhinoJsEngine.java:83)

                at com.sap.ip.bi.zen.rt.framework.jsengine.JsEngine.runScript(JsEngine.java:32)

                at com.sap.ip.bi.zen.rt.framework.jsengine.rhino.RhinoScriptInterpreterBialService.interprete(RhinoScriptInterpreterBialService.java:188)

                at com.sap.ip.bi.base.command.impl.Command.interprete(Command.java:191)

                at com.sap.ip.bi.webapplications.runtime.impl.page.Page.processCommandSequence(Page.java:4839)

                at com.sap.ip.bi.webapplications.runtime.impl.page.Page.doProcessRequest(Page.java:2580)

                at com.sap.ip.bi.webapplications.runtime.impl.page.Page._processRequest(Page.java:851)

                at com.sap.ip.bi.webapplications.runtime.impl.page.Page.processRequest(Page.java:5255)

                at com.sap.ip.bi.webapplications.runtime.impl.page.Page.processRequest(Page.java:5248)

                at com.sap.ip.bi.webapplications.runtime.impl.controller.Controller.doProcessRequest(Controller.java:1226)

                at com.sap.ip.bi.webapplications.runtime.impl.controller.Controller._processRequest(Controller.java:1082)

                at com.sap.ip.bi.webapplications.runtime.impl.controller.Controller.processRequest(Controller.java:1048)

                at com.sap.ip.bi.webapplications.runtime.impl.controller.Controller.processRequest(Controller.java:1)

                at com.sap.ip.bi.server.runtime.sevice.impl.BIRuntimeServerService._handleRequest(BIRuntimeServerService.java:822)

                at com.sap.ip.bi.server.runtime.sevice.impl.BIRuntimeServerService.handleRequest(BIRuntimeServerService.java:1205)

                at com.sap.ip.bi.server.execution.engine.runtime.LocalBIExecutionService.executeRequest(LocalBIExecutionService.java:34)

                at com.sap.ip.bi.zen.rt.client.handler.designer.LocalExecutionAdapter.executeRequest(LocalExecutionAdapter.java:39)

                at com.sap.ip.bi.zen.rt.client.handler.RuntimeRequestHandler.handleRequest(RuntimeRequestHandler.java:28)

              (0) 
              1. Mike Howles Post author

                Re this error:

                JsEngineTimeoutException

                I should at this time have already known that you would find the next (Design Studio imposed) limitation 😉 — This is another one I won’t be able to help you overcome.  From what I can tell, any given snippet of script has some predetermined amount of time to execute before some sort of timeout governor kicks in and kills it, presumably so that no single piece of BIAL/ZTL can take down an entire server process/thread.  I think again in this regard you are finding the boundaries of what I can do for you, however I encourage you to keep finding them 😉

                (0) 
                1. Alfons Gonzalez Comas

                  Hi Mike,

                  I am facing again an issue with our friendly error

                  com.sap.ip.bi.zen.rt.framework.jsengine.JsEngineTimeoutException

                  in a different scenario using DataIterator. This time I need only to iterate across 10 records (!!), but each iteration includes additional calculations based on row data content, so complete loop takkes more than 10 seconds.

                  Unfortunately when engine counts 10seconds above error appears…..

                  Some doubts:

                  1) Does exist anyway to change this 10 seconds time limit? (I assume that not)

                  2) If instead of using your data iterator component I loop across the dataset by using a multiple calls to getmember/getValue and script execution time exceeds 10seconds error will appear anyway. It isn’t? (error does not rely on component used, it is only a script execution time limit that SAP establish to avoid “forever” running scripts

                  Thanks

                  (0) 
        2. Mike Howles Post author

          Mustafa is right – The limit I speak of that you are hitting, isn’t a datasource volume limit, rather a property update limit.  Essentially, because BIAL/ZTL methods do not have direct access to data values of their own component at the script layer (a HUGE gap, in my opinion), I am “looping back” client-side and just passing the value back to the script layer as a string, and then re-assembling it there.  It’s definitely a workaround for this gap, but there is no other way I have found.  And as we’ve all seen, getData techniques are lacking when you basically just want to loop over rows, etc…

          Let’s talk about where the significant “spend” of the 200KB “budget” comes in:

          If you have 20k cells, that’ll be 20k tuples.  Here’s an example of the one tuple for two dimensions:

          [0,44]

          Depending on indece lengths, this one tuple will “cost me” around 6 characters of the 200KB “budget”.  Here’s a tuple example with 4 dimensions:

          [0,29,5,1]

          In this example, 6 (Edit 10, I cannot count today!) characters to express one cell.

          The second significant part the “spends” characters is the metadata for each dimension member

          {“key”:”20020116″,”text”:”1/16/2002″}

          That’s 37 bytes spent.  So here you can see depending on the cardinality (unique members) of your dimensions, this will add up.

          And then finally, the last part that spends an amount, is the data values itself:

          Unformatted:

          10000

          5 bytes

          Formatted:

          10,000 USD

          10 bytes

          So here is maybe a piece that could save you some excess.  I could drop also formatted values to save you some space…

          (0) 
            1. Mike Howles Post author

              Well yeah that’s what I mean, I can totally drop the whole formattedData array of the JSON string.  This accounted for 1,892 bytes of 12,726 bytes in my sample dataset.

              There’s also an unused (for me, when flattening) axis_rows and axis_columns section that shaves off another 2,847 bytes.

              These things would I think optimize it the most.  I think at this point, if someone is still approaching 200K, it’s time to write their own extension, or reconsider the data volume, unfortunately.

              (0) 
          1. Mike Howles Post author

            Update, it’s actually even a little worse, the payload is urlencoded which will add to the bloat.  I’ll see what compression tricks I can do.

            /wp-content/uploads/2016/02/encoded_896088.png

            (0) 
  7. Vijay Balagopala

    Hi Mike,

           I’ve implemented your Data Iterator Component and assigned a BW Query to it. However, there seems to be a problem as the application is going into an infinite loop and I have no control on it. It’s stuck on the page as my picture suggests. Can you help me understand why it would be doing so?

    Data Iterator Error.PNG

    (0) 
      1. Vijay Balagopala

        Mike,

                I figured out the issue. Some of the pre-requisite objects weren’t installed. A re-install fixed the issue. However, this created a new problem. We were able to design a dashboard using the components, but I’m not able to install the same on the platform. Anything I’m missing before the installation?

        (0) 
        1. Karol Kalisz

          for the platform, assure you install all bundles – also the one called shared. If you let the shared uninstalled, some code required by  other bundles is missing

          (0) 
  8. Vijay Balagopala

    Hi Mike,

             I see you are using a button component to trigger all the activity. I tried using the scripting for a table and data iterator on the background processing event and it gives me an error. Can you help me understand any precursor steps that need to be done for the data iterator if I need this to be automated? My idea of using the script is to have the table ready on the dashboard startup without any manual intervention.

    Thanks & Regards,

    Vijay

    (0) 
    1. Karol Kalisz

      Hi Vijay,

      data iterator has own event, this must be used for triggering any actions – instead of background processing. check the event “On Data Change”. Reason is, data iterator needs first the data and on startup data is not yet available.

      Karol

      (0) 
  9. Patrice Mathieu

    DATAITERATOR it’s a very good component BUT when I try to hide or show a PANEL or a KPITILE on my application depending data retreive by DATAITERATOR on “ON DATA CHANGE” in the DATAITERATOR, the PANEL or KPITILE never change.

    If I use a BUTTON with the same coding in my layout and I push on it, it’s work but never from the DATAITERATOR

    Example of coding : PANEL_1.setvisible(true);

    Have you an idea ? Thanks

    (0) 
      1. Patrice Mathieu

        Thanks but it’s not necessary. I check my coding and I found a small error.

        When if a value in the KITILE with deltachart is empty because no data, I have an error. I correct this coding and check if the value is never empty and now it’s work fine

        Thanks very much for your help

        (0) 
  10. Lawrence Chan

    Hi Mike,

    Does Data iterator support time measures?  Currently they are outputted as NULL.

    As a simple example, I have a Bex query returning 5 columns.

    – 2 dimensions and 3 measure (2 as time measures) from Bex query.

    ScreenHunter_41 Apr. 21 17.36.jpg

    However, in data iterator, time dimension are outputted ok but when time is a key figure/measure, they appears as NULL values in data iterator.

         ScreenHunter_42 Apr. 21 17.38.jpg

    I have tried both row.getMeasures() and getFormattedMeasures(), but they both did not work.

    Is there any way to show the time measure? Am I missing something?

    Thanks for your good work! 

    Regards,

    Lawrence

    FYI: Here is my simple codes inside Data iterator

    ScreenHunter_43 Apr. 21 17.45.jpg

    (0) 
  11. Vijay Balagopala

    Hi Mike,

              Does the Data Iterator support attributes of a characteristic? I have Region and Area attributes for a Plant but the Data Iterator seems to be bringing only the Plant Name. Can you help me on how I can retrieve these attribute values

    Thanks & Regards,

    Vijay

    (0) 
    1. Mike Howles Post author

      It is available as a Technical Component, which means you will not see in the Component List panel, but rather by right-clicking Technical Components in your Outline.

      (0) 
      1. Xavier Polo

        I can’t see it as a Technical Component, may be the problem is that components were updated from early versions (DS and SCN Components).

        I will try to remove it and install full again.

        thx

        (0) 
  12. Kirill Bondarenko

    hi Mike,

    Data Iterator is a very nice one. thanks for that!

    may you please clarify does Data Iterator support attributes for Data Sources based on BW queries? Are there any methods like getAttributeMemberText ?

    Thanks,

    Kirill

    (0) 
  13. Ashraf Sharif

    Hi,

    We made an update to DS 1.6 SP2 and after that the Data iterator stopped working.

    all the application enter to infinite loop.

    Please help.

    Thanks,

    Ashraf

    (0) 
  14. Akshay Bhandari

    Hello Mike,

    We tried using the Data Iterator component and we found some issues with the same. Can you please help us out . Details are as below.

    1. Does the Dataiterator component works “On-startup ” event?

        We used it but it is throwing error

    On Starup.jpg

    2. We tried creating a report using the Data iterator component along with a filter component. On Execution .

    DataIterator - On startup.jpg

    – Then on first selection of value in Filter component the data in the datasource doesn’t filter out.

    DataIterator - Selection of 1st value in Filter.jpg

    – On second selection of the filter value the data displayed is for the previous selection value in the Filter.

    DataIterator - On 2nd filter selection.jpg

    Kindly help us out with your inputs .

    Many Thanks

    Akshay

    (0) 
    1. Dilip B

      Hi Akshay,

      I’m getting the same error too and I’m on version 1.6 SP 3. Is this resolved for you? If yes, please guide me.

      Thanks!
      -Dilip

       

      (0) 
  15. temer kuz

    Hi Mike,

    When I try to use dataiterator (in onclick event of a button) I got the following error. I have a Bex query as a datasource. We are on DS 1.6 sp1.

    Message: org.mozilla.javascript.EcmaError: SyntaxError: Empty JSON string (flatten#12)

    The simple code I used onclick event of a button.

    var dim = DATAITERATOR_1.getDimensions(); dim.forEach(function(dimension, index) {   LISTBOX_1.addItem(dimension.key, dimension.text); });

    (0) 
  16. James Heltmach

    Hi question.  I’m interested in using the data iterator but don’t see it in the technical components section.  I’m using D/S 1.6.1 and have JDK and Eclipse installed on my machine.  I have the DS 1.6 SP02 SDK samples downloaded from the SAP site.  When I run Design Studio from the Eclipse it opens DS and shows all the SDK components.  I then look in “Technical Components and nothing is there.  I’ve never worked with the SDK components.

    thanks

    SDKScreenshot.png

    (0) 
  17. Jonas Duclos

    Hello all,

    I see i’m maybe not the only one facing issue with Data Iterator component using SP02.

    Someone can give us a feedback concerning using this item on BI Platform 1.6 SP02 ?

    On my side, i have an issue with “item could not be generated”. No issue on local Mode.

    Someone can help us with Data Iterator issue ?

    Thank !

    Best Regards,

    Jonas.

    (0) 
  18. Mustafa Bensan

    Hey Mike,

     

    I have just noticed that the getRows() method returns the data in ascending alphabetical order by dimension member, rather than retaining the sort order of the data source Initial View.  Is this by design?

     

    Thanks,

     

    Mustafa.

    (0) 
  19. Henry Taylor

    I think I have the same problems as some others.  We are on 1.6 SP2.  We are also getting the “Message: org.mozilla.javascript.EcmaError: SyntaxError: Empty JSON string (flatten#12)” and the “item could not be generated” error.

     

    I tried reinstalling the Utils package to my server, but now the application won’t event load.  It just spins the loading symbol.

     

    Has any fix been found for these errors?

     

    Thanks,

     

    Henry

    (1) 
    1. Dilip B

      I’m getting the same error and on same version 1.6 SP 3. Is this resolved for you? If yes, please guide me.

      Thanks!
      -Dilip

      (1) 
      1. Justin Boss

        Release 1.6 SP4 Patch 1 (Version: 16.4.1)

         

        I’m having the same issue. But the only code I have in the script is:

        var flatdata = DATAITERATOR_1.getRows(0,100);

        So it would appear that it is a bug, because I’m not even able to initialize the variable.

        (0) 
        1. Knoa Support

          From what I’ve seen the code doesn’t work if it’s put inside the application’s onStartup() event.

          If  DATAITERATOR_1.getRows() is called at a later time, e.g. inside of an onClick() event of a button, or inside the SDK’s Timer onTimer() event, this it works for me.

          I think that was the intention of this comment.

          I hope this was helpful.

          (0) 
          1. Justin Boss

            Yes, it looks like the data source is not ready to be queried at startup. What I did to get around this was in the onStartup() I added a call to a timer that waits .5 sec then runs the DATAITERATOR_1.getRows(). It worked for me now.

            Thanks for your help.

             

            (0) 
  20. Swapna Reddy

    Hi  Mike,

    Can you please suggest on how to get same back ground color by grouping dimension data as shown in image below.

    Let’s say I have 2 Dimensions. and Dimension 2 has multiple rows against each data row of Dimension 1. How to group the values based on Dimension 1 and set their back ground color.

    Regards,

    Reddy

    (0) 
  21. Levent Cuhaci

    Hello all,

    is Data Iterator component supported on mobile platforms (iOS)? We’ve created a dashboard with a Data Iterator in it and it works perfectly fine on laptop/PC. But when we try to open it on an iPad tablet, we receive a runtime scripting error and the visualization component (actually a KPI-Tile) which is used to show a calculated data from DataIterator does not show any value.

    Thanks in advance,

    Levent Cuhaci

    (0) 
    1. Mike Howles Post author

      Can you provide the error?  I don’t remember if I ever tried this on mobile Safari or in BusinessObjects Mobile to be honest.

      (0) 
  22. Giulia Sogaro

    Hi Mike,

    Data Iterator and Rapidprototype are usefull component. I use them to create a table with conditional formatting. I would like to select a table row for filtering another data source, is it possible?

    Regards,

    Giulia

     

    (0) 

Leave a Reply