CData Software Blog

クラウド連携のCData Software の技術ブログです。

D365 for Sales 営業案件データをステージごとにグルーピングした一覧表を C# WPF アプリで作ってみる(Infragistics WPF XamDataGrid & CData Dynamics 365 for Sales Driver)

こんにちは! CData Software Japan リードエンジニアの杉本です。

Dynamics 365 for Sales で営業案件を俯瞰したい場合、よくパイプラインステージ(提案段階)や受注確度に応じて、データをグルーピングして見えるようにしたい、といった要望がよくあるなと思います。

その場合「Excelにデータをエクスポートして、ピボットテーブルを使う」もしくは「SSRS(SQL Server Reporting Service)などのレポーティングツールを使う」みたいなアプローチがあると思うんですが、前者は都度データを最新化しなければいけない、後者はソースが固定的で柔軟性に欠けるといった点があります。

そこでそんな要望に応えるために、今回はC# WPFベースを使って、柔軟なグルーピング機能を備えたWindows 用アプリケーションを作ってみました。

どんなことができるの?

今回作ったのは以下のようなアプリケーションです。ほぼHelpなどに記載されているサンプルコードを組み合わせるだけで、このようなアプリケーションが実現可能です。

https://cdatajbuilds.s3-ap-northeast-1.amazonaws.com/sugimototest/xamDataGrid.gif

単純なGridのアプリケーションに見えますが

f:id:sugimomoto:20190715224431p:plain

以下のようにProcessStage(stepname)でグルーピングし、表示することができるようになっています。

f:id:sugimomoto:20190715224437p:plain

使うもの1 Infragistics WPF XamDataGrid

今回のWPFアプリケーションでは、Infragistics社で提供されている WPF UIコンポーネントの中から「XamDataGrid」という高機能なデータグリッドコンポーネントを利用して作成しました。

「XamDataGrid」を使うことで、Windows標準で提供されているDataGridでは実現できない、グルーピングやフィルターなど柔軟な一覧表示処理を手軽にアプリケーションへ組み込むことが可能です。

Infragistics WPFは以下からトライアル版のダウンロードが可能です。

https://jp.infragistics.com/products/wpf

f:id:sugimomoto:20190715224443p:plain

「XamDataGrid」のリファレンスは以下からどうぞ。

xamDataGridのリファレンス https://jp.infragistics.com/help/wpf/xamdatagrid

使うものその2 CData Dynamics 365 for Sales ADO.NET Provider

「XamDataGrid」と併せて、Dynamics 365 for Salesからデータを取得するために、「CData Dynamics 365 for Sales ADO.NET Provider」も利用します。

http://www.cdata.com/jp/drivers/d365sales/ado/

f:id:sugimomoto:20190715224452p:plain

通常、Dynamics 365 から外部のアプリケーションにデータをロードする場合は、Web APIを通じた開発やOAuth認証の処理が必要となりますが、「CData Dynamics 365 for Sales ADO.NET Provider」を使うことで、SQLベースで手軽に Dynamics 365 for Salesデータにアクセスができるようになります。

また、標準のADO.NETコンポーネントとして提供されているため、SQL Serverと同じ感覚でWPFアプリケーションにデータをバインドすることができます。

こちらもトライアルが提供されているので、事前にインストールしておいてください。

手順

1. WPFプロジェクトの作成

それでは、作成していきましょう。

VisualStudioを立ち上げて、WPFアプリのプロジェクトを作成します。

f:id:sugimomoto:20190715224459p:plain

今回はデータを柔軟に取り出せるように、CData ADO.NET ProviderにSQLを渡すためのTextBoxと実行用のボタンを配置しました。

f:id:sugimomoto:20190715224506p:plain

この段階でのXAMLは以下のようになっています。

<Window x:Class="CData.XamDataGrid.GropingListApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CData.XamDataGrid.GropingListApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBox x:Name="sqlTextBox" HorizontalAlignment="Left" Height="45" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="668"/>
        <Button x:Name="executeButton" Content="Execute" HorizontalAlignment="Left" Margin="683,10,0,0" VerticalAlignment="Top" Width="99" Height="45"/>

    </Grid>
</Window>

2. XamDataGrid の配置・設定

次に「XamDataGrid」を配置します。 Infragistics WPF UIコンポーネントをインストールしている場合、ツールボックスに以下のように表示されます。

f:id:sugimomoto:20190715224512p:plain

これをデザイナー画面で以下のように配置しました。

f:id:sugimomoto:20190715224517p:plain

併せて、任意の名称(xamDataGridとしました)、DataSourceは{Binding}を指定し、フィルター機能を使えるように「Custom:FieldSettings」に「AllowRecordFiltering="true"」「AllowSummaries="True" 」を追加しました。

