Salesforce Reports and Dashboards API via Apexを使ってみる


以下の質問があったので、私も実際に試してみました。

+ [Apexのテストメソッド内に以下オブジェクトへのデータをインサートしてみたが、レポートに対象データとして読み込みされず、テストができない。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cm91q)
+ [特定の項目が「検索条件」に使用されているレポートを一覧化したい](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000PWSvn)


# 参考資料

+ [Salesforce Reports and Dashboards API via Apex](https://developer.salesforce.com/docs/atlas.ja-jp.248.0.apexcode.meta/apexcode/apex_analytics_intro.htm)
+ [Apex を使用したレポートとダッシュボード API](https://salesforce-germany.de/en/reports-and-dashboads-api-with-apex/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ca8489fd-b546-a811-9b39-be9014599abb.png)

# 私のコード

```Java
@isTest
public class ReportsInApexTest {
    //https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_analytics_test_reports.htm
    
    @isTest(SeeAllData='true')
    public static void testAsyncReportWithTestData() {
        List <Report> reportList = [SELECT Id,DeveloperName FROM Report where
                                    DeveloperName = 'New_Report_20240619'];
        String reportId = (String)reportList.get(0).get('Id');
        System.debug('******** reportId  ' + reportId );
        
        
        //create recird
        Campaign c = new Campaign();
        c.IsActive = true;
        c.Name = 'test Campaign';
        c.EndDate = date.today();
        c.StartDate= date.today();
        c.Status = 'Planned';
        insert c;
        
        Lead l = new Lead();
        l.Company = 'myCompany';
        l.LastName = 'test';
        insert l;
        
        CampaignMember cm = new CampaignMember();
        cm.CampaignId = c.Id;
        cm.LeadId = l.Id;
        insert cm;
        
        List<CampaignMember> cmList = [select Id,CampaignId,LeadId from CampaignMember];
        System.debug('******** cmList  ' + cmList );
        
        Reports.ReportMetadata reportMetadata =
          Reports.ReportManager.describeReport(reportId).getReportMetadata();
        
        
        Test.startTest();
        
        Reports.ReportInstance instanceObj =
            Reports.ReportManager.runAsyncReport(reportId,reportMetadata,false);
        String instanceId = instanceObj.getId();
        
        Test.stopTest();
        
        instanceObj = Reports.ReportManager.getReportInstance(instanceId);
        System.assertEquals(instanceObj.getStatus(),'Success');
        System.debug('******** instanceObj  ' + instanceObj );
        Reports.ReportResults result = instanceObj.getReportResults();
        System.debug('******** result  ' + result );
        //T!T はレポートの合計
        Reports.ReportFact grandTotal = (Reports.ReportFact)result.getFactMap().get('T!T');
        System.debug('******** grandTotal  ' + grandTotal );
        System.debug('******** grandTotal.getAggregates()  ' + grandTotal.getAggregates() );
        //System.assertEquals(1,(Decimal)grandTotal.getAggregates().get(1).getValue());
    }
    
    @isTest(SeeAllData='true')
    public static void testSyncReportWithTestData() {
        
        //create recird
        Campaign c = new Campaign();
        c.IsActive = true;
        c.Name = 'test Campaign';
        c.EndDate = date.today();
        c.StartDate= date.today();
        c.Status = 'Planned';
        insert c;
        
        Lead l = new Lead();
        l.Company = 'myCompany';
        l.LastName = 'test';
        insert l;
        
        CampaignMember cm = new CampaignMember();
        cm.CampaignId = c.Id;
        cm.LeadId = l.Id;
        insert cm;
        
        List <Report> reportList = [SELECT Id,DeveloperName FROM Report where
                                    DeveloperName = 'New_Leads_Report_xrc'];
        String reportId = (String)reportList.get(0).get('Id');
        System.debug('******** reportId  ' + reportId );
        
        Reports.ReportMetadata reportMetadata =
            Reports.ReportManager.describeReport(reportId).getReportMetadata();
        System.debug('******** reportMetadata  ' + reportMetadata );
        
        List<CampaignMember> cmList = [select Id,CampaignId,LeadId from CampaignMember];
        System.debug('******** cmList  ' + cmList );
        
        // Add a filter.
        List<Reports.ReportFilter> filters = new List<Reports.ReportFilter>(); 
        Reports.ReportFilter newFilter = new Reports.ReportFilter();
        newFilter.setColumn('TITLE');
        //newFilter.setOperator('not equal to');
        newFilter.setOperator('equals');
        newFilter.setValue('test');
        //filters.add(newFilter);
        //reportMetadata.setReportFilters(filters);
        
        Reports.ReportResults result =
            Reports.ReportManager.runReport(reportId); 
            //Reports.ReportManager.runReport(reportId,reportMetadata,true); 
        	
        Reports.ReportFact grandTotal = (Reports.ReportFact)result.getFactMap().get('T!T');
        System.debug('******** grandTotal  ' + grandTotal );
        
        System.debug('******** result  ' + result );
       
    }
}
```

私も数種類のレポートで実行しましたが、テストクラス内で作成したレコードは完全に無視されてしまいます。実際のデータしか読まないですね。

またフィルターを追加したのですが、実際のデータに対しても全く機能しません。

同じような質問を見つけました。

If I manually create an Opportunity in the Org with a Name of 'ApexTestOpp' then the assertion succeeds. The report running in the unit test is not seeing the records created by the unit test.

I tried to report this through Salesforce Support and they said my company would need to upgrade to Premium Support in order for them to even take a look at it, which is completely absurd. This is broken. Salesforce needs to fix it. I'm posting here in the hope that someone from Salesforce sees it and can do something about it.

https://salesforce.stackexchange.com/questions/411766/running-and-filtering-reports-in-apex

### 結論

+ 説明と違って既存のレコードにしか使えないようです。
+ フィルターの追加も機能しません。