2017-06-22 5 views
1

私は空港のコレクションを作成したいと思います。VBAクラスモジュールのコレクションを正しく操作するにはどうすればよいですか?

空港は多くのパラメータがありますが、簡単のために、のは空港のクラスは空港クラスモジュールに次のように定義されていると仮定してみましょう:

'Class Airport 
Public name As String ' Stores name of the airport 
Public flights As Long ' Stores number of flights in that airport 

その後、私のモジュールはかなり大きいですが、これはどこの部分であります私は、重複したものを削除し、空港のコレクション内のExcelファイルとストア値から列を読む:

Dim airports As Collection 
Set airports = New Collection 

'Putting airports in collection 
       Dim c As Range 
       For Each c In wsToCheck.Range("D:D") 
       On Error Resume Next 
       Dim airport As New Airport 
       airport.name = c.Value 
       airports.Add airport, c.Value 
       On Error GoTo 0 
       Next 

私は真ん中

で行う場合

ます。Debug.Print airport.name

私は名前を得るが、私が行うとき

のDebug.Print空港(1)

何も印刷されません(ただし、さを.nameのエラーもない)。

以前は文字列のコレクションを使用していましたが、それは機能していました。しかし、空港ごとに複数の文字列が必要になります。

私のコードで何が間違っていますか?コレクションを使用していますか?

+0

Debug.Printのどの時点でコードを実行しましたか?このコードを実行すると、期待どおりに実行されました。 –

+0

私は空港のクラスも作っていますので、 'airports.AirPortExists'' getAirportRunways(strAiportCode)'と言うと、上記のコードがコンストラクト内に存在するか、 '.populateAiports(rng as excel.range)'と答えます –

答えて

2

コードに2つの問題があります。

最初は、反復処理している範囲がすべて列D(D:D)なので、おそらく数百万のアイテムでCollectionが作成されています。これは縛られる必要があります。

第2の問題は、変数名airportは、クラスAirportとまったく同じ名前です。これは簡単にVBAを混乱させる可能性があるため、そのうちの1つに別の名前を選択する必要があります。あなたのコード内で最大の問題に言及した@PeterT問題に加え

Option Explicit 

Sub test() 
    Dim wsToCheck As Worksheet 
    Set wsToCheck = ThisWorkbook.Sheets("Sheet1") 

    Dim airportNames As Range 
    Set airportNames = wsToCheck.Range("D1:D10") 

    Dim airports As Collection 
    Set airports = New Collection 

    'Putting airports in collection 
    Dim i As Long 
    Dim c As Range 
    For Each c In airportNames 
     Dim thisAirport As Airport 
     'Debug.Print c.Address & "=" & c.Value 
     Set thisAirport = New Airport 
     thisAirport.name = c.Value 
     thisAirport.flights = i 
     i = i + 1 
     airports.Add thisAirport 
    Next 

    'now print them out 
    For i = 1 To airports.Count 
     Debug.Print airports(i).name & ", " & airports(i).flights 
    Next i 

End Sub 
+0

これは働いています、ありがとう。しかし、私は各ファイルの空港の数、20-30000を知りません。私はD:Dでそれを続け、それはクラッシュしません。それはいくつかの問題につながるかもしれない? –

+1

一般的に、VBAを使用して、その列にある空港の数を判断する必要があります。最終的な行番号が範囲を設定するものであることを理解する必要があります。たとえば、 'Dim lastRow as Long'、' lastRow = wsToCheck.Range( "A"&wsToCheck.Rows.Count).End(xlUp) .Row' – PeterT

+0

これを実行すると、プログラムのスピードが大幅に向上しました。 2分以上20秒以下。素晴らしいアドバイス。 –

1

が新しいAirportオブジェクトが作成される方法です。ここで

は作品例です。私は実際にはオブジェクトが1つだけのオブジェクトがあるので、Airportオブジェクトをよく言います。

これは、空港変数の宣言方法(Dim airport As New Airport)が原因です。 1つのオブジェクトのみがここで作成された理由VBA-DocumentationDimへの声明の中で、我々は理由を見つけることができます。

Newキーワードは、オブジェクトの暗黙の作成を可能にします。オブジェクト変数を宣言するときにNew を使用すると、オブジェクトの新しいインスタンスは最初に参照時に作成された であるため、オブジェクト参照を割り当てるためにSet ステートメントを使用する必要はありません。

したがってDim Newは、変数airportが初めて使用されたときに新しいインスタンスが確実に作成されます。しかしそれはそれです。他のインスタンスは作成されません。最初のインスタンスのみが作成されます。各ループで、この1つのインスタンスだけが変更され、コレクションに追加されます。コレクションには、同じ空港オブジェクトへの参照が含まれています。

しかし、空港オブジェクトだけでなく、すべてのオブジェクトが必要です。したがってNewSetと一緒に使用する必要があります。ドキュメントは言う:

新をセットで使用されている場合、それはクラス


の新しいインスタンスを作成し、検討する次のコード(範囲D1:D3が含まれている値のAAAA、BBBB、 CCCC)

Dim airports As Collection 
Set airports = New Collection 
Dim c As Range 

For Each c In Worksheets(1).Range("D1:D3") 
    Dim Airport As New Airport 
    Airport.name = c.Value 
    airports.Add Airport 
Next 

Dim airports2 As Collection 
Set airports2 = New Collection 
Dim airport2 As Airport 
For Each c In Worksheets(1).Range("D1:D3") 
    Set airport2 = New Airport 
    airport2.name = c.Value 
    airports2.Add airport2 
Next 

Debug.Print "Airports:" 
For Each airport2 In airports 
    Debug.Print airport2.name 
Next 

Debug.Print vbNewLine 

Debug.Print "Airports2:" 
For Each airport2 In airports2 
    Debug.Print airport2.name 
Next 

出力

Airports: 
CCCC 
CCCC 
CCCC 


Airports2: 
AAAA 
BBBB 
CCCC 

This questionとほぼ同じ問題です。

関連する問題