0

vbaでモジュールを作成しました。「AddDropDowns」と「RemoveDropDowns」の 2 つの関数があります。最初の関数では、後で2番目の関数でアクセスできる変数に値を保存したいと思います。これら 2 つの関数が含まれているのと同じモジュールで「DropDownsCounter」という変数を宣言しましたが、変数は関数呼び出し間でその値を保持しません。私の質問は、なぜ、どのようにこれを達成するのですか? このモジュールのコードは以下です。

    Option Explicit    
        Private DropDownsCounter As Integer
        Public Const QueryAttributes = "Query1:Query2:Query3:Query4:Query5"

        Private Const DropDownsWidth = 70
        Private Const DropDownsHeight = 16.5    
        Function AddDropDowns()
            DropDownsCounter = DropDownsCounter + 1
            Dim QueryAttributesArray() As String
            Dim NumberOfDropDowns As Integer
            QueryAttributesArray() = Split(QueryAttributes, ":")
            Application.ScreenUpdating = False
            Dim x As Integer
            For x = 0 To UBound(QueryAttributesArray)
                Dim Name As String
                Name = "DropDown_" & (NumberOfDropDowns + x)
                Dim CmbBox As OLEObject
                Set CmbBox = Worksheets("Poizvedba").OLEObjects.Add("Forms.ComboBox.1")
                With CmbBox
                    .Left = GetLastDropDownLeftPos(DN)
                    .Top = Range(DNStartCell).Top + x * DropDownsHeight
                    .Width = DropDownsWidth
                    .Height = DropDownsHeight
                    .Name = Name
                End With
            Next x
            Application.ScreenUpdating = True
            End Function

    Function RemoveDropDowns()
        Dim QueryAttributesArray() As String
        Dim LastDropDown As Integer
        DropDownsCounter = DropDownsCounter - 9
        QueryAttributesArray() = Split(QueryAttributes, ":")
        Dim OleObj As OLEObject
        For Each OleObj In Worksheets("Poizvedba").OLEObjects
            Dim SplittedObjectName() As String
            SplittedObjectName() = Split(OleObj.Name, "_")
            If SplittedObjectName(0) = "DropDown" Then
                LastDropDown = SplittedObjectName(1)
            End If
        Next OleObj
        Dim StartIndexToRemove As Integer
        Dim EndIndexToRemove As Integer
        StartIndexToRemove = LastDropDown - UBound(QueryAttributesArray)
        EndIndexToRemove = LastDropDown
        Dim Sh As OLEObject
        For Each Sh In Worksheets("Poizvedba").OLEObjects
            Dim x As Integer
            For x = StartIndexToRemove To EndIndexToRemove
                If Sh.Name = "DropDown_" & x Then
                    Sh.Delete
                Exit For
                End If
            Next x
        Next Sh
    End Function

Private Function GetLastDropDownLeftPos(ByVal DropDownCategory As String) As Integer
    Dim pos As Integer
    pos = Range("A4").Width + Range("B4").Width + DropDownsWidth * DropDownsCounter
    GetLastDropDownLeftPos = pos
End Function

まだ変数値を失う新しいコード

ワークシート コード:

Public QueryDropDownsCollection As New Collection

Public Sub CommandButton1_Click()
    Dim NewQuery As QueryDropDown
    Set NewQuery = New QueryDropDown
    QueryDropDownsCollection.Add NewQuery
    Call NewQuery.Initialize(1, 20, 20, 70, 17, 9)
    NewQuery.AddDropDowns
End Sub

Public Sub CommandButton2_Click()
    QueryDropDownsCollection(QueryDropDownsCollection.Count - 1).RemoveDropDowns
End Sub

クラスコード:

Private pID As Integer
Private pDropDownsWidth As Integer
Private pDropDownsHeight As Integer
Private pLeftPos As Integer
Private pTopPos As Integer
Private pNumberOfDropDowns As Integer
Private pDropDownNames() As String

Property Get ID() As Integer
    ID = pID
End Property

Private Const DropDownsWidth = 70
Private Const DropDownsHeight = 16.5

Public Sub Initialize(ByVal ID As Integer, ByVal LeftPos As Integer, ByVal TopPos As Integer, ByVal DropDownsWidth As Integer, ByVal DropDownsHeight As Integer, ByVal NumberOfDropDowns As Integer)
    pID = ID
    pLeftPos = LeftPos
    pTopPos = TopPos
    pDropDownsWidth = DropDownsWidth
    pDropDownsHeight = DropDownsHeight
    pNumberOfDropDowns = NumberOfDropDowns
    pSheet = Sheet
End Sub

Function AddDropDowns()
    For x = 0 To (pNumberOfDropDowns - 1)
        Dim Name As String
        Name = "DropDown_" & pID & "_" & x
        ReDim Preserve pDropDownNames(0 To x)
        pDropDownNames(x) = Name
        With ActiveSheet.OLEObjects.Add("Forms.ComboBox.1")
            .Left = LeftPos
            .Top = pTopPos + x * pDropDownsHeight
            .Width = pDropDownsWidth
            .Height = pDropDownsHeight
            .Name = Name
            With .Object
                .AddItem "Krneki1"
            End With
        End With
    Next x
End Function

Function RemoveDropDowns()
    Dim Sh As OLEObject
    For Each Sh In ActiveSheet.OLEObjects
        Dim x As Integer
        For x = 0 To pNumberOfDropDowns
            If Sh.Name = pDropDownNames(x) Then
                Sh.Delete
            Exit For
            End If
        Next x
    Next Sh
End Function
4

3 に答える 3

0

関数呼び出し間でグローバル変数を保持することの問題は、OLEObjects をワークシートに動的に追加することにあります。OLEObject が VBA コードから Worksheet に追加されると、OLEObject 自体がプロジェクトのプロパティになるため、プロジェクトを再コンパイルする必要があります。再コンパイルのプロセスでは、すべての変数値が失われます。私も見つけたこの問題へのいくつかの参照:

http://www.pcreview.co.uk/forums/dynamically-adding-activex-controls-via-vba-kills-global-vba-heap-t3763287p2.html

http://www.experts-exchange.com/Software/Office_Productivity/Office_Suites/MS_Office/Excel/Q_23574623.html

于 2013-10-22T18:39:08.567 に答える
0

変数 DropDownsCounter は、AddDropDowns() の呼び出しごとにインクリメントする必要があります。これは GetLastDropDownLeftPos() でのみ使用され、RemoveDropDowns() では使用されません。

AddDropDowns() では、変数 NumberOfDropDowns はローカル変数です。RemoveDropDowns() では、変数 NumberOfDropDowns は暗黙的にグローバル変数です。

NumberOfDropDowns と DropDownsCounter 変数を混同していませんか?

すべての VBA コードで、モジュールのヘッダーを追加して、変数を明示的に宣言する必要があります。

Option Explicit

これにより、デバッグ用のコードのコンパイル エラーが発生します。

于 2013-10-19T19:56:45.340 に答える
0

ドロップダウンを管理するクラス モジュールを作成することをお勧めします。次に、通常のモジュールで Public の Module レベルの宣言を使用してインスタンス化できます。プロパティと内部変数は、プロジェクトが End ステートメントまたは VBE リセットによってリセットされるまで、呼び出し間で値を保持します。

于 2013-10-20T14:55:44.900 に答える