使用基于过滤器的 Apps 脚本从 Salesforce 获取报告数据
Get report data from Salesforce with Apps Script based on filter
尝试从 Saleforce Analytics API 获取数据到 Google spreadsheet 基于此 handy script on Github。除了 运行 整个报告之外,我试图通过基于同一文档的不同 sheet 上的电子邮件列表列的电子邮件过滤器。
// Use the Analytics API to get report data
function runContactsReport() {
var reportId = '';
var sheetName = 'Report';
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v29.0/analytics/reports/" + reportId + "?includeDetails=true"; // Actual request for report Data
var response = UrlFetchApp.fetch(queryUrl, { method : "GET", headers : { "Authorization" : "OAuth "+sfService.getAccessToken() } });
var queryResult = JSON.parse(response.getContentText());
// sheet to insert reports
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
//emails to filter on
var dataSheet = ss1.getSheetByName('DATA');
var emails = getColumnNrByName(dataSheet, 'Email')
var emailFilters = dataSheet.getRange(2, emailds, dataSheet.getLastRow() -1).getValues();
var answer = queryResult.factMap["T!T"].rows; // assumes tabular report
var headers = queryResult.reportExtendedMetadata.detailColumnInfo;
var headname = queryResult.reportMetadata.detailColumns;
var filters = queryResult.reportMetadata.reportFilters; //get filters
var myArray = [];
var tempArray = [];
for (i = 0 ; i < headname.length ; i++) {
tempArray.push(headers[headname[i]].label);
}
myArray.push(tempArray);
for (i = 0 ; i < answer.length ; i++ ) {
var tempArray = [];
function getData(element,index,array) {
tempArray.push(array[index].label)
}
answer[i].dataCells.forEach(getData);
myArray.push(tempArray);
}
var lastRow = sheet.getLastRow();
if (lastRow < 1) lastRow = 1;
sheet.getRange(1,1,lastRow, myArray[0].length).clearContent();
sheet.getRange(1,1, myArray.length, myArray[0].length).setValues(myArray);
}
为此,我需要发回带有已编辑过滤器的报告元数据对象。
以下是每个 Salesforce API:
返回的一些典型元数据
'{reportMetadata":{"name":"MerchandiseReport","id":"00OD0000001ZbP7MAK","developerName":"MerchandiseReport","reportType":{"type":"MerchandiseList","label":"Merchandise"},"reportFormat":"MATRIX","reportBooleanFilter":null,"reportFilters":[{"column": "QUANTITY", "operator":"greaterThan", "value":"12"}],"detailColumns":["MERCHANDISE.NAME","CREATED_DATE","QUANTITY"],"currency":null,"aggregates":["RowCount"],"groupingsDown":[{"name":"CONTACT2.COUNTRY_CODE","sortOrder":"Asc","dateGranularity":"None"}],"groupingsAcross":[{"name":"OWNER","sortOrder":"Asc","dateGranularity":"None"}]}}'
很遗憾,我不知道如何在 Apps 脚本中传递它。感谢您的帮助!
更新:与这段代码作斗争后,这里是最新的结果。根据 API 说明,我需要通过 POST 请求来传递过滤器参数。向执行异步资源发送 POST 请求。如果您要传递过滤器,请将它们包含在 POST 请求元数据中。请求 returns 存储 运行 结果的实例 ID。
这就是我所拥有的:
function filterReport(){
var reportId = '00O33000004Dels';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName('DATA');
var emailds = getColumnNrByName(dataSheet, 'Email');
var emailFilters = dataSheet.getRange(2, emailds, dataSheet.getLastRow() -1).getValues();
for (var i = 0; i < emailFilters.length; i++) {
var payload = JSON.stringify({
'reportMetadata': {
'reportFilters': [{
'value' : emailFilters[i][0],
'column': 'EMAIL',
'operator': 'equals'
}]
}
});
filter(reportId, payload);
}
}
function filter(reportId, payload) {
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances";
var options = {
'headers': {
'Authorization' : 'Bearer ' + sfService.getAccessToken()
},
'contentType' : 'application/json',
'method' : 'POST',
'payload' : payload
};
var response = UrlFetchApp.fetch(queryUrl, options);
if (response.getResponseCode() == 200) {
var params = JSON.parse(response.getContentText());
//Logger.log(response.getContentText());
var filterId = params.id;
//Logger.log(filterId);
Logger.log(response.getContentText())
}
}
这 returns 不是一个实例 ID,而是 4 个实例 ID,正如我在样本传播中所具有的那样sheet...我需要一个 ID 来传递 4 个结果(根据本示例)。
之后,我需要用这个实例 ID 发送 GET 请求,这样我就可以将带有过滤器的数据放入传播sheet。
我有这个功能,它有点用,但我不知道如何从我的 POST 请求中自动将实例 ID 传递给它...
// Use the Analytics API to get report data
// The try-catch can be removed if you do not need to track errors
function runContactsReport() {
var reportId = '00O33000004Dels';
var sheetName = 'Contact Email Validation Report';
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances/0LG33000005ZJdqGAG"; // Actual request for report Data
var response = UrlFetchApp.fetch(queryUrl, { method : "GET", headers : { "Authorization" : "OAuth "+sfService.getAccessToken() } });
var queryResult = JSON.parse(response.getContentText());
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
var answer = queryResult.factMap["T!T"].rows; // assumes tabular report
var headers = queryResult.reportExtendedMetadata.detailColumnInfo;
var headname = queryResult.reportMetadata.detailColumns;
var myArray = [];
var tempArray = [];
for (i = 0 ; i < headname.length ; i++) {
tempArray.push(headers[headname[i]].label);
}
myArray.push(tempArray);
for (i = 0 ; i < answer.length ; i++ ) {
var tempArray = [];
function getData(element,index,array) {
tempArray.push(array[index].label)
}
answer[i].dataCells.forEach(getData);
myArray.push(tempArray);
}
var lastRow = sheet.getLastRow();
if (lastRow < 1) lastRow = 1;
sheet.getRange(1,1,lastRow, myArray[0].length).clearContent();
sheet.getRange(1,1, myArray.length, myArray[0].length).setValues(myArray);
}
所以,我又卡住了..请帮忙!
我终于让它工作了。希望它会对某人有所帮助。我遇到的唯一问题是,偶尔当我 运行 运行ContactsReport() 时,它返回错误 - “TypeError:无法从 null 读取 属性 "T!T"。”但后来 运行 很好 - 非常令人费解......这是我得到的:
//this is POST request to pass filters based on email column into report
function filterContacts() {
var reportId = 'YOUR REPORT ID'; //SF Contacts Report ID
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName('DATA');
var emailds = getColumnNrByName(dataSheet, 'Email'); //custom function that finds header name and returns column umber
var emailFilters = dataSheet.getRange(2, emailds, dataSheet.getLastRow() -1).getValues(); //column with emails
//put all emails in one comma separated string, so we get one instance ID
var emails = emailFilters.toString().split(",").join();
var payload = JSON.stringify({
'reportMetadata': {
'reportFilters': [{
'value' : emails,
'column': 'EMAIL',
'operator': 'equals'
}]
}
});
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances";
var options = {
'headers': {
'Authorization' : 'Bearer ' + sfService.getAccessToken()
},
'contentType' : 'application/json',
'method' : 'POST',
'payload': payload
};
//Logger.log(options)
var response = UrlFetchApp.fetch(queryUrl, options);
if (response.getResponseCode() == 200) {
var params = JSON.parse(response.getContentText());
}
//Logger.log("my id is:" + params.id);
return params.id; //return instance ID
}
// use returned instance ID to run report based on email filter
function runContactsReport() {
filterContacts();
var reportId = 'YOUR REPORT ID'; //SF Contact Email Validation Report
Utilities.sleep(200);// pause in the loop for 200 milliseconds
var instanceId = filterContacts();
// Logger.log("And my id is:" + instanceId);
var sheetName = 'Contact Email Validation Report';
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances/" + instanceId; // Actual request for report Data
var response = UrlFetchApp.fetch(queryUrl, { method : "GET", headers : { "Authorization" : "OAuth "+sfService.getAccessToken() } });
var queryResult = JSON.parse(response.getContentText());
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
var answer = queryResult.factMap["T!T"].rows; // assumes tabular report
var headers = queryResult.reportExtendedMetadata.detailColumnInfo;
var headname = queryResult.reportMetadata.detailColumns;
var filters = queryResult.reportMetadata.reportFilters;
//Logger.log(filters)
var myArray = [];
var tempArray = [];
for (i = 0 ; i < headname.length ; i++) {
tempArray.push(headers[headname[i]].label);
}
myArray.push(tempArray);
for (i = 0 ; i < answer.length ; i++ ) {
var tempArray = [];
function getData(element,index,array) {
tempArray.push(array[index].label)
}
answer[i].dataCells.forEach(getData);
myArray.push(tempArray);
}
var lastRow = sheet.getLastRow();
if (lastRow < 1) lastRow = 1;
sheet.getRange(1,1,lastRow, myArray[0].length).clearContent();
sheet.getRange(1,1, myArray.length, myArray[0].length).setValues(myArray);
}
尝试从 Saleforce Analytics API 获取数据到 Google spreadsheet 基于此 handy script on Github。除了 运行 整个报告之外,我试图通过基于同一文档的不同 sheet 上的电子邮件列表列的电子邮件过滤器。
// Use the Analytics API to get report data
function runContactsReport() {
var reportId = '';
var sheetName = 'Report';
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v29.0/analytics/reports/" + reportId + "?includeDetails=true"; // Actual request for report Data
var response = UrlFetchApp.fetch(queryUrl, { method : "GET", headers : { "Authorization" : "OAuth "+sfService.getAccessToken() } });
var queryResult = JSON.parse(response.getContentText());
// sheet to insert reports
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
//emails to filter on
var dataSheet = ss1.getSheetByName('DATA');
var emails = getColumnNrByName(dataSheet, 'Email')
var emailFilters = dataSheet.getRange(2, emailds, dataSheet.getLastRow() -1).getValues();
var answer = queryResult.factMap["T!T"].rows; // assumes tabular report
var headers = queryResult.reportExtendedMetadata.detailColumnInfo;
var headname = queryResult.reportMetadata.detailColumns;
var filters = queryResult.reportMetadata.reportFilters; //get filters
var myArray = [];
var tempArray = [];
for (i = 0 ; i < headname.length ; i++) {
tempArray.push(headers[headname[i]].label);
}
myArray.push(tempArray);
for (i = 0 ; i < answer.length ; i++ ) {
var tempArray = [];
function getData(element,index,array) {
tempArray.push(array[index].label)
}
answer[i].dataCells.forEach(getData);
myArray.push(tempArray);
}
var lastRow = sheet.getLastRow();
if (lastRow < 1) lastRow = 1;
sheet.getRange(1,1,lastRow, myArray[0].length).clearContent();
sheet.getRange(1,1, myArray.length, myArray[0].length).setValues(myArray);
}
为此,我需要发回带有已编辑过滤器的报告元数据对象。 以下是每个 Salesforce API:
返回的一些典型元数据'{reportMetadata":{"name":"MerchandiseReport","id":"00OD0000001ZbP7MAK","developerName":"MerchandiseReport","reportType":{"type":"MerchandiseList","label":"Merchandise"},"reportFormat":"MATRIX","reportBooleanFilter":null,"reportFilters":[{"column": "QUANTITY", "operator":"greaterThan", "value":"12"}],"detailColumns":["MERCHANDISE.NAME","CREATED_DATE","QUANTITY"],"currency":null,"aggregates":["RowCount"],"groupingsDown":[{"name":"CONTACT2.COUNTRY_CODE","sortOrder":"Asc","dateGranularity":"None"}],"groupingsAcross":[{"name":"OWNER","sortOrder":"Asc","dateGranularity":"None"}]}}'
很遗憾,我不知道如何在 Apps 脚本中传递它。感谢您的帮助!
更新:与这段代码作斗争后,这里是最新的结果。根据 API 说明,我需要通过 POST 请求来传递过滤器参数。向执行异步资源发送 POST 请求。如果您要传递过滤器,请将它们包含在 POST 请求元数据中。请求 returns 存储 运行 结果的实例 ID。
这就是我所拥有的:
function filterReport(){
var reportId = '00O33000004Dels';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName('DATA');
var emailds = getColumnNrByName(dataSheet, 'Email');
var emailFilters = dataSheet.getRange(2, emailds, dataSheet.getLastRow() -1).getValues();
for (var i = 0; i < emailFilters.length; i++) {
var payload = JSON.stringify({
'reportMetadata': {
'reportFilters': [{
'value' : emailFilters[i][0],
'column': 'EMAIL',
'operator': 'equals'
}]
}
});
filter(reportId, payload);
}
}
function filter(reportId, payload) {
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances";
var options = {
'headers': {
'Authorization' : 'Bearer ' + sfService.getAccessToken()
},
'contentType' : 'application/json',
'method' : 'POST',
'payload' : payload
};
var response = UrlFetchApp.fetch(queryUrl, options);
if (response.getResponseCode() == 200) {
var params = JSON.parse(response.getContentText());
//Logger.log(response.getContentText());
var filterId = params.id;
//Logger.log(filterId);
Logger.log(response.getContentText())
}
}
这 returns 不是一个实例 ID,而是 4 个实例 ID,正如我在样本传播中所具有的那样sheet...我需要一个 ID 来传递 4 个结果(根据本示例)。
之后,我需要用这个实例 ID 发送 GET 请求,这样我就可以将带有过滤器的数据放入传播sheet。
我有这个功能,它有点用,但我不知道如何从我的 POST 请求中自动将实例 ID 传递给它...
// Use the Analytics API to get report data
// The try-catch can be removed if you do not need to track errors
function runContactsReport() {
var reportId = '00O33000004Dels';
var sheetName = 'Contact Email Validation Report';
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances/0LG33000005ZJdqGAG"; // Actual request for report Data
var response = UrlFetchApp.fetch(queryUrl, { method : "GET", headers : { "Authorization" : "OAuth "+sfService.getAccessToken() } });
var queryResult = JSON.parse(response.getContentText());
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
var answer = queryResult.factMap["T!T"].rows; // assumes tabular report
var headers = queryResult.reportExtendedMetadata.detailColumnInfo;
var headname = queryResult.reportMetadata.detailColumns;
var myArray = [];
var tempArray = [];
for (i = 0 ; i < headname.length ; i++) {
tempArray.push(headers[headname[i]].label);
}
myArray.push(tempArray);
for (i = 0 ; i < answer.length ; i++ ) {
var tempArray = [];
function getData(element,index,array) {
tempArray.push(array[index].label)
}
answer[i].dataCells.forEach(getData);
myArray.push(tempArray);
}
var lastRow = sheet.getLastRow();
if (lastRow < 1) lastRow = 1;
sheet.getRange(1,1,lastRow, myArray[0].length).clearContent();
sheet.getRange(1,1, myArray.length, myArray[0].length).setValues(myArray);
}
所以,我又卡住了..请帮忙!
我终于让它工作了。希望它会对某人有所帮助。我遇到的唯一问题是,偶尔当我 运行 运行ContactsReport() 时,它返回错误 - “TypeError:无法从 null 读取 属性 "T!T"。”但后来 运行 很好 - 非常令人费解......这是我得到的:
//this is POST request to pass filters based on email column into report
function filterContacts() {
var reportId = 'YOUR REPORT ID'; //SF Contacts Report ID
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName('DATA');
var emailds = getColumnNrByName(dataSheet, 'Email'); //custom function that finds header name and returns column umber
var emailFilters = dataSheet.getRange(2, emailds, dataSheet.getLastRow() -1).getValues(); //column with emails
//put all emails in one comma separated string, so we get one instance ID
var emails = emailFilters.toString().split(",").join();
var payload = JSON.stringify({
'reportMetadata': {
'reportFilters': [{
'value' : emails,
'column': 'EMAIL',
'operator': 'equals'
}]
}
});
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances";
var options = {
'headers': {
'Authorization' : 'Bearer ' + sfService.getAccessToken()
},
'contentType' : 'application/json',
'method' : 'POST',
'payload': payload
};
//Logger.log(options)
var response = UrlFetchApp.fetch(queryUrl, options);
if (response.getResponseCode() == 200) {
var params = JSON.parse(response.getContentText());
}
//Logger.log("my id is:" + params.id);
return params.id; //return instance ID
}
// use returned instance ID to run report based on email filter
function runContactsReport() {
filterContacts();
var reportId = 'YOUR REPORT ID'; //SF Contact Email Validation Report
Utilities.sleep(200);// pause in the loop for 200 milliseconds
var instanceId = filterContacts();
// Logger.log("And my id is:" + instanceId);
var sheetName = 'Contact Email Validation Report';
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances/" + instanceId; // Actual request for report Data
var response = UrlFetchApp.fetch(queryUrl, { method : "GET", headers : { "Authorization" : "OAuth "+sfService.getAccessToken() } });
var queryResult = JSON.parse(response.getContentText());
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
var answer = queryResult.factMap["T!T"].rows; // assumes tabular report
var headers = queryResult.reportExtendedMetadata.detailColumnInfo;
var headname = queryResult.reportMetadata.detailColumns;
var filters = queryResult.reportMetadata.reportFilters;
//Logger.log(filters)
var myArray = [];
var tempArray = [];
for (i = 0 ; i < headname.length ; i++) {
tempArray.push(headers[headname[i]].label);
}
myArray.push(tempArray);
for (i = 0 ; i < answer.length ; i++ ) {
var tempArray = [];
function getData(element,index,array) {
tempArray.push(array[index].label)
}
answer[i].dataCells.forEach(getData);
myArray.push(tempArray);
}
var lastRow = sheet.getLastRow();
if (lastRow < 1) lastRow = 1;
sheet.getRange(1,1,lastRow, myArray[0].length).clearContent();
sheet.getRange(1,1, myArray.length, myArray[0].length).setValues(myArray);
}