NC6X报表数据加工做语义模型(返回SQL篇)

更新时间:2024-04-03 19:00:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

报表语义模型(数据加工:返回SQL方式)

数据加工方式:1.返回查询SQL ; 2.返回结果集DataSet;3.返回数据表(下次做了提供案例)。 实现方式基本一致,可以参照系统原有报表语义模型(抱歉不详细仅供参考)

一、实现基本思路概况(不详细比较啰嗦)

1. 首先不管语义模型数据加工是返回SQL、DataSet或者TABLE任何一种类型基本实现

步骤一致;

2. 先按需求实现的难易程度来选择使用以上那种方式来实现:一般数据都能SQL查询出

来的,偶尔有一两点数据取不到可以选择返回SQL,不会取数的那段创建临时表;如果是基本上都是东拼西凑的取数那就返回DataSet方式;最后一种时返回TABLE这种场景标准产品用的也不多,后续提供案例;

3. 数据加工做语义脚本肯定需要定义接口和实现类,确定好报表属于那个模块创建接口和

实现类并配置好接口文件UPM就好,具体配置可以参考改模块其他接口文件; 4. 数据加工接口参数一一般都是传com.ufida.dataset.IContext或者

nc.pub.smart.context.SmartContext,这个是报表上下文,所有查询参数及系统变量 5. 都放在这个里面,语义模型与接口里面这个两个context 基本可以互相转换,后面案

例就可以看出;

6. 不要想着是不是我要先把语义模型和自由报表配置好了再写数据加工代码,没用!正确

可行的方式先写数据加工代码;

7. 首先就要自己明确报表的取数逻辑,脑海大概设计下大概的代码怎么写;

8. 确定查询条件及数据类型,接口实现类里面定义全局变量查询条件(推荐)默认否赋值,

方便调试代码,因为这块还没用到查询模板,没法动态获取查询条件,后面分配了查询模板重新覆盖查询变量值就好了(数据加工报表只能做单据查询模板那种分配给报表节点);

9. 如果是DataSet返回方式的接口实现类里面定义好元数据列及数据类型,SQL返回方

式没有这一步操作;

10. 然后就是写报表取数逻辑代码,按自己默认设定查询变量值去写好代码及判断逻辑,最

后返回数据(SQL、DataSet或者TABLE);

11. 客开报表一般把语义模型和自由报表定义在集团或者全局的节点,这也是规范和经验所

得;

12. 在语义模型-集团(举例,全局节点也行)节点定义好自己的与模型,点设计弹出界面数

据加工放入调用写好的数据加工过接口进行代码调试及代码纠正;

13. 现在调试接口参数context基本上时没有什么数据的,目前也不会有查询条件字段在

里面,没有分配给节点查询模板呢,打开报表节点查询调用代码才能看到里面很多参数和值,所以暂时接口实现类不初始化查询参数方法及校验;

14. 语义模型数据加工里面放入调用接口代码,格式化,编译通过,下一步,代码成功的话

会正常返回报表字段列(元数据)页签,点确定,“3选择字段”自己添加字段列,这里的字段必须是代码返回的,不能自己随便新增无效的;自己添加字段“表达式大方框”必须选择左下角“数据加工(dp)”里面的字段,这个表达式里面可以写公式;最后解释下“数据加工(dp)”这个命名都是这样写规范,防止其他实施不随意修改。

15. 然后就是自由报表设计了,在“自由报表-集团”或者“自由报表-全局”节点,引入刚

才做好的语义模型文件,设计报表界面及相关统计等(这里不多说,不懂问实施或开发); 16. 记得自由报表设计界面有右上角“标题”左边有个“主组织属性设置”螺丝一样的按钮,

