【UiPath】データテーブルの操作（2）デバッグ出力

# はじめに

この投稿は、RPAツール「UiPath」の データテーブル の操作方法について「個人的に」まとめたものです。
量が多いので、数回に分けて書きます。


この記事は、UiPath Friends もくもく会 2021年5月開催（5-28（土）08:45 - 12:00）で書きました。

https://uipath-friends.doorkeeper.jp/events/136176



# データテーブルの操作 シリーズ

DataTableの操作方法について記載した記事が、他にもあります。参考まで。

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

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/f45b67fbc2575f0d6d77

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

# データテーブルをデバッグ出力したい

ロボットの処理中に、データテーブルをログに出力したいときがあります。
「中身がどうなっているか？」を確認したいときです。

出力方法は以下の２つが挙げられます

|No| 出力方法 | メリット | デメリット |
|:-|:-|:-|:-|
|1| **データテーブルを出力**<br> アクティビティで文字列に出力  | 標準アクティビティ<br>だけ簡単に出来る  | 変数の用意が必要<br>フォーマットが固定  |
|2| **Linq** で文字列を抽出して出力 | メッセージをログ<br>アクティビティだけで完結 | Linqに慣れが必要  |

以下でそれぞれ説明します。

# データテーブルを出力 アクティビティ

UiPath 標準の「データ テーブルを出力 (Output Data Table) 」アクティビティ を使用すると、DataTable を文字列に出力できます。

https://docs.uipath.com/activities/lang-ja/docs/output-data-table

ログ出力するには、String型の変数を宣言し、以下のように「メッセージをログ」アクティビティでログ出力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/fa83c291-580d-1477-7e5a-374e287c3a39.png)

アクティビティで出力される際のフォーマットは以下のようになっています。
``` 
ColumName1,ColumName2,ColumName3,…   '// 1行目は列定義。カンマ区切り
ValueA1,ValueB1,ValueBC,…            '// 2行目からデータ。カンマ区切り
ValueA2,ValueB2,ValueC2,…
ValueA3,ValueB3,ValueC3,…
…
```
既存アクティビティだけで簡単に出力できるのですが、出力先の`変数の用意`が必要です。また、`フォーマットが固定`で変更できません。


# LINQ で作成した文字列を出力

LINQ を使って DataTable の中身を文字列に変換します。
「メッセージをログ」アクティビティのメッセージボックス欄に LINQ を直接入れます。（出力文字列の変数は不要です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/b1c4d713-41b1-9e0f-4208-80fa11011408.png)


LINQ の内容を変えれば好みのフォーマットに変更できるのもメリットです。

LINQ には「`メソッド構文`」と「`クエリ式`」という２種類の書き方がありますが、以下にそれぞれサンプルを記載します。

「メッセージをログ」アクティビティのメッセージボックスに、そのままセットして使用できます）


1）LINQ：メソッド構文（ドットでつなげる書き方）
```
'// A）列は「カンマ」区切り、行は「改行」区切り
String.Join(",", dt.Columns.Cast(Of DataColumn).Select(Function(c As DataColumn) c.ColumnName.ToString).ToArray) & ControlChars.NewLine & _
String.Join(ControlChars.NewLine, dt.AsEnumerable.Select(Function(r As DataRow) String.Join(",", r.ItemArray)).ToArray)

'// B）列は「Tab」区切り、行は「改行」区切り
String.Join(ControlChars.Tab, dt.Columns.Cast(Of DataColumn).Select(Function(c As DataColumn) c.ColumnName.ToString).ToArray) & ControlChars.NewLine & _
String.Join(ControlChars.NewLine, dt.AsEnumerable.Select(Function(r As DataRow) String.Join(ControlChars.Tab, r.ItemArray)).ToArray)

'// C）列は「Tab」区切り、行は「改行」区切り、データは最大2件のみ
String.Join(ControlChars.Tab, dt.Columns.Cast(Of DataColumn).Select(Function(c As DataColumn) c.ColumnName.ToString).ToArray) & ControlChars.NewLine & _
String.Join(ControlChars.NewLine, dt.AsEnumerable.Select(Function(r As DataRow) String.Join(ControlChars.Tab, r.ItemArray)).Take(2).ToArray)
```

基本的に、上記の3つでやっていることは同じ です。

少しだけ、何をしているのかを説明すると、
```
String.Join(",", 
　dt.Columns.Cast(Of DataColumn).Select(
　　Function(c As DataColumn) c.ColumnName.ToString
　).ToArray
) 
```
これは、見出し行を作成しています。
`String.Join(",", `　で配列をカンマで区切って
`dt.Columns.Cast(Of DataColumn)` でDataTableから列定義を取り出して
`.Select(Function(c As DataColumn) c.ColumnName.ToString)` で列定義から列名を取り出して
`.ToArray` で取り出した列名を配列にします（カンマで区切れるように）

という感じです。同じように、データの中身も`dt.AsEnumerable.Select。。。`で取得して、改行で区切っています。

<br>

2）LINQ：クエリ式（Fromなどの構文を半角スペースでつなぐ書き方）
```
'// A）列は「カンマ」区切り、行は「改行」区切り
String.Join(",", (From c As DataColumn In dt.Columns.Cast(Of DataColumn) Select c.ColumnName).ToArray) & ControlChars.NewLine & _
String.Join(ControlChars.NewLine, From r As DataRow In dt.AsEnumerable Select String.Join(",", r.ItemArray))

'// B）列は「Tab」区切り、行は「改行」区切り
String.Join(ControlChars.Tab, (From c As DataColumn In dt.Columns.Cast(Of DataColumn) Select c.ColumnName).ToArray) & ControlChars.NewLine & _
String.Join(ControlChars.NewLine, From r As DataRow In dt.AsEnumerable Select String.Join(ControlChars.Tab, r.ItemArray))

'// C）列は「Tab」区切り、行は「改行」区切り、データは最大2件のみ
String.Join(ControlChars.Tab, (From c As DataColumn In dt.Columns.Cast(Of DataColumn) Select c.ColumnName).ToArray) & ControlChars.NewLine & _
String.Join(ControlChars.NewLine, (From r As DataRow In dt.AsEnumerable Select String.Join(ControlChars.Tab, r.ItemArray)).Take(2))
```

<br>

同じワークフロー内で、何回も呼び出す場合は、変数として定義すると便利です。

１）変数で以下のように「Func<DataTable, String>」型を用意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/5c62930c-b0e4-8c05-b5a1-af74cad8b681.png)

２）変数に以下の関数をセット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/5a7bef25-3237-a345-fdb8-033f7533612e.png)

変数パネルの規定値でセットしても構いません。代入する関数は、例えば以下のような内容です。
（上記のサンプルの先頭に「Function(dt As DataTable)」を足します）
``` 
Function(dt As DataTable) String.Join(",", (From c As DataColumn In dt.Columns.Cast(Of DataColumn) Select c.ColumnName).ToArray) & ControlChars.NewLine & String.Join(ControlChars.NewLine, From r As DataRow In dt.AsEnumerable Select String.Join(",", r.ItemArray))
```

この変数を利用すると、以下のようにデバッグ出力を指定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/b479c0f8-0b52-797e-00c4-e2b0712fa903.png)


# 終わりに
以上、DataTableのデバッグについて でした。なにかの役に立てば幸いです。

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