Excel VBA: prace s promennou odkazujici na vice dat Vyřešeno

Programy pro práci v kanceláři (Word, Excel, Access…=>Office)

Moderátor: Mods_senior

Adalbert
nováček
Příspěvky: 28
Registrován: únor 11
Pohlaví: Muž
Stav:
Offline

Excel VBA: prace s promennou odkazujici na vice dat

Příspěvekod Adalbert » 10 úno 2011 14:54

Tema navazuje na http://www.pc-help.cz/viewtopic.php?f=35&t=63722&start=0.

Pri plneni ostrymi daty doslo k jedne podstatne situaci, ktera mi nabourala pripravenou proceduru; a to:

list1!Axx:Bxx muze tez obsahovat hodnotu "allA" pro sloupec A:A a "allB" pro sloupec B:B.
Hodnota allA je zastupny znak pro mnozinu vsech dat, ktera mohou byt pouzita v list1!Axx a jejichz seznam je definovan v list3!Axx
Hodnota allB je zastupny znak pro mnozinu vsech dat, ktera mohou byt pouzita v list1!Bxx a jejichz seznam je definovan v list3!Bxx

Soucasna procedura dokaze vyhodnotit a doplnit do odpovidajichch radku data pri shode obou sloupcu v list1!Axx:Bxx a list2!Axx:Bxx.
Pochopitelne nedochazi k prenosu dat z list1 do list2 v pripadech, kdy je hodnotou zastupny znak allA, nebo allB.
Potreboval bych jeste poradit jak se vyporadat s timto problemem.

Prikladam opet konkretni priklad.
Vytvoril jsem proceduru ktera mi naplni list2 vsemi moznymi kombinacemi dat z list3 (uvedomuji si, ze zatim je procedura nedokonala, jelikoz mam vstupni data dofinovana v Array rucne, misto aby si vstupni data procedura vytahla z list3, ale bohuzel zatim sem neprisel na to jak)

K temto vytvorenym datum v list2 potrebuji pak priradit hodnoty z list1, s tim ze nyni jiz v list1 nemam pouze konkretni dvojice dat ktere bych mohl porovnavat, ale obcas i mnoziny dat.
Tedy pokud jsou na list1 hodnoty:

allA Z 3

Hodnota 3 by se mi mela prenest k vsem nasledujicim dvojicim, tedy:

A Z 3
B Z 3
C Z 3
D Z 3
E Z 3

Z prilozeneho prikladu snad bude srozumitelnejsi nez mym psanym vykladem.

Procedury jsou v prilozenem .xls, ale dodavam pro prehlednost i do tela tematu:

Procedura generovani vsech kombinaci:

Kód: Vybrat vše

Sub Kombinace()
    Dim abc As Variant
    Dim xyz As Variant
    Dim r As Integer
    Dim x As Integer
    Dim y As Integer
    abc = Array("A", "B", "C", "D", "E")
    xyz = Array("X", "Y", "Z")
    r = 1
    With Worksheets("List2")
        .Cells(r, 1) = "abc"
        .Cells(r, 2) = "xyz"
        For x = 0 To UBound(abc)
            For y = 0 To UBound(xyz)
                     r = r + 1
                    .Cells(r, 1) = abc(x)
                    .Cells(r, 2) = xyz(y)
            Next y
        Next x
    End With
End Sub


Procedura vyhledavani a plneni dat:

Kód: Vybrat vše

Option Explicit
    Sub VyhledatDoplnit()
      Dim BlkA As Range, BlkB As Range
      Dim CllA As Range, CllB As Range
      Dim frstAddr As String
      ' definovani bloku bunek na listech
      With Worksheets("list1")
        Set BlkA = .Range(("a1:a") & .Cells(.Rows.Count, "a").End(xlUp).Row)
      End With
      With Worksheets("list2")
        Set BlkB = .Range(("a1:a") & .Cells(.Rows.Count, "a").End(xlUp).Row)
      End With
      ' prochazet BlkA
      For Each CllA In BlkA.Cells
        ' prohledavat BlkB
        With BlkB
          Set CllB = .Find(CllA.Value, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows)
          If Not CllB Is Nothing Then  ' pri shode porovnat sloupce B:B
            frstAddr = CllB.Address
            Do
              If CllB.Offset(0, 1).Value = CllA.Offset(0, 1).Value Then  ' pri shode doplnit do sl C:C data
                ' abs nova hodnota > abs stara hodnota
                 If Abs(CllA.Offset(0, 2).Value) >= Abs(CllB.Offset(0, 2).Value) Then
                  If Abs(CllA.Offset(0, 2).Value) > Abs(CllB.Offset(0, 2).Value) Then
                   CllB.Offset(0, 2).Value = CllA.Offset(0, 2).Value
                   Else: CllB.Offset(0, 2).Value = "kolize"
                  End If
                 End If
              End If
             Set CllB = .FindNext(CllB)
             Loop While CllB.Address <> frstAddr
           End If
        End With
      Next CllA
      ' odstranit objektove promenne
      Set CllB = Nothing
      Set CllA = Nothing
      Set BlkB = Nothing
      Set BlkA = Nothing
    End Sub
Přílohy
Sešit1.xls
(37 KiB) Staženo 40 x

Reklama
navstevnik
Level 4
Level 4
Příspěvky: 1142
Registrován: srpen 08
Pohlaví: Nespecifikováno
Stav:
Offline

Re: Excel VBA: prace s promennou odkazujici na vice dat

Příspěvekod navstevnik » 10 úno 2011 15:53

Smysl ma vyskyt konkretnich hodnot typu
A Z (B Z; ...E Z; A X;...; E X;.....)
na listu 2, takze otazka generovani techto dat z listu 3 na list 2 je irelevantni. Zustava doplnit proceduru o nalezeni vsech dvojic A Z; B Z ;...; E Z z listu 3 v datech listu 2 v pripade vyskytu dat typu allA Z 3 na listu 1.
Obdobne pro C allB 3 nalezt C X; C Y, C Z

Potvrd ci dopln.

Adalbert
nováček
Příspěvky: 28
Registrován: únor 11
Pohlaví: Muž
Stav:
Offline

Re: Excel VBA: prace s promennou odkazujici na vice dat

Příspěvekod Adalbert » 10 úno 2011 16:59

Irelevantni to neni, jelikoz je pro me smerodatne to, co je v list1!Axx:Bxx:Cxx. A to vsechno musi byt i v list2!Axx:Bxx:Cxx.

Takze, je li zaznam v list1!Axx:Bxx:Cxx napr.: allA; Z; 3
- MUSI se mi vsechny kombinace allA;Z s prislusnou hodnotou ("3") objevit, prenest tez do list2.

Jinymi slovy. Prestoze v .xls, ktere jsem prilozil jako priklad v list2 neni vyskyt hodnot C;Z, musi se mi tam kvuli zaznamu allA; Z; 3 v list1 zobrazit.
Proto jsem pridal do list3 sloupec A = seznam vsech hodnot, ktere jsou mnozinou promenne allA
a sloupec B = seznam vsech hodnot, ktere jsou mnozinou promenne allB.

Proto sem nasledne generoval vsechny mozne kombinace z techno dvou seznamu, abych k nim pak mohl priradit hodnoty
napr.: zaznamu allA; allB; 7 z list1!Axx:Bxx:Cxx - coz je vlastne mnozina vsech kombinaci moznych hodnot v list1!Axx:Bxx s prirazenou hodnotou 7.

navstevnik
Level 4
Level 4
Příspěvky: 1142
Registrován: srpen 08
Pohlaví: Nespecifikováno
Stav:
Offline

Re: Excel VBA: prace s promennou odkazujici na vice dat

Příspěvekod navstevnik » 10 úno 2011 17:28

Napsal jsi:
Vytvoril jsem proceduru ktera mi naplni list2 vsemi moznymi kombinacemi dat z list3 (uvedomuji si, ze zatim je procedura nedokonala, jelikoz mam vstupni data dofinovana v Array rucne, misto aby si vstupni data procedura vytahla z list3, ale bohuzel zatim sem neprisel na to jak)

a to je z hlediska pozadavku na doplneni hodnot irelevantni.
Otestuj proceduru:

Kód: Vybrat vše

Option Explicit

