[VBA] Excel kopieer bepaalde waardes uit een lijst

Pagina: 1
Acties:
  • 370 views sinds 30-01-2008
  • Reageer

  • abbastijn
  • Registratie: Augustus 2002
  • Laatst online: 08-04 21:31
Ik ben voor mijn werk bezig met het uitzoeken van een grote lijst (80000 rows) met gegevens van materialen in de rijen (ca. 12000 unieke materialen). Er zijn meerdere rows per materiaal, en we willen naar 1 row per materiaal toe. Het kan zijn dat er voor een bepaalde property van een materiaal (columns) meerdere waardes zijn. Hier is een voorbeeld van een stukje uit de sheet:

MaterialInfo recordVendor
22852
22852
228525300187148I0116
228525300187148I0116
22386
223865300187244
22386Y0336


Ik heb nu de volgende macro gemaakt. Ik ben niet zo bekend met VBA, maar ben druk lerende ;)
Wat dit doet is alle waardes voor een bepaalde property van een materiaal in een array zetten (als ze niet leeg zijn) en dan die waarde naar een andere sheet schrijven. Vooralsnog even alleen voor de materialen die maar 1 property hebben, maar hij moet dus uiteindelijk als er meerdere zijn die ook gaan vergelijken en als ze hetzelfde zijn schrijven.

PROBLEEM: als ik het probeer te draaien geeft ie een 'Runtime error 91: Object variable or with block variable not set'. Ik heb geen idee waar dat aan ligt, is het iets inhoudelijks in mijn code? Ik heb al geprobeerd de twee object variables anders te doen, maar dat helpt niet.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Sub TrimExtract()
Dim SourceCell As Object
Dim WorkRange As Range
Dim DestCell As Object
Dim SourceRow As Long
Dim NewMaterial As Boolean
Dim ArraySize As Integer
ArraySize = 0
Dim MaterialValues() As String

WorkRange = Worksheets("BRON1").Range("C2:C50")
DestCell = Worksheets("DOEL").Cells("C2")

' Loop voor iedere rij
For Each SourceCell In WorkRange
    'SourceRow = SourceCell.Row
    
    ' Kijken of het een nieuw materiaal is
    If Range("A" & (SourceCell.Row)).Value = "NEW" Then
        NewMaterial = True
    Else
        NewMaterial = False
    End If
    
    ' Als er een nieuw materiaal is, moet er eerst worden bekeken of er meerdere waardes in de array
    ' zitten en moet er iets naar DOEL worden geschreven
    If NewMaterial = True Then
        If ArraySize > 1 Then
            'doe iets moeilijks om te bepalen welke we moeten schrijven
            DestCell.Value = "meerdere waardes!"
            'daarna moet de array weer op 0 worden gezet
            ArraySize = 0
            ReDim MaterialValues(ArraySize)
            'ReDim MaterialValues(UBound(MaterialValues) - ArraySize)
        Else
            If ArraySize = 0 Then
                'het is de eerste die we doen, dus we hoeven nog niets naar het doel te schrijven
            Else
                'er staat maar 1 cel met een waarde voor dit materiaal in het bronbereik, dus we kunnen die waarde schrijven
                DestCell.Value = MaterialValues(1)
                'daarna moet de array weer op 0 worden gezet
                ArraySize = 0
                ReDim MaterialValues(ArraySize)
                'ReDim MaterialValues(UBound(MaterialValues) - ArraySize)
            End If
        End If
        
        'de doelcel moet 1 naar onder worden gezet
        DestCell = DestCell.Offset(1, 0)
        
    
    Else
    ' Als er geen nieuw materiaal is, schrijf dan de volgende waarde naar de array als de broncel niet leeg is
        If SourceCell <> "" Then
            ReDim Preserve MaterialValues(ArraySize)
            MaterialValues(ArraySize) = SourceCell.Value
        End If
    End If
Next SourceCell
End Sub

There's so much comedy on television. Does that cause comedy in the streets?


  • Lustucru
  • Registratie: Januari 2004
  • Niet online

Lustucru

26 03 2016

object variabelen in vba wijs je toe met het sleutelwoord set:
code:
1
2
3
set Obj = object
ipv
Obj = object

De oever waar we niet zijn noemen wij de overkant / Die wordt dan deze kant zodra we daar zijn aangeland


Verwijderd

je hoeft ook geen generiek objecttype te gebruiken in de for each loop. als je weet dat een subbereik van een bereik ook een bereik is, kan je best de overeenstemmende variabele als zodanig definiëren. (dus bv. dim sourcecell as range). de vb-ide doet dan het intellisense werk voor het opzoeken van beschikbare eigenschappen & methodes.

  • abbastijn
  • Registratie: Augustus 2002
  • Laatst online: 08-04 21:31
Nu heb ik dit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Sub TrimExtract()
Dim WorkRange As Range
Dim DestCell As Range
Dim SourceCell As Range
Dim NewMaterial As Boolean
Dim ArraySize As Integer
ArraySize = 0
Dim MaterialValues() As String


Set WorkRange = Worksheets("BRON1").Range("C2:C50")
Set DestCell = Worksheets("DOEL").Range("C2")

