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 中数据的最简单方式.使用对象级安全性 您可以防止用户查看.创 建.编辑或删除特殊类型对象的任何实例 如潜在客户或业务机会.对象 ...
随机推荐
- 利用IIS管理器模拟CDN
CDN(Content Delivery Network,内容分发网络).其含义,在百度百科上是这么写的:CDN 是构建在数据网络上的一种分布式的内容分发网.CDN 的作用是采用流媒体服务器集群技术, ...
- OpenGL法向量变换
OpenGL光照开启时,法向量用于决定特定顶点或面上接受到光照的多少.光照处理过程作用于观察坐标空间,因此,模型对象坐标系的法向量也需要使用GL_MODELVIEW矩阵变换到观察坐标系. 然而,法向量 ...
- .net frameworkAPI文档下载地址
http://www.msdn.hk/html/2014/5.html VS2013 ILdasm 反编译工具安装在下面地址里了 C:\Program Files (x86)\Microsoft SD ...
- Python 获得对象内存占用内存大小 sys.getsizeof
from sys import getsizeof class A(object): pass class B: pass for x in (None, 1, 1L, 1.2, 'c', [], ( ...
- 可以链接不同源的资源的html元素(能实现跨域)
可以链接不同源的资源的html元素(能实现跨域): img.script.css.video.audio.object.embed.applet.@font-face.frame.iframe等. ( ...
- js post提交
/* js跳转页面 url跳转地址,params参数列表 */ function Posturl(url,params){ //创建form表单 var temp_form=document.crea ...
- SQL总结系列
SQL总结系列 总结SQL基本知识.用法,并结合多年的应用对SQL有关的相关知识进行总结.希望这些分享能给大家带来一些帮助,如有不足或错误,请批评指正. 主要内容 1)编辑相关,包括:数据库的创建与删 ...
- 【转】error while loading shared libraries: libevent-2.0.so.5: cannot open shared object file: No such file or directory
错误信息: /usr/local/memcacheq/bin/memcacheq: error while loading shared libraries: libevent-2.0.so.5: c ...
- 【MySQL】排序原理与案例分析
前言 排序是数据库中的一个基本功能,MySQL也不例外.用户通过Order by语句即能达到将指定的结果集排序的目的,其实不仅仅是Order by语句,Group by语句,Distinct语句都会隐 ...
- 通过宏判断VS编译版本以及系统平台
MSC_VER 定义编译器的版本.下面是一些编译器版本的_MSC_VER值(参见扩展阅读中的参考文献2的链接) MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio ...