循环文件以运行PowerShell脚本

循环文件以运行PowerShell脚本,powershell,Powershell,我试图循环浏览文件夹中未知数量的Excel文件,并将每个文件中的第一个工作表重命名为特定名称 到目前为止,我得到的是: Clear-Host $file = Get-ChildItem -Path "C:\PowerShell\BA" -Name -Include *.xlsx Write-Output $file 这将列出文件夹中的所有Excel文件。然后,我尝试运行ImportExcel模块中的一个命令,将第一个工作表重命名为“Sheet1” 但是,当我运行此代码时,文

我试图循环浏览文件夹中未知数量的Excel文件,并将每个文件中的第一个工作表重命名为特定名称

到目前为止,我得到的是:

Clear-Host
$file = Get-ChildItem -Path "C:\PowerShell\BA" -Name -Include *.xlsx
Write-Output $file
这将列出文件夹中的所有Excel文件。然后,我尝试运行ImportExcel模块中的一个命令,将第一个工作表重命名为“Sheet1”

但是,当我运行此代码时,文件夹中的每个文件都会出现以下错误:

WARNING: Could not find C:\WINDOWS\system32\11.25.2020_JH_BDX.xlsx 11.25.2020_JH_COV.xlsx 11.25.2020_JH_MISC.xlsx bx_1_coverage_report_2020-11-25 Final V.1 .xlsx bx_2_misc_report_2020-11-25 Final V.1 .xlsx bx_3_bordereau_report_2020-11-25 Final. V.1 .xlsx ic
at_cov_20201126053019.xlsx icat_misc_20201126053024.xlsx
Cannot index into a null array.
At line:8 char:1
+ $sheet1 = $xl.Workbook.Worksheets[1]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray
 
Close-ExcelPackage : Cannot bind argument to parameter 'ExcelPackage' because it is null.
At line:10 char:20
+ Close-ExcelPackage $xl
+                    ~~~
    + CategoryInfo          : InvalidData: (:) [Close-ExcelPackage], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Close-ExcelPackage
如果我以32位而不是64位运行,它看起来像是在这里查找文件:

WARNING: Could not find C:\Users\1192643\11.25.2020_JH_BDX.xlsx 11.25.2020_JH_COV.xlsx 11.25.2020_JH_MISC.xlsx bx_1_coverage_report_2020-11-25 Final V.1 .xlsx bx_2_misc_report_2020-11-25 Final V.1 .xlsx bx_3_bordereau_report_2020-11-25 Final. V.1 .xlsx icat_
cov_20201126053019.xlsx icat_misc_20201126053024.xlsx
我不确定它为什么在
C:\WINDOWS\system32
或我的用户指南中查找Excel文件。我已尝试通过在
foreach
块中添加完整路径来确保它位于正确的文件夹中,方法如下:

foreach ($i in $file )
{
$xl= Open-ExcelPackage "C:\PowerShell\BA\"$file
$sheet1 = $xl.Workbook.Worksheets[1]
$sheet1.Name ="Sheet1"
Close-ExcelPackage $xl
}
但这也不起作用。有人能帮我理解我在这里遗漏了什么吗?我的版本是5.1.17763.1490

$xl
变量更新为
$xl=Open ExcelPackage$i.fullname
会出现以下错误-因此它现在似乎有正确的路径,但它不喜欢代码。 Open ExcelPackage:无法将参数绑定到参数“Path”,因为它为null。 在C:\PowerShell\BA\RenameWorksheet.ps1:23 char:24 +$xl=打开ExcelPackage$i.fullname + ~~~~~~~~~~~ +CategoryInfo:InvalidData:(:)[Open ExcelPackage],参数BindingValidationException +FullyQualifiedErrorId:ParameterArgumentValidationErrorNullNotAllowed,打开ExcelPackage

Cannot index into a null array.
At C:\PowerShell\BA\RenameWorksheet.ps1:24 char:1
+ $sheet1 = $xl.Workbook.Worksheets[1]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray
 
The property 'Name' cannot be found on this object. Verify that the property exists and can be set.
At C:\PowerShell\BA\RenameWorksheet.ps1:25 char:1
+ $sheet1.Name ="Sheet1"
+ ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound
 
Close-ExcelPackage : Cannot bind argument to parameter 'ExcelPackage' because it is null.
At C:\PowerShell\BA\RenameWorksheet.ps1:26 char:20
+ Close-ExcelPackage $xl
+                    ~~~
    + CategoryInfo          : InvalidData: (:) [Close-ExcelPackage], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Close-ExcelPackage
为了测试代码,我可以使用以下方法更新特定.xlsx文件中的工作表名称:

$xl= Open-ExcelPackage "C:\PowerShell\BA\11.25.2020_JH_MISC.xlsx"
$sheet1 = $xl.Workbook.Worksheets[1]
$sheet1.Name ="Sheet1"
Close-ExcelPackage $xl

谢谢,

不要在循环中引用$file。如果要查找其中一个文件的句柄,请使用$i,因为这是您在foreach设置中选择的名称。请注意,我已将$I放入带引号的字符串中

foreach ($i in $file )
{
$xl= Open-ExcelPackage "C:\PowerShell\BA\$i"
$sheet1 = $xl.Workbook.Worksheets[1]
$sheet1.Name ="Sheet1"
Close-ExcelPackage $xl
}

