RPAでExcelを操作する際のヒント (UiPath編)

RPAツールでは、Excelのプログラムインターフェイスを使って外部からExcelを操作したり、キーボード操作/マウス操作をExcelのウィンドウに送ることで、Excelを外部から操作できます。それにより、Excelファイルを加工したり、データを読み込んだり書き出したり、他のツールと連携させたり、といったことが可能になります。

この記事では、UiPathではどういった仕組みを標準機能でサポートしているかと同時に、Excel操作でよくやりたいことをベースに逆引きで記載してみました。

**環境**

* UiPath Studio 2019.07 
* Microsoft Excel 2019 (サポート範囲は「[Excel アクティビティパックについて](https://docs.uipath.com/activities/lang-ja/docs/about-the-excel-activities-pack)」を参照) (with **UiPath.Excel.Activities**)

# UiPathのExcel関係コマンド
利用できるアクティビティとして、以下の35種類が標準で用意されています (以下、**Excel系アクティビティ**と呼びます)。これらを使うと、Excelを操作したい部分のかなりの部分をカバーできます。
![uipath-excel-activities.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/c41086e3-81b0-a6bf-4881-c433e413baa9.png)

また、上記と同じ動作がありますが、以下の9種類のアクティビティはExcelがない環境でも動作します(以下、**ワークブック系アクティビティ**と呼びます)。これはバックエンドの仮想マシン上で多数のExcelを処理する場合にいくつExcelのライセンスが必要になってくるかに影響し、またExcel for Office 365の場合はユーザーライセンスのためバックエンドの利用がライセンス上難しかったり、RDSへのインストールサポートがないなどグレーな部分があるため重宝します。
![uipath-workbook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/d896c12a-4591-0a65-9404-331726578fe6.png)

このほかは、キーボード操作やマウス操作をExcelのウィンドウに送る、特に[Excelで用意されているショートカットキー](https://support.office.com/ja-jp/article/1798d9d5-842a-42b8-9c99-9b7213f0040f?ui=ja-JP&rs=ja-JP&ad=JP)を駆使して操作します。もしくは、操作するExcelファイル内にあらかじめVBAでプログラムを書いておき、それを呼び出すという方法で複雑な操作の補完ができます。


# Excelアプリケーションスコープとは
Excel系アクティビティの実行をする際に最初に定義しておくことが必須となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/fc5b7900-1ce1-40ce-baf8-d60435af4423.png)
プロパティには、開くワークブックのパスを「ワークブックのパス」に指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/34d60d3e-fdef-d932-98cf-1777c5395099.png)
このスコープで囲まれている範囲内に各種Excel系アクティビティを入力します。

# こんなことをやるには！？


### ファイルを読み込むには
ファイルの読み込みは、実はExcelアプリケーションスコープにワークブックのパスを指定して実行すれば完了です。ただし、Excelアプリケーションスコープ内のすべてのアクティビティが終了するとExcelが閉じてしまうので、「ワークフロー > 制御 > 待機」アクティビティを入れると、待機時間だけExcelが表示されて閉じます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/24bf3736-a1b0-fbfd-ec3f-d942aeefd523.png)

もしくは、開いたワークブックの**セッション**を変数に保持しておくと、Excelアプリケーションスコープ終了後も、ロボットの全処理終了までExcelウィンドウは開いたままになります。後でもろもろの操作を行う際にも便利なので、Excelアプリケーションスコープの「出力 > ワークブック」プロパティに変数を指定しておきましょう。

変数は、右クリックで「変数の作成」メニューから作成できます。
![create-variable.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/b7012479-b16f-9243-b4a7-3fc92fd52188.png)

変数の型は「Workbook.Application」を選択、ここで作成した変数 (ここではwaBook1)を、「出力 > ワークブック」プロパティに指定します。
![Excel-application-scope-variable.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/38e315f1-a24c-84df-0d7c-3c629901e499.png)


