derhoeppi
Goto Top

Powershell Funktion zum Konvertieren einer Datatable zu einem Array

Hallo,
ich habe ein Datagridview mit einer Datatable als Quelle. Bei dieser kann Einträge hinzufügen, verändern und löschen. Wenn ich mir zur weiteren Verarbeitung die Daten des Datagridviews bzw. der Datatable ausgeben möchte (Write-Host $Datatable) dann erhalte ich pro Zeile die Ausgabe System.Data.DataRow. Damit kann ich natürlich nichts anfangen.

Vor wenigen Jahren hatte ich ein ähnliches Projekt, wobei statt einen DGV ein ListView verwendet wurde. Dort habe ich dann die Elemente des LV durchiteriert und diese einem Array hinzugefügt. Das hat soweit ganz gut funktioniert. Der Nachteil an dem Code war jedoch das ich pro Listview den Code für das durchiterieren setzen muss.

Für das DGV möchte ich das durchiterieren, sofern es notwendig ist, gerne in eine Funktion auslagern, bei der ich das DGV oder die Datatable übergebe und als Rückgabe ein Array mit den Werten erhalte. Mit dieser Funktion habe ich bereits angefangen. Aktuell übergebe ich das DGV (wobei das keinen Unterschied zur Datatable sein sollte) und kann in der Funktion mit dem DGV arbeiten. So habe ich mir die Anzahl der Spalten ausgeben lassen.

Nun stehe ich jedoch vor dem Problem folgendes variable zu gestalten:

$dt.Rows | %{
        $cols = $_.ItemArray
        $ArrayDatatable += New-Object PSObject -Property @{"Titel1"=$cols;"Title2"=$cols[1];"Title3"=$cols[2];"Title4"=$cols[3]}  
        }

Das Problem ist das ich mir via $dt.Columns die Anzahl der Spalten und deren Bezeichnung ausgeben kann. Wie aber kann ich dieses variable gestalten, sodass die Property Eigenschaft des New-Object den Spalten entsprechend lang wird. Hintergrund ist das ich mal eine Datatable mit einer unterschiedlichen Spaltenanzahl unterbringe und den Code nicht pro Datatable vorhalten möchte - zumal ich doppelt editieren müsste, wenn sich mal eine Spalte umbenennt.

Content-Key: 393184

Url: https://administrator.de/contentid/393184

Ausgedruckt am: 19.03.2024 um 01:03 Uhr

Mitglied: 137846
Lösung 137846 18.11.2018 aktualisiert um 14:02:57 Uhr
Goto Top
Zitat von @derhoeppi:

Bei dieser kann Einträge hinzufügen, verändern und löschen. Wenn ich mir zur weiteren Verarbeitung die Daten des Datagridviews bzw. der Datatable ausgeben möchte (Write-Host $Datatable) dann erhalte ich pro Zeile die Ausgabe System.Data.DataRow. Damit kann ich natürlich nichts anfangen.
Logisch, eine Datatable besteht nun mal aus DataRows, deren Inhalt musst du nur anzeigen indem sie die Daten der Spalten abrufts face-wink.



Nun stehe ich jedoch vor dem Problem folgendes variable zu gestalten:

> 
> $dt.Rows | %{
>         $cols = $_.ItemArray
>         $ArrayDatatable += New-Object PSObject -Property @{"Titel1"=$cols;"Title2"=$cols[1];"Title3"=$cols[2];"Title4"=$cols[3]}  
>         }
> 

Das Problem ist das ich mir via $dt.Columns die Anzahl der Spalten und deren Bezeichnung ausgeben kann. Wie aber kann ich dieses variable gestalten, sodass die Property Eigenschaft des New-Object den Spalten entsprechend lang wird. Hintergrund ist das ich mal eine Datatable mit einer unterschiedlichen Spaltenanzahl unterbringe und den Code nicht pro Datatable vorhalten möchte - zumal ich doppelt editieren müsste, wenn sich mal eine Spalte umbenennt.
Ich sehe da nicht wirklich ein Problem, die Rows hast du, die Columns im $dt Objekt auch, also einfach für jede Row in einer Schleife über die Columns die Inhalte einer Hashtable hinzufügen und daraus ein Object machen.
$dt.Rows | %{
    $row = $_
    $rht = @{}
    0..($dt.Columns.Count-1) | %{$rht.($dt.Columns[$_]) = $row[$_]}
    [pscustomobject]$rht
}
Fertig ist die Tabelle. Oder eben das ganze einer ArrayList zuweisen.
Mitglied: derhoeppi
derhoeppi 18.11.2018 um 14:19:22 Uhr
Goto Top
Danke.

das foreach in foreach war mir schon bewusst. Ich bin nur nicht auf die Idee gekommen das so kurz und charmant mit dem hochzählen zu machen (0..($dt.Columns.Count-1)).
Mitglied: derhoeppi
derhoeppi 18.11.2018 um 17:54:34 Uhr
Goto Top
Hallo,

