Microsoft Excel

Herbers Excel/VBA-Archiv

Browser Element anspreche - gleiche ID


Betrifft: Browser Element anspreche - gleiche ID von: Gordon
Geschrieben am: 24.04.2017 09:01:27

Guten Morgen alle zusammen,

ich versuche mich gerade mal wider seit längerem an VBA und bin auf ein Problem gestoßen. Und zwar:

Über Excel und VBA steuere ich eine Webpage an und fülle dort ein Formular mit Daten aus dem Excel aus. Bisher ging das auhc immer recht gut. Die jeweiligen Elemente (hauptsächlich ComboBoxen) spreche ich mit ".getelementbyid()" an und gebe dabei die gewünschte Listenfeld-ID mit. Als Beispiel:

.getelementbyid("GatewayMaster_ContentSection_dgKategorieMerkmal__ctl17_ctrlMerkmalItem_cboMerkmalItem").Value = 2655

Nun habe ich aber das Problem, dass ich zwei Comboboxen auf der Seite habe, die während meiner Eingaben jeweils erst sichtbar gemacht werden (Event "onchange"), und die gleiche ID besitzen: "dgUnterKategorieMerkmal__ctl2_ctrlMerkmalItem_cboMerkmalItem"

Ich kann also diese beiden Comboboxen mit keiner bisherigen Methode sie anzusprechen nicht steuern. Jetzt frage ich natürlich, wie ich das anstonsten tun könnte. Ich könnte zwar mit "Application.SendKeys" arbeiten, was ich aber recht unschön finden würde. Gibt es eine andere Möglichkeit die Boxen mit der gleichen ID jeweils anzusprechen?

Hier einmal die jeweilige Konfiguration die ich zu den Boxen im Code gefunden haben:

1.

SELECT onchange="cboMerkmalChanged(this, this.options[this.selectedIndex].value);" id= _
dgUnterKategorieMerkmal__ctl2_ctrlMerkmalItem_cboMerkmalItem
style="MAX-WIDTH: 200px; WIDTH: 200px" name=dgUnterKategorieMerkmal:_ctl2:ctrlMerkmalItem: _
cboMerkmalItem data-iziel-id="396046" data-nachgelagert=""
data-sziel-id="361457" data-pflichtfeldTyp="1" data-kategorie-id="257" data-zom-id="4751026"  _
data-onload-selection="">
2.
SELECT onchange="cboMerkmalChanged(this, this.options[this.selectedIndex].value);" id= _
dgUnterKategorieMerkmal__ctl2_ctrlMerkmalItem_cboMerkmalItem
style="MAX-WIDTH: 200px; WIDTH: 200px" name=dgUnterKategorieMerkmal:_ctl2:ctrlMerkmalItem: _
cboMerkmalItem data-iziel-id="396046" data-nachgelagert="" 
data-sziel-id="361457" data-pflichtfeldTyp="2" data-kategorie-id="300" data-zom-id="" data- _
onload-selection="">

Vielleicht hat ja jemand von euch eine Idee? Ich danke schon mal für eure Beiträge im Voraus!

Gruß
Gordon

  

Betrifft: AW: Browser Element ansprechen - gleiche ID von: Gordon
Geschrieben am: 24.04.2017 12:31:49

Ergämnzende Frage hier zu:
Gibt es eine Möglichkiet eine der Boxen mit einem Attributwert anzusprechen. Also zum Beispiel:

.getelementbyid("TEST").hasAttribute("data-kategorie-id").hasAttributeValue("300")
Oder so ähnlich?

Gruß
Gordon


  

Betrifft: Browser Element anspreche - gleiche ID von: Anton
Geschrieben am: 24.04.2017 16:32:13

Hallo Gordon,

so vielleicht:

Code:

Sub b()
  Dim IEApp As Object, sels As Object, sel As Object, attr As Object  
  Set IEApp = GetObject("new:{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}")  
  IEApp.Visible = True
  IEApp.Navigate "C:\Temp\test.htm" 'anpassen
  Do: Loop Until IEApp.Busy = False    
  Do: Loop Until IEApp.Busy = False    
  Do: Loop Until IEApp.Document.ReadyState = "complete"    
  Set sels = IEApp.Document.getelementsbyName("dgUnterKategorieMerkmal:_ctl2:ctrlMerkmalItem:cboMerkmalItem")  
  If Not sels Is Nothing Then    
    For Each sel In sels  
      For Each attr In sel.Attributes  
        If attr.Name = "data-kategorie-id" And attr.Value = 257 Then  
          sel.Value = "1" 'Combobox 1
        ElseIf attr.Name = "data-kategorie-id" And attr.Value = 300 Then    
          sel.Value = "2" 'Combobox 2
        End If  
      Next
    Next
  End If  
  Set IEApp = Nothing  