ロボットの終了後Excelを開いたままにする操作は少々厄介で、ロボットのすべての処理をExcelアプリケーションスコープ内で完了させた後に、Excelファイルをいったん閉じさせて、その後「システム > アプリケーション > プロセスを開始」アクティビティで、同じワークブックのパスを指定して実行して開きなおす、といったことが必要になります。詳しくは別途実験した記事「[【UiPath】Excelアプリケーションスコープで開いたファイルを開いたままにする](https://qiita.com/vicugna-pacos/items/55725ec7526a5f80d82f)」を紹介しておきます。


### ファイルを閉じるには
先に説明した通り、UiPath では処理が終わるとファイルは自動的に閉じますが、その前に強制的に閉じたい場合は、「ワークブックを閉じる」アクティビティを使います。ターゲットとなるワークブックには、Excelアプリケーションスコープで取得したセッションの変数を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/15e58fd7-3f94-1155-13a3-e6f1b4bf96f1.png)

ちなみに、ファイルを閉じるときに自動で内容が保存されるかどうかは、Excelアプリケーションスコープのプロパティ「自動保存」で決まります。

### Excel ファイルを新規作成する
Excelアプリケーションスコープにワークブックのパスを指定する際に、存在しないExcelファイル名を指定しておけば、その場所に新しいExcelファイルが作成されます。Excelアプリケーションスコープのプロパティのオプションで「新しいファイルの作成」がONになっている必要があります。また、指定したパスは書き込み可能である必要があります。

### 別名で保存するには
`F12`キーで「名前を付けて保存」ダイアログボックスを開き、新しいファイル名を指定して`ENTER`キーを押下すればOKです。`F12`キーは「UI Automation > 要素 > キーボード > ホットキーを押下」アクティビティで入力、キーボード入力は「UI Automation > 要素 > キーボード > 文字を入力」アクティビティで指定します。ファイル名の後ろに`k(enter)`と、`ENTER`キーを押下するコマンドを入れ、全体をダブルクオートで囲えばOKです。UI要素は指定しなくても、アクティブウィンドウに送信してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/7334037c-63bc-f560-7416-a634196c6757.png)

### シートの切り替え、新規作成、名前の変更を行うには
シートの切り替えのための専用アクティビティはありませんが、「範囲を選択」アクティビティで切り替えたい先のシート名を指定し、範囲としてどこか任意の場所を指定すれば、そこが選択された状態でシートが切り替わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/d082589e-9411-dbac-e84b-e776c388dcd9.png)

シートの新規作成は`Shift`+`F11`のキーボードショートカット操作を行います。

シートの名前変更は、キーボードショートカット操作`Alt`＋`H`＋`O`＋`R`の後、新しい名前`ENTER`を「UI Automation > 要素 > キーボード > 文字を入力」アクティビティで入力します。

### セルの値を読む、セルに値を書き込むには
セルの値の読み込みには1つのセルを取得する方法と、範囲を読み込む方法があります。

**1つのセルを取得**
セルの値を変数に読み込むには、「セルを読み込み」アクティビティを使います。あらかじめ変数を作成して起き、プロパティの「結果」に指定します。「表示形式を保持」のオプションを使って、見た目の書式通りに文字列を格納するのかどうかを選べます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/8d1b42de-fd64-5853-11da-85279e9d9fc6.png)

**範囲を読み込む**
「範囲を読み込み」アクティビティでは、アドレスでセルの範囲指定を行います。あらかじめDataTable型 (Visual BasicのクラスでいうSystem.Data.DataTable)の変数 dtDataTableを作成して起き、出力結果に指定すると、この変数に指定した範囲のデータが読み込まれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/d5ad736c-69c5-f871-bf71-6d5deaeb4472.png)

