Automation Anywhere で多重ループを使う

Automation Anywhere で提供されるLOOPコマンドは、基本的にはネストなしの単純なループ、テーブルでいえば**列方向は固定であることを想定した「行」方向のループ**、が想定されているように見えます。RPAではそもそもそんなに複雑なロジックを組まない、というのが前提なのでしょう。

ただし、コマンド上はLOOPをネストして配置させることも可能なので、どんなふうに多重ループを組めるかについてExcel操作を例に見てみたいと思います。

**対象**

* Automation Anywhere Enterprise 11.3.2
* Automation Anywhere Community Edition

# LOOPコマンドとは
LOOPコマンドは、指定したアクションリストを繰り返し実行する仕組みです。繰り返してアクションリストの先頭に戻ってくる際には`$Counter$`システム変数の値が増えており、扱っているデータの現在位置(テーブルの行、配列の引数、等)が1増えます。そして、データの最後になるまで or 指定された回数分だけ or 特定の条件を満たしている間、繰り返し処理が実行されます。`$Counter$`システム変数の値は1から開始されます。

以下がLOOPのコマンド群です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/821f2b36-77ca-5ed1-7d48-05f1b2b86425.png)


これらをドラッグ＆ドロップで追加すると、以下のダイアログボックスが開き、オプションを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/20887baf-104a-e3ea-88a6-94b7a206002d.png)

ここで「保存」ボタンをクリックすると、以下のような「Start Loop」「End Loop」アクションがセットで追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/5919767c-cb24-d818-d73d-680406a061ec.png)

また、自動で追加されたコメント行にも記載されている通り、Excelのループの場合は、`$Excel Column$`システム変数を使って値を参照します。ループの中のアクションリストで`$Excel Column(<列の番号 or 名前>)$`といった形で列を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/79267c54-c02f-23f9-6dff-180dc479b57e.png)


# 多重ループでやりたいこと
さて、LOOPコマンドの基本を押さえたうえで、Excelテーブルを操作する前提で構造がどうなっているかを整理すると、以下の図のように行単位で`$Excel Column(n)$` (nは列の番号 or 名前)を使い、ループを回していくのが、通常のLOOP-Each row in a Excel Sheetの処理になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/aa79fed8-2eba-be82-a5d6-6daf402498ee.png)

プログラミングをやったことがある人なら、たとえばVBAだと

```
For Counter=1 To MaxRow
  MessageBox ExcelColumn(n)
Next

```
みたいなイメージです。RPAにおいては通常は列方向のデータ量は固定の表を扱うので、あとはnを必要回数だけ指定すれば事足ります。
Excelテーブルのすべてのデータ要素を順に表示するには以下のように書きます。

```
For Counter=1 To MaxRow
  MessageBox ExcelColumn(1)
  MessageBox ExcelColumn(2)
  MessageBox ExcelColumn(3)
  ...
  MessageBox ExcelColumn(n)
Next

```


ただし、せっかくなので

```
For Counter=1 To MaxRow
  For CounterColumn=1 to MaxColumn
      MessageBox ExcelColumn(CounterColumn)
  Next
Next

```
のように列方向もループをまわすことができれば、通常のプログラミング言語だと記述がよりシンプルになります。これをやろうとしたときにAutomation Anywhere だとどうなるでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/05288fec-fa6a-8db4-a042-9cd2168f06a7.png)

# Excelテーブルで多重ループを組んでみた

以下のデータを前提に、多重ループを組む方法を考えました。

|名前|生年月日|
|:--|--:|
|山田太郎|1971/3/4|
|石川たか子|1986/12/4|
|鈴木一郎|1976/3/31|
|佐藤栄作|1980/12/31|
|西川正二|1966/2/15|

### 方法1: 列の最大数がわかっているとして組む場合

今回は、列の最大数は2です。これを踏まえると、MaxColumn=2として、外側はLOOP-Each row in a Excel Sheet、内側はLOOP-Timesで多重ループを組めばOKです。

アクションリストは以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/20a36298-5529-0919-0d86-54e89d9f942c.png)


これを実行すると、「山田太郎」「1971/3/4」「石川たか子」「1986/12/4」「鈴木一郎」「1976/3/31」...と、表の中のヘッダーを除くデータ部分が、1行目から横方向に順番に1セルずつメッセージボックスで表示されていきます。

