none
Filtern / Combobox RRS feed

  • Frage

  • Hallo zusammen.

    Ich würde gerne Daten aus einer Textdatei einlesen, verteilt über 2 Comboboxen. Die gefilterten Daten sollen dann in einer Textbox angezeigt werden. Soweit so gut. Ich habe ein Script bisher fertig, was auch soweit funktioniert, nur bekomme ich dennoch beim Start des Forms Fehler.

    Vielleicht erkennt ja hier jemand den Fehler auf Anhieb, oder vielleicht hat jemand gar noch einen besseren Vorschlag das Einlesen der Daten und das Filtern besser zu gestalten.

    Hier erstmal der Code:

    $x = @()
    $Etagenbezeichnung = '<(.*)>'
    $Raumbezeichnung = '#(.*\d.*)#'
    
    $computerNames = Get-Content $tb_Path.Text |
       ForEach-Object{
          if ($_ -match $Etagenbezeichnung)
          {
             if ($obj) { $obj }
             $key = $matches[1]
             $obj = New-Object PsObject -Property @{ Etage = $key; Systems = @() }
          }
          else { $obj.Systems += $_ }
       }
       
       $computerNames += $obj
       $combobox1.DataSource = [System.Collections.ArrayList]$computerNames
       $combobox1.DisplayMember = 'Etage'
       $combobox1.ValueMember = 'Systems'
       
       #raumdaten anzeigen
       $computerNames_room = Get-Content $tb_Path.Text |
       ForEach-Object{
          if ($_ -match $Raumbezeichnung)
          {
             if ($obj) { $obj }
             $key_room = $matches[1]
             $obj = New-Object PsObject -Property @{ Etage = $key_room; Systems_room = @() }
          }
          else { $obj.Systems_room += $_ }
       }
       
       $computerNames_room += $obj
       $combobox_raum.DataSource = [System.Collections.ArrayList]$computerNames_room
       $combobox_raum.DisplayMember = 'Etage'
       $combobox_raum.ValueMember = 'Systems_room'
    }
    
    
    $combobox1_SelectedIndexChanged = {
       if ($combobox1.SelectedIndex -ge 0)
       {
          $systems = $combobox1.SelectedItem.Systems | ? { -not ($_ -match $Raumbezeichnung) }
          $listbox2.Items.Clear()
          $listbox2.Items.AddRange($Systems)
       }
       if ($combobox1.Text -eq "alle")
       {
          $list_all = (Get-Content -Path $tb_Path.Text) | where { $_ -ne "" } | where { $_.readcount -gt 1 -and $_.readcount -lt 150 } | ? { -not ($_ -match $Etagenbezeichnung) } | ? { -not ($_ -match $Raumbezeichnung) }
          $listbox2.Items.Clear()
          $listbox2.Items.Addrange($list_all)
          
       }
    }
    
    
    $combobox_raum_SelectedIndexChanged = {
       if ($combobox_raum.SelectedIndex -ge 0)
       {
          $systems_room = $combobox_raum.SelectedItem.Systems_room | ? { -not ($_ -match $Etagenbezeichnung) }
          $listbox2.Items.Clear()
          $listbox2.Items.AddRange($Systems_room)
       }
    

    Hier die Fehlermeldungen beim Start des Forms:

    ERROR: Property 'Systems_room' cannot be found on this object; make sure it exists and is settable.
    MainForm.psf (124): ERROR: At Line: 124 char: 15
    ERROR: + else { $obj. <<<< Systems_room += $_ }
    ERROR: + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    ERROR: + FullyQualifiedErrorId : PropertyAssignmentException
    ERROR:
    ERROR: Property 'Systems_room' cannot be found on this object; make sure it exists and is settable.
    
    MainForm.psf (124): ERROR: At Line: 124 char: 15
    ERROR: + else { $obj. <<<< Systems_room += $_ }
    ERROR: + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    ERROR: + FullyQualifiedErrorId : PropertyAssignmentException
    ERROR:
    ERROR: Property 'Systems_room' cannot be found on this object; make sure it exists and is settable.
    
    MainForm.psf (124): ERROR: At Line: 124 char: 15
    ERROR: + else { $obj. <<<< Systems_room += $_ }
    ERROR: + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    ERROR: + FullyQualifiedErrorId : PropertyAssignmentException
    ERROR:
    ERROR: Property 'Systems_room' cannot be found on this object; make sure it exists and is settable.
    
    MainForm.psf (124): ERROR: At Line: 124 char: 15
    ERROR: + else { $obj. <<<< Systems_room += $_ }
    ERROR: + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    ERROR: + FullyQualifiedErrorId : PropertyAssignmentException
    ERROR:
    ERROR: Exception calling "AddRange" with "1" argument(s): "Value cannot be null.
    ERROR: Parameter name: items"
    
    MainForm.psf (156): ERROR: At Line: 156 char: 27
    ERROR: + $listbox2.Items.AddRange <<<< ($Systems_room)
    ERROR: + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    ERROR: + FullyQualifiedErrorId : DotNetMethodException
    ERROR:
    ERROR: Exception calling "AddRange" with "1" argument(s): "Value cannot be null.
    ERROR: Parameter name: items"
    
    MainForm.psf (156): ERROR: At Line: 156 char: 27
    ERROR: + $listbox2.Items.AddRange <<<< ($Systems_room)
    ERROR: + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    ERROR: + FullyQualifiedErrorId : DotNetMethodException
    ERROR:
    ERROR: Exception setting "ValueMember": "Cannot bind to the new value member.
    ERROR: Parameter name: value"
    MainForm.psf (130): ERROR: At Line: 130 char: 17
    ERROR: + $combobox_raum. <<<< ValueMember = 'Systems_room'
    ERROR: + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    ERROR: + FullyQualifiedErrorId : PropertyAssignmentException
    ERROR:

    um es etwas zu erklären. Es besteht eine Textdatei mit einer Liste von Computern. Die Textdatei hat diese Formatierung:

    <2 Etage>
    SCW0201
    SCW0202
    SCW0203
    SCW0204
    #Raum201#
    SCW0213
    SCW0214
    SCW0215
    #Raum202#
    SCW0216
    <3 Etage>
    SCW0301
    SCW0302
    #Raum301#
    SCW0303
    SCW0304

    Die Daten werden eingelesen und über die beiden Comboboxen verteilt gefiltert.
    Combobox 1 soll NUR die Etagen anziehen, also z.B. 2 Etage und klickt man nun auf 2 Etage, werden in der Textbox nur alle PCs der zweiten Etage angezeigt. Combobox 2 zeigt NUR die Räume an.
    Klickt man dagegen in der zweiten Comboxbox auf z.B. Raum 202, werden in der Listbox NUR die PCs im Raum 202 angezeigt. 

    Montag, 2. Juni 2014 09:10

Antworten

  • Hallo agenosko!

    PowerShell Produziert und verarbeitet am liebsten Objekte und nicht Text!

    Deshalb würde ich aus deiner Textdatei erst mal Objekte Formen.
    Du liest die Textdatei auch sehr häufig mit Get-Content ein und parst den Text, das kostet jedes mal Rechenzeit.

    Dies kann man vermeiden in dem man die Texdatei nur einmal einliest und daraus Objekte Formt.
    Ich mache erstelle hier Computerobjekte die die gewünschten Daten enthalten:

    Bitte Probiere diesen Code erst mal außerhalb von deiner Form aus!

    $I = 0
    $Etage = ''
    $Raum = ''
    
    
    $ComputerObjekte = Get-Content '<PfadzurDateiHierEintragen>'  | ForEach-Object {
    
      # Die Aktuell verarbeitete Zeile befindet sich in der Automatisch generierten Variable $_
    
        If($_ -match '<(.*)>') {
        # Die Zeile enthält eine Etagen Angabe
        $Etage = $_.Replace('<','').Replace('>','')
      }  ElseIf($_ -match '#(.*\d.*)#'){
        # Die Zeile enthält eine Raum Angabe
        $Raum = $_.Replace('#','') 
      } Else {
        # Die Zeile enthält eine Computernamem
        $ComputerName = $_
      }
      
      # Ein Objekt aus den gesammelten Daten zusammenbauen und in die Pipeline ausgeben
      # Objekte werden in der Variable $ComputerObjekte gesammelt
      New-Object -TypeName PSobject -Property @{Etage=$Etage;Raum=$Raum;Computername=$ComputerName}
    
    }
    
    
    # nun kann man die Objekte Filtern wie man lustig ist!
    
    Write-Host 'Alle Etagen eindeutig herausfiltern (zum befüllen für die Combobox)'
    $ComputerObjekte | Select-Object -ExpandProperty Etage -Unique
    
    Write-Host 'Alle Räume eindeutig herausfiltern (zum befüllen für die Combobox)'
    $ComputerObjekte | Select-Object -ExpandProperty Raum -Unique
    
    Write-Host 'Alle Computer in der 3. Etage in Raum 301 Herausfiltern'
    $ComputerObjekte | Where-Object { $_.Etage -Like "3 Etage*" -and $_.Raum -like "Raum301*" } | Select-Object -ExpandProperty Computername


    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+

    • Als Antwort vorgeschlagen Alex Pitulice Dienstag, 3. Juni 2014 11:45
    • Als Antwort markiert Alex Pitulice Mittwoch, 18. Juni 2014 13:23
    Montag, 2. Juni 2014 12:04

Alle Antworten

  • Hallo agenosko!

    PowerShell Produziert und verarbeitet am liebsten Objekte und nicht Text!

    Deshalb würde ich aus deiner Textdatei erst mal Objekte Formen.
    Du liest die Textdatei auch sehr häufig mit Get-Content ein und parst den Text, das kostet jedes mal Rechenzeit.

    Dies kann man vermeiden in dem man die Texdatei nur einmal einliest und daraus Objekte Formt.
    Ich mache erstelle hier Computerobjekte die die gewünschten Daten enthalten:

    Bitte Probiere diesen Code erst mal außerhalb von deiner Form aus!

    $I = 0
    $Etage = ''
    $Raum = ''
    
    
    $ComputerObjekte = Get-Content '<PfadzurDateiHierEintragen>'  | ForEach-Object {
    
      # Die Aktuell verarbeitete Zeile befindet sich in der Automatisch generierten Variable $_
    
        If($_ -match '<(.*)>') {
        # Die Zeile enthält eine Etagen Angabe
        $Etage = $_.Replace('<','').Replace('>','')
      }  ElseIf($_ -match '#(.*\d.*)#'){
        # Die Zeile enthält eine Raum Angabe
        $Raum = $_.Replace('#','') 
      } Else {
        # Die Zeile enthält eine Computernamem
        $ComputerName = $_
      }
      
      # Ein Objekt aus den gesammelten Daten zusammenbauen und in die Pipeline ausgeben
      # Objekte werden in der Variable $ComputerObjekte gesammelt
      New-Object -TypeName PSobject -Property @{Etage=$Etage;Raum=$Raum;Computername=$ComputerName}
    
    }
    
    
    # nun kann man die Objekte Filtern wie man lustig ist!
    
    Write-Host 'Alle Etagen eindeutig herausfiltern (zum befüllen für die Combobox)'
    $ComputerObjekte | Select-Object -ExpandProperty Etage -Unique
    
    Write-Host 'Alle Räume eindeutig herausfiltern (zum befüllen für die Combobox)'
    $ComputerObjekte | Select-Object -ExpandProperty Raum -Unique
    
    Write-Host 'Alle Computer in der 3. Etage in Raum 301 Herausfiltern'
    $ComputerObjekte | Where-Object { $_.Etage -Like "3 Etage*" -and $_.Raum -like "Raum301*" } | Select-Object -ExpandProperty Computername


    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+

    • Als Antwort vorgeschlagen Alex Pitulice Dienstag, 3. Juni 2014 11:45
    • Als Antwort markiert Alex Pitulice Mittwoch, 18. Juni 2014 13:23
    Montag, 2. Juni 2014 12:04
  • Erstmal VIELEN DANK für diese Antwort. Dann werde ich mal nachher diesen Code soweit einbauen und versuchen meine Comboboxen damit zu befühlen. 
    Dienstag, 3. Juni 2014 07:01