2015-09-16 221 views
0

你好,stackoverflow的朋友!Powershell:将数据从一个Excel工作簿复制到另一个工作簿

我有一个剧本Powershell我的工作在哪里我试图做到以下几点:

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

我已经拥有了所有我需要的工作,使用Excel对象的Range方面。当试图将数据从实例化为一个COM对象,然后激活XLSX文件,我得到一个错误,说明

异常调用“粘贴”和“1”的参数(或多个)的CSV文件复制:“粘贴方法 工作表类失败”在行:1个字符:1

  • $脚本:ExcelWorkSheet.Paste($ tempRange)
  • ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
    • CategoryInfo:NotSpecified:(:) [],MethodInvocationException
    • FullyQualifiedErrorId: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#代码更轻松地完成这样的任务,那么我就是耳熟能详!

回答

0

花了很多时间后,我终于找到了一个可行的解决方案。 对于任何未来可能会通过搜索引擎遇到此问题的人,我希望以下代码能够帮助您!

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 
{ 

} 
相关问题