65.9K
CodeProject 正在变化。 阅读更多。
Home

CRM 定制 - 通过电子邮件从 Excel 导入潜在客户到 MS CRM

starIconstarIconstarIconstarIconstarIcon

5.00/5 (18投票s)

2007年8月30日

CPOL

2分钟阅读

viewsIcon

74798

构建一个流程,通过电子邮件将 Excel 中的潜在客户记录导入到 MS CRM 中。

引言

本文介绍如何设置一个流程,通过电子邮件将 Excel 文件中的潜在客户导入/上传到 Microsoft CRM 中。

查看其他关于使用 Excel 和 SQL 的Siccolo 文章

以及另一篇展示 MS CRM 定制的文章

1. 将 Excel 中的潜在客户转移到 CRM 潜在客户

假设我们有一个 Excel 文件,例如这样

从 SQL 访问它

    ...
    select      first_name
        , last_name
        , company
        , number
        , street
        , city
        , state
        , zip


    from 
        OpenRowSet('MSDASQL'
            ,'Driver={Microsoft Excel Driver (*.xls)};' +
            'DBQ=c:\inetpub\wwwroot\sfa\leads\leads_to_be_imported\leads.xls', 
            'SELECT * FROM [excel_data$]') tmp

    ...

其中c:\inetpub\wwwroot\sfa\leads\ 是 CRM 服务器上的一个文件夹。首先,我将从 Excel 将 Leads 记录加载到一个临时表中

    if not exists (select id 
            from [MSCRM].dbo.sysobjects
            where name = 'tmp_leads_to_be_imported' and type ='U')
    begin
        -- create temp table:
        create table [MSCRM].dbo.tmp_leads_to_be_imported
        (
             number     varchar(150)    null    -- phone number
            , first_name    varchar(50)    null    
            , last_name    varchar(50)    null    
            , company    varchar(100)    null
            , street    varchar(50)    null
            , city        varchar(50)    null
            , state        varchar(50)    null
            , zip        varchar(50)    null
        )
    end
    else
    begin
        delete [MSCRM].dbo.tmp_leads_to_be_imported 
    end


    insert into  [MSCRM].dbo.tmp_leads_to_be_imported     
    (
        number         
        , first_name    
        , last_name    
        , company    
        , street    
        , city        
        , state        
        , zip        

    
    )
    select     number
        , first_name
        , last_name
        , company
        , street
        , city
        , state
        , zip


    from 
        OpenRowSet('MSDASQL'
            ,'Driver={Microsoft Excel Driver (*.xls)};DBQ=c:\inetpub\wwwroot\
                     sfa\leads\leads_to_be_imported\temp_leads.xls', 
            'SELECT * FROM [excel_data$]') tmp

    -- to handle possible "oops":
    select @err_code = @@error
    select @records = @@rowcount
    if @err_code<>0
    begin
        set @err = 'Failed to insert into temp table. error=[' + 
                   convert(varchar(10),@err_code) + ']'
        set @message = 'Failed Process Excel Leads Records' + char(13) + @err
        exec master.dbo.xp_sendmail @recipients ='CRM Person in Charge'
            ,@message = @message
            ,@subject = 'Failed Process Excel Leads Records'
        RAISERROR (@err, 16, 1)
        return
    end
    if @records=0
    begin
        set @err =  'Failed to insert into temp table. error=[no records inserted]'
        set @message = 'Failed Process Excel Leads Records' + char(13) + @err
        exec master.dbo.xp_sendmail @recipients ='CRM Person in Charge'
            ,@message = @message
            ,@subject = 'Failed Process Excel Leads Records'
        RAISERROR (@err, 16, 1)
        return
    end

    -- get number of Leads records from the original Excel file
    set @file_count = (select count(*) from  [MSCRM].dbo.tmp_leads_to_be_imported )

其中 [MSCRM] 是 CRM 数据库的名称。通常,它看起来像:[公司名称]_MSCRM;例如,Siccolo_MSCRM

