我是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;