2013-06-18 14 views
5

ho qualche codice che assomiglia a questo:per ogni proprietà di classe in Excel VBA

pos.Clutch = sh2.Cells(R, Clutch) 
pos.Wiper = sh2.Cells(R, Wiper) 
pos.Alternator = sh2.Cells(R, Alternator) 
pos.Compressor = sh2.Cells(R, Compressor) 
... 
pos.Telephone = sh2.Cells(R, Telephone) 
poss.Add pos 

poss è una raccolta, e frizione, Wiper ecc, sono indici di colonna (a partire da 1). Questo funziona attualmente ma è molto brutto. Sto cercando un modo per fare qualcosa di simile ...

Do While i <= classProperty.count 
    For each classProperty in pos 
     classProperty = sh2.Cells(R + 1, i) 
    Next classProperty 
Loop 

Ovviamente questo non avrebbe funzionato, ma qualcuno ha qualche consiglio su come rendere un metodo o di raccolta all'interno di una classe che avrebbe compiere o meno la stesso?

+0

Poiché gli indici partono da 1, può essere più ordinato di usare un sottoinsieme al posto di una classe in modo da poter loop su colonna indici con 'pos.add sh2.Cells (R, i)'. Quindi utilizzare l'indice Colonna per accedere al valore es. 'Pos (Clutch)'. –

risposta

4

non so di un buon modo. L'unica ragione per cui è brutto è perché non l'hai ancora nascosto in una classe. Prendi questa procedura

Sub Main() 

    Dim clsPos As CPos 
    Dim clsPoses As CPoses 

    Set clsPoses = New CPoses 
    Set clsPos = New CPos 

    clsPos.AddFromRange Sheet1.Range("A10:E10") 
    clsPoses.Add clsPos 

End Sub 

Niente di brutto. Ora il metodo AddFromRange è un po 'brutto, ma basta guardarlo quando lo scrivi o quando cambi i dati.

Public Sub AddFromRange(ByRef rRng As Range) 

    Dim vaValues As Variant 

    vaValues = rRng.Rows(1).Value 

    Me.Clutch = vaValues(1, 1) 
    Me.Wiper = vaValues(1, 2) 
    Me.Alternator = vaValues(1, 3) 
    Me.Compressor = vaValues(1, 4) 
    Me.Telephone = vaValues(1, 5) 

End Sub 

Aggiornamento: metodo alternativo per mangiare una matrice invece di un Range.

Public Sub AddFromArray(vaValues as Variant) 

    Me.Clutch = vaValues(1, 1) 
    Me.Wiper = vaValues(1, 2) 
    Me.Alternator = vaValues(1, 3) 
    Me.Compressor = vaValues(1, 4) 
    Me.Telephone = vaValues(1, 5) 

End Sub 
+0

Ci proverò anche io. L'installazione è più semplice di quanto suggerito da @CuberChase e l'aggiunta di nuove proprietà è ancora facile, una specie di. –

+0

Hm. @dickkusleika Ho cambiato il mio codice in modo che l'intero intervallo venga scaricato in un array. Come posso rendere .AddFromRange ancora valido con un array? –

+0

Vorrei creare un nuovo metodo per mangiare un array. Non sono un fan dei metodi multiuso. Vedi l'aggiornamento. –

0

Le classi VBA non consentono di definire un costruttore.

Nel modulo principale vorrei creare un "creatore":

For R = R1 To R2 
    pos.Add NewPos(Range("A" & R & ":E" & R) 
    Next R 

Function NewPos(R As Range) As classProperty 
    Set NewPos = New ClassProperty 
    NewPos.Init(R) 
Exit Function 

Nella classe:

Sub Init(R As Range) 
    Clutch = R.Cells(1, 1) 
    Wiper = R.Cells(1, 2) 
    ... 
End Sub 
4

Come altri hanno affermato, non esiste un modo diretto per scorrere le proprietà di un oggetto. Ho un foglio di calcolo che memorizza molti valori che ho bisogno di leggere in fase di esecuzione, simile al tuo. Il metodo migliore che ho trovato per farlo è utilizzando il metodo CallByName che consente di impostare o ottenere una proprietà tramite il nome .

Ora, alcuni potrebbero dire che la configurazione iniziale è eccessiva, ma spesso aggiungo e rimuovo queste proprietà, quindi fare lo stesso con il codice è ancora più problematico. Quindi la bellezza di questo metodo è che puoi modificare frequentemente il tuo numero di proprietà senza dover cambiare questo codice. È possibile utilizzare le funzioni impressionanti che fanno uso di CallByName da qui: https://stackoverflow.com/a/5707956/1733206

Poi per il tuo esempio, vorrei fare quanto segue nella mia collezione poss (notare che questo non fa alcun controllo degli errori, ecc, che come si può do):

Public Sub ReadInData() 
    Dim vInputs As Variant, ii As Integer, jj As Integer, cp As pos 
    Dim sPropertyName As String, vPropertyValue As Variant 

    'Raead in the data. I've set it from the activesheet, you can do it how you like 
    With ActiveSheet 
     vInputs = .Range(.Cells(1, 1), .Cells(.UsedRange.Rows.Count, .UsedRange.Columns.Count)).Value2 
    End With 

    'Look through the rows of data, one row per 'pos' object 
    For ii = LBound(vInputs, 1) + 1 To UBound(vInputs, 1) 

     'Set up your object 
     Set cp = New pos 

     'Loop through the columns of data eg Clutch, wiper, etc 
     For jj = LBound(vInputs, 2) To UBound(vInputs, 2) 
      'Put in seperate variables so its easy to see what's happening 
      sPropertyName = vInputs(1, jj) 
      vPropertyValue = vInputs(ii, jj) 

      'Use the callable method to set the property (from here: https://stackoverflow.com/a/5707956/1733206) 
      Call SetProperty(sPropertyName, vPropertyValue, cp) 
     Next jj 

     Me.Add cp 
     Set cp = Nothing 
    Next ii 
End Sub 

Ecco un esempio in una cartella di lavoro: https://dl.dropboxusercontent.com/u/13173101/VBAObject.xlsm

Edit: Dal momento che si stia cambiando l'oggetto spesso, ho incluso un altro modulo che è molto utile e sarà in realtà scrivere la classe pos per te in base alle intestazioni delle colonne nel tuo foglio di lavoro. Ciò significa che se aggiungi un'altra colonna, queste verranno aggiunte all'oggetto! Presuppone che tutte le proprietà siano stringhe ma è possibile modificarle.

+0

vedrò se questo funziona, dovrebbe. Anch'io devo aggiungere spesso nuove proprietà, quindi questa è una soluzione ideale. Grazie! –

+0

Felice è d'aiuto. Ho fatto una modifica leggermente fuori tema che sono abbastanza sicuro che vorrai controllare. – CuberChase

0

Potrebbe essere possibile utilizzare un codice come questo. Come è questo stampa fuori ogni procedura e proprietà pensiero:

Function getPropCount(ClassName As String) As String 
    Dim classes, Class 
    Dim i As Integer 
    Dim strClass As String 
    Dim propCount As Integer 

    For Each classes In Application.VBE.CodePanes 
     If classes.CodeModule.Name = ClassName Then 
     Set Class = classes 
     End If 
    Next 
    For i = 1 To Class.CodeModule.CountOfLines 
     If Class.CodeModule.ProcOfLine(i, 1) <> strClass Then 
     strClass = Class.CodeModule.ProcOfLine(i, 1) 
     Debug.Print strClass 
     propCount = propCount + 1 
     End If 
    Next 
    getPropCount = propCount 
End Function 

Buona fortuna, LC