DataTable型はUiPathのコーディングの中でよく使われます。各セルのデータへのアクセス方法ですが、たとえば"A1:B10"の範囲をすべてデータとして読み込んだ場合、"B3"のデータへのアクセス方法は `dtDataTable(2)(1)` または `dtDataTable.Rows(2).Item(1)`となります。DataTable型では最初の行/列のアドレスが0となります。つまり「dtDataTable(行-1)(列-1)」と覚えておくとよいでしょう。DataTable型の解説は @UmegayaRollcake さんの記事「[UiPathで避けて通れないDataTableをおさらい](https://qiita.com/UmegayaRollcake/items/a8e0b787d7c38077b8f2)」を参照してください。


セルに値を書き込むには、「セルに書き込み」アクティビティを使います。書き込むシート名、範囲、値を指定します。値はダブルクオートで囲みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/df77e5c0-c5c6-a898-926a-7fb52d0b762c.png)
もしくは、「範囲を選択」アクティビティの後、「UI Automation > 要素 > キーボード > 文字を入力」アクティビティを使う手もあります。文字入力時には、Excelウィンドウを指定して、最後に`ENTER`キーを押下しておくと入力が滞りなく行われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/876cdb0d-4da6-1cf2-e2f5-048dd94c9a22.png)


### セルの値を空白に戻すには
「セルに書き込み」アクティビティで "" を書き込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/aa470f7a-8649-bafb-5cae-08026658ccfb.png)



### セルに式を入力するには
値と同様に、「＝」(イコール)で始まる文字列を書き込めばOKです。

### セルの値でなく式を読み込むには
「セルの数式を読み込む」アクティビティを使います。たとえば、以下の表がある際に、B4のセルの値を「セルの数式を読み込む」「セルを読み込み」の両方で読み込んでみると違いが判ります。

||A|B|
|:--|:--|--:|
|**1**|商品|数量|
|**2**|A|10|
|**3**|B|15|
|**4**|合計|**25**|


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/3d4a0fbf-7e8b-b24e-dbcd-46362de95215.png)

* **セルの数式を読み込む**: "SUM(B2:B3)" (先頭のイコールは出力されません)
* **セルを読み込み**: "25"


### フォントやセルの色を変えるには
フォントやセルの色を変える、などの操作は、選択範囲に対してリボン上に表示されているコマンドはショートカットキーの押下で対応します。ただし、コントロール上で現在選択されている色は、対象とするセルの現在の色や装飾に依存するため、装飾が既定の状態 (フォント色=自動、セル色=白、太字/斜体/下線=なし、等)でない場合は意図しない結果になる可能性もあります。また、カラーパレットやショートカットはExcelのバージョンによっても異なるため、異なるバージョンが混在する場合も注意が必要です。
例:

* 太字:`Alt`+`H`+`1`
* 斜体:`Alt`+`H`+`I`+`1`
* 下線:`Alt`+`H`+`3`+`U`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/bbd0c338-da78-aec8-756f-c3935ebe9352.png)
A2を太字にする例。ショートカットキーを押下するときのウィンドウはExcelウィンドウを指定しておくこと。以下同様。

フォントの色を変更する例
赤: (`Alt`+`H`+`F`+`1`)+`↓`x7+`←`x4+`ENTER` 
(リボン上のフォントの色コントロールのドロップダウンメニューで下に7回、左に4回移動して赤を選択後、`ENTER`で確定)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/44b207de-7ec9-8ce2-4012-aaa2e89e8140.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/9d37d7fc-7224-b9fb-3cf0-f846bf0d60f7.png)


セルの色については「範囲の色を設定」アクティビティを使います。「シート名」と「範囲」はセルのアドレスを指定、「色」はダイアログボックスを開いて「Color.」と入力すると、入力候補の色のテキストが出てくるので選択後、「OK」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/4eff2680-e5cb-28e9-0851-347d102bbeca.png)


### Excel でデータの入っている一番最後の列/行の情報を取得するには
UiPathでは、アクティブセルを移動させるアクティビティがないので、ショートカットキーの押下で対応します。`Ctrl`+`→` (現在のデータ領域の右端列に移動)、`Ctrl`+`↓` (現在のデータ領域の末尾行に移動)を押下後、「選択範囲を取得」アクティビティで現在アクティブになっているセルのアドレスを取得できます。

### セルを削除するには
「行の挿入・削除」「列の挿入・削除」アクティビティを使います。それぞれ、削除する行/列の位置とそこから削除する行数/列数を数字で指定します。