如果是报表存在组织查询条件的报表,这里必须设置集团和组织字段(代码或者SQL里面默认字段pk_org与pk_group)就不需要你设置,自动识别,否则需要手动设置(集团节点设置pk_group,反之都设置),如果这里没设置,可能出现语义模型可以预览数据,而自由报表预览无数据现象。一般不需要查询组织条件的报表,报表字段只需要业务字段+pk_group,发布组织类型为集团的报表节点即可;如果需要用到组织查询的报表,报表字段只需要业务字段+pk_group+pk_org,发布组织类型为具体组织(销售、库存、财务等)的的报表节点。

17. 自由报表界面格式设计好了就需要发布节点,如果改报表用不到组织字段那就发布集团

类型的报表节点;如果用到了组织,那就发布具体的组织(销售、库存、财务等)的节点。 18. 分配报表节点权限,制作报表查询模板,并分配给报表; 19. 打开报表节点 校验报表及查询模板能否正常加载出来;

20. 如果报表正常显示加载出来,测试查询模板,接口实现类断点调试,把剩下的查询参数

初始化与查询条件值校验工作完成;

21. 以上工作完成,导出代码补丁、报表文件补丁、SQL脚本补丁给实施测试验证就大功

告成!

二、定义报表数据加工接口及实现类代码

1. 定义接口及接口方法: 截图:

以下是代码:

package nc.itf.cmp.report.ext;

import com.ufida.dataset.IContext; /**

* 资金管理>现金管理报表>集团现金流简表(新)(性能优化-由原来的语义脚本改成数据加工) *

* @author WYR * @since 2017-09-25 * */

public interface GroupcashflowprofileNewItf {

}

/**

* 集团现金流简表(新) *

* @param context * @return

* @throws Exception */

public String getQuerySql(IContext context) throws Exception;

2. 接口实现类截图介代码: 截图:

代码:

package nc.impl.cmp.report.ext;

import nc.itf.cmp.report.ext.GroupcashflowprofileNewItf; import com.ufida.dataset.IContext; /**

* 资金管理>现金管理报表>集团现金流简表(新)(性能优化-由原来的语义脚本改成数据加工) *

* @author WYR * @since 2017-09-25 *

*/

