Powershell:将数据从一个Excel工作簿复制到另一个

本文关键字:Excel 一个 工作簿 复制 另一个 数据 Powershell | 更新日期: 2023-09-27 18:13:06

大家好!

我有一个Powershell脚本,我正在努力做以下事情:

  • 选择一个Excel xlsx文件与现有的工作表只有标题
  • 选择文本文件
  • 从文本文件创建一个临时CSV文件,并添加标题以匹配Excel文件
  • 将CSV文件中的信息复制到Excel文件
  • 中的工作表中
  • 保存/退出

我已经得到了使用Excel对象的范围方面所需的一切。当尝试从实例化为COM对象的CSV文件复制数据,然后激活xlsx文件时,我得到一个错误,说明

异常调用"粘贴",参数为"1":"粘贴方法工作表类失败" At line:1 char:1

  • 脚本:美元ExcelWorkSheet.Paste ($ tempRange)
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    • CategoryInfo: NotSpecified: (:) [], MethodInvocationException
    • fulllyqualifiederrid: ComMethodTargetInvocation

下面是我到目前为止的代码。任何帮助都将是非常感激的,因为我不知道:

BEGIN
{
    Function Set-ScriptVars()
    {
        Add-Type -AssemblyName System.Windows.Forms
    }
    Function Select-File($FileType)
    {
        ## Select file via selection dialog
        do {
            if($FileType -eq "xlsx")
            {
                Write-Host "`nPlease select the Excel file to import in the dialog"
            }
            elseif($FileType -eq "txt")
            {
                Write-Host "`nPlease select the Prescan or Postscan text file to import in the dialog"
            }
            Start-Sleep -Seconds 1
            $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{InitialDirectory = [Environment]::GetFolderPath('Desktop')}
            [void]$FileBrowser.ShowDialog()
            Write-Host "`nFile selected: " -NoNewline  
            Write-Host $FileBrowser.FileNames -ForegroundColor Yellow 
            $FileName = $FileBrowser.FileName
            if ($FileName.EndsWith(".$FileType"))
            {
                $selectionValid = $True
            }
            else
            {
                Write-Host "The file selected is not a .$FileType file."
                Write-Host "Restarting file selection loop."
                $selectionValid = $False
            }
        } until ($selectionValid -eq $True)
        if($FileType -eq "txt")
        {
            $Script:TextFile = $FileName
            $Script:TextParentPath = (Get-Item $FileName).Directory.FullName
        }
        elseif($FileType -eq "xlsx")
        {
            $Script:ExcelFile = $FileName
            $Script:ExcelParentPath = (Get-Item $FileName).Directory.FullName
        }
    }
    Function Open-Excel($Sheet)
    {
        $ActiveSheet = $Sheet
        $ExcelPath = $Script:ExcelFile
        $Script:Excel = New-Object -ComObject Excel.Application
        $Script:Excel.Visible = $True
        $Script:Excel.UserControl = $False
        $Script:Excel.Interactive = $False
        $Script:Excel.DisplayAlerts = $False
        $Script:ExcelWorkBook = $Script:Excel.Workbooks.Open($ExcelPath)
        $Script:ExcelWorkSheet = $Script:Excel.WorkSheets.item($ActiveSheet)
        $Script:ExcelWorkSheet.Activate()
    }
    Function Get-TextContent()
    {
        $Script:TextContent = Get-Content $Script:TextFile 
    }
    Function Copy-TextData()
    {
        # create a random file name
        $randomInt = @(0001..9999) | Get-Random
        $tempCSV = Import-CSV $Script:TextFile -Header "Server","Role","Type","Object","Path" 
        $tempCSV | Export-CSV -Path $ENV:USERPROFILE'Desktop'tempCSV_$randomInt.csv -NoTypeInformation
        $tempCSVPath = "$ENV:USERPROFILE'Desktop'tempCSV_$randomInt.csv"
        $tempCSVName = "tempCSV_$randomInt"
        # create a temporary file to copy from
        $TempExcel = New-Object -ComObject Excel.Application
        $TempExcel.Visible = $True
        $TempWorkBook = $TempExcel.WorkBooks.Open($tempCSVPath)
        $TempWorkSheet = $TempWorkBook.WorkSheets.Item($tempCSVName)
        $tempRange = $TempWorkSheet.Range("A2:E2").UsedRange
        $tempRange.Copy() | Out-Null
        $Script:ExcelWorkSheet.Activate()
        $Script:ExcelWorkSheet.Range("A2:E2").EntireColumn
        $Script:ExcelWorkSheet.Paste($tempRange)
        $Script:ExcelWorkBook.Save()
        $Script:Excel.Quit()
        [gc]::Collect()
        [gc]::WaitForPendingFinalizers()
        Write-Host "Break"
    }
}
PROCESS
{
    Set-ScriptVars
    Select-File -FileType "xlsx"
    Select-File -FileType "txt"
    if($Script:TextFile -match "Prescan")
    {
        Open-Excel -Sheet "Prescan"
    }
    elseif($Script:TextFile -match "Postscan")
    {
        Open-Excel -Sheet "Postscan"
    }
    Get-TextContent
    Copy-TextData
}
END
{
}

