I have a client GL file (Excel) that needs to be regularly imported to SQL Server (as tab-delimited txt).
Sample (simplified):
PayCode PayDesc Dept1 Dept2 Dept3 ======================================== REG Regular 00001 00001 00002 VAC Vacation 00011 00012 00013 HOL Holiday 00021 00022 00022
However, the number of columns (departments) may change over time, and SQL Server doesn't support importing files with an uncertain column count. So rather than recode the SQL import each time a change occurs, I decided to "unpivot" the data prior to import, so the resulting table structure will always be static:
PayCode PayDesc DeptCode GLCode ==================================== REG Regular Dept1 00001 REG Regular Dept2 00001 REG Regular Dept3 00002 VAC Vacation Dept1 00011 VAC Vacation Dept2 00012 VAC Vacation Dept3 00013 HOL Holiday Dept1 00021 HOL Holiday Dept2 00022 HOL Holiday Dept3 00022
I've got the script functioning, but being a PS lightweight, I thought I would solicit for enhancement ideas. I feel like I'm missing good pipeline opportunities due to inexperience.
Code updated using feedback from briantist
$srcDir = "C:"
$srcTab = "Sheet1"
$srcFile = Join-Path -Path $srcDir -ChildPath "ClientGL.xlsx"
$outFile = Join-Path -Path $srcDir -ChildPath "ClientGL.txt"
$delim = "`t"
## Export from Excel to tab-delimited .txt
Write-Host "Launch Excel"
$Excel = New-Object -comobject Excel.Application
$Excel.Visible = $False
$Excel.displayalerts = $False
Write-Host "Open $srcFile"
$Workbook = $Excel.Workbooks.Open($srcFile)
$Workbook.Worksheets.Item($srcTab).Select()
Write-Host "Export $outFile as Tab-Delimited TXT"
$Workbook.SaveAs("$outFile",-4158)
Write-Host "Quit Excel"
$Excel.Quit()
If(Get-Process -name excel){Stop-Process -name excel}
## Import data and headers
Write-Host "Import $outFile data"
$inData = Import-Csv -Path $outFile -Delimiter $delim
Write-Host "Import $outFile headers"
$inHeaders = (Get-Content -Path $outFile -TotalCount 1) -split $delim
## Build output datatable
Write-Host "Build output datatable"
$outData = New-Object System.Data.DataTable
[Void]$outData.Columns.Add("PayCode",[string])
[Void]$outData.Columns.Add("PayDesc",[string])
[Void]$outData.Columns.Add("DeptCode",[string])
[Void]$outData.Columns.Add("GLCode",[string])
## Unpivot Department columns, and add results to datatable
Write-Host "Unpivot each Dept column and add data to datatable"
for($col=2; $col -lt $inHeaders.Count; $col++)
{
$dept = $inHeaders[$col] #current $col header name
foreach($row in $inData)
{
$dr = $outData.NewRow();
$dr.Item("PayCode") = $row.PayCode
$dr.Item("PayDesc") = $row.PayDesc
$dr.Item("DeptCode") = $dept #header name
$dr.Item("GLCode") = $row.$dept #row.col value
$outData.Rows.Add($dr)
}
}
## Output modified file
Write-Host "Output modified $outFile"
$outData | Export-Csv -Path $outFile -Delimiter $delim -notypeinformation -Force
Write-Host "Remove quotes from file"
(Get-Content -Path $outFile) | ForEach-Object {$_ -replace '"', ""} | Out-File -FilePath $outFile -Force