VBAでキュー(Queue)を使うには
キューとはデータを入れた順に取り出す仕組みのことで、ところてん方式とか言われることもあります。キューにデータを入れるエンキューと言い、取り出すことをデキューと言います。
このキューですが、VBAの標準の仕組みでは実装されていません。そのため、自作するか外部ライブラリを利用するかのどちらかになります。
自作するのであればクラスにエンキューとデキューのメソッドを用意して、データを保持する仕組みに配列かコレクションで実装する形になってくると思います。
キューを使う場合では一般的にはかなりの高速性や完全な排他制御を求められることが結構多く、そのような要求を満たすためにC言語+ミューテックスによる実装を行ったりすることが多くなりがちです。それに加えてVBAではそもそもキューを使う要件が少なく、高速性などの厳しい条件を求められることは少ないため、VBAにはキューが実装されていないのかもしれません。
とは言っても複数のブックに実装しているVBA間で排他や同期をとりたい場合などにキューの仕組みが必要になることもあります。
自作してもいいのですがそれは別に機会があればやるとして、ここでは.NET FrameworkのSystem.Collections.Queueクラスを利用する方法について説明します。
事前設定
.NET FrameworkのSystem.Collections.Queueクラスを利用するには事前に参照設定が必要です。
VBA画面のツールメニュー→参照設定で以下の選択もしくは参照してください。
C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb
Microsoft Common Language Runtime Class Library
詳細は「VBAで.NET FrameworkのArrayListを使う」にも書いていますのでご参照ください。
System.Collections.Queueクラスの使い方とコード例
System.Collections.Queueの各メソッドやプロパティの詳細は以下です。Microsoftのヘルプの日本語がおかしいのは標準仕様ですのでなんとか読み取ってください。
https://docs.microsoft.com/ja-jp/dotnet/api/system.collections.queue?view=netframework-4.8
メソッド等の詳細はリンクで見てもらうとして、実際にVBAで書く場合はどのように書くのかのコード例を紹介します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
Sub QueueTest() ' Dim q As Queue '// System.Collections.Queue Dim q As mscorlib.Queue '// System.Collections.Queue Dim sDeq As String '// Dequeue結果 '// インスタンス生成 ' Set q = New Queue Set q = CreateObject("System.Collections.Queue") '// データを4つ追加 Call q.Enqueue("1") Call q.Enqueue("2") Call q.Enqueue("3") Call q.Enqueue("4") '// 4を出力 Debug.Print q.Count '// 1つ取り出し+削除("1"を削除) sDeq = q.Dequeue '// 取り出した"1"を出力 Debug.Print sDeq '// 3を出力 Debug.Print q.Count '// キューに値が含まれる場合 If (q.Contains("3") = True) Then Debug.Print q.Contains("3") End If '// キューに値が含まれない場合 If (q.Contains("AAA") = False) Then Debug.Print q.Contains("AAA") End If '// 1つ取り出し+削除はしない sDeq = q.Peek() '// 取り出した"2"を出力 Debug.Print sDeq '// 3を出力 Debug.Print q.Count End Sub |
サンプルコードにはSystem.Collections.Queueクラスのデータを入れるEnqueueメソッド、取り出すDequeueメソッド、データが含まれているか確認するContainsメソッド、最終データを取得し削除はしないPeekメソッド、の4つを使っています。
変数宣言の2行目と3行目はどちらでもいいです。同様に7行目と8行目もどちらでもいいです。
サンプルに書いた他にもQueueクラスにはプロパティやメソッドが用意されていますが、全てが使えるかどうかまでは確認していないため、必要なプロパティやメソッドがある場合は色々試してみてください。
ちなみにfor eachやwhileで使えるかどうかを試してみようと反復列挙子を取得するGetEnumerator()メソッドを試してみましたが、取得までは出来たのですがそのあとの利用ができませんでした。書き方の問題かもしれません。