之后,我们可以将记录从临时表转移到 Lead 视图。您可能知道,CRM 在底层数据和 CRM 用户界面之间有一个额外的层 - 视图。例如,用于存储潜在客户信息的底层表是 *LeadBase*;但 CRM 接口使用 Lead 视图对象。

    -- in order insert new records into Leads
    -- we need  SecurityDescriptor and ModifiedBy values:
    declare @security_descriptor     varchar(555)
    declare @modified_by         varchar(255)     
    
    select @security_descriptor = SecurityDescriptor
        , @modified_by = ModifiedBy
    from [MSCRM].dbo.SystemUser
    -- find CRM user by using originator email address
    where InternalEmailAddress = @user_email or ( isnull(PersonalEmailAddress,'')!='' 
                                 and PersonalEmailAddress = @user_email)


    -- now, insert into Leads view:
    insert into [MSCRM].dbo.Lead
    ( 
        Subject
        , CompanyName
        , FirstName
        , LastName

        , Telephone1

        , Address1_Line1
        , Address1_City
        , Address1_StateOrProvince
        , Address1_PostalCode

        , Description

        , OwningUser
        , LeadId
        , StateCode
        , DeletionStateCode
        , SecurityDescriptor
        , ModifiedBy
        , CreatedOn
        , ModifiedOn
    )

    select     company as Subject
        , company    
        , first_name    
        , last_name    

        , number         

        , street    
        , city        
        , state        
        , zip        
        

        , 'This Lead was created automatically from Excel file' as Description
    
        , @modified_by        as OwningUser
        , NEWID()        as LeadID
        , 0            as StateCode        -- open lead
        , 0            as DeletionStateCode
        , @security_descriptor    as SecurityDescriptor    
        , @modified_by        as ModifiedBy
        , getdate()        as CreatedOn
        , getdate()        as CreatedOn


    from [MSCRM].dbo.tmp_leads_to_be_imported 
    
    select @record_count = @@rowcount

    select @file_count        as 'original_file_count' 
        , @record_count     as 'processed_record_count'

其中 [MSCRM] 是 CRM 数据库的名称。通常,它看起来像 [公司名称]_MSCRM;例如,Siccolo_MSCRM

现在,把它变成一个存储过程

    CREATE procedure <code>p_Lead_Process_Excel_Leads_File
    (
        @user_email            varchar(50)
        ,@leads_excel_file_name     varchar(255)

        ,@file_count            int         =null output
        ,@record_count             int        =null output
    )
    as
    set nocount on
        ...
        ...
        -- insert into temp table from Excel
        ...
        ...
        -- insert into Lead view from temp table
        ...
        ...

    set nocount off

旁注

MS CRM 为了处理 INSERT/UPDATE/DELETE,在 Lead 视图上有一组**触发器**

不幸的是,Microsoft 的 CRM 团队没有计划一次插入多个 Lead 记录的情况,因此我需要对 t_create_lead 触发器进行一些更改,并创建一个新的函数 f_GetFullName

t_create_lead 触发器的更改

        ...
        declare @organizationid uniqueidentifier
        select @organizationid = BusinessUnitBase.OrganizationId
        from BusinessUnitBase
        where BusinessUnitBase.BusinessUnitId = @owningbusinessunit

        
        -- -----------------------------------------------------------
        -- Before changes:
        /*
            declare @firstname nvarchar(50)
            declare @lastname nvarchar(50)
            declare @middlename nvarchar(50)
            declare @fullname nvarchar(160)

            select @firstname = FirstName, @middlename = MiddleName, 
                                @lastname = LastName, @fullname = FullName
            from inserted

            if @fullname is null 
               exec p_GetFullName @organizationid, @firstname, 
                                  @lastname, @middlename, @fullname output
        */

        ...
        ...

        insert LeadBase(
                ...
                ...
                )
        select 
                LeadId, 
                ...
                FirstName, 
                MiddleName, 
                LastName, 
                ...
                EMailAddress3, 
                -- -----------------------------------------------------------------
                -- full name!:
                dbo.f_GetFullName(@organizationid, FirstName, LastName, MiddleName)
                -- ------------------------------------------------------------------
                ...
        from inserted

        ...
        ...

旁注

  • @@ROWCOUNT - 返回受上一个语句影响的行数。
  • @@ERROR - 返回上一个 Transact-SQL 语句执行的错误号。

2. 处理电子邮件并导入潜在客户

