rodrigocf
rodrigocf

Reputation: 2099

Export salesforce report as CSV

I'm trying to pull salesforce reports through python. I've tried this approach:

import requests

l = requests.get('sfinstanceurl/?un=user&pw=passw')

report = requests.get('sfinstanceurl/reportid?view=d&snip&export=1&enc=UTF-8&xf=csv',cookies=l.cookies)

print(report.content)

Also this one:

def sfdc_to_pd(reportid):

    login_data = {'un': 'your_username', 'pw': 'your_password'}

    with requests.session() as s:
    s.get('https://your_instance.salesforce.com', params = login_data)
    d = requests.get("https://your_instance.salesforce.com/{}?export=1&enc=UTF-8&xf=csv".format(reportid), headers=s.headers, cookies=s.cookies)
    lines = d.content.splitlines()
    reader = csv.reader(lines)
    data = list(reader)
    data = data[:-7]
    df = pd.DataFrame(data)
    df.columns = df.iloc[0]
    df = df.drop(0)
    return df
    print df

And for both, when i print the content I get this (even though the status response is always 200):

b'\r\n<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n<html>\n<head>\n    <meta HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">\n\n\n\n\n\n<script>\nif (this.SfdcApp && this.SfdcApp.projectOneNavigator) { SfdcApp.projectOneNavigator.handleRedirect(\'sfinstanceurl?ec=302&startURL=%2F00O0m000000JzRc%3Fview%3Dd%26enc%3DUTF-8%26export%3D1%26xf%3Dcsv%26snip%3D\'); }  else \nif (window.location.replace){ \nwindow.location.replace(\'sfinstanceurl?ec=302&startURL=%2F00O0m000000JzRc%3Fview%3Dd%26enc%3DUTF-8%26export%3D1%26xf%3Dcsv%26snip%3D\');\n} else {;\nwindow.location.href =\'sfinstanceurl?ec=302&startURL=%2F00O0m000000JzRc%3Fview%3Dd%26enc%3DUTF-8%26export%3D1%26xf%3Dcsv%26snip%3D\';\n} \n</script>\n\n</head>\n\n\n</html>\n\n\n\n\n\n<!-- Body events -->\n<script type="text/javascript">function bodyOnLoad(){if(window.PreferenceBits){window.PreferenceBits.prototype.csrfToken="null";};}function bodyOnBeforeUnload(){}function bodyOnFocus(){}function bodyOnUnload(){}</script>\n\t\t\t\n</body>\n</html>\n\n\n<!--\n...................................................................................................\n...................................................................................................\n...................................................................................................\n...................................................................................................\n-->\n'

My company uses SSO, so security tokens are not something i have to try a different approach. Am I missing something? Why do I not get the report in the content?

EDIT:

I also just tried this approach:

from simple_salesforce import Salesforce
import requests
import base64
import json

sf = Salesforce(username=    #login
                ,password=  # password
                ,security_token= # token )

print "get sid ", sf.session_id

response = requests.get("https://instancename/reportid?view=d&snip&export=1&enc=UTF-8&xf=csv",
                  headers = sf.headers, cookies = {'sid' : sf.session_id})

response.content

It still returns the same HTML object.

Upvotes: 1

Views: 4661

Answers (1)

Tiaan Swart
Tiaan Swart

Reputation: 624

Looks like you are running reports from the SF instance directly, this will always return HTML as it is not an API call.

To access Reports through an API please refer to the documentation for Salesforce Reports and Dashboards REST API:

https://developer.salesforce.com/docs/atlas.en-us.api_analytics.meta/api_analytics/sforce_analytics_rest_api_intro.htm

Below is a link to the resources specifically for reports:

https://developer.salesforce.com/docs/atlas.en-us.api_analytics.meta/api_analytics/sforce_analytics_rest_api_get_reportdata.htm

When using Simple Salesforce you can easily call the API, like this:

from simple_salesforce import Salesforce
import requests
import base64
import json

sf = Salesforce(username=[username],password=[password],security_token=[token])
reportId = '00OR0000000K2UeMAK'
reportRESTPath = ('analytics/reports/{id}'.format(id='00OR0000000K2UeMAK')

# Synchronous report get

reportJSON = sf.restful(reportRESTPath, {'includeDetails': 'true'})

# Asynchronous report create

asyncJobJSON = sf.restful(reportRESTPath, {'includeDetails': 'true'}, 'POST')

# Asynchronous report get

reportJSON = sf.restful(('{basePath}/instances/{instanceId}'.format(basePath=reportRESTPath,instanceId=asyncJobJSON.Id), {'includeDetails': 'true'})

Upvotes: 3

Related Questions