【UiPath】データテーブルの操作（7）行・列の挿入／削除

# はじめに

この投稿は、RPAツール「UiPath」で Datatable で「行・列の挿入／削除」をする方法について、個人的にまとめたものです。

UiPathブログ発信チャレンジ の 20日目の記事です。

https://note.com/shumpei_w/n/n19383ce5abb1


# データテーブルの操作 シリーズ
DataTable の操作方法について記載した記事が、他にもあります。参考まで。

https://qiita.com/miya_gis/items/6c0dd40378db702bd4b2

https://qiita.com/miya_gis/items/edc3557f3dc7cf6b3cfd

https://qiita.com/miya_gis/items/171b3d12775c95f722c4

https://qiita.com/miya_gis/items/cde6c1eb3c33378d9718

https://qiita.com/miya_gis/items/78dd08bc7f0b5497b83d

https://qiita.com/miya_gis/items/966113ce9732cb112c49

https://qiita.com/miya_gis/items/67eac96071aa7d7d24dd

# 検証・動作環境／目次

この記事は、以下のバージョンをもとに作成しています。

- UiPath Studio：2022.4.3（Community版）
- UiPath.System.Activities：22.4.1

今回使用するアクティビティは、ここ数年はアップデートされていないので、上記より古いバージョンでも支障（機能差異）は無いと思います。

記事の内容は、以下の順で説明します。

- 1）行の追加と削除（UiPath 標準アクティビティで実施）
- 1-A）行の追加（「メソッドを呼び出し」＆「.NETの機能」）
- 1-B）行の削除（「メソッドを呼び出し」＆「.NETの機能」）
- 2）列の追加と削除（UiPath 標準アクティビティで実施）
- 2-A）列の追加（「メソッドを呼び出し」＆「.NETの機能」）
- 2-B）列の削除（「メソッドを呼び出し」＆「.NETの機能」）


# 前提）DataTableにおける、行と列の構造と概念

簡単に言うと、DataTableの行と列は、以下のように構成されています。
行は「**index**」、列は「**ordinal**」で順序が管理され、それぞれ「**0（ゼロ）**」から始まります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/a58b63e8-bb8d-34f1-a6aa-a3fab48a4005.png)

:::note info
順序を変更したり、間に挿入する場合には、この「**index（通し番号の意）**・**ordinal（順序の意）**」を意識する必要があります。
:::


# 1）行の追加と削除（UiPath 標準アクティビティで実施）

UiPath 標準のアクティビティで「**データ行を追加 (Add Data Row)**」と「**データ行を削除 (Remove Data Row)**」があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/70714c6c-0d08-69f4-13b7-24a83a458848.png)

見てわかるように、この２つは微妙に「見た目」「引数プロパティ」が少し違います。

| アクティビティ名 | 違い |
|:-:|:-:|
| 行追加  |  `「配列型」でも行追加できる` ようになっている  |
| 行削除  |   `「インデックス（位置）指定」でも削除できる` ようになっている |

なので、`「行追加の時は、位置を指定できない」` と思われがちですが、以降で紹介するように .NETの機能を使用すれば出来ます。

https://docs.uipath.com/activities/lang-ja/docs/add-data-row

https://docs.uipath.com/activities/lang-ja/docs/remove-data-row


# 1-A）行の追加（「メソッドを呼び出し」＆「.NETの機能」）

行の追加は、データテーブル標準のメソッド「**.Rows.Add**」または「**.Rows.InsertAt**」で出来ます。
「**.Rows.Add**」は**最後尾**に、「.**Rows.InsertAt**」は**指定位置**に行を追加します。

| ケース | 使用するメソッド |
|:-|:-|
| 行の「**末尾**」に追加したい場合  | dt.Rows.**Add**(行or配列オブジェクト)  |
| 行の「**先頭**」に追加したい場合  | dt.Rows.**InsertAt**(行オブジェクト, 0) |
| 行の「**2番目**」に追加したい場合  | dt.Rows.**InsertAt**(行オブジェクト, 1)  |

※ dt は データテーブルの変数を指します

Add の場合、行オブジェクトだけでなく、配列型でも追加できます。

InsertAt の第２引数には「行インデックス」を指定し、どの位置に挿入したいかを指定できます。
この行インデックスは「0始まり」なので、１行目に追加する場合は「0」を指定するのがポイントです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/be73db00-499f-2076-77b6-fbe4e64a2ed4.png)

また、例えば「特定の行の前に挿入したいが、その行の行インデックスが分からない」という場合は、

| ケース | 使用するメソッド |
|:-:|:-:|
|その行の「インデックス値」を知りたい|dt.Rows.**IndexOf**(行オブジェクト)|

で、行インデックス値を取得できます。
この機能を使用すれば、ロジック上で自由に行の並びをコントロールできるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/049f7b92-891f-e43e-413f-2f079a315212.png)


# 1-B）行の削除（「メソッドを呼び出し」＆「.NETの機能」）

行の削除は、データテーブル標準のメソッド「**.Rows.Remove**」または「**.Rows.RemoveAt**」で出来ます。

