2016-08-04 60 views
1

我有一個相當簡單的請求(對我來說這是一項非常艱鉅的任務tbh)。Powershell在Excel單元格中使用多行文字工作

我有兩個CSV文件,我想要轉換爲Excel,因此這兩個CSV文件中的每一個將佔用一張紙。 到目前爲止,我已經成功了,但我想要糾正這個小問題。

之一的CSV細胞包含多個文本行,像這樣:

這是第1項

這是進入2

我想有這兩個條目需要進口到Excel單元格中以同樣的方式是在CSV,但是當我檢查我的Excel文件,第二個項目被導入到下一行:

行1個小區1 - 這是進入1

第2行第1行 - 這是條目2

我不知道我是否應該使用.NET類worksheet.UsedRange.EntireRow或worksheet.UsedRange.EntireColumn或其他。 我正在檢查MSDN,但由於我仍是一個noob,我找不到任何東西。

這是我的代碼示例:

Function Merge-CSVFiles 
{ 
Param(
$CSVPath = ".\Reports", 
$XLOutput=".\final_final_report.xlsx" 
) 

$csvFiles = Get-ChildItem ("$CSVPath\*") -Include *.csv 
$Excel = New-Object -ComObject excel.application 
$Excel.visible = $false 
$Excel.sheetsInNewWorkbook = $csvFiles.Count 
$workbooks = $excel.Workbooks.Add() 
$CSVSheet = 1 

Foreach ($CSV in $Csvfiles) 

{ 
$worksheets = $workbooks.worksheets 
$CSVFullPath = $CSV.FullName 
$SheetName = ($CSV.name -split "\.")[0] 
$worksheet = $worksheets.Item($CSVSheet) 
$worksheet.Name = $SheetName 
$TxtConnector = ("TEXT;" + $CSVFullPath) 
$CellRef = $worksheet.Range("A1") 
$Connector = $worksheet.QueryTables.add($TxtConnector,$CellRef) 
$worksheet.QueryTables.item($Connector.name).TextFileCommaDelimiter = $True 
$worksheet.QueryTables.item($Connector.name).TextFileParseType = 1 
$worksheet.QueryTables.item($Connector.name).Refresh() 
$worksheet.QueryTables.item($Connector.name).delete() 
$worksheet.UsedRange.EntireColumn.AutoFit() 
$CSVSheet++ 

} 

$workbooks.SaveAs($XLOutput,51) 
$workbooks.Saved = $true 
$workbooks.Close() 
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbooks) | Out-Null 
$excel.Quit() 
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null 
[System.GC]::Collect() 
[System.GC]::WaitForPendingFinalizers() 

} 
+0

嗯,好像直接在Excel中打開CSV時,你可以用引號括整個進入和Excel將識別新行作爲同一項目的一部分像(http://stackoverflow.com/questions/566052/can -you編碼-CR-LF-在 - 進入 - CSV文件)。因此,您可以預處理CSV並將條目換成引號。但即使如此,使用QueryTables的方法也無法正確識別。 Excel自己的數據導入工具 - 我唯一可以實現的方法是將.csv作爲Excel中的新工作簿打開。 – Mikegrann

+0

我可以想出的最佳解決方案:對所有數據進行預處理(例如用「,」替換),然後用'Workbooks.Open'單獨打開所有.csv文件。全部打開後,通過從所有工作簿複製到主工作簿來合併數據。 – Mikegrann

+0

否則使用特殊代碼預處理數據以替換換行符的實例,以便excel將整個事件視爲一個條目,然後在導入後可以後處理將此代碼替換回換行符。 – Mikegrann

回答

0

我不知道爲什麼你正在使用的方法,這是否但是我能夠重現我的系統上也是如此。我做了一些類似的操作在建立一個大型的Excel工作簿我的劇本之一,我已經成功地使用了下面的方法:

  1. 導入CSV擁有自營CSV
  2. 將其轉換爲一個多維數組

    $TxtConnector = ("TEXT;" + $CSVFullPath) 
    $CellRef = $worksheet.Range("A1") 
    $Connector = $worksheet.QueryTables.add($TxtConnector,$CellRef) 
    $worksheet.QueryTables.item($Connector.name).TextFileCommaDelimiter = $True 
    $worksheet.QueryTables.item($Connector.name).TextFileParseType = 1 
    $worksheet.QueryTables.item($Connector.name).Refresh() 
    $worksheet.QueryTables.item($Connector.name).delete() 
    
  3. 寫範圍對象

。例如數組值2,看起來像這樣替換代碼

用這個代替:

$CsvContents = Import-Csv $CSVFullPath 
$MultiArray = (ConvertTo-MultiArray $CsvContents -Headers).Value 
$StartRowNum = 1 
$StartColumnNum = 1 
$EndRowNum = $CsvContents.Count + 1 
$EndColumnNum = ($CsvContents | Get-Member | Where-Object { $_.MemberType -eq 'NoteProperty' }).Count 
$Range = $worksheet.Range($worksheet.Cells($StartRowNum, $StartColumnNum), $worksheet.Cells($EndRowNum, $EndColumnNum)) 
$Range.Value2 = $MultiArray 

對於工作,你還需要我用一個對象轉換爲一個多維數組(基於關閉一個貼here但稍作修改)功能:

function ConvertTo-MultiArray 
{ 
    param (
     $InputObject, 
     [switch]$Headers = $false 
    ) 
    begin 
    { 
     $Objects = @() 
     [ref]$Array = [ref]$null 
    } 
    process 
    { 
     $Objects += $InputObject 
    } 
    end 
    { 
     $Properties = $Objects[0].PSObject.Properties | ForEach-Object{ $_.Name } 
     $Array.Value = New-Object 'object[,]' ($Objects.Count + 1), $Properties.Count 
     $ColumnNumber = 0 
     if ($Headers) 
     { 
      $Properties | ForEach-Object{ 
       $Array.Value[0, $ColumnNumber] = $_.ToString() 
       $ColumnNumber++ 
      } 
      $RowNumber = 1 
     } 
     else 
     { 
      $RowNumber = 0 
     } 
     $Objects | ForEach-Object{ 
      $Item = $_ 
      $ColumnNumber = 0 
      $Properties | ForEach-Object{ 
       if ($Item.($_) -eq $null) 
       { 
        $Array.Value[$RowNumber, $ColumnNumber] = "" 
       } 
       else 
       { 
        $Array.Value[$RowNumber, $ColumnNumber] = $Item.($_).ToString() 
       } 
       $ColumnNumber++ 
      } 
      $RowNumber++ 
     } 
     $Array 
    } 
} 
+0

再次問候。喬恩,我已經嘗試過你的解決方案,它的工作:)謝謝你,你已經救了我很可能幾個小時與我的頭撞牆。 我得到了我想要的,當我將它移動到Excel中時,CSV文件中的多行文本保留在一個單元格中。 –

+0

非常好!我很高興,當我嘗試自動化Excel任務時,我的痛苦時間已經讓其他人受益。 :) –

相關問題