使用Powershell从CSV文件中删除列

时间:2015-07-09 18:36:03

标签: csv powershell

我需要从CSV文件中删除多个列,而不在Powershell中导入CSV文件。下面是我输入CSV的示例以及我希望输出CSV的外观。

Input.csv

A,1,2,3,4,5

B,6,7,8,9,10

C,11,12,13,14,15

d,15,16,17,18,19,20

Idealoutput.csv

A,3,5-

B,8,10

C,13,15

d,17,20

我尝试过以下代码,但它给了我很多错误,并说我不能使用"删除"方法这种方式(我过去做过的)......有什么想法吗?

$Workbook1 = $Excel.Workbooks.open($file.FullName) 
$header = $Workbook1.ActiveSheet.Range("A1:A68").EntireRow
$unneededcolumns1 = $Workbook1.ActiveSheet.Range("A1:O1").EntireColumn
$unneededcolumns2 = $Workbook1.ActiveSheet.Range("B1:K1").EntireColumn
$unneededcolumns3 = $Workbook1.ActiveSheet.Range("F1:I1").EntireColumn
$unneededcolumns4 = $Workbook1.ActiveSheet.Range("G1:I1").EntireColumn
$unneededcolumns5 = $Workbook1.ActiveSheet.Range("H1:O1").EntireColumn
$unneededcolumns6 = $Workbook1.ActiveSheet.Range("J1:AL1").EntireColumn
$unneededcolumns7 = $Workbook1.ActiveSheet.Range("K1").EntireColumn
$unneededcolumns8 = $Workbook1.ActiveSheet.Range("L1:AK1").EntireColumn
$unneededcolumns9 = $Workbook1.ActiveSheet.Range("F1:I1").EntireColumn
$unneededcolumns10 = $Workbook1.ActiveSheet.Range("M1:AB1").EntireColumn
$unneededcolumns11 = $Workbook1.ActiveSheet.Range("N1:X1").EntireColumn
$unneededcolumns12 = $Workbook1.ActiveSheet.Range("O1:BA1").EntireColumn
$unneededcolumns13 = $Workbook1.ActiveSheet.Range("P1:U1").EntireColumn
$header.Delete()
$unneededcolumns1.Delete()
$unneededcolumns2.Delete()
$unneededcolumns3.Delete()
$unneededcolumns4.Delete()
$unneededcolumns5.Delete()
$unneededcolumns6.Delete()
$unneededcolumns7.Delete()
$unneededcolumns8.Delete()
$unneededcolumns9.Delete()
$unneededcolumns10.Delete()
$unneededcolumns11.Delete()
$unneededcolumns12.Delete()
$unneededcolumns13.Delete()

$Workbook1.SaveAs("\\output.csv")

2 个答案:

答案 0 :(得分:4)

我还是要添加这个,因为我希望说服你避免使用Excel是多么容易。

$source = "c:\temp\file.csv"
$destination = "C:\temp\newfile.csv"
(Import-CSV $source -Header 1,2,3,4,5,6 | 
    Select "1","4","6" | 
    ConvertTo-Csv -NoTypeInformation | 
    Select-Object -Skip 1) -replace '"' | Set-Content $destination

我们将任意标题分配给对象,这样我们就可以按位置调用第1列,第4列和第6列。导出后,文件将包含以下内容,这些内容与我认为您想要的内容相匹配,而不是您在问题中的内容。你的最后一行有一个额外的值(20),我不知道它是否有意。

A,3,5
B,8,10
C,13,15
D,17,19

如果这不可行,我真的很感兴趣。

Excel方法

好吧,所以文件很大,所以Import-CSV不是一个可行的选择。保持你的excel想法我想出了这个。它将做的是获取列索引并删除那些不在这些索引中的列。

等等你说?...由于列索引在删除列时发生变化,因此无法正常工作。使用我们想要保留的索引,我们得到基于工作表UsedRows的删除反转。然后,我们将每个列删除并删除一个等于数组位置的值。原因是当实际删除列时,已经调整了下一个值以考虑该移位。

$file = "c:\temp\file.csv"
$ColumnsToKeep = 1,4,6

# Create the com object
$excel = New-Object -comobject Excel.Application
$excel.DisplayAlerts = $False
$excel.visible = $False

# Open the CSV File
$workbook = $excel.Workbooks.Open($file)
$sheet = $workbook.Sheets.Item(1)

# Determine the number of rows in use
$maxColumns = $sheet.UsedRange.Columns.Count

$ColumnsToRemove = Compare-Object $ColumnsToKeep (1..$maxColumns) | Where-Object{$_.SideIndicator -eq "=>"} | Select-Object -ExpandProperty InputObject
0..($ColumnsToRemove.Count - 1) | %{$ColumnsToRemove[$_] = $ColumnsToRemove[$_] - $_}
$ColumnsToRemove  | ForEach-Object{
    [void]$sheet.Cells.Item(1,$_).EntireColumn.Delete()
}

# Save the edited file
$workbook.SaveAs("C:\temp\newfile.csv", 6)

# Close excel and release the com object.
$workbook.Close($true)
$excel.Quit()
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
Remove-Variable excel 

即使在阅读"correct" way to do it之后,我仍然遇到Excel问题仍未解决的问题。内在的逻辑是重要的。不要忘记根据需要更改路径。

答案 1 :(得分:0)

这是我使用的更好的方法,但是它不是大型文件上性能最高的方法。两者都已经过1GB文件的测试。

Powershell:

Import-Csv '.\inputfile.csv' 
  | select ColumnName1,ColumnName2,ColumnName3 
  | Export-Csv -Path .\outputfile.csv -NoTypeInformation

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/export-csv?view=powershell-5.1

如果要摆脱该工具添加的那些讨厌的引号,请升级到Powershell 7。

PowerShell 7 +:

Import-Csv '.\inputfile.csv' 
  | select ColumnName1,ColumnName2,ColumnName3 
  | Export-Csv -Path .\outputfile.csv -NoTypeInformation -UseQuotes Never

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/export-csv?view=powershell-7