【问题标题】:Powershell - Creating Excel Workbook - Getting "Insufficient memory to continue the execution of the program"Powershell - 创建 Excel 工作簿 - 获取“内存不足,无法继续执行程序”
【发布时间】:2021-12-24 21:57:36
【问题描述】:

我正在尝试创建一个 Excel 工作簿,然后使用从搜索许多 txt 文件中找到的数据填充单元格。

我在找到“IDENTIFICATION DIVISION”之后和在找到“ENVIRONMENT DIVISION”之前读取了一个文件并提取了所有 cmets 然后我在我的 excel 工作簿中填充两个单元格。如果文件和单元格二是提取的 cmets,则单元格一。

我在工作服务器上有 256GB 内存。在 Powershell 引发内存错误之前,正在使用小于 %5。

谁能看出我哪里出错了?

谢谢, -罗恩

$excel = New-Object -ComObject excel.application
$excel.visible = $False
$workbook = $excel.Workbooks.Add()
$diskSpacewksht= $workbook.Worksheets.Item(1)
$diskSpacewksht.Name = "XXXXX_Desc"
$col1=1
$diskSpacewksht.Cells.Item(1,1) = 'Program'
$diskSpacewksht.Cells.Item(1,2) = 'Description'

$CBLFileList = Get-ChildItem -Path 'C:\XXXXX\XXXXX' -Filter '*.cbl' -File -Recurse
$Flowerbox = @()

ForEach($CBLFile in $CBLFileList) {
    $treat = $false
    Write-Host "Processing ... $CBLFile" -foregroundcolor green      
    Get-content -Path $CBLFile.FullName |
    ForEach-Object {
        if ($_ -match 'IDENTIFICATION DIVISION') {
#             Write-Host "Match IDENTIFICATION DIVISION" -foregroundcolor green      
            $treat = $true
        }
        if ($_ -match 'ENVIRONMENT DIVISION') {
#             Write-Host "Match ENVIRONMENT DIVISION" -foregroundcolor green 
             $col1++
             $diskSpacewksht.Cells.Item($col1,1) = $CBLFile.Name
             $diskSpacewksht.Cells.Item($col1,2) = [String]$Flowerbox
             $Flowerbox = @()
             continue
        }
        if ($treat) {
            if ($_ -match '\*(.{62})') {
                Foreach-Object {$Flowerbox += $matches[1] + "`r`n"}
         $treat = $false
            }
        }
    }
}

$excel.DisplayAlerts = 'False'
$ext=".xlsx"
$path="C:\Desc.txt"
$workbook.SaveAs($path) 
$workbook.Close
$excel.DisplayAlerts = 'False'
$excel.Quit()

【问题讨论】:

  • 您正在尝试将 FileInfo 对象 $CBLFile 作为值插入到单元格中。也许您的意思是把文件的名称或全名放在那里?
  • @Theo 该字段 $CBLFile 仅捕获名称。
  • 你不应该依赖一个对象字符串化的任何东西。如果你想要文件名,添加$CBLFile.Name,如果你想要文件完整路径和名称,添加$CBLFile.FullName。我想说的代码要具体。
  • 你需要在主循环中将$treat初始化为$false。然后在if ($treat) {..} 块中也将其设置回$false,否则它将永远保持$true。为什么要在所有工作完成之后而不是在创建 Com 对象之后直接设置 Excel 属性 .DisplayAlerts
  • $col1 在循环中永远不会重置为 1,因此您可能超过了 Excel 文件可以处理的列数。

标签: excel powershell


【解决方案1】:

不知道 .CBL 文件的内容可能是什么,我建议不要尝试使用 Excel COM 对象来完成所有这些操作,而是创建一个 CSV 文件以使事情变得更容易。
完成后,您只需在 Excel 中打开该 csv 文件即可。

# create a List object to collect the 'flowerbox' strings in
$Flowerbox = [System.Collections.Generic.List[string]]::new()
$treat = $false

# get a list of the .cbl files and loop through. Collect all output in variable $result
$CBLFileList = Get-ChildItem -Path 'C:\XXXXX\XXXXX' -Filter '*.cbl' -File -Recurse
$result = foreach ($CBLFile in $CBLFileList) {
    Write-Host "Processing ... $($CBLFile.FullName)" -ForegroundColor Green
    # using switch -File is an extremely fast way of testing a file line by line.
    # instead of '-Regex' you can also do '-WildCard', but then add asterikses around the strings
    switch -Regex -File $CBLFile.FullName {
        'IDENTIFICATION DIVISION' { 
            # start collecting Flowerbox lines from here    
            $treat = $true
        }
        'ENVIRONMENT DIVISION' {
            # stop colecting Flowerbox lines and output what we already have
            # output an object with the two properties you need
            [PsCustomObject]@{
                Program     = $CBLFile.Name  # or $CBLFile.FullName
                Description = $Flowerbox -join [environment]::NewLine
            }
            $Flowerbox.Clear()  # empty the list for the next run
            $treat = $false
        }
        default {
            # as I have no idea what these lines may look like, I have to
            # assume your regex '\*(.{62})' is correct..
            if ($treat -and ($_ -match '\*(.{62})')) { 
                $Flowerbox.Add($Matches[1])
            }
        }
    }
}

# now you have everything in an array of PSObjects so you can save that as Csv
$result | Export-Csv -Path 'C:\Desc.csv' -UseCulture -NoTypeInformation

参数-UseCulture 确保您可以双击文件,以便在 Excel 中正确打开


您还可以通过编程方式从此 csv 创建 Excel 文件,例如:

$excel = New-Object -ComObject Excel.Application 
$excel.Visible = $false
$workbook = $excel.Workbooks.Open('C:\Desc.csv')
$worksheet = $workbook.Worksheets.Item(1)
$worksheet.Name = "XXXXX_Desc"

# save as .xlsx
# 51 ==> [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault
# see: https://docs.microsoft.com/en-us/office/vba/api/excel.xlfileformat
$workbook.SaveAs('C:\Desc.xlsx', 51) 

# quit Excel and remove all used COM objects from memory
$excel.Quit()
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($worksheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

【讨论】:

  • 嘿伙计,谢谢你的代码。不幸的是,它没有捕捉到 IDENTIFICATION DIVISION 和 ENVIRONMENT DIVISION 之间的内容。
  • @user3166462 啊,我知道缺少什么了。明天补上。
  • 甜蜜!谢谢!我周末外出 - 我将在星期一登录以查看您的解决方案
  • @user3166462 已编辑;)
  • 这就像一个魅力!太棒了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-28
  • 2020-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多