使用PowerShell时,有两件事需要记住

  • PowerShell是面向对象的
  • PowerShell使用管道
  • 这里我们有一个变量和一个循环。通过切换到管道,可以消除这两种情况

    请注意阅读帮助文件以了解更多信息

    如Doug所述,
    -Name
    参数:

    -名字

    仅获取位置中项目的名称。输出是一个字符串对象,可以通过管道发送到其他命令。允许使用通配符

    这里我们从
    FileInfo
    对象变成
    String
    。因此,我们丢失了有价值的信息,例如每个文件的位置:
    $\uU4.FullName
    这导致了
    $i.FullName

    另外,
    -Include
    需要在
    -Path
    中使用特殊的通配符

    -包括

    以字符串数组形式指定此cmdlet在操作中包含的一个或多个项。此参数的值限定路径参数。输入路径元素或模式,例如“*.txt”。允许使用通配符。Include参数仅在命令包含项的内容时有效,例如C:\Windows\*,其中通配符指定C:\Windows目录的内容

    Get ChildItem
    将不会产生任何输出,除非您遵循此模式或(出于某种原因)包含
    -Name
    参数。这可能就是您开始使用
    -Name
    参数的原因

    最终答案
    如果您有大量文件并且能够安装PowerShell 7,则可以使用
    -Parallel
    参数来加快处理速度

    Get-ChildItem -Path "C:\PowerShell\BA\*" -Include "*.xlsx" | 
      ForEach-Object -Parallel { 
        $xl = Open-ExcelPackage $_.FullName
        $sheet1 = $xl.Workbook.Worksheets[1]
        $sheet1.Name ="Sheet1"
        Close-ExcelPackage $xl
      } -ThrottleLimit 5
    
    如果您不是本地管理员,可以从应用商店获取PowerShell 7

    解释错误消息 加载PowerShell时,
    C:\WINDOWS\system32\
    $env:USERPROFILE
    是默认的工作目录

    看看我们的道路:

    C:\WINDOWS\system32\11.25.2020_JH_BDX.xlsx
    
    我们有一个默认目录和一个自定义文件

    这表明我们只为函数提供文件名。例如,
    $\名称

    在我们的例子中,此错误的根本原因是
    getchilditem-Name
    ,它只生成作为字符串的文件名。有必要根据Walter对这些文件名进行限定。或者删除
    -Name
    并使用per-Doug/Itchydon的
    FullName
    属性


    Open ExcelPackage:无法将参数绑定到参数“Path”,因为它为null
    $xl=打开ExcelPackage$i.fullname

    这里有两条线索

    第一,我们刚刚改变了

    $xl= Open-ExcelPackage $file
    

    因此,
    $i.fullname
    一定是问题所在

    第二,我们可以向后跟踪错误消息的逻辑

    它为空
    ->
    参数“路径”
    ->
    打开的ExcelPackage无法绑定
    ->
    打开的ExcelPackage$i.fullname

    最有可能的两种情况是,
    $i
    $i.FullName
    从一开始就不存在

    如果我们检查,我们会看到
    $i
    没有
    全名
    属性

    调试 为脚本文件中的
    $xl=Open ExcelPackage$i.fullname
    行设置断点

    比如说,

    1  # C:\users\michael\desktop\vim\demo 1.ps1
    2  $file = Get-ChildItem -Path "C:\users\michael\desktop\vim" -Name -Include *.out
    3  
    4  
    5  foreach ($i in $file )
    6  {
    7  $xl= Open-ExcelPackage $i.fullname
    8  $sheet1 = $xl.Workbook.Worksheets[1]
    9  $sheet1.Name ="Sheet1"
    10 Close-ExcelPackage $xl
    11 }
    

    无法将参数绑定到参数“Path”
    无法索引到空数组中
    在此对象上找不到属性“Name”
    关闭ExcelPackage:无法绑定参数

    通常,解决第一个错误会修复代码或使更大的问题变得明显

    例如,我们知道如果
    $xl=Open ExcelPackage$i.fullname
    不起作用,那么
    $sheet1=$xl.Workbook.Worksheets[1]
    (这取决于定义的$xl)将不起作用

    在解决第一个错误之前,查看第二个、第三个、第四个等错误没有多大意义

    管道 需要了解的两件事是:

  • cmdlet与管道连接
    |
    (ASCI
    $xl= Open-ExcelPackage $file
    
    $xl= Open-ExcelPackage $i.fullname
    
    1  # C:\users\michael\desktop\vim\demo 1.ps1
    2  $file = Get-ChildItem -Path "C:\users\michael\desktop\vim" -Name -Include *.out
    3  
    4  
    5  foreach ($i in $file )
    6  {
    7  $xl= Open-ExcelPackage $i.fullname
    8  $sheet1 = $xl.Workbook.Worksheets[1]
    9  $sheet1.Name ="Sheet1"
    10 Close-ExcelPackage $xl
    11 }
    
    > # from the shell
    > Set-PSBreakpoint -Script '.\demo 1.ps1' -Line 7
    
      ID Script            Line Command           Variable         Action
      -- ------            ---- -------           --------         ------
       0 demo 1.ps1           7
    
    > & '.\demo 1.ps1'
    Entering debug mode. Use h or ? for help.
    
    Hit Line breakpoint on 'C:\Users\Michael\desktop\vim\demo 1.ps1:7'
    
    At C:\Users\Michael\desktop\vim\demo 1.ps1:7 char:1
    + $xl= Open-ExcelPackage $i.fullname
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    > $i | gm
    
       TypeName: System.String
    
    Name             MemberType            Definition
    ----             ----------            ----------
    Clone            Method                System.Object Clone(), System.Object ...
    CompareTo        Method                int CompareTo(System.Object value), i...
    Contains         Method                bool Contains(string value)
    ...
    
    > # We have a string. 
    
    > $i | Get-Member | Where-Object { $_.name -match "^f" }
    > # No match for properties starting with the letter 'f'. 
    > # So, strings don't have a 'FullName' property. 
    > q # to quit the debugger