Sort a listbox

Solved
Erich-Oueb Posted messages 5 Status Membre -  
Erich-Oueb Posted messages 5 Status Membre -

Hello, I am loading a text file (fields separated by ; and no headers) into a listbox. I only take the 1st field and would like to sort it, and if possible avoid duplicates. I tried using Sort-Object | Get-Unique but it doesn't work. Could someone help me?

Here is the code that fills the listbox:

$ListePC = New-Object System.Windows.Forms.ListBox
$ListePC.Location = New-Object System.Drawing.Point(350,40)
$ListePC.Size = New-Object System.Drawing.Size(300,20)
$ListePC.Height = 160
$Computers = Get-Content \\path\Parc.txt
foreach($Computer in $Computers)
 {
  $Zone=$Computer.split(';')
  [void]$ListePC.items.add($Zone[0])
 }
$form.Controls.Add($ListePC)


2 réponses

Bruno83200_6929 Posted messages 707 Registration date   Status Membre Last intervention   168
 

Hello,

To do this, you can use some built-in features of PowerShell.

Get-Content "\\path\Parc.txt" | ForEach-Object { $_.split(';')[0] } extracts the first field from each line.


Sort-Object | Select-Object -Unique sorts the list and removes duplicates.


Then, the foreach loop adds each unique and sorted item to the ListBox.

# Creating the ListBox $ListePC = New-Object System.Windows.Forms.ListBox $ListePC.Location = New-Object System.Drawing.Point(350,40) $ListePC.Size = New-Object System.Drawing.Size(300,20) $ListePC.Height = 160 # Reading the file and extracting the first field $Computers = Get-Content "\\path\Parc.txt" | ForEach-Object { $_.split(';')[0] } # Sorting the items and removing duplicates $UniqueSortedComputers = $Computers | Sort-Object | Select-Object -Unique # Adding the sorted and unique items to the ListBox foreach($Computer in $UniqueSortedComputers) { [void]$ListePC.items.add($Computer) } # Adding the ListBox to the form $form.Controls.Add($ListePC) 

1
Erich-Oueb Posted messages 5 Status Membre
 

Thanks Bruno, plus with the comments it seems so simple. Can I push my luck by complicating the issue: if I want to display in the listbox 2 other fields from the files in addition for example [2] and [3] and only sort based on the [1] field, I think I need to use a listview?

0
Bruno83200_6929 Posted messages 707 Registration date   Status Membre Last intervention   168
 

Yes, if you want to display multiple columns in your graphical interface, like area [2] and area [3] in addition to area [1] while sorting by area [1], a ListView would indeed be more suitable than a ListBox, as it allows for multiple column handling.

Here’s how you can adapt your script to use a ListView with multiple columns and sort the items based solely on the first area (area [0]).

# Creating the ListView $ListView = New-Object System.Windows.Forms.ListView $ListView.Location = New-Object System.Drawing.Point(350,40) $ListView.Size = New-Object System.Drawing.Size(500,200) $ListView.View = [System.Windows.Forms.View]::Details $ListView.FullRowSelect = $true # Adding columns $ListView.Columns.Add("Zone 1", 150) # To display area [0] $ListView.Columns.Add("Zone 2", 150) # To display area [2] $ListView.Columns.Add("Zone 3", 150) # To display area [3] # Reading the file and extracting areas 1, 2, and 3 $Computers = Get-Content "\\path\Parc.txt" | ForEach-Object { $Zone = $_.split(';') [PSCustomObject]@{ Zone1 = $Zone[0] Zone2 = $Zone[2] Zone3 = $Zone[3] } } # Sorting items by Zone1 $SortedComputers = $Computers | Sort-Object Zone1 # Adding sorted items to the ListView foreach($Computer in $SortedComputers) { $item = New-Object System.Windows.Forms.ListViewItem($Computer.Zone1) $item.SubItems.Add($Computer.Zone2) $item.SubItems.Add($Computer.Zone3) [void]$ListView.Items.Add($item) } # Adding the ListView to the form $form.Controls.Add($ListView) 

The ListView is configured with three columns (Zone 1, Zone 2, Zone 3).
The display mode is set to Details to show the columns.
FullRowSelect allows for entire row selection.

The file is read and transformed into custom objects (PSCustomObject) with three properties: Zone1, Zone2, and Zone3 corresponding to areas [0], [2], and [3] of the file.

Sort-Object Zone1 sorts the items solely based on the first area (Zone1).
 

For each sorted item, a ListViewItem object is created with the first area as the main item, and the other two areas are added as SubItems.


0
Erich-Oueb Posted messages 5 Status Membre
 

Great, I just needed $ListView.Height = 160 (otherwise, we could only see the column headers). However, a silly thing, I can't find how to retrieve the selected Zone1 in a variable? For example, below, it shows me blank. I tried using .text or .value properties but no better.

if ($ListView.SelectedItems) {

    $NomPC = $ListView.SelectedItems.items[0]
    [System.Windows.Forms.MessageBox]::Show($NomPC)

}

0
Bruno83200_6929 Posted messages 707 Registration date   Status Membre Last intervention   168 > Erich-Oueb Posted messages 5 Status Membre
 

To retrieve the selected item from a ListView, the correct method is to access the Text property of the selected item. The problem in your example is that you are trying to access items[0] which does not exist at this stage.

Here is how you can correctly retrieve the value of Zone1 (the first column) of the selected item:

if ($ListView.SelectedItems.Count -gt 0) { # Retrieve the text of the first column (Zone1) of the selected item $NomPC = $ListView.SelectedItems[0].Text [System.Windows.Forms.MessageBox]::Show($NomPC) } else { [System.Windows.Forms.MessageBox]::Show("No item selected.") } 

If you want to retrieve the values from the other columns (for example, Zone2 and Zone3), you can use the SubItems property:

if ($ListView.SelectedItems.Count -gt 0) { $NomPC = $ListView.SelectedItems[0].Text # Zone 1 $Zone2 = $ListView.SelectedItems[0].SubItems[1].Text # Zone 2 $Zone3 = $ListView.SelectedItems[0].SubItems[2].Text # Zone 3 [System.Windows.Forms.MessageBox]::Show("Zone 1: $NomPC`nZone 2: $Zone2`nZone 3: $Zone3") } 

$ListView.SelectedItems[0].SubItems[1].Text accesses Zone2 (index 1).


$ListView.SelectedItems[0].SubItems[2].Text accesses Zone3 (index 2).


Thus, you will be able to display the different selected zones in a message box.

0
Bruno83200_6929 Posted messages 707 Registration date   Status Membre Last intervention   168 > Bruno83200_6929 Posted messages 707 Registration date   Status Membre Last intervention  
 
if ($ListView.SelectedItems.Count -gt 0) { # Retrieve the values from the different areas of the selected item $Zone1 = $ListView.SelectedItems[0].Text # Zone 1 $Zone2 = $ListView.SelectedItems[0].SubItems[1].Text # Zone 2 $Zone3 = $ListView.SelectedItems[0].SubItems[2].Text # Zone 3 # Display the zones in a message box [System.Windows.Forms.MessageBox]::Show("Zone 1: $Zone1`nZone 2: $Zone2`nZone 3: $Zone3") } else { # Message if no item is selected [System.Windows.Forms.MessageBox]::Show("No item selected.") } 


0
Erich-Oueb Posted messages 5 Status Membre > Bruno83200_6929 Posted messages 707 Registration date   Status Membre Last intervention  
 

Indeed, it works well like that and I was even able to add the option to sort by clicking on the headers -> thanks again for pointing me in the right direction, it's great!

0