2016-05-25 14 views
2

Ich musste Excel VBA nicht in einer Weile verwenden, aber ich beschloss, es auszugraben, um ein paar benutzerfreundliche und zugängliche Vorlagen für die Verfolgung von monatlichen Sendungen zu erstellen.Excel VBA - Objekt erforderlich

Diese spezielle Suchfunktion gibt mir Kopfschmerzen und ich vermute, es liegt daran, dass ich mit der Syntax ziemlich eingerostet bin.

Ich habe mich an diesen Punkt, wo ich ein 'Objekt erforderlich' Fehler beim Aufruf eines Benutzerformulars erhalten, aber von dem, was ich sehen kann von Schritt durch, ich habe explizit erklärt und definiert alles im Zusammenhang mit dem Problem Linie.

Schätzen Sie jede Hilfe/Refresher. Mein Gesicht wartet gespannt auf meine Handfläche.

Edit: Aktuelle Code arbeitet in Antwort geschrieben unter

Voll Code

Private Sub UserForm_Initialize() 
'Clear result message 
Me.rResult.caption = "" 

'BOL (cached) 
Dim BOL As Range 
Set BOL = ThisWorkbook.Sheets("Values").Range("$A$3") 
'Addresses (cached) 
Dim addr As Range 
Set addr = ThisWorkbook.Sheets("Values").Range("$A$4:$D$21") 
Dim i As Range 
'Search Range 
Dim srange As Range 
'Target Range 
Dim trange As Range 
'First result 
Dim fr As Range 
'Result counter 
Dim c As Integer 
c = 0 

With ThisWorkbook.ActiveSheet 
    'Set search range 
    Set srange = .Range(.Cells(7, 6), _ 
    .Cells(.Cells(Rows.Count, 5).End(xlUp).Row, _ 
    .Cells(6, Columns.Count).End(xlToLeft).Column)) 

    'Find search results in search range 
    Set trange = srange.Find(BOL.Value, LookIn:=xlValues) 
    'If the cell is not empty and the header in row 6 has a value of "BOL" 
    If Not trange.Value Is Nothing Then '***Problem Line*** 
     If .Cells(6, trange.Value).Value = "BOL" Then 
     'set first address 
     Set fr = .Range(trange.Address) 
     Do 
      'result counter 
      c = c + 1 
      'save each address within cache range 
      For Each i In addr 
       If i.Value = "" Then i.Value = trange.Address 
      Next i 
      Set trange = trange.FindNext(trange) 
     Loop While Not trange Is Nothing And trange.Address <> fr.Address 
     End If 
    End If 
End With 

'Select the first address 
If c <> 0 Then fr.Select 

'Result message 
Me.rResult.caption = "Search found " & c & _ 
    " result(s) for BOL: " & BOL.Value & "." 

'clear cached BOL 
BOL.Clear 

End Sub 
+0

'Mein Gesicht wartet sehnsüchtig auf meine palm.' +1 Edit: die Leitungsfehler wirft? – findwindow

+0

@findwindow wahrscheinlich derjenige mit dem Kommentar, der sagt "**** Das ist die Zeile, die den Fehler auslöst. ****';). –

+0

@VincentG danke aber einer, zu faul, um es durchzulesen (OP sollte immer in Frage zu identifizieren). Zwei, haben es nicht gesehen, weil es hinter der Schriftrolle ist (siehe Punkt 1^_ ^). – findwindow

Antwort

3

Ich denke, es am Ende des trange Ihre .value ist. Wenn du einen Fund machst und nichts gefunden wird, kommt der Transgender als nichts zurück. Dann fragen Sie nach dem Wert von nichts, der Ihnen den Objektfehler gibt.

Ändern Sie es einfach zu If Not trange Is Nothing..., aber ich denke, @Abe Gold hat Recht, Sie brauchen zwei if-Anweisungen. Weil Sie ".cells (6, trange.value) .value =" BOM "" nicht überprüfen können, wenn trange nichts ist.

sollte wie folgt aussehen für Ihre if-Anweisung (Entnommen aus @Abe Gold-Code oben)

