新系统上线后,需要导入历史数据,但是旧数据格式,数据缺失,数据错误,奇异值,属性归类与新系统有很大的gap。因此我们需要建立一套数据动态清洗规则给Salesforce系统,通过这些规则自动清洗导入数据,清洗规则可以让function自己配置。而不需要IT负责

下面将详细举一个例子如何在salesforce中做数据处理。数据清洗需要分成5个步骤

1,建立2个关联数据的Object的和 一个数据清洗后台设置的Object的
2,数据导入页面csv
3,定义每个字段的范围、属性,如果是错误的则自动重新分配,或者修改成临近值
4,数据清洗合并。
5,导出错误数据到Excel
 
第一步,新建立两个关联的Recruit 和 Recruit Department, 并且建立一个清洗规则的Object,当导入数据后我们可以读取设置的清洗规则,并对导入的数据进行清洗
第二步,对于清洗规则,我们只能有一条规则被激活,因此我们在插入新规则和更改旧规则的时候,我们需要添加一个tirgger针对Data_Washing_Setting,保证规则的唯一性。

 trigger IsActiveChecking on Data_Washing_Setting__c (before insert,before update) {

     List<Data_Washing_Setting__c> ListOldData =[select Id from Data_Washing_Setting__c
where Active_this_Rule__c = true];
List<Data_Washing_Setting__c> ListNewData =trigger.new; //system.debug('ListNewData:'+ListNewData.size());
integer itemNum = 0;
if(trigger.isInsert)
{
if(trigger.isBefore)
{
for(Data_Washing_Setting__c dws : trigger.new)
{
if(dws.Active_this_Rule__c)
{
itemNum++;
}
}
itemNum +=ListOldData.size(); if(itemNum>1)
{
for(Data_Washing_Setting__c dws : trigger.new){
dws.adderror('only one record can be actived! pls check your history data and try again.');
}
}
}
}
else if(trigger.isUpdate)
{
if(trigger.isBefore)
{
// 去掉更新的数据
for(Data_Washing_Setting__c dws : trigger.new)
{
for(integer i=0;i<ListOldData.size();i++){
if(dws.Id== ListOldData[i].Id)
{
ListOldData.remove(i);
}
}
if(dws.Active_this_Rule__c)
{
itemNum++;
}
}
itemNum +=ListOldData.size();
if(itemNum>1)
{
for(Data_Washing_Setting__c dws : trigger.new){
dws.adderror('only one record can be actived! pls check your history data and try again.');
}
} }
}
}

第三步,我们需要建立导入页面,并添加相应的验证按钮

VF的代码

 <apex:page controller="BatchInsertByCsvController">
<apex:form >
<apex:sectionHeader title="Upload Recruit Data"/>
<apex:pageMessages />
<apex:pageblock >
<center>
<apex:inputFile value="{!contentFile}" fileName="{!fileName}" />
<apex:commandButton action="{!LoadData}" value="Batch Insert"/>
<apex:commandButton action="{!LoadBlankList}" value="Filter Blank Data"/>
<apex:commandButton action="{!ExportBlankToCSV}" value="Export CSV"/> </center>
</apex:pageblock>
<apex:pageBlock title="Import Data">
<apex:pageblocktable value="{!RecruitList}" var="ReList">
<apex:column value="{!ReList.Name}" />
<apex:column value="{!ReList.Position_Name__c}" />
<apex:column value="{!ReList.Recruit_Department__c}" />
<apex:column value="{!ReList.Recruit_Type__c}" />
<apex:column value="{!ReList.Recruit_Number__c}" />
</apex:pageblocktable>
</apex:pageBlock>
<apex:pageBlock title="Blank Data">
<apex:pageblocktable value="{!BlankList}" var="BList">
<apex:column value="{!BList.Name}" />
<apex:column value="{!BList.Position_Name__c}" />
<apex:column value="{!BList.Recruit_Department__c}" />
<apex:column value="{!BList.Recruit_Type__c}" />
<apex:column value="{!BList.Recruit_Number__c}" />
</apex:pageblocktable>
</apex:pageBlock>
</apex:form>
</apex:page>

