我正在为一个用户编写脚本,该脚本连接多个PDF文件并将表格数据附加为文本文件。现在的问题是用户可以手动命名文本文件,以便脚本必须验证哪个PDF文件属于数据。通常它会按名称进行,但由于用户可以(并且显然)更改PDF的名称,脚本应要求用户选择要合并的正确PDF。
我在我的脚本中编写了一个函数,它使用Winforms显示包含可用PDF文件的Listbox,用户应选择一个。
function Select-Rechnung
{
param
(
[string] $Rechnung,
[string[]] $PdfFiles
)
$form = New-Object System.Windows.Forms.Form
$form.Text = "Rechnung wählen"
$form.Size = New-Object System.Drawing.Size(640,320)
$form.StartPosition = "CenterScreen"
$form.KeyPreview = $true
$form.Add_KeyDown({if($_.KeyCode -eq "Enter") { $x = $PdfFiles[$ListBox.SelectedIndex]; $form.Close() }})
$form.Add_KeyDown({if($_.KeyCode -eq "Escape") { $form.Close() }})
$OkButton = New-Object System.Windows.Forms.Button
$OkButton.Location = New-Object System.Drawing.Size(240,240)
$OkButton.Size = New-Object System.Drawing.Size(75,23)
$OkButton.Text = "OK"
$OkButton.Add_Click({ $x = $PdfFiles[$ListBox.SelectedIndex]; $form.Close() })
$form.Controls.Add($OkButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(325,240)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Abbrechen"
$CancelButton.Add_Click({$form.Close()})
$form.Controls.Add($CancelButton)
$Label = New-Object System.Windows.Forms.Label
$Label.Location = New-Object System.Drawing.Size(10,20)
$Label.Size = New-Object System.Drawing.Size(600,20)
$Label.Text = [string]::Format("Für die Rechnung {0} wurden mehrere mögliche Dateien gefunden. Bitte auswählen:", $Rechnung)
$form.Controls.Add($Label)
$ListBox = New-Object System.Windows.Forms.ListBox
$ListBox.Location = New-Object System.Drawing.Size(10,40)
$ListBox.Size = New-Object System.Drawing.Size(600, 20)
$ListBox.Height = 200
foreach($pdfFile in $PdfFiles)
{
[void] $ListBox.Items.Add($pdfFile)
}
$form.Controls.Add($ListBox)
$form.TopMost = $true
$form.Add_Shown({$form.Activate()})
[void] $form.ShowDialog()
$x
}
现在,在KeyDown
处理程序或Click
处理程序中,该函数应将选定的PDF文件分配给变量$x
。我已检查$PdfFiles
是否正确地传递给函数,并且在处理程序执行期间,$PdfFiles[$ListBox.SelectedIndex]
实际上具有正确的字符串值。但是,在处理完表单$x
后访问ShowDialog
时,它为空,因此函数的返回值为空。
为什么不将值(在处理程序中正确计算的值)分配给我的变量并返回它?
答案 0 :(得分:2)
通过引入类似哈希表的引用类型来尝试它,并使用它来修改和返回值,如此
function Select-Rechnung
{
param
(
[string] $Rechnung,
[string[]] $PdfFiles
)
$x = @{ Value = '' }
...
$OkButton.Add_Click({ $x.Value = $PdfFiles[$ListBox.SelectedIndex];
...
$x.Value
}
您还可以通过使用
访问外部作用域的$x
变量来实现目标
Set-Variable -Name x -Scope 1 $PdfFiles[$ListBox.SelectedIndex]
或者其他一个范围修饰符(global
或script
- 请参阅about scopes),如果您想避免额外的哈希表。
答案 1 :(得分:2)
我现在通过解决这个问题来做到这一点。在KeyDown
和Click
处理程序中,我不再直接设置变量,而是:
$form.Add_KeyDown({
if($_.KeyCode -eq "Enter")
{
if($ListBox.SelectedIndex -ge 0)
{
$form.DialogResult = System.Windows.Forms.DialogResult]::OK;
}
$form.Close()
}
})
最后,我会检查DialogResult
:
[string]$x = $null
if($form.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK)
{
$x = $PdfFiles[$ListBox.SelectedIndex]
}
return $x
这确实导致返回正确的值。
答案 2 :(得分:1)
我建议您将$ x变量的范围级别更改为至少脚本范围,以便在脚本中的任何位置都可以使用它。现在它只是"生活"内部脚本块的句柄事件。将每个$ x变量更改为 $ script:x
function Select-Rechnung
{
param
(
[string] $Rechnung,
[string[]] $PdfFiles
)
$form = New-Object System.Windows.Forms.Form
$form.Text = "Rechnung wählen"
$form.Size = New-Object System.Drawing.Size(640,320)
$form.StartPosition = "CenterScreen"
$form.KeyPreview = $true
$form.Add_KeyDown({if($_.KeyCode -eq "Enter") { $script:x = $PdfFiles[$ListBox.SelectedIndex]; $form.Close() }})
$form.Add_KeyDown({if($_.KeyCode -eq "Escape") { $form.Close() }})
$OkButton = New-Object System.Windows.Forms.Button
$OkButton.Location = New-Object System.Drawing.Size(240,240)
$OkButton.Size = New-Object System.Drawing.Size(75,23)
$OkButton.Text = "OK"
$OkButton.Add_Click({ $script:x = $PdfFiles[$ListBox.SelectedIndex]; $form.Close() })
$form.Controls.Add($OkButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(325,240)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Abbrechen"
$CancelButton.Add_Click({$form.Close()})
$form.Controls.Add($CancelButton)
$Label = New-Object System.Windows.Forms.Label
$Label.Location = New-Object System.Drawing.Size(10,20)
$Label.Size = New-Object System.Drawing.Size(600,20)
$Label.Text = [string]::Format("Für die Rechnung {0} wurden mehrere mögliche Dateien gefunden. Bitte auswählen:", $Rechnung)
$form.Controls.Add($Label)
$ListBox = New-Object System.Windows.Forms.ListBox
$ListBox.Location = New-Object System.Drawing.Size(10,40)
$ListBox.Size = New-Object System.Drawing.Size(600, 20)
$ListBox.Height = 200
foreach($pdfFile in $PdfFiles)
{
[void] $ListBox.Items.Add($pdfFile)
}
$form.Controls.Add($ListBox)
$form.TopMost = $true
$form.Add_Shown({$form.Activate()})
[void] $form.ShowDialog()
$script:x
}
现在正以这种方式为我工作:
Select-Rechnung -Rechnung 'string' -PdfFiles 'file1.pdf','file2.pdf','file3.pdf'
输出:
file3.pdf