CData Software ハンズオン（Salesforce と kintone の顧客データを同期するC#アプリケーション）

# はじめに

本資料では、Salesforceの取引先データをkintoneに同期するWindowsフォームのC#アプリケーションを作成する手順です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/19120579-c810-2ba5-f7f7-591fb53f9ee3.png)

# 使用するCData製品

- [ODBC Driver for Salesforce](https://www.cdata.com/jp/drivers/salesforce/odbc/)
- [ODBC Driver for kintone](https://www.cdata.com/jp/drivers/kintone/odbc/)

※30日間の無償評価版

# 前提作業

- SalesforeのAPIを利用できる権限のアカウントを保有していること。
- kintoneのアカウントを保有しており、アプリテンプレートの「営業支援パック」でアプリを作成済みであること。
- 上記、ODBCドライバをインストールして、ODBCのDSNの設定が完了しており、Salesforce、および、kintoneへの「接続のテスト」が成功していること。


## SalesforceのDSN設定情報

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/c52d9ed7-32e4-408d-7d75-d0582bbc781c.png)

| Salesforceの接続情報 | 設定項目 |
|:-----------------|:---------------|
| ユーザID | User |
| パスワード | Password |
| セキュリティートークン | Security Token |

## kintoneのDSN設定情報

![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/39b2fc8a-1bf8-2023-d543-2df5689bc6c5.png)

| kintoneの接続情報 | 設定項目 |
|:-----------------|------------------|
| ユーザID | User |
| パスワード |Password|
| kintoneのサブドメイン含むサイトURL（例：https://\*\*\*\*.cybozu.com）　※https://\*\*\*\*.cybozu.com/k/の「/k」は不要 |Url|

# プロジェクトの作成

VisualStudio2017を起動して、メニューバーの「ファイル > 新規作成 > プロジェクト」を開きます。 

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/fd5bfacf-97ff-8baa-2f78-748ae88c8a09.png)

「新しいプロジェクト」ウィザードが起動するので、「VisualC# > Windowsフォームアプリケーション（.NET Framework）」を選択して、名前に「Salesforce2Kintone」と入力して「OK」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/6b09faa2-b233-9960-49f9-0a9fc662fe78.png)

プロジェクト作成され、Formのデザイナが開きます。

# DataGridViewの配置、および、データバインド

くので、Formを適当な大きさに拡大します。左側の「ツールボックス」の検索ボックスに「table」と入力して抽出された「TableLayoutPanel」を選択して、ドラッグ＆ドロップで、Form上に配置します。配置するときに、行列を「１行×３列」に設定して、Formいっぱいに拡大します。「TableLayoutPanel」が選択された状態で、右側のプロパティ内の「配置 > Anchor」を「Top, Left」から「Top, Bottom, Left, Right」に変更します。あわせて「配置 > Columns」を開き、「列と行のスタイル」ウィンドウにて「サイズの型」を以下の通り設定して保存します。

| メンバー | サイズの型 | 値 |
|:-----------------|:-----------------|:---------------|
| Column1 | Percent | 45.00% |
| Column2 | Percent | 10.00% |
| Column3 | Percent | 45.00% |

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/39341d08-5901-0809-ceb9-1c9b9b4f6187.png)

「TableLayoutPanel」のバランスが取れたところで、「ツールボックス」の検索ボックスにて「DataGridView」と入力して抽出された「DataGridView」を、「TableLayoutPanel」の左にドラッグ＆ドロップで配置します。「DataGridView」右上の小さな再生ボタン「▶︎」をクリックして、「データソースの選択」の「（なし）」右の下矢印をクリックして、「プロジェクトデータソースの追加」リンクをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/e87682e0-cef1-513a-1c25-653dc57a1e4c.png)

「データソース構成ウィザード」が立ち上がるので、「データベース > データセット」を選択して進みます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/9789fc58-1dd0-adb4-3ae9-64ef75596a0a.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/77a9de77-7904-c53b-7ed8-2da3de5a0c17.png)