' Loop voor iedere rij
For Each SourceCell In DOEL1.UsedRange
    'SourceRow = SourceCell.Row
    
    ' Kijken of het een nieuw materiaal is
    If Range("A" & (SourceCell.Row)).Value = "NEW" Then
        NewMaterial = True
    Else
        NewMaterial = False
    End If
    
    ' Als er een nieuw materiaal is, moet er eerst worden bekeken of er meerdere waardes in de array
    ' zitten en moet er iets naar DOEL worden geschreven
    If NewMaterial = True Then
        If ArraySize > 1 Then
            'doe iets moeilijks om te bepalen welke we moeten schrijven
            DestCell.Value = "meerdere waardes!"
            'daarna moet de array weer op 0 worden gezet
            ArraySize = 0
            ReDim MaterialValues(ArraySize)
            
        Else
            If ArraySize = 0 Then
                'het is de eerste die we doen, dus we hoeven nog niets naar het doel te schrijven
            Else
                'er staat maar 1 cel met een waarde voor dit materiaal in het bronbereik, dus we kunnen die waarde schrijven
                DestCell.Value = MaterialValues(1)
                'daarna moet de array weer op 0 worden gezet
                ArraySize = 0
                ReDim MaterialValues(ArraySize)
                
            End If
        End If
        
        'de doelcel moet 1 naar onder worden gezet
        Set DestCell = DestCell.Offset(1, 0)
    
    Else
    ' Als er geen nieuw materiaal is, schrijf dan de volgende waarde naar de array als de broncel niet leeg is
        If Trim(SourceCell.Value) <> "" Then
            ReDim Preserve MaterialValues(ArraySize)
            MaterialValues(ArraySize) = SourceCell.Value
        End If
    End If
Next SourceCell
End Sub

Maar nu zegt hij weer: 'Error 424: Object required'... :?

There's so much comedy on television. Does that cause comedy in the streets?


Verwijderd

Visual Basic:
1
for each sourcecell in Worksheets("BRON1").Range("C2:C50")

  • abbastijn
  • Registratie: Augustus 2002
  • Laatst online: 08-04 21:31
Stom! Bedankt _/-\o_

Ik kan weer verder met debuggen... als het niet lukt laat ik wel weer wat horen :)

There's so much comedy on television. Does that cause comedy in the streets?


  • Lieuwe15
  • Registratie: Januari 2004
  • Laatst online: 17:01
Ik zit ongeveer met hetzelfde probleem hier op mijn werk,
Ik heb een lijst met relaties en daarbij staan er vele dubbel of zelfs driedubbel in, met het normale adres en postbus adres.
Alleen nu moet het postbus adres achter het normale adres komen te staan en de hele regel van het postbusadres verwijderen.
Alleen nu is hier niemand thuis in visual basic en het probleem van abbastijn lijkt veel op onze, alleen het moet zo spoedig mogelijk klaar zijn..
Ik heb wel ongeveer een logica bedacht hoe het moet gebeuren, maar het vertalen in een script is erg lastig omdat ik niet thuis ben in zulk spul..
[table border=1 width=350 cellpadding=2 bordercolor=#000000]
[tr]
[td]47[/td][td]Klant b.v.[/td][td]Postbus[/td][td]nr[/td][td]1234 AA[/td][td]Plaatsnaam[/td][td]True[/td]
[/tr]
[tr]
[td]47[/td][td]Klant b.v.[/td][td]Adres[/td][td]nr[/td][td]1234 AB[/td][td]Plaatsnaam[/td][td]False[/td]
[/tr]
[/table]
Dit is een voorbeeld, hierbij moet dus het postbus tot plaatsnaam gekopieerd worden en achter de ander geplakt worden. De True en False waardes zijn voor postbus, dus als er een postbus is, is het true en anders false.
De ene keer staat het postbus adres erboven en andere keer eronder.
Ik had zoiets in gedachte:


Als Postbsveld = True & Klantnummer =/ uniek
Selecteer van die rij kolom E:K
Kopieer selectie
Zoek naar Klantnummer gegeven in die rij en het resultaat moet niet dezelfde rij zijn.
Als dat waar is
plak klembord in kolom L van de rij
End if
Verwijder de gehele rij waar het uit komt
Als Klantnummer = uniek OR Postbusveld bij die klantnummer = False (oftewel als er geen postbus nummer meer is maar bijvoorbeeld wel 2 adressen)
Zoek naar volgende Klantnummer
End if
End if


Zoiets moet het ongeveer worden, alleen het in visual basic vertalen ben ik te slecht in, ik heb wel een beetje gehad, maar niet genoeg om dit te kunnen aangezien dit met totaal andere syntaxen werkt omdat het met excel gaat..
Ik hoop dat iemand mij zou kunnen helpen...
Ik weet dat het niet de bedoeling is om om een complete script te vragen, maar er zit haast achter anders had ik het zelf grotendeels wel uitgevogeld, maar daar is helaas geen tijd en middelen voor..


Ik heb het al voor melkaar, de script is niet echt fool proof en er zitten te veel variabelen in, maar als iemand er interesse in heeft post ik hem graag.
Edit: laat maar hij heeft niet goed gewerkt, relaties staan allemaal verkeerd..

[ Voor 12% gewijzigd door Lieuwe15 op 14-12-2007 11:53 ]

Pagina: 1