jetzt muss ich das doch noch einmal aufgreifen, weil ich in der Bearbeitung Probleme habe.

$dt.Rows | %{
    $row = $_
    $rht = @{}
    0..($dt.Columns.Count-1) | %{$rht.($dt.Columns[$_]) = $row[$_]}
    [pscustomobject]$rht
}

Nur zu meinem Verständnis. Du iterierst durch die Zeilen und steckst die Key / Value Paare der Spalten in eine Hashtable. Mit " [pscustomobject]$rht" machst du aus der Hashtable ein PowerShell-Objekt. Dieses Objekt habe ich nun genommen und in ein Array gepackt. Das habe ich Analog dem gemacht - was ich damals für mein ListView Element durchgeführt habe. Mein Code sieht also jetzt so aus:

$ArrayDatatable = @()
$dt.Rows | %{
    $row = $_
    $rht = @{}
    0..($dt.Columns.Count-1) | %{$rht.($dt.Columns[$_]) = $row[$_]}
    [pscustomobject]$rht
   $ArrayDatatable += [pscustomobject]$rht
}
Wenn ich mir das nun ausgeben lasse, erhalte ich wunderbar die Key / Value Paare. Wenn meine Datatable mehrere Zeilen hat, bekomme ich als Ausgabe jede Zeile in einem eigenen Array. Lasse ich mir den BaseType von $ArrayDatatable ausgeben wird es mir als System.Array ausgegeben. Für mich bedeutet es das es eigentlich passen müsste. Mein Ziel ist jedoch eine kleine Tabelle aufzubauen, so dass es ebenso eine Tabelle ist als ob ich $test = get-process aufrufe.

Mein Hirn hinkt also momentan hinterher was der Unterschied zwischen "$ArrayDatatable += New-Object PSObject -Property @{"Titel1"=$cols;"Title2"=$cols[1];"Title3"=$cols[2];"Title4"=$cols[3]} " und dem "$ArrayDatatable += [pscustomobject]$rht" ist? Vielleicht kannst du hier noch einmal mit einem Tipp helfen.
Mitglied: 137846
137846 18.11.2018 aktualisiert um 19:04:37 Uhr
Goto Top
bekomme ich als Ausgabe jede Zeile in einem eigenen Array
Dann machst du einen Fehler oder hast deine Variable in der ISE noch als anderen Typ deklariert.
Mein Hirn hinkt also momentan hinterher was der Unterschied zwischen "$ArrayDatatable += New-Object PSObject -Property @{"Titel1"=$cols;"Title2"=$cols[1];"Title3"=$cols[2];"Title4"=$cols[3]} " und dem "$ArrayDatatable += [pscustomobject]$rht" ist
Ist exakt das selbe, das letzte ist nur eine Abkürzung und seit PS3.0 eingeführt und etwas schneller beim Erzeugen. In deinem PSObject nutzt du ja auch eine Hashtable als Property. Heraus kommt bei beiden ein CustomObject, welches du dann einem Array hinzufügt, also alles kein Hexenwerk.
Ziel ist jedoch eine kleine Tabelle aufzubauen, so dass es ebenso eine Tabelle ist als ob ich $test = get-process aufrufe.
Das ist keine Tabelle das sind immer Arrays aus Objekten!!

Siehe das Beispiel
https://tio.run/##fZBBC4JAEIXv@yv2YKiQS3YPKjsX5FFEtpyKWF1xZxGxfrvtWkEhNY ...

Denn get-process etc liefern dir auch nur Arrays aus Objekten eben nur anderer Klassen, hier ist es nur eben nur ein CustomObject mit selbst definierten Eigenschaften und/oder Methoden.

Thema erledigt.
Mitglied: derhoeppi
derhoeppi 18.11.2018 um 19:40:40 Uhr
Goto Top
Hi,

nach deinem letzten Post bestätigst du mir zumindest das ich es richtig verstehe. Trotzdem funktioniert es nicht in meinem Code. Wenn ich deinen wiederum in eine leere Datei bringe und ausführe, sieht es wie gewollt aus. Ich finde jedoch nicht den Unterschied warum es bei mir nicht geht.
Aus diesem Grund mal mein Script mit dem DGV, damit man es als komplettes nachvollziehen kann.