If Not trange Is Nothing Then 
    If .Cells(6, trange.Value).Value = "BOL" Then 
     'set first address 
     Set fr = .Range(trange.Address) 
     Do 
     'result counter 
     c = c + 1 
     'save each address within cache range 
     For Each i In addr 
      If i.Value = "" Then i.Value = trange.Address 
     Next i 
     Set trange = trange.FindNext(trange) 
    Loop While trange.Address <> fr.Address 
    End IF 
End If 
+0

Ich habe mit Scheindaten getestet, so dass ich weiß, dass Trange belegt ist. Allerdings habe ich den Wert entfernt und es scheint so zu funktionieren. – ssoong

+0

@ssoong entfernen Sie den '.value'. Syntax-Fehler. Palm bereit? – findwindow

+0

Ja, da ist definitiv ein Handabdruck auf meinem Gesicht. Ich entfernte den Wert von der ersten IF und als ich auf die 2. IF schaute, erkannte ich, dass ich "trange.value" anstelle von "trange.column" verwendet hatte, um die Kopfzeile darüber zu überprüfen. Problem gelöst. Vielen Dank! – ssoong

4

Eine weitere Änderung.

If Not trange.Value Is Nothing Then 

sollte

sein
If Not trange Is Nothing Then 

Rewrite Ihre IF in zwei IFs:

If Not trange.Value Is Nothing Then 
     If .Cells(6, trange.Value).Value = "BOL" Then 
      'set first address 
      Set fr = .Range(trange.Address) 
      Do 
      'result counter 
      c = c + 1 
      'save each address within cache range 
      For Each i In addr 
       If i.Value = "" Then i.Value = trange.Address 
      Next i 
      Set trange = trange.FindNext(trange) 
     Loop While trange.Address <> fr.Address 
     End IF 
End If 
+0

Immer noch wirft Fehler:/ – ssoong

1

Ich weiß, es ist sowohl eine akzeptierte Antwort und zwei am upvoted sind, aber ich bin beide schlägt Verbesserungen und hauptsächlich etwas (siehe letzter Punkt) fehlt

beachten Sie bitte diesen Code:

'Find search results in search range 
Set trange = srange.Find(BOL.Value, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False) '<~~always specify those parameters since they are saved from any Find() usage, even that from UI 
If Not trange Is Nothing Then 'If the cell is not empty and the header in row 6 has a value of "BOL" 
    If .Cells(6, trange.Column).Value = "BOL" Then 
     Set fr = trange '<~~store first trange occurrence found 
     Do 
      c = c + 1 'update result counter 
      addr.SpecialCells(xlCellTypeConstants) = trange.Address '<~~save current address within cache range 
      Set trange = srange.FindNext(trange) '<~~search next occurrence of trange in srange 
     Loop While Not trange.Address <> fr.Address 
    End If 
End If 

deren Unterschiede f rom sind einerseits die OP hiermit zusammengefasst:

  • Set trange = srange.Find(BOL.Value, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)

    immer diese Parameter angeben, da sie von jedem Find() Nutzung gespeichert werden, auch das von UI, so dass yo finden sich unfreiwillig an Zeichenfolge Teil suchen und Passende

  • If Not trange Is Nothing Then

    ok/oder Fallbetreuung, die bereits wurde von allen Antworten etabliert und Kommentare

  • Set fr = trange

    seit .Range(trange.Address) ist redundant

  • addr.SpecialCells(xlCellTypeConstants) = trange.Address

    anstelle der For Each i In addr Schleife

  • Set trange = srange.FindNext(trange)

    hier gab es Set trange = trange FindNext(trange)

    sollte nicht die zweite trangesrange sein?

+0

