Salesforce 数据清洗
新系统上线后,需要导入历史数据,但是旧数据格式,数据缺失,数据错误,奇异值,属性归类与新系统有很大的gap。因此我们需要建立一套数据动态清洗规则给Salesforce系统,通过这些规则自动清洗导入数据,清洗规则可以让function自己配置。而不需要IT负责
下面将详细举一个例子如何在salesforce中做数据处理。数据清洗需要分成5个步骤



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 数据清洗的更多相关文章
- Salesforce开发者学习笔记之一:基本知识
本文介绍了Salesforce开发平台的基本知识, 包括如下内容: Salesforce平台介绍 Salesforce基本术语 定制和扩展Salesforce平台 创建一个简单的应用程序 Salesf ...
- salesforce 零基础学习(六十一)apex:component简单使用以及图片轮转播放的实现
有的时候,我们项目有可能有类似需求:做一个简单的图像轮转播放功能,不同的VF页面调用可以显示不同的图片以及不同的图片描述.这种情况,如果在每个页面单独处理相关的图像轮转播放则显得代码特别冗余,此种情况 ...
- salesforce 零基础学习(五十五)java通过SOAP方式定时访问某个文件然后插入到sObject中
项目源码:https://github.com/zhangyueqidlmu/SOAP-Access-SFDC.git 项目背景:salesforce端相关数据需要其他系统提供,其他系统可以提供相关数 ...
- salesforce 零基础学习(五十四)常见异常友好消息提示
异常或者error code汇总:https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_con ...
- salesforce 零基础学习(五十三)多个文件生成一个zip文件(使用git上封装的代码)
此篇参考git代码:https://github.com/pdalcol/Zippex 学习salesforce可以访问一个朋友的网站:https://www.xgeek.net 首先感谢git上提供 ...
- Hawk 4. 数据清洗
数据清洗模块,包括几十个子模块, 这些子模块包含四类:生成, 转换, 过滤和执行. 数据清洗可以通过组合多个不同的子模块,生成多样的功能,通过拖拽构造出一个工作流,它能够产生一个有限或无限的文档序列. ...
- Salesforce的sharing Rule 不支持Lookup型字段解决方案
Salesforce 中 sharing rule 并不支持Look up 字段 和 formula 字段.但在实际项目中,有时会需要在sharing rule中直接取Look up型字段的值,解决方 ...
- 微软要如何击败Salesforce?Office365、Azure、Dynamics365 全面布局AI | 双语
微软在上月宣布组建自己的 AI 研究小组.该小组汇集了超过 5000 名计算机科学家和工程师,加上微软内部研究部门,将共同挖掘 AI 技术. 与此同时,亚马逊,Facebook,Google,IBM ...
- SalesForce 记录级别安全性
对象级安全性 简档 对象级安全性提供了控制 Salesforce.com 中数据的最简单方式.使用对象级安全性 您可以防止用户查看.创 建.编辑或删除特殊类型对象的任何实例 如潜在客户或业务机会.对象 ...
随机推荐
- uva1635
/* 哑元 组合数的递推整除判断_________________________________________________________________________________ #i ...
- JS~~~ 前端开发一些常用技巧 模块化结构 &&&&& 命名空间处理 奇技淫巧!!!!!!
前端开发一些常用技巧 模块化结构 &&&&& 命名空间处理 奇技淫巧!!!!!!2016-09-29 17 ...
- 数位DP之奥义
恩是的没错数位DP的奥义就是一个简练的dfs模板 int dfs(int position, int condition, bool boundary) { ) return (condition ? ...
- 数据库设计与 ER 模型 - 数据库系统原理
数据库系统生存周期 数据库应用系统的开发是一项软件工程,一般具有信息的采集.组织.加工.抽取.综合.传播等功能,但又有自己的特点,所以称为 数据库工程. 数据库应用系统从开始规划.设计.实现.维护到最 ...
- 使用SPM创建新组件
(前提:已经安装好了spm) 步骤如下:
- 【原创】刚刚发现的SVN的几个有用的功能
一.可看到一个文件/目录跨Branch的所有变更历程 二.SVN可自动利用Word2013的审阅功能对比docx文档
- [2016.01.18]文本替换专家 v5.3
文本替换专家,界面简洁易用,功能强大实用.支持大小写匹配,支持多级目录.多行文本.多种文件格式的同时批量查找和批量替换.智能准确的区分ANSI.UTF-8(包括无BOM的UTF-8).Unicode. ...
- ios 写项目的时候遇到的问题及解决方案(2)
11.自适应文本高度 NSDictionary *attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:]}; CGRect rec ...
- C指针详解(经典,非常详细)
前言:复杂类型说明要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其优 ...
- Atom插件推荐
1.File Icons 为各种不同的文件显示icon 2.git plus 添加git的功能 3.atom-beauty 代码格式化工具 4.eclipse keybindings 在atom上使用 ...