function Show-DatagridviewExampleDatatable_psf {

	#----------------------------------------------
	#region Import the Assemblies
	#----------------------------------------------
	[void][reflection.assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')  
	[void][reflection.assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')  
	#endregion Import Assemblies

	#----------------------------------------------
	#region Generated Form Objects
	#----------------------------------------------
	[System.Windows.Forms.Application]::EnableVisualStyles()
	$form1 = New-Object 'System.Windows.Forms.Form'  
	$buttonEdit = New-Object 'System.Windows.Forms.Button'  
	$buttonAdd = New-Object 'System.Windows.Forms.Button'  
	$labelValue2 = New-Object 'System.Windows.Forms.Label'  
	$labelValue3 = New-Object 'System.Windows.Forms.Label'  
	$labelValue1 = New-Object 'System.Windows.Forms.Label'  
	$textboxValue2 = New-Object 'System.Windows.Forms.TextBox'  
	$textboxValue3 = New-Object 'System.Windows.Forms.TextBox'  
	$textboxValue1 = New-Object 'System.Windows.Forms.TextBox'  
	$datagridview1 = New-Object 'System.Windows.Forms.DataGridView'  
	$buttonClose = New-Object 'System.Windows.Forms.Button'  
	$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'  
	#endregion Generated Form Objects

	#----------------------------------------------
	# User Generated Script
	#----------------------------------------------
	#Create datatable as datasource for datagridview
	$dtValues = New-Object System.Data.Datatable
	$dtValues.Columns.Add('Value1', [string])  
	$dtValues.Columns.Add('Value2', [string])  
	$dtValues.Columns.Add('Value3', [string])  
	$dtValues.Columns.Add('Value4', [string])  
	
	[void]$dtValues.Rows.Add("1", "2", "3", "4")  
	
	$datagridview1.DataSource = $dtValues
	
	$form1_Load={
		#TODO: Initialize Form Controls here
	}
	
	#region Control Helper Functions

	FUNCTION Get-DatatableData
	{
		[CmdletBinding()]
		PARAM
		(
			[Parameter(Mandatory = $true)]
			[System.Data.DataTable]$Datatable
		)
		
		#TODO: Place script here
		$UD_DGV_Data = @()
		$UD_DGV_Data = $Datatable.Rows | %{
			$row = $_
			$rht = @{ }
			0 .. ($Datatable.Columns.Count - 1) | %{ $rht.($Datatable.Columns[$_]) = $row[$_] }
			[pscustomobject]$rht
			
		}
		RETURN $UD_DGV_Data
	}
	
	#endregion
	
	$buttonEdit_Click={
		#TODO: Place custom script here
		IF ($buttonEdit.Text -eq "Edit")  
		{
			$textboxValue1.Text = $datagridview1.SelectedRows.Cells.Value
			$textboxValue2.Text = $datagridview1.SelectedRows.Cells[1].Value
			$textboxValue3.Text = $datagridview1.SelectedRows.Cells[2].Value
			$buttonAdd.Text = "Abort"  
			$buttonEdit.Text = "Save"  
		}
		ELSE
		{
			$UD_DGV_User = Get-DatatableData -Datatable $dtValues
			Write-Host $UD_DGV_User
			$buttonAdd.Text = "Add"  
			$buttonEdit.Text = "Edit"  
		}
	}
	
	$buttonAdd_Click={
		#TODO: Place custom script here
		IF ($buttonAdd.Text -eq "Add")  
		{
			$ValuesAdd = $dtValues.NewRow()
			$ValuesAdd['Value1'] = $textboxValue1.Text  
			$ValuesAdd['Value2'] = $textboxValue2.Text  
			$ValuesAdd['Value3'] = $textboxValue3.Text  
			$dtValues.Rows.Add($ValuesAdd)
			$textboxValue1.Text = ""  
			$textboxValue2.Text = ""  
			$textboxValue3.Text = ""  
		}
		ELSE
		{
			$textboxValue1.Text = ""  
			$textboxValue2.Text = ""  
			$textboxValue3.Text = ""  
			$buttonAdd.Text = "Add"  
			$buttonEdit.Text = "Edit"  
		}
	}
	
	# --End User Generated Script--
	#----------------------------------------------
	#region Generated Events
	#----------------------------------------------
	
	$Form_StateCorrection_Load=
	{
		#Correct the initial state of the form to prevent the .Net maximized form issue
		$form1.WindowState = $InitialFormWindowState
	}
	
	$Form_Cleanup_FormClosed=
	{
		#Remove all event handlers from the controls
		try
		{
			$buttonEdit.remove_Click($buttonEdit_Click)
			$buttonAdd.remove_Click($buttonAdd_Click)
			$form1.remove_Load($form1_Load)
			$form1.remove_Load($Form_StateCorrection_Load)
			$form1.remove_FormClosed($Form_Cleanup_FormClosed)
		}
		catch { Out-Null <# Prevent PSScriptAnalyzer warning #> }
	}
	#endregion Generated Events

	#----------------------------------------------
	#region Generated Form Code
	#----------------------------------------------
	$form1.SuspendLayout()
	#
	# form1
	#
	$form1.Controls.Add($buttonEdit)
	$form1.Controls.Add($buttonAdd)
	$form1.Controls.Add($labelValue2)
	$form1.Controls.Add($labelValue3)
	$form1.Controls.Add($labelValue1)
	$form1.Controls.Add($textboxValue2)
	$form1.Controls.Add($textboxValue3)
	$form1.Controls.Add($textboxValue1)
	$form1.Controls.Add($datagridview1)
	$form1.Controls.Add($buttonClose)
	$form1.AutoScaleDimensions = '6, 13'  
	$form1.AutoScaleMode = 'Font'  
	$form1.ClientSize = '606, 261'  
	$form1.MaximizeBox = $False
	$form1.MinimizeBox = $False
	$form1.Name = 'form1'  
	$form1.ShowIcon = $False
	$form1.Text = 'Form'  
	$form1.add_Load($form1_Load)
	#
	# buttonEdit
	#
	$buttonEdit.Anchor = 'Bottom, Right'  
	$buttonEdit.Location = '385, 226'  
	$buttonEdit.Name = 'buttonEdit'  
	$buttonEdit.Size = '66, 23'  
	$buttonEdit.TabIndex = 25
	$buttonEdit.Text = 'Edit'  
	$buttonEdit.UseCompatibleTextRendering = $True
	$buttonEdit.UseVisualStyleBackColor = $True
	$buttonEdit.add_Click($buttonEdit_Click)
	#
	# buttonAdd
	#
	$buttonAdd.Anchor = 'Bottom, Right'  
	$buttonAdd.Location = '457, 226'  
	$buttonAdd.Name = 'buttonAdd'  
	$buttonAdd.Size = '66, 23'  
	$buttonAdd.TabIndex = 24
	$buttonAdd.Text = 'Add'  
	$buttonAdd.UseCompatibleTextRendering = $True
	$buttonAdd.UseVisualStyleBackColor = $True
	$buttonAdd.add_Click($buttonAdd_Click)
	#
	# labelValue2
	#
	$labelValue2.AutoSize = $True
	$labelValue2.Location = '464, 69'  
	$labelValue2.Name = 'labelValue2'  
	$labelValue2.Size = '40, 17'  
	$labelValue2.TabIndex = 21
	$labelValue2.Text = 'Value2'  
	$labelValue2.UseCompatibleTextRendering = $True
	#
	# labelValue3
	#
	$labelValue3.AutoSize = $True
	$labelValue3.Location = '463, 115'  
	$labelValue3.Name = 'labelValue3'  
	$labelValue3.Size = '40, 17'  
	$labelValue3.TabIndex = 20
	$labelValue3.Text = 'Value3'  
	$labelValue3.UseCompatibleTextRendering = $True
	#
	# labelValue1
	#
	$labelValue1.AutoSize = $True
	$labelValue1.Location = '464, 26'  
	$labelValue1.Name = 'labelValue1'  
	$labelValue1.Size = '40, 17'  
	$labelValue1.TabIndex = 19
	$labelValue1.Text = 'Value1'  
	$labelValue1.UseCompatibleTextRendering = $True
	#
	# textboxValue2
	#
	$textboxValue2.Location = '464, 89'  
	$textboxValue2.Name = 'textboxValue2'  
	$textboxValue2.Size = '121, 20'  
	$textboxValue2.TabIndex = 17
	#
	# textboxValue3
	#
	$textboxValue3.Location = '463, 135'  
	$textboxValue3.Name = 'textboxValue3'  
	$textboxValue3.Size = '122, 20'  
	$textboxValue3.TabIndex = 18
	#
	# textboxValue1
	#
	$textboxValue1.Location = '463, 46'  
	$textboxValue1.Name = 'textboxValue1'  
	$textboxValue1.Size = '122, 20'  
	$textboxValue1.TabIndex = 15
	#
	# datagridview1
	#
	$datagridview1.AllowUserToAddRows = $False
	$datagridview1.ColumnHeadersHeightSizeMode = 'AutoSize'  
	$datagridview1.Location = '12, 12'  
	$datagridview1.Name = 'datagridview1'  
	$datagridview1.ReadOnly = $True
	$datagridview1.SelectionMode = 'FullRowSelect'  
	$datagridview1.ShowEditingIcon = $False
	$datagridview1.Size = '445, 206'  
	$datagridview1.TabIndex = 13
	#
	# buttonClose
	#
	$buttonClose.Anchor = 'Bottom, Right'  
	$buttonClose.CausesValidation = $False
	$buttonClose.DialogResult = 'Cancel'  
	$buttonClose.Location = '529, 226'  
	$buttonClose.Name = 'buttonClose'  
	$buttonClose.Size = '75, 23'  
	$buttonClose.TabIndex = 14
	$buttonClose.Text = '&Close'  
	$buttonClose.UseCompatibleTextRendering = $True
	$buttonClose.UseVisualStyleBackColor = $True
	$form1.ResumeLayout()
	#endregion Generated Form Code

	#----------------------------------------------

	#Save the initial state of the form
	$InitialFormWindowState = $form1.WindowState
	#Init the OnLoad event to correct the initial state of the form
	$form1.add_Load($Form_StateCorrection_Load)
	#Clean up the control events
	$form1.add_FormClosed($Form_Cleanup_FormClosed)
	#Show the Form
	return $form1.ShowDialog()

} #End Function

#Call the form
Show-DatagridviewExampleDatatable_psf | Out-Null

Es wäre super, wenn du das mal kurz bei Dir ausführen könntest. Das starten einer neuen PowerShell Session bewirkt bei mir leider keine Veränderung.
Mitglied: 137846
137846 18.11.2018 aktualisiert um 21:35:54 Uhr
Goto Top
Zeile 38 ist dein Fehler. Die muss so aussehen:
[void]$dtValues.Rows.Add(@("1", "2", "3", "4"))   
Du willst ja ein Array für die Spalten übergeben und nicht 4 Parameter.

Außerdem ist Zeile 58 überflüssig.

Alles in allem ist das doch viel zu umständlich gedacht was du da machst. Eine Hashtable die mit einem Datagridview verbunden ist, ist automatisch synchron wenn man das Datagrid und dessen Items verändert! Da hatte mein Vorposter in deinem letzten Thread absolut recht.
Mitglied: derhoeppi
derhoeppi 19.11.2018 um 07:37:23 Uhr
Goto Top
Das heißt es liegt nur an dieser einen Zeile. Danke - aber was lief denn dann falsch, wenn ich Einträge über den Add Button hinzufüge? Diese wurden auch nicht vernünftig hinzugefügt.

Wenn ich ganz ehrlich bin, habe ich die Antwort in meinem letzten Thread nicht ganz verstanden. Ich habe meine Datatable als Datasource im DGV verknüpft. In der Antwort vom letzten Thread habe stand, dass ich ein Binding aktivieren soll. Wo aber ist der Unterschied? Aus den verlinkten URL's bin ich ebenso nicht schlau geworden.
Vielleicht kannst du es mir kurz erläutern. Am liebsten möchte ich nur die Datatable pflegen und analog einem Array Werte hinzufügen, verändern und löschen. Das habe ich zwar inzwischen hinbekommen, aber bei der Ausgabe von der Datatable habe ich immer nur system.data.datarow als Wert erhalten. Wenn ich mir aber Artikel bei MXFAQ ansehe, funktioniert es analog einem Array. Und genau das habe ich nicht hinbekommen. Deshalb bin ich jetzt wieder den Umweg über ein separates Array gegangen.
Mitglied: 137846
137846 19.11.2018 um 14:02:20 Uhr
Goto Top
Zitat von @derhoeppi:

Das heißt es liegt nur an dieser einen Zeile. Danke - aber was lief denn dann falsch, wenn ich Einträge über den Add Button hinzufüge? Diese wurden auch nicht vernünftig hinzugefügt.

Wenn ich ganz ehrlich bin, habe ich die Antwort in meinem letzten Thread nicht ganz verstanden. Ich habe meine Datatable als Datasource im DGV verknüpft. In der Antwort vom letzten Thread habe stand, dass ich ein Binding aktivieren soll. Wo aber ist der Unterschied? Aus den verlinkten URL's bin ich ebenso nicht schlau geworden.
Vielleicht kannst du es mir kurz erläutern. Am liebsten möchte ich nur die Datatable pflegen und analog einem Array Werte hinzufügen, verändern und löschen. Das habe ich zwar inzwischen hinbekommen, aber bei der Ausgabe von der Datatable habe ich immer nur system.data.datarow als Wert erhalten. Wenn ich mir aber Artikel bei MXFAQ ansehe, funktioniert es analog einem Array. Und genau das habe ich nicht hinbekommen. Deshalb bin ich jetzt wieder den Umweg über ein separates Array gegangen.

Du scheinst das mit der Objektorientierten Programmierung noch nicht ganz verinnerlicht zu haben. Eine Datatable ist ein Objekt, das hat Eigenschaften wie die Rows Eigenschaft die selbst ein Array ist, also Objekte vom Typ DataRow beinhaltet, dieses kannst du in Powershell wie gehabt entweder mit Schleifen durchlaufen oder auch direkt mit Index [n] hinter der Eigenschaft ansprechen. Die Spaltennamen der Datarows kannst du in Powershell direkt mit Ihren Namen als Eigenschaft des Objekts ansprechen.

Hier mal zusammengefasst, das siehst du das wie es geht: Füge ein paar Rows hinzu und klicke dann auf irgendeine Zeile im DGV doppelt mit der Maus dann bekommst du Beispiele der verknüpften Datatable aus dem Gridview angezeigt. Daran siehst du das die Datatable immer synchron mit dem DGV ist wenn sie per DataSource verknüpft ist.
function Show-DatagridviewExampleDatatable_psf {

	#----------------------------------------------
	#region Import the Assemblies
	#----------------------------------------------
	[void][reflection.assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')  
	[void][reflection.assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')  
	#endregion Import Assemblies

	#----------------------------------------------
	#region Generated Form Objects
	#----------------------------------------------
	[System.Windows.Forms.Application]::EnableVisualStyles()
	$form1 = New-Object 'System.Windows.Forms.Form'  
	$buttonEdit = New-Object 'System.Windows.Forms.Button'  
	$buttonAdd = New-Object 'System.Windows.Forms.Button'  
    $buttonDelete = New-Object System.Windows.Forms.Button
	$labelValue2 = New-Object 'System.Windows.Forms.Label'  
	$labelValue3 = New-Object 'System.Windows.Forms.Label'  
	$labelValue1 = New-Object 'System.Windows.Forms.Label'  
	$textboxValue2 = New-Object 'System.Windows.Forms.TextBox'  
	$textboxValue3 = New-Object 'System.Windows.Forms.TextBox'  
	$textboxValue1 = New-Object 'System.Windows.Forms.TextBox'  
	$datagridviewProjectUser = New-Object 'System.Windows.Forms.DataGridView'  
	$buttonClose = New-Object 'System.Windows.Forms.Button'  
	$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'  
	#endregion Generated Form Objects

	#----------------------------------------------
	# User Generated Script
	#----------------------------------------------
    $global:cEditIndex = -1


	#Create datatable as datasource for datagridview
	$dtValues = New-Object System.Data.DataTable
	$dtValues.Columns.Add('Value1', [string])  
	$dtValues.Columns.Add('Value2', [string])  
	$dtValues.Columns.Add('Value3', [string])  
	$datagridviewProjectUser.DataSource = $dtValues
	
	$form1_Load={
		
		
	}

    $buttonDelete_Click = {
        $datagridviewProjectUser.SelectedRows | %{$datagridviewProjectUser.Rows.RemoveAt($_.Index)}
    }
	
	$buttonEdit_Click={
		IF ($buttonEdit.Text -eq "Edit")  
		{
            # das ist der Index des DG den wir bearbeiten
            $global:cEditIndex = $datagridviewProjectUser.SelectedRows.Index
			$textboxValue1.Text = $datagridviewProjectUser.SelectedRows.Cells.Value
			$textboxValue2.Text = $datagridviewProjectUser.SelectedRows.Cells[1].Value
			$textboxValue3.Text = $datagridviewProjectUser.SelectedRows.Cells[2].Value
			$buttonAdd.Text = "Abort"  
			$buttonEdit.Text = "Save"  
		}
		ELSE
		{
            $datagridviewProjectUser.Rows[$global:cEditIndex].Cells.Value = $textboxValue1.Text
            $datagridviewProjectUser.Rows[$global:cEditIndex].Cells[1].Value = $textboxValue2.Text
            $datagridviewProjectUser.Rows[$global:cEditIndex].Cells[2].Value = $textboxValue3.Text
            $textboxValue1.Text = ""  
			$textboxValue2.Text = ""  
			$textboxValue3.Text = ""  
			$buttonAdd.Text = "Add"  
			$buttonEdit.Text = "Edit"  
		}
	}
	
	$buttonAdd_Click={
		
		IF ($buttonAdd.Text -eq "Add")  
		{
			$ValuesAdd = $dtValues.NewRow()
			$ValuesAdd['Value1'] = $textboxValue1.Text  
			$ValuesAdd['Value2'] = $textboxValue2.Text  
			$ValuesAdd['Value3'] = $textboxValue3.Text  
			$dtValues.Rows.Add($ValuesAdd)
			$textboxValue1.Text = ""  
			$textboxValue2.Text = ""  
			$textboxValue3.Text = ""  
		}
		ELSE
		{
			$textboxValue1.Text = ""  
			$textboxValue2.Text = ""  
			$textboxValue3.Text = ""  
			$buttonAdd.Text = "Add"  
			$buttonEdit.Text = "Edit"  
		}
	}
	
	# --End User Generated Script--
	#----------------------------------------------
	#region Generated Events
	#----------------------------------------------
	
	$Form_StateCorrection_Load=
	{
		#Correct the initial state of the form to prevent the .Net maximized form issue
		$form1.WindowState = $InitialFormWindowState
	}
	
	$Form_Cleanup_FormClosed=
	{
		#Remove all event handlers from the controls
		try
		{
			$buttonEdit.remove_Click($buttonEdit_Click)
			$buttonAdd.remove_Click($buttonAdd_Click)
			$form1.remove_Load($form1_Load)
			$form1.remove_Load($Form_StateCorrection_Load)
			$form1.remove_FormClosed($Form_Cleanup_FormClosed)
		}
		catch { Out-Null <# Prevent PSScriptAnalyzer warning #> }
	}
	#endregion Generated Events

	#----------------------------------------------
	#region Generated Form Code
	#----------------------------------------------
	$form1.SuspendLayout()
	#
	# form1
	#
    $form1.Controls.Add($buttonDelete)
    $form1.Controls.Add($buttonEdit)
	$form1.Controls.Add($buttonAdd)
	$form1.Controls.Add($labelValue2)
	$form1.Controls.Add($labelValue3)
	$form1.Controls.Add($labelValue1)
	$form1.Controls.Add($textboxValue2)
	$form1.Controls.Add($textboxValue3)
	$form1.Controls.Add($textboxValue1)
	$form1.Controls.Add($datagridviewProjectUser)
	$form1.Controls.Add($buttonClose)
	$form1.AutoScaleDimensions = '6, 13'  
	$form1.AutoScaleMode = 'Font'  
	$form1.ClientSize = '606, 261'  
	$form1.MaximizeBox = $False
	$form1.MinimizeBox = $False
	$form1.Name = 'form1'  
	$form1.ShowIcon = $False
	$form1.Text = 'Form'  
	$form1.add_Load($form1_Load)
	
    #
	# buttonDelete
	#
	$buttonDelete.Anchor = 'Bottom, Right'  
	$buttonDelete.Location = '310, 226'  
	$buttonDelete.Name = 'buttonEdit'  
	$buttonDelete.Size = '66, 23'  
	$buttonDelete.TabIndex = 25
	$buttonDelete.Text = 'Delete'  
	$buttonDelete.UseCompatibleTextRendering = $True
	$buttonDelete.UseVisualStyleBackColor = $True
	$buttonDelete.add_Click($buttonDelete_Click)
    $buttonDelete.Enabled = $false
    #
	# buttonEdit
	#
	$buttonEdit.Anchor = 'Bottom, Right'  
	$buttonEdit.Location = '385, 226'  
	$buttonEdit.Name = 'buttonEdit'  
	$buttonEdit.Size = '66, 23'  
	$buttonEdit.TabIndex = 25
	$buttonEdit.Text = 'Edit'  
	$buttonEdit.UseCompatibleTextRendering = $True
	$buttonEdit.UseVisualStyleBackColor = $True
	$buttonEdit.add_Click($buttonEdit_Click)
    $buttonEdit.Enabled = $false
	#
	# buttonAdd
	#
	$buttonAdd.Anchor = 'Bottom, Right'  
	$buttonAdd.Location = '457, 226'  
	$buttonAdd.Name = 'buttonAdd'  
	$buttonAdd.Size = '66, 23'  
	$buttonAdd.TabIndex = 24
	$buttonAdd.Text = 'Add'  
	$buttonAdd.UseCompatibleTextRendering = $True
	$buttonAdd.UseVisualStyleBackColor = $True
	$buttonAdd.add_Click($buttonAdd_Click)
	#
	# labelValue2
	#
	$labelValue2.AutoSize = $True
	$labelValue2.Location = '464, 69'  
	$labelValue2.Name = 'labelValue2'  
	$labelValue2.Size = '40, 17'  
	$labelValue2.TabIndex = 21
	$labelValue2.Text = 'Value2'  
	$labelValue2.UseCompatibleTextRendering = $True
	#
	# labelValue3
	#
	$labelValue3.AutoSize = $True
	$labelValue3.Location = '463, 115'  
	$labelValue3.Name = 'labelValue3'  
	$labelValue3.Size = '40, 17'  
	$labelValue3.TabIndex = 20
	$labelValue3.Text = 'Value3'  
	$labelValue3.UseCompatibleTextRendering = $True
	#
	# labelValue1
	#
	$labelValue1.AutoSize = $True
	$labelValue1.Location = '464, 26'  
	$labelValue1.Name = 'labelValue1'  
	$labelValue1.Size = '40, 17'  
	$labelValue1.TabIndex = 19
	$labelValue1.Text = 'Value1'  
	$labelValue1.UseCompatibleTextRendering = $True
	#
	# textboxValue2
	#
	$textboxValue2.Location = '464, 89'  
	$textboxValue2.Name = 'textboxValue2'  
	$textboxValue2.Size = '121, 20'  
	$textboxValue2.TabIndex = 17
	#
	# textboxValue3
	#
	$textboxValue3.Location = '463, 135'  
	$textboxValue3.Name = 'textboxValue3'  
	$textboxValue3.Size = '122, 20'  
	$textboxValue3.TabIndex = 18
	#
	# textboxValue1
	#
	$textboxValue1.Location = '463, 46'  
	$textboxValue1.Name = 'textboxValue1'  
	$textboxValue1.Size = '122, 20'  
	$textboxValue1.TabIndex = 15
	#
	# datagridviewProjectUser
	#
	$datagridviewProjectUser.AllowUserToAddRows = $False
	$datagridviewProjectUser.ColumnHeadersHeightSizeMode = 'AutoSize'  
	$datagridviewProjectUser.Location = '12, 12'  
	$datagridviewProjectUser.Name = 'datagridviewProjectUser'  
	$datagridviewProjectUser.ReadOnly = $True
	$datagridviewProjectUser.SelectionMode = 'FullRowSelect'  
	$datagridviewProjectUser.ShowEditingIcon = $False
	$datagridviewProjectUser.Size = '445, 206'  
	$datagridviewProjectUser.TabIndex = 13
    $datagridviewProjectUser.add_SelectionChanged({
        if ($datagridviewProjectUser.SelectedRows.Count -gt 0){
            $buttonEdit.Enabled = $true
            $buttonDelete.Enabled = $true
        }else{
            $buttonEdit.Enabled = $false
            $buttonDelete.Enabled = $false
        }
    })
     $datagridviewProjectUser.add_CellMouseDoubleClick({
        if ($datagridviewProjectUser.SelectedRows.Count -gt 0){
            [System.Windows.Forms.MessageBox]::Show("Current Datatable: `n`n" + ($dtValues | ft -Auto | out-string))  
            [System.Windows.Forms.MessageBox]::Show("Values from first column: `n`n" + ($dtValues.Rows.Value1 -join "`n"))  
            [System.Windows.Forms.MessageBox]::Show("Values from second column: `n`n" + ($dtValues.Rows.Value2 -join "`n"))  
            [System.Windows.Forms.MessageBox]::Show("Values from third column: `n`n" + ($dtValues.Rows.Value3 -join "`n"))  
            [System.Windows.Forms.MessageBox]::Show("Value from first item and second column: `n`n" + ($dtValues.Rows.Value2))  
            [System.Windows.Forms.MessageBox]::Show("Nu alles klar?")  
        }
    })
	#
	# buttonClose
	#
	$buttonClose.Anchor = 'Bottom, Right'  
	$buttonClose.CausesValidation = $False
	$buttonClose.DialogResult = 'Cancel'  
	$buttonClose.Location = '529, 226'  
	$buttonClose.Name = 'buttonClose'  
	$buttonClose.Size = '75, 23'  
	$buttonClose.TabIndex = 14
	$buttonClose.Text = '&Close'  
	$buttonClose.UseCompatibleTextRendering = $True
	$buttonClose.UseVisualStyleBackColor = $True
	$form1.ResumeLayout()
	#endregion Generated Form Code

	#----------------------------------------------

	#Save the initial state of the form
	$InitialFormWindowState = $form1.WindowState
	#Init the OnLoad event to correct the initial state of the form
	$form1.add_Load($Form_StateCorrection_Load)
	#Clean up the control events
	$form1.add_FormClosed($Form_Cleanup_FormClosed)
	#Show the Form
	return $form1.ShowDialog()

} #End Function

#Call the form
Show-DatagridviewExampleDatatable_psf | Out-Null
Mitglied: derhoeppi
derhoeppi 20.11.2018 aktualisiert um 20:15:50 Uhr
Goto Top
Entschuldigung für die verspätete Rückmeldung. Ich hatte eben Zeit dein Beispiel durchzugehen und anschließend den Fehler in meinem Code zu suchen. Prinzipiell habe ich schon das Gefühl das ich das objektorientierte programmieren verstanden habe, aber die Datatable bzw. der Umgang und die Ausgabe damit begreif ich nicht.
Zur Fehlersuche lasse ich mir in aller Regel alles via Write-Host ausgeben. Wenn ich das mache, erhalte ich nur "System.Data.DataRow" je nachdem wie viele Zeilen ich habe. Nun habe ich mal die $dtValues mit dem Scope global angelegt, so dass ich nach dem Beenden des Scripts noch auf die Datatable zugreifen kann. Wenn ich nun nur $dtValues in die Eingabeaufforderung eingebe erhalte ich die Datatable. Schreibe ich jedoch Write-Host davor erhalte ich wieder "System.Data.DataRow" pro Zeile. Scheinbar ist allein das mein Problem. Ich wär davon ausgegangen, dass die Ausgabe mit und ohne Write-Host identisch aussieht. Kannst du mir dafür vielleicht noch eine Erklärung geben?

PS: Seit ihr eigentlich hauptberuflich Entwickler / Programmierer?
Mitglied: 137846
137846 20.11.2018 aktualisiert um 21:10:40 Uhr
Goto Top
alles via Write-Host ausgeben
Fehler!
Write-Host gibt nur das aus was ein Objekt zur Umwandlung in einen String mit toString() machen kann, wenn es nur ein Objekt ist wie in dem Fall eins vom Typ Datarow gibt es natürlich nur den Datentyp aus anstatt einer Tabelle. Weil Write-Host ja Strings erwartet und eine Datarow ist nun mal kein String sondern ein Objekt. Nur Objekte die explizit in Ihrer toString() Methode definiert haben was in dem Falle auszugeben ist, werden dir den reinen Inhalt per write-host anzeigen, deshalb also die Eigenschaften abrufen damit du den Inhalt bekommst.
Write-host musst du also mitteilen was du als String ausgeben willst ansonsten gibt es bei einem Objekt einfach nur den Klassentyp aus.
Scheinbar ist allein das mein Problem.
Das ist dann aber nur ein reines Verständnisproblem.
p.s. : Seit ihr eigentlich hauptberuflich Entwickler / Programmierer?
Wer ist wir? Ist hier noch jemand face-smile?