【问题标题】:Powershell Function import multiple CSVs into Excel workbookPowershell 函数将多个 CSV 导入 Excel 工作簿
【发布时间】:2015-01-14 22:42:34
【问题描述】:

好的,是时候重新开始这个问题了。我找到了以下脚本http://blogs.technet.com/b/heyscriptingguy/archive/2010/09/09/copy-csv-columns-to-an-excel-spreadsheet-by-using-powershell.aspx

我的问题是如何让 powershell 为任意数量的 CSV 文件循环该脚本。脚本的速度并不重要。我收到了一些答案,它们在某种程度上存在问题。使用 Technet 脚本可提供正确的输出。

我想出了这个方法,但很难让代码循环遍历多个 CSV 文件。

Function Excel-Stuff {
[cmdletBinding()]
Param([Parameter(ValueFromPipeline=$true)][string]$junk)
$excel.cells.item(1,1) = "Server"
$excel.cells.item(1,2) = "Rack"
$excel.cells.item(1,3) = "Environment"
$excel.cells.item(1,4) = "RebootTime"
$excel.cells.item(1,5) = "Schedule"
$i = 2
$processes = Import-Csv 'C:\Monday.csv'
foreach ($process in $processes){
 $excel.cells.item($i,1) = $process.Server
 $excel.cells.item($i,2) = $process.Rack
 $excel.cells.item($i,3) = $process.Environment
 $excel.cells.item($i,4) = $process.RebootTime
 $excel.cells.item($i,5) = $process.Schedule
 $i++
} #end foreach process
$autofit = $Global:worksheet.UsedRange
$autofit.EntireColumn.AutoFit() | Out-Null
}#End Function.
$Excel = New-Object -ComObject excel.application
$workbook = $Excel.workbooks.add(1)
$Global:worksheet = $workbook.WorkSheets.Item(1)
$Global:worksheet.Name='Monday'
Excel-Stuff
$Excel.visible = $True

【问题讨论】:

  • 这种方法很慢。您不能直接在 Excel 中打开 CSV 并将工作表复制到新工作簿吗?至于您遇到的错误:工作表对象没有Worksheets 属性(它们不包含其他工作表)。
  • 我承认我只是对代码示例投掷飞镖,试图提出一些可行的方法。我还没有找到可以打开任意数量的 CSV 然后将它们移动到 Excel 并重命名工作表的示例代码。

标签: arrays excel function powershell csv


【解决方案1】:

好的,所以我们不要这样做。复制/粘贴是您的朋友,您可以在这里轻松完成。

您有周一至周五的标签,我假设有 7 个 CSV 文件。循环这个东西 7 次,在每个循环中创建一个选项卡,命名它,然后复制整个 CSV,将其转换为制表符分隔的 CSV,并将其通过管道传输到 CLIP.exe。然后只需在当前工作表上选择 A1 并粘贴。使用下一个 CSV 文件开始下一个循环。

$path = "c:\tmp\mytest.xlsx"
$day = @("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")
$Excel = New-Object -ComObject excel.application
$Excel.visible = $false
$workbook = $Excel.workbooks.add(1)

$day | %{
 $processes = Import-Csv -Path "D:\Scripts\work\$_.csv"
 $worksheet = $workbook.WorkSheets.add()
 $processes | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Clip.exe
 $worksheet.select()
 $worksheet.Name = $_
 [void]$Excel.ActiveSheet.Range("A1:A1").Select()
 [void]$Excel.ActiveCell.PasteSpecial()
 [void]$worksheet.UsedRange.EntireColumn.AutoFit()
}

#Clean up extra sheets
$Excel.DisplayAlerts = $false
$workbook.Worksheets|?{$day -notcontains $_.name}|%{$_.Delete()}
$Excel.DisplayAlerts = $true

[void]$Excel.ActiveSheet.Range("A1:A1").Select()
$workbook.saveas($path)
$Excel.Quit()
Remove-Variable -Name excel
[gc]::collect()
[gc]::WaitForPendingFinalizers()

那么您唯一关心的是 CSV 文件的顺序是否正确。如果您将 CSV 文件命名为 Monday.csv、Tuesday.csv 等,这可能会更简单,但只要将它们命名为星期一是第一个,并且按照字母数字顺序排列,您就可以了那个代码。

(编辑以反映保存前对单个单元格选择的评论建议,并将 -notin 更改为 -notcontains)

【讨论】:

  • 谢谢!它完全符合我的目标,但是每个工作表上的单元格范围仍然突出显示。我知道有一个 unselect 方法可以在添加工作表后取消选择某些东西,但目前它正在躲避我。
  • 嗯,在保存之前添加一行 $Excel.ActiveSheet.Range("A1:A1").Select() 这样只会使当前工作表的第一个单元格成为唯一选择的内容。
  • 遇到了操作员的问题 -notin 因为我的工作站上安装了 Powershell v4,我不能指望使用它的每个人都拥有 PS v4。还有其他想法吗?
  • 交换订单并使用 -NotContains。就我们的目的而言,($B -notin $A)($A -notcontains $B) 相同,并且更加向后兼容。 (更新答案以反映我的建议)
  • 出了点问题。 XLSX 星期日工作表没有来自 Sunday.CSV 的数据,如果我将源 CSV 重命名为 aMonday 然后 bTuesday 等等,则工作表顺序是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 2021-01-27
  • 2011-06-04
  • 2015-10-22
  • 1970-01-01
相关资源
最近更新 更多