「データ接続の選択」にて、「新しい接続」ボタンをクリックして、「データソースの選択」ウィンドウから「Microsoft ODBC データソース」を選択して「続行」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/da475a21-1662-8ca1-7e25-000baf406e0a.png)

「ユーザーデータソースまたはシステムデータソース名を使用」のドロップダウンリストから既に作成しているSalesforceのODBC DSN「CData Salesforce Source」を選択して、「テスト接続」をクリックします。テスト接続に成功したら「OK」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/f07f3025-bb4d-f438-6cff-245114d51fd4.png)

「次へ」ボタンをクリックして進みます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/7d16f561-8359-ee94-4b65-467330738f7d.png)

プロジェクト内のアプリケーション構成ファイルに保存する名称「ConnectionStringSalesforce」を入力して「次へ」を進みます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/a398fe0b-b11e-b68d-23c6-c9fecc438b2f.png)

Salesforce内のオブジェクトがテーブルリストとして表示されるので取引先に相当する「Account」にチェックを入れ、データセット名を「DataSetSalesforce」として「完了」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/b9267fad-d502-b973-c3e0-c5f77234edae.png)

フォームのデザイナに戻り、左側の「DataGridView」に、ヘッダー行が追加されたことを確認します。「DataGridView」を選択して、プロパティ内の「配置 > Dock」を「Fill（四角の真ん中）」に変更します。これにより、「TableLayoutPanel」の中いっぱいに「DataGridView」が拡大されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/822a13a9-02e9-7dc3-98d7-c6bdccb8b02b.png)

今度は、右側の「DataGridView」にkintoneの情報をバインドする設定を行いましょう。Salesforceの時と同様に「データベース > データセット」を選択して進みます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/e4779cef-46c4-03b5-c143-6a23113b472d.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/c51f6182-1fdc-5256-d171-094df0e63d7c.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/f33de7bc-58b9-2a39-515d-029aa418083c.png)

「データ接続の選択」の「新しい接続」から、今度は、「ユーザーデータソース名またはシステムデータソース名を使用」からkintoneのODBC DSN「CData Kintone Source」を選択します。「テスト接続」をクリックして、接続に成功したのを確認して「OK」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/adde3581-cb13-fe76-7a5c-0d111eebbe48.png)

「次へ」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/c6ddfc72-0ad6-1232-e4a4-e0396b6a8f61.png)

kintone側の接続文字列名を「ConnectionStringKintone」として「次へ」進みます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/ada922d8-1f57-bd52-393c-cfe14ea7eb42.png)

kintone内のアプリがテーブルリストとして表示されるので、「顧客管理（営業支援パック）」にチェックを入れてデータセット名は「DataSetKintone」として「完了」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/244f1238-e59c-b279-e6a2-261e413fc81f.png)

kintone側の「DataGridView」を選択して、プロパティ内の「配置 > Dock」を「Fill（四角の真ん中）」に変更します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/6cd6ea24-2e67-055c-1558-638f18b2a771.png)

それでは、Salesforceとkintoneのデータが、「DataGridView」にバインドされるか確認してみます。メニューバー内の「▶︎開始」ボタンをクリックして実行してみます。しばらくすると「Form1」が起動して、Salesforceとkintoneのデータが表示されれば成功です。確認出来たら「■」の停止ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/09ed83aa-04fa-d3ec-3e80-882135fe152a.png)

次に、「DataGridView」内の不要な項目を非表示にすることで、より、左（Salesforce）右（kintone）の項目を比較しやすくします。まずは、左側のSalesforce側の「DataGridView」の右上の「▶︎」ボタンをクリックして「列の編集」リンクをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/af1835b6-2ab0-dc49-2859-d07ee8abfd40.png)

