用友uap nc65開發-使用自定義公式解決參照多顯問題
1.場景描述:在項目開發中,收費清單存在多房産且該字段為參照,在資料庫中存在多個pk值且以逗号隔開,但在界面無法顯示,在前面部落格中已使用另外一種方法解決,但對于資料量大的單據無法處理,會導緻當機。 2.解決思路:使用自定義顯示公式,傳入參照的表名,pk,name,對應行的pk_head,通過代碼處理,将參照對應的pk在對應表中查出對應的name值,并使用逗号分割顯示在界面。 3.在home\resources\formulaconfig\custfunction目錄下建立一個xml檔案配置公式,如圖所示:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiclRnblN0LclHdpZXYyd2LcBzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX9sGRNRzZq5UNFpXTmZEWjZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DM3YjNxYzMxETMxcDM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
xml檔案配置如下:
<?xml version="1.0" encoding="utf-8"?>
<formula-array>
<formula>
<customType>0</customType>
<functionName>MultiRefName</functionName>
<functionClass>nc.itf.fdc_pr.formula.MultiRefNameFormula</functionClass>
</formula>
</formula-array>
其中functionClass對應公式支援的java類,functionName對應公式顯示名稱。
4.MultiRefNameFormula代碼支援類如下:
package nc.itf.fdc_pr.formula;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
import nc.bs.framework.common.NCLocator;
import nc.itf.fdc_crmbd.IH3H045Maintain;
import nc.vo.pub.formulaset.IFormulaConstant;
import nc.vo.pub.formulaset.core.ParseException;
import nc.vo.pub.formulaset.function.PostfixMathCommand;
/**
*
* @author lqh
*
*/
public class MultiRefNameFormula extends PostfixMathCommand{
public MultiRefNameFormula() {
numberOfParameters = 4;//參數數量
functionType = IFormulaConstant.FUN_CUSTOM;//公式類型
functionDesc = "根據傳進來的多選參照主鍵傳出參照顯示名稱";//公式描述
}
@Override
/**
* Stack 棧取資料的順序和存資料的順序相反(FILO先進後出)
* 是以要用反序指派
*/
public void run(Stack s) throws ParseException {
checkStack(s);
String tableName = (String) s.pop();//表名
String pkFieldName = (String) s.pop();//主鍵字段名
/**
* 傳進來的是一個list,其中的每一個String對應一行資料
* 是以傳回也要傳回一個List,對應每一行資料
*/
ArrayList<String> pks = (ArrayList<String>) s.pop();//每一行的主鍵
String nameFieldName = (String) s.pop();//要擷取的字段名
List<String> names = getRefName(tableName, pkFieldName, pks.toArray(new String[0]), nameFieldName);
// for (int i = 0 ; i < pks.size() ; i ++){
// String pk = pks.get(i);
// if (pk != null){
// String name = getRefName(tableName,pkFieldName,pk.split(","),nameFieldName);
// names.add(name);
// }else{
// names.add(null);
// }
// }
s.push(names);
}
private List<String> getRefName(String tableName, String pkFieldName, String[] pks, String nameFieldName) {
IH3H045Maintain maintain = NCLocator.getInstance().lookup(IH3H045Maintain.class);
String[] names = maintain.queryRefName(tableName, pkFieldName, pks, nameFieldName);
return Arrays.asList(names);
}
}
重要代碼方法在類中已經标記。
public String[] queryRefName(String tableName, String pkFieldName,
String[] pks, String nameFieldName) {
if (tableName == null || pks == null || pks.length == 0) {
return null;
}
String[] names = new String[pks.length];
if (pkFieldName == null) {
pkFieldName = "pk_head";
}
if (nameFieldName == null) {
nameFieldName = "name";
}
BaseDAO dao = new BaseDAO();
StringBuilder sql = new StringBuilder();
for (int i = 0; i < pks.length; i++) {
sql.setLength(0);
sql.append("select ");
sql.append(nameFieldName);
sql.append(" from ");
sql.append(tableName);
sql.append(" where ");
sql.append(pkFieldName);
sql.append(" in ( '1' ");
int j = 0;
if (pks[i] == null){
names[i] = null;
continue;
}
for (String str : pks[i].split(",")) {
if (str != null) {
sql.append(",'").append(str).append("'");
j++;
if (j == 300) {
sql.append(") or pk_head in ( '1' ");
}
}
}
sql.append(")");
try {
String name = (String) dao.executeQuery(sql.toString(),
new ResultSetProcessor() {
/**
*
*/
private static final long serialVersionUID = -4527998249487262608L;
@Override
public Object handleResultSet(ResultSet rs)
throws SQLException {
StringBuffer name = new StringBuffer();
while (rs != null && rs.next()) {
name.append(rs.getString(1)).append(",");
}
if (name.length() != 0) {
name.deleteCharAt(name.lastIndexOf(","));
return name.toString();
}
return null;
}
});
names[i] = name;
} catch (DAOException e) {
ExceptionUtils.wrappBusinessException("查詢資料庫錯誤:"
+ e.getMessage());
}
}
return names;
}
5.重新開機伺服器,清理緩存,打開單據模版初始化節點,我們使用另外一個字段來實作該多參照名字,在該字段中配置顯示公式: temp->getcolvalue( fdc_pr_bill,pk_allhouses,pk_head ,pk_head );
multirefname( "name",temp,"pk_head" ,"fdc_crmbd_fangchanzhubiao") 先在收費清單表中查出對應行的房産pk值賦給temp,後調用我們寫的自定義公式,将值傳入。
6.結果如下: