Telefonszámunk: 1-472-0679

[Resolved] excel makro tömb és használata

Kezdőlap Fórumok Excel programozás [Resolved] excel makro tömb és használata

Topic Resolution: Resolved
6 bejegyzés megtekintése - 1-6 / 6
  • Szerző
    Bejegyzés
  • #4382
    karesz_k
    Felhasználó

      Sziasztok!
      A kérdésem egy picit összetett.
      -Az első hogyan tudom megoldani egy változónak (pl:tomb) hogy több értéket tároljon. Pl: sorok számát
      Folyamat 1 :elindul egy ciklus ami feltételt vizsgál, ha a feltétel teljesül el kellene tárolni a sor
      számát,ha ismét igaz a feltétel azt a sorszámot is tárolja el, tehát előre nem tudom megmondani hány eleme
      lesz a „tomb” változónak. Az első ciklus után futna egy második ami szintén a „tomb”-be tárolná a
      sorszámokat. Ha lement a két ciklus „tomb” a tömb elemei pl. a következők lennének: 6, 8, 25, 9, 17
      -A második kérdés/feladat. A „tomb” változó elemeit érték szerint csökkenő sorrendben felhasználni.
      pl: egy következő ciklushoz sor=”legnagyobb érték” jelen példában 25 vagyis sor=25
      a ciklus második körében sor=”2. legnagyobb érték” vagyis sor=17
      addig amíg el nem fogynak a tömb elemei, a példa szerint a ciklus utolsó futása a sor=6 és utána
      lépjen ki a ciklusból.
      Ha lehet ilyet akkor azt úgy kellene megoldania hogy ne kelljen cellába írnia a folyamatnak a „tomb”
      elemeit.
      A segítséget előre is Köszönöm!

      #4385
      horvimi
      Adminisztrátor

        Szia!

        Ez egy 1 dimenziós tömb.
        Amikor deklarálod, akkor dinamikus tömbként tedd.
        Dim sorszamok() as integer vagy long

        Amikor értéket akarsz bele tenni, akkor Redim kulcsszóval újradimenzionálhatod.
        Ha a már benne lévő elemeket meg akarod őrizni, akkor a Redim Preserve parancs kell.
        Összedobtam egy kis példát, ami az első 500 páros számot beírja egy dinamikus tömbbe While ciklussal.
        Külön változóban számolja (i), hogy hol tart a számolással, és külön változót növel akkor, ha párosat talál(tombszamlalo). A tömböt csak utóbbi esetben méretezi át, a végén kiírja a tömb méretét.

        Sub tomb_proba()
        Dim sorszamok() As Long
        Dim i As Integer
        Dim tombszamlalo As Integer
        
            i = 0
            tombszamlalo = 0
            Do While i <= 1000
               If i Mod 2 = 0 Then
                ReDim Preserve sorszamok(tombszamlalo)
                sorszamok(tombszamlalo) = i
                tombszamlalo = tombszamlalo + 1
               End If
               i = i + 1
            Loop
            MsgBox UBound(sorszamok)
        End Sub

        A tömb rendezése már érdekesebb, mert a tömbökön nincs natív SORT metódus a VBA-ban.
        Tehát vagy magadnak kell egy rendezést írni (nyilván csak keresni kell egyet a neten), vagy megpróbálod használni a .NET Core libet, azon belül az

        ArrayList konstrukciót.
        Erre leírást itt találsz:
        http://www.snb-vba.eu/VBA_Arraylist_en.html

        A bal oldali tartalomjegyzékben van rendezés témakör is.
        Ez egy szuper dolog.
        Ebben az esetben persze a fenti tömböt is ArrayList-ként kell megcsinálni, és az Add metódusal beletenni a sorszámokat.

        Végül egy felvetés:
        ha az egész algoritmust úgy csinálnád meg, hogy lentről lépkedjen felfelé, akkor a tömbbe eleve csökkenő sorrendben lennének a sorszámok nem?
        Bár ha a két ciklus egymás után ugyanazon a tartományon megy végig, akkor ugye egymás után lesznek rendezve.
        És ha csak egy ciklust csinálsz és vagy feltétellel nézel két dolgot?
        Vagy az első ciklus változtat valamit az adatokon?

        Imre

        • A hozzászólás módosításra került: 6 years, 9 months telt el-horvimi.
        • A hozzászólás módosításra került: 6 years, 9 months telt el-horvimi.
        • A hozzászólás módosításra került: 6 years, 9 months telt el-horvimi.
        #4392
        karesz_k
        Felhasználó

          Szia Imre!
          Köszönöm a segítséget!
          Mind a két ciklus .find és .find previous -t használ. Első körben for ciklussal kerestem soronkénti feltételvizsgálattal de a kb 800.000 soron nagyon lassú volt. Utána rátaláltam a .find metodusra ez sokkal gyorsabb, de ezzel nem tudom hogy lehet-e és ha igen hogyan két elemet keresni egyszerre. Most ugy megy hogy az első ciklus C és D oszlopban megkeresi név1-et ha talál és a C oszlopban van megnézi D oszlopban hogy név2 van-e, ha igen megjegyzi a sorszámot. Ezután fut a második ami név2 keres ugyan így csak a C oszlopban vizsgálja név1-re. Szóval lentről lépked felfelé de kétszer, emiatt nincs sorban és nekem a tíz legnagyobb sorszám kellene.
          A ciklusok nem változtatnak az adatokon.
          Szóval kb azt csinálja a két ciklus mint ha auto szűrővel leszűrném C oszlopot név1-re utána D oszlopot név2-re kiírnám a sorszámokat és ujra szűrnék de most C oszlopot név2-re D oszlopot név1-re és ezt is kiírnám az előző listához csak ennél nincs sor elrejtés felfedés.

          #4394
          horvimi
          Adminisztrátor

            Ha jól értem, akkor ez egy sima VAGY művelet.
            tehát ha C és D oszlop aktuális adatait összefűzöd, akkor elég egy ciklust futtatn, ami ráadásul kiléphet, ha lentről felfelé már talált 10 előfordulást.
            Tehát tegyük fel, hogy nev1 és nev2 az, amiket keresel így felcserélve.
            Csinálsz két változót. Az egyikbe beleteszed nev1 & nev2-t (legyen a), a másikba nev2 & nev1-et, (legyen b).

            A ciklusban pedig az a feltétel, hogy

            ha az aktuális sorban A oszlop és B oszlop =a vagy A oszlop & B oszlop =b, akkor tegye el a sor számát.

            De lehet úgy is, hogy csinálsz egy számított oszlopt előbb, ami összefűzi az A és B oszlopot, és abban keresel. A VAGY ekkor is kelleni fog.

            Mit gondolsz?

            imre

            #4404
            karesz_k
            Felhasználó

              Szia Imre!
              Ha jól értettem akkor valami ilyesmire gondoltál. Erre az összefűzős megoldásra nem gondoltam, érdekes de jó. Nálam ez 6 mp alatt fut le 155791 soron.
              Sub teszt2()
              starttime = Time

              a = Range(„D1”).Value & Range(„E1”).Value
              b = Range(„E1”).Value & Range(„D1”).Value
              c = 1
              sor = 155791
              Do
              If Range(„A” & sor) & Range(„B” & sor) = a Or Range(„A” & sor) & Range(„B” & sor) = b Then
              Range(„F” & c) = sor
              c = c + 1
              End If

              sor = sor – 1
              Loop Until c = 10 Or sor = 1
              endtime = Time
              fut = (endtime – starttime) * 24 * 60 * 60
              Range(„A1”) = fut

              End Sub

              Én erre a megoldásra jutottam. Ez 1 mp alatt lemegy ugyanazon a listán.
              Sub teszt3()
              starttime = Time

              vég = Cells(Rows.Count, „B”).End(xlUp).Row
              x = Range(„D1”).Value
              y = Range(„E1”).Value
              sor = 1
              With Range(„A1:B” & vég)
              Set c = .Find(x, LookAt:=xlWhole)
              If Not c Is Nothing Then
              firstAddress1 = c.Address
              Set c = .FindPrevious(c)
              Z = c.Row

              End If
              Set c = .Find(y, LookAt:=xlWhole)
              If Not c Is Nothing Then
              firstAddress2 = c.Address
              Set c = .FindPrevious(c)
              v = c.Row

              End If
              End With

              If Z > v Then
              With Range(„A1:B” & vég)
              Set c = .Find(x, LookAt:=xlWhole)
              If Not c Is Nothing Then
              firstAddress = c.Address
              End If
              Do
              Z = c.Row
              o = c.Column

              If o = 1 And Range(„B” & Z) = y Or o = 2 And Range(„A” & Z) = y Then
              Z = c.Row
              o = c.Column
              Range(„G” & sor) = Z
              sor = sor + 1
              End If
              Set c = .FindPrevious(c)

              Loop Until sor = 10 Or Not c Is Nothing And c.Address = firstAddress
              End With

              Else
              With Range(„A1:B” & vég)
              Set c = .Find(y, LookAt:=xlWhole)
              If Not c Is Nothing Then
              firstAddress = c.Address
              End If
              Do
              Z = c.Row
              o = c.Column

              If o = 1 And Range(„B” & Z) = x Or o = 2 And Range(„A” & Z) = x Then
              Z = c.Row
              o = c.Column
              Range(„G” & sor) = Z
              sor = sor + 1
              End If
              Set c = .FindPrevious(c)

              Loop Until sor = 10 Or Not c Is Nothing And c.Address = firstAddress
              End With
              End If

              endtime = Time
              fut = (endtime – starttime) * 24 * 60 * 60
              Range(„B1”) = fut
              End Sub

              Köszönet a segítségért és ezért az oldalért, igazán hasznos.

              #4405
              horvimi
              Adminisztrátor

                Örülök, hogy sikerült.

              6 bejegyzés megtekintése - 1-6 / 6
              • Be kell jelentkezni a hozzászóláshoz.