「列の編集」の「選択された列」に以下の項目のみ残し、「OK」ボタンをクリックします。

| 選択された列 | 備考 |
|:-----------------|:-----------------|
| Id | 内部キー項目 |
| Name | 取引先名 |
| BillingStreet | 住所 |
| BillingPostalCode | 郵便番号 |
| Phone | 電話番号 |
| Fax | Fax |


![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/fffc29c9-0e9f-a049-c7a0-db6c09b16b53.png)

同様に右側のkintone側の「DataGridView」の右上の「▶︎」ボタンをクリックして「列の編集」リンクをクリックします。「列の編集」の「選択された列」に以下の項目のみ残し、「OK」ボタンをクリックします。

| 選択された列 | 備考 |
|:-----------------|:-----------------|
| RecordId | 内部キー項目 |
| Revision | レコードバージョン番号 |
| 郵便番号 |  |
| 顧客名 |  |
| 住所 |  |
| TEL |  |
| FAX |  |

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/03479c0e-03c8-8584-9793-0f1f0d0818ba.png)

再度、Salesforceとkintoneのデータが、必要項目のみ「DataGridView」にバインドされるか確認してみます。メニューバー内の「▶︎開始」ボタンをクリックして実行してみます。しばらくすると「Form1」が起動して、Salesforceとkintoneの項目が設定した項目のみ表示されれば成功です。確認出来たら「■」の停止ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/8729fa4c-2963-9baf-6505-b49005697dd5.png)

# 同期処理の実装

「ツールボックス」の検索ボックスにて「button」と検索して抽出された「Button」コントロールを、「TableLayoutPanel」の間に配置します。デフォルトでは右上に寄った配置となるため、「配置 > Anchor」を「None」に変更することで中央に移動します。また、「表示 > Text」をコピーを行う処理として「>>>」に変更して、ボタンをドラッグ＆ドロップ操作で縦に広げて大きくします。追加した「Button」コントロールをダブルクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/1feb3960-2f7d-db85-dc79-97ac0907968e.png)

「Form1.cs」のコードが表示されます。下イメージの「ここ」部分に下記のコードをコピーします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/766be3b0-2956-dab8-0611-bed8c4d3504b.png)

```c#

            //// エラー処理は省略

            this.button1.Enabled = false;

            this.dataGridView1.Rows.Cast<DataGridViewRow>()
                .Where(o => o.Selected)
                .Select((o, i) => new { Row = (DataSetSalesforce.AccountRow)((DataRowView)o.DataBoundItem).Row, Index = i })
                .ToList()
                .ForEach(selected =>
                {
                    var row = this.dataSetKintone._顧客管理_営業支援パック_.Rows.Cast<DataSetKintone._顧客管理_営業支援パック_Row>()
                        .Where(o => o.顧客名 == selected.Row.Name)
                        .FirstOrDefault();

                    if (row == null)
                    {
                        row = this.dataSetKintone._顧客管理_営業支援パック_.New_顧客管理_営業支援パック_Row();
                        row.RecordId = selected.Index
                            + (this.dataSetKintone._顧客管理_営業支援パック_.Rows.Cast<DataSetKintone._顧客管理_営業支援パック_Row>().Max(o => (int?)o.RecordId) ?? 0)
                            + 1;
                        row.Revision = 0;
                    }

                    row.顧客名 = selected.Row.Name;
                    row.郵便番号 = selected.Row.IsBillingPostalCodeNull() ? "" : selected.Row.BillingPostalCode;
                    row.住所 = selected.Row.IsBillingStreetNull() ? "" : selected.Row.BillingStreet;
                    row.TEL = selected.Row.IsPhoneNull() ? "" : selected.Row.Phone;
                    row.FAX = selected.Row.IsFaxNull() ? "" : selected.Row.Fax;

                    if (row.Revision == 0)
                    {
                        this.dataSetKintone._顧客管理_営業支援パック_.Rows.Add(row);
                    }

                    this.顧客管理_営業支援パック_TableAdapter.Update(this.dataSetKintone);
                });

            this.顧客管理_営業支援パック_TableAdapter.Fill(this.dataSetKintone._顧客管理_営業支援パック_);

            this.button1.Enabled = true;

```

