Avatar billede ExcelJ95 Seniormester
16. maj 2019 - 09:04 Der er 21 kommentarer og
1 løsning

VBA Kan man skrive en FOR som tjekker vandret og ikke lodret?

Hej.

Kan man laver en "for" der kører vandret og leder efter en værdi på tværs af kolonner og ikke ned af på tværs af rækker?

Noget i stil med:

For X = A to Z
Var1 = range("1" & X).value

If Var1 > 0 then
Msgbox "Der er en værdi i celle: " Var1
End if
Next X

Pft.
16. maj 2019 - 09:17 #1
Kolonner er har også bare et tal... A=1, B=2 osv...

Sub exp_1009017()
    Dim lCol As Long
   
    For lCol = 1 To 28
        If Cells(1, lCol).Value <> "" Then
            MsgBox "Cellen " & Cells(1, lCol).Address & " har værdien " & Cells(1, lCol).Value
        End If
    Next lCol
End Sub
Avatar billede ExcelJ95 Seniormester
16. maj 2019 - 10:07 #2
Min konkrete problem er at jeg skal finde en værdi ud fra et bestemt kundenavn.

Dvs. jeg kører først en "for" for at finde et kundenavn, og så derefter skal jeg gå ud af rækken og finde en værdi.
Umiddelbart kan jeg ikke se hvad jeg gør forkert, men jeg for ingen respons fra excel når jeg kører den.
Min kode:

Sub find()
kundenavn = Range("m2").Value
For X = 23 To 70
    Kunde = Range("a" & X).Value
        For Y = 2 To 10
                If kundenavn = Kunde And Cells(23, Y).Value <> "" Then
                    MsgBox "Værdien er: " & Cells(23, Y).Value
                    Exit For
                End If
        Next Y
        Exit For
Next X
End Sub
Avatar billede ExcelJ95 Seniormester
16. maj 2019 - 10:09 #3
23 i mit x er den række hvor mine liste over kundenavne starter.
Avatar billede Jan K Ekspert
16. maj 2019 - 10:34 #4
Test du ikke altid for en blank værdi i række 23 uanset, hvor kunden står?
Avatar billede ExcelJ95 Seniormester
16. maj 2019 - 10:38 #5
hmm.. Jo måske.

Men hvis jeg skriver den om så jeg først tjekker at kundenavnet står i kolonne A, og så leder på tværs af kolonner, sker der stadig ingen ting:


Sub find()
Kundenavn = Range("m2").Value
For X = 23 To 70
    Kunde = Range("a" & X).Value
      If Kunde = Kundenavn Then
   
        For Y = 2 To 10
                If Kundenavn = Kunde And Cells(23, Y).Value <> "" Then
                    MsgBox "Værdien er: " & Cells(23, Y).Value
                    Exit For
                End If
        Next Y
        Exit For
        End If
Next X
End Sub
Avatar billede Dan Elgaard Ekspert
16. maj 2019 - 10:46 #6
Der, hvor du har '23':

If Kundenavn = Kunde And Cells(23, Y).Value <> "" Then MsgBox "Værdien er: " & Cells(23, Y).Value

...skal du skrive 'X':

If Kundenavn = Kunde And Cells(x, Y).Value <> "" Then MsgBox "Værdien er: " & Cells(x, Y).Value
Avatar billede ExcelJ95 Seniormester
16. maj 2019 - 11:56 #7
Jeg ved ikke hvorfor, men det fungerer heller ikke at placere X på 23's plads:

Sub find()
Kundenavn = Range("m2").Value
For X = 23 To 70
    Kunde = Range("a" & X).Value
   
   
        For Y = 2 To 10
                If Kundenavn = Kunde And Cells(X, Y).Value <> "" Then
                    MsgBox "Værdien er: " & Cells(X, Y).Value
                    Exit For
                End If
        Next Y
        Exit For
       