Ich wusste nicht, dass UI-Einstellungen die Suchmethode beeinflussen, aber es macht definitiv Sinn. Vielen Dank! Ich räumte den Code ein wenig mehr auf, nachdem wir das Problem gelöst und die Redundanz und den Fehler gefunden haben. :) Wie bei den SpecialCells ist der Zweck der for-Schleife, eine leere Zelle innerhalb des Addr-Bereichs zu finden, um die Adresse zwischenzuspeichern. Korrigiere mich, wenn ich falsch liege, aber sollte xlCellTypeConstants nicht xlCelltypeBlanks sein? Und ich denke, dass spezielle Zellen ALLE Zellen auswählen, die den Typkriterien innerhalb des Bereichs entsprechen, während ich nach einer einzelnen Zelle zum Ausfüllen suche. – ssoong

+0

danke für das Feedback. 1) Ja, um leere Zellen auszuwählen, verwende 'xlCellTypeBlanks' Parameter anstelle von' xlCellTypeConstants' für 'SpecialCells' Methode 2)' SpecialCells' Methode gibt ALL (leer, wenn mit 'xlCellTypeBlanks' Parameter) Zellen des' Bereichs' auf den er aufgerufen wird , so würde 'addr.SpecialCells (xlCellTypeBlanks) = trange.Address' alle leeren Zellen von' addr' 'range' mit' tranange.Address' füllen. Genau das hat Ihre 'For Each I In addr'-Schleife getan. 3) Wie könnten frühere Lösungen mit der 'Set trange = trange FindNext (trange)' Anweisung (und mit dem 'Find()' gespeicherten Parameterproblem) funktionieren? – user3598756

+0

Das ist mein Fehler. Ich habe ein 'Exit For' in der ursprünglichen Version der Schleife verpasst. Eine unvorsichtige Aufsicht. Das habe ich irgendwann nach dem Posting behoben, als ich sah, dass der Cache mit der ersten Adresse gefüllt wurde. Ich fing das 'FindNext' Problem auf und korrigierte es, sobald ich den Code durchging und die IF-Anweisungen fehlerfrei übergab. Die gespeicherten Parameter hatten keinen Einfluss auf mein Suchwerkzeug, da ich während der Fehlersuche keine Suche mit verschiedenen Parametern durchgeführt hatte. Definitiv ein guter Tipp für die Zukunft. Ich füge die aktuelle Version des Codes in einer separaten Antwort hinzu. – ssoong

0

Diese If Anweisung wurde nur auf die erste gefundene Adresse angewendet. Ich habe es in die Schleife verschoben, um auf jedes iterative Ergebnis angewendet zu werden.

If .Cells(6, trange.Column).Value = "BOL" Then 

Eine Reihe anderer Änderungen/Korrekturen hinzugefügt, die in den obigen Antworten beschrieben sind. Vielen Dank!

Aktuelle Arbeits Code Schnipsel:

'Find search results in search range 
Set trange = srange.Find(BOL.Value, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False) 
'If the cell is not empy and the header in row 6 has a value of "BOL" 
If Not trange Is Nothing Then 
    'set first address 
    Set fr = trange 
    Do 
     If .Cells(6, trange.Column).Value = "BOL" Then 
     'result counter 
     c = c + 1 
     'save each address within cache range 
     For Each i In addr 
      If i.Value = "" Then 
       i.Value = trange.Address 
       Exit For 
      End If 
     Next i 
     End If 
    Set trange = srange.FindNext(trange) 
    Loop While Not trange Is Nothing And trange.Address <> fr.Address 
End If 
+0

Sie können den '... Not trange Is Nothing ...' -Teil in der 'Loop While'-Endbedingung weglassen, da 1) der 'Loop' erst beginnt, wenn' If Not trange Is Nothing 'bei jeder Iteration 2') "trange" wird auf "srange.FindNext (trange)" gesetzt, was "never_ be" sein kann, da 'FindNext' immer ein' BOL.Value' -Vorkommen im 'srange'-Bereich findet, das in einer kreisförmigen Schleife in ihm gefangen ist. von dem die notwendige Überprüfung auf die "erste Adresse", um die Schleife zu beenden – user3598756

+0

Ja, ich habe es nur da drin gelassen, weil ich dachte, es tat niemandem weh, aber aus Gründen der Transparenz werde ich es entfernen. – ssoong