Avatar billede bone Nybegynder
20. september 2006 - 15:04 Der 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:

Middel = (Data(:,3)+Data(:,4)+Data(:,5)+Data(:,6))/4.
Avatar billede gider_ikke_mere Nybegynder
20. september 2006 - 15:24 #1
Hvad har du af kode?
Avatar billede bone Nybegynder
20. september 2006 - 15:28 #2
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 :-)
Avatar billede bone Nybegynder
20. september 2006 - 15:30 #3
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.
Avatar billede gider_ikke_mere Nybegynder
20. september 2006 - 16:58 #4
Skal du ikke bare have gennemsnittet af C1, D1, E1 og F1 i en ny celle, eksempelvis G1? Og så for hele arket nedad?
Avatar billede gider_ikke_mere Nybegynder
20. september 2006 - 18:13 #5
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
Avatar billede bone Nybegynder
21. september 2006 - 12:52 #6
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å.
Avatar billede gider_ikke_mere Nybegynder
21. september 2006 - 13:49 #7
Det har jeg så misforstået. Du skrev at du skulle have lavet en Excelmakro.
Avatar billede gider_ikke_mere Nybegynder
01. oktober 2006 - 01:04 #8
?? Eller?
Avatar billede bone Nybegynder
11. oktober 2006 - 08:49 #9
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.
Avatar billede gider_ikke_mere Nybegynder
11. oktober 2006 - 10:34 #10
Jamen har du testet min kode?
Avatar billede bone Nybegynder
12. oktober 2006 - 14:51 #11
Jeg har prøvet at køre en et par gange med nogle tilfældige tal, men den lavede fejl.
Avatar billede gider_ikke_mere Nybegynder
12. oktober 2006 - 15:31 #12
Hvor melder den fejl?
Avatar billede gider_ikke_mere Nybegynder
12. oktober 2006 - 16:39 #13
Har lige testet med 30.000 rækker - skæve værdier i C til F, altså 120.000 tal. Det tager under 1 sekund på en AMD2500+. Er det ikke hurtigt nok?
Avatar billede gider_ikke_mere Nybegynder
12. oktober 2006 - 16:42 #14
Avatar billede bone Nybegynder
13. oktober 2006 - 10:44 #15
Jeg kan stadig ikke få den til at virke. Hvad giver du funktionen som input?
Avatar billede gider_ikke_mere Nybegynder
13. oktober 2006 - 16:01 #16
At du ændrer noget i arket. Hvad fejl får du?
Avatar billede bone Nybegynder
16. oktober 2006 - 13:40 #17
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.
Avatar billede gider_ikke_mere Nybegynder
16. oktober 2006 - 21:41 #18
Får du fejl, når du ændrer en celle. Det burde du i hvertfald ikke.
Avatar billede gider_ikke_mere Nybegynder
22. oktober 2006 - 22:49 #19
?
Avatar billede bone Nybegynder
24. oktober 2006 - 08:33 #20
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).
Avatar billede gider_ikke_mere Nybegynder
24. oktober 2006 - 17:37 #21
Så det virker nu?
Avatar billede bone Nybegynder
25. oktober 2006 - 08:44 #22
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.
Avatar billede gider_ikke_mere Nybegynder
25. oktober 2006 - 17:27 #23
Hvordan vil du så have resultatet? Hvad mener du med "indbyggede procedurer til "matrix-algebraen" med additionen af søjler"?
Avatar billede bone Nybegynder
27. oktober 2006 - 11:22 #24
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.
Avatar billede gider_ikke_mere Nybegynder
30. oktober 2006 - 22:08 #25
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.
Avatar billede bone Nybegynder
31. oktober 2006 - 09:15 #26
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.
Avatar billede bone Nybegynder
09. november 2006 - 09:05 #27
Lukker.

akyhne: Du får ½ af pointsne som tak for forsøget.
Avatar billede gider_ikke_mere Nybegynder
09. november 2006 - 16:40 #28
Takker.
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester