2011-02-02 26 views
5

Sto cercando di implementare una classe "Stack" in VBA per Excel. Voglio usare una struttura Last in First Out. Qualcuno ha mai incontrato questo problema prima? Sai librerie esterne struttura di movimentazione quali Catasta, Hastable, vettore ... (a parte la collezione originale di Excel, ecc ...)LIFO (Stack) Algorithm/Class per Excel VBA

Grazie

risposta

7

Ecco una semplice classe stack.

Option Explicit 
Dim pStack As Collection 
Public Function Pop() As Variant 
    With pStack 
     If .Count > 0 Then 
      Pop = .Item(.Count) 
      .Remove .Count 
     End If 
    End With 
End Function 
Public Function Push(newItem As Variant) As Variant 
    With pStack 
     .Add newItem 
     Push = .Item(.Count) 
    End With 

End Function 
Public Sub init() 
    Set pStack = New Collection 
End Sub 

test è

Option Explicit 
Sub test() 
    Dim cs As New cStack 
    Dim i As Long 
    Set cs = New cStack 
    With cs 
     .init 

     For i = 1 To 10 
      Debug.Print CStr(.Push(i)) 
     Next i 

     For i = 1 To 10 
      Debug.Print CStr(.Pop) 
     Next i 
    End With 
End Sub 

Bruce

+1

Benvenuti in StackOverflow! +1 per fornire un codice e mostrare quanto può essere semplice. Qualche avvertimento: 1) Usare '=' per restituire un valore nelle routine 'Push' e 'Pop' fallirà quando gli oggetti sono coinvolti a causa della fastidiosa sintassi VBA 'Set'. Vedere la fine di questa risposta: http://stackoverflow.com/questions/4716382/excel-select-case/4719706#4719706 2) Si tenga presente che l'indicizzazione in una raccolta è O (n) per volta. Vedi http://stackoverflow.com/questions/4827963/what-is-the-difference-between-the-time-complexity-of-th-two-ways-of-using-loo/4830157#4830157 – jtolle

1

non so di eventuali librerie VBA esterne per queste strutture. Per la mia procedura: stack di chiamate, uso solo un array globale e un puntatore di array con i metodi Push e Pop.

1

Bruce McKinney fornito il codice per una pila, List, e Vector in questo libro (era VB5(), ma che probabilmente non importa molto!):

http://www.amazon.com/Hardcore-Visual-Basic-Bruce-McKinney/dp/1572314222

(E 'fuori stampate, ma copie usate sono a buon mercato)

Il codice sorgente sembra essere disponibile qui:.

http://vb.mvps.org/hardweb/mckinney2a.htm#2

(Ca veat - Non ho mai usato nessuno dei suoi codici, ma so che è un esperto VB di lunga data e il suo libro è stato incluso su MSDN per molto tempo.)

Sono sicuro che ci sono anche molte diverse implementazioni per queste cose che fluttuano su Internet, ma non so se qualcuno di loro sia ampiamente utilizzato da chiunque tranne i loro autori.

Ovviamente, nessuna di queste cose è così difficile scrivere il proprio codice, dal momento che VBA supporta array ridimensionabili (la maggior parte del modo di un vettore) e fornisce una classe Collection incorporata (la maggior parte del modo di una lista). La risposta di Charles William per uno stack riguarda tutte le informazioni di cui hai bisogno. Basta fornire il proprio wrapper attorno a un array o a una Collection, ma il codice all'interno può essere relativamente banale.

Per una tabella hash, la MS Scripting Runtime include una classe Dictionary che in fondo è uno. Vedi:

Hash Table/Associative Array in VBA

+1

Tengo a precisare che il codice di McKinney non è abbastanza "banale". Fornisce anche lezioni di iteratore per le sue raccolte, ecc. – jtolle

+0

grazie mille, avrà un aspetto ad esso – BlackLabrador

0

È possibile utilizzare la classe di stack in System.Collections, come si può usare coda e altri. Basta cercare lo stack vb.net per la documentazione. Non ho provato tutti i metodi (ad esempio GetEnumerator - non so come usare un iteratore, se possibile in VBA). Utilizzando una pila o di una coda ti dà qualche bella benefici, di norma non così facile in VBA. È possibile utilizzare

anArray = myStack.ToArray 

EVEN se lo stack è vuoto (Restituisce un array di dimensioni da 0 a -1).

Utilizzando un collezioni personalizzate oggetto, esso funziona molto veloce grazie alla sua semplicità e può essere facilmente riscritto (per esempio per il trattamento esclusivo varibles fortemente tipizzati). Potresti voler fare un controllo per lo stack vuoto. Se si tenta di utilizzare pop su uno stack vuoto, VBA non gestirà con grazia, come tutti nulli-oggetti.Ho trovato più ragionevole da usare:

If myStack.Count > 0 Then 

dalla funzione utilizzando lo stack, invece di cottura in clsStack.Pop. Se lo inforni nella classe, una chiamata a Pop può restituire un valore di tipo prescelto - ovviamente puoi usarlo per gestire i valori vuoti, ma ottieni molto più dolore in quel modo.

Un esempio di utilizzo:

Private Sub TestStack() 
    Dim i as long 
    Dim myStack as clsStack 

    Set myStack = New clsStack 
    For i = 1 to 2 
     myStack.Push i 
    Next 

    For i = 1 to 3 
     If myStack.Count > 0 Then 
      Debug.Print myStack.Pop 
     Else 
      Debug.Print "Stack is empty" 
     End If 
    Next 

    Set myStack = Nothing 
End Sub 

Utilizzando un LIFO-stack può essere estremamente utile!

Classe clsStack

Dim pStack as Object 
Private Sub Class_Initialize() 
    set pStack = CreateObject("System.Collections.Stack") 
End Sub 
Public Function Push(Value as Variant) 
    pStack.Push Value 
End Function 
Public Function Pop() As Variant 
    Pop = pStack.Pop 
End Function 
Public Function Count() as long 
    Count = pstack.Count 
End Function 
Public Function ToArray() As Variant() 
    ToArray = pStack.ToArray() 
End Function 
Public Function GetHashCode() As Integer 
    GetHashCode = pStack.GetHashCode 
End Function 
Public Function Clear() 
    pStack.Clear 
End Function 
Private Sub Class_terminate() 
    If (Not pStack Is Nothing) Then 
     pStack.Clear 
    End If 
    Set pStack = Nothing 
End Sub