Sub VyhledatDoplnit()
  Dim BlkA As Range, BlkB As Range
  Dim CllA As Range
  Dim ABC() As Variant, XYZ() As Variant
  Dim i As Integer

  ' nacist data pro allA a allB
  With Worksheets("list3")
    Set BlkA = .Range(("a1:a") & .Cells(.Rows.Count, "a").End(xlUp).Row)
    ReDim ABC(1 To BlkA.Cells.Count)
    For i = LBound(ABC) To UBound(ABC)
      ABC(i) = BlkA(i).Value
    Next i
    Set BlkA = .Range(("b1:b") & .Cells(.Rows.Count, "b").End(xlUp).Row)
    ReDim XYZ(1 To BlkA.Cells.Count)
    For i = LBound(XYZ) To UBound(XYZ)
      XYZ(i) = BlkA(i).Value
    Next i
  End With
  ' definovani bloku bunek na listech
  With Worksheets("list1")
    Set BlkA = .Range(("a1:a") & .Cells(.Rows.Count, "a").End(xlUp).Row)
  End With
  With Worksheets("list2")
    Set BlkB = .Range(("a1:a") & .Cells(.Rows.Count, "a").End(xlUp).Row)
  End With
  ' prochazet BlkA
  For Each CllA In BlkA.Cells
    ' prohledavat BlkB
    If CllA.Value <> "allA" And CllA.Offset(0, 1) <> "allB" Then
      Vykonat BlkB, CllA.Value, CllA.Offset(0, 1).Value, CllA.Offset(0, 2).Value
    ElseIf CllA.Value = "allA" And CllA.Offset(0, 1) <> "allB" Then
      For i = LBound(ABC) To UBound(ABC)
        Vykonat BlkB, ABC(i), CllA.Offset(0, 1).Value, CllA.Offset(0, 2).Value
      Next i
    ElseIf CllA.Value <> "allA" And CllA.Offset(0, 1) = "allB" Then
      For i = LBound(XYZ) To UBound(XYZ)
        Vykonat BlkB, CllA.Value, XYZ(i), CllA.Offset(0, 2).Value
      Next i
    End If
  Next CllA
  ' odstranit objektove promenne
  Set CllA = Nothing
  Set BlkB = Nothing
  Set BlkA = Nothing
End Sub

Private Sub Vykonat(ByVal BlkB As Range, ValColA As Variant, ValColB As Variant, ValColC As Variant)
  Dim CllB As Range
  Dim frstAddr As String

  With BlkB
    Set CllB = .Find(ValColA, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows)
    If Not CllB Is Nothing Then  ' pri shode porovnat sloupce B:B
      frstAddr = CllB.Address
      Do
        If CllB.Offset(0, 1).Value = ValColB Then  ' pri shode doplnit do sl C:C data
          ' abs nova hodnota > abs stara hodnota
          If Abs(ValColC) >= Abs(CllB.Offset(0, 2).Value) Then
            If Abs(ValColC) > Abs(CllB.Offset(0, 2).Value) Then
              CllB.Offset(0, 2).Value = ValColC
            Else
              CllB.Offset(0, 2).Value = "kolize"
            End If
          End If
        End If
        Set CllB = .FindNext(CllB)
      Loop While CllB.Address <> frstAddr
    End If
  End With
  Set CllB = Nothing
End Sub

Neni resen pripad, kdy se vyskytuje na listu 1 dvojice allA allB xx
PS.: pri opakovanem spusteni procedury s testovacim daty ze souboru sesit1.xls dojde k chybe v behu procedury pokud v predchazejicim behu byla doplnena hodnota "kolize" na list2. Asi bude vhodnejsi kolizni stavy vypsat do zpravy na zaver.
Ovsem obdobne muze tato chyba vzniknou i pri hodnotach allA nebo allB a s hodnotu ze sloupce C:C vyvolavajici kolizni stav: A Z -3 nasleduje A Z 3 > kolize a dale nasleduje allA Z 3, co s tim?

Adalbert
nováček
Příspěvky: 28
Registrován: únor 11
Pohlaví: Muž
Stav:
Offline

Re: Excel VBA: prace s promennou odkazujici na vice dat

Příspěvekod Adalbert » 11 úno 2011 10:59

Ano, mas pravdu, reseni kolizniho stavu neni stastne z duvodu, ktere si popsal a upravim proceduru tak, aby pri kolizi byla vlozena ciselna hodnota "9999" . Teprve na zaver necham prepsat tuto hodnotu hodnotou "kolize". - to zvladnu sam

Dale do procedury vlozim do prislusne casti (pred provadeni vkladani dat do list2:Cxx)
prikaz .ClearContents na smazani celeho sloupce list2:Cxx. -tez zvladnu taky sam

jinak nevim zda si rozumime ohledne smyslu teto procedury. Smyslem je prenest data z listu1 do listu2 v prehlednejsi podobe.
V listu1 jsou vlastne data zaznamenavana v mnozinach (diky existenci hodnot allA, allB maji nektere hodnoty vice hodnot nez jednu) a kazda mnozina ma ciselnou hodnotu (rekneme prioritu)
Jednotlive mnoziny se pak prolynaji a prave pri techto prunicich mnozin dochazi k porovnavani ciselnych hodnot/priorit. Proto porovnavam absolutni hodnoty, protoze znamenko mi zohlednuje pouze konecny vysledek (+ Ano, - Ne).

Takze nemam nijak predem definovyny seznam na listu2, to jsem na zacatku pouzil pouze pro priklad, jaka data budou v listu2.
Proto defakto plati, ze list2 muze byt na zacatku prazdny a podle definic mnozin s prioritami na listu1 se naplni po ukonceni procedury.
A naplni se hodnotami se stejnym vyznamem jako jsou hodnoty v listu1, avsak v podobe srozumitelne kazdemu, bez analyzovani dat v listu1.
Proto generuji seznam vsech moznych kombinaci a teprve pak je plnim daty. proto si mohu dovolit vyresit problem kolize mazanim pred kazdym novym plnenim priorit. Vzdy vysledna data v listu2 jenom kopiruji situaci na listu1, jen jsou jinak strukturovana.

Neni resen pripad, kdy se vyskytuje na listu 1 dvojice allA allB xx


Takze v tuto chvilil uz posledni vec se kterou bych potreboval poradit je prave reseni i vyskytu dvojice allA allB xx na listu 1

navstevnik
Level 4
Level 4
Příspěvky: 1142
Registrován: srpen 08
Pohlaví: Nespecifikováno
Stav:
Offline

Re: Excel VBA: prace s promennou odkazujici na vice dat

Příspěvekod navstevnik » 11 úno 2011 12:02

Zde je upravena procedura "Kombinace", se kterou jsi mel potize:

Kód: Vybrat vše

Option Explicit

Sub Kombinace()
  Dim Cll As Range, OfsR As Long
  Dim BlkAllA As Range, BlkAllB As Range
  Dim CllAllA As Range, CllAllB As Range

  With Worksheets("list2")
    Set Cll = .Range("a1")
    ' vyprazdnit sloupce
    Cll.Resize(.Rows.Count, 4).ClearContents
  End With
  With Worksheets("list3")
    Set BlkAllA = .Range(("a1:a") & .Cells(.Rows.Count, "a").End(xlUp).Row)
    Set BlkAllB = .Range(("b1:b") & .Cells(.Rows.Count, "b").End(xlUp).Row)
  End With
  Cll.Offset(0, 0).Value = "abc"
  Cll.Offset(0, 1).Value = "xyz"
  OfsR = 1
  For Each CllAllA In BlkAllA.Cells
    For Each CllAllB In BlkAllB.Cells
      Cll.Offset(OfsR, 0).Value = CllAllA.Value
      Cll.Offset(OfsR, 1).Value = CllAllB.Value
      OfsR = OfsR + 1
    Next CllAllB
  Next CllAllA
  Set Cll = Nothing
  Set CllAllA = Nothing
  Set BlkAllA = Nothing
  Set CllAllB = Nothing
  Set BlkAllB = Nothing
End Sub

Dale je upravena procedura pro vlozeni dat. Doplneno vyprazdneni sloupcu list2!C:D, doplneno vyhodnoceni dvojice allA allB xx, presunuto oznaceni kolize do sloupce D:D a generovani zpravy o zjistenych kolizich (kdyz, tak si uprav podle sebe):

Kód: Vybrat vše

Option Explicit
Dim ErrStr As String

