Powershell Excel-使用新范围进行搜索会给出旧范围的错误

时间:2018-07-02 18:03:46

标签: excel vba excel-vba powershell

我是Microsoft PowerShell的完整入门者,但是我使用过C ++,Java和C#。我当时正在为自己的工作编写这个小脚本,但遇到一个奇怪的问题,可能是由于我没有正确了解范围的工作原理。该脚本应该打开一个Excel工作簿,在每个工作表中搜索一个名称,并提供与其信息匹配的名称。问题是,当我再次设置范围以搜索信息的起始列索引(在这种情况下,该列位于标有“描述”的列的右侧)时,当它搜索多个匹配项时,它将打破范围相同的姓氏。

我有一个使用worksheet.range.entirerow.findnext()的do-while循环,因此我可以找到多个具有相同姓氏的对象。在使用新范围worksheet.range.entirecolumn.find()之前,此方法一直有效。这是我尝试过的最新代码,但是我已经尝试将$ Range硬编码为5(可以,但是我希望它是动态的)或使用了新变量$ RowRange(未能解决问题)。如果我正确理解,范围就像当前选择的两个或多个单元格一样,那么为什么不能重置它或使用新变量呢?它不会循环播放,因此我只会在每张纸上不断查找名字。

P.S。作为附带的问题,我遇到了一个问题,即将我要在后台打开的Excel文档关闭,而又不关闭其他Excel工作簿。由于某种原因,使用Get-Process EXCEL停止过程-强制关闭我所有打开的工作簿。我已将其注释掉,但我担心执行完此代码后该过程还没有结束。

# Prepare output file for results
$FileName = "TEST";
$OutputFile = "Results.txt";
Remove-Item $OutputFile;
New-Item $OutputFile -ItemType file;
$Writer = [System.IO.StreamWriter] $OutputFile;
Clear-Host
Write-Host Starting...

# Start up Excel
$Excel = New-Object -ComObject Excel.Application;
$File = $FileName + ".xlsx";

# Prompt user for last name of person to search for (and write to the Results.txt output file)
Clear-Host
Write-Host Search for users in each region by their last name.
$SearchLastName = Read-Host -Prompt "Please input the person's last name";
Write-Host Searching for person...;
$Writer.WriteLine("Name Search: " + $SearchLastName);
$Writer.WriteLine("");

# Then open it without it being made visible to the user
$Excel.Visible = $false;
$Excel.DisplayAlerts = $true;
$Excel.Workbooks.Open($File);

# For each worksheet, or tab, search for the name in the first column (last names)
$Excel.Worksheets | ForEach-Object{
    $_.activate();
    $Range = $_.Range("A1").EntireColumn;

    # Note: To search for text in the ENTIRETY of a cell, need to use the find method's lookat 
    # parameter (use 1). Otherwise, if searching for Smith, Nesmith also gets detected.
    $SearchLast = $Range.find($SearchLastName,[Type]::Missing,[Type]::Missing,1);

    $Writer.WriteLine($_.name + ": ");
    if ($SearchLast -ne $null) {
        $FirstRow = $SearchLast.Row;
        do {
            # If a first name was found, get the first name too
            $FirstName = $_.Cells.Item($SearchLast.Row, $SearchLast.Column + 1).value();

            # Then display in proper order
            $Writer.WriteLine(" " + $SearchLast.value() + "," + $FirstName);

            # From here, find the relevant information on that person
            # Search for the column labeled "Description", the starting column is the next one, ending column is the number of used columns
            $BeginCol = $_.Range("A1").EntireRow.find("Description",[Type]::Missing,[Type]::Missing,1).Column + 1;
            $MaxColumns = $_.UsedRange.Columns.Count;

            # Check each column for relevant information. If there are no extra rows after "Description" just skip
            for ($i = $BeginCol; $i -le $MaxColumns; $i++) {
                # The information of the current cell, found by the row of the name and the current row
                $CurrentCell = $_.Cells.Item($SearchLast.Row, $i);

                # Only add the description if it exists.
                if (!([string]::IsNullOrEmpty($CurrentCell.value2))) {
                    $Description = $_.Cells.Item(1,$i).text();
                    # Concatenate the description with it's information.
                    $Display = "  - (" + $Description + ": " + $CurrentCell.text() + ")";

                    # Display the information
                    $Writer.WriteLine($Display);
                }
            }

            $Writer.WriteLine("");

            # Keep searching that name in the current workbook until it finds no more
            $SearchLast = $Range.FindNext($SearchLast);

        } while (($SearchLast -ne $null) -and ($SearchLast.Row -ne $FirstRow));
    } else {
        $Writer.WriteLine("Not Found");
    }

    $Writer.WriteLine("");
};

# Cleaning up the environment

$Writer.close();
$Excel.Workbooks.Item($FileName).close();

$Excel.Quit();

# Force quit the Excel process after quitting
# Get-Process EXCEL | Stop-Process -Force;

# Then remove the $Excel com object to ready it for garbage collection
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel);

# Then, open up the Results.txt file
Invoke-Item Results.txt;

0 个答案:

没有答案