后台APEX 导入代码

 public class BatchInsertByCsvController {

     public string fileName{get;set;}
//Blob:二进制对象类型。通过inputFile选中后的文件在后台获取的时候是一个Blob类型,
public Blob contentFile{get;set;}
public String[] filelines = new String[]{};
public List<Recruit__c> RecruitList{get;set;}
public List<Recruit__c> BlankList{get;set;}
public List<Recruit__c> invaildList{get;set;}
//初始化
public PageReference LoadData()
{
try{
filename = bitToString(contentFile,'ISO-8859-1');
filelines = fileName.split('\n');
// ApexPages.Message msgs = new ApexPages.Message(ApexPages.Severity.INFO, 'import account:'+filelines.size());
// ApexPages.addMessage(msgs);
RecruitList = new List<Recruit__c>();
string[] inputvalues;
string SwpNumber; for(Integer i=1;i<filelines.size();i++)
{
inputvalues = new string[]{};
inputvalues = filelines[i].split(',');
Recruit__c recruits = new Recruit__c();
recruits.Name = inputvalues[0];
recruits.Position_Name__c = inputvalues[1];
recruits.Recruit_Department__c = [SELECT Id
FROM Recruit_Department__c
WHERE Name =:inputvalues[2] LIMIT 1].Id;
recruits.Recruit_Type__c = inputvalues[3];
SwpNumber = inputvalues[4];
recruits.Recruit_Number__c = Decimal.valueOf(SwpNumber.trim());
RecruitList.add(recruits);
}
}
catch(exception e){
ApexPages.Message errormsg = new ApexPages.Message(ApexPages.Severity.ERROR,'An error has occured reading the CSV file: '+e.getMessage());
ApexPages.addMessage(errormsg);
}
try{
// insert RecruitList;
// ApexPages.Message successMsg = new ApexPages.Message(ApexPages.severity.INFO,'import success');
// ApexPages.addMessage(successMsg);
}
catch(Exception e)
{
//ApexPages.Message errormsg = new ApexPages.Message(ApexPages.severity.ERROR,'An error has occured inserting the records'+e.getMessage());
//ApexPages.addMessage(errormsg);
}
return null;
}
//blob是二进制存储的,String是16进制存储的,所以使用此种方式加上编码解码等操作肯定会更加适应,包括中文
private String bitToString(Blob input, String inCharset){
//转换成16进制
String hex = EncodingUtil.convertToHex(input);
//一个String类型两个字节 32位(bit),则一个String长度应该为两个16进制的长度,所以此处向右平移一个单位,即除以2
//向右平移一个单位在正数情况下等同于除以2,负数情况下不等
//eg 9 00001001 >>1 00000100 结果为4
final Integer bytesCount = hex.length() >> 1;
//声明String数组,长度为16进制转换成字符串的长度
String[] bytes = new String[bytesCount];
for(Integer i = 0; i < bytesCount; ++i) {
//将相邻两位的16进制字符串放在一个String中
bytes[i] = hex.mid(i << 1, 2);
}
//解码成指定charset的字符串
return EncodingUtil.urlDecode('%' + String.join(bytes, '%'), inCharset);
}
//筛选空值
public PageReference LoadBlankList()
{
try
{
BlankList=new list<Recruit__c>();
DataWashingSetting dws=new DataWashingSetting();
string[] flines = dws.AddQuestionsData(filelines);
string[] inputvalues;
string SwpNumber; for(Integer i=0;i<flines.size();i++)
{
inputvalues = new string[]{};
inputvalues = flines[i].split(',');
Recruit__c recruits = new Recruit__c();
recruits.Name = inputvalues[0];
recruits.Position_Name__c = inputvalues[1];
recruits.Recruit_Department__c = [SELECT Id
FROM Recruit_Department__c
WHERE Name =:inputvalues[2] LIMIT 1].Id;
recruits.Recruit_Type__c = inputvalues[3];
SwpNumber = inputvalues[4];
recruits.Recruit_Number__c = Decimal.valueOf(SwpNumber.trim());
BlankList.add(recruits);
}
ApexPages.Message msgs = new ApexPages.Message(ApexPages.Severity.INFO, 'blank num:'+BlankList.size());
ApexPages.addMessage(msgs);
}
catch(Exception e)
{
ApexPages.Message errormsg = new ApexPages.Message(ApexPages.Severity.ERROR,'An error has occured reading the CSV file: '+e.getMessage());
ApexPages.addMessage(errormsg);
}
return null;
}
public PageReference ExportBlankToCSV()
{
return new PageReference('/apex/ExportCSV');
}
}

