概要:

我们在做项目的时候,经常会遇到一个问题:

一个选择List字段的可选项被另一个选择List制约,这种情况如何在后台取得这两者的对应关系。

原文在这里(侵删):

Apexで連動項目の選択肢を取得する方法 - Qiita

Apexで連動項目の選択肢を取得する方法(改善版) - Qiita

之前第一个博文看不懂,看了第二个之后才明白大概原理。

所以才有了这篇随笔:

·Example.apxc
public class Example {
private static String INITIAL_VALUE = '';
// 選択リストで選択された値が格納される変数
public SomeObject objectInstance {get; set;} public List<SelectOption> DependentPickListOptions{
get{
List<SelectOption> options = new List<SelectOption>(); // 選択リストの一番上にデフォルトの選択値を設定
options.add(new SelectOption(INITIAL_VALUE, '-- なし --')); // 制御項目ctrlPicklistが選択されている時に連動項目depPicklistで選べる選択肢を取得する。
if( this.objectInstance.ctrlPicklist != null || this.objectInstance.ctrlPicklist != INITIAL_VALUE ){
List<DepPickListCtrl.TPicklistEntry> tPicklistEntries =
DepPickListCtrl.GetDependentOptions('SomeObject','ctrlPicklist','depPicklist').get(this.objectInstance.ctrlPicklist); for( DepPickListCtrl.TPicklistEntry e : tPicklistEntries ){
options.add(new SelectOption(e.value, e.label));
}
}
return options;
}
} // コンストラクタ
public Example(){
this.objectInstance = new SomeObject();
}
}

这个部分,相信大部分人都能查看文档弄清楚。

最关键的下面这个方法(GetDependentOptions):DepPickListCtrl.apxc

