Jump to content
We've recently updated our Privacy Statement, available here ×

Setting styles dynamically, here: background color


rainer_klute

Recommended Posts

I'd like to set the background color dynamically depending on a field value. Unfortunately this is neither possible with

<reportElement backcolor="$F{color}" ... />

nor with

<reportElement backcolor="<![CDATA[$F{color}]]>" ... />

Using a scriptlet I had some success setting the background color in the afterDetailEval() method: The scriptlet reads the field value, locates the proper band element and sets its background color. As a result, the report element is rendered in that color.

However, this works for the first datasource row only. When processing subsequent rows, JasperReports disregards any further color values and stays with what the scriptlet set for the first line. Consequently, all repetitions of the report element are rendered with the background color that has been set first. And yes, I checked that my scriptlet indeed set different color values.

Any ideas?

Link to comment
Share on other sites

  • Replies 5
  • Created
  • Last Reply

Top Posters In This Topic

  • 2 years later...

It is possible to achieve something like this by modifying the jrPrint object after the report has been filled.  I made the expressions for the text fields that needed different background return ##RRGGBB#Actual Text Wanted i.e. put # followed by the desired background colour followed by # and then the actual text to be shown.  Then after filling the report to produce a jrPrint object I then modify the jrPrint.  You can't set the background colour on a jrTemplatePrintText element directly but instead need to create a new template with the desired background colour (using Apache commons lang SerializationUtils.clone( oldTemplate) to get the new one.  You can then call setBackcolor on this new template (no need to use reflection to call the method it isn't private) and call setTemplate on the original JRPrintText element to set the new template.  Also, take the prefix off the text (call getFullText to get the text) and then setText to put it back.  You need to have net.sf.jasperreports.print.keep.full.text set to true on the report (or at least the report elements you'll be modifying) or the ##ABCDEF# at the start might mean that your text gets truncatyed when it shouldn't be.

 

The following code works, but you'll need to take the logging out for production (and stop it all being static!!):

 

 
public class ManipulateJasperPrint 
{
    public static JRBaseStyle changeStyleName( JRBaseStyle base, String newName, Color newBackColor )
    {
        try 
        {
            JRBaseStyle newS = (JRBaseStyle) SerializationUtils.clone(base);
            MyLogger.log( "Cloned style " + base.getName());
            
            Field field = newS.getClass().getDeclaredField( "name" );
            field.setAccessible(true);
            field.set( newS, newName );
            MyLogger.log( "Clones name is now " + newS.getName() );
            
            field = newS.getClass().getDeclaredField( "backcolor" );
            field.setAccessible(true);
            field.set( newS, newBackColor);
            MyLogger.log( "Cloned style's backcolor is " + newS.getBackcolor() );
            
            return newS;
        } 
        catch (NoSuchFieldException ex) 
        {
            MyLogger.log( "Couldn't find field name" + ex );
        } 
        catch (SecurityException ex) 
        {
            MyLogger.log( "Couldn't access name field " + ex );
        } 
        catch (IllegalArgumentException ex) 
        {
            MyLogger.log( "Bad argument changing field " + ex );
        } 
        catch (IllegalAccessException ex) 
        {
            MyLogger.log( "Couldn't access field " + ex );
        }
        return null;
    }
    
    public static void changeTemplate( JRTemplatePrintElement element, JRStyle style, Color c )
    {
        try
        {
            JRTemplateElement oldTemplate = element.getTemplate();
            MyLogger.log( "Old template is ID=" + oldTemplate.getId() + 
                    " and Key=" + oldTemplate.getKey() );
            JRTemplateElement newT = (JRTemplateElement) SerializationUtils.clone( oldTemplate );
            if( style != null )
            {
                newT.setStyle(style);
                MyLogger.log( "Clone's new style is " + newT.getStyle().getName() );
            }
            if( c != null )
            {
                newT.setBackcolor©;
                MyLogger.log( "Clone's new backcolor is " + newT.getBackcolor() );
            }
            element.setTemplate(newT);
            MyLogger.log( "Set template to " + newT + " and we have " + element.getTemplate() );
        } 
        catch (SecurityException ex) 
        {
            MyLogger.log( "Couldn't access name field " + ex );
        } 
        catch (IllegalArgumentException ex) 
        {
            MyLogger.log( "Bad argument changing field " + ex );
        } 
        
    }
    
   private static String repeat( char c, int n )
   {
       StringBuilder b = new StringBuilder(n);
       while( n-- > 0 )
           b.append©;
       return b.toString();
   }
   private static JRStyle newStyle = null;
   private static int counter = 0;
   