Next X
End Sub
Avatar billede Jan K Ekspert
16. maj 2019 - 13:25 #8
Din nr. 2 Exit For betyder at den går ud af den ydre løkke allerede efter første gennemløb, så hvis ikke kunden står i række 23, sker der ikke mere.
Avatar billede Jan K Ekspert
16. maj 2019 - 13:29 #9
Og den første Exit for betyder at også den første løkke kun køres en gang, s¨du finder kun den første værdi for kunden. Hvis du skal finde dem alle, skal du fjerne begge Exit For - eller flytte dem til et sted, hvor de ikke "gør skade" :-)
Avatar billede ExcelJ95 Seniormester
16. maj 2019 - 13:39 #10
Nu har jeg fjernet begge mine Exit for, og den kører nu ud af kolonnerne og giver mig værdier.

Men - den kører ikke ud fra den rigtige linje jf. Kundenavn.
Hvordan kan det være?

Sub find()

Kundenavn = Range("m2").Value

For X = 23 To 100
    Kunde = Range("a" & X).Value
 
   
        For Y = 2 To 733
                If Cells(X, Y).Value <> "" Then
                    MsgBox "Værdien er: " & Cells(X, Y).Value
                 
                End If
       
        Next Y
       
       
Next X
End Sub
Avatar billede Jan K Ekspert
16. maj 2019 - 13:52 #11
Måske fordi du ikke sammligner Kundenavnet i M2 med det kundenavn der står i "A"&x

Prøv med

Sub find()

kundenavn = Range("m2").Value
Debug.Print kundenavn
For X = 23 To 100
    kunde = Range("a" & X).Value
    If kundenavn = kunde Then
        For Y = 2 To 733
              If Cells(X, Y).Value <> "" Then
                  MsgBox "Værdien er: " & Cells(X, Y).Value
              End If
        Next Y
      End If
Next X
End Sub
Avatar billede ExcelJ95 Seniormester
16. maj 2019 - 14:19 #12
Hvad gør debug.print Kundenavn?
Avatar billede Dan Elgaard Ekspert
16. maj 2019 - 14:23 #13
Må jeg ikke komme med et alternativt forslag:

Dim Celle As Excel.Range
For Each Celle In Range("B23:J70").Cells
    If Celle.Value = Range("M2").Value Then
        MsgBox "Kunden " & Range("M2").Value & " findes i række " & Celle.Row & "og kolonne " & Celle.Column
        Exit For
    End If
Next
Avatar billede Jan Hansen Ekspert
16. maj 2019 - 14:49 #14
Mit bidrag er

Option Explicit

Sub FindKundeData()
Dim rKunde As Range, rData As Range, rCell As Range

Set rKunde = Range("A23")
Set rKunde = Range(rKunde, rKunde.Offset(500, 0).End(xlUp))
    For Each rCell In rKunde
        If rCell.Value = Range("M2").Value Then Set rData = Range(rCell.Offset(0, 1), rCell.Offset(0, 25))
    Next
    For Each rCell In rData
        If rCell.Value <> "" Then MsgBox rCell.Value
    Next

End Sub

Jan
Avatar billede Dan Elgaard Ekspert
16. maj 2019 - 14:58 #15
#14: Altid huske, aldrig glemme... ...Ungarnsk notation er af det slemme :-)

Men, ja, ellers er du inde på det samme som jeg: 'For...Each' og ikke 'For...To'

Hvordan man så laver afgrænsningen og sammenligningen kan så være en smagssag, men lad ExcelJ95 selv bestemme, hvad han foretrækker.
16. maj 2019 - 15:06 #16
For Each - auch, det er en af de langsomme - helst ikk, helst aldrig
Endnu værre at vi alle læser i cellerne - mega sløvt

Definer området - indlæs i et variant array, og kør en For-To på array'et
Avatar billede Dan Elgaard Ekspert
16. maj 2019 - 15:15 #17
#16: 'For...Each' er _MEGET_ hurtigere end 'For...To'

