Discussions
Categories
Groups
Community Home
Categories
INTERNAL ENABLEMENT
POPULAR
THRUST SERVICES & TOOLS
CLOUD EDITIONS
Quick Links
MY LINKS
HELPFUL TIPS
Back to website
Home
Intelligence (Analytics)
Broken Javascript when adding a dataset field with an importPackage statement
Charles Paluda
<p>Ok, I'm totally confused by this one. I have a text box on the layout section that has some javascript in the onRender section to reformat a report parameter that is passed in as an integer type. I also assigned it to a report variable with the expression params["parameter_name"].value.</p><p> </p><p>The code in the textbox that uses the report variable is blockId = vars["rv_ca_blockId"].toString();</p><p> </p><p>This was working just fine until I added a couple of fields from two different datasets to the footer on the Master Page. Basically I have two datasets getting money information from a transaction table. All transactions processed by a specific employee for a day get a unique number. One dataset gets any rows for that day's unique number that are of payment type "check" and that dataset is used to list out each check amount & and ID number. The other dataset goes back in and for the same unique number gets any rows that are of type "cash" and just adds it up. </p><p> </p><p>In the footer I need to be able to add the check total and the cash total together. I use computed fields in the datasets to first get the totals and then the as per some searches I found here on how to add things from two different datasets I use the following script for example in the onCreate section to assign the values to a global variable </p><p> </p><div><pre class="_prettyXprint">importPackage(Packages.java.lang);if (this.getValue() == null){this.setDisplayValue(parseFloat("0.00"));}var mydbl = new Double(this.getValue());reportContext.setGlobalVariable("totalCash", mydbl);</pre><p>I saw a lot of references to using setPersistentGlobalVariable instead but that never worked for some reason. Anyway, something about having to use the "importPackage" statement is breaking the ability to use toString() in the other script. I get the error error instantiating (): class java.lang.Number is interface or abstract when BIRT tries to run that script with the blockId = vars["rv_ca_blockId"].toString(); statement in it. If I leave off toString() then I get errors about Int vs. string of course. Anyone have any ideas on this? I'm completely lost.</p></div>
Find more posts tagged with
Comments
micajblock
<p>Can you build a sample report using dummy data? What version of BIRT are you using?</p>
Charles Paluda
<p>Ok here is a dummy version. I used text boxes for where there would have normally been the computed fields in the master page footer from the datasets and then because I couldn't get the text field values in onCreate I just hard coded some values into the script instead of using this.getValue(). It still acts the same as the live report though so you should be able to look at all the scripts. As I said, commenting out the importPackage statements fixes the problem for the script on the text field on the layout page but breaks the scripts on the Master Page because then it doesn't know what Double is.</p><p> </p><p>Oh, as near as I can tell if I'm looking in the right spot, using BIRT 4.2.1 with Eclipse 4.2.1. </p>
micajblock
<p>I just want to make sure I have the requirements, right. Do you want the totals on the bottom pf every page or just the last one? If the former is it a running total?</p><p> </p><p>P.S. Why do you need 2 different data sets? I have a Devshare on how do perform union so you can have it all in one data set (BTW, this is an OOTB feature of Actuate BIRT).</p><p> </p><p><a data-ipb='nomediaparse' href='
http://developer.actuate.com/community/forum/index.php?/files/file/993-simple-union-dataset/'>http://developer.actuate.com/community/forum/index.php?/files/file/993-simple-union-dataset/</a></p><p> </p><p>P.P.S
I think you way over complicating things as you should not need to convert data types or format in code. Can you provide all the requirements you have? Why are putting the parameter in a report variable?</p>
Charles Paluda
<p>The report is only ever one page long. The max records for a transaction is 99 split up over 3 columns using that Newspaper Layout workaround. I used the footer to force the totals to be at the bottom of the page. I'm sure there might be another way to do it but we've only started using BIRT in the last few months so we're still doing a lot of learning of how it works.</p><p> </p><p>So, the two datasets that are picking up cash and checks, both the cash and the checks all come from the same table. The amount is in a column called "cashiered_amount" and there is a "media_type" of cash or check. I was using one dataset to get all the check type amounts for display on the report. Cash does not need to be listed out line by line, only as a sub-total so I was using a 2nd query that gets all the cash. Here's an example of the cash query. In this cash the check on is the same except looking for checks.</p><p> </p><div><pre class="_prettyXprint">select cashiered_amountfrom ca_paymentswhere block_id = ?and GetCMNCodeCode( media_type_ID ) = 'CASH'</pre><p>Media_type_ID above is a numeric code and it's looked up in a table by the function to get the actual media_type name associated with it. Looking back I could probably pick all the cashiered amounts together and use some kind of filtering in BIRT to split them up, but I had already done a similar sub-total/total block on another report and figured it would save time to copy it to the new one (until it broke the other script). The other report however used very different queries for checks & cash due to some extra things that needed to be picked up so there was definitely no way to get both all in one shot on the other report.</p><p> </p><p> A lot of these reports we're doing were done it Oracle reports 15 years ago and relied on stored procedures to gather the data for them and dump it into a generic table where they could get the processed data from. The new version of the software we're working on does not use a generic table like that. In some cases we are moving a stored procedure over and creating tables for a specific report, but where we can get all the data with a few queries instead with BIRT that's what we're trying to do.</p><p> </p><p>Also I guess I should have been more clear about what the large piece of script was in that text field on the layout section. That code was to take the incoming numeric parameter and format it into a barcode. In order to work it needs to be turned into a string so that it can have each character evaluated and a check digit calculated and added to it along with a start/stop character. The barcode info is not already in a column in the database. Well, it's not in there formatted with the start/stop character and check digit because it's that block_id number from the above query which is a FK to another table.</p></div>
Charles Paluda
<p>Hmmm I looked at that link on doing a union. Guess I'm going to have to spend some time with that. It didn't make much sense. Maybe because I didn't see anything that looked like an actual query string in it.</p>
micajblock
<p>As I said I think you are making this way more complicated then it needs to be. You can have one query. Hide the rows for cash In the Sub-total which you can just put at the end you can filter the aggregations by the media type. As to the bar code all you need is to create a data item of type of string with the expression (BIRT will convert to string automatically) StartCharacter + [color=rgb(40,40,40);font-family:'Source Sans Pro', sans-serif;]params["parameter_name"].value + EndCharacter[/color]</p>
Charles Paluda
<blockquote class="ipsBlockquote" data-author="mblock" data-cid="128047" data-time="1400175123"><div><p>As I said I think you are making this way more complicated then it needs to be. You can have one query. Hide the rows for cash In the Sub-total which you can just put at the end you can filter the aggregations by the media type. As to the bar code all you need is to create a data item of type of string with the expression (BIRT will convert to string automatically) StartCharacter + [color=rgb(40,40,40);font-family:'Source Sans Pro', sans-serif;]params["parameter_name"].value + EndCharacter[/color]</p></div></blockquote><p> </p><p>That actually won't work for the barcode. It needs to add up values from a MOD operation on each character's ASCII code and then run another calculation to figure out what ASCII character to add in for a check digit. I.e. StartCharacter + params["param_name"].value + CheckDigit + EndCharacter. BIRT's Javascript String functions won't work unless the parameter value starts out as a string. I.e. params["param_name"].toString() in our case since the parameter is actually set up as an integer coming into the report. Converting it to a string like that worked until the subtotal scripts got added in. I think I managed to fix that once somehow but then I got errors about "fromCharCode" not being a method in String or something like that which further breaks things.</p><p> </p><p>We ended up moving over a barcode function from the old database and are just calling that now to get the barcode by passing the BIRT parameter to it during a query for some header data. Since we did that we no longer need the script that was broken by the subtotal scripts. I guess I'm still curious on why they wouldn't work with both sets of scripts in the report though. Something with that importPackage in the subtotal scripts totally broke the barcode generation one and I still don't understand why.</p>
micajblock
<p>I do not know why your code does not work. The report you posted works for me fine.</p>
Charles Paluda
<p>In case you didn't see it, here is the script that I was running for the barcode conversion. </p><pre class="_prettyXprint">startStopChar = "*";currentSum = 0;blockId = vars["rv_ca_blockId"].toString();blockIdLength = BirtStr.charLength(blockId);currentPosition = 0;checkValue = "";stringToNum = 0;modValue = 0;while (currentPosition < blockIdLength){ stringToNum = blockId.charCodeAt(currentPosition) - 48; currentSum += stringToNum; currentPosition++;}modValue = BirtMath.mod(currentSum, 43);if (modValue >= 0 && modValue <= 9){ checkValue = String.fromCharCode((modValue + 48));}else if (modValue >= 10 && modValue <= 35){ checkValue = String.fromCharCode((modValue + 55));}else if (modValue = 36){ checkValue = "-";}else if (modValue = 37){ checkValue = ".";}else if (modValue = 38){ checkValue = "&";}else if (modValue = 39){ checkValue = "$";}else if (modValue = 40){ checkValue = "/";}else if (modValue = 41){ checkValue = "+";}else if (modValue = 42){ checkValue = "%";}else{ checkValue = null;} this.text = startStopChar + blockId + checkValue + startStopChar;</pre>
micajblock
<p>I see it and it runs fine for me.</p>
Charles Paluda
<blockquote class="ipsBlockquote" data-author="mblock" data-cid="128049" data-time="1400178327"><div><p>I do not know why your code does not work. The report you posted works for me fine.</p></div></blockquote><p> </p><p>You didn't get <strong>[color=#ff0000;][font="'Source Sans Pro', sans-serif;"]error instantiating (): class java.lang.Number is interface or abstract [/color][/font]</strong> when you ran it? Wow, that's really weird. I get that error when running it in the Preview tab in Eclipse. If I run it as a PDF for example it "runs" but there is no barcode at the top of the report.</p>
micajblock
<p>Nope, no error. Try using an external browser. That is what I use by default as that is the way most users will view reports. To change your default go to menu item Windows/Preferences/Report Design/Preview. The click on the toolbar item 'View Report'</p>
Charles Paluda
<blockquote class="ipsBlockquote" data-author="mblock" data-cid="128053" data-time="1400179368"><div><p>Nope, no error. Try using an external browser. That is what I use by default as that is the way most users will view reports. To change your default go to menu item Windows/Preferences/Report Design/Preview. The click on the toolbar item 'View Report'</p></div></blockquote><p> </p><p>Oh, that is very odd, it actually did work in the web viewer. That is really strange. Unfortunately it wouldn't have helped, our application will actually be generating reports in PDF format. I just want to double check though, what version of BIRT are you checking with? Also, is it the standard version or the Professional one? </p><p> </p><p>At first until I tried that web format I thought maybe it was because we were on a much older version. I realized yesterday we were using 4.2.1 which is from Sept. 2012 and the latest is Feb. 2014. I was starting to think I was running into a bug in Eclipse or that version of BIRT. </p><p> </p><p>Can you try using the internal preview tab and see if you get an error, or run it as a PDF and see if the barcode no longer shows up? At least I would know it's not a problem specific to my machine/environment in that case.</p>
micajblock
<p>Interesting, when I moved your code from the onRender to onCreate I get the error. Can you explain what the logic is to create check value?</p>
micajblock
<p>OK, I fixed it so it works in PDF and Viewer. Look at the code I am using in the master page. I had to change the name of the Bar code font (as I downloaded a free version), so change it back to your font. I also moved the code to the onCreate as this is the more appropriate place for your code.</p><p>It does have something to do with the import but I am not sure why.</p><p> </p><p>P.S. Maybe a review of your reports with someone who has experience with BIRT design will help you along the way.</p>
Charles Paluda
<p>Thanks I will take a look. Hmm, I guess I thought onRender was the correct place for something like that. Unfortunately we have nobody at my organization with BIRT experience. It's myself and one other person and we're learning it as we go. Our lead developers evaluated a couple reporting tools.....Crystal and BIRT...and settled on BIRT because it could do some stuff with printers and trays that Crystal couldn't and we needed to have. Our main application is being written in Groovy/Grails and uses a BIRT plugin for Grails to actually run the reports. Looks like I need to take a look though and get a better grasp of what is done where as far as onRender vs. onCreate.</p><p> </p><p>So I actually just looked at that file you uploaded. Wow I wish I had known I could have done the subtotal/total stuff with those much simpler statements. It was really hard to find anything on how to do that in the first place. The code I was using was from the Eclipse forums <a data-ipb='nomediaparse' href='
http://www.eclipse.org/forums/index.php/mv/msg/369684/905588/#msg_905588'>from
a 2009 post</a>. I had first tried Joint Datatset in BIRT but it was soooooooo slow. Just in the UI for creating it, trying to give the dataset a name it was literally type a letter and wait 20-30 seconds before I could type again. Anyway, those simpler statements you changed it to would have prevented my problem for sure with the error I was getting. </p>
micajblock
<p>You might want to check out this video on BIRT events. </p><p> </p><p>
https://www.youtube.com/watch?v=FQ9VjByPNWM</p><p> </p><p>P.S.
There is a whole BIRT YouTube channel. </p>
Charles Paluda
<p>Thanks, I'll be sure to pass this on to the rest of our developers who are working with BIRT as well.</p><p> </p><p>I'm going to go back to the couple of reports I have done now with that subtotal block and put the simpler statements in for assigning the global variables and adding them up. I've also added back in the null check so I can display $0.00 if there are no checks or no cash in a set of results. Right now there are many times no cash entries, but we're planning to move the main system to electronic check depositing and the check entry on these reports will then end up always being $0.00 (the reports are for depositing/handling of physical checks). Otherwise it just leaves a blank space that doesn't look good. (to me at least) I actually had to have the null check before in the original scripts to avoid a null pointer exception.</p><pre class="_prettyXprint _lang-js">reportContext.setGlobalVariable("totalCash", this.getValue());if (this.getValue() == null){ this.setDisplayValue("$0.00");}</pre>
Charles Paluda
<p>Actually that didn't quite work. The total script BirtMath.add(reportContext.getGlobalVariable("totalCash"),reportContext.getGlobalVariable("totalChecks")); was not returning a total when cash was empty on one of the reports. I had originally used sum(column) in the sql on that report but found I still had to do a computed column with SUM in BIRT to get the setGlobalVariable script to work. The other report that it did work on I did not use sum(column) in the query but of course still used the computed column in BIRT.</p><p> </p><p>Anyway, switching the script to this works for both.</p><pre class="_prettyXprint _lang-js">if (this.getValue() == null){ this.setDisplayValue(parseFloat(0.00));}reportContext.setGlobalVariable("totalCash", this.getValue());</pre>
micajblock
<p>Once again you are over complicating things. See attached design. Adding a 0 to null will do the trick.</p>
Charles Paluda
<blockquote class="ipsBlockquote" data-author="mblock" data-cid="128062" data-time="1400191050"><div><p>Once again you are over complicating things. See attached design. Adding a 0 to null will do the trick.</p></div></blockquote><p> </p><p>I think I'm missing something? I don't see anything in there adding 0 to null anywhere? </p><p> </p><p> </p><p>EDIT: Nevermind I found it. Thanks!</p>
micajblock
<p>Look at the exprssion for NullFloat</p><pre class="_prettyXprint">dataSetRow["NullFloat"] + 0</pre><p>Take away the + 0 and see what happens.</p>
Charles Paluda
<p>Thanks again! Hopefully I'm on my way to doing things right/better now finally. I really appreciate the extra time you took walking me through these last couple things
</p>
Charles Paluda
<p>One more question if you don't mind. I've had a couple of reports where I needed to put parameter that was passed in to use in the SQL query on the report itself for display. Is there any reason not to use the report parameter directly? I wasn't sure if the parameter should be assigned to a page or report variable in the Variables section of the Data Explorer and use the variable instead of the Report Parameter for that.</p>
micajblock
<blockquote class="ipsBlockquote" data-author="Charles Paluda" data-cid="128066" data-time="1400192879"><div><p>One more question if you don't mind. I've had a couple of reports where I needed to put parameter that was passed in to use in the SQL query on the report itself for display. Is there any reason not to use the report parameter directly? I wasn't sure if the parameter should be assigned to a page or report variable in the Variables section of the Data Explorer and use the variable instead of the Report Parameter for that.</p></div></blockquote><p>Nope, using params["parmaeterName"].value is always the easiest and the best.</p>