【UiPath】Excel - 列番号と列名称を変換する

# はじめに

この投稿は、RPAツールのUiPathで、Excelの列番号と列名を変換する方法についての投稿です。

「Excel操作を.NETのコードでやってみよう」シリーズです。他の投稿はこちら。

https://qiita.com/miya_g/items/1c3bb14583110ccac14b

https://qiita.com/miya_g/items/8341d6cc0cf0fb77ac31

https://qiita.com/miya_g/items/e36f7b5da5bc994a49d7

https://qiita.com/miya_g/items/e4bf3de19c8b0c4225ca


# 列番号と列名の相互変換

エクセルでは列位置の表現方法として「**列番号**」と「**列名**」があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/ed4dfe8b-2856-13b9-9685-0c1c4df05834.png)


列番号は例えば「1」、列名称は例えば「A」という感じですが、
UiPathではこの「列番号」を「列名」に変換したり、逆に戻したりと、相互の変換が必要になることがあります。
なぜなら「範囲選択」をする時に「列名」で範囲指定するからです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/5bbc9832-389f-93e4-3dbd-ef2c16875a40.png)
例えば、以下のように相互変換したい時があります

```
　例）1行目の10列目のセルの値を取得したい
　　　　⇒ 列番号「10」を列名「J」に変換し「J1」を範囲指定

　例）AG1から横に3セル取得したい
　　　 ⇒「AG」を列番号「33」に変換し、3足して「36」を「AJ」に変換し「AG1：AJ1」を範囲指定
```

なので、

・列番号「10」　⇒　列名称「J」
・列名称「AG」　⇒　列番号「33」

のような変換が、サッと出来ると便利です。


# 変換方法

2022年6月現在、`標準アクティビティ` ではこの「列名・列番号」の変換は提供されてませんが、以下の方法で変換できます。

1）UiPathが提供している ExcelUtilities を使う
2）.Netのコードで変換する


# 1）UiPathが提供している ExcelUtilities を使う

UiPath内部で使用する「ExcelUtilities」を使って、変換できます。

| 変換の例 | 構文 |
|:-:|:-:|
|列番号(1)->列名称(A) | UiPath.Excel.Helpers.ExcelUtilities.ConvertColumnIndexToColumnLetter(2)  |
|列名称(C)->列番号(2) | UiPath.Excel.Helpers.ExcelUtilities.ConvertColumnLetterToColumnIndex("C")  |

以下のように使用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/e6b8a3e8-a356-5d6a-03a0-226af1e37510.png)

ExcelUtilities が使えるバージョンなら、これが一番簡単です。（古いStudioバージョンの場合、使用できないかもしれません（未確認））




# 2）.Netのコードで変換する

原始的なやり方として「列名と列番号のセットをどこかに持たせておいて、そこから導き出す」方法もありますが、列は最大で「16,384」まであり全部用意するのが大変です。「1000列位までで良いよ」っていうならアリですが。出来るならロジックで計算して導き出すのがベターです。

# 列番号を列名称に変換

.NETのコードをInvokeCodeで実行させます。以下はVB.NETのコードです
　※ 移植しやすいように、匿名関数（Func）にしています

``` VB
Dim ConvertColumNumberToName As Func(Of Integer, String) = 
	Function(columnIndex As Integer) As String
		Dim colLetter As String = String.Empty
		Dim modNum As Integer = 0
		Dim divEnd As Integer = columnIndex
		While divEnd > 0
			modNum = (divEnd - 1) Mod 26 '// 26 = A-Z
			colLetter = Chr(65 + modNum) & colLetter '//char(65) = A
			divEnd = CInt((divEnd - modNum) \ 26)
		End While
		Return colLetter
	End Function

'// 列番号10は列名Jなので「J」と表示される
Console.WriteLine(ConvertColumNumberToName(10))
```

ロジックの説明はこちら（記述は少し違いますが、ロジックは一緒です）
　https://docs.microsoft.com/ja-jp/office/troubleshoot/excel/convert-excel-column-numbers

呼び出し可能なxamlファイルにしたものを用意しました。以下からダウンロードできます。
　[[github]ConvertColumNumberToName.xaml](
https://github.com/miyag/UiPath.ReusableCode/blob/master/ExcelSwitchColumnNumberAndColumnName/ConvertColumNumberToName.xaml)


# 列名を列番号に変換

こちらも.NETのコードをInvokeCodeで実行させます。以下はVB.NETのコードです
　※ 移植しやすいように、匿名関数にしています

``` VB
Dim ConvertColumNameToNumber As Func(Of String, Integer) = 
	Function(columnLetter As String) As Integer
		Dim sum As Integer = 0
		columnLetter = columnLetter.ToUpper()
		For idx As Integer = 0 To columnLetter.Length - 1
			sum *= 26
			Dim charA As Integer = CInt(Char.GetNumericValue("A"c))
			Dim charColLetter As Integer = CInt(Char.GetNumericValue(columnLetter(idx)))
			sum += (charColLetter - charA) + 1
		Next
		Return sum
	End Function

'// 列名AAは列番号27なので「27」と表示される
Console.WriteLine(ConvertColumNameToNumber("AA"))
```

呼び出し可能なxamlファイルにしたものを用意しました。以下からダウンロードできます。
　[[github] ConvertColumNameToNumber.xaml](https://github.com/miyag/UiPath.ReusableCode/blob/master/ExcelSwitchColumnNumberAndColumnName/ConvertColumNameToNumber.xaml)


# 終わりに

UiPath標準で「列名<->列番号」の変換アクティビティが登場してほしいですが、それまでは頑張って計算するしか有りません。難しくはないしコピペで済むので、参考になれば幸いです。

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