在实际业务中,有时候会需要拿到字段依赖的Excel格式,这里有两种方法供参考:
(1)复制粘贴法。在字段依赖编辑的状态下,可以直接复制下来,然后粘贴在Excel里,通过单元格颜色格式排序,处理之后得到想要的表。适用于依赖字段不多的情况,否则要复制很多次,点得累不划算不划算。
(2)Map转二维数组法。 将字段得依赖结构化为Map格式,再将Map转为二维数组,再将结合csv的逗号分隔属性,将数组用页面输出。
用于输出csv的VF:
<apex:page controller="ExportAllDepentCtrl" cache="true" contenttype="text/csv;charset=UTF-8;#export.csv" showheader="false" readonly="true">{!headerValue}
<apex:repeat value="{!DependentStrList}" var="t3">
{!t3}
</apex:repeat>
</apex:page>
用于输出csv的VF的控制类:
public class ExportAllDepentCtrl {
public List<String> DependentStrList {get; set;}
public String headerValue {get; set;}
public ExportAllDepentCtrl() {
DependentStrList = new List<String>();
headerValue = '';
String OBJ_NAME = System.Label.TempObjName; //对象名称
String CTRL_FIELD_NAME = System.Label.TempCtrlFieldName; //控制字段
String DEP_FIELD_NAME = System.Label.TempDeptFieldName; //依赖字段
//调用的方法见下面的类
Map<String,List<String>> dependMap = EbestPicklist.getDependentOptions(OBJ_NAME, CTRL_FIELD_NAME, DEP_FIELD_NAME);
System.debug(LoggingLevel.DEBUG, '*** dependMap: ' + dependMap);
//设置表头
for(String keyStr : dependMap.keySet()){
if(String.isNotBlank(keyStr)){
if(keyStr.contains(',')){
keyStr = ('\"'+keyStr+'\"');
}
headerValue += (keyStr + ',');
}
}
//去掉最后的分号
headerValue = headerValue.substring(0, headerValue.length()-1);
//找出dependent最多的值
Integer maxDependent=0;
List<String> tempList = new List<String>();
List<String> denpList = new List<String>();
for(String keyStr : dependMap.keySet()){
denpList = dependMap.get(keyStr);
if(denpList.size()>maxDependent){
maxDependent = denpList.size();
}
}
//生成二位数组类型,转义字符里的英文逗号
String tempStr;
for(Integer i=0;i<maxDependent;i++){
tempList = new List<String>();
tempStr = '';
for(String keyStr : dependMap.keySet()){
denpList = dependMap.get(keyStr);
if(i<denpList.size()){
tempList.add(denpList[i]);
if(String.isNotBlank(denpList[i]) && denpList[i].contains(',')){
tempStr+=('\"'+denpList[i]+'\"'+',');
}else{
tempStr+=(denpList[i]+',');
}
}else{
tempList.add('');
tempStr+=(''+',');
}
}
tempStr = tempStr.substring(0, tempStr.length()-1);
System.debug(LoggingLevel.DEBUG, '*** tempStr: ' + tempStr);
DependentStrList.add(tempStr);
}
}
}
用于输出csv的VF控制类引用的工具类(将字段依赖格式转为Map):
global Class EbestPicklist
{
global static Map<String,List<String>> getDependentOptions(String pObjName, String pControllingFieldName, String pDependentFieldName)
{
Map<String,List<String>> objResults = new Map<String,List<String>>();
//get the string to sobject global map
Map<String,Schema.SObjectType> objGlobalMap = Schema.getGlobalDescribe();//key is low case
if (!objGlobalMap.containsKey(pObjName.toLowerCase()))
return objResults;
//get the type being dealt with
Schema.SObjectType pType = objGlobalMap.get(pObjName);
Map<String, Schema.SObjectField> objFieldMap = pType.getDescribe().fields.getMap();
system.debug('**FieldMap'+objFieldMap);
String ctrKey = pControllingFieldName.toLowerCase();
String depKey = pDependentFieldName.toLowerCase();
system.debug('**C '+ctrKey);
//verify field names
if (!objFieldMap.containsKey(ctrKey) || !objFieldMap.containsKey(depKey))
return objResults;
//get the control values
List<Schema.PicklistEntry> ctrl_ple = objFieldMap.get(ctrKey).getDescribe().getPicklistValues();
system.debug('**C'+ctrl_ple);
//get the dependent values
List<Schema.PicklistEntry> dep_ple = objFieldMap.get(depKey).getDescribe().getPicklistValues();
system.debug('**D'+dep_ple);
//iterate through the values and get the ones valid for the controlling field name
Bitset objBitSet = new Bitset();
//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<String>());
}
// cater for null and empty
// 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);
TPicklistEntry objDepPLE = (TPicklistEntry)JSON.deserialize(pEntryStructure, TPicklistEntry.class);
system.debug('***'+objDepPLE);
//if valid for is empty, skip
if (objDepPLE.validFor==null || objDepPLE.validFor=='')
{
system.debug('***validFor');
continue;
}
//iterate through the controlling values
for(Integer pControllingIndex=0; pControllingIndex<ctrl_ple.size(); pControllingIndex++)
{
if (objBitSet.testBit(objDepPLE.validFor,pControllingIndex))
{
//get the label
String pControllingLabel = ctrl_ple[pControllingIndex].getLabel();
objResults.get(pControllingLabel).add(objDepPLE.label);
}
}
}
return objResults;
}
public class Bitset
{
public Map<String,Integer> AlphaNumCharCodes { get;set; }
public Map<String, Integer> Base64CharCodes { get; set; }
public Bitset()
{
LoadCharCodes();
}
//Method loads the char codes
private void LoadCharCodes()
{
AlphaNumCharCodes = new Map<String,Integer>{
'A'=>65,'B'=>66,'C'=>67,'D'=>68,'E'=>69,'F'=>70,'G'=>71,'H'=>72,'I'=>73,'J'=>74,
'K'=>75,'L'=>76,'M'=>77,'N'=>78,'O'=>79,'P'=>80,'Q'=>81,'R'=>82,'S'=>83,'T'=>84,
'U'=>85,'V'=> 86,'W'=>87,'X'=>88,'Y'=>89,'Z'=>90
};
Base64CharCodes = new Map<String, Integer>();
//lower case
Set<String> pUpperCase = AlphaNumCharCodes.keySet();
for(String pKey : pUpperCase)
{
//the difference between upper case and lower case is 32
AlphaNumCharCodes.put(pKey.toLowerCase(),AlphaNumCharCodes.get(pKey)+32);
//Base 64 alpha starts from 0 (The ascii charcodes started from 65)
Base64CharCodes.put(pKey,AlphaNumCharCodes.get(pKey) - 65);
Base64CharCodes.put(pKey.toLowerCase(),AlphaNumCharCodes.get(pKey) - (65) + 26);
}
//numerics
for (Integer i=0; i<=9; i++)
{
AlphaNumCharCodes.put(string.valueOf(i),i+48);
//base 64 numeric starts from 52
Base64CharCodes.put(string.valueOf(i), i + 52);
}
AlphaNumCharCodes.put('+',43);
AlphaNumCharCodes.put('/',47);
Base64CharCodes.put('+',62);
Base64CharCodes.put('/',63);
}
public Boolean testBit(String pValidFor,Integer n)
{
//the list of bytes
List<Integer> pBytes = new List<Integer>();
//multiply by 6 since base 64 uses 6 bits
Integer bytesBeingUsed = (pValidFor.length() * 6)/8;
//will be used to hold the full decimal value
Integer pFullValue = 0;
//must be more than 1 byte
if (bytesBeingUsed <= 1)
return false;
//calculate the target bit for comparison
Integer bit = 7 - (Math.mod(n,8));
//calculate the octet that has in the target bit
Integer targetOctet = (bytesBeingUsed - 1) - (n >> bytesBeingUsed);
//the number of bits to shift by until we find the bit to compare for true or false
Integer shiftBits = (targetOctet * 8) + bit;
//get the base64bytes
for(Integer i=0;i<pValidFor.length();i++)
{
//get current character value
pBytes.Add((Base64CharCodes.get((pValidFor.Substring(i, i+1)))));
}
//calculate the full decimal value
for (Integer i = 0; i < pBytes.size(); i++)
{
Integer pShiftAmount = (pBytes.size()-(i+1))*6;//used to shift by a factor 6 bits to get the value
pFullValue = pFullValue + (pBytes[i] << (pShiftAmount));
}
//& is to set the same set of bits for testing
//shift to the bit which will dictate true or false
Integer tBitVal = ((Integer)(Math.Pow(2, shiftBits)) & pFullValue) >> shiftBits;
return tBitVal == 1;
}
}
/*
* @Summary: Entity to represent a json version of a picklist entry
* so that the validFor property becomes exposed
*/
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(){}
}
}