20. september 2006 - 15:04Der er
26 kommentarer og 2 løsninger
VBA: Udvælge hele rækker/søjler fra 2D arrays/matricer
Hej eksperter!
Jeg er havnet i den uheldige situation, at jeg skal programmere en makro i excel, som kan analysere nogle måledata - bl.a. udregne middelværdier.
Jeg har lavet en version, hvor udregningerne sker i et regneark i excel, men jeg er ikke tilfreds med hastigheden, så nu holder jeg mig udelukkene til arrays i VBA.
Jeg loader mine målinger ind i et array, Data, hvor der i 3.-6. søjle er nogle temperaturmålinger, som jeg gerne vil have en middelværdi af.
Mit spørgsmål er, om der ikke VBA er en indbygget funktion, der kan pille hele rækker eller søjler ud af Data, så jeg slipper for alle de forfærdelige for-loops?
Hvis det hjælper på forståelsen kan jeg sige, at jeg gerne vil have hvad der i Matlab ville være kodet som:
P.t. har jeg kun strikket noget sammen til at addere to matricer:
Function MatrixAdd(MatA() As Integer, MatB() As Integer, Result() As Integer) As Boolean ' Lægger to matricer med samme størrelse (og indeksering) sammen. 'On Error GoTo errhandler
Dim Row1() As Variant, Row2() As Variant, tmpRow1() As Variant, tmpRow2() As Variant Dim i As Integer, j As Integer Dim rows As Integer, cols As Integer
' Verificerer, at matricerne har samme dimension (og samme indeksering). If (UBound(MatA(), 1) <> UBound(MatB(), 1)) Or _ (LBound(MatA(), 2) <> LBound(MatB(), 2)) Or _ (UBound(MatA(), 2) <> UBound(MatB(), 2)) Or _ (LBound(MatA(), 2) <> LBound(MatB(), 2)) Then GoTo errhandler
rows = UBound(MatA(), 1) - LBound(MatA(), 1) cols = UBound(MatA(), 2) - LBound(MatA(), 2) ' Dimensionen på matricerne, der adderes
ReDim Row1(0 To 0, cols) ReDim Row2(0 To 0, cols)
ReDim Result(rows, cols) For i = 0 To rows For j = 0 To cols Result(i, j) = MatA(i, j) + MatB(i, j) Next j Next i
MatrixAdd = True Exit Function
' Fejlrapportering errhandler: MatrixAdd = False MsgBox "Der opstod en fejl mens programmet prøvede at addere to matricer. " & vbCrLf _ & "Deres indices var hhv. (" _ & LBound(MatA(), 1) & " til " & UBound(MatA(), 1) _ & " , " _ & LBound(MatA(), 2) & " til " & UBound(MatA(), 2) _ & ") og (" _ & LBound(MatB(), 1) & " til " & UBound(MatB(), 1) _ & " , " _ & LBound(MatB(), 2) & " til " & UBound(MatB(), 2) _ & ")."
End Function
Da jeg gik i gang med at arbejde på den med vektorerne/søjlerne kom jeg til en masse overvejelser om fejlsikring - hvilket jeg ikke vil til at bruge tid på at udarbejde. Så der ikke er nogle brugbare indbyggede funktioner tror jeg, jeg dropper vba - for aldrig at vende tilbage :-)
Som det fremgår kan rutinen til addition af matricer kun lægge to matricer sammen, hvis de ud over samme størrelse også bruger samme indeksering (i.e. fra 0 til max i både rækker og søjler).
Grunden til, jeg ikke har gjort det bedre er, at det med al forventining kun er mig selv, der skal kalde rutinen, så jeg ved, hvordan jeg undgår fejlene.
Private Sub Worksheet_Change(ByVal Target As Range) If ActiveCell.Column = 3 Or ActiveCell.Column = 4 Or ActiveCell.Column = 5 Or ActiveCell.Column = 6 Then Dim Nederste As Long, I As Long Application.EnableEvents = False Nederste = Range("C63536").End(xlUp).Row Dim MitArray() ReDim ResultArray(Nederste) MitArray = Range("C1:F" & Nederste) For I = 1 To UBound(MitArray) ResultArray(I) = Application.WorksheetFunction.Average(MitArray(I, 1), MitArray(I, 2), MitArray(I, 3), MitArray(I, 4)) Next Range("G1:G" & Nederste) = Application.WorksheetFunction.Transpose(ResultArray) Application.EnableEvents = True End If End Sub
akyhne: Nu har jeg ikke lige tid til at teste koden nu her, men umiddelbart synes jeg, det ser ud til, det foregår i et regneark, hvilket jeg jo vil undgå.
Jo jo, det var skam en Excel Makro, jeg har brug for, men som jeg skriver:
"Jeg har lavet en version, hvor udregningerne sker i et regneark i excel, men jeg er ikke tilfreds med hastigheden, så nu holder jeg mig udelukkene til arrays i VBA."
Komplet citat med stavefejl og det hele, kan jeg se...
Måske det ikke er så tydeligt, som jeg trode, men pointen er, at manipulation af data, der allerde er skrevet ind i cellerne på regnearket er noget skidt - der er simpelt hen så mange data, at det kører af lo**.... knap så godt. Så derfor har jeg valgt den anden metode, og nøjes med at skrive alle data ud på regnearket til allersidst, når de ikke behøver yderligere manipulation.
Ideelt set havde jeg aldrig lavet det i excel, men det er ikke kun op til mig at beslutte.
Jeg har faktisk fået lavet et work-around, men jeg har ladet spørgsmålet stå, for jeg vil stadig gerne se, om der var nogen, der kendte til regulære "matrix/vektor-operation"s-funktioner i VBA.
Nåh. Ja så kan jeg bedre forstå det. Havde slet ikke tænkt på det i de baner - i min makro skal brugeren ikke redigere i regnearket, men kun udvælge en csv-fil, som så bliver behandlet (i VBA arrays) for til sidst at blive præsenteret i færdig form på regnearket.
Ud fra den devise sad jeg og prøvede at kalde funktionen med en range som input.
Nej, ikke ved at ændre i en celle. Fejlen kom fordi jeg ikke kunne se ud over min egen næsetip og prøvede at kalde funktionen fra en anden makro (fordi det er sådan, jeg har strikket tingene sammen).
Altså din eksempelfil virker fint - måske lige med den undtagelse, at gennemsnittet af en række står i den følgende række. Men jeg har stadig ikke kunnet finde nogen indbyggede procedurer til "matrix-algebraen" med additionen af søjler.
Jeg kører jo som sagt databehandlingen i VBA-array regi og ikke på selve regnearket. Med de indbyggede procedurer til "matrix-algebraen" mener jeg specifikke VBA-kommandoer, der kan addere vektorer/matrix-søjler, så jeg ikke skal definere løkker kørende fra Lbound til Ubound igen og igen hver gang jeg skal lave udregninger.
Det må være store mængder data du arbejder med, hvis du synes det går for langsomt. Måske du skulle oprette et nyt spm med dine sidste problemer, for jeg er ikke sikker på jeg forstår hvad du mener. Det vil give dig mere respons.
Ja, det er meget store mængder data, der skal behandles. Og problemet er, at det foregår på outdatede computere, så koden skal optimeres efter alle kunstens regler.
Jeg tror dog, jeg lader spørgsmålet stå et par dage endnu - det er jo aldrig til at vide, om der kommer nogen forbi, der har ledt efter netop de samme funktioner som jeg.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.