2013-09-27 9 views
6

Ho problemi a gestire alcuni array in VBA, o più specificamente sto avendo problemi a cercare di utilizzare in modo efficiente alcune subroutine/metodi esistenti per lavorare su array di vario formati/dimensioni.Modifica la funzione esistente per gestire matrici di varie dimensioni/struttura

Gli array vengono recuperati da un oggetto COM e mentre arrivano in una struttura prevedibile e coerente in base alla quale la routine restituisce l'array (s), we have had trouble getting all of the functions to return the data in the same structure.

Quindi, mi occupo di strutture variabili, a volte un array 2D, ma a volte un array 1D in cui ogni elemento dell'array è una variante/matrice. Ad esempio, se ho una funzione esistente che prevede una struttura 2D come arr(0,0), devo modificarla per accettare anche un array 1D, in cui ogni elemento è di tipo Variant (strutturato come arr(0)(0))

Quello che sto facendo attualmente

a disattivare gli errori, e testare l'Ubound della seconda dimensione, sapendo che solleverà un errore se si tratta di una matrice 1D. Posso quindi eseguire un'iterazione leggermente diversa in base alla struttura dell'array.

  • odio usando On Error Resume Next se posso evitarlo, ma sembra come quella può essere la più efficiente in questo caso.

  • Inoltre non mi piace fare affidamento su Excel.Application.Transpose ma non su trovare alcun metodo che possa farlo in modo nativo in PowerPoint.

Esempio:

Function GetSmallFromBar(counts As Variant, banner As Variant, categories As Variant) As Variant 
Dim small As Object 
Dim arrSizeErr As Variant 
Dim i As Long 
Set small = CreateObject("Scripting.Dictionary") 

On Error Resume Next 
arrSizeErr = UBound(counts, 2) 
arrSizeErr = (Err.Number <> 0) 
Err.Clear 
On Error GoTo 0 

'Array is structured like arr(0)(0) instead of arr(0,1) 
If arrSizeErr Then 
    counts = Excel.Application.Transpose(counts) 
    ReDim Preserve counts(0 To UBound(counts) - 1) 
    'Modify for unique array structure 
    For i = LBound(categories) To UBound(categories) 
     If counts(i) < 100 Then 
      small(i) = categories(i) 
     End If 
    Next 
    GoTo EarlyExit 
End If 

'This works for the expected array structure, arr(0,0) 
For i = LBound(categories) To UBound(categories) 
    If counts(i, 0) < 100 Then 
     small(i) = categories(i) 
    End If 
Next 
EarlyExit: 
GetSmallFromBar = small.Items() 

Set small = Nothing 
End Function 

Nota: I ReDim matrice perché ho bisogno di lavorare con array 0-base.

Ci sono probabilmente una mezza dozzina di posti nel mio codice in cui mi imbatto in qualcosa di simile, e ognuno si basa su un metodo simile ma probabilmente non identico.

Sto cercando di sistemare il mio codice altrove, mi stavo chiedendo se questo è un buon approccio che posso quindi standardizzare come una funzione e chiamare da altri moduli dove questo è un potenziale errore, o se c'è un altro modo di fai questo in modo più efficiente.

Ulteriori informazioni e screenshot

sto lavorando esclusivamente con 1 e 2-d array. Ma a volte ottengo un array 1D in cui ogni elemento è anche un tipo Variant. Questo mi dà le convinzioni perché spero di poter modificare alcune delle funzioni e dei metodi che uso su un array 2d per lavorare sulla struttura "array of array".

Previsto 2D-Array

enter image description here

problematico matrice di varianti

enter image description here

+0

Un approccio potrebbe essere quello di avvolgere la chiamata dell'oggetto COM in una routine VBA che standardizza l'output in un formato particolare (un array 2d o un array di matrici) in modo che tutto il tuo altro codice sappia esattamente quale formato aspettarsi. –

+1

È anche possibile utilizzare 'application.choose (array (1), v)' per convertire una variante 'v' (range, array, array di array 1D) in un array 2D (basato su 1). Questo potrebbe essere usato per standardizzare i formati prima di aggiungere al dizionario. –

+0

@lori_m funziona in PPT? (Non sono in grado di testare adesso ...) Non ho visto il metodo '.choose' prima. Sembra forse quello di cui ho bisogno. –

risposta

1

Finché il codice funziona attualmente penso che sia bene. Se possibile, si consiglia di includere alcune delle funzioni della subroutine nelle proprie funzioni in modo che siano riutilizzabili.

Chip Pearson ha una funzione disponibile sul suo sito matrice che vi darà il numero di dimensioni della matrice, che è quindi possibile utilizzare per determinare che cosa dovete fare:

Public Function NumberOfArrayDimensions(Arr As Variant) As Integer 
Dim Ndx As Integer 
Dim Res As Integer 
On Error Resume Next 
    Do 
     Ndx = Ndx + 1 
     Res = UBound(Arr, Ndx) 
    Loop Until Err.Number <> 0 
NumberOfArrayDimensions = Ndx - 1 
End Function 

Fonte: Chip Pearson, VBA Arrays

+0

Questo dovrebbe aiutare. Uso già alcune delle sue funzioni di array e sebbene ne conoscessi questa per qualunque ragione non l'ho usato, il che a ben vedere mi sembra sciocco. –