概要:

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

一个选择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. 插头dp 模板

    [JLOI2009]神秘的生物 只需要维护连通情况,采用最小表示法,表示此格是否存在,也即插头是否存在 分情况讨论当前格子的轮廓线上方格子和左方格子状态,转移考虑当前格子选不选,决策后状态最后要能合法 ...

  2. JZOJ.4724 斐波那契

    \(\text{Problem}\) \(\text{Solution}\) \(\text{Fibonacci}\) 数列有一个性质:若 \(H_1=a,H_2=b,H_n=H_{n-2}+H_{n ...

  3. CPU AMX 详解

    CPU AMX 详解 CPU AMX 详解 概述 算力如何 问题定义 AVX如何解决矩阵乘问题 AMX如何解决矩阵乘问题 如何实现的 计算部分 数据部分 路才开始 概述 2016 年开始,随着 NV ...

  4. Python接口自动化之pymysql数据库操作

    一.pymysql介绍及安装 01 pymysql介绍 MySQL应该说是如今使用最为普遍的数据库了,没有之一,而Python作为最为流行的语言之一,自然少不了与MySQL打交道,其中PyMySQL就 ...

  5. Linux内存占用过高排查过程

    1 查看服务器状态 系统是 CentOS Linux release 7.5.1804 (Core)使用top命令看了下系统的状态 系统的整体负载和cpu并不高,但是内存使用比较高(总8G使用了7.2 ...

  6. Linux操作命令(三)1.more命令 2.less命令 3.head命令 4.tail命令

    1.more 命令 分页显示文本文件的内容 more 命令,功能类似 cat ,cat 命令是将整个文件的内容从上到下显示在屏幕上. more 命令会一页一页的显示,方便使用者逐页阅读,而最基本的指令 ...

  7. Android Studio连接SQLlite

    1. MainActivity.java package com.example.dbproject;import android.database.sqlite.SQLiteDatabase;imp ...

  8. tabs 滑动效果

    https://www.zhangxinxu.com/wordpress/2020/07/css-var-improve-components/ 伪类选择器 https://blog.csdn.net ...

  9. Mysql数据库基础第四章DDL(数据定义语言):库表的管理、数据类型与约束条件

    Mysql数据库基础系列 软件下载地址 提取码:7v7u 数据下载地址 提取码:e6p9 mysql数据库基础第一章:(一)数据库基本概念 mysql数据库基础第一章:(二)mysql环境搭建 mys ...

  10. NSIS Inetc插件 扩展使用

    Inetc客户端插件,用于文件的上传和下载. 官网文档:https://nsis.sourceforge.io/Inetc_plug-in 以下载net包为例 inetc::get "htt ...