SalesforceのデータをSOQLを書いて自由にエクセルにダウンロードする方法

Salesforceのデータをエクセルやcsvに出力するにはいくつか方法がありますが、DataLoaderや開発者コンソール、WorkbenchなどのWebAPIを実装したツール等を使う必要があったりします。

開発中であったり、使用者が開発者であったりする場合は、比較的自由度の高いその方法を取ることも考えられますが、要件が「営業やマーケティングチームのユーザが毎日の業務のために、Salesforceにある最新のデータを取得したい」といったものである場合は、もう少し、使いやすく、用意しやすい方法がよいですよね。

ひとつのソリューションは、「レポート」にして、実行結果をエクセルやcsv形式で出力するというものです。

ただし、この方法は、少し複雑な結合条件のクエリだと、なかなか定義しづらいという欠点もあります。

それを解消するため、「SFDCのデータをエクセルで参照、加工する」というソリューションもあります。

なかなか良いアイディアですよね。

調べてみるといくつかあるので、興味のある方はサーチしてみてください。

さて、それらのソリューションの多くは、無料ではないので、自作してみました。

同じアプローチを考えていて、自分でコーディングしたいという方の助けになるかもしれませんので、サンプルソースも掲載しておきます。

エクセルでSalesforceのデータを参照する方法

やりたいことは、こうです。

エクセルのマクロで、httpリクエストをgetしたり、postしたりすることができます。

また、Salesforceは、WebAPIを公開していますので、WebAPI経由でデータの取得が比較的容易にできます。通常はJavaなどのプログラミング言語を使ってバッチなどを作成するのですが、エクセル・マクロでそれが行えれば、コンパイルも必要ありませんし、少し修正したりするのも簡単だというわけです。

今回のマクロは、エクセルのセルに、ログインURLとログインID、パスワードを書き込むことで、それを使用して、ログインし、そこで取得したトークンを利用してクエリを投げるシンプルなものにします。画面のイメージはちょうど下のような感じです。

サンプルソース

実際のサンプルソースです。

Public gLoginURL As String
Public gUserName As String
Public gPassword As String
Public gAccessToken As String
Public gServerURL As String
Public gServiceURL As String
 
Sub btnLogin_Click()
 
 
 
    gLoginURL = Worksheets("Setting").Range("cLoginURL").Value
    gUserName = Worksheets("Setting").Range("cUserName").Value
        gPassword = Worksheets("Setting").Range("cPassword").Value
    'MsgBox gLoginURL
 
    Dim targetURL, loginSendData
 
    targetURL = gLoginURL & "/services/Soap/u/40.0"
 
    loginSendData = ""
 
 
    '   POSTで飛ばします
    Dim httpReq
    Set httpReq = CreateObject("Microsoft.XMLHTTP")
    httpReq.Open "POST", targetURL, False
    Call httpReq.setRequestHeader("Content-Type", "text/xml;charset=utf-8")
    Call httpReq.setRequestHeader("SOAPAction", "login")
     
    Dim postData As Variant
    postData = "<!--?xml version=""1.0"" encoding=""utf-8"" ?--><env:envelope xmlns:xsd="" http:="" www.w3.org="" 2001="" xmlschema""="" xmlns:xsi="" xmlschema-instance""="" xmlns:env="" schemas.xmlsoap.org="" soap="" envelope="" ""=""><env:body><n1:login xmlns:n1="" urn:partner.soap.sforce.com""=""><n1:username>" + gUserName + "</n1:username><n1:password>" + gPassword + "</n1:password></n1:login></env:body></env:envelope>"
     
    Call httpReq.Send(postData)
     
     
    Dim respData As String
  
    If httpReq.Status = 200 Then
        respData = httpReq.responseText
    End If
    MsgBox respData
     
     
    Dim XDoc As Object, root As Object
      
    Set XDoc = CreateObject("MSXML2.DOMDocument")
    XDoc.async = False: XDoc.validateOnParse = False
    XDoc.LoadXML (respData)
    Set root = XDoc.DocumentElement
     
    Set accessTokenField = XDoc.SelectNodes("//loginResponse/result/sessionId")
    gAccessToken = accessTokenField(0).Text
     
    Set serverUrlField = XDoc.SelectNodes("//loginResponse/result/serverUrl")
    gServerURL = serverUrlField(0).Text
     
      
    Set XDoc = Nothing
     
    'MsgBox gServerURL
     
     
    Dim regEx, Match, Matches As Object   ' 変数を作成します。
    Set regEx = CreateObject("VBScript.RegExp")   ' 正規表現を作成します。
    regEx.Pattern = "https://([A-Za-z0-9_\-\.]*)/services"   ' パターンを設定します。
    regEx.IgnoreCase = True   ' 大文字と小文字を区別しないように設定します。
    regEx.Global = True   ' 文字列全体を検索するように設定します。
    Set Matches = regEx.Execute(gServerURL)   ' 検索を実行します。
    For Each Match In Matches   ' Matches コレクションに対して繰り返し処理を行います。
        RetStr = ""
        RetStr = RetStr & Match.Value
    Next
     
    gServiceURL = RetStr
    
    'MsgBox gServiceURL
    
 
End Sub
 
 
 
 
Sub serviceQuery_Click()
 
     
    Dim restTargetURL
    restTargetURL = gServiceURL & "/data/v40.0/query/?q=select%20Id%20From%20Account"
    MsgBox restTargetURL
    MsgBox gAccessToken
     
    '   GETで飛ばします
    Set httpObj = CreateObject("Microsoft.XMLHTTP")
    httpObj.Open "GET", restTargetURL, False
    Call httpObj.setRequestHeader("Content-Type", "application/json; charset=UTF-8")
    Call httpObj.setRequestHeader("Authorization", "Bearer " + gAccessToken)
    Call httpObj.setRequestHeader("Accept", "application/xml")
    httpObj.Send (sendData)
     
    MsgBox httpObj.responseText
 
End Sub