因此,此时,我有一个程序可以从 Excel 文件中导入/上传潜在客户记录到 Lead 视图中。下一步 - 创建一个程序来处理收到的电子邮件并将它们路由到 p_Lead_Process_Excel_Leads_File。 为了在 SQL Server 中/使用 SQL Server 处理电子邮件,我们可以使用 xp_readmailxp_findnextmsgxp_sendmailxp_deletemail SQL 邮件扩展存储过程。 像这样

    CREATE procedure p_email_Process_Incoming_Emails
    as

        set nocount on
            ...
            ...
        /* get first message id */
        declare @status int
        declare @msg_id varchar(94)
        declare @mapifailure int
    
        exec @status     = master.dbo.<code>xp_findnextmsg
            @msg_id    = @msg_id output,
            @unread_only='true'

        if @status <> 0
        begin
            set @mapifailure=1
            select 'failed to execute xp..findnextmessage'
        end
        
        while (@mapifailure=0)
        begin
            if @msg_id is null break
            if @msg_id = '' break
    
            -- peek at incoming email message
            -- and see if we need to process it:

            declare @originator varchar(255)
                ,@originator_address varchar(255)

            declare @cc_list varchar(255)
            declare @msg_subject varchar(255)
            declare @msg_message varchar(8000)

            exec @status = master.dbo.xp_readmail
                @msg_id        = @msg_id,
                @originator    = @originator output,
                @cc_list    = @cc_list output,
                @subject    = @msg_subject output,
                @message    = @msg_message output,
                @peek        = 'true',
                @suppress_attach='true',
                @originator_address = @originator_address output

            if @status <> 0
            begin
                select @mapifailure=1
                break
            end

            /* get new message id before processing & deleting current */
            set @current_msg=@msg_id
            exec @status     = master.dbo.xp_findnextmsg
                @msg_id    = @msg_id output,
                @unread_only='true'

            if @status <> 0
            begin
                select @mapifailure=1
            end
            print 'checking email [' + @msg_subject + ']'


            declare @attachments varchar(255)
                
            -- if message subject contains "magic" words:
            if (lower(@msg_subject) = 'iMport Excel CRM Leads')
            begin
                print 'import excel CRM leads'
                set @bad_input = 0
            
                exec @status         = master.dbo.xp_readmail
                    @msg_id        = @current_msg,
                    @originator    = @originator output,
                    @cc_list    = @cc_list output,
                    @subject    = @msg_subject output,
                    @message    = @msg_message output,
                    @peek        = 'false',    -- this time no peeking, get email message
                    @suppress_attach='false',
                    @attachments     = @attachments output, -- and get attachted Excel file!
                    @originator_address = @originator_address output
                    -- make sure user has rights to import CRM Leads!!!
                /* 
                    check user credentials bases on user email address
                */
                -- also, check if user email is in CRM SystemUser:
                if not exists ( select SystemUserId from [MSCRM].dbo.SystemUser
                        where InternalEmailAddress = @originator or 
                                ( isnull(PersonalEmailAddress,'')!='' 
                                  and PersonalEmailAddress = @originator)
                        ) 
                begin
                    set @msg_message = 'User [' + @originator + 
                                       '] does not have access to CRM!'
                    set @msg_subject = @msg_message
                    exec @status= master.dbo.xp_sendmail @recipients = @originator
                                ,@message     = @msg_message
                                ,@subject     = @msg_subject
                                ,@attachments     = @attachments
                        set @bad_input = 1
                end
                    
                if @bad_input = 0     
                begin
                exec [MSCRM].dbo.p_Lead_Process_Excel_Leads_File
                                    @originator
                                    , @attachments
                                    , @file_count            output
                                    , @record_count         output


                    -- if number of Leads records in Excel file is different
                    -- then number of records inserted into CRM Leads,
                    -- let user know:
                    if (@file_count != @record_count)
                    begin
                      set @msg_subject = 'Processed '  + 
                          @msg_subject + ' - !Totals Do Not Match!'
                      set @msg_message = 'Processed ' + @msg_subject + char(13)+ char(13)+
                          'File Record Count: ' + char(9)+ 
                          '   convert(varchar,isnull(@file_count,0)) + char(13)+ char(13)+
                          'Processed Count: ' + char(9)+
                          '   convert(varchar,isnull(@record_count,0)) + char(13)+ char(13)+
                          char(9)+ '!File Total Does Not Match Processed Total!'
                    end
                    else
                    begin
                        -- number of records in Excel is the same
                        -- as number of records inserted into CRM Leads:
                        -- simply let user know that Leads Excel file is processed
                        set @msg_subject = 'Processed '  + @msg_subject
                        set @msg_message = 'Processed '  + @msg_subject + char(13)+ char(13)+
                                'Record Count: ' + char(9)+
                                '  convert(varchar,@file_count) + char(13)+ char(13)+
                                'Processed Count: ' + char(9)+ convert(varchar,@record_count)
                    end
                
                    -- and send email response back to user:
                    exec @status= master.dbo.xp_sendmail @recipients = @originator
                                ,@message     = @msg_message
                                ,@subject     = @msg_subject
                                ,@attachments     = @attachments
                end -- end of if @bad_input = 0 

                print 'deleting  - import excel CRM leads' + convert(varchar, @current_msg)
                exec master.dbo.xp_deletemail @current_msg

            end    -- end of if (lower(@msg_subject) = 'import excel CRM leads')

        end -- end of while (@mapifailure=0)

    -- done with messages in Inbox
    if @mapifailure=1
          begin
        raiserror(15079,-1,-1,@messages)
        return(1)
    end
      else
    begin
        return(0)
    end

    set nocount off

因此,为了让 SQL Server 将 Excel 文件中的潜在客户处理到 Lead 视图中,只需将带有 Excel 文件附件的电子邮件发送到 SQL Server,并将 *import excel CRM leads* 作为电子邮件主题。

历史

到目前为止没有改进。 几乎完美。

关注点

如果您想阅读更多关于这个故事的信息 - 请查看 Siccolo - 用于 SQL Server 的免费移动管理工具,以及 Siccolo 上的更多文章。

© . All rights reserved.