はじめに
VBAにおいても基本的なアルゴリズムを使うと色々と便利になります。
ここでは、個人的に重用している「ソート(並べ替え)アルゴリズム」や「Excelの列番号取得のアルゴリズム」などの、基本的なコードを備忘として残しておきます。
<目次>
1. 並べ替えのアルゴリズム(ソートアルゴリズム)
1-1. 前準備(共通で使用する関数)
1-2. バブルソート
1-3. クイックソート
1-4. 2次元配列のソート
2. 進数変換のアルゴリズム
2-1. 進数変換の計算方法
2-2. 10進数からn進数に変換するサンプルコード
2-3. n進数から10進数に変換するサンプルコード
3. Excelの列番号を取得するアルゴリズム
3-1. Excelの列番号を取得するアルゴリズムについての考察
3-2. 数字をアルファベット列番号に変換するサンプルコード
3-3. アルファベット列番号を数字に変換するサンプルコード
1. 並べ替えのアルゴリズム(ソートアルゴリズム)
ソートアルゴリズムは、データを並べ替えるためのアルゴリズムです。
ここでは、簡単に実装できる例としてバブルソートを、処理の早い例としてクイックソートを紹介しておきます。
あわせて、2次元配列を対象としたソートについても、サンプルコードと簡単な説明を書いておきます。
1-1. 前準備(共通で使用する関数)
先に、共通で使用する関数(プロシージャ)を書いておきます。
この記事で書くサンプルコードに使用していきますので、最初にこれらのコードを標準モジュールに記載しておいてください。
<スワップ関数>
2つの値を入れ替えるだけの関数です。
'スワップ関数(値aと値bを入替えるプローシージャ)
Sub Swap(a As Variant, b As Variant)
Dim tmp As Variant
tmp = a
a = b
b = tmp
End Sub
<配列作成関数>
乱数を利用して配列を作成する関数です。
配列nums()
に、n
個の要素(整数値)をランダムに作成します。
'乱数による配列作成プロシージャ
Sub CreateArray(nums() As Long, n As Long)
Dim i As Long
ReDim nums(n - 1)
Randomize '乱数ジェネレーターを初期化(都度異なる乱数値を取得するため)
For i = 0 To UBound(nums)
nums(i) = Fix(Rnd * n)
Next
End Sub
<配列出力関数>
1次元配列をイミディエイトウィンドウに出力する関数です。
'1次元配列の内容を出力するプロシージャ
Sub PrintArray(nums As Variant)
Dim i As Long
Dim buf As String
For i = 0 To UBound(nums)
buf = buf & nums(i) & ", "
Next
Debug.Print buf
End Sub
1-2. バブルソート
バブルソートは処理速度が遅いですが、アルゴリズムが単純なので、簡単に作成することができます。
データが大量でなければ、このバブルソートで十分だったりします。
1-2-1. バブルソートのアルゴリズム概要
バブルソートは、以下の図のように隣り合う要素を順に比較して、値が大きいものを後ろに移動させていくアルゴリズムです。
一巡するたびに、一番大きい値が末尾に置かれて確定していきます。
バブル(泡)がどんどん上に上っていくように、大きい値が末尾に移動して確定していくというイメージです。
1-2-2. バブルソートのサンプルコード(数値型)
<ソースコード>
'バブルソート
Sub BubbleSort(nums() As Long)
Dim i As Long
Dim j As Long
For i = UBound(nums) - 1 To 0 Step -1 '比較する範囲を1つずつ小さくしていく
For j = 0 To i
If nums(j) > nums(j + 1) Then
Call Swap(nums(j), nums(j + 1)) '前方の値の方が大きければ数値を入れ替える
End If
Next
Next
End Sub
For i = UBound(nums) - 1 To 0 Step -1
のところで、1巡目、2巡目、3巡目と進むにつれて比較する範囲を一つずつ小さくしています。
If nums(j) > nums(j + 1) Then
のところで数値の大小を比較して、前者の数字が大きければSwap関数
で入替え処理をしています。
<出力確認>
'BubbleSortの出力
Sub OutputBubbleSort()
Dim nums() As Long
Call CreateArray(nums, 10) '配列を作成
Call PrintArray(nums) 'ソート前の配列を出力
Call BubbleSort(nums) 'バブルソートを実行
Call PrintArray(nums) 'ソート後の配列を出力
End Sub
7, 2, 0, 9, 8, 8, 7, 6, 4, 2,
0, 2, 2, 4, 6, 7, 7, 8, 8, 9,
1-2-3. バブルソートのサンプルコード(Variant型)
実際にソートを使用する場合には、数値型以外の文字列型、日付型のデータを並べ替えする必要も生じます。
そういう前提を踏まえて、Variant型でソースコードを作成していると便利な場合もありますので、以下ソースコードを残しておきます。
<ソースコード>
'バブルソート(Variant型)
Sub BubbleSortV(arr As Variant)
Dim i As Long
Dim j As Long
For i = UBound(arr) - 1 To 0 Step -1
For j = 0 To i
If arr(j) > arr(j + 1) Then
Call Swap(arr(j), arr(j + 1))
End If
Next
Next
End Sub
<出力確認>
例として、日付型のデータの並べ替えをしてみます。
Sub OutputBubbleSortV()
Dim arr As Variant: arr = Array(#11/21/2020#, #11/4/2020#, #9/12/2020#, #10/30/2020#, #10/2/2020#)
Call BubbleSortV(arr)
Call PrintArray(arr)
End Sub
2020/09/12, 2020/10/02, 2020/10/30, 2020/11/04, 2020/11/21,
以上のように、日付型として並べ替えされていることが分かります。
1-3. クイックソート
クイックソートは、その名のとおり処理速度が速いアルゴリズムです。
取り扱うデータが大量となる場合は、こちらのアルゴリズムを使った方が良いでしょう。
1-3-1. クイックソートのアルゴリズム概要
クイックソートでは、以下の図のように、配列の中で基準となる数値を一つ決めて、基準よりも小さい値のグループと、基準以上の値のグループに分けていきます。
各グループで更にこれを繰り返すことで、並べ替えを完了させるアルゴリズムです。
1-3-2. クイックソートのサンプルコード(数値型)
以下のサンプルコードでは、基準値として配列の中央を選択しています。
細かいことは、ソースコードの後で説明をします。
<ソースコード>
'クイックソート
'引数(nums=対象となる配列、s=配列の開始位置、e=配列の終了位置)
Sub QuickSort(nums() As Long, s As Long, e As Long)
If s >= e Then Exit Sub '開始位置sが終了位置e以降になる場合は関数を抜ける
Dim i As Long
Dim p As Long: p = s
Call Swap(nums(s), nums((s + e) \ 2)) '配列中央の値を基準値にして先頭と入れ替え
For i = s + 1 To e
If nums(i) < nums(s) Then 'nums(s)を基準値として数値を比較していく
p = p + 1 '基準値より小さい数があるごとにpを1つ進める
Call Swap(nums(i), nums(p)) 'Swap関数で入れ替えを行う。
End If
Next
Call Swap(nums(s), nums(p)) 'Swap関数で入れ替え
Call QuickSort(nums, s, p - 1) '基準値より小さいグループを再帰処理
Call QuickSort(nums, p + 1, e) '基準値より大きいグループを再帰処理
End Sub
<出力確認>
'QuickSortの出力
Sub OutputQuickSort()
Dim nums() As Long
Call CreateArray(nums, 10) '配列を作成
Call PrintArray(nums) 'ソート前の配列を出力
Call QuickSort(nums, 0, UBound(nums)) 'クイックソートを実行
Call PrintArray(nums) 'ソート後の配列を出力
End Sub
6, 3, 0, 1, 4, 1, 8, 0, 1, 9,
0, 0, 1, 1, 1, 3, 4, 6, 8, 9,
<ソースコードの説明>
基本的なアルゴリズムの実装方法は、Wikipediaに書いてあるとおりですが、実際にコードにしようとすると少々複雑なコードとなってしまいます(私にとっては)。
そのため、ここでは、こちらの論文「(MAX上における)アルゴリズム的問題におけるユーザーインターフェースの改良」で紹介されているクイックソートの考え方をベースとしてコードを書いています。
処理の流れを図解すると、次のようになります。
以上の処理を終えた後に、更に、基準値未満の数(s
からp-1
までの要素)と、基準値以上の数(p+1
からe
までの要素)について同じ処理を再帰的に繰り返すことになります。
1-3-3. クイックソートのサンプルコード(Variant型)
これはもう書くまでもないかもしれません。
念のため、数値型以外(文字列型、日付型など)でも並べ替えができるように、Variant型でソースコードを作成した場合の例を記載しておきます。
'クイックソート(Variant型)
Sub QuickSortV(arr As Variant, s As Long, e As Long)
If s >= e Then Exit Sub
Dim i As Long
Dim p As Long: p = s
Call Swap(arr(s), arr((s + e) \ 2))
For i = s + 1 To e
If arr(i) < arr(s) Then
p = p + 1
Call Swap(arr(i), arr(p))
End If
Next
Call Swap(arr(s), arr(p))
Call QuickSortV(arr, s, p - 1)
Call QuickSortV(arr, p + 1, e)
End Sub
1-4. 2次元配列のソート
実際に並べ替え処理を行いたいのは、2次元配列の場合が多いと思いますので、備忘用にサンプルコードを記載しておきます。
対象として次のようなテーブルを例にします。
どのカラム(列)でソートを掛けるかで、並ぶ順番も変わってきます。
名前 | 区分 | 価格 | 個数 | 日付 |
---|---|---|---|---|
にんじん | 野菜 | 70 | 3 | 2020/11/14 |
りんご | 果物 | 150 | 2 | 2020/11/18 |
みかん | 果物 | 40 | 10 | 2020/10/22 |
キャベツ | 野菜 | 180 | 1 | 2020/11/1 |
トマト | 野菜 | 50 | 3 | 2020/11/20 |
じゃがいも | 野菜 | 50 | 15 | 2020/11/5 |
バナナ | 果物 | 300 | 2 | 2020/10/15 |
メロン | 果物 | 1500 | 1 | 2020/11/8 |
1-4-1. 2次元ソートのサンプルコード(クイックソート)
2次元配列のため、データ型は文字列型(String型
)に固定して処理を行ってます。
工夫が必要となるのは、対象が数値、日付の場合の並べ替えです。
これは、IsNumeric関数
で数値かどうかを、IsDate関数
で日付かどうかを判定して、それぞれのデータ形式に応じた並べ替え処理を行うようにしています。
<ソースコード>
'2次元クイックソート
'引数(arr=対象となる配列、s=配列の開始位置、e=配列の終了位置、t=対象となる列番号)
Sub QuickSort2D(arr() As String, s As Long, e As Long, t As Long)
If s >= e Then Exit Sub '開始位置sが終了位置e以降になる場合は関数を抜ける
Dim i As Long, j As Long
Dim p As Long: p = s
Dim flg As Boolean
Dim typ As Long
If IsNumeric(arr(t, s)) Then
typ = 0 '数値型の場合
ElseIf IsDate(arr(t, s)) Then
typ = 1 '日付型の場合
Else
typ = 2 'それ以外の場合
End If
For j = 0 To UBound(arr, 1)
Call Swap(arr(j, s), arr(j, (s + e) \ 2)) 'Swap関数で入れ替え
Next
For i = s + 1 To e
Select Case typ
Case 0
flg = Val(arr(t, i)) < Val(arr(t, s)) '数値で比較
Case 1
flg = CDate(arr(t, i)) < CDate(arr(t, s)) '日付で比較
Case Else
flg = arr(t, i) < arr(t, s) '文字列で比較
End Select
If flg Then 'arr(t, s)を基準値として数値を比較していく
p = p + 1 '基準値より小さい数があるごとにpを1つ進める
For j = 0 To UBound(arr, 1)
Call Swap(arr(j, i), arr(j, p)) 'Swap関数で入れ替えを行う。
Next
End If
Next
For j = 0 To UBound(arr, 1)
Call Swap(arr(j, s), arr(j, p)) 'Swap関数で入れ替え
Next
Call QuickSort2D(arr, s, p - 1, t) '基準値より小さいグループを再帰処理
Call QuickSort2D(arr, p + 1, e, t) '基準値より大きいグループを再帰処理
End Sub
なお、上記のサンプルコードでは、最初の要素のみでデータ型を判定しています。
正確を期すならば、複数行の判定を行っても良いかもしれません。
<出力確認>
以下、出力用のコードと、イミディエイトウィンドウの表示例を示しておきます。
サンプル用の2次元配列の作成部分が、ちょっと不格好です(もっといい方法がありそうな気がします)。
'QuickSortの出力(2次元)
Sub OutputQuickSort2D()
Dim arr() As String
Call Create2DArray(arr) '2次元配列の作成
Call QuickSort2D(arr, 0, UBound(arr, 2), 4) '列番号4(日付)を基準に2次元ソートの実行
Call Print2DArray(arr) 'ソート後2次元の配列出力
End Sub
'2次元配列を作成するプロシージャ
Sub Create2DArray(arr() As String)
Dim table As String
table = "にんじん,野菜,70,3,2020/11/14;" & _
"りんご,果物,150,2,2020/11/18;" & _
"みかん,果物,40,10,2020/10/22;" & _
"キャベツ,野菜,180,1,2020/11/1;" & _
"トマト,野菜,50,3,2020/11/20;" & _
"じゃがいも,野菜,50,15,2020/11/5;" & _
"バナナ,果物,300,2,2020/10/15;" & _
"メロン,果物,1500,1,2020/11/8"
Dim i As Long, j As Long
Dim tmp1 As Variant, tmp2 As Variant
tmp1 = Split(table, ";")
ReDim arr(UBound(Split(tmp1(0), ",")), UBound(tmp1))
For i = 0 To UBound(arr, 2)
tmp2 = Split(tmp1(i), ",")
For j = 0 To UBound(arr, 1)
arr(j, i) = tmp2(j)
Next
Next
End Sub
'2次元配列の内容を出力するプロシージャ
Sub Print2DArray(arr As Variant)
Dim i As Long, j As Long
Dim Output As String
For i = 0 To UBound(arr, 2)
For j = 0 To UBound(arr, 1)
Output = Output & arr(j, i) & ", "
Next
Output = Output & vbCrLf
Next
Debug.Print Output
End Sub
バナナ, 果物, 300, 2, 2020/10/15,
みかん, 果物, 40, 10, 2020/10/22,
キャベツ, 野菜, 180, 1, 2020/11/1,
じゃがいも, 野菜, 50, 15, 2020/11/5,
メロン, 果物, 1500, 1, 2020/11/8,
にんじん, 野菜, 70, 3, 2020/11/14,
りんご, 果物, 150, 2, 2020/11/18,
トマト, 野菜, 50, 3, 2020/11/20,
以上のように、うまく日付順にソートすることができています。
バブルソートの例は掲載しませんが、気になる方はご自身で作成してみてください。
2. 進数変換のアルゴリズム
次に、進数の変換に関するアルゴリズムです。
あまり使う機会は少ないかもしれませんが、この考え方は、次に紹介する「3. Excelの列番号を取得するアルゴリズム」でも使用しますので、先に書いておきます。
2-1. 進数変換の計算方法
予備知識として、簡単な形ではありますが、進数の計算方法について書いておきます。
例えば、10
という数字を2進数に変換
するには、次のように、数字を基数2
で割っていくことで計算できす。
10 ÷ 2 = 5 余り 0 → 商の5は再度[基数2]で割る。余りの0は1の位の数字となる
5 ÷ 2 = 2 余り 1 → 商の2は再度[基数2]で割る。余りの1は2の位の数字となる
2 ÷ 2 = 1 余り 0 → 商の1は再度[基数2]で割る。余りの0は3の位の数字となる
1 ÷ 2 = 0 余り 1 → 商が0なので計算終了。余りの1は4の位の数字となる
10を2進数で表示すると[1010]となる。
4進数であれば基数4
で割り、16進数であれば基数16
で割れば、同様に算出できます。
なお2進数1010
を10進数に直すには、次のように計算します。
[1の位の0] × [2の0乗] = 0
[2の位の1] × [2の1乗] = 2
[3の位の0] × [2の2乗] = 0
[4の位の1] × [2の3乗] = 8
以上の結果を加算して、0 + 2 + 0 + 8 = 10となる。
つまり、2進数1010
において、4の位の1
は1 × 2の3乗
(すなわち8
)を表し、2の位の1
は1 × 2の1乗
(すなわち2
)を表しているといことです。
これを10進数365
で考えると、3の位の3
は3 × 10の2乗
(すなわち300
)を表し、2の位の6
は6 × 10の1乗
(すなわち60
)を表し、1の位の5
は5 × 10の0乗
(すなわち5
)を表していることと同じです。
2-2. 10進数からn進数に変換するサンプルコード
以上の考え方を元にして10進数からn進数に変換するソースコードを書くと次のようになります。
<ソースコード>
'整数(num)をn進数(base)に変換する
Function ConvBaseNumber(ByVal num As Long, base As Long) As String
If base <= 0 Or base > 35 Then Exit Function 'エラー回避
Dim rmd As String '余り(remainder)を格納
Do While num
rmd = num Mod base '基数で割った余りを取り出す
num = num \ base '基数で除算
If Val(rmd) > 9 Then rmd = Chr(55 + rmd) 'remが10以上の場合はアルファベットに変換
ConvBaseNumber = rmd & ConvBaseNumber
Loop
End Function
少々厄介に見えるのは、If Val(rmd) > 9 Then rmd = Chr(55 + rmd)
の部分だと思います。
16進数などの場合は、10以上の数字を、A
、B
、C
、D
、E
、F
というようにアルファベットで表示しますので、ここでその変換処理を行っています。
例えば、A
の文字コードは、SHIFT_JISコード(ASCIIコード)で65
となります。
そして、VBAのChr関数
を使用して、Chr(65)
と書くことで、文字コード65
から文字A
を表示することができます。
なお、B
の文字コードは66
、C
の文字コードは67
というように、文字コードが1つ加算されるごとに、アルファベットも1つずつ進むようになっています。
この考え方を使用してChr(55 + rmd)
の部分で、数値をアルファベットに変換しています(rmd=10
ならば戻り値はA
となるということです)。
<出力確認>
'ConvBaseNumberの出力
Sub OutputConvBaseNumber()
Debug.Print ConvBaseNumber(255, 2)
Debug.Print ConvBaseNumber(255, 16)
End Sub
11111111
FF
2-3. n進数から10進数に変換するサンプルコード
次にn進数から10進数に変換するコードを書くと、次のようになります。
<ソースコード>
'n進数(n = base)を10進数に変換する
Function ConvDecimalNumber(strNum As String, base As Long) As Long
If base <= 0 Or base > 35 Then Exit Function 'エラー回避
Dim i As Long
Dim tmpChr As String
Dim tmpNum As Long
For i = 0 To Len(strNum) - 1
tmpChr = Mid(strNum, Len(strNum) - i, 1) '数字を1つずつ取り出す
If IsNumeric(tmpChr) Then
tmpNum = Val(tmpChr)
Else
tmpNum = Asc(tmpChr) - 55 'アルファベットの場合は数値に変換
End If
ConvDecimalNumber = ConvDecimalNumber + tmpNum * (base ^ i)
Next
End Function
ここでは、先ほどの例(10進数からn進数に変換)の場合と逆に、A
、B
、C
というようなアルファベットを、数値に変換する必要があります。
これは、文字
から文字コード
を取り出すAsc関数
を使用することで処理をしています。
コード中のtmpNum = Asc(tmpChr) - 55
の部分となります。
<出力確認>
'ConvDecimalNumberの出力
Sub OutputConvDecimalNumber()
Debug.Print ConvDecimalNumber("11111111", 2)
Debug.Print ConvDecimalNumber("AA", 16)
End Sub
255
170
以上のように、正常に変換されています。
なお、n進数から10進数に変換
する関数と、10進数からn進数に変換
する関数を組み合わせれば、n1進数からn2進数に変換
というように、自由に進数を変換する関数を作ることもできます。
3. Excelの列番号を取得するアルゴリズム
最後に、Excelの列番号を取得するアルゴリズムについてです。
Excel表では、1番目の列はA
、6番目の列はF
、28番目の列はAB
というように、列番号をアルファベットで表示しています。
この数字とアルファベットの関係を取得するソースコードについて考えてみます。
3-1. Excelの列番号を取得するアルゴリズムについての考察
アルゴリズムについては、何となく、A
を0
、B
を1
というように順に数字を当てはめて、最後はZ
が25
となる26進数
と考えれば良さそうです。
しかし、少し考慮しないといけないことがあります。
列番号A
、AA
、AAA
を見てみると、実際は次のように数字に対応しています。
列番号 A = 1
列番号 AA = 27
列番号 AAA = 703
※列番号Aは0でなく1としています(Cellsプロパティに対応させるためです)
ここで、26進数として、A
を0
と置き換えると、列番号A
は0
、列番号AA
は00
、列番号AAA
は000
と変換されて、全て0
という値を持つことになります。
26進数に当てはめるならば、桁数が変わる度に、また0
からカウントするという形式と捉える必要があるわけです。
Excelの列番号について整理すると次のような形になります。
桁数 | 範囲 | 組合せ数 | 開始値 | 終了値 |
---|---|---|---|---|
1桁 | A~Z | 26通り | 1(A) | 26(Z) |
2桁 | AA~ZZ | 26×26通り | 27(AA) | 702(ZZ) |
3桁 | AAA~ZZZ | 26×26×26通り | 703(AAA) | 18278(ZZZ) |
各桁数の最初の列番号について、計算で取得してみると、次のようになります。
列番号A
の数字については、26進数変換によるA = 0
に補正値1
(Cellsプロパティに対応させるため)を加算することで1
が導き出されます。
列番号AA
の数字については、26進数変換によるAA = 0
に、A~Zまでの組合せ数26
を加算し、最後に補正値1
(Cellsプロパティに対応させるため)を加算することで27
が導き出されます。
列番号AAA
の数字については、26進数変換によるAAA = 0
に、A~Zまでの組合せ数26
及びAA~ZZまでの組合せ数26 × 26 = 676
を加算し、最後に補正値1
(Cellsプロパティに対応させるため)を加算することで703
が導き出されます。
それ以外の列番号で見てみると、例えば、列番号AC
であれば、26進数変換によるAC = 2
に、A~Zまでの組合せ数26
を加算し、最後に補正値1
(Cellsプロパティに対応させるため)を加算することで29
が導き出されます。
以下、このルールに従って、ソースコードを作成していきます。
3-2. 数字をアルファベット列番号に変換するサンプルコード
ます、数字から列番号に変換するコードについてです。
先に検討したルールを踏まえると、引数として渡す数値が、1~26
の範囲か、27~702
の範囲か、703~18278
の範囲かを判定した上で、処理を進めていく必要があります。
<ソースコード>
'Excelの行番号(Alphabet)を取得する関数
Function Num2ExlClm(ByVal num As Long) As String
Dim digits As Long: digits = 0
Do While num >= 26 ^ digits
num = num - 26 ^ digits
digits = digits + 1
Loop
Dim i As Long
For i = 0 To digits - 1
Num2ExlClm = Chr(num Mod 26 + 65) & Num2ExlClm
num = num \ 26
Next
End Function
上記のコードをみてみると、引数としてnum = 1
が渡されたら、Do While num >= 26 ^ digits
の部分を1回通り、num = num - 26 ^ digits
のところで、num = 0
に変換されます(あわせてdigits = 1
となります)。
そして、For i = 0 To digits - 1
のところで、digits(桁数)が1
であることから1回ループして、0 = "A"
と読み替えられて、"A"
を戻り値として返します。
また、引数としてnum = 30
が渡されたら、Do While num >= 26 ^ digits
の部分を2回通り、num = num - 26 ^ digits
のところで、num
の値は1回目で1
減算して、2回目で26
減算して、num = 3
に変換されます(あわせてdigits = 2
となります)。
そして、For i = 0 To digits - 1
のところで、digits(桁数)が2
であることから2回ループして、3 = "AD"
と読み替えられて、"AD"
を戻り値として返します。
<出力確認>
'Num2ExlClmの出力
Sub OutputNum2ExlClm()
Debug.Print Num2ExlClm(5)
Debug.Print Num2ExlClm(2000)
End Sub
E
BXX
3-3. アルファベット列番号を数字に変換するサンプルコード
これも、先述した考え方に沿って、引数として渡す文字列がE
というように1桁であれば加算値は1
として、引数として渡す文字列がAA
というように2桁であれば加算値は26 + 1 = 27
として、引数として渡す文字列がBXX
というように3桁であれば加算値は26 + 26 × 26 + 1 = 703
として、これをアルファベットを26進数として見立てた数字
と合算することで必要な数値を導き出します。
<ソースコード>
'Excelの行番号から数字を取得する関数
Function ExlClm2Num(ByVal alphabet As String) As Long
Dim i As Long
Dim digits As Long: digits = Len(alphabet) '文字列の長さから桁数を出す
For i = 0 To digits - 1
ExlClm2Num = ExlClm2Num + 26 ^ i '1つ前の桁数までの組合せ数を加算
Next
Dim tmpNum As Long
For i = 0 To Len(alphabet) - 1
tmpNum = Asc(Mid(alphabet, Len(alphabet) - i, 1)) - 65 'アルファベットを取り出して数値に変換
ExlClm2Num = ExlClm2Num + tmpNum * (26 ^ i)
Next
End Function
'ExlClm2Numの出力
Sub OutputExlClm2Num()
Debug.Print ExlClm2Num("E")
Debug.Print ExlClm2Num("BXX")
End Sub
<出力確認>
5
2000
以上のように、必要な数字に変換することができました。
さいごに
職場が変わって、過去のコードをコピペできない状況になり、ソート関数などをまた1から書いたりしていました。
そのため、この記事は、「自分自身が基本的なコードをいつでもコピペで使えるように」という意図で書いたものです。
本当は、マージソートやヒープソートのほか、ナップサック問題やダイクストラ法あたりまでは入れておきたかったのですが、そもそも使う場面が少ないし、気力も尽きてしまったことから、そのあたりはまた後日ということにします。
2020/12/12追記
当初のクイックソートのソースコードでは、「配列の先頭を基準値として拾う場合」と、「配列の中央を基準値として拾う場合」の2種類を掲載していました。
しかし、前者においては、対象となる配列がほぼ昇順に並んでいる場合は、計算量がO(n2)となりバブルソート並みになるため、前者を削り、後者の「配列の中央を基準値として拾う場合」のみに改めました。