后台调用的验证清洗代码,可以根据需要任意添加

 public class DataWashingSetting {

     //消除重复数据
public List<Recruit__c> DelDuplicateData(List<Recruit__c> OriginalList)
{
set<Recruit__c> myset= new set<Recruit__c>();
List<Recruit__c> result = new List<Recruit__c>(); myset.addAll(OriginalList);
result.addAll(myset); return result;
}
//筛选为空数据
public string[] AddQuestionsData(string[] filelines)
{
string[] result =new string[]{};
string[] inputvalues;
for(Integer i=1;i<filelines.size();i++)
{
inputvalues = new string[]{};
inputvalues = filelines[i].split(',');
if(inputvalues[0] == ''||inputvalues[1] == '' ||inputvalues[2] == ''
||inputvalues[3] == '' ||inputvalues[4] == '')
{
result.add(filelines[i]);
}
}
return result;
}
//检测各个字段的合理性
public string[] CheckFiled(string[] filelines)
{
//读取规则
Data_Washing_Setting__c dws = [select Position_Name_Rule__c,
Recruit_End_Number__c,Recruit_Department_Rule__c,Recruit_Start_Number__c from Data_Washing_Setting__c where Active_this_Rule__c = true];
string PositionNameRule = dws.Position_Name_Rule__c; //部门规则是否允许重复
decimal startNumber= dws.Recruit_Start_Number__c; //招聘人数底线
decimal endNumber= dws.Recruit_End_Number__c; //招聘人数上线
string department = dws.Recruit_Department_Rule__c;//部门限制 string[] result =new string[]{};
string[] inputvalues;
for(Integer i=1;i<filelines.size();i++)
{
inputvalues = new string[]{};
inputvalues = filelines[i].split(',');
//填写验证代码
}
return result; //返回不合格代码
}
}

出现问题数据直接导出问题数据到Excel,手动处理后再导入。

 <apex:page controller="BatchInsertByCsvController" cache="true" contentType="application/x-excel# BlankList.xls" showHeader="false">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
</head>
<apex:pageBlock >
<apex:pageblocktable value="{!BlankList}" var="BList">
<apex:column value="{!BList.Name}" />
<apex:column value="{!BList.Position_Name__c}" />
<apex:column value="{!BList.Recruit_Department__c}" />
<apex:column value="{!BList.Recruit_Type__c}" />
<apex:column value="{!BList.Recruit_Number__c}" />
</apex:pageblocktable>
</apex:pageBlock>
</apex:page>

下面就是最终效果:

1,导入数据,自动筛选有缺失值的数据,并支持Excel导出

2,后台清洗的规则设置。

 