/* Reference
* Great thanks to Neel
* http://titancronus.com/blog/2014/05/01/salesforce-acquiring-dependent-picklists-in-apex/
*/ public class DepPickListCtrl {
public static Map<String,List<DepPickListCtrl.TPicklistEntry>> GetDependentOptions(String pObjName, String pControllingFieldName, String pDependentFieldName){
Map<String,List<DepPickListCtrl.TPicklistEntry>> objResults = new Map<String,List<DepPickListCtrl.TPicklistEntry>>();
//get the string to sobject global map
// 拿到Schema命名空间的描述
  Map<String,Schema.SObjectType> objGlobalMap = Schema.getGlobalDescribe();
if (!objGlobalMap.containsKey(pObjName))
return objResults;
//get the type being dealt with
Schema.SObjectType pType = objGlobalMap.get(pObjName);
Map<String, Schema.SObjectField> objFieldMap = pType.getDescribe().fields.getMap();
//verify field names
if (!objFieldMap.containsKey(pControllingFieldName) || !objFieldMap.containsKey(pDependentFieldName))
return objResults;
//get the control values
// 拿到控制的选择List选项对应关系
List<Schema.PicklistEntry> ctrl_ple = objFieldMap.get(pControllingFieldName).getDescribe().getPicklistValues();
//get the dependent values
// 拿到被控制的List选项对应关系
List<Schema.PicklistEntry> dep_ple = objFieldMap.get(pDependentFieldName).getDescribe().getPicklistValues();
//iterate through the values and get the ones valid for the controlling field name
// 这个Validfor我实在不知道是干嘛的。官方文档上也没找打,但是这个值很重要
DepPickListCtrl.DependentValidFor dvf=new DepPickListCtrl.DependentValidFor(); //set up the results
for(Integer pControllingIndex=0; pControllingIndex<ctrl_ple.size(); pControllingIndex++){
//get the pointer to the entry
Schema.PicklistEntry ctrl_entry = ctrl_ple[pControllingIndex];
//get the label
String pControllingLabel = ctrl_entry.getLabel();
//create the entry with the label
objResults.put(pControllingLabel,new List<DepPickListCtrl.TPicklistEntry>());
}
//cater for null and empty
objResults.put('',new List<DepPickListCtrl.TPicklistEntry>());
objResults.put(null,new List<DepPickListCtrl.TPicklistEntry>());
//check the dependent values
for(Integer pDependentIndex=0; pDependentIndex<dep_ple.size(); pDependentIndex++){
//get the pointer to the dependent index
Schema.PicklistEntry dep_entry = dep_ple[pDependentIndex];
//get the valid for
// 不转换成Json,你是拿不到validfor这个值的
String pEntryStructure = JSON.serialize(dep_entry);
DepPickListCtrl.TPicklistEntry objDepPLE = (DepPickListCtrl.TPicklistEntry)JSON.deserialize(pEntryStructure, DepPickListCtrl.TPicklistEntry.class);
//if valid for is empty, skip
if (objDepPLE.validFor==null || objDepPLE.validFor==''){
continue;
}
//iterate through the controlling values
// 【getControlIndexes】这个方法就是取得被控制选择List选项的Index的方法
// 实现原理看在下面
for(Integer idx : dvf.getControlIndexes(objDepPLE.validFor)){
//get the label
String pControllingValue = ctrl_ple[idx].getValue();
objResults.get(pControllingValue).add(objDepPLE);
}
}
return objResults;
}
public class TPicklistEntry{
public string active {get;set;}
public string defaultValue {get;set;}
public string label {get;set;}
public string value {get;set;}
public string validFor {get;set;}
public TPicklistEntry(){
}
}
private class DependentValidFor {
private Map<String,Set<Integer>> mapValidForIndexes=new Map<String,Set<Integer>>();
public Set<Integer> getControlIndexes(String validFor){
if(mapValidForIndexes.containsKey(validFor))
return mapValidForIndexes.get(validFor);
// 将validfor从Base64转化成16进制格式
// 对,也就是说,validfor是Base64格式的数据
// 而官方只提供了转化成16进制格式的方法(convertToHex),这样才将validfor变为可读数据
String hex=EncodingUtil.convertToHex(EncodingUtil.base64Decode(validFor));
Set<Integer> result=new Set<Integer>();
// 循环遍历16进制数的每一位
for(Integer i=0; i<hex.length(); i++){
String b=hex.substring(i, i+1);
Integer off=i*4;
// 每一位都当成二进制数据
switch on b { //0123(index)
when '0'{ //0000
}
// 第一次循环时i=0

// 当0010的时候,意味着被控制选择List的选项的Index2的选项是可选的
// 当0100的时候,意味着被控制选择List的选项的Index3的选项是可选的
// 。。。。

// 也就是说决定那个Index的选项可选不是看值的大小,
// 而是看值的位置,1处在那个位置上,index几就是可选项。
// 因为每一个16进制数可以表示n~n+4(index),
// 所以当i+1时,index就是从n+4开始的,
// 例子: i=0时,“f” → 0,1,2,3
// 例子: i=1时, “f” → 4,5,6,7
// 所以off每次都要*4
when '1'{ //0001
result.add(off+3);
}

when '2'{ //0010
result.add(off+2);
}
when '3'{ //0011
result.add(off+2);
result.add(off+3);
}
when '4'{ //0100
result.add(off+1);
}
when '5'{ //0101
result.add(off+1);
result.add(off+3);
}
when '6'{ //0110
result.add(off+1);
result.add(off+2);
}
when '7'{ //0111
result.add(off+1);
result.add(off+2);
result.add(off+3);
}
when '8'{ //1000
result.add(off+0);
}
when '9'{ //1001
result.add(off+0);
result.add(off+3);
}
when 'a'{ //1010
result.add(off+0);
result.add(off+2);
}
when 'b'{ //1011
result.add(off+0);
result.add(off+2);
result.add(off+3);
}
when 'c'{ //1100
result.add(off+0);
result.add(off+1);
}
when 'd'{ //1101
result.add(off+0);
result.add(off+1);
result.add(off+3);
}
when 'e'{ //1110
result.add(off+0);
result.add(off+1);
result.add(off+2);
}
when 'f'{ //1111
result.add(off+0);
result.add(off+1);
result.add(off+2);
result.add(off+3);
}
}
}
mapValidForIndexes.put(validFor,result);
return result;
}
}
}

  

DepPickListCtrl.apxc
 