在这种情况下,不能使用VB宏。如果利用。net程序集或以@' '@格式加入c#代码更容易完成这样的任务,我将洗耳恭听!

Powershell:将数据从一个Excel工作簿复制到另一个

在花费了大量时间之后,我终于找到了一个可行的解决方案。对于将来可能通过搜索引擎遇到这种情况的任何人,我希望下面的代码能有所帮助!

BEGIN
{
    Function Set-ScriptVars()
    {
        Add-Type -AssemblyName System.Windows.Forms
    }
    Function Select-File($FileType)
    {
        ## Select file via selection dialog
        do {
            if($FileType -eq "xlsx")
            {
                Write-Host "`nPlease select the Excel file to import in the dialog"
            }
            elseif($FileType -eq "txt")
            {
                Write-Host "`nPlease select the Prescan or Postscan text file to import in the dialog"
            }
            Start-Sleep -Seconds 1
            $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{InitialDirectory = [Environment]::GetFolderPath('Desktop')}
            [void]$FileBrowser.ShowDialog()
            Write-Host "`nFile selected: " -NoNewline  
            Write-Host $FileBrowser.FileNames -ForegroundColor Yellow 
            $FileName = $FileBrowser.FileName
            if ($FileName.EndsWith(".$FileType"))
            {
                $selectionValid = $True
            }
            else
            {
                Write-Host "The file selected is not a .$FileType file."
                Write-Host "Restarting file selection loop."
                $selectionValid = $False
            }
        } until ($selectionValid -eq $True)
        if($FileType -eq "txt")
        {
            $Script:TextFile = $FileName
            $Script:TextParentPath = (Get-Item $FileName).Directory.FullName
        }
        elseif($FileType -eq "xlsx")
        {
            $Script:ExcelFile = $FileName
            $Script:ExcelParentPath = (Get-Item $FileName).Directory.FullName
        }
    }
    Function Open-Excel($Sheet)
    {
        $ExcelPath = $Script:ExcelFile
        $Script:Excel = New-Object -ComObject Excel.Application
        $Script:Excel.Visible = $False
        $Script:Excel.UserControl = $False
        $Script:Excel.Interactive = $True
        $Script:Excel.DisplayAlerts = $False
        $Script:ExcelWorkBook = $Script:Excel.Workbooks.Open($ExcelPath)
        $Script:ExcelWorkSheet = $Script:Excel.WorkSheets.item($Sheet)
        $Script:ExcelWorkSheet.Activate()
    }
    Function Get-TextContent()
    {
        $Script:TextContent = Get-Content $Script:TextFile 
    }
function Release-Ref ($ref) { 
    ([System.Runtime.InteropServices.Marshal]::ReleaseComObject( 
    [System.__ComObject]$ref) -gt 0) | Out-Null
    [System.GC]::Collect() 
    [System.GC]::WaitForPendingFinalizers() 
} 
    Function Copy-TextData()
    {       
        # create a CSV from the scan data
        $Script:TextContent = Get-Content $Script:TextFile
        $data = @()
        $row = New-Object PSObject
        foreach($line in $Script:TextContent)
        {
            if($line -eq "CSV was validated without errors." -or $line -eq "")
            {
                Out-Null
            }
            else
            {
                $i = 0
                $values = $line -split ","
                $result = [PSCustomObject]@{Server=$values[0];`
                                            Role=$values[1];`
                                            Object=$values[2];`
                                            Type=$values[3];`
                                            Path=$values[4]
                                           }
                [Array]$results = $results + $result
            }
        }
        $csvName = "scanData_" + "$(@(000..999) | Get-Random)"
        $results | Export-CSV -Path "$ENV:USERPROFILE'Desktop'$csvName.csv" -NoTypeInformation
        $csvPath = $(Get-Item $ENV:USERPROFILE'Desktop'$csvName.csv).VersionInfo.FileName
        # Remove header generated by hashtable
        # and skip the next two lines
        $tempContent = Get-Content $csvPath
        $replacementContent = $tempContent | Select -Skip 3
        Set-Content $csvPath -Value $replacementContent
        # create temporary workbook and save as xlsx
        $tempXL = New-Object -ComObject Excel.Application
        $tempXL.Visible = $False
        $tempXL.UserControl = $False
        $tempXL.Interactive = $True
        $tempXL.DisplayAlerts = $False
        $tempWB = $tempXL.WorkBooks.Open("$csvPath")
        $tempWS = $tempWB.WorkSheets
        $convertedName = $csvPath.Replace(".csv",".xlsx")
        $tempWB.SaveAs($convertedName,1)
        $tempWB.Saved = $True
        $tempRange = $tempWB.Worksheets.Item(1).UsedRange
        $tempRange.Copy()
        if($Script:logSelection -eq "Prescan")
        {
            $permRange = $Script:ExcelWorkBook.Worksheets.Item(2)
        }
        else
        {
            $permRange = $Script:ExcelWorkBook.Worksheets.Item(3)
        }
        $subRange = $permRange.Range("A2","E2")
        $permRange.Paste($subRange)
        $permRange.Columns.AutoFit()
        $Script:ExcelWorkBook.Save()
        $Script:ExcelWorkBook.Saved = $True
        $Script:Excel.Quit()
        $tempWB.Save()
        $tempWB.Saved = $True
        $tempXL.Quit()
        Release-Ref($Script:ExcelWorkSheet)
        Release-Ref($tempWS)
        Release-Ref($Script:ExcelWorkBook)
        Release-Ref($tempWB)
        Release-Ref($Script:Excel)
        Release-Ref($tempXL)
        Remove-Item $csvPath -Force
        Get-Item $convertedName | Remove-Item -Force
    }
    Function Prompt-ReRun
    {
        do
        {
            $openChoice = Read-Host "`nRun again? (y/n)"
            $openChoice = $openChoice.ToLower()
        } until($openChoice -eq "y" -or $openChoice -eq "n")
        if($openChoice -ne "y" -and $openChoice -ne "n")
        {
            Write-Host "Invalid entry"
        }
        elseif($openChoice -eq "y")
        {
            Run-Selection
        }
        else
        {
            Out-Null
        }
    }
    Function Run-Selection
    {
        Select-File -FileType "xlsx"
        Select-File -FileType "txt"
        if($Script:TextFile -match "Prescan")
        {
            Open-Excel -Sheet "Prescan"
            $Script:logSelection = "Prescan"
        }
        elseif($Script:TextFile -match "Postscan")
        {
            Open-Excel -Sheet "Postscan"
            $Script:logSelection = "Postscan"
        }
        Get-TextContent
        Copy-TextData
        Prompt-ReRun
    }
}
PROCESS
{
    Set-ScriptVars
    Run-Selection
}
END
{
}