もしくは「範囲を削除」アクティビティも使えます。こちらは、単一セルもしくは複数セルを選択し、削除した後に周りのセルをシフトするかどうかを指定するオプションがあります。

### 並び替えを行うには
テーブルを範囲指定してしまえれば、テーブル機能の並び替えを使うことができます。テーブルになる範囲を「"A1:F100"」のように指定して名前を付け、列名を指定して、プロパティの(並び替え)順序 (Ascending (昇順)/Descending (降順))を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/fa438658-87b5-09e2-71da-6ce0216c182b.png)

もしくは、キーボードショートカット操作を使います。表の中で並び替えたい列のどこかに「範囲を選択」アクティビティで移動します。その後、キーボードショートカット操作をExcelに送ります。(昇順は`Alt`+`A`+`S`+`A`、降順は`Alt`+`A`+`S`+`D`)

### 文字列/パターンの検索と置換
UiPathではExcelの検索/置換ダイアログボックスの機能を活用する機能が残念ながらありません。文字列を検索したい場合の一番簡単なパターンは、「範囲内で検索」アクティビティを使って指定した検索範囲の中で該当する値が最初に見つかるセルのアドレスを文字列で返すパターンです。`targetCell`というString型変数を作成してアクティビティの出力結果を受け取るように指定しておくと、アドレスが得られます。既出の表を検索すると、"10"が入力されている"B2"の文字列が返ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/e409cfcc-d61f-9e0f-9fca-d4aa2eead4a1.png)

この方法では、セル内の文字列に部分一致するものも結果が返ってくるので、セルの文字列との完全一致のもののみ結果としてほしいのであれば、得られたアドレスの文字列との比較をコーディングする必要があります。

複数個所に含まれる可能性がある文字列をすべて列挙するには、自分でコーディングして実装する必要がある。「プログラミング > データテーブル > データテーブルでフィルタリング」アクティビティもよく使われているようです。

文字列の置換を行うには、このアドレスのセルに含まれる文字列を取得して値を加工します。パターンマッチング、部分文字列置換は自分でコーディングして実装する必要があります。「プログラミング > 文字列 > 置換」アクティビティを使うのが便利です。



### Excelマクロを実行するには
「マクロを実行」アクティビティを使います。data.xlsm の Sheet1 に含まれる main() を呼び出すには、"data.xlsm!Sheet1.main"と記載します。マイクロに渡す引数、戻り値、エラーハンドリングを行うことができるプロパティがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/3d48650e-6582-7bf7-143f-a45ab1b0ab43.png)


# (おまけ) 運用環境と費用についての考察
今回は RPA ソフトウェアであるUiPathを使ってExcel操作を行ってみましたが、Excel操作を行うだけに特化すれば RPA を使わなくてもExcelマクロを使えば済んでしまいます。RPA は、どの主要ベンダーも、最低年間 100 万円弱くらいの費用がかかりますので、Excel操作だけでRPAを使うのはペイしないでしょう。RPA を実際に運用環境としてExcel操作に使うには、以下のような条件のいずれかを満たしている必要があるかと思います。

* 無料の Community Editionが使える小規模企業に該当 (年商500万米ドル未満、かつユーザー数/PC 250人/台未満)
* 既にRPAツールが別目的で導入されているため、Excel操作用の追加ライセンス費用があまりかからない
* Excel操作を他のシステムと連携させたり、大規模にExcel操作を行う必要がある

RPAツールをExcel操作に使うメリットは以下のようなものがありますので、上記の条件に該当するのであれば、活用してみたいところです。

* Excelマクロよりも操作が簡単である。プログラミングがわからなくても操作が可能
* 取り出したデータを他のシステムとも簡単に連携できる


# 参考情報

* [Excel for Windows のショートカットキー - Excel ヘルプ](https://support.office.com/ja-jp/article/1798d9d5-842a-42b8-9c99-9b7213f0040f?ui=ja-JP&rs=ja-JP&ad=JP) - バージョンごとに若干異なる場合があるので注意が必要です。