   private static String getText(JRPrintElement inner) 
    {
        if( !( inner instanceof JRPrintText ) )
            return "";
        JRPrintText t = (JRPrintText) inner;
        Color newC = null;
        String oTest = t.getFullText();
        String text = t.getOriginalText();
        int colPos = text.indexOf( "##");
        int pend = -1;
        if( colPos >= 0 )
            pend = text.indexOf("#", 2 );
        if( colPos >= 0 && pend > colPos + 2 )
        {
            MyLogger.log( "Will modify " + text + " : " + oTest );
            String color = text.substring( colPos + 2, pend - colPos );
            Integer c = Integer.parseInt( color, 16);
            MyLogger.log( "Got color int as " + Integer.toHexString© );
            newC = new Color( c );
            MyLogger.log( "Created color " + newC);
            t.setBackcolor(newC); //actually does nothing - we set in template instead
            String newText = text.substring( pend + 1 );
            t.setText( newText );
            Integer trunc = t.getTextTruncateIndex();
            if( trunc != null  )
            {
                MyLogger.log( "Changing truncation was " + trunc + " and new text is " 
                        + newText + " (length=" + newText.length() + ")");
                if( trunc >= newText.length() )
                    trunc = null;
                t.setTextTruncateIndex(trunc);
                MyLogger.log( "trunc now " + trunc + " we get " + t.getTextTruncateIndex() );
            }
        }
/*        JRBaseStyle oldStyle = (JRBaseStyle) t.getStyle();
        
        String styleName = "";
        if( oldStyle != null )
            styleName = oldStyle.getName();
        if( styleName.startsWith("imp") || styleName.startsWith("scor") )
        {
            String newName = styleName+"_" + ++counter;
            Color newColor = Color.PINK;
            newStyle = changeStyleName( oldStyle, newName, newColor);
            t.setStyle(newStyle);
            MyLogger.log( "Have changed style for t to " + t.getStyle().getName() );
        }*/
        if( newC != null )
        {
            if( inner instanceof JRTemplatePrintElement )
            {
                JRTemplatePrintElement template = (JRTemplatePrintElement) inner;
                MyLogger.log( "Trying template clone and change");
                changeTemplate( template, newStyle, newC );
                MyLogger.log( "And after bc=" + inner.getBackcolor() );
            }
            else
                MyLogger.log( "Not a JRTemplatePrintElement");
        }
        return t.getFullText();
    }
 
   private static int getRGB( Color c )
   {
       if( c == null )
           return 0;
       else
           return c.getRGB();
   }
   
   private static String getSimpleText( JRPrintElement el )
   {
       if( !( el instanceof JRPrintText) )
           return "";
       JRPrintText text = (JRPrintText)el;
       StringBuilder b = new StringBuilder(1000);
       b.append( text.getFullText() );
       JRStyle style = text.getStyle();
       if( style != null )
           b.append( " STYLE=").append( style.getName() );
       return b.toString();
   }
   
    private static void dumpElements( List<JRPrintElement> elements, int depth )
    {
        for( JRPrintElement element : elements )
        {
            JROrigin origin = element.getOrigin();
            BandTypeEnum bandT = origin != null ? origin.getBandTypeValue() : null;
            String band = bandT == null ? "" : bandT.getName();
            MyLogger.log( String.format( "%s%-21s BAND=%10s X=%3d Y=%3d BC=%06x OBC=%06x %s", 
                    repeat( ' ', depth+depth),
                    element.getClass().getSimpleName(),
                    band,
                    element.getX(),
                    element.getY(),
                    getRGB(element.getBackcolor()),
                    getRGB(element.getOwnBackcolor()),
                    getSimpleText( element )       
                    )
                );
            if( element instanceof JRPrintFrame )
                dumpElements( ((JRPrintFrame)element).getElements(), depth + 2);
        }
    }
    private static void dumpJR( JasperPrint jr )
    {
        List<JRPrintPage> pages = jr.getPages();
        if( pages == null || pages.isEmpty() )
            return;
        int p = 1;
        for( JRPrintPage page: pages )
        {
            MyLogger.log( "Start PAGE " + p + " >>>>>>>>");
            List<JRPrintElement> elements = page.getElements();
            dumpElements( elements, 1 );
            MyLogger.log( "END PAGE " + p++ + " <<<<<<<");
        }
        MyLogger.log( "END REPORT");
    }
    
    private static void modifyBackColours( List<JRPrintElement> elements )
    {
        for( JRPrintElement element : elements )
        {
            if( element instanceof JRPrintText)
            {
               // MyLogger.log( "Will examine " + ((JRPrintText)element).getFullText() );
 
                getText( element );
            }
            else if( element instanceof JRTemplatePrintFrame )
            {
                JRTemplatePrintFrame frame = (JRTemplatePrintFrame)element;
                modifyBackColours( frame.getElements() );
            }
        }
    }
 
    public static JasperPrint modifyBackgrounds( JasperPrint jr )
    {
        if( jr == null )
            return null;
        MyLogger.log( "About to show original JR");
        dumpJR( jr );
        MyLogger.log( "Now will modify");
        List<JRPrintPage> pages = jr.getPages();
        if( pages == null || pages.isEmpty() )
            return jr;
        
        for( JRPrintPage page: pages )
        {
            List<JRPrintElement> elements = page.getElements();
            
            modifyBackColours( elements );
            //MyLogger.log( "Class of elements is " + elements.getClass().getSimpleName());
        }
        MyLogger.log( "Finished modifications - JR now:");
        dumpJR(jr);
        return jr;
    }
    
}
 

 

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...