2017-08-30 166 views
0

我试图在PowerShell脚本中使用Export-Csv创建没有头文件的多个CSV文件。我读过几篇关于使用Select-Object -Skip 1技巧的文章,但是我还没有成功完成我的代码。以下是我试图把它叫做:PowerShell导出Csv没有头文件

$DataSet.Tables[0] | Select-Object -Skip 1 | 
    Export-Csv -NoTypeInformation -Path "C:\$($csvname[$i])_$timer.csv" 

这里有我全,功能代码:

function Run-Query { 
    Param([string[]]$queries,[string[]]$csvname) 
    Begin { 
     $SQLServer = 'myserver' 
     $Database = 'mydatabase' 
     $SqlConnection = New-Object System.Data.SqlClient.SqlConnection 
     $SqlConnection.ConnectionString = "Server = $SQLServer; Database = $Database; Integrated Security = True" 
     $timer = (Get-Date -f yyyy-MM-dd) 
    } # End Begin 
    Process { 
     # Loop through each query 
     for ($i = 0; $i -lt $queries.Count; $i++) { 
      $SqlCmd = New-Object System.Data.SqlClient.SqlCommand 

      # Use the current index ($i) to get the query 
      $SqlCmd.CommandText = $queries[$i] 
      $SqlCmd.Connection = $SqlConnection 
      $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter 
      $SqlAdapter.SelectCommand = $SqlCmd 
      $DataSet = New-Object System.Data.DataSet 
      $SqlAdapter.Fill($DataSet) 

      # Use the current index ($i) to get the sheetname for the CSV 
      $DataSet.Tables[0] | Export-Csv -NoTypeInformation -Path "C:\$($csvname[$i])_$timer.csv" 
     } 
    } # End Process 
    End { 
     $SqlConnection.Close() 
    } 
} # End function run-query. 

#Entery Query 
$queries = @() 
$queries += @' 
SELECT * FROM table2 
'@ 
$queries += @' 
SELECT * FROM table1 
'@ 

#List of CSV file names. 
$csvname = @() 
$csvname += 'file1' 
$csvname += 'file2' 
Run-Query -queries $queries -csvname $csvname 
+0

'Select-Object -skip 1'“trick”用于_importing_ CSVs作为文本文件而不是对象。如果没有标题信息,您将无法导出CSV。你为什么想要? CSV格式的定义包括标题。 –

+0

它是我将文件传输到的第三方所必需的。有没有办法用PowerShell来解决这个问题? – Joe

+0

@Joe你的第三方需要一个逗号分隔的文件没有标题?他们如何知道任何领域的含义? – TheIncorrigible1

回答

2

你误会的CSV在PowerShell中是如何工作的。假设你有以下内容的CSV文件:

 
foo,bar,baz 
A,1,2 
B,3,4 

导入是通过Import-Csv CSV会给你2个对象与属性foobarbaz填充值从每一个数据行。使用JSON符号对象的列表如下所示:

[ 
    { 
     "foo": "A", 
     "bar": "1", 
     "baz": "2" 
    }, 
    { 
     "foo": "B", 
     "bar": "3", 
     "baz": "4" 
    } 
] 

Export-Csv确实基本上是相同的,只是在背面。我将对象作为输入并将其属性的值写入CSV的字段。这些字段由第一个对象Export-Csv接收的属性决定。如果其中一个属性在后续对象中丢失,则将NULL值写入相应的字段。如果后续对象具有第一个对象没有的其他属性,则会忽略它们。

使用Select-Object -Skip 1Import-CsvExport-Csv是无用的,因为通常你不想跳过任何输入或输出对象(否则你会丢失数据)。

有,但是,类似Import-CsvExport-Csv读取和写入字符串,而不是文件的两个其他cmdlet:ConvertFrom-CsvConvertTo-CsvImport-Csv基本上是Get-ContentConvertFrom-Csv的组合,并且Export-Csv的组合是ConvertTo-CsvSet-Content

那么,Select-Object -Skip 1在这里发挥了什么作用?当您通过ConvertTo-Csv将对象输入转换为CSV并跳过字符串输出的第一行时,可以有效地从输出文本中删除标题行,这是您无法使用Export-Csv执行的操作。

演示:该输出入Set-Content,你有你想要的头部信息的CSV文件

 
PS C:\>$data = @() 
PS C:\>$data += [PSCustomObject]@{"foo"="A"; "bar"="1"; "baz"="2"} 
PS C:\>$data += [PSCustomObject]@{"foo"="B"; "bar"="3"; "baz"="4"} 
PS C:\>$data | Format-Table -Auto 

foo bar baz 
--- --- --- 
A 1 2 
B 3 4 

PS C:\>$data | ConvertTo-Csv -NoType 
"foo","bar","baz" 
"A","1","2" 
"B","3","4" 
PS C:\>$data | ConvertTo-Csv -NoType | Select-Object -Skip 1 
"A","1","2" 
"B","3","4" 

管。

$DataSet.Tables[0] | 
    ConvertTo-Csv -NoType | 
    Select-Object -Skip 1 | 
    Set-Content "C:\$($csvname[$i])_$timer.csv" 
+0

工作完美!谢谢! – Joe

+0

@downvoter小心解释你认为我的答案错了吗? –

0

这里有一种方法来输出作为制表符分隔的CSV输入对象无头:

function ConvertTo-Tsv { 
    param(
    [parameter(ValueFromPipeline=$true)] 
    [Object[]] $Object 
) 
    process { 
    foreach ($objectItem in $Object) { 
     ($objectItem.PSObject.Properties | Select-Object -ExpandProperty Value) -join "`t" 
    } 
    } 
} 

然后您可以执行以下任一操作:

Import-Csv "inputfile.csv" | ConvertTo-Tsv 

$data = Import-Csv "inputfile.csv" 
ConvertTo-Tsv $data 
+0

我在我的“Export-Csv”行下添加了“Import-Csv”$($ csvname [$ i])_ $ timer.csv“| ConvertTo-Tsv”。这极大地增加了脚本的执行时间,但似乎对标题没有任何影响。 – Joe

+0

这个答案提供的功能是一个很好的解决方案,但如何使用它的例子是误导性的。数据的来源是一个SQL数据库,而不是另一个CSV文件,所以不需要使用'Import-Csv'。相反,用'ConvertTo-Csv'代替'Export-Csv'就像这样:'$ DataSet.Tables [0] | ConvertTo-Tsv | Set-Content -Path“C:\ $($ csvname [$ i])_ $ timer.csv”' – BACON

+0

正确,我的示例是通用的(指CSV) - 假设用户负责传递正确对象进入函数的管道。 –