public class GroupcashflowprofileNewImpl implements GroupcashflowprofileNewItf{

/**

* 资金管理>现金管理报表>集团现金流简表(新)(性能优化-由原来的语义脚本

改成数据加工) }

3. 后面自己完善逻辑。

*

* @author WYR * @since 2017-09-25 * */

public String getQuerySql(IContext context) throws Exception { }

return null;

三、创建临时表参考案列 import java.util.ArrayList; import java.util.List;

import nc.impl.pubapp.pattern.database.TempTable; import nc.vo.pub.JavaType;

//NC6x后台创建临时表并插入数据(select 多列 from TempTable 那种) public String createTempTable(String tempName, String[] ids) { List> rows = new ArrayList>(); for (String ite : ids) {

List row = new ArrayList(); String[] dates = ite.split(\ row.add(dates[0]); row.add(dates[1]); rows.add(row); }

//这个自己写个String columns =\分割一下就好了,方便拼

接select 语句查询 String[] columns = { \ };

String[] columnTypes = {

\ };

JavaType[] types = new JavaType[] { JavaType.String, JavaType.String };

TempTable dao = new TempTable();

return dao.getTempTable(tempName, columns, columnTypes, types, rows);//返回表名 }

四、查询条件获取与查询模板简单说明

五、义模型放入数据加工接口代码操作步骤

1.创建语义模型:

2.设计语义模型(语义模型按钮组下面点设计按钮):

3.放入数据加工写好的代码接口代码:

4.格式化代码>编译>下一步>确定:

5.添加语义模型字段:

六、自由报表设计

七、实打开报表节点测试查询模板调试代码修改代码(自己体会)

此处省略一万个草泥马(骂平台的最多能调试三次,超过3次报错直接结束开发环境启动的服务)........

八、接口文件配置

tx=\ supportAlias=\>

nc.itf.cmp.report.ext.GroupcashflowprofileNewItf

ace>

nc.impl.cmp.report.ext.GroupcashflowprofileNewI

mpl

九、提供案例所有类代码:

1.临时表VO:

package nc.vo.cmp.report.ext; /***

* 资金管理>现金管理报表>集团现金流简表(新) *

* @author WYR *@since 2017-09-26 * */

public class GpCflowprofileNewTempVO { private String pk_group; private String inoutname; private String cuname; private double money; private String tallydate; private String cashflow;

临时表VO

public String getPk_group() { }

public void setPk_group(String pk_group) { }

public String getInoutname() { }

public void setInoutname(String inoutname) { }

public String getCuname() { }

public void setCuname(String cuname) { }

public double getMoney() {

this.cuname = cuname; return cuname;

this.inoutname = inoutname; return inoutname; this.pk_group = pk_group; return pk_group;

}

}

return money;

public void setMoney(double money) { }

public String getTallydate() { }

public void setTallydate(String tallydate) { }

public String getCashflow() { }

public void setCashflow(String cashflow) { }

this.cashflow = cashflow; return cashflow;

this.tallydate = tallydate; return tallydate; this.money = money;

2.接口:

package nc.itf.cmp.report.ext;

import com.ufida.dataset.IContext; /**

* 资金管理>现金管理报表>集团现金流简表(新)(性能优化-由原来的语义脚本改成数据加工) *

* @author WYR * @since 2017-09-25 * */

public interface GroupcashflowprofileNewItf {

/**

* 集团现金流简表(新) *

* @param context * @return

}

* @throws Exception */

public String getQuerySql(IContext context) throws Exception;

3.实现类:

package nc.impl.cmp.report.ext;

import java.util.ArrayList; import java.util.HashMap; import java.util.List; import nc.bs.dao.BaseDAO; import nc.bs.dao.DAOException;

import nc.impl.pubapp.pattern.database.TempTable; import nc.itf.cmp.report.ext.GroupcashflowprofileNewItf; import nc.jdbc.framework.processor.BeanListProcessor; import nc.vo.cmp.report.ext.GpCflowprofileNewTempVO; import nc.vo.pub.JavaType;

import nc.vo.pub.query.ConditionVO;

import nc.vo.pubapp.pattern.exception.ExceptionUtils;

import com.ufida.dataset.IContext;

import nc.pub.fa.common.util.NumberUtils;

import com.ufida.report.anareport.FreeReportContextKey; /**

* 资金管理>现金管理报表>集团现金流简表(新)(性能优化-由原来的语义脚本改成数据加工) *

* @author WYR * @since 2017-09-25 * */

public class GroupcashflowprofileNewImpl implements GroupcashflowprofileNewItf{

/*****最终返回的查询SQL******/

private StringBuilder builderSQL = new StringBuilder(); private BaseDAO dao=null; /*****创建的临时表名*******/

private String TempTableName=null; /*****临时表查询SQL列*******/ private final String

TempSelectField=\;

/*****项目类型(拼SQL用到)******/ private String [] cashflows=new String[]{

\经营流入\,\经营流出\,\土地费用\,\筹资流入\,\筹资流出\,\投资流入\,\

投资流出\,\集团内部抵消项\,\理财收支\};

/*******开始日期*********/

private String beg_date=\; /*******结束日期*********/

private String end_date=\; /********java 数据类型*********/

private JavaType[] types = new JavaType[] {

JavaType.String, JavaType.String, JavaType.String,

JavaType.BigDecimal,JavaType.String,JavaType.String

};

/************数据库列类型*************/ private String[] columnTypes = { \,

\,\,\, \, \};

//以下汇率只是以默认定义的(测试使用,否则开发时语义模型没法测试编译下一

步通过),后续查询条件必输会覆盖值

//那个时候还没用到查询模板 /********美元汇率********/ private double usd=6.5382; /********港币汇率********/

private double hkd=0.83687; /********马币汇率********/ private double mb=1.55; /********澳元汇率********/ private double ob=1.7; /********新币汇率********/ private double xb=1.2; /********加币汇率********/ private double jb=1.3;

/**

* 资金管理>现金管理报表>集团现金流简表(新)(性能优化-由原来的语义脚本

改成数据加工)

*

* @author WYR * @since 2017-09-25 * */

public String getQuerySql(IContext context) throws Exception {

return null;

} /***

* 拼接查询SQL *

* @param context 报表参数上下文 * @author WYR * @since 2017-09-25 * @return

* @throws Exception */

private String getConvertSql(IContext context)throws Exception{ } /***

TempTableName=null;

this.getQueryParameters(context); this.checkQueryParametersIsNotNull(); this.getCreateTempTableName(); this.buildSelectSql(); this.getEmbeddedSql();

return this.builderSQL.toString();

* 获取第二层嵌套的SQL *

* @author WYR * @since 2017-09-26 * @throws Exception */

private void getEmbeddedSql() throws Exception{

StringBuilder bdSql = new StringBuilder(); bdSql.append(\); bdSql.append(\); bdSql.append(\);

bdSql.append(\+getSameCasewhenPartSql(\经营\,\经营流入\)+\); bdSql.append(\);

bdSql.append(\+getSameCasewhenPartSql(\经营\,\经营流出\)+\); bdSql.append(\);

bdSql.append(\);

bdSql.append(\+getSameCasewhenPartSql(\土地费用\,\土地费用

\)+\);

bdSql.append(\); bdSql.append(\);

bdSql.append(\+getSameCasewhenPartSql(\筹资\,\筹资流入\)+\); bdSql.append(\);

bdSql.append(\+getSameCasewhenPartSql(\筹资\,\筹资流出\)+\); bdSql.append(\);

bdSql.append(\); bdSql.append(\);

bdSql.append(\+getSameCasewhenPartSql(\投资\,\投资流入\)+\); bdSql.append(\);

bdSql.append(\+getSameCasewhenPartSql(\投资\,\投资流出\)+\); bdSql.append(\);

bdSql.append(\); bdSql.append(\);

bdSql.append(\+getSameCasewhenPartSql(\集团内部\,\集团内部抵

消项\)+\);

bdSql.append(\);

bdSql.append(\);

bdSql.append(\+getSameCasewhenPartSql(\理财收支\,\理财收支

\)+\);

}

/**获取查询 Union all (里面的子查询SQL) 改用公共方法 *

bdSql.append(\);

this.builderSQL.append(bdSql);

* @param sqlField 默认的inouttype值 'F.理财收支' * @param cashflow 项目 '理财收支'

* @例子 select pk_group,'F.理财收支' inouttype,'理财收支' as

aitem,inoutname as fitem,

* @author WYR * @since 2017-09-26 * @return

* @throws Exception */

private String getSameCasewhenPartSql(String sqlField,String

cashflow)throws Exception{

StringBuilder samePartSql = new StringBuilder(); samePartSql.append(\+sqlField+\

inouttype,'\+cashflow+\);

samePartSql.append(\

usd,sum(mb) as mb,sum(xb) as xm,\);

samePartSql.append(\); samePartSql.append(\);

samePartSql.append(\

cuname='美元' then money else 0 end as usd,\);

samePartSql.append(\马币' then money else 0 end

as mb,\);

samePartSql.append(\人民币' then money else 0

end as Rmb,\);

samePartSql.append(\港币' then money else 0 end

as hkd,\);

samePartSql.append(\澳元' then money else 0 end

as ob,\);

samePartSql.append(\加币' then money else 0 end

as jb,\);

samePartSql.append(\新加坡元' then money else 0

end as xb \);

samePartSql.append(\);

samePartSql.append(\+getQueryTempTableDataSql(cashflow)+\

group by pk_group,inoutname\);

}

return samePartSql.toString();

/***

* 初始化查询参数(获取查询条件值) *

* @param context * @author WYR * @since 2017-09-26

* @throws Exception */

private void getQueryParameters(IContext context)throws Exception{

HashMap hashmap=null;//获取查询条件(key,值)对应 ConditionVO[] conditionvos=(ConditionVO[])

context.getAttribute(FreeReportContextKey.KEY_REPORT_QUERYCONDITIONVOS);

if(null!=conditionvos&&conditionvos.length>0){

hashmap=new HashMap(); for(ConditionVO conditionvo:conditionvos){

hashmap.put(conditionvo.getFieldCode(),

conditionvo.getValue());

}

checkQueryParametersAndSetValue(hashmap);

}else{

ExceptionUtils.wrappBusinessException(\查询条件不能为空,请检

查!\);

}

/***校验查询条件与赋值 *

}

* @author WYR * @since 2017-09-26 *

* @param hashmap * @throws Exception */

private void checkQueryParametersAndSetValue(HashMap

hashmap)throws Exception{

beg_date=null; end_date=null; usd=0.00;

hkd=0.00;

mb=0.00; ob=0.00; xb=0.00; jb=0.00;

if(null==hashmap||hashmap.size()==0){

ExceptionUtils.wrappBusinessException(\查询条件不能为空,请检

查!\);

}

String begdate=hashmap.get(\); String enddate=hashmap.get(\);

String usdstr=hashmap.get(\); String hkdstr=hashmap.get(\); String mbstr=hashmap.get(\); String obstr=hashmap.get(\); String xbstr=hashmap.get(\); String jbstr=hashmap.get(\);

if(null==begdate||begdate.length()==0){

ExceptionUtils.wrappBusinessException(\开始日期不能为空,请检

查!\);

}

if(null==enddate||enddate.length()==0){

ExceptionUtils.wrappBusinessException(\结束日期不能为空,请检

查!\);

}

if(!NumberUtils.isNumber(usdstr)){

ExceptionUtils.wrappBusinessException(\美元汇率只能输入正整数或

正小数,请检查!\);

}

if(!NumberUtils.isNumber(hkdstr)){

ExceptionUtils.wrappBusinessException(\港币汇率只能输入正整数或

正小数,请检查!\);

}

if(!NumberUtils.isNumber(mbstr)){

ExceptionUtils.wrappBusinessException(\马币汇率只能输入正整数或

正小数,请检查!\);

}

if(!NumberUtils.isNumber(obstr)){

ExceptionUtils.wrappBusinessException(\澳元汇率只能输入正整数或

正小数,请检查!\);

}

if(!NumberUtils.isNumber(xbstr)){

ExceptionUtils.wrappBusinessException(\新币汇率只能输入正整数或

正小数,请检查!\);

}

if(!NumberUtils.isNumber(jbstr)){

ExceptionUtils.wrappBusinessException(\加币汇率只能输入正整数或

正小数,请检查!\);

}

//由于试图里面日期字段是2017-09-27 与2017-09-27 09:06:37 这两种 beg_date=begdate.substring(0, 10);

end_date=enddate.substring(0, 10)+\; usd=Double.valueOf(usdstr);

hkd=Double.valueOf(hkdstr);

mb=Double.valueOf(mbstr);

}

ob=Double.valueOf(obstr); xb=Double.valueOf(xbstr); jb=Double.valueOf(jbstr);

/***

* 校验查询条件是否为空(目前所有条件必输项) *

* @author WYR * @since 2017-09-26 * @throws Exception */

private void checkQueryParametersIsNotNull()throws Exception{

if(null==beg_date||\.equals(beg_date)){

ExceptionUtils.wrappBusinessException(\开始日期不能为空,请检

查!\);

}

if(null==end_date||\.equals(end_date)){

ExceptionUtils.wrappBusinessException(\结束日期不能为空,请检

查!\);

}

if(usd<=0){

ExceptionUtils.wrappBusinessException(\美元汇率必须大于0,请检

查!\);

}

if(hkd<=0){

ExceptionUtils.wrappBusinessException(\港币汇率必须大于0,请检

查!\);

}

if(mb<=0){

ExceptionUtils.wrappBusinessException(\马币汇率必须大于0,请检

查!\);

}

if(ob<=0){

ExceptionUtils.wrappBusinessException(\澳元汇率必须大于0,请检

查!\);

}

if(xb<=0){

ExceptionUtils.wrappBusinessException(\新币汇率必须大于0,请检

查!\);

}

if(jb<=0){

ExceptionUtils.wrappBusinessException(\加币汇率必须大于0,请检

查!\);

}

}

/**

* 最外层查询SQL字段部分

* @author WYR * @since 2017-09-26

*/

private void buildSelectSql() {

this.builderSQL=new StringBuilder();

String totalFiled=\+hkd+\+usd+\

\+mb+\+xb+\+jb+\+ob+\ ;

this.builderSQL.append(\);

this.builderSQL.append(\

hkd ,usd/10000 as usd,\);

this.builderSQL.append(\

jb,ob/10000 as ob,\+totalFiled);

} /***

* 查询所有子查询总结果集(9个子查询视图的结果集) * @author WYR

* @since 2017-09-25 * @return

* @throws DAOException */

@SuppressWarnings(\)

private List> getTempTableData() throws DAOException{

List> data = new ArrayList>(); List tempVOList=null; String sql=getubqueryAllSql();

tempVOList=(List)

getDao().executeQuery(sql, new

BeanListProcessor(GpCflowprofileNewTempVO.class));

if(null!=tempVOList&&tempVOList.size()>0){

for (GpCflowprofileNewTempVO tempVO : tempVOList) {

List row = new ArrayList(); row.add( tempVO.getPk_group()); row.add( tempVO.getInoutname()); row.add( tempVO.getCuname()); row.add( tempVO.getMoney()); row.add( tempVO.getTallydate()); row.add( tempVO.getCashflow()); data.add(row);

}

}

}

if(null!=data&&data.size()>0){ }

return data;

return null;

/**获取所有子查询UNION ALL 查询SQL(9个子查询视图的SQL UNION ALL) *

* @author WYR * @since 2017-09-25 * @return */

private String getubqueryAllSql(){

String samePartSql=\

pk_group,inoutname,cuname,nvl(recmoney, 0) - nvl(paymoney, 0) as\ +

\ where \;

String sameWherePartSql=\+beg_date+\tallydate<= '\+end_date+\;

String unionStr=\;

StringBuilder bfSql= new StringBuilder();

}

for (int i = 0; i < cashflows.length; i++) { }

return bfSql.toString();

String cashflow = cashflows[i]; bfSql.append(samePartSql);

bfSql.append(\+cashflow+\); bfSql.append(sameWherePartSql); if(i<(cashflows.length-1)){ }

bfSql.append(unionStr);

/**根据cashflow获取子查询临时表SQL *

* @author WYR * @since 2017-09-25 * * @return */

private String getQueryTempTableDataSql(String cashflow){

String tempSelceSql=\+TempSelectField+\

\+TempTableName+

\+cashflow+\

tallydate>='\+beg_date+\+end_date+\;

return tempSelceSql;

} /**

* 创建临时表并插入数据 * @author WYR * @since 2017-09-25 * */

private void getCreateTempTableName() throws Exception{

List> rows =getTempTableData(); TempTable dao = new TempTable(); String[] columns=TempSelectField.split(\);

TempTableName=dao.getTempTable(\, columns,

columnTypes, types, rows);

} /**

* 获取BaseDAO *

* @author WYR

}

* @since 2017-09-25 * @return */

public BaseDAO getDao() { } /**

* set BaseDAO *

* @author WYR * @since 2017-09-25 * @param dao */

public void setDao(BaseDAO dao) { }

this.dao = dao; if(dao==null){ }

return dao;

dao=new BaseDAO();

十、最后来个总结

其实没什么难的,都不是个事,哈哈 开玩笑,比较啰嗦,希望可以帮助大家,不对的可以提出纠正或大家补充,仅供参考不负任何责任^_^!

整 理 人:WYR

编写日期:2017-09-27

本文来源:https://www.bwwdw.com/article/kw2r.html

Top