Why do I get a separate row in a BIRT report for each custom attribute?
Hello,
I'm using RTC 3.0.1 and BIRT. I've added 4 custom attributes to a work item type. I can retrieve the custom attribute values (STRING_KEY/STRING_VAL) in the BIRT report but for each workitem ID, I get 4 results (rows); one for each custom attribute value.
How can I display the 4 custom attributes for one row only in the BIRT report?
Thanks in advance for your help.
9 answers
Custom attributes are not stored the way that you want to view them. You'd like for each custom attribute to get its own column in a table, but they are stored (as you see) in a generic key-value way since we don't know ahead of time what all the possible attributes could be. I think the simplest solution looks something like this:
1. Create a global javascript array which will contain one object per work item. Do this in the initialize method of the report.
2. In onFetch of your data set, you want logic that does the following:
If this is the first time you've seen this work item (i.e. if myArray[row["WI_ID"]] == null/undefined) then initialize myArray[row["WI_ID"]] to an empty object {}.
Otherwise look up the object at myArray[row["WI_ID"]]
In this array, put a field corresponding to the custom attribute you found. For example, myArray[row["WI_ID"]][row["STRING_KEY"]] = row["STRING_VAL"]; or something like that.
3. Create a scripted data set that reads elements from myArray and produces a row for each one, with first-class columns for each of your (known) custom attributes.
But beware of the performance implications of this - depending on how many work items you are fetching, this could get expensive in terms of memory.
james
Thanks James for your reply.
I would need more help for 1) as I'm not too familiar with reading data source in javascript.
- I've created an array workItems = []; in the initialize event for the report
- I've created a data source script and a data set using that data source. On the "fetch" event of the data set, I need to read the workItems array. Should I do something like that:
<code>if (index < workItems.length) {
row["Col1"] = workItems[index];
index++;
return true;
} else {
return false;
}</code>
Thanks
Yes, that's the basic idea regarding your fetch. If you'd like an example of a report which does this, check out any of our story points-based reports that ship with RTC. For examples, "Story Points.rptdesign" which you can find in the com.ibm.team.examples.reports.common plug-in folder in your RTC client installation. Import that into your workspace and open it with BIRT. You'll see a similar pattern which you can copy.
Thanks James - I almost got it to work.
This is what I have in the onFetch of the dataset for workItems
<code>
if (typeof(workItems) == "undefined") {
return;
}
if (workItems[row["WI_ID"]] == null) {
workItems[row["WI_ID"]] = new Object();
workItems[row["WI_ID"]]["SUMMARY"] = row["SUMMARY"];
.......
} else {
workItems[row["WI_ID"]][row["STRING_KEY"]] = row["STRING_VAL"];
}</code>
My only problem is with reading elements from
workItems to produce a row as you mentioned in 3).
How can I read the items from workItems, I can't use workItems.length to iterate tru the array as the index is the workitem id.
Thanks for your help