Salesforce 数据清洗的更多相关文章

  1. Salesforce开发者学习笔记之一:基本知识

    本文介绍了Salesforce开发平台的基本知识, 包括如下内容: Salesforce平台介绍 Salesforce基本术语 定制和扩展Salesforce平台 创建一个简单的应用程序 Salesf ...

  2. salesforce 零基础学习(六十一)apex:component简单使用以及图片轮转播放的实现

    有的时候,我们项目有可能有类似需求:做一个简单的图像轮转播放功能,不同的VF页面调用可以显示不同的图片以及不同的图片描述.这种情况,如果在每个页面单独处理相关的图像轮转播放则显得代码特别冗余,此种情况 ...

  3. salesforce 零基础学习(五十五)java通过SOAP方式定时访问某个文件然后插入到sObject中

    项目源码:https://github.com/zhangyueqidlmu/SOAP-Access-SFDC.git 项目背景:salesforce端相关数据需要其他系统提供,其他系统可以提供相关数 ...

  4. salesforce 零基础学习(五十四)常见异常友好消息提示

    异常或者error code汇总:https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_con ...

  5. salesforce 零基础学习(五十三)多个文件生成一个zip文件(使用git上封装的代码)

    此篇参考git代码:https://github.com/pdalcol/Zippex 学习salesforce可以访问一个朋友的网站:https://www.xgeek.net 首先感谢git上提供 ...

  6. Hawk 4. 数据清洗

    数据清洗模块,包括几十个子模块, 这些子模块包含四类:生成, 转换, 过滤和执行. 数据清洗可以通过组合多个不同的子模块,生成多样的功能,通过拖拽构造出一个工作流,它能够产生一个有限或无限的文档序列. ...

  7. Salesforce的sharing Rule 不支持Lookup型字段解决方案

    Salesforce 中 sharing rule 并不支持Look up 字段 和 formula 字段.但在实际项目中,有时会需要在sharing rule中直接取Look up型字段的值,解决方 ...

  8. 微软要如何击败Salesforce?Office365、Azure、Dynamics365 全面布局AI | 双语

    微软在上月宣布组建自己的 AI 研究小组.该小组汇集了超过 5000 名计算机科学家和工程师,加上微软内部研究部门,将共同挖掘 AI 技术. 与此同时,亚马逊,Facebook,Google,IBM ...

  9. SalesForce 记录级别安全性

    对象级安全性 简档 对象级安全性提供了控制 Salesforce.com 中数据的最简单方式.使用对象级安全性 您可以防止用户查看.创 建.编辑或删除特殊类型对象的任何实例 如潜在客户或业务机会.对象 ...

随机推荐

  1. CE 消息处理

    MFC消息发送: static HANDLE hWnd =FindWindow(NULL,_T("Client")); //找到窗口 if(hWnd == INVALID_HAND ...

  2. [WARNING]考前必读?!

    考试策略很重要. 1)             认真读懂每道题,把题意搞明白,把样例算出来,把题目要求的细节标出. 2)             推出每道题的模型,确定每道题的策略,是部分分还是要全部 ...

  3. LeetCode-Subsets

    Given a set of distinct integers, nums, return all possible subsets. Note: The solution set must not ...

  4. [课程设计]Scrum 1.7 多鱼点餐系统开发进度

    [课程设计]Scrum 1.7 多鱼点餐系统开发进度(点餐菜式内容添加及美化) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题 ...

  5. Python几种主流框架

    从GitHub中整理出的15个最受欢迎的Python开源框架.这些框架包括事件I/O,OLAP,Web开发,高性能网络通信,测试,爬虫等. Django: Python Web应用开发框架 Djang ...

  6. ugui,button的一个坑

    如果ugui button下面挂了一些image或text,而这些image或text的范围超出了button本身的范围,则应将image和text的raycast Target属性的勾选去掉,否则只 ...

  7. 远程监控显示brother数控机床数据

    最近几个月公司太忙了,到现在已经连续出差两个多月了. 这个项目这要做mes系统,涉及到产品在机床的加工过程监控,然后led看板显示产品进度. 这里的主角是日本的brother数控机床,服务器按照一定频 ...

  8. Mac10.9用brew搭建Eclipse4.4+Maven3.2.3+JDK1.8运行环境

    --------------------------------------- 博文作者:迦壹 博客标题:Mac10.9用brew搭建Eclipse4.4+Maven3.2.3+JDK1.8运行环境 ...

  9. 【SharePoint学习笔记】第4章 SharePoint UI 定制

    第4章 SharePoint UI 定制   SharePoint 与 ASP.NET     好的​Asp.Net人员很快就能成为好的SharePoint开发人员     Web应用程序    Mi ...

  10. 认识UML类图元素

    在Visio里,包和类的关系是包含关系,将类拖入包的文件夹之后,关系就建立了,二元关联符号可以设置为:聚合.合成.接口:空心圆+直线(唐老鸭类实现了‘讲人话’):依赖:虚线+箭头(动物和空气的关系): ...