**注意: 多重ループの場合のCounter変数の取り扱い**
ここで注意しないといけないのは`$Counter$`システム変数がどの場所でどのループの値を持っているかです。ループが2重になっていても、`$Counter$`変数はひとつしかありません。`$Counter$`変数は、常に一番内側のループの値が入力されています。内側のループを抜けると、その外側のループの値が入力されます。これはデバッグ機能で`$Counter$`変数の値をウォッチしながらステップオーバーしていくとわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/781ef044-ffaf-60fc-08b6-649c6dd91f74.png)




### 方法2: 列の最大数を自動で取得する場合
当初、いろいろと調べてみたのですが、どうやら`$Excel Column(n)$`のnに指定できる最大値を取得できる簡単な方法がないのです。配列だと利用できる`$ArrayColumns($<Array 型変数名>$)$`は`$Excel Column(n)$`には適用できません。かといって、`$Excel Column$`システム変数はList変数でもないため、LOOPコマンドで提供されているListオプションも使えません。

また、「[Excel でデータの入っている一番最後の列/行の情報を取得するには](https://qiita.com/RPAbot/items/5e513aa259a595182dd0#excel-%E3%81%A7%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E5%85%A5%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E4%B8%80%E7%95%AA%E6%9C%80%E5%BE%8C%E3%81%AE%E5%88%97%E8%A1%8C%E3%81%AE%E6%83%85%E5%A0%B1%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF)」の方法で列の最後の場所を出すことはできますが、`$Excel Cell Column$`の返す値はアルファベットの値 (3なら"C")となるため、これから列の最大数を簡単に出せません。(Excelの列の番号から数字に変換してくれる関数があれば別ですが！ちなみに、この関数はBot Storeで無料配布されている「[Perform Various Spreadsheet Operations-Microsoft](https://botstore.automationanywhere.com/bot/excel-operations/)」にありました！記事「[RPAでExcelを操作する際のヒント (Automation Anywhere拡張編) - R1C1形式とA1形式の列番号を変換するには](https://qiita.com/RPAbot/items/b9c279acf1efffd4955c#r1c1%E5%BD%A2%E5%BC%8F%E3%81%A8a1%E5%BD%A2%E5%BC%8F%E3%81%AE%E5%88%97%E7%95%AA%E5%8F%B7%E3%82%92%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF)」で使い方を参照してください。)

よって、一番合理的な方法は、「[Excel データを配列変数に読み込むには](https://qiita.com/RPAbot/items/5e513aa259a595182dd0#excel-%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E9%85%8D%E5%88%97%E5%A4%89%E6%95%B0%E3%81%AB%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80%E3%81%AB%E3%81%AF)」の方法に従って、いったんExcelテーブルをArray変数に読み込み、多重ループをまわすことです。


Array変数は変数マネージャーでの初期化のところで、Excelファイルからデータを読み込んでおく (Read from excel/csv file) というオプションがあります。ここで「すべてのセル (All Cells)」を指定して読み込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/b90dfefe-01ba-aa67-bdb2-d8a2f9ff07b9.png)

すると、変数マネージャーでArray変数 `$arrayTable$` が定義されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/1c8daa43-225c-a794-751e-0e910b4468a2.png)

これを使ってアクションリストを組むと以下のようになります。内側/外側ともにLOOP-Timesで多重ループを組みます。先に説明したように `$Counter$` 変数はひとつしかないので、外側のループの値を `$Row$` 変数に代入して内側のループに持ち込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/8f123f16-3f2a-c230-3b42-dc9daab8c532.png)


今回は、Array変数に読み込んだデータにはヘッダーかどうかの区別がないため、メッセージボックスに表示される実行結果は「名前」「生年月日」「山田太郎」「1971/3/4」「石川たか子」「1986/12/4」「鈴木一郎」「1976/3/31」...と、ヘッダーも含めて列挙されてしまいます。ここは必要に応じて後で工夫すればよいです。


# まとめ
いかがでしたでしょうか。Automation Anywhere ではループを多重に組むことも可能です。ループ内での現在位置を表す`$Counter$` システム変数は一つしかないので、外側のループでの値を適宜他の変数に代入して内側に持ち込んでください。

最後までお読みいただきありがとうございました。