# EAS BOS 开发问题集锦
1:二次开发后,EAS的运行机制
(以下说明只适合于BOS6.1以后版本)
BOS视图目录说明:MMEAS:EAS解决方案目录
-
metadata:二次开发元数据存放目录
-
basemetas:标准产品元数据存放目录
在BOS开发平台中,当在basemetas目录下双击某一个元数据文件时,BOS会自动帮我们生成该元数据的一份拷贝到metadata目录下,二次开发如果需要修改元数据,就到metadata目录下修改。 EAS在运行时,会优先加载metadata目录下的元数据。(注:若删除metadata目录下修改过的元数据,EAS会自动加载basemetas目录下标准产品的元数据,因此在开发过程中,如果metadata目录下的元数据文件改乱了,可大胆将其删除)。
Java视图目录说明: 在BOS视图对元数据进行发布后,BOS平台会在Java视图生成相应的.java文件。此时,开发者可以通修改相关的java文件进行二次开发的工作。注意:二次开发所做的修改,要尽量避免与产品打补丁产生冲突。
2:UI类常用方法说明
方法:onLoad() |
方法:actionAddNew_actionPerformed(ActionEvent arg0) |
方法:verifyInput(ActionEvent e) |
方法:applyDefaultValue(IObjectValue iobjectvalue) |
方法:getSelectors() |
方法:*_dataChanged(DataChangeEvent e) |
方法:storeFields() |
方法:actionRec_actionPerformed(ActionEvent e) |
方法:applyDefaultValue(IObjectValue iobjectvalue) |
方法:public void verifyInput(ActionEvent actionevent) |
3:如何让表头的字段在单据提交后还能进行修改?
一般情况下,单据提交后,是不允许修改的。但是也存在一些特殊的情况,需要在工作流中,对单据中的某些字段进行修改,此时,一般是通过在自定义的UI扩展类中,重写onLoad()方法,然后在方法中调用控件的setEnabled()、setEditable()、setReadOnly()方法(这三个方法不一定需要全部调用,根据具体情况而定),如下代码:
@Override public void onLoad() throws Exception { super.onLoad(); //单据未生成凭证之前,"收款类型"为可编辑、“往来户”也可编辑 boolean hasFV = this.editData.isFiVouchered(); if(!hasFV){ //收款类型 f7RecBillType.setEnabled(true); f7RecBillType.setEditable(true); f7RecBillType.setReadOnly(false); //往来户 prmtPayer.setEnabled(true); prmtPayer.setEditable(true); prmtPayer.setReadOnly(false); } }
4:如何修改F7字段所关联的基础档案
在一般情况下,在BIM视图对单据新增F7字段时,就可以关联到想要的基础档案或其它视图。但是,当需要关联一些不存在业务单元(即*.bizunit文件)的基础档案时(如:自定义核算项目)。此时就只能通过以下步骤来处理:
-
在BIM里加一个F7字段,关联物料或其他可以选到的基础资料。保存后先别发布
-
切换到BOS透视图,打到对应的.relation文件,修改supplierEntity,原来是指定物料的实体,改成自定义核算项目的实体
-
打开XXXEditUI.ui,修改F7字段的queryInfo,原来是指向物料的query,改成自定义核算项目的query
5:如何给F7控件设置过滤条件
当需要对F7控件所打个视图中的内容进行过滤时,可对F7控件设置过滤条件,使用方法如下:
EntityViewInfo evi = new EntityViewInfo(); //创建实体视图 FilterInfo f = new FilterInfo();//创建过滤对象 FilterItemInfo filter1 = new FilterItemInfo("number", "SHFL001", CompareType.GREATER);//创建第一个过滤条件,第一个参数:所查询的实体的属性,第二个参数:属性的目标值,第三个参数:比较符 FilterItemInfo filter2= new FilterItemInfo("age", "20", CompareType.GREATER);//创建第二个过滤条件 f.getFilterItems().add(filter1);//将过滤条件添加到过滤对象中 f.getFilterItems().add(filter2); f.setMaskString("#0 or #1");//设置两个过滤条件之间的关系 evi.setFilter(f);//设置实体视图的过滤器 f7.setEntityViewInfo(evi);//将实体视图绑定到F7控件 f7 .getQueryAgent().resetRuntimeEntityView();
6:如何通过IObjectPK pk获取实体对象
IObjectPK是一个表示实体对象id的对象,在日常开发工作中,经常需要通过它来获取实体对象。以下是通过IObjectPK获取实体对象代码的模版:
I*Info i*Info = *Factory.getLocalInstance(ctx); *Info info = i*Info.get*Info(pk); //以下示例,通过IObjectPK获取成本对象实体:CostObjectInfo ICostObject iCostInfo = CostObjectFactory.getLocalInstance(ctx); CostObjectInfo coi = iCostInfo.getCostObjectInfo(pk);
7:如何通过实体对象的id获取实体对象
//如下代码,通过应收单的id号,获取应收单表体实体
String entityID ="dsfarlewkrjewrojafad"; //BOSUuid uid = BOSUuid.create(entityID); IObjectPK opk = new ObjectUuidPK(entityID); OtherBillentryInfo obi = OtherBillentryFactory.getRemoteInstance().getOtherBillentryInfo(opk);
8:BOTP自定义公式解决方案
注意:只适用于EASBOS530或以上版本
一、业务场景: 运行时BOTP的公式平台提供的函数较少,如果要实现比较复杂的逻辑,譬如通过物料编码从其他单据取出对应数量,运行时的公式平台就显得捉襟见肘了。对于客户开发的单据,可以通过写代码实现。但是对于标准产品的单据,如果反编译代码,则升级时相当麻烦。而自定义公式方案正是为了解决此难题而生。它可以通过写代码在BOTP公式平台挂上自定义的公式,公式内容由程序员自由决定,而不会受升级影响。
二、原理:(业务人员只需重点关注步骤3、4、5)
1.在BOS自定义一个类,实现com.kingdee.bos.service.formula.api.IFormulaFunctions
接口。(该类必须位于com.kingdee.bos.service.formula.api
此包下,因为要引用此包里的非公共类) 类的定义参考如下:
package com.kingdee.bos.service.formula.api; import java.util.Iterator; import java.util.List; import java.util.Vector; import com.kingdee.bos.kscript.KScriptException; /** * BOTP自定义公式demo * @author Yang Yihao. Just call me House. * @date since 2007-9-6 * @Email: dejavu.house@gmail.com */ public class CustomBTPFunctionDemo implements IFormulaFunctions { //用于存放公式的变量 private static Vector funcInfos; static { //加载类时定义自定义公式 funcInfos = new Vector(); //FuncInfo()的第一个参数是公式名,第二个参数是公式所在的分类(可随便取名),第三个参数是公式的描述信息(在BOTP公式平台显示) funcInfos.add(new FuncInfo("helloLiuXun", "HelloWorld", "Wish the Telecom project would complete soon.")); } /** * 运行时BOTP公式平台加载自定义公式时,就是从该返回值里取公式的名称的 * @author Yang Yihao. Just call me House. * @date since 2007-9-6 * @Email: dejavu.house@gmail.com * @return 所有自定义公式的名称 */ public String[] getAllFuncNames() { String as[] = new String[funcInfos.size()]; for(int i = 0; i < funcInfos.size(); i++) as[i] = ((FuncInfo)funcInfos.get(i)).funcName; return as; } /** * 运行时BOTP公式平台加载自定义公式时,就是从该返回值里取公式的分类的(看运 行时的界面就很好理解) * @author Yang Yihao. Just call me House. * @date since 2007-9-6 * @Email: dejavu.house@gmail.com * @param s * @return */ public String getFuncCategory(String s) { if(s == null) return null; for(int i = 0; i < funcInfos.size(); i++) if(s.equals(((FuncInfo)funcInfos.get(i)).funcName)) return ((FuncInfo)funcInfos.get(i)).funcCategory; return null; } /** * 获取公式的描述 * @author Yang Yihao. Just call me House. * @date since 2007-9-6 * @Email: dejavu.house@gmail.com * @param s * @return */ public String getFuncDesc(String s) { if(s == null) return null; for(int i = 0; i < funcInfos.size(); i++) if(s.equals(((FuncInfo)funcInfos.get(i)).funcName)) return ((FuncInfo)funcInfos.get(i)).funcDesc; return null; } public boolean existFunction(String s) { if(s == null) return false; for(int i = 0; i < funcInfos.size(); i++) if(s.equals(((FuncInfo)funcInfos.get(i)).funcName)) return true; return false; } /** * 运行公式时调用此方法,公式的具体逻辑就写在这里 * @author Yang Yihao. Just call me House. * @date since 2007-9-6 * @Email: dejavu.house@gmail.com * @param func 公式名称 * @param paramList 公式的参数 * @return 公式结果 * @throws KScriptException */ public Object evalFunction(String func, List paramList) throws KScriptException { //判断用户是选了哪个公式 if(func != null && func.equals("helloLiuXun")) { //这里可以写满足各式各样需求的代码 if(paramList != null && paramList.size() > 0) { StringBuffer sb = new StringBuffer(10); for(Iterator iter = paramList.iterator(); iter.hasNext();) { sb.append(iter.next()).append(","); } return sb.toString(); } else return "Congratulations"; } return "TheEnd"; } }
2.在BOTP目标单据的实体(entity)上加上扩展属性“billFormulaClass”,属性值设为第1步创建的类的全名(含包名)。如下图:
(注意:此 扩展属性 要在 表头实体 的 基础信息 页签中添加,表体实体是不存在billFormulaClass这个扩展属性的)
3.运行时,在BOTP规则设置的“公式平台”->“公式元素”->“函数”页签里可以看到自定义的函数
helloLiuXun()就是自定义公式。
4.设置BOTP公式的格式如下:
参数用半角双引号括起来,可以传多参数,参数间用半角逗号隔开。 5.恭喜,令人兴奋的结果完全满足你个性化的需求!
9:在自定我Java类中,引用系统日志的方法
import org.apache.log4j.Logger; // 获取写日志的对象 private static Logger logger = Logger.getLogger("com.kingdee.eas.custom.gz.bd.app.BizTypeGZControllerBean"); //写日志 logger.info(e.getMessage());
10:EAS-BOS项目路径变更的方法
拷贝工作区的时候,会出现目录变更,在发布项目是,会出现启动ear失败情况,如下错误:
[apusic.service.J2EEDeployer] 启动应用 'eas.ear' 失败。 com.apusic.deploy.runtime.InvalidModuleException: 模块文件 'D:\zgh\Project\gz\eTianxia\workspace\EWorld\runtime\server\deploy\eas.ear' 不存在。
EAS-BOS项目路径变更的方法:
1. 修改:$ProjectPath$\runtime\server\profiles\server1\config\bosconfig.xml <attribute key="MetaDataPath" value="D:\workspace\EWorld/metadata" />` 2. 修改$ProjectPath$\runtime\server\profiles\server1\config\licensefile.xml <uri>D:\workspace\EWorld\runtime\server\profiles\server1\config\licenses\license</uri> 3. $ProjectPath$\runtime\server\profiles\server1\config\portalConfig\easWebConfig.xml <!--本地元数据加载路径--> <attribute key="metadatapath" value="D:\workspace\EWorld\metadata" /> 4. 修改$ProjectPath$\EWorld\runtime\apusic\config\server.xml <server> <application name="eas.ear" base="D:/workspace/EWorld/runtime/server/deploy/eas.ear" start="auto" /> </server>
11:部署时提示版本不一致的解决办法
从服务器的目录:如: D:\Kingdee\eas\server\properties
Copy文件eascomponents.xml
到部署机的目录: 如:E:\workspace\mmeas(具体名称根据你的项目名而定)
12:如何获取当前用户
-
在UI扩展类中,获取当前用户可通过工具类SysContext 如:
SysContext.getSysContext().getCurrentUserInfo()
-
在ControlerBean的扩展类中,获取当前用户可通过工具类ContextUtil 如:
ContextUtil.getCurrentUserInfo(ctx)
关于SysContext和ContextUtil这两个工具类中方法的介绍: 这两个类是EAS的全局工具类,用于获取当前用户信息,当前组织单元信息、客户端IP、客户端名字等信息。SysContext用于客户端,如UI扩展类中;而ContextUtil
用于服务端,如ControllerBean
扩展类中。
13:如何增加F7界面上的过滤条件
找到F7界面所对应的Query后,选择字段页签,找对应的属性?扩展属性:增加“是否在通用过滤中显示”的扩展属性,并将其值设置为true。重新发布。
14:访问应用服务器[server1,127.0.0.1:6888]时,用户名[admin]认证失败!
请检查部署应用时配置的的用户名及密码是否能正常登录应用服务器的管理页面。
-
如果不能登录,请首先应用服务器的管理控制台创建用户;
-
或者重新部署应用,修改部署向导配置的用户名/密码为合法值。 异常堆栈:
com.kingdee.eas.tools.admin.domain.exception.AppServerLoginFailedException: Authentication denied,the user name and/or password is not valid! at com.kingdee.eas.tools.admin.domain.impl.EASServerServiceImpl.startApplicationServer(EASServerServiceImpl.java:913) at com.kingdee.eas.tools.admin.domain.impl.EASServerServiceImpl.startApplicationServer(EASServerServiceImpl.java:719)
上述提示的方案好像有点问题,我另找了一个解决办法: 进入%Apusic_home%\domains\server1\store
,将users.db文件删除,重启应用服务器,即可恢复admin密码为初始密码。
15:如何获得BOSType
打开*.entity实体视图。切换到“源代码”标签,找到<bosType>48DA3A71</bosType>。这就是该实体所对应的BOSType了 或者java代码:
BOSObjectType objectType = objectValue.getBOSType();
16:如何添加第3方jar包
1、在项目中切换到 java视图 选择项目工程右键 >构建路径>配置构建路径 2、将jar包分别Copy到以下路径
-
用于BOS使用 \workspacewm\wmnew\lib\client\trd \workspacewm\wmnew\lib\server\trd
-
部署路径 /kingdee/eas/server/deploy/fileserver.ear/easWebClient/lib/client/trd /kingdee/eas/server/deploy/fileserver.ear/easWebClient/deploy/client /kingdee/eas/server/lib/server/trd /kingdee/eas/server/lib/client/trd
17:bos登陆客户端显示没有许可
原因:bos工具自带eas license没有对应模块许可导致。 解决方法:将eas7.0安装包中自带eas 的license文件替换到bos工具如下路径即可, \bim\eclipse\plugins\com.kingdee.bos.bim_template_6.1.0\templates\licenses PS:license文件名必修改成“license”字样才可 就把licenses PS:license文件放到相同路径。文件名为license
18:手动添加合计行
1. 代码方式处理
//添加合计栏 KDTFootManager footmgr = new KDTFootManager(kdtE2); footmgr.addFootView(); kdtE2.setFootManager(footmgr); kdtE2.addFootRow(0); IRow row = footmgr.getFootRow(0); row.getCell(0).setValue("合计:"); //设置合计字段(重视父类方法) protected void setTableToSumField() { setTableToSumField(kdtE1, new String[] { "ContractAmount" }); super.setTableToSumField(); }
完整代码
IRow row = tblMain.addRow(); row.getStyleAttributes().setBackground(new Color(236, 255, 255)); row.getCell(0).setValue("合 计 栏 :"); row.getStyleAttributes().setBold(true); row.getStyleAttributes().setFontColor(Color.RED); BigDecimal sum1 = new BigDecimal("0.00"),sum2 = new BigDecimal("0.00"); BigDecimal sum3 =new BigDecimal("0.00"),sum4=new BigDecimal("0.00"); for (int i=0;i<tblMain.getRowCount();i++) { //合计最后俩栏 if (tblMain.getCell(i, 1).getValue()!=null && !tblMain.getCell(i, 1).getValue().equals("")) { tblMain.getCell(i, 1).setValue(((BigDecimal)tblMain.getCell(i, 1).getValue()).setScale(2)); sum1 = sum1.add((BigDecimal)tblMain.getCell(i, 1).getValue()); } if (tblMain.getCell(i, 2).getValue()!=null && !tblMain.getCell(i, 2).getValue().equals("")) { tblMain.getCell(i, 2).setValue(((BigDecimal)tblMain.getCell(i, 2).getValue()).setScale(2)); sum2 = sum2.add((BigDecimal)tblMain.getCell(i, 2).getValue()); } } row.getCell(1).setValue(sum1.setScale(2)); row.getCell(2).setValue(sum2.setScale(2));
2. bim设计处理
-
ListUI所绑定的Query字段页签设置两个扩展属性
是否统计字段:true
统计字段按主键进行统计:设置为主键字段名,比如(id,entrys.id),如果不设置的话,统计的时候会按分录行统计,对非分录行统计出来的结果会不正确。
-
在ListUI.java中重写isFootVisible方法,将返回值设置为
true
。
@Override protected boolean isFootVisible() { // TODO Auto-generated method stub return true; }
19:bos保存后自动退出
我猜到可能是JVM内存的问题,于是找到exlipse.ini,修改为: Eclipse.ini 路径:D:\kingdee\EASStudio\bos\BOSModular\platform\eclipse -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M
20:屏蔽分录双击排序功能
this.kdtEntrys.removeKDTMouseListener(this.kdtEntrys.getSortMange());//所有列 tblMain.getColumn(i).setSortable(false); //单个
21:获取单元格显示的值
detailTable.getCellDisplayText(cell);
22:合并这两个EntityViewInfo
EntityViewInfo view1 = new EntityViewInfo(); EntityViewInfo view2 = new EntityViewInfo(); view1.getFilter().mergeFilter(view2.getFilter(), "and");
23:指定F7对字段排序
SorterItemCollection sorter = new SorterItemCollection(); SorterItemInfo sortinfo = new SorterItemInfo(); sortinfo.setPropertyName("属性名称"); sortinfo.setSortType(SortType.DESCEND); EntityViewInfo entityInfo = new EntityViewInfo(); entityInfo.setSorter(sorter); my_PromptBox.setEntityViewInfo(entityInfo);
24:标准产品如何扩展类以便重写方法
-
对于客户端的UI类,无论是listUI,还是EditUI,都可以在通过追加后缀名CTEx的方式来扩展。如要重写标准产品采购订单的保存方法: com.kingdee.eas.scm.sm.pur.client.PurorderEditUI,在实际二次开发中,发布之后只会生成com.kingdee.eas.scm.sm.pur.client.AbstractPurorderEditUI,如果要重写保存的方法,则可以在com.kingdee.eas.scm.sm.pur.client包下新建PurorderEditUICTEx,此类继承PurorderEditUI类即可,然后在PurorderEditUICTEx重写保存方法。
-
服务端的扩展,主要是对bean的扩展,有两种方法 方法1. 1、在bim里面找到对应的业务单据XXX,打开“业务单元->功能”,新建一功能,然后发布。 2、切换到java视图,可以找到刚才的业务单据的XXXControllerBeanEx。 3、在XXXControllerBeanEx中覆盖对应的方法即可。 方法2. 新建一扩展类如:TestControllerBeanEx,然后在文本打开实体元数据,增加一扩展属性
<rs key="entityObject[com.kingdee.eas.custom.app.Test].extendedProperty.controllerBeanEx"> <lang locale="en_US" value="com.kingdee.eas.custom.app.TestControllerBeanEx" /> <lang locale="zh_CN" value="com.kingdee.eas.custom.app.TestControllerBeanEx" /> <lang locale="zh_TW" value="com.kingdee.eas.custom.app.TestControllerBeanEx" /> </rs>
注意上面的写法[com.kingdee.eas.custom.app.Test]中的"Test"是TestControllerBeanEx的controllerBeanEx前面的Test,可以参考该实体文件的其他的属性 <rs ....> ... </rs>
备注 客户端的扩展针对行业版提供的是PIEx,为了不影响产品的后续维护,针对客户的客户端UI扩展务必使用后缀CTEx。
25:如何让编辑界面一打开就是最大化
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.setPreferredSize(screenSize);
26:去掉导出Excel右键菜单
public void addCommonMenusToTable(KDTable table) { super.addCommonMenusToTable(table); PopupMenuManager mgr = getPopupMenuManager(table); mgr.removeMenuSection("export"); }
27:设置是否在调入列表界面之前先出过滤框
protected boolean initDefaultFilter() { return true; }
28:隐藏EditUI上面板上的添加行删除行的按钮
this.kdtPaymentInfoEntry_detailPanel.getAddNewLineButton().setVisible(false); this.kdtPaymentInfoEntry_detailPanel.getInsertLineButton().setVisible(false); this.kdtPaymentInfoEntry_detailPanel.getRemoveLinesButton().setVisible(false);
29:特殊数据授权开发
一, 首先需要单据支持特殊数据权限,具体开发步骤如下:
-
权限项绑定实体,。
-
权限项的是否支持数据权限为“是”
-
在${EAS_HOME}/server/profiles/server*/config/EAS_PermissionConfiguration.xml配置文件中增加单据实体,添加方式如下:
<special-data-permission> <name>com.kingdee.eas.fi.gl.app.Voucher</name> <type>2652E01E</type> </special-data-permission>
-
发布,部署,重启服务,同步权限项。
-
在特殊数据权限界面找到单据勾选上拥有者有权和主管权限,此时单据只能由制单人和自己的上级主管查看。如果要其他人查看则在指定主管中选择相应的人员和要查看的部门
30:多页签切换事件
panel_componentShown //事件。当页签切换时间。调用这方法 this.kDTabbedPane1.setSelectedIndex(0); //指定显示第一个页签
31:通过实体获取表名
MetaDataLoaderFactory.getRemoteMetaDataLoader().getEntity(info.getId().getType()).getTable();
32:table空白行也保存
kdtable.getRow(i).setChange(true);
33:组织切换(app下代码处理)
OrgSwitchFacadeFactory.getLocalInstance(ctx).orgSwitch(company.getId().toString());
34:禁用分录按钮(添加,删除,插入)
/** * 禁用分录按钮 * @param table */ public static void disableHMDEntryButtons(KDTable table) { if (table.getParent() == null || table.getParent().getParent() == null) return; // 隐藏按钮 Component c = table.getParent().getParent(); if (c instanceof DetailPanel) { JPanel panel = (JPanel) c; JPanel controlPanel = null; // 获得controlPanel Component[] components = panel.getComponents(); for (int i = 0; i < components.length; i++) { Component component = components[i]; if ("controlPanel".equals(component.getName())) { controlPanel = (KDPanel) component; } } // 获得btn if (controlPanel != null) { components = controlPanel.getComponents(); for (int j = 0; j < components.length; j++) { Component component = components[j]; if (component instanceof KDWorkButton) { KDWorkButton workButton = (KDWorkButton) component; workButton.setEnabled(false); } } } } } } final KDTable kddetailTable=getDetailTable(); Container con =kddetailTable.getParent().getParent(); if (con instanceof DetailPanel) { DetailPanel detail =(DetailPanel)con; KDWorkButton btnadd= detail.getAddNewLineButton();
35:系统的组织隔离
FilterInfo otherFilter = com.kingdee.eas.framework.FrameWorkUtils.getF7FilterInfoByAuthorizedOrg(com.kingdee.eas.basedata.org.OrgType.getEnum("Admin"),"OrgUnit.id",true);
36:获取记账委托组织
IOrgUnitRelation iOrgUnitRelation = OrgUnitRelationFactory.getLocalInstance(ctx); iOrgUnitRelation.getToUnit(storageOrgUnit1.getId().toString(), OrgType.STORAGE_VALUE, OrgType.COMPANY_VALUE);
37:F7多选并保存数据
-
设置F7开户多选功能,F7.setEnabledMultiSelection(true);
-
除了F7本身字段以外,再添加两个文本字段,F7Name(用于ListUI查询用),F7ID(用于保存多选值),F7自身是不保存数据值的
-
在F7_dataChanged方法里把F7多选到的值分别赋值到F7Name,F7ID中,例:
protected void f7_dataChanged( com.kingdee.bos.ctrl.swing.event.DataChangeEvent e) { Object[] F7cols = (Object[]) e.getNewValue(); if (null == F7cols) { txtF7Name.setText(null); txtF7ID.setText(null); SysUtil.abort(); } StringBuilder f7id = new StringBuilder(); StringBuilder f7Name = new StringBuilder(); for (int i = 0; i < F7cols.length; i++) { OperationTypeInfo info = (OperationTypeInfo) kOperationType[i]; String idString = info.getId().toString();// 业务类别 operationTypeid.append(idString).append(";"); operationTypeName.append(info.getNumber()).append("-").append(info.getName()).append(";"); } String operationTypeidValue = operationTypeid.toString(); if (!StringUtils.isEmpty(operationTypeidValue)) { operationTypeidValue = operationTypeidValue.substring(0, operationTypeidValue.length() - 1); txtF7ID.setText(operationTypeidValue); } String operationTypeNameValue = operationTypeName.toString(); if (!StringUtils.isEmpty(operationTypeNameValue)) { operationTypeNameValue = operationTypeNameValue.substring( 0, operationTypeNameValue.length() - 1); txtF7Name.setText(operationTypeNameValue); } }
-
在数据加载的时候,把数据通过ID再解析出来赋值给F7字段 一定要先super.loadFields,再设计f7字段为多选功能,否则这里保存出来的值是内存地址
public void loadFields() { // 加载 super.loadFields(); f7.setEnabledMultiSelection(true); String operationTypeID = editData.getOperationTypeID(); if (!StringUtils.isEmpty(operationTypeID)) { String[] operationType = operationTypeID.split(";"); StringBuilder sbBuilder = new StringBuilder(); EntityViewInfo evi = new EntityViewInfo(); // 创建实体视图 FilterInfo f = new FilterInfo();// 创建过滤对象 for (int i = 0; i < operationType.length; i++) { FilterItemInfo filter1 = new FilterItemInfo("id", operationType[i], CompareType.EQUALS); f.getFilterItems().add(filter1);// 将过滤条件添加到过滤对象中 sbBuilder.append("#").append(i).append(" ").append("or "); } String maskString = sbBuilder.toString(); if (!StringUtils.isEmpty(maskString)) { maskString = maskString.substring(0, maskString.length() - 3); f.setMaskString(maskString); evi.setFilter(f);// 设置实体视图的过滤器 try { IOperationType instance = OperationTypeFactory.getRemoteInstance(); OperationTypeCollection collection = instance.getOperationTypeCollection(evi); int size = collection.size(); Object[] infoObjects=new Object[size]; for (int i = 0; i < size; i++) { infoObjects[i]=collection.get(i); } f7.setData(infoObjects); } catch (BOSException e) { e.printStackTrace(); } } }
38:通过人员获取职位
PositionInfo getPositionByPerson(Context ctx,PersonInfo info)throws EASBizException, BOSException { EntityViewInfo view = new EntityViewInfo(); SelectorItemCollection sic = new SelectorItemCollection(); sic.add(new SelectorItemInfo("id")); sic.add(new SelectorItemInfo("person.id")); sic.add(new SelectorItemInfo("person.name")); sic.add(new SelectorItemInfo("person.number")); sic.add(new SelectorItemInfo("position.id")); sic.add(new SelectorItemInfo("position.number")); sic.add(new SelectorItemInfo("position.name")); sic.add(new SelectorItemInfo("position.job.id")); sic.add(new SelectorItemInfo("position.job.number")); sic.add(new SelectorItemInfo("position.job.name")); view.setSelector(sic); FilterInfo filter = new FilterInfo(); filter.getFilterItems().add(new FilterItemInfo("person.id", info.getId() + "")); filter.getFilterItems().add(new FilterItemInfo("isPrimary", new Integer(1))); view.setFilter(filter); PositionMemberCollection col = PositionMemberFactory.getLocalInstance(ctx).getPositionMemberCollection(view); if ((col != null) && (col.size() > 0) && (col.get(0) != null)) { return col.get(0).getPosition(); } return null; }
39:通过用户获取对应组织是否有对应名称权限
boolean flag=false; BOSUuid userId=SysContext.getSysContext().getCurrentUserInfo().getId(); BOSUuid orgId=SysContext.getSysContext().getCurrentOrgUnit().getId(); ObjectUuidPK userPK = new ObjectUuidPK(userId); ObjectUuidPK orgPK = new ObjectUuidPK(orgId); com.kingdee.eas.base.permission.IPermission perm= null; //获取权限 try { perm =PermissionFactory.getRemoteInstance(); flag=perm.hasFunctionPermission(userPK, orgPK, "权限名称"); } catch (Exception e1) { e1.printStackTrace(); }
40:在有分录的单据ListUI中,点击“关联生成”后,可不可以实现选中一条记录就生成包含所有分录的目标单据?
如果想根据单据头做botp转换,需要自己在单据的序时簿代码中添加 相关的代码设置,代码参考:
public void actionCreateTo_actionPerformed(ActionEvent e) throws Exception { setDAPTrans(true); super.actionCreateTo_actionPerformed(e); setDAPTrans(false); }
41:用业务建模工具新定义的单据如何跟权限管理集成起来?
新定义的单据,在没有做权限管理之前,是不受权限控制的。 将新单据跟权限管理集成起来,大致分为三个步骤:
-
【工具】>【权限管理】,在此界面定义单据所在的目录及给单据设置各种权限项(查看、新增、修改、删除、审核等)。如果没有新建某种权限项,则默认此种权限项不受控制,是可以在任何情况下 使用的。-----这只是加了权限项,但是并没有应用到单据中。
-
要应用到单据中,必须在主菜单管理中给业务单元加上相应的权限项,然 后发布,这是设计期要做的工作。
-
在运行期时,通过administrator登录,在“用户管理”里同步权限项?分配相应的权限即可
42:单据和基础资料是如何做组织隔离的及其他
假如BIM中定义了一个主业务组织是采购组织的单据,那么: 序时簿的过滤:
-
首先到用户的组织范围中查询用户有哪些组织的权限;
-
再找出用户的组织范围中的组织有哪些是采购组织; (例如用户的组织范围中可能有A、B、C三个组织,但是A是财务组织,B、C是采购组织,那么必 须把A给过滤掉);
-
功能权限的过滤,看看用户对当前单据有没有查看的权限
-
看看筛选出来的B和C这两个采购组织是不是实体,如果不是采购组织实体,那么也必须过滤掉; 编辑界面的过滤:
-
用户设置了单据的主业务组织是采购组织,则在单据的界面上应该动态加一个F7类型的字段“采购组 织”
-
该“采购组织”必须是必录的、可修改的
-
该"采购组织"的过滤条件参照序时簿的条件1、2、4
43:指定单据业务属性(即主业务组织)有什么意义?体现在哪里?##
指定当前单据的业务属性可以控制当前登录用户的访问权限,比如,单据Test的业务属性为库存组织,当前登录用户的组织范围有采购组织,财务组织,行政组织,由于此用户没有库存组织的权限,所以访问不到这个单据。
44:知道一个OrgUnitInfo,如何获取此info下面的子OrgUnitInfo?##
找OrgUnitInfo的长编码字段longNumber,他们是由!隔开的,这里可以找到所有ou的编码信息。
45:在程序中给F7增加过滤参数,发现有组织隔离的F7,比如养户档案,得到F7的Filter后增加一个FilterItemInfo条件,调试的时候没有看到我加的条件,只看到了框架做的组织隔离的条件?(适用于序时簿的过滤)##
重载方法:
protected FilterInfo getDefaultFilterForQuery() { FilterInfo info =super.getDefaultFilterForQuery(); FilterInfo info1 = new FilterInfo(); info.merge(info1,"AND"); }
45:做过组织隔离的F7进行再过滤在实现类构造函数里添加如下代码(适用于编辑界面)##
EntityViewInfo evInfo = new EntityViewInfo(); FilterInfo filter = new FilterInfo(); filter.getFilterItems.add("",""); // 加用户的过滤项 evInfo.setFilter(filter); F7PromptControl.setEntityViewInfo(evInfo);
46:getCurrentFIUnit()和getCurrentOrgUnit()之间的区别?##
如果我当前登录的组织是库存组织, getCurrentFIUnit()是不是就会找当前组织的上一级财务组织单元?其他的 getCurrentCtrlUnit(), getCurrentAdminUnit(), getCurrentCostUnit()等是否也是这个原理?
getCurrentFIUnit
就是取当前财务组织,一般用于财务类型的单据; getCurrentOrgUnit
是取当前的业务组织,适用于所有单据; getCurrentFIUnit()
是指去当前登录用户所对应的财务组织; 同理:getCurrentCtrlUnit()、getCurrentAdminUnit()、getCurrentCostUnit()
分别指当前用户所切换组织所对应的CU,行政组织,成本组织。
47:如何在BIM中添加图片##
在业务单元定义界面增加一个标签类型字段,如为:TestImage
,则对应的标签控件名为:lblTestImage
,再如业务单元名为:TestBill
,则在TestBillEditUI.java
中的的构造函数中的Super()语句下添加
public TestBillEditUI() throws Exception { super(); this.lblTestImage.setIcon(new javax.swing.ImageIcon("E:\Images\testimage.jpg")); }
下面为完整Demo
public class SingleEnrollEditUI extends AbstractSingleEnrollEditUI { private static final long serialVersionUID = 1525974852523168246L; private static final Logger logger = CoreUIObject .getLogger(SingleEnrollEditUI.class); PhotoPanel pPanel = new PhotoPanel(); private boolean existPhoto; /** * output class constructor */ public SingleBillEditUI() throws Exception { super(); pPanel = new PhotoPanel(); existPhoto = false; isSave = false; } // 存储照片 private void storePhotoFile() throws Exception { if ((pPanel.getSelectFile() != null && pPanel.getSelectImageBytes() != null) || pPanel.getSelectImage() != null) { editData.setImageData(pPanel.getSelectImageBytes()); } else if (existPhoto) { if (pPanel.getSelectImage() != null) { editData.setImageData(pPanel.getSelectImageBytes()); } else { editData.setImageData(null); } } } public void loadFields() { super.loadFields(); pPanel.setOprtStat(getOprtState()); try { this.loadImage();// 加载图片 } catch (Exception e) { e.printStackTrace(); } } // 初始化图片显示区 private void initPhotoPanel() { pPanel.setOprtStat("ADD"); pPanel.setBounds(627, 117, 169, 150); photoPanel.add(pPanel); } // 在非新增状态下加载已经存储的图片 public void loadImage() throws IOException, BOSException { ISingleBill irentVehicle = SingleBillFactory.getRemoteInstance(); SingleBillInfo rentVehicleInfo = null; try { rentVehicleInfo = irentVehicle .getSingleBillInfo("select imageData where id =" + "'" + this.editData.getId() + "'"); if (!rentVehicleInfo.isEmpty()) { if (rentVehicleInfo.getImageData() != null) { byte[] byteArray = rentVehicleInfo.getImageData(); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( byteArray); BufferedImage bufferedImage = ImageIO .read(byteArrayInputStream); pPanel.setSelectImage(bufferedImage); byteArrayInputStream.close(); pPanel.repaint(); } } } catch (ObjectNotFoundException e) { MsgBox.showInfo("照片不存在"); SysUtil.abort(); } catch (EASBizException e) { e.printStackTrace(); } } public void onShow() throws Exception { // ((JFrame) getUIWindow()).setExtendedState(JFrame.MAXIMIZED_BOTH); photoPanel.setLayout(null); photoPanel.add(pPanel); pPanel.setBounds(0, 0, 109, 152); super.onShow(); } } byte[] bys = (byte[]) list.get(44); BufferedImage image = ImageIO .read(new ByteArrayInputStream(bys)); pPanel.setSelectImage(image); pPanel.repaint();
48:获取当前窗口的工作状态(新增、修改或查看)##
getOprtState().equals(OprtState.ADDNEW);
49:在listui 中,有个小数字段,我在EDITUI中录入0时,保存后在LISTUI中显示为空,而不是0,请问怎么让他显示出来?##
请重载listui
里的getQueryExecutor()
方法,然后在语句“super.getQueryExecutor();”后面加上exec.option().isAutoIgnoreZero = false; 用来设置0不转换为空。
protected IQueryExecutor getQueryExecutor(IMetaDataPK queryPK, EntityViewInfo viewInfo) { IQueryExecutor executor= super.getQueryExecutor(queryPK, viewInfo); executor.option().isAutoIgnoreZero=false; return executor; }
50:我想让一个EditUI的分录不能新增行,已经把新增行的按钮什么的都去掉了,但在分录的最后一列按回车,table还是会自动新增一行。请问怎么屏蔽掉?##
你在屏蔽“新增分录”那个按钮的同时, 调用屏蔽table的自动新增行语句disableAutoAddLine();
使之不能自动新增行
51:多分录单据如何刷新editData?##
调用loadData();
52:如果我想通过代码取物料中的“多计量单位”的记录,请问怎么实现?##
String materialID = "";//物料ID EntityViewInfo view = new EntityViewInfo(); FilterInfo filter = new FilterInfo(); filter.getFilterItems().add(new FilterItemInfo("material.id",materialID)); view.setFilter(filter); MultiMeasureUnitCollection units = MultiMeasureUnitFactory.getRemoteInstance().getCollection(view);
53:oracle 外键查询语句##
只需要把红色的文字换成相应的要查找的表名就可以了
select oc.name as "CONSTRAINT_NAME", o.name as "TABLE_NAME", o1.name as "R_TABLE_NAME" from sys.con$ oc, sys.con$ rc, sys.obj$ o, sys.cdef$ c, sys.obj$ o1, sys.cdef$ c1 where oc.con# = c.con# and c.obj# = o.obj# and c.rcon# = rc.con#(+) and o.owner# = userenv('SCHEMAID') and c.type# = 4 and rc.con# = c1.con# and c1.obj# = o1.obj# and c1.type# = 2 and o1.name = 'tableName.toUpperCase()'
54:单据经过审批以后,需要把审核人写到单据里,应该怎么做##
在单据对应的实体里加上方法auditBill(ctx,model),然后在单据生成的对应的controlBean类中在方法auditBill里加上写审核人的代码,如:
protected void _auditBill(Context ctx, IObjectValue model) throws BOSException { // TODO 自动生成方法存根 //super._auditBill(ctx, model); PurReqInfo purReqInfo = null ; // 进行值对象转化 purReqInfo = (PurReqInfo)model; // 获取当前日期 Date currentDate = new Date(); // 获取用户信息 UserInfo currentUser = (UserInfo) ctx.get(SysContextConstant.USERINFO); // 设置审核人 purReqInfo.setAuditor(currentUser); // 设置单据状态 // purReqInfo.setState(PurOrderType.Excute); // purReqInfo.setBizDate(currentDate); // 更新单据 try { update(ctx, new ObjectUuidPK(purReqInfo.getId()),purReqInfo); } catch (EASBizException e) { // TODO 自动生成 catch 块 e.printStackTrace(); } catch (BOSException e) { // TODO 自动生成 catch 块 e.printStackTrace(); } }
55:请问分录是如何过滤的##
分录的过滤,需要在过滤语句前设置它的分录类型和名字, 格式如下:
filter.setEntryType(EntryFilterType.NORMAL); filter.setEntryName("xxx")
ps:xxx是分录的名字
56: 通过编号更新EAS用户密码##
protected String _updatePassword(Context ctx, String number, String oldPwd, String newPwd) throws BOSException { IUser instance = UserFactory.getLocalInstance(ctx); UserCollection collection = instance.getUserCollection("where number='"+number+"'"); if (collection.size()>0) { UserInfo userInfo = collection.get(0); try { String strOldPwd = CryptoTean.encrypt(userInfo.getNumber(), oldPwd); String strNewPwd = CryptoTean.encrypt(userInfo.getNumber(), newPwd); IObjectPK iObjectPK = new ObjectUuidPK(userInfo.getId().toString()); instance.updatePass(iObjectPK, strOldPwd, strNewPwd); return "0000|update password is Success."; } catch (CryptException e) { e.printStackTrace(); return "0003|"+e.toString(); } catch (EASBizException e) { e.printStackTrace(); return "0001|"+e.toString(); } }else { return "9999|number not found user info."; } }
57:分录添加默认值##
protected IObjectValue createNewDetailData(KDTable table) { BizContractPayPlanEntryInfo info = new BizContractPayPlanEntryInfo(); info.setAmount(BigDecimal.ZERO); return info; }
58:获取当前在线用户数##
本文介绍的是在FacadeControllerBean也就是服务端获取的方法,GUI层面获取的方法在UserMonitorUI.class里已有代码,请自行查看;
UMRegistryCollection regs = null; try { ILoginModule loginModule = LoginModuleFactory.getLocalInstance(ctx); String encodePwd = CryptoTean.encrypt("EAS用户名", "密码"); //获取一个用户登录的上下文对象 LoginContext loginContext = new LoginContext("EAS用户名", encodePwd, ctx.getSolution(), ctx.getAIS(), ctx.getLocale()); loginContext.put("dbType", "Oracle"); loginContext.put("UserAuthPattern", "BaseDB"); try { String sessionId = loginModule.login(loginContext); ctx = SessionManager.getInstance().getSession(sessionId).getContext(); } catch (BOSLoginException e) { e.printStackTrace(); throw new BOSException(e.getMessage()); } regs = ((UMRegistryCollection) UserMonitorFactory.getLocalInstance(ctx).getCollectionUsingOrgRange( DataCenterName)); } catch (Exception e1) { e1.printStackTrace(); } int total = regs.size(); //这个就是总用户数了,如果要区分出哪些是GUI哪些是PORTAL的,可自行去UserMonitorUIj里看相关代码 ;
59:根据职员获取职位和职称##
PositionInfo getPositionByPerson(Context ctx,PersonInfo info)throws EASBizException, BOSException { EntityViewInfo view = new EntityViewInfo(); SelectorItemCollection sic = new SelectorItemCollection(); sic.add(new SelectorItemInfo("id")); sic.add(new SelectorItemInfo("person.id")); sic.add(new SelectorItemInfo("person.name")); sic.add(new SelectorItemInfo("person.number")); sic.add(new SelectorItemInfo("position.id")); sic.add(new SelectorItemInfo("position.number")); sic.add(new SelectorItemInfo("position.name")); sic.add(new SelectorItemInfo("position.job.id")); sic.add(new SelectorItemInfo("position.job.number")); sic.add(new SelectorItemInfo("position.job.name")); view.setSelector(sic); FilterInfo filter = new FilterInfo(); filter.getFilterItems().add(new FilterItemInfo("person.id", info.getId() + "")); filter.getFilterItems().add(new FilterItemInfo("isPrimary", new Integer(1))); view.setFilter(filter); PositionMemberCollection col = PositionMemberFactory.getLocalInstance(ctx).getPositionMemberCollection(view); if ((col != null) && (col.size() > 0) && (col.get(0) != null)) { return col.get(0).getPosition(); } return null; }
60:KDTable 表达式应用工具类##
/** * 给单元格添加sum表达式 * @param cell * @param from * @param to */ public static void setCellSumExpr(ICell cell, int from, int to) { cell.setExpressions(getSumExpr(from, to)); } /** * 给单元格添加IF表达式 * @param cell * @param condExpr * @param expr1 * @param expr2 */ public static void setCellIFExpr(ICell cell,String condExpr,String expr1,String expr2){ cell.setExpressions(getIFExpr(condExpr, expr1, expr2)); } /** * 给单元格添加Add表达式 * @param cell * @param a * @param b */ public static void setCellAddExpr(ICell cell,int a,int b){ cell.setExpressions(getAddExpr(a, b)); } /** * 给单元格添加Add表达式,允许不连续区域求和 * @param cell * @param range */ public static void setCellAddRangeExpr(ICell cell,int[] range){ cell.setExpressions(getAddRangeExpr(range)); } /** * 给单元格添加Substract表达式 * @param cell * @param a * @param b */ public static void setCellSubExpr(ICell cell,int a,int b){ cell.setExpressions(getSubExpr(a, b)); } // return =sum(from:to); public static String getSumExpr(int from, int to) { StringBuffer buff = new StringBuffer(); buff.append("=SUM(").append(getExcelColumnLabel(from)); buff.append(":").append(getExcelColumnLabel(to)); buff.append(")"); return buff.toString().intern(); } // return =a+b public static String getAddExpr(int a, int b) { StringBuffer buff = new StringBuffer(); buff.append("=").append(getExcelColumnLabel(a)); buff.append("+").append(getExcelColumnLabel(b)); return buff.toString().intern(); } // return =range[0]+range[1]+...+range[n] public static String getAddRangeExpr(int[] range) { StringBuffer buff = new StringBuffer(); buff.append("="); boolean flag = false; for (int i = 0, n = range.length; i < n; i++) { if (flag) { buff.append("+"); } buff.append(getExcelColumnLabel(range[i])); flag = true; } return buff.toString().intern(); } // return =a-b public static String getSubExpr(int a, int b) { StringBuffer buff = new StringBuffer(); buff.append("=").append(getExcelColumnLabel(a)); buff.append("-").append(getExcelColumnLabel(b)); return buff.toString().intern(); } // retur =IF(condExpr,expr1,expr2); public static String getIFExpr(String condExpr, String expr1, String expr2) { StringBuffer buff = new StringBuffer(); buff.append("=IF(").append(condExpr).append(","); buff.append(expr1).append(",").append(expr2); buff.append(")"); return buff.toString(); } /** 根据列的的位置获取列标,如A、AA、AB...采用类似进制转换的算法 */ public static String getExcelColumnLabel(int colCount) { String rs = ""; do { colCount--; rs = ((char) (colCount % 26 + (int) 'A')) + rs; colCount = (int) ((colCount - colCount % 26) / 26); } while (colCount > 0); return rs; } /** 根据列标获取列的索引,采用类似进制转换的算法 */ public static int getExcelColumnIndex(String colName) { if (colName == null || colName.equals("")) { return -1; } colName = colName.toUpperCase(); int count = -1; char[] cs = colName.toCharArray(); for (int i = 0; i < cs.length; i++) { count += (cs[i] - 64) * Math.pow(26, cs.length - 1 - i); } return count; }
61:客户F7 物料F7 左树右表##
prmtCustomer.setQueryInfo("com.kingdee.eas.basedata.master.cssp.app.F7CustomerQuery"); F7BaseSelector selector = new F7CustomerSimpleSelector(this, prmtCustomer); prmtCustomer.setSelector(selector); //-------- public void getMaterialF7ForReportFilterUI(KDBizPromptBox kDBizPromptBoxMaterial) throws Exception { GeneralKDPromptSelectorAdaptor selectorLisenterMaterial = null; MaterialGroupInfo info = new MaterialGroupInfo(); selectorLisenterMaterial = new GeneralKDPromptSelectorAdaptor(kDBizPromptBoxMaterial, new F7MaterialTreeListUI(), this, info.getBOSType().toString(), "com.kingdee.eas.basedata.master.material.app.F7MaterialInventoryQuery", "materialGroup.id", false); selectorLisenterMaterial.setIsMultiSelect(false); selectorLisenterMaterial.setQueryProperty("helpCode", "or"); kDBizPromptBoxMaterial.setSelector(selectorLisenterMaterial); kDBizPromptBoxMaterial.addSelectorListener(selectorLisenterMaterial); // kDBizPromptBoxMaterial.setQueryInfo("com.kingdee.eas.basedata.master.material.app.F7MaterialInventoryNoGroupQuery"); } /** * 描述:获得客户F7<用于表头客户F7> * @param prmtPromptBox F7控件 * @param queryInfo QueryInfo * @param owner 所有者 * @param orgType 组织类型 */ public static void getBizCustomerF7(KDBizPromptBox prmtPromptBox, String queryInfo, Component owner, OrgType orgType) { OrgUnitInfo orgInfo = SysContext.getSysContext().getCurrentOrgUnit(orgType); SCMGroupClientUtils.setBizCustomerF7(prmtPromptBox, owner, orgType, queryInfo); SCMGroupClientUtils.setApproved4CustomerF7(prmtPromptBox, orgType); prmtPromptBox.setCurrentMainBizOrgUnit(orgInfo, orgType); } /** * 描述:获得物料F7<用于表头物料F7> * @param prmtPromptBox F7控件 * @param queryInfo QueryInfo * @param owner 所有者 * @param orgType 组织类型 * @throws BOSException */ public static void getBizMaterialF7(KDBizPromptBox prmtPromptBox, String queryInfo, Component owner, OrgType orgType, boolean isMulSelect) throws BOSException { OrgUnitInfo orgUnit = SysContext.getSysContext().getCurrentOrgUnit(orgType); SCMGroupClientUtils.setBizMaterialF7(prmtPromptBox, owner, orgType, isMulSelect, queryInfo); SCMGroupClientUtils.setApproved4MaterialF7(prmtPromptBox, orgType); prmtPromptBox.setCurrentMainBizOrgUnit(orgUnit, orgType); } //Query 设置为null,会根据组织类型查询Query SLClientUtils.getBizCustomerF7(prmtCustomer, "com.kingdee.eas.basedata.master.cssp.app.F7CustomerQuery", this, OrgType.Sale); SLClientUtils.getBizMaterialF7(prmtMaterial, null, this, OrgType.Sale, false);
62:EAS BOS 服务端直接调用BOTP
参数说明:
-
ctx :服务端上下文
-
srcBosType:源单据的BosType
-
destBosType:目标单据的BosType
-
srcBillCollection:源单据集合,可以批量转换
-
botpPK:要使用的BOTP的PK。 可以通过表T_BOT_Mapping查找到id,将id转换成PK。 select t.fid from T_BOT_Mapping t where t.fname='',是botp的名称。
public static void generateDestBill(Context ctx, String srcBosType, String destBosType, CoreBillBaseCollection srcBillCollection, IObjectPK botpPK) throws Exception { IBOTMapping botMapping = BOTMappingFactory.getLocalInstance(ctx); CoreBillBaseInfo billInfo = srcBillCollection.get(0); BOTMappingInfo botMappingInfo = botMapping.getMapping(billInfo, destBosType, DefineSysEnum.BTP); if (botMappingInfo == null) { throw new FMException(FMException.NODESTBILL); } IBTPManager iBTPManager = BTPManagerFactory.getLocalInstance(ctx); BTPTransformResult btpResult = null; /*String[] ids = new String[srcBillCollection.size()]; for (int i = 0; i < srcBillCollection.size(); ++i) { CoreBaseInfo info = srcBillCollection.get(i); ids[i] = info.getId().toString(); }*/ btpResult = iBTPManager.transformForBotp(srcBillCollection,destBosType, botpPK); IObjectCollection destBillCols = btpResult.getBills(); BOTRelationCollection botRelationCols = btpResult.getBOTRelationCollection(); for (int i = 0; i < destBillCols.size(); i++) { CoreBillBaseInfo destBillInfo = (CoreBillBaseInfo) destBillCols.getObject(i); iBTPManager.submitRelations(destBillInfo, botRelationCols); } }
63:进度条(没有百分比)##
LongTimeDialog dialog = new LongTimeDialog((Frame) SwingUtilities .getWindowAncestor(this)); dialog.setLongTimeTask(new ILongTimeTask() { public Object exec() throws Exception { Object obj = "12345"; // 进度条期间的操作 MeterProcureTrackReportUI.this.queryData(); return obj; } public void afterExec(Object result) throws Exception { } }); Component[] cps=dialog.getContentPane().getComponents(); for(Component cp:cps){ if(cp instanceof JLabel){ ((JLabel) cp).setText("数据查询中......."); } } dialog.show(); int count = this.kdtreport.getRowCount(); if (count < 1) { MsgBox.showInfo("没有找到相关记录!"); }
64:手动保存botp关系##
private void _saveBOTPRelationShip(Context ctx, EntRepaymentBillInfo entRepaymentBillInfo, IObjectPK pk) throws BOSException { botpRelationShip.clear(); botpRelationShip.put(entRepaymentBillInfo.getLoanBillID().getId().toString(), pk.toString()); FMHelper.saveBOTRelation(ctx, botpRelationShip); }
botpRelationShip是map。key=原单据id,value=目标单据id
65: F7专用选择界面的设置
public void setF7Selector() throws Exception { KDBizPromptBox bizPromptBox = new KDBizPromptBox();// 要绑定的F7控件 CoreUIObject ui = null;// 父界面对象 CompanyOrgUnitInfo companyInfo = null; // 当前财务组织 // 客户 bizPromptBox.setSelector(new GeneralKDPromptSelectorAdaptor(bizPromptBox, new F7CustomerTreeDetailListUI(), ui)); // 供应商 bizPromptBox.setSelector(new GeneralKDPromptSelectorAdaptor(bizPromptBox, new F7SupplierTreeDetailListUI(), ui)); // 物料 bizPromptBox.setSelector(new GeneralKDPromptSelectorAdaptor(bizPromptBox, new F7MaterialTreeListUI(), ui)); // 职员 HashMap map = new HashMap(); map.put(PersonF7UI.ALL_ADMIN, "YES"); bizPromptBox.setSelector(new PersonPromptBox(ui, map)); // 公司 CompanyF7 org = new CompanyF7(ui); org.setRootUnitID(""); bizPromptBox.setSelector(new CompanyF7(ui)); // 成本中心 bizPromptBox.setSelector(new CostCenterF7(ui)); // 行政组织 bizPromptBox.setSelector(new AdminF7(ui)); // 采购组织 bizPromptBox.setSelector(new PurchaseF7(ui)); // 库存组织 bizPromptBox.setSelector(new StorageF7(ui)); // 销售组织 bizPromptBox.setSelector(new SaleF7(ui)); // 利润中心组织 bizPromptBox.setSelector(new ProfitCenterF7(ui)); // 利润中心组织 bizPromptBox.setSelector(new ProfitCenterF7(ui)); // 科目 bizPromptBox.setSelector(new AccountPromptBox(ui, companyInfo, new FilterInfo())); }
66:手工发送消息##
//以下是发送一个消息的核心片断,如果针对的是某组织批量发送,自己的需要取得组织的用户ID集合,然后构造receiver SenderAgent senderAgent = SenderAgent.getSenderAgent(); Message message; Locale[] lcla = getContextLocales(ctx);//获取ctx的语言信息列表 Locale locale = null; message = MessageFactory.newMessage("kingdee.workflow");//生成一个消息对象 for (int j = 0, m = lcla.length; j < m; j++) { //此处循环进行多语言消息的设置 locale = lcla[j]; message.setLocaleStringHeader("title","标题", locale);//设置消息标题 message.setLocaleStringHeader("sender","发送人" , locale);//设置发送人,属于文本,不是ID message.setLocaleStringHeader("body", "消息体内容",Locale);//设置消息体内容,根据具体业务自己设定 } message.setIntHeader("type", MsgType.NOTICE_VALUE);//设置消息类型为通知 message.setIntHeader("bizType", MsgBizType.WORKFLOW_VALUE);//业务类型设置为工作流 message.setIntHeader("sourceStatus", MsgSourceStatus.EMPTY_VALUE);//设置任务状态,此处是通知消息,所以设置空 message.setIntHeader("priority", MsgPriority.MIDDLE_VALUE);//设置消息优先级,自己根据需要设定相应的级别 message.setStringHeader("databaseCenter", ctx.getAIS());//得到数据中心 message.setStringHeader("solution", ctx.getSolution());//设置解决方案 message.setStringHeader("receiver", '4ff9eebb-0108-1000-e000-15acc0a813c813B7DE7F;4ff9eebb-0108-1000-e000-1db0c0a813c813B7DE7F'); //设置接收者,后面那参数是用户ID,多个ID可用分号";"分割 senderAgent.sendMessage(message); //发送消息 /** * 获取ctx的语言信息列表 * * @param ctx * @return */ public static Locale[] getContextLocales(Context ctx) { Locale[] locales = null; SolutionInfo solu = MetaDataLoaderFactory.getLocalMetaDataLoader(ctx) .getSolution(); if (solu != null) { LanguageCollection langs = solu.getLanguages(); if (langs != null) { locales = new Locale[langs.size()]; for (int i = 0; i < langs.size(); i++) { locales[i] = langs.get(i).getLocale(); } } } return locales; }
67:EAS KDTABLE 虚模式分页##
/** * 描述:批次加载数据 * @param e */ protected void kdtTable_doRequestRowSet(RequestRowSetEvent e) { int start = ((Integer) e.getParam1()).intValue(); int length = (((Integer) e.getParam2()).intValue() - start) + 1; try { queryExecutor.setObjectView(getDefaultEntityView()); com.kingdee.jdbc.rowset.IRowSet rowSet = queryExecutor.executeQuery(start, length); e.setRowSet(rowSet); } catch (Exception exc) { ExceptionHandler.handle(exc); } } //虚模式分页 table.getDataRequestManager().setDataRequestMode(KDTDataRequestManager.VIRTUAL_MODE_PAGE);
68:KDSpinner控件选择年##
Calendar cal = Calendar.getInstance(); Integer year = cal.get(Calendar.YEAR); Integer min = new Integer(2002); Integer max = new Integer(9999); Integer step = new Integer(1); SpinnerNumberModel model = new SpinnerNumberModel(year, min, max, step); txtYear.setModel(model);
69:KDTable常用代码##
设置表格为自动宽度
int columnCount = tblMain.getColumnCount(); for (int i = 0; i < columnCount; i++) { KDTableHelper.autoFitColumnWidth(tblMain, i); }
如何使得KDTable支持多行文本的显示:
只需要给KDTable的列设置一个多行显示的属性即可。设置的方法: col.getStyleAttributes().setWrapText(true);
如何设置KDTable向下键自动新增行
KDTableHelper里面的方法
/** * 在table的最后一行按下箭头自动新增行。 * * @param table * @param isAddRow * 是否自动新增行 * @param actionAfterAddRow * 新增行后将触发的事件 */ public static void downArrowAutoAddRow(KDTabletable, boolean isAddRow, Action actionAfterAddRow)
如何设置KDTableTab键和Enter键自动新增行
KDTableHelper的这个方法可以满足这个需求:
/** * 修改Enter键的行为使它于Tab一致 * * @param table * @param isAddRow * 焦点到了最后一行,再次按下enter和tab是否自动增加新行 * @param actionAfterAddRow * 添加新行后的事件 */ public static void updateEnterWithTab(KDTabletable, boolean isAddRow, Action actionAfterAddRow)
如何调整KDTable的Tab键和enter键的行为
-
KDTable默认情况下Tab键和Enter键分别起到单元格选择调整的作用,Tab键跳到右侧单元格,Enter键跳到下方的单元格。
-
KDTableHelper提供了一些方法用于修改Enter键和Tab键的行为。
-
KDTableHelper.releaseEnter:释放Enter键,即KDTable将不响应Enter键。
-
KDTableHelper.releaseTab:释放Tab键,即KDTable将不响应Tab键。
-
KDTableHelper.releaseEnterAndTab:释放Tab和Enter键。
KDTable如何根据内容自动调整行高列宽
双击KDTable的两行(或者列)之间的边线,将会根据内容自动调整行高(列宽)。
通过调用KDTableHelper的autoFitRowHeight和autoFitColumnWidth这两个方法也可以调整行高列宽。计算行高和列宽需要结合字体、Graphics上下文,是比较耗时的,应有时需要注意。
KDTable的排序要如何实现
KDTable的排序都是由KDTSortManager来实现的。分为实模式和虚模式两种应用模式。
虚模式:排序的具体实现由外部通过继承并重写KDTSortManager的sort方法来实现。例如ListUI的就是重写了这个sort方法,在这个方法中清楚KDTable中的数据,然后刷新KDTable,用新的排序方式重新向服务端取数。
KDTSortManager sm = new KDTSortManager(table) { public void sort(int colIndex, int sortType) { // 一定要调用super.sort,这句代码将影响表头排序箭头的显示效果 super.sort(colIndex, sortType); if (sortType == KDTSortManager.SORT_ASCEND) { // 升序 } else { // 降序 } } };
复制代码
实模式:KDTSortManager内置了实模式下的排序方式,不需要重写sort方法即可实现实模式的排序,当然,你也可以重写sort方法来实现自己的排序逻辑。
KDTSortManager sm = new KDTSortManager(table) sm.setSortAuto(true);
KDTable中如何调整行高列宽
有些时候,KDTable中单元格的文本内容过长,单元格显示不下,需要调整行高或者列宽,通过鼠标双击行或者列的边框线,KDTable会自动调整行高或者列宽到合适位置。
如果想要通过代码在后台调整行高列宽到合适位置,下面的方法分别对应行高、列宽、表头行高:
KDTableHelper的autoFitRowHeight、autoFitColumnWidth、autoFitHeadRowHeight
由于计算合适行高列宽,需要结合当前Graphics以及字体等信息进行计算,这个动作是相对比较耗时的,因此这些方法要结合实际情况使用,大数据量下使用这些方法,将可能导致性能问题。
KDTable部分数据导出到excel后显示格式不一致
这种问题一般是由于没有给KDTable设置正确的格式导致的。主要分为一下几类:
-
由数字组成的长字符串导出excel后显示为科学计数法或字符串显示不完整,例如手机号13433445678。
解决办法:给KDTable的列设置格式串(col.getStyleAttributes().setNumberFormat("@")),指定该列为字符型即可。
-
数字位过多的大数字导出excel后显示为科学计数法或精度丢失。
解决办法:给KDTable的列设置格式串(col.getStyleAttributes().setNumberFormat("0.00"))。这里的0.00只是示例,数字格式还有很多种,具体可以参考前面显示格式的介绍。
-
日期类型数据导出excel后显示格式不正确。
解决办法:给KDTable的列设置格式串(col.getStyleAttributes().setNumberFormat("yyyy-MM-dd"))。这里的yyyy-MM-dd只是示例,日期格式还有很多种,具体可以参考前面显示格式的介绍
如何控制KDTable的显示格式
KDTable提供了格式化的功能,通过格式化的功能可以控制单元格的显示格式,设置列格式的方法:table.getColumn(colIndex).getStyleAttributes().setNumberFormat(formatString);
目前KDTable已能支持Excel2003的格式串,只有个缺陷:格式串中有中文导出尚有问题,中文变乱码, 建议将来都使用Excel2003的格式串,但旧的格式化串还支持,但是如果该表需要导出到excel,必须使用新的格式串,否则导出到excel,可能会显示不一致。
文本类:
@
指定内容按文本显示,主要用于编码、手机号等用数字表示的文本。设定该格式后,可以保证导出excel时,此类文本不会被转成数字显示。
数值类:
-
0.00 表示两位小数,例如3.10367显示为3.10
-
0.## 表示两位小数,当小数末位为0时,0将不显示。例如3.10显示为3.1
-
#,##0.00
表示两位小数,且显示千份位 -
#,##0.00;[Red]#,##0.00
表示负数红字 -
0.00;[Red]0.00;" "
表示负数红字,且数据为0时不显示 -
0.00;[Red](0.00);" "
表示正数时两位小数,负数时两位小数并显示红色,0时不显示。0.00;[Red](0.00)
只是一个示例,可以为任意的数字格式串,后边再加上;" "(空格)即表示数据为0时不显示。
日期类:
-
yyyy-m-d
-
yyyy-MM-dd
-
yyyy-MM-dd hh:mm:ss
-
yyyy年MM月dd日
百分比:
-
0%
-
0.00%
…… 详细请打开Excel2003,单元格右键,设置单元格格式,选一种格式,点自定义即可看到该格式的格式串;有的Excel格式串后有带”_”,在使用时,必须去掉。
如何理解KDTable的Render和Editor
Render即为绘制器,KDTable的每个单元格都是对应的绘制器绘制出来的,例如文本绘制器将进行文本的绘制,CheckBox绘制器将在单元格绘制CheckBox的样子,图片绘制器将在单元格绘制图片等。
Editor 即为编辑器,当单元格进入编辑状态后,会在单元格的位置显示编辑器,通过编辑器可以修改单元格的值。在同一时刻,只能有一个单元格进入编辑状态。
进入编辑状态的方法有:
-
双击或者单击某个单元格,有些编辑器是双击以后再进入,有些编辑器是单击后进入;
-
选中某个单元格,按F2可以进入编辑器;
-
选中某个单元格,按下编辑器能接受的按键,例如文本编辑器可以接受任意可见字符,checkbox可以接受空格键作为切换选择的键,按下这些键后,单元格也将进入编辑状态。
结束编辑的方法有:
-
在编辑器中按下Enter键或者Tab键;
-
在编辑状态下点击表格的其他单元格;
-
表格控件失去焦点。在编辑状态下按下Esc键将取消编辑。
结束编辑和取消编辑的区别在于,结束编辑时会将单元格的值修改为编辑器的值,取消编辑器将保持单元格的旧值。
如何在取数之后,调整KDTable单元格的内容或者显示格式
table. addKDTDataFillListener这个事件将在取数事件之后被调用,在这个事件当中,取数事件获取的数据已经填充到KDTable当中,可以直接获取KDTable的行及单元格进行操作。DataFillListener和取数事件是一一对应的,取数事件调用一次则 DataFillListener将被调用一次,而且DataFillListener的事件参数中的起始行和结束行也是和取数事件的参数一致的。需要注意的是在DataFillListener中只能访问事件参数中的起始行和结束行范围的行,千万不要在这个事件里访问table的所有行,因为如果在这里访问不在事件参数范围内的行,可能导致再次触发取数事件。
如何通过代码控制KDTable新增行
方法一:
//增行 EmpEnrollBizBillEntryInfoentry=newEmpEnrollBizBillEntryInfo();//创建分录的实体 entry.setEmpName(name);//设置实体属性 entry.setIDCardNo(id); editData.getEntrys().add(entry);//将实体新增到editData的实体列表中。 loadFields();//重新加载分录信息
方法二:
//增行 addLine(kdtEntries); IRownewRow=kdtEntries.getRow(kdtEntries.getRowCount()-1);//获取新增的行对象 //设置分录的实体 newRow.setUserObject(newReceivingBillEntryInfo()); //设置分录实体的属性 newRow.getCell("Band").setValue(obei.getBand());//品牌 newRow.getCell("ProductSeries").setValue(obei.getProductSeries());//产品线 newRow.getCell("Period").setValue(obei.getPeriod());//期数
70:采购入库单BOTP生成应付单控制是否反写成本##
//重写BillWriteOff类中的calculateWriteOffDiffAmt方法。 package com.kingdee.eas.scm.cal.app.calculate; import com.kingdee.eas.scm.cal.app.calculate.model.BillWrittenOffData; import com.kingdee.eas.scm.cal.app.calculate.model.CalculateWrittenOffEntry; public class BillWriteOff extends AbstractBillWriteOff { public BillWrittenOffData calculateWriteOffDiffAmt(CalculateWrittenOffEntry bill, CalculateWrittenOffEntry standardBill, boolean isDevolve) { bill.setNeedRetWriteUnitCost(false); BillWrittenOffData diffAmt = super.calculateWriteOffDiffAmt(bill, standardBill, isDevolve); return diffAmt; }
71:报表添加合计行和每行合计##
//fieldSumList.add(Number)//number 表示名列 //这样合计行在表尾,如果需要合计行在数据行下面,只需要把合计行当数据处理,添另一列即可 private void appendFootRow(KDTable table, List fieldSumList) { Map columnMap = new HashMap(); columnMap.clear(); KDTable tableSum = table; for (int j = 0; j < fieldSumList.size(); ++j) { String Number = (String) fieldSumList.get(j); if (Number != null) { BigDecimal dbSum = new BigDecimal("0"); for (int r = 0; r < tableSum.getRowCount(); ++r) { if (tableSum.getRow(r).getStyleAttributes().isHided()) { continue; } ICell cell = tableSum.getRow(r).getCell(Number); String cellValue = tableSum.getCellDisplayText(cell); if (cellValue != null) { cellValue = cellValue.toString().replaceAll(",", ""); } if (!StringUtility.isNumber(cellValue)) { Object cellObj = cell.getValue(); if (cellObj != null) cellValue = cellObj.toString(); if (!StringUtility.isNumber(cellValue)) { continue; } } BigDecimal bigdem = new BigDecimal(String .valueOf(cellValue).trim()); dbSum = dbSum.add(bigdem); } String strSum = dbSum.toString(); columnMap.put(Number, strSum); } } if (columnMap.size() > 0) { IRow footRow = null; //这里通过 tableSum.addRow(); 获取,然后在 注释粉红色代码 添加 footRow.getCell(0).setValue(total); KDTFootManager footRowManager = tableSum.getFootManager(); if (footRowManager == null) { footRowManager = new KDTFootManager(tableSum); footRowManager.addFootView(); tableSum.setFootManager(footRowManager); } footRow = footRowManager.getFootRow(0); if (footRow == null) { // 这里条件可以去掉 String colFormat = "%{#,###.##########}f"; int colIndex = -1; footRow = footRowManager.addFootRow(0); String total = EASResource .getString("com.kingdee.eas.framework.FrameWorkResource.Msg_Total"); tableSum.getIndexColumn().setWidthAdjustMode((short) 1); tableSum.getIndexColumn().setWidth(30); footRowManager.addIndexText(0, total); footRow.getCell(0).setValue(total); footRow.getStyleAttributes().setBackground( new Color(246, 246, 191)); footRow.getStyleAttributes().setNumberFormat(colFormat); footRow.getStyleAttributes().setHorizontalAlign( Styles.HorizontalAlignment.getAlignment("right")); footRow.getStyleAttributes().setFontColor(Color.BLACK); } Iterator valueIterator = columnMap.entrySet().iterator(); while (valueIterator.hasNext()) { Map.Entry colEntry = (Map.Entry) valueIterator.next(); String colIndex = (String) colEntry.getKey(); String colValue = (String) colEntry.getValue(); footRow.getCell(colIndex).setValue(colValue); } } } public static void appendTotal(KDTable table) { Map columnMap = new HashMap(); int rowCount = table.getRowCount(); KDTColumns columns = table.getColumns(); for (int i = 0; i <rowCount ; i++) { BigDecimal dbSum = new BigDecimal("0"); for (int j = 0; j < columns.size(); j++) { KDTColumn column = columns.getColumn(j); String fieldName = column.getKey(); if (fieldName.startsWith("F")) { ICell cell = table.getRow(i).getCell(fieldName); String cellValue = table.getCellDisplayText(cell); if (cellValue != null) { cellValue = cellValue.toString().replaceAll(",", ""); } if (!StringUtility.isNumber(cellValue)) { Object cellObj = cell.getValue(); if (cellObj != null) cellValue = cellObj.toString(); if (!StringUtility.isNumber(cellValue)) { continue; } } BigDecimal bigdem = new BigDecimal(String .valueOf(cellValue).trim()); dbSum = dbSum.add(bigdem); } } String strSum = dbSum.toString(); columnMap.put(i, strSum); } Iterator valueIterator = columnMap.entrySet().iterator(); while (valueIterator.hasNext()) { Map.Entry colEntry = (Map.Entry) valueIterator.next(); Integer rowIndex = (Integer) colEntry.getKey(); String colValue = (String) colEntry.getValue(); table.getCell(rowIndex, "Total").setValue(colValue); }
72:bean根据编码规则获取编号##
if(mmsi.getNumber()==null){ ICodingRuleManager iCodingRuleManager = null; iCodingRuleManager = CodingRuleManagerFactory.getLocalInstance(arg0); String orgUnitID = ContextUtil.getCurrentOrgUnit(arg0).getId().toString(); if(iCodingRuleManager.isExist(mmsi, orgUnitID)){ if(iCodingRuleManager.isUseIntermitNumber(mmsi, orgUnitID) ){ //编码规则不允许断号 --> 获取断号编码 mmsi.setNumber(iCodingRuleManager.getNonbreakNumber(mmsi,orgUnitID)); }else{ mmsi.setNumber(iCodingRuleManager.getNumber(mmsi,orgUnitID)); } } }
73:F7多选择保存##
EAS BOS F7控件实现多选择并保存
-
设置F7开户多选功能,F7.setEnabledMultiSelection(true);
-
除了F7本身字段以外,再添加两个文本字段,F7Name(用于ListUI查询用),F7ID(用于保存多选值),F7自身是不保存数据值的
-
在F7_dataChanged方法里把F7多选到的值分别赋值到F7Name,F7ID中,例:
protected void f7_dataChanged( com.kingdee.bos.ctrl.swing.event.DataChangeEvent e) { Object[] F7cols = (Object[]) e.getNewValue(); //Object data = kDLabelExpenseType.getData(); 这样也可以获取到数据, //Object[] F7cols = (Object[])data; if (null == F7cols) { txtF7Name.setText(null); txtF7ID.setText(null); SysUtil.abort(); } StringBuilder f7id = new StringBuilder(); StringBuilder f7Name = new StringBuilder(); for (int i = 0; i < F7cols.length; i++) { OperationTypeInfo info = (OperationTypeInfo) kOperationType[i]; String idString = info.getId().toString();// 业务类别 operationTypeid.append(idString).append(";"); operationTypeName.append(info.getNumber()).append("-").append(info.getName()).append(";"); } String operationTypeidValue = operationTypeid.toString(); if (!StringUtils.isEmpty(operationTypeidValue)) { operationTypeidValue = operationTypeidValue.substring(0, operationTypeidValue.length() - 1); txtF7ID.setText(operationTypeidValue); } String operationTypeNameValue = operationTypeName.toString(); if (!StringUtils.isEmpty(operationTypeNameValue)) { operationTypeNameValue = operationTypeNameValue.substring( 0, operationTypeNameValue.length() - 1); txtF7Name.setText(operationTypeNameValue); } }
4.在数据加载的时候,把数据通过ID再解析出来赋值给F7字段 一定要先super.loadFields
,再设计f7字段为多选功能,否则这里保存出来的值是内存地址
public void loadFields() { // 加载 super.loadFields(); f7.setEnabledMultiSelection(true); String operationTypeID = editData.getOperationTypeID(); if (!StringUtils.isEmpty(operationTypeID)) { String[] operationType = operationTypeID.split(";"); StringBuilder sbBuilder = new StringBuilder(); EntityViewInfo evi = new EntityViewInfo(); // 创建实体视图 FilterInfo f = new FilterInfo();// 创建过滤对象 for (int i = 0; i < operationType.length; i++) { FilterItemInfo filter1 = new FilterItemInfo("id", operationType[i], CompareType.EQUALS); f.getFilterItems().add(filter1);// 将过滤条件添加到过滤对象中 sbBuilder.append("#").append(i).append(" ").append("or "); } String maskString = sbBuilder.toString(); if (!StringUtils.isEmpty(maskString)) { maskString = maskString.substring(0, maskString.length() - 3); f.setMaskString(maskString); evi.setFilter(f);// 设置实体视图的过滤器 try { IOperationType instance = OperationTypeFactory.getRemoteInstance(); OperationTypeCollection collection = instance.getOperationTypeCollection(evi); int size = collection.size(); Object[] infoObjects=new Object[size]; for (int i = 0; i < size; i++) { infoObjects[i]=collection.get(i); } f7.setData(infoObjects); } catch (BOSException e) { e.printStackTrace(); } } }
74:如何通过代码将query数据进行查询数据
IMetaDataPK queryPK = new MetaDataPK("com.kingdee.eas.gzw.basedata.app.CentralCorpobyOrgQuery"); IQueryExecutor queryExcutor = QueryExecutorFactory.getRemoteInstance(queryPK); //设置过滤条件 queryExcutor.setObjectView(viewInfo); //查询出所有满足条件的集合; IRowSet rows=queryExcutor.executeQuery();
75:手动刷新EditUI##
if(editData.getId() != null){ com.kingdee.bos.dao.IObjectPK iObjectPk = new ObjectUuidPK(editData.getId()); editData = ((IOtherReceivable)getBizInterface()).getOtherReceivableInfo(iObjectPk, getSelectors()); setDataObject(editData); loadFields(); loadData(); }
76:EAS系统日志及说明##
客户端日志
-
记录最近一次EAS的运行日志,会记录系统运行的详细情况和出现的异常信息。每次启动客户端会删除原有的内容(开发分析问题需提供)。
$EAS_HOME\client\logs\client.log
-
EAS运行日志,类似client.log。会保存历史日志,另外还有可控制日志详细程度。受client/deploy/client/log4j.properties控制,需要专业人士协助配置。
$EAS_HOME\client\logs\log4j.log
-
log4j.log的历史记录,每天记录一个。
$EAS_HOME\client\logs\log4j.log.*
-
记录自动更新日志,会保存历史记录。
$EAS_HOME\client/logs/autoupdate.log
服务端日志
-
记录了应用服务器启动和运行日志,包括异常信息等。
$EAS_HOME\eas\server\profiles\server1\logs\apusic.log.0
-
记录的是管理控制台的服务器端日志
$EAS_HOME\eas\admin\logs\admin.log
-
记录的是管理控制台客户端的日志
$EAS_HOME\eas\admin\logs\admin_client.log
-
记录的是权限日志
$EAS_HOME\eas\server\profiles\server1\logs\PermissionTrace.log
-
记录的是botp日志
$EAS_HOME\server\profiles\serverXXX\logs\botpTrace.log
77:在分录上添加按钮##
/** * 在KDTable添加button * @param table * @param button */ public static void addButtonToHMDEntry(KDTable table, KDWorkButton button) { if (table.getParent() == null || table.getParent().getParent() == null) return; // 隐藏按钮 Component c = table.getParent().getParent(); if (c instanceof DetailPanel) { JPanel panel = (JPanel) c; JPanel controlPanel = null; // 获取controlPanel Component[] components = panel.getComponents(); for (int i = 0; i < components.length; i++) { Component component = components[i]; if ("controlPanel".equals(component.getName())) { controlPanel = (KDPanel) component; } } // 添加btn if (controlPanel != null) { controlPanel.add(button, new com.kingdee.bos.ctrl.swing.KDLayout.Constraints(table.getWidth()-140, 5, button.getWidth(), 19, 9));// 9=1+8上右固定,左边缩放 } } } //调用方法 public void onLoad() throws Exception { super.onLoad(); addButtonToHMDEntry(getDetailTable(), btnAudit); }
78:在APP下调用存储过程##
--新建存储过程-Oracle create or replace procedure proc_invperiodclose ( projectorg in varchar2 default '' , projectid in varchar2 default '' , periodid in varchar2 default '' , lastperiodid in varchar2 default '' ) as begin --清空缓存表 DELETE FROM tempTable; end proc_invperiodclose;
//关键代码 public static Map<String, String> executeStoredProcedure(Context ctx,String proc, String[] params, String[] paramNames, String[] outParamNames) throws BOSException { Connection conn = null; CallableStatement cstmt = null; ResultSet rs = null; Map map = null; try { try { conn =EJBFactory.getConnection(ctx); } catch (Exception e) { e.printStackTrace(); } cstmt = conn.prepareCall(proc); for (int i = 0; i < params.length; ++i){ cstmt.setString(paramNames[i], params[i]); } for (int i = 0; i < outParamNames.length; ++i){ cstmt.registerOutParameter(outParamNames[i], 12); } cstmt.execute(); map = new HashMap(); for (int i = 0; i < outParamNames.length; ++i) { map.put(outParamNames[i], cstmt.getString(outParamNames[i])); } } catch (SQLException exc) { StringBuffer sb = new StringBuffer(""); for (int i = 0; i < params.length; ++i) sb.append("param ").append(i).append(" is:").append(params[i]); throw new BOSException("Sql execute exception : " + proc, exc); } finally { com.kingdee.util.db.SQLUtils.cleanup(rs, cstmt, conn); } return map; } //系统调用代码 String[] params=new String[]{projectOrg,project,period,lastperiodid}; String[] paramNames=new String[]{"projectorg","projectid","periodid","lastperiodid"}; DBUtils.executeStoredProcedure(ctx, "{call proc_invperiodclose(?,?,?,?)}",params , paramNames, new String[]{});
完整的 DBUtils.java可参考 code\Demo Code\DBUtils.java
79:删除已发布流程脚本##
注: 1、以下代码需一条一条分步执行执行
2、JKSZLP-0001为发布到流程模版表单编码,请对应修改
3、此语句会删除已经起草的审批流程,请慎用!
--1、删除处理过的工作流任务 select * from T_WFR_AssignDetail where fbizobjid in (select fid from CT_WFB_JSKZLP-0001) delete from T_WFR_AssignDetail where fbizobjid in (select fid from CT_WFB_JSKZLP-0001) --2.查看工作流任务 select * from T_WFR_Assign where fbizobjid in (select fid from CT_WFB_JSKZLP-0001) delete from T_WFR_Assign where fbizobjid in (select fid from CT_WFB_JSKZLP-0001) --3.删除工作流实例 select * from T_WFR_ProcInst where fprocdefname_l2 like '%JSKZLP-0001%' delete from T_WFR_ProcInst where fprocdefname_l2 like '%JSKZLP-0001%' --4.删除所有流程单据 select * from CT_WFB_JSKZLP-0001 drop table CT_WFB_JSKZLP-0001 --5.删除流程模板 select * from t_bas_template where fnumber = 'JSKZLP-0001' delete from T_BAS_Template where fnumber = 'JSKZLP-0001'
80:二次开发的目录在子系统树中没有正确显示##
1、保证服务器目录eas/servser/properties/下的文件subsystem_bos.xml文件中有二次开发的路径;
2、保证服务器元数据目录eas/server/metas以及eas\server\deploy\fileserver.ear\easWebClient\metas目录下的所有元数据包中只有一份.mdbview文件,且存在与metas/bos/mdbview-metas.jar中,其他jar中的.mdbview文件如果存在,建议将其删除;(具体方法:可以使用类似winrar的压缩工具查找功能,在metas目录下搜索*.mdbview文件)
3、如果服务器eas\server\profiles\server1\config\subsystem目录下存在*.mdbview文件(如果目录不存在,则此步骤忽略),建议确认是否有人在“系统平台-参数配置-子系统树管理”里面有修改过子系统树配置?如果不确定,可以现将该目录下的mdbview文件,备份至其他目录,此目录下文件都清空。
4、重新生成子系统树
81:EAS查询大数据量中断问题##
--中断信息: Caused exception message is: fetched too much rows, cell number exceeding limit 1000000. fetched column count:20. fected row count:50000. fected cell count:1000000 [Client -- String Serialize]
解决方法:
1、停止服务器
2、关闭EAS管理控制台
3、eas服务器安装目录eas\admin\config下有个admin.vmoptions文件
需要修改该文件的exceptionCellNumber参数,由原来的1000000改成8000000(因现场需要调整)
4、启动eas管理控制台
5、启动服务
常用零碎代码##
-
金额大写函数:
GlUtils.getChineseFormat(amount, true)
-
获取界面参数:
String uiParam=context.get("UIClassParam").toString();
-
抛出业务基类异常:
throw new EASBizException(new NumericExceptionSubItem("0003", "单据已提交或已审核,无法删除"));
-
获取 datacenters.xml中的密码:
String passwd = com.kingdee.bos.sql.KSqlUtil.decodePassword("ksqle:J8CQQm9M5Q4UaPELUb1V8EXq+ObMhjzN");
-
Client执行SQL:
SQLExecutorFactory.getRemoteInstance(sql.toString()).executeSQL();
app执行SQL:DbUtil.execute(ctx, sql, new Object[] { map.get("remain"), map.get("id") });
6.BOTP 写SQL取值方法(如果值为对象,需要再调用函数[__BOTgetObjectFromID()
]):公式结果 = #sql_val("select fname_l2 from t_pm_user where fnumber='daidai'");
获取当前会计期间:
CompanyOrgUnitInfo currentFIUnit = ContextUtil.getCurrentFIUnit(ctx); PeriodInfo currentPeriod = SystemStatusCtrolUtils.getCurrentPeriod(ctx, SystemEnum.GENERALLEDGER, currentFIUnit);
获取当前期间上一期间
//获取上一期间 PeriodInfo prePeriodInfo = PeriodUtils.getPrePeriodInfo(ctx, new ObjectUuidPK(periodPk));
-
根据bosType获取对应的表:
String tableName = FMIsqlFacadeFactory.getLocalInstance(ctx).getTableNameByBosType(bosType);
-
组织隔离:
FilterInfo otherFilter = com.kingdee.eas.framework.FrameWorkUtils.getF7FilterInfoByAuthorizedOrg(com.kingdee.eas.basedata.org.OrgType.getEnum("Admin"),"OrgUnit.id",true);
-
中断方法:
SysUtil.abort();