Как вернуть объект из функции - PullRequest
0 голосов
/ 09 июля 2019

У меня большая проблема, которую я не могу понять, когда беру данные из листа Excel. Я использую эту функцию для чтения данных (1 строка) из Excel, и она делает это правильно

function ExtractExcelRows {
    [cmdletbinding()]
    Param($ExcelFile)

    # Excel.exe not autokill fix
    $before = Get-Process | % { $_.Id }
    $excel = New-Object -ComObject Excel.Application
    $excelId = Get-Process excel | % { $_.Id } | ? { $before -notcontains $_ }

    $workbook = $excel.Workbooks.Open($ExcelFile.FullName)
    $sheet = $workbook.Worksheets.Item(1)
    $excel.Visible = $false

    $rowMax = ($sheet.UsedRange.Rows).Count

    # Declare the starting positions
    $rowEmail, $colEmail = 1, 11

    $Rows = @()
    for ($i=1; $i -le $rowMax-1; $i++) {
        if ($sheet.Cells.Item($rowEmail+$i, $colEmail).Text) {
            $Rows += @{
                Email = $sheet.Cells.Item($rowEmail+$i, $colEmail).Text
            }
        }
    }

    $workbook.Close($false)
    $excel.Quit()

    Stop-Process -Id $excelId -Force

    Write-Host $Rows.Count  # count 1 row ! right!

    return $Rows
}

Когда я пытаюсь сохранить свой объект в глобальной переменной, результат подсчета отличается, и я не понимаю, почему.

$global:ExcelData = ExtractExcelRows $ExcelFile
write-host $ExcelData.Count  # count 4 row!!!! not right!

Может кто-нибудь сказать мне, где ошибка и как ее исправить?

Ответы [ 2 ]

1 голос
/ 10 июля 2019

Чтобы разместить мои комментарии в качестве ответа:

function ExtractExcelRows {
    [cmdletbinding()]
    Param($ExcelFile)

    $excel = New-Object -ComObject Excel.Application
    $excel.Visible = $false

    $workbook = $excel.Workbooks.Open($ExcelFile.FullName)
    $sheet    = $workbook.Worksheets.Item(1)
    $rowMax   = ($sheet.UsedRange.Rows).Count

    # Declare the starting positions
    $rowEmail, $colEmail = 1, 11

    $Rows = for ($i = 1; $i -lt $rowMax; $i++) {
        if ($sheet.Cells.Item($rowEmail + $i, $colEmail).Text) {
            [PSCustomObject]@{ 'Email' = $sheet.Cells.Item($rowEmail+$i, $colEmail).Text }
        }
    }

    $workbook.Close($false)
    $excel.Quit()
    # clean up used COM objects
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($sheet)    | Out-Null
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook) | Out-Null
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)    | Out-Null
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()

    Write-Host $Rows.Count  # count 1 row ! right!

    # The comma used as unary operator wraps the array in another single element array. 
    # Powershell unboxes that to return an array, even if it is empty.
    return ,$Rows
}
0 голосов
/ 09 июля 2019

Вы проверили содержимое этой переменной? Бьюсь об заклад, первые три элемента являются True / False, или что-то в этом роде. Причина заключается в том, что методы объекта com com в Excel, как правило, возвращают значение, указывающее, было ли выполнение успешным или нет, и весь вывод, который не перенаправлен явно, выводится функцией, а не только элементы, которые вы указываете с помощью return (для В этом случае нет необходимости использовать return). Вы должны передать такие вещи, как $workbook.close($false) to Out-Null как таковые:

$workbook.close($false) | Out-Null
$excel.quit() | Out-Null

Это должно учитывать 2 из 4 ваших предметов, я не уверен, что это за другой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...