JXLS生成报表的常规应用及扩展(下)

阅读更多

在上一篇中了解了JXLS的工作原理后,这次来对上篇结尾的问题进行分析。

因为一个JXLS报表模板中的表达式往往对应一个或者多个JAVA对象数据(实例集合或者实例)比如${stus}和${grade}两个。

所以在接到新需求中,要创建新的report,这样不可避免的要创建新对应的JAVA Bean。那有没有一种方法可以动态的去创建JAVA类呢(所谓动态则是不需要物理存在的java类文件),我们可以配置一些类的属性在文件或数据库中,然后动态的去创建一个类,根据配置设置类的属性,以及设置好属性的值。

后来发现其实CGLIB这个类库(在很多开源框架中使用)已经实现了这些功能(BeanGenerator)。

下面代码是一个简单的封装

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import net.sf.cglib.beans.BeanGenerator;
import net.sf.cglib.beans.BeanMap;
import net.sf.jxls.exception.ParsePropertyException;
import net.sf.jxls.transformer.XLSTransformer;

/**
 * The class which use to generate dynamic bean for jxls display.
 */
public class ReportJXLSGenerateBeanHelper {
    
    /**
     * Generate single DTO Bean.
     * @param properties properties list for a single DTO bean
     * @return DTO bean (Object type)
     */
    public Object generateObject(final Map> properties) {
        BeanGenerator generator = new BeanGenerator();
        Set keySet = properties.keySet();
        for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
            String key = (String) iterator.next();
            generator.addProperty(key, (Class) properties.get(key));
        }
        return generator.create();
    }
  
    /**
     * Getter value.
     * @param obj DTO Object
     * @param property property
     * @return property value
     */
    public Object getValue(final Object obj, final String property) {
        BeanMap beanMap = BeanMap.create(obj);
        return beanMap.get(property);
    }
  
    /**
     * Setter value.
     * @param obj DTO Object
     * @param property property
     * @param rawValue property value
     * @throws Exception 
     */
    public void setValue(final Object obj, final String property, final Object rawValue){
        Object value = rawValue;
        if (value == null) {
        	value = "";
        }
        BeanMap beanMap = BeanMap.create(obj);
        try {
            beanMap.put(property, value);
        } catch (ClassCastException e) {
        	LogServices.app.info("ReportJXLSGenerateBeanHelper.setValue():" + e.getMessage());
        } 
    }
    
    
    /**
     * generate report.
     * @param templateFile report template
     * @param beans 
     * @param outputPath
     * @throws IOException 
     * @throws InvalidFormatException 
     * @throws ParsePropertyException 
     */
    public void exportExcel(final String templateFile, final Map beans, final String outputPath) throws ParsePropertyException, InvalidFormatException, IOException {
        XLSTransformer transformer = new XLSTransformer();
        LogServices.app.debug2("generate report begin" + Calendar.getInstance().getTime().toString());
        transformer.transformXLS(templateFile, beans, outputPath);
        LogServices.app.debug2("generate report end" + Calendar.getInstance().getTime().toString());
    }
}

 这个帮助类中有4个方法:

1. exportExcel 想必很熟悉,就是用来生成目标报表文件

2. generateObject 这个就是自动生产一个Object,他的参数是一个Map类型,每一对KAY VALUE即是这个Object中的一个属性和类型,比如:

Map> fieldMap = new HashMap>();
fieldMap.put("vendorName", Class.forName("java.lang.String"));
fieldMap.put("productName", Class.forName("java.lang.String"));

有个属性叫vendorname是String类型,另外一个是productName是个String类型(集合也是支持的,比如List)。

3. setValue 设置对象某个属性的值

4. getValue 取得对象某个属性的值

 接下来用这个方法可以达到获取一个对象集合的目的

/**
     * Return single DTO bean list.
     * @param fieldMap
     * @param resultList rs from the DB
     * @return dtoBeanList
     * @throws ClassCastException 
     * @throws Exception
     */
    public List getSingleDTOBeanList(Map> fieldMap, List resultList) throws ClassCastException, Exception {
        List dtoBeanList = new ArrayList();
        for (Iterator iterator = resultList.iterator(); iterator.hasNext();) {
            ListOrderedMap listOrderedMap = iterator.next();
            Object object = generateObject(fieldMap);
            Iterator iter = fieldMap.entrySet().iterator();
            while (iter.hasNext()) {
                Map.Entry> entry = (Map.Entry>) iter.next();
                Object key = entry.getKey();
                setValue(object, key.toString(), listOrderedMap.get(key.toString().toUpperCase()));
            }
            dtoBeanList.add(object);
        }
        return dtoBeanList;
    } 
  

 

OK 到了这里大家应该都明白了,剩下的工作就是怎么管理我们的配置,这里用到的是DB配置

RPT_JXLS_OID PROP_SEQ PROP_NAME DATA_TYPE
3702 1 vendorName String
3702 2 productName String

这里值得注意的是PROP_NAME得和SQL中结果中的别名一样(忽略大小写)。

 

有了上面的基础,以后有新的需求只要配置这张表和新建相应XLS模板即可,不用物理创建对应的JAVA类了。

你可能感兴趣的:(JAVA,JXLS,报表,cglib)