コピー＆ペーストして、構文エラー（赤い波線）が出るようであれば、Datasetの名称など、これまでの設定内容と照らし合わせてください。特に構文エラーがない場合は、プロジェクトをリビルドして、再度、「▶︎開始」でプロジェクトを実行してみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/d6425280-00c8-dd15-7149-f88028fd4e13.png)

Formが起動するので、左側のSalesforceのデータを一レコード選択した状態で、「>>>」ボタンをクリックしてみてください。右側に一レコード追加されれば成功です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/ddc090ae-14ab-dace-f03f-fe9f6b1a6f3b.png)

実際に、kintoneの画面を開き、追加されているか確認してみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/2c82afe4-e2ba-23d0-7eb5-8833fe466cb8.png)

もう一度、左側のSalesforceのデータの同じ一レコード選択した状態で、「>>>」ボタンをクリックしてみてください。今度はエラーで止まりました。

```c#
                    this.顧客管理_営業支援パック_TableAdapter.Update(this.dataSetKintone);
```

「From1.cs」内の下記のUpdateするところで「[RecordId]列は読み取り専用です。この列の値を更新出来ません。」というエラーが出ています。これは、kintone側のレコード毎に保有のキー項目であるRecordIdは更新出来ないため発生します。そこで、必要な項目のみUpdate（更新）するように変更します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/068398d6-5616-ae4f-5dbe-9ad596d2a518.png)

右側の「ソリューションエクスプローラー」から「DataSetKintone.xsd」を選択して、右クリックから「デザイナーの表示」を開きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/8bba32af-619e-a4ee-9d9c-c68860b98e02.png)

「顧客管理（営業支援パック）　Table Adapter」のアイコンをクリックして、右下の「プロパティ」が「顧客管理（営業支援パック）　Table Adapter」になった事を確認して、「UpdateCommand」のプラスボタンを開き、「CommandText」を右側の「...」から開きます。　

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/f87f868d-1de4-848b-7c49-eb79fd57989b.png)

「クエリービルダー」が開くので、下記の「郵便番号、住所、TEL、FAX」のみ更新するように変更します。

```sql
UPDATE                    Kintone."顧客管理（営業支援パック）"
SET                              郵便番号 = ?, 住所 = ?, TEL = ?, FAX = ?
WHERE                       (RecordId = ?)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/0ae5796d-55ac-31fd-3856-5786a27d4cda.png)

「OK」ボタンをクリッっくして「クエリービルダー」を閉じて、再度、、プロジェクトをリビルドして、再度、「▶︎開始」でプロジェクトを実行してみます。既にkintone側にコピー済みのレコードを再度Salesforce側のレコードを選択してコピーしてみます。kintone側のRevisionが「1」から「２」にカウントアップすれば成功です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/66e42292-c655-1dd4-9d1b-e0e9947f481c.png)

それでは、左側のSalesforce側のレコードをすべて選択して、コピーを実行してみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/e32f95fc-1af7-9f63-1e3a-98f06a97f362.png)

実行が完了したらkintone側の画面でみてみましょう。Salesforce側の取引先（Account）情報が、kintone側の顧客管理（営業支援パック）に同期されたことを確認出来たら完成です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152422/8e519582-f4d6-2417-c175-fe4e939b375c.png)

# まとめ

資料では、Salesforceの取引先データをkintoneに同期するWindowsフォームのC#アプリケーションを作成する手順について説明しました。このように、最小限のプログラミングで、そして、ODBCというRDBと同じ規格で、Salesforceとkintoneの両方のSaasに接続してデータ連携を行うことが出来ます。