http://www.EXCELGAARD.dk/Lib/Macros/GPP/Loops/

Og, vi løber netop ikke flere celler i gennem, end OP allerede gør, hvis du læser vores koder - vi stopper netop, når vi finder kunden.
16. maj 2019 - 15:17 #18
Denne her er ikke testet, og jeg gør det heller ikke (så der kan være fejl), men princippet er at data læses ind i hukommelsen, og løbes igennem derinde og du får en liste over alle celler, hvor kundenummeret findes.
Denne kode er i princippet ligeglad med om der er 100 eller 100.000 celler - den er bare pisse hurtig - why? bla. fordi de kun spørges til celle værdier 2 gange

Sub FindKundeData()
    Dim rKunde As Range, lRow As Long, lCol As Long, sKundeNavn As String
    Dim aKunde As Variant, cKunde As New Collection, sResult As String

    Set rKunde = Range("A23")
    Set rKunde = Range(rKunde, rKunde.Offset(50000, 0).End(xlUp))
    aKunde = rKunde.Value
    sKundeNavn = Range("M2").Value

    For lCol = LBound(aKunde, 2) To LBound(aKunde, 2)
        For lRow = LBound(aKunde, 1) To LBound(aKunde, 1)
            If aKunde(lRow, lCol).Value = sKundeNavn Then
                cKunde.Add "Celle(" & lRow & "," & lCol & "): " & aKunde(lRow, lCol).Value
            End If
        Next lRow
    Next lCol

    If cKunde.Count > 0 Then
        For lRow = 1 To cKunde.Count
            sResult = sResult & cKunde(lRow) & vbCrLf
        Next lRow
    End If
End Sub
16. maj 2019 - 15:25 #19
Min erfraing fra modeller med 1,5 mill.+ records har skabt Rule No 1 hos Smart Office: Aldrig For Each eller For To på Range/Cells
For each er langsom når det er på celler - faktisk er alt arbejde langsomt på celler, hvorfor et variant array er klart stjernen i range arbejde.

Prøv at leg med ovenstående eksempel - og ja sæt endelig et Exit ind i min kode også, gør dog ingen forskel for denne kode, når antal er så få...

Prøv at lave 50.000 rækker og skriv et kundenavn i række 40.000.... da mærker du forskellen og debug.print gerne start og slut tidspunkter
Avatar billede Dan Elgaard Ekspert
16. maj 2019 - 15:55 #20
#19: Det er ikke kun loops, der er langsomme på celler - ALT læsning til og fra celler skal undgås, hvis muligt - især, hvis man kommer over 1000 celler...

...men, her, hvor vi snakker omkring 400 celler, er din kode skudt langt over målet, og du vil næppe kunne måle en tidsmæssig forskel, set fra brugerens side af, og så kommer et andet princip ind i billedet, der ALTID skal have præcedens:

Læselighed og forståelighed.

Og, der vil jeg påstå, at min korte simple kode, langt overgår alle andre forslag i denne tråd :-)
16. maj 2019 - 16:11 #21
#20 Til formålet her er det ligegyldigt hvilken der vælges, men til #17 om at hastighed, så er det ikke lige gyldigt
Langt overgår hihi - godt med lidt selvtillid - god weekend
Avatar billede Dan Elgaard Ekspert
16. maj 2019 - 16:49 #22
Det er ikke noget med selvtillid at gøre - det er simpel læsning.

Læser jeg din kode, og min kode, så er min kode langt kortere, mere overskueligt, nemmere, at forstå, og mere læsevenlig.

Simple as that :-)

Min kode fylder 7 korte, simple linjer, mens din kode fylder 18 lange, komplicerede linjer - som endda er gjort mere uoverskuelige og fejlmulige med ungarnsk notation !

Men, lad høre, hvilken version ExcelJ95 vælger, at benytte?
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

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





CIO
Sådan tager top-CIO Pernille Geneser livtag med 40 år gamle it-systemer i Stark Group med 10.000 medarbejdere