ですが、「**データ行を削除 (Remove Data Row)**」と「できることは同じ」なので、あえて「.NET構文」を使わなくても良いでしょう。
InvokeCodeを使用して、ロジック上でスッキリ処理したい場合は、.NET構文のほうが便利だったりもしますが、この辺はお好みで。

| ケース | 使用するメソッド |
|:-|:-|
| 行を「オブジェクト指定」で削除したい場合  | dt.Rows.**Remove**(行オブジェクト)  |
| 「先頭」の行を削除したい場合  | dt.Rows.**RemoveAt**(0) |
| 「2番目」の行を削除したい場合  | dt.Rows.**RemoveAt**(1)  |

InsertAt のときと同じく、RemoveAt の第１引数には「行インデックス」を指定し、どの位置を削除したいかを指定します。
この行インデックスは「0始まり」なので、１行目を削除する場合は「0」を指定するのがポイントです。


# 2）列の追加と削除（UiPath 標準アクティビティで実施）

UiPath 標準のアクティビティで「`データ列を追加 (Add Data Column)`」と「`データ列を削除 (Remove Data Column)`」があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/04f2b159-fb63-1d22-264b-ffbd2d2bf350.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/ccca4fce-b9a6-0958-ce5a-0dc37e09514a.png)

見てわかるように、この２つも微妙に「見た目」「引数プロパティ」が違います。

| アクティビティ名 | 違い |
|:-:|:-:|
| 列追加  |  `追加時に「列名」を指定できる` ようになっている  |
| 列削除  |   `「インデックス（位置）指定」でも削除できる` ようになっている |

なので、`列追加時は「位置を指定できない」`と思われがちですが、以降で紹介するように .NETの機能を使用すれば出来ます。

https://docs.uipath.com/activities/lang-ja/docs/remove-data-column

https://docs.uipath.com/activities/lang-ja/docs/add-data-column


# 2-A）列の追加（「メソッドを呼び出し」＆「.NETの機能」）

列の追加は、データテーブル標準のメソッド「**.Columns.Add**」で出来ます。（※1）

| ケースNo | 処理の内容 | 使用するメソッド |
|:-:|:-|:-|
| 1 | 価格列を追加したい  | dt.Columns.**Add**("価格")  |
| 2 | 価格列をInt型で追加したい  | dt.Columns.**Add**("価格", Type.GetType("System.Int32")) |

残念ながら（行追加の「InsertAt」のように）「追加と順序指定」を同時に処理することは出来ません。
そのため、「列を追加」した後で「列の順番変更」の処理を行います。

| ケースNo | 処理の内容 | 使用するメソッド |
|:-:|:-|:-|
| 3 | 価格列を2番目にしたい  | dt.Columns("価格").**SetOrdinal**(1)  　　　　　　　　　|

SetOrdinal で指定する値は「列インデックス」です。例のごとく「0始まり」なので、１列目に追加する場合は「0」を指定します。

※1 「dt.Columns.Add("SalesTax", typeof(Double), "Total * 0.086") 」のような「他列参照の値セット」の列作成方法もありますが、使用頻度は低いので割愛します。

また、例えば「特定の列の前に挿入したい」場合は、その列のインデックスを求めて、setOrdinal で指定すれば変更できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/268a0d52-468a-ea66-e1ad-99608a7fb943.png)

※ 追加した列に「各行の値」をセットする処理は、別途実施してください。

# 2-B）列の削除（「メソッドを呼び出し」＆「.NETの機能」）

列の削除は、データテーブル標準のメソッド「**.Columns.Remove**」または「**.Columns.RemoveAt**」で出来ます。

| ケースNo | 処理の内容 | 使用するメソッド |
|:-:|:-|:-|
| 1 | 「価格」列を削除したい  | dt.Columns.**Remove**("価格")  |
| 2 | 「先頭」の列を削除したい  | dt.Columns.RemoveAt(0)) |
| 3 | 「2番目」の列を削除したい  | dt.Columns.RemoveAt(1)) |

RemoveAtで指定する値は列インデックスで、例のごとく「0（セロ）」始まりです。

行の削除と同じく、「**データ列を削除 (Remove Data Column)**」と「できることは同じ」なので、あえて「.NET構文」を使わなくても良いでしょう。
InvokeCodeを使用して、ロジック上でスッキリ処理したい場合は、.NET構文のほうが便利だったりもしますが、この辺はお好みで。


# 番外編）ループ内で追加・削除する場合の注意

行や列のループの中で「行・列の追加」や「行・列の削除」をすると、処理中にデータの順序が変わるため、エラーになったり想定外の処理結果になることがあります。

エラーを避けるためには、

- 「追加・削除」は別のループで行う
- 行や列の「後ろ」から処理していく（頭から実施すると、以降の順序が崩れる）

など、工夫が必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/ec8c6805-4534-d965-9b0c-4473fc9c2166.png)


# 終わりに

以上、DataTableの「行・列」の挿入／削除方法について、でした。

標準アクティビティで事足りなければ「.NETの機能も使用してみる」と、要件を満たせることもあります。ちょっと使うくらいなら難しくありません。

この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。