/* Reference
* Great thanks to Neel
* http://titancronus.com/blog/2014/05/01/salesforce-acquiring-dependent-picklists-in-apex/
*/ public class DepPickListCtrl {
public static Map<String,List<DepPickListCtrl.TPicklistEntry>> GetDependentOptions(String pObjName, String pControllingFieldName, String pDependentFieldName){
Map<String,List<DepPickListCtrl.TPicklistEntry>> objResults = new Map<String,List<DepPickListCtrl.TPicklistEntry>>();
//get the string to sobject global map
Map<String,Schema.SObjectType> objGlobalMap = Schema.getGlobalDescribe();
if (!objGlobalMap.containsKey(pObjName))
return objResults;
//get the type being dealt with
Schema.SObjectType pType = objGlobalMap.get(pObjName);
Map<String, Schema.SObjectField> objFieldMap = pType.getDescribe().fields.getMap();
//verify field names
if (!objFieldMap.containsKey(pControllingFieldName) || !objFieldMap.containsKey(pDependentFieldName))
return objResults;
//get the control values
List<Schema.PicklistEntry> ctrl_ple = objFieldMap.get(pControllingFieldName).getDescribe().getPicklistValues();
//get the dependent values
List<Schema.PicklistEntry> dep_ple = objFieldMap.get(pDependentFieldName).getDescribe().getPicklistValues();
//iterate through the values and get the ones valid for the controlling field name
DepPickListCtrl.DependentValidFor dvf=new DepPickListCtrl.DependentValidFor(); //set up the results
for(Integer pControllingIndex=0; pControllingIndex<ctrl_ple.size(); pControllingIndex++){
//get the pointer to the entry
Schema.PicklistEntry ctrl_entry = ctrl_ple[pControllingIndex];
//get the label
String pControllingLabel = ctrl_entry.getLabel();
//create the entry with the label
objResults.put(pControllingLabel,new List<DepPickListCtrl.TPicklistEntry>());
}
//cater for null and empty
objResults.put('',new List<DepPickListCtrl.TPicklistEntry>());
objResults.put(null,new List<DepPickListCtrl.TPicklistEntry>());
//check the dependent values
for(Integer pDependentIndex=0; pDependentIndex<dep_ple.size(); pDependentIndex++){
//get the pointer to the dependent index
Schema.PicklistEntry dep_entry = dep_ple[pDependentIndex];
//get the valid for
String pEntryStructure = JSON.serialize(dep_entry);
DepPickListCtrl.TPicklistEntry objDepPLE = (DepPickListCtrl.TPicklistEntry)JSON.deserialize(pEntryStructure, DepPickListCtrl.TPicklistEntry.class);
//if valid for is empty, skip
if (objDepPLE.validFor==null || objDepPLE.validFor==''){
continue;
}
//iterate through the controlling values
for(Integer idx : dvf.getControlIndexes(objDepPLE.validFor)){
//get the label
String pControllingValue = ctrl_ple[idx].getValue();
objResults.get(pControllingValue).add(objDepPLE);
}
}
return objResults;
}
public class TPicklistEntry{
public string active {get;set;}
public string defaultValue {get;set;}
public string label {get;set;}
public string value {get;set;}
public string validFor {get;set;}
public TPicklistEntry(){
}
}
private class DependentValidFor {
private Map<String,Set<Integer>> mapValidForIndexes=new Map<String,Set<Integer>>();
public Set<Integer> getControlIndexes(String validFor){
if(mapValidForIndexes.containsKey(validFor))
return mapValidForIndexes.get(validFor);
String hex=EncodingUtil.convertToHex(EncodingUtil.base64Decode(validFor));
Set<Integer> result=new Set<Integer>();
for(Integer i=0; i<hex.length(); i++){
String b=hex.substring(i, i+1);
Integer off=i*4;
switch on b { //0123(index)
when '0'{ //0000
}
when '1'{ //0001
result.add(off+3);
}
when '2'{ //0010
result.add(off+2);
}
when '3'{ //0011
result.add(off+2);
result.add(off+3);
}
when '4'{ //0100
result.add(off+1);
}
when '5'{ //0101
result.add(off+1);
result.add(off+3);
}
when '6'{ //0110
result.add(off+1);
result.add(off+2);
}
when '7'{ //0111
result.add(off+1);
result.add(off+2);
result.add(off+3);
}
when '8'{ //1000
result.add(off+0);
}
when '9'{ //1001
result.add(off+0);
result.add(off+3);
}
when 'a'{ //1010
result.add(off+0);
result.add(off+2);
}
when 'b'{ //1011
result.add(off+0);
result.add(off+2);
result.add(off+3);
}
when 'c'{ //1100
result.add(off+0);
result.add(off+1);
}
when 'd'{ //1101
result.add(off+0);
result.add(off+1);
result.add(off+3);
}
when 'e'{ //1110
result.add(off+0);
result.add(off+1);
result.add(off+2);
}
when 'f'{ //1111
result.add(off+0);
result.add(off+1);
result.add(off+2);
result.add(off+3);
}
}
}
mapValidForIndexes.put(validFor,result);
return result;
}
}
}

关于Salesforce存在至于项目的选择List的取值问题的更多相关文章

  1. pycharm新建项目时选择virtualenv的说明

    虚拟环境及venv和virtualenv介绍:https://www.cnblogs.com/mind18/p/13877170.html pip介绍:https://www.cnblogs.com/ ...

  2. git的使用学习笔记3---关于项目分支创建克隆拉取推送

    一.创建项目 1.打开官网 2.填写相关内容 查看新创建的项目 3.选择方式 4.在git上新建文件夹 1)克隆: mkdir workspace 将代码克隆到本地,取本地配置的.ssh的文件 git ...

  3. jQuery取得select选择的文本与值

    jquery获取select选择的文本与值获取select :获取select 选中的 text :$("#ddlregtype").find("option:selec ...

  4. springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序

    springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序 http://www.360doc.com/content/14/03 ...

  5. Android项目,从web上取下汉字,中文部分乱码

    Android项目,从web上取下汉字,中文部分乱码. 常见问题,搜索一下,网上有很多办法解决.如果还没有试过这个办法,可以尝试一下. BufferedReader in = new Buffered ...

  6. [荐] jQuery取得select选择的文本与值

    csdn:http://blog.csdn.net/tiemufeng1122/article/details/44154571 jquery获取select选择的文本与值获取select :获取se ...

  7. Salesforce中所有常用类型字段的取值与赋值

    Salesforce中所有常用字段类型的定义以及如何用代码进行取值和赋值: Field Type的定义: http://www.salesforce.com/us/developer/docs/api ...

  8. Xamarin.iOS项目提示error MSB3174:”TargetFrameworkVersion”的值无效

    Xamarin.iOS项目提示error MSB3174:”TargetFrameworkVersion”的值无效 错误信息:MSBulid\14.0\bin\Microsoft.Common.Cur ...

  9. jquery获取select选择的文本与值

    jquery获取select选择的文本与值获取select :获取select 选中的 text :    $("#ddlregtype").find("option:s ...

  10. bootstrap select 多选的用法,取值和赋值(取消默认选择第一个的对勾)

    h5自带的select标签可以实现按住ctrl键多选的功能,但是样式及其难看. bootstrap select是很好用的前端插件 ​ 首先引入bootstrap和bootstrap-select的c ...

随机推荐

  1. ctfshow_web入门 PHP特性

    PHP特性 这里以半做题,半学习为主,所以就显得比较啰嗦 阿巴阿巴,但是实际上,写得比较水,等过一段时间再总结一下 比较深刻的印象是:下一个手册,多看手册 从web135还是几开始,就是看的这个师傅的 ...

  2. 【KAWAKO】MNN-1.2.0版本交叉编译遇到的错误与解决方法

    目录 在使用gcc-linaro-7.5.0-aarch64-linux-gnu.gcc-linaro-6.3.1-aarch64-linux-gnu交叉编译链对MNN1.2.0进行交叉编译的过程中, ...

  3. 深度学习-LSTM

    目录 前言 神经网络的历史和背景 循环神经网络的出现及其作用 LSTM在处理序列数据中的应用 LSTM的基本原理 LSTM的结构和原理 遗忘门.输入门.输出门的作用 LSTM的训练方法 代码 LSTM ...

  4. 云服务器安装 redis

    下载地址:https://download.redis.io/releases/ 此处示例使用的版本是:redis-6.2.10.tar.gz 前提环境: 云服务器 Xshell(操作终端) Xftp ...

  5. IO相关了解

    1.IO的概念 IO简单来讲就是对输入输出设备的简化表达形式 单片机中各种接口,进行数据流的传输 从磁盘中读取数据至内存,又或者从内存中写入磁盘 编程中的IO 此时的IO其应用程序的运行态,即进程-- ...

  6. 微信消息自动推送(评论区有我改好的模板及exe一键推送文件)

    方案1:腾讯云函数(企业ID+应用ID和密钥(发送密钥得下企业微信app)+自己云函数的IP固定IP详情方法在下图) 推荐使用多图,因为内容会显示的丰富(所有图片文字都可以自定义 都在评论区下面的模板 ...

  7. k8s网路策略

    Network Policy(网络策略) 默认情况下,k8s集群网络是没有任何限制的,Pod可以和任何其他Pod通信,在某些场景下需要做网络控制,减少网络面的攻击,提高安全性,就会用到网络策略(Net ...

  8. 设备树编译链接报错arch/arm/boot/dts/imx50.dtsi:16:42: fatal error: dt-bindings/

    1.vim scripts/Makefile.lib, add 3 lines into dtc_cpp_flags dtc_cpp_flags  = -Wp,-MD,$(depfile).pre.t ...

  9. python判断文件后缀名

    endswith()方法 利用文件名或路径名对文件后缀进行判断,例如对文件名后缀是否为.jpg的文件进行判断. path = "file.jpg" bool = path.ends ...

  10. python启动robotframework-ride失败,解决方案

    python启动robotframework-ride提示str(os.path.dirname(rf_file), 'utf-8'))).publish() UnicodeDecodeErro的解决 ...