【问题标题】:Array to Excel Range only gives first element of the Array数组到 Excel 范围仅给出数组的第一个元素
【发布时间】:2015-08-01 11:07:54
【问题描述】:

我创建了以下函数,它将数组的值导出到 Excel,但它只导出第一个元素。

Function Export_Excel ($Array,$Column,$Sheet) {
  [System.Threading.Thread]::CurrentThread.CurrentCulture = "en-US"
  [System.Threading.Thread]::CurrentThread.CurrentUICulture = "en-US"

  $Global:sheet = $Global:wkbk.WorkSheets.Item("$Sheet")
  $intRow = 3

  $LastRow = $Array.count + 2
  $Range = "$Column" + $intRow +":$Column" + "$LastRow"

  $RangeSet = $Global:sheet.Range("$Range")
  $RangeSet.Value2 = $Array

  [gc]::collect()
  [gc]::WaitForPendingFinalizers() 
  [System.Threading.Thread]::CurrentThread.CurrentCulture = $Global:OldCulture
  [System.Threading.Thread]::CurrentThread.CurrentUICulture = $Global:OldUICulture
}

我的数组是用$Array+=$ValueForArray生成的。

当我执行时

Export_Excel $Array "B" "Sheet1"

它只为整个数组长度导出每个单元格中的第一个元素。谁能看到我做错了什么?

【问题讨论】:

  • 以防万一我测试时,我们还需要知道 $array 是如何声明的。 $Array = @()?
  • 你好,马特,确实 $Array 被声明为 $Array = @()
  • 当我使用 Export_Excel $Array "3" "Sheet1" 数组“正确”导出时,您将获得第 33 行的所有信息。

标签: arrays excel powershell


【解决方案1】:

这只是一个字符串数组吗?如果是这样,这可以so简单得多。将每个字符串转换为一个对象,将对象数组转换为没有类型信息的 CSV,并使其以制表符分隔,跳过标题行,复制到剪贴板,粘贴到您希望它向下流动的任何位置。如果你真的想把它作为一个函数,你可以这样做:

Function Export_Excel ($Array,[String]$Column,[String]$Sheet) {
    $ColNum = ([int][char]$Column.ToUpper()) - 64
    $Array | Select @{n='Header';e={$_}} | ConvertTo-Csv -NoTypeInformation -Delimiter "`t" | Select -Skip 1 | clip
    [void]$Wkbk.WorkSheets.Item("Sheet1").Columns.Item($ColNum).Cells.Item(3).PasteSpecial()
}

哦,对了,我也在其中将列字母转换为数字等价物。所以,要测试这个......

Function Export_Excel ($Array,[String]$Column,[String]$Sheet) {
    $ColNum = ([int][char]$Column.ToUpper()) - 64
    $Array | Select @{n='Header';e={$_}} | ConvertTo-Csv -NoTypeInformation -Delimiter "`t" | Select -Skip 1 | clip
    [void]$Wkbk.WorkSheets.Item("Sheet1").Columns.Item($ColNum).Cells.Item(3).PasteSpecial()
}

$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $True
$Wkbk = $Excel.Workbooks.Add()

$Fruit = @("Apple","Orange","Banana")

Export_Excel $Fruit 'f' 'Sheet1'

结果:Excel 打开,创建了一个空白工作簿,然后用单词 Apple 填充单元格 F3,用单词 Orange 填充单元格 F4,用单词 Banana 填充单元格 F5。我很确定那是你的意图。

【讨论】:

  • 这就像一个魅力。非常感谢。现在将数组导出到 Excel 只需不到一秒钟的时间。
  • CovertTo-Csv 的唯一问题是,如果您的数组字符串中有“é,ô,ö,à,è,...”,它将删除这些字符并将其更改为???。使用 swithc -encoding UTF8 不会改变这一点
【解决方案2】:

值是按行而不是按列分配的。改用循环:

for ($i = 0; $i -lt $Array.Length; $i++) {
  $global:sheet.Cells.Item($i+3, $Column).Value2 = $Array[$i]
}

请注意,您需要为此设置 $Column 一个数字参数。

作为替代方案,您可以将数组放在临时表上的一行中,然后在转置值时复制/粘贴该范围:

$temprange = "A1:" + [string][char]($Array.Length + 64) + "1"
$range     = "$Column${intRow}:$Column$LastRow"

$global:tempsheet.Range($temprange).Value2 = $Array
[void]$global:tempsheet.Range($temprange).Copy()
[void]$global:sheet.Range($range).PasteSpecial(-4163, -4142, $false, $true)

【讨论】:

  • 唯一的问题是其中会有超过 100.000 个元素的数组。所以循环需要很长时间,并且转置是不可能的。有没有办法在列而不是行中分配值?
  • 如果你有 100000 行或更多,你不应该首先使用 Excel。
  • 我知道,但这是管理层的要求。 For 循环工作,但它真的很慢。如果我可以将数组放在一列中,它将在 50 倍的时间内完成。
  • 您可以使用复制/粘贴转置方法以数千个元素($Array[0..15000]$Array[15001..30000]、...)的块的形式处理数组。
  • 我必须同意这里的 OP...使用 Excel ComObject 循环单元格并设置它们的值非常慢。可以很好地使用 PasteSpecial 和转置!太棒了 =)
猜你喜欢
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-14
  • 1970-01-01
相关资源
最近更新 更多