2016-12-06 1 views
1

Beatbox를 사용하여 Pandas DataFrame으로 SalesForce 보고서를 구문 분석 한 사람이 있습니까? 그래서 몇 가지 예제가 있지만 그 중 누구도 포괄적 인 솔루션을 제공하지 않았으며 적어도 내가 인식하지 못했던 것은 아닙니다.Beatbox를 사용하여 Pandas DataFrame의 Salesforce 보고서를 구문 분석하십시오.

#!/usr/bin/env python3 

import beatbox 
import pandas as pd 


sf = beatbox._tPartnerNS 
service = beatbox.Client() 
service.serverUrl = 'https://login.salesforce.com/services/Soap/u/38.0' 
service.login('my-username', 'my-password') 

report_id = '00myreport4G3V' 

query = "SELECT Name FROM Report where id = '{}'".format(report_id) 
query_result = service.query(query) 

이것은 단지 이름을 선택하는 것이지만 이상적으로는 보고서의 내용을 DataFrame에로드하고 싶습니다. 어떤 도움을 주시겠습니까?

답변

0

보고서 데이터는 Salesforce Reports and Dashboards REST API에 의해 검색 될 수 있습니다. Summer'15 (ver 34.0) 이후 Salesforce에서 작동합니다.

REST API로 인해 Simple-salesforce 패키지와 함께 예제를 작성했습니다. (단지 requests 패키지를 간단 영업 인력없이 재 작성 및 비트 박스에서 API 세션을 사용하여, 코드의 약 10 추가 라인을 작성하고 설치하는 그러나 수 있습니다.)

범용 코드

from collections import OrderedDict 
from simple_salesforce import Salesforce 
import pandas as pd 
import json 

class SfReportsApi(Salesforce): 
    def __init__(self, *args, **kwargs): 
     super(SfReportsApi, self).__init__(*args, **kwargs) 

    def describe_report(self, report_id): 
     return self._call_report(report_id, command='/describe') 

    def to_pandas_dataframe(self, report_id, metadata=None): 
     """SF report details exported to DataFrame, can be modified by metadata""" 
     resp = self._call_report(report_id, metadata=metadata) 
     if not resp['allData']: 
      print("Detailed data have been truncated to the usual report limit (2000).") 
     columns = [] 
     converters = [] 
     get_label = lambda x: x['label'] 
     sf_pandas_map = { 
      'boolean': lambda x: x['value'], 
      'currency': lambda x: x['value']['amount'], 
      'date': lambda x: pd.Timestamp(x['value']), 
      'datetime': lambda x: pd.Timestamp(x['value']), 
      'double': lambda x: x['value'], 
      'picklist': get_label, 
      'string': get_label, 
      'textarea': get_label, 
     } 
     for col in resp['reportExtendedMetadata']['detailColumnInfo'].values(): 
      columns.append(col['label']) 
      converters.append(sf_pandas_map.get(col['dataType'], get_label)) 
     data = [[conv(cell) for conv, cell in zip(converters, row['dataCells'])] 
       for sect_key, section in resp['factMap'].items() 
        if sect_key != 'T!T' 
         for row in section['rows'] 
       ] 
     df = pd.DataFrame(data, columns=columns) 
     return df 

    def _call_report(self, report_id, metadata=None, command=None): 
     url = '{}analytics/reports/{}{}'.format(self.base_url, report_id, command or '') 
     data = json.dumps({'reportMetadata': metadata}) if metadata else None 
     resp = self._call_salesforce('POST' if metadata else 'GET', url, data=data) 
     return resp.json(object_pairs_hook=OrderedDict) 

사용 예

report_id = '00O24000004qtI4EAI' 
# set Salesforce session_id some way (by login or reused from other app) 
sf = SfReportsApi(username='[email protected]', password='password', security_token='token') 
# sf = SfReportsApi(instance_url='https://na1.salesforce.com', session_id='') 
# get report metadata if useful 
metadata = sf.describe_report(report_id)['reportMetadata'] 
# modify them or write only the modified keys, e.g. change filters or remove subtotals etc. 
metadata = { 
    'orderBy': ['ACCOUNT.NAME'], 
    'reportFilters': [{'value': 'W', 'column': 'ACCOUNT.NAME', 'operator': greaterOrEqual'}] 
} 
df = sf.to_pandas_dataframe(report_id, metadata) 

동적으로관한 항목, 필터 등의 분류 (문서에 추가 할 수있다). 방법 to_pandas_dataframe은 세부 정보가있는 일반 테이블 형식 보고서 용이며 선택 사항으로 하나의 총계와 한 단계 이상의 부분합이 될 수 있습니다. 더 복잡한 보고서 (Decode the Fact Map 또는 cheatsheet에 대한 문서 참조)에서 데이터를 검색 할 수도 있지만 실행하기 전에 메타 데이터 매개 변수를 사용하여 즉시 제거하기가 쉽기 때문에 구현되지 않았습니다.

2000 개의 세부 데이터 행만보고 할 수 있습니다. 필터가있는 여러 요청을 사용하여 모든 데이터를 볼 수 있습니다.

+0

gist [Python의 Salesforce 보고서 데이터 분석] (https://gist.github.com/hynekcer/a9d72c959c4569af32141e2586c7b86e)에이 코드를 추가했습니다. – hynekcer

관련 문제