また、サンプルプログラムではデザインテーマの「Theme="Metro"」も設定しています。このあたりはお好みでどうぞ。

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CData.XamDataGrid.GropingListApp"
        xmlns:Custom="http://infragistics.com/DataPresenter" x:Class="CData.XamDataGrid.GropingListApp.MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBox x:Name="sqlTextBox" HorizontalAlignment="Left" Height="45" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="668"/>
        <Button x:Name="executeButton" Content="Execute" HorizontalAlignment="Left" Margin="683,10,0,0" VerticalAlignment="Top" Width="99" Height="45"/>

        <!-- XamDataGrid を追加 -->
        <Custom:XamDataGrid Name="xamDataGrid" DataSource="{Binding}" HorizontalAlignment="Left" Margin="10,60,0,0" VerticalAlignment="Top" Height="349" Width="772" Theme="Metro">
            <Custom:XamDataGrid.FieldSettings>
                <Custom:FieldSettings AllowSummaries="True" AllowRecordFiltering="true"/>
            </Custom:XamDataGrid.FieldSettings>
        </Custom:XamDataGrid>

    </Grid>
</Window>

3. CData Dynamics 365 for Sales ADO.NET Provider への接続を構成

最後に CData Dynamics 365 for Sales ADO.NET Provider への接続部分を作成します。

まずは参照設定からCData Dynamics 365 for Sales ADO.NET Provider のライブラリである「System.Data.CData.D365Sales.dll」を追加します。

以下のフォルダに保存されています。

C:\Program Files\CData\CData ADO.NET Provider for Dynamics 365 Sales 2019J\lib

f:id:sugimomoto:20190715224527p:plain

その後、名前空間に「System.Data.CData.D365Sales」を追加し

using System.Data.CData.D365Sales;

ボタンをクリックした時にTextBoxからSQL文を取得し、D365 Salesからデータを取得する処理を記述します。この記述方法は以下のヘルプに記載されているものがほぼそのままです。

TextBoxにはデフォルト値となるSQLを予め入力しておきました。

http://cdn.cdata.com/help/ERE/jp/ado/pg_ADOqueriestable.htm

using System.Data;
using System.Data.CData.D365Sales;
using System.Windows;

namespace CData.XamDataGrid.GropingListApp
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            sqlTextBox.Text = "SELECT  name, closeprobability, actualvalue, stepname FROM opportunities";
        }

        private void ExecuteButton_Click(object sender, RoutedEventArgs e)
        {
            string connectionString = "InitiateOAuth=GETANDREFRESH;OrganizationUrl=https://XXXXX.crm7.dynamics.com/;";

            using (var connection = new D365SalesConnection(connectionString))
            {
                var dataAdapter = new D365SalesDataAdapter(
                sqlTextBox.Text, connection);

                var table = new DataTable();
                dataAdapter.Fill(table);

                this.DataContext = table.Rows;
            }
        }
    }
}

認証部分は以下のConectionStringを記述するだけで、OKです。接続先となる「OrganizationUrl」は各環境に併せて書き換えてください。

            string connectionString = "InitiateOAuth=GETANDREFRESH;OrganizationUrl=https://XXXXX.crm7.dynamics.com/;";

            using (var connection = new D365SalesConnection(connectionString))

CData Dynamics 365 for Sales ADO.NET Provider はその名の通りADO.NETベースのラッパーでもあるため、「IEnumerable」が実装されたDataRowCollectionをそのままDataCotenxtに渡すことで、「XamDataGrid」が利用できるようになります。

ここが「XamDataGrid」と「CData Dynamics 365 for Sales ADO.NET Provider」の親和性が高い重要な要素と言えます。

this.DataContext = table.Rows;

通常のWebAPIをそのまま実装した場合、自身でWebAPIリクエストの処理から認証部分、「XamDataGrid」渡すデータ構造の構成まで定義しなければいけませんが、これらコンポーネントの活用により省力化してアプリケーションを開発できます。

実行してみる

それではプログラムを実際に実行してみます。

f:id:sugimomoto:20190715224535p:plain

プログラムが立ち上がると、以下のようにアプリケーションが表示されます。Executeを押すと、初回はOAuth認証が「CData Dynamics 365 for Sales ADO.NET Provider 」によって自動的に行われます。

f:id:sugimomoto:20190715224545p:plain

ブラウザが立ち上がり、ログインを求められるので、対象の環境のユーザーID・PWでログインします。

f:id:sugimomoto:20190715224555p:plain

ログイン後、アクセス許可を行い、以下のようにメッセージが表示されれば接続は完了です。

f:id:sugimomoto:20190715224603p:plain

データがGridに表示されました。

f:id:sugimomoto:20190715224609p:plain

列タイトルをドラッグアンドドロップして、ヘッダー部分に持っていくことでグルーピングが可能です。

f:id:sugimomoto:20190715224617p:plain

これでプロセスステージごとにどの営業案件が存在するのか、可視化することができました。

このSQLにはWhere句も使えるため、必要な営業案件だけを絞り込んで取得することも可能です。

f:id:sugimomoto:20190715224625p:plain

また、グルーピングはネストさせていくことが可能です。今回はプロセスステージ(Stepname)に確度(CloseProbability)をネストさせてみました。

f:id:sugimomoto:20190715224630p:plain

SampleCode

Sample Codeは以下のGithubに掲載しています。

github.com