Sub VyhledatDoplnit()
  Dim BlkA As Range, BlkB As Range
  Dim BlkAllA As Range, BlkAllB As Range
  Dim CllA As Range, CllAllA As Range, CllAllB As Range

  ' definovani bloku bunek na listech
  With Worksheets("list1")
    Set BlkA = .Range(("a1:a") & .Cells(.Rows.Count, "a").End(xlUp).Row)
  End With
  With Worksheets("list2")
    Set BlkB = .Range(("a1:a") & .Cells(.Rows.Count, "a").End(xlUp).Row)
    ' vyprazdnit sloupce C:D
    BlkB.Resize(BlkB.Rows.Count, 2).Offset(0, 2).ClearContents
  End With
  ' definovat bloky pro allA a allB
  With Worksheets("list3")
    Set BlkAllA = .Range(("a1:a") & .Cells(.Rows.Count, "a").End(xlUp).Row)
    Set BlkAllB = .Range(("b1:b") & .Cells(.Rows.Count, "b").End(xlUp).Row)
  End With
  ErrStr = vbNullString
  ' prochazet BlkA
  For Each CllA In BlkA.Cells
    ' prohledavat BlkB
    If CllA.Value <> "allA" And CllA.Offset(0, 1) <> "allB" Then
      Vykonat BlkB, CllA.Value, CllA.Offset(0, 1).Value, CllA.Offset(0, 2).Value
    ElseIf CllA.Value = "allA" And CllA.Offset(0, 1) <> "allB" Then
      ' vyskyt allA
      For Each CllAllA In BlkAllA.Cells
        Vykonat BlkB, CllAllA.Value, CllA.Offset(0, 1).Value, CllA.Offset(0, 2).Value
      Next CllAllA
    ElseIf CllA.Value <> "allA" And CllA.Offset(0, 1) = "allB" Then
      ' vyskyt allB
      For Each CllAllB In BlkAllB.Cells
        Vykonat BlkB, CllA.Value, CllAllB.Value, CllA.Offset(0, 2).Value
      Next CllAllB
    ElseIf CllA.Value = "allA" And CllA.Offset(0, 1) = "allB" Then
      For Each CllAllB In BlkAllB.Cells
        For Each CllAllA In BlkAllA.Cells
          Vykonat BlkB, CllAllA.Value, CllAllB.Value, CllA.Offset(0, 2).Value
        Next CllAllA
      Next CllAllB
    End If
  Next CllA
  ' chybova zprava
  If ErrStr <> vbNullString Then
    MsgBox "Vyskytly se kolize:" & vbCr & ErrStr, vbOKOnly + vbExclamation
  End If
  ' odstranit objektove promenne
  Set CllAllA = Nothing
  Set BlkAllA = Nothing
  Set CllAllB = Nothing
  Set BlkAllB = Nothing
  Set CllA = Nothing
  Set BlkB = Nothing
  Set BlkA = Nothing
End Sub

Private Sub Vykonat(ByRef Blk As Range, ValColA As Variant, ValColB As Variant, ValColC As Variant)
  Dim CllB As Range
  Dim frstAddr As String

  With Blk
    Set CllB = .Find(ValColA, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows)
    If Not CllB Is Nothing Then  ' pri shode porovnat sloupce B:B
      frstAddr = CllB.Address
      Do
        If CllB.Offset(0, 1).Value = ValColB Then  ' pri shode doplnit do sl C:C data
          ' abs nova hodnota > abs stara hodnota
          If Abs(ValColC) >= Abs(CllB.Offset(0, 2).Value) Then
            If Abs(ValColC) > Abs(CllB.Offset(0, 2).Value) Then
              CllB.Offset(0, 2).Value = ValColC
            Else
              CllB.Offset(0, 3).Value = "kolize"
              ErrStr = ErrStr & CllB.Address & ", " & ValColA & ", " & ValColB & ", " & ValColC & vbCr
            End If
          End If
        End If
        Set CllB = .FindNext(CllB)
      Loop While CllB.Address <> frstAddr
    End If
  End With
  Set CllB = Nothing
End Sub

PS.: procedura nerozlisuje mala a velka pismena, osetrit?

Adalbert
nováček
Příspěvky: 28
Registrován: únor 11
Pohlaví: Muž
Stav:
Offline

Re: Excel VBA: prace s promennou odkazujici na vice dat  Vyřešeno

Příspěvekod Adalbert » 11 úno 2011 13:56

Diky, to je presne ono.
Preju prijemnej vikend.


  • Mohlo by vás zajímat
    Odpovědi
    Zobrazení
    Poslední příspěvek
  • Tisk více excel souborů najednou.
    od Myerina » 17 dub 2024 17:42 » v Kancelářské balíky
    2
    930
    od Myerina Zobrazit poslední příspěvek
    20 dub 2024 11:36
  • excel text na konec více řádků najednou Příloha(y)
    od Myerina » 03 led 2024 11:51 » v Kancelářské balíky
    5
    1090
    od Zivan Zobrazit poslední příspěvek
    04 led 2024 09:42
  • Notebook kancelářská práce
    od Leopoldkol » 20 úno 2024 21:23 » v Rady s výběrem hw a sestavením PC
    2
    749
    od Leopoldkol Zobrazit poslední příspěvek
    20 úno 2024 22:39
  • 220nitů a 400 nitů internet a práce
    od p3v4x » 05 lis 2023 12:33 » v Problémy s hardwarem
    1
    905
    od Kuba5 Zobrazit poslední příspěvek
    06 lis 2023 09:29
  • QD-Oled a práce s photoshopem (burn-in) ?
    od name66 » 06 čer 2023 15:21 » v Rady s výběrem hw a sestavením PC
    1
    747
    od Vladicek Zobrazit poslední příspěvek
    07 čer 2023 11:40

Zpět na “Kancelářské balíky”

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 3 hosti