SalesforceにおけるWebサービスコールアウトのテスト完全ガイド

SalesforceでApexを使ったレポートデータの取得方法


SalesforceでApexを使用したレポートデータ取得の実践ガイド

Salesforceでレポートデータをプログラム的に取得する際、エラー処理やデバッグログの記録を含む安全な方法を使用することが推奨されます。本記事では、Apexを利用してレポートデータを取得し、構造化された結果を返す方法について解説します。さらに、エラー発生時のログ記録やデータ処理のサンプルコードも含めています。


概要

以下のポイントに焦点を当てた実装:

  1. 構造化された結果の返却: 成功状態、エラーメッセージ、サマリーデータ、詳細行データを含む`Map<String, Object>`形式で結果を返します。
  2. エラー処理: 実行中のエラーをキャッチし、処理を中断せずに適切なエラーメッセージを返します。
  3. ログの記録: 詳細なデバッグログを記録し、問題発生時に迅速なトラブルシューティングを可能にします。

コード実装

メインクラス:ReportDataRetriever

public class ReportDataRetriever {
    /**
     * 指定されたレポートの開発者名(DeveloperName)に基づき、
     * レポートデータを取得して構造化された結果を返す。
     * 
     * @param reportDeveloperName レポートのDeveloperName
     * @return Map<String, Object> 結果を含むマップ
     */
    public static Map<String, Object> getReportData(String reportDeveloperName) {
        // 結果を格納するMapを初期化
        Map<String, Object> result = new Map<String, Object>();
        result.put('success', false); // 初期状態: 成功ではない
        result.put('message', '');   // エラーメッセージ用
        result.put('summaryData', new List<Object>()); // サマリーデータ用
        result.put('detailData', new List<Object>());  // 詳細行データ用

        try {
            // ステップ1: レポートIDを取得
            List<Report> reportList = [SELECT Id, DeveloperName FROM Report WHERE DeveloperName = :reportDeveloperName LIMIT 1];
            if (reportList.isEmpty()) {
                result.put('message', '指定されたDeveloperNameのレポートが見つかりません: ' + reportDeveloperName);
                return result;
            }
            String reportId = reportList[0].Id;

            // ステップ2: レポートを実行
            Reports.ReportResults results = Reports.ReportManager.runReport(reportId, true);

            // ステップ3: グルーピング情報を取得
            Reports.Dimension dim = results.getGroupingsDown();
            if (dim == null || dim.getGroupings().isEmpty()) {
                result.put('message', 'レポートにグルーピングがありません。');
                return result;
            }
            Reports.GroupingValue groupingVal = dim.getGroupings()[0];

            // ステップ4: FactMapキーを構築し、詳細データを取得
            String factMapKey = groupingVal.getKey() + '!T';
            Reports.ReportFactWithDetails factDetails = (Reports.ReportFactWithDetails)results.getFactMap().get(factMapKey);

            if (factDetails == null) {
                result.put('message', '指定されたキーに対応するデータが見つかりません: ' + factMapKey);
                return result;
            }

            // ステップ5: サマリー値を取得
            List<Map<String, Object>> summaryData = new List<Map<String, Object>>();
            for (Reports.SummaryValue sumVal : factDetails.getAggregates()) {
                summaryData.add(new Map<String, Object>{
                    'label' => sumVal.getLabel(),
                    'value' => sumVal.getValue()
                });
            }
            result.put('summaryData', summaryData);

            // ステップ6: 詳細行データを取得
            List<List<Object>> detailData = new List<List<Object>>();
            for (Reports.ReportDetailRow row : factDetails.getRows()) {
                List<Object> rowData = new List<Object>();
                for (Reports.ReportDataCell cell : row.getDataCells()) {
                    rowData.add(cell.getValue());
                }
                detailData.add(rowData);
            }
            result.put('detailData', detailData);

            result.put('success', true);
            result.put('message', 'レポートデータの取得に成功しました');
        } catch (Exception e) {
            // エラー処理: メッセージを格納し、デバッグログに記録
            result.put('message', 'レポートデータ取得中にエラーが発生しました: ' + e.getMessage());
            System.debug(LoggingLevel.ERROR, 'Error in ReportDataRetriever.getReportData: ' + e.getMessage());
            System.debug(LoggingLevel.ERROR, 'スタックトレース: ' + e.getStackTraceString());
        }

        return result;
    }
}

呼び出しコード例

Map<String, Object> reportResult = ReportDataRetriever.getReportData('Your_Report_Developer_Name');

if ((Boolean)reportResult.get('success')) {
    List<Map<String, Object>> summaryData = (List<Map<String, Object>>)reportResult.get('summaryData');
    List<List<Object>> detailData = (List<List<Object>>)reportResult.get('detailData');
    
    // サマリーデータの処理
    System.debug('サマリーデータ:');
    for (Map<String, Object> summary : summaryData) {
        System.debug('ラベル: ' + summary.get('label') + ', 値: ' + summary.get('value'));
    }
    
    // 詳細行データの処理
    System.debug('詳細行データ:');
    for (List<Object> row : detailData) {
        System.debug('行: ' + row);
    }
} else {
    System.debug('エラー: ' + reportResult.get('message'));
}

使用例

  1. 正常な結果の例:
サマリーデータ:
ラベル: 合計売上, 値: 50000
ラベル: 総販売数, 値: 3000

詳細行データ:
行: [500, 100]
行: [400, 200]
  1. エラー発生時の例:
エラー: 指定されたDeveloperNameのレポートが見つかりません: Your_Report_Developer_Name

コメント