End Sub  



mfg Anton


  

Betrifft: AW: Browser Element anspreche - gleiche ID von: Gordon
Geschrieben am: 25.04.2017 11:55:16

Hallo Anton,

danke für den Code. Sowas ähnliches hatte ich schon im Netz gesheen, aber leider funktioniert es irgendwie nicht. Theoretisch habe ich auch vielleicht irgendwo einen Fehler. Hier mal mein Code-Schnipsel:

With browser.Document
...
..
Set cbbs = .getelementbyid("dgUnterKategorieMerkmal:_ctl2:ctrlMerkmalItem:cboMerkmalItem")
If Not cbbs Is Nothing Then
  For Each cbb In cbbs
    For Each attr In cbb.Attributes
      If attr.Name = "data-kategorie-id" And attr.Value = 300 Then
        cbb.Value = TEST(x)
      End If
    Next
  Next
End If
..
...
End With
Beim Debugging viel mir auf auf dass das Object "cbbs" nach "Set cbbs = .getelementbyid("dgUnterKategorieMerkmal:_ctl2:ctrlMerkmalItem:cboMerkmalItem")" nur mit ["Object"] gefüllt war. Das klingt im ersten Moment komisch. Danach läuft dann die For-Schleife endlos. Es wird nichts gefunden. :-(

Vielleicht hat da jemand noch eine Idee?

Gruß
Gordon


  

Betrifft: Warum nimmst du .getelementbyid? oT von: Anton
Geschrieben am: 25.04.2017 12:14:58




  

Betrifft: AW: Warum nimmst du .getelementbyid? oT von: Gordon
Geschrieben am: 25.04.2017 13:53:41

Moin Anton,

ich hatte erst .getelementbyname versucht, aber dabei bekomme bei der Code-Zeile

"Set cbbs = .getelementbyname("dgUnterKategorieMerkmal:_ctl2:ctrlMerkmalItem:cboMerkmalItem")"
die Fehlermeldung
Laufzeitfehler '438':
Objekt unterstützt diese Eigenschaft oder Methode nicht
Mit .getelementbyid geht es zwar weiter, füllt die Variable cbbs aber anscheinend nicht wie gewollt.

Gruß
Gordon


  

Betrifft: .getelementSbyname von: Anton
Geschrieben am: 25.04.2017 14:41:27

Hallo Gordon,

.getelementSbyName

siehe auch hier.

mfg Anton


  

Betrifft: Grundsätzliche Überlegungen dazu von: Zwenn
Geschrieben am: 25.04.2017 15:40:09

Hallo Gordon,
hallo Anton,

sorry, wenn ich mich hier einmische, aber ich habe mir einige Gedanken zu diesem Problem gemacht. Generell ist die Verwendung der gleichen ID für mehrere Elemente in einer Seite ein absolutes no go. Leider musst Du aber damit klar kommen, weil jemand diesen Fehler bei der Programmierung gemacht hat.

Zunächst mal folgendes:

  • getElemetByID greift genau auf das Element mit genau dieser ID zu. Es handelt sich um eine Variable

  • Alle get-Befehle, die ein Elements statt nur das Element enthalten, geben ein Array zurück


  • Ich sehe mehrere Lösungsansätze, zu denen ich aber nicht mehr sagen kann, weil ich den Rest des Seitenaufbaus nicht kenne. Du hast uns leider nur die Beiden select-Tags gegeben. Deshalb mal einige allgemeine Ausführungen.

    1. Es gibt mehr als die gezeigten select-Tags, aber die gewünschten liegen innerhalb eines form-Tags
    In diesem Fall würde ich schauen, ob Du zunächst das richtige form-Tag ansprechen kannst. Je nachdem, wie die Seite aufgebaut ist, kann das ganz gut über getElementByID oder über getElementsByTagName("form") funktionieren.

    Über die ID gibt es einen direkten Zugriff, über den Tag-Namen kannst Du das Array durchgehen und nach funktionierenden Kriterien das richtige form-Tag raussuchen, innerhalb dessen Du dann das richtige select-tag auswählst.


    2. Es gibt eine überschaubare Anzahl select-Tags, die klare Unterscheidungsmerkmale haben
    In dem Fall nutzt Du zunächst getElementsByTagName("select") und suchst innerhalb des Arrays das richtige select-Tag heraus.

    Das funktioniert in Deinem Fall wahrscheinlich am besten über die Suche nach einem bestimmten Attributwert. Sofern ich es in den von Dir gezeigten select-Tags richtig gesehen habe, sind die bis auf wenige Ausnahmen fast identisch. Du könntest z.B. auf data-pflichtfeldTyp abfragen und die richtige Nummer rausssuchen. Einfacher dürfte es aber sein zu prüfen, ob data-zom-id bereits ein Wert zugewiesen wurde oder nicht. Du suchst dafür nur das select ohne einen Attributwert für data-zom-id und hast gefunden, was Du suchst.


    3. Es gibt nur die select-Tags auf der Seite, an die Du soswieso ran willst
    Dann brauchst Du nur ein Array über getElementsByTagName("select") bilden und es von vorne nach hinten durchgehen.


    Eine weitere Überlegung:
    Du hast geschrieben, die nächste Auswahlliste erscheint erst, wenn in der aktuellen eine Auswahl getroffen wurde. Wird die nächste Auswahlliste dann erst erzeugt oder wird sie nur sichtbar gemacht und ist vorher schon in der Seite enthalten?

    Sofern sie erst erzeugt wird, musst Du das Dokument neu in dein VBA-Makro holen und kannst das zusätzliche select-Tag erst dann finden. Sofern Du eine Seite vom Aufbau her im Browser veränderst, veränderst Du dadurch ja nicht automatisch das Objekt im Makro.

    In diesem Fall und wenn es die einzigen select-Tags in der Seite oder im als VBA-Objekt gespeicherten Dokumentteil sind (z.B. form-Tag), kannst Du das zuletzt erzeugte select-Tag sehr einfach ansprechen, indem Du das Array-Element mit dem höchsten Index ansprichst. Aus dem Array, dass Du über getElementsByTagName("select") bildest.


    Vielleicht gibt es die Möglichkeit für uns, einen Blick auf den ganzen HTML-Code der Seite zu werfen. Dann könnte man sicher spezifischere Aussagen machen, um Dir zu helfen.

    Viele Grüße,

    Zwenn


      

    Betrifft: AW: Grundsätzliche Überlegungen dazu von: Gordon
    Geschrieben am: 25.04.2017 21:26:55

    Moin Zwenn,

    erstmal vielen Dank für deine ausführlichen Erläuterungen. Leider bin ich gerade unterwegs und kann daher schwer hier etwas mit Code posten, aber vielleicht schaffe ich es ja morgen. Der HTML Code ist vielleicht etwas viel zum posten, aber das Java Script, welches für die Erstellung/Anzeige der beiden Comboboxen mit den gleichen IDs zuständig ist, kann ich vielleicht hier anhängen. Ich schaue mal, ob ich das morgen schaffe.

    Mir ist aber heute beim Testen und Probieren etwas aufgefallen - und zwar erstmal das grundsätzliche Szenario:

    Generell geht es ja bei mir im zwei bestimmte Comboboxen mit der selben ID. Ich nenne sie mal CB1 und CB2. Beide Boxen sind intital nicht auf der Seite vorhanden, sondern erscheinen erst, wenn man jeweils einen Eintrag in einer überstehenden Combobox auswählt.

    Ablauf:
    1.
    Ich lade per VBA eine Webpage und navigiere erstmal durch die Menüs per Script.
    2.
    Auf der letzten Seite sind CB1 und CB2 nich nicht zu sehen. Generell sind sonst noch alle anderen Elemente der Seite nicht gefüllt.

    3.
    Es wird ein bestimmter Eintrag per Combobox gewählt. Daraufhin wird die Seite nochmal geladen und die leeren bestehenden Elemente befüllt. Unter anderen wird CB1 auch angezeigt und befüllt. CB2 ist nicht angezeigt.

    4.
    Nun wird ein weiteren aktull leeres Element per VBA gefüllt und per ".FireEvent(onCBBChange)" wird so CB2 sichtbar geschaltet bzw. generiert.

    5.
    CB2 soll nun gefüllt werden, aber es fehlt mir aktuell die Möglichkeit diese CB2 anzusprechen.


    Soviel erstmal zum Szenario.
    Ich habe etwas getestet und in meinem Browser Objekt (Set Browser = CreateObject("InternetExplorer.Application")) nach den Select Attributen (bzw. Optionen) gesucht. Den genauen Code habe ich gerade nicht zur Hand. Aber bei meiner Schleifensuche viel auf, dass er nur die Attribute der CB1 findet, aber nicht die der CB2. Als wären sie nicht auf der Seite vorhanden.

    Kann es daher sein, dass ich irgendwie den aktuellen Browser Inhalt abermals in meinem Browser Object aktualieren muss, damit der die CB2 findet? Bin da aktuell echt verwirrt.

    Gruß
    Gordon


      

    Betrifft: AW: Grundsätzliche Überlegungen dazu von: Zwenn
    Geschrieben am: 26.04.2017 01:31:06

    Moin Gordon,

    angenem, einen weiteren Nordi hier zu treffen ;-)

    So wie Du das Verhalten der Seite beschreibst, scheint es so zu sein, als wenn eine weitere Combobox wirklich erst generiert wird, wenn du die vorhergehende ausfüllst. Der Unterschied zwischen sichtbar machen und neu generieren ist für Dein Vorhaben grundlegend wichtig. Wird ein Element der Seite nur sichtbar gemacht, ist es in der ersten geladenen Fassung der Seite schon vorhanden und Du kannst es abfragen und bearbeiten. Wird es hingegen erst neu generiert, sobald Du dies durch ein anderes Element der Seite ausgelöst hast, musst Du das Document-Objekt im Makro durch den aktuellen Browserinhalt ersetzen. Wenn Du das nicht machst, kannst Du das gesuchte (neu generierte) Element niemals finden.

    Es wäre wirklich hilfreich, wenn Du den ganzen HTML Code posten würdest. Das Format ist dabei relativ egal. Es gibt Tools, die das Ganze 'schön machen'. Naja, hoffe ich jedenfalls ;-) Die JS allein dürften ziemlich wenig Aussagekraft für Dein Problem haben.

    Viele Grüße,

    Zwenn


      

    Betrifft: AW: Grundsätzliche Überlegungen dazu von: Gordon
    Geschrieben am: 26.04.2017 07:36:39

    Moin Zwenn,

    da es sich teilweise um eher um empfindliche Daten auf der Webpage handelt, würde ich diese ungerne hier öffentlich posten. Wenn du mir deine E-Mail-Adresse gibst, könnte ich sie dir so zu kommen lassen.
    Was ich aber noch dazu sagen muss: CB1 und CB2 befinden sich nicht auf dem Quellcode der Seite - selbst wenn sie sichtbar sind! Den Code zu diesen beiden Boxen sehe ich nur, wenn ich auf die Boxen bzw. neben die Boxen in die HTNL-Tabelle rechtsklicke und "Element untersuchen" auswähle. Dann sehe ich auf einmal einen anderen Code der nicht im direkten Quellcode der Seite zu finden ist.
    Mein Gefühl ist, dass alle Untermenü (wie. z.B. CB1 udn CB2) aus dieser anderen Quellcode-Seite per Javascript generiert werden.

    Wie könnte ich denn das aktuelle Document-Objekt im Makro durch den aktuellen Browserinhalt am einfachsten ersetzen?

    Gruß
    Gordon


      

    Betrifft: AW: Grundsätzliche Überlegungen dazu von: Gordon
    Geschrieben am: 26.04.2017 10:56:32

    So,

    ich habe es nun hinbekommen. Anscheinend sind die Boxen doch nicht generiert. Habe nun folgenden Abfrage gebastelt, die die richtige ComboBox greift:

    Set cbbs = .getElementsByTagName("select")
    If Not cbbs Is Nothing Then
      For Each cbb In cbbs
        If cbb.Name = "dgUnterKategorieMerkmal:_ctl2:ctrlMerkmalItem:cboMerkmalItem" And cbb. _
    innerText = " A X" Then
          cbb.Value = "1000"
        End If
      Next
    End If
    
    Der innerText der Box ist sehr eindeutig. Daher konnte ich darüber an die Box kommen. Jetzt funktioniert es auf jeden Fall. :-)
    Am libsten würde ich zwar statt innerText die uniqueNumber der Combobox benutzen, aber da habe ich Angst das diese Number beim nächsten Seitenaufruf neu vergeben wird.

    Danke auf jeden Fall an euch zwei!

    Gruß
    Gordon


      

    Betrifft: AW: Grundsätzliche Überlegungen dazu von: Zwenn
    Geschrieben am: 26.04.2017 18:43:13

    Toll,

    schön dass Du eine Lösung gefunden hast :-)

    Viele Grüße,

    Zwenn


    Beiträge aus den Excel-Beispielen zum Thema "Browser Element anspreche - gleiche ID"