Проблемы с Excel Найти / заменить одну строку в нескольких файлах Excel - PullRequest
1 голос
/ 28 февраля 2020

Я пытаюсь написать скрипт powershell, который найдет и заменит одну строку другой строкой во всех файлах Excel в каталоге. Когда я запускаю код ниже, я получаю ошибки, показанные ниже кода. Первый говорит, что он не может найти имя файла, но файл, очевидно, там или он не будет знать имя. Есть идеи?

$object = New-Object -comObject Shell.Application  
$folder = $object.BrowseForFolder(0, 'Select the folder', 0)    
$oldname = Read-Host 'Enter your old string to search for'
$newname = Read-Host 'Enter your new string'

if (!$folder -or !$oldname -or !$newname) {exit} 

$excel = New-Object -comObject Excel.Application
$excel.Visible = $true
$excel.DisplayAlerts = $true

foreach ($file in Get-ChildItem -literalPath $folder.self.Path*.xlsx) {
    $workbook = $excel.Workbooks.Open($file.name)    
    foreach ($sheet in $workbook.Sheets) {                    

        foreach ($cell in $sheet) {
            $cell.Address = $cell.Address -replace $oldname, $newname                        
        }            
    }
    $workbook.Save()
    $workbook.Close()
}
$excel.quit()    

[System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
[System.GC]::Collect() 
[System.GC]::WaitForPendingFinalizers() 

Read-Host -Prompt "Press Enter to exit"

Извините, мы не смогли найти testDo c .xlsx. Возможно ли это было перемещено, переименовано или удалено? В C: \ Users \ KAbernathy \ Documents \ replaceTest3.ps1: 13 char: 5 + $ workbook = $ excel.Workbooks.Open ($ file.name) + ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo: OperationStopped: (:) [], COMException + FullyQualifiedErrorId: System.Runtime .InteropServices.COMException

Нельзя вызвать метод для выражения с нулевым значением. В C: \ Users \ KAbernathy \ Documents \ replaceTest3.ps1: 20 char: 5 + $ workbook.Save () + ~~~~~~~~~~~~~~~~ + CategoryInfo: InvalidOperation: ( :) [], RuntimeException + FullyQualifiedErrorId: InvokeMethodOnNull

Вы не можете вызвать метод для выражения с нулевым значением. В C: \ Users \ KAbernathy \ Documents \ replaceTest3.ps1: 21 символ: 5 + $ workbook.Close () + ~~~~~~~~~~~~~~~~~ + CategoryInfo: InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId: InvokeMethodOnNull

Исключение, вызывающее «ReleaseComObject» с аргументом «1»: «Ссылка на объект не установлена ​​на экземпляр объекта.» В C: \ Users \ KAbernathy \ Documents \ replaceTest3.ps1: 25 char: 1 + [System.Runtime.Interopservices.Marshal] :: ReleaseComObject ($ workbook) + ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~ + CategoryInfo: NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId: NullReferenceException

1 Ответ

1 голос
/ 29 февраля 2020

Как прокомментировано, вы используете свойство $file.Name, где вы должны использовать $file.FullName. Это то, о чем говорится в сообщении об ошибке.

Сказав это, код довольно неэффективен и может выглядеть примерно так:

$shell = New-Object -ComObject Shell.Application  
$folder = $shell.BrowseForFolder(0, 'Select the folder', 0)    
if ([string]::IsNullOrWhiteSpace($folder)) { exit }

# release Shell COM object
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell)

$oldname = Read-Host 'Enter your old string to search for'
if ([string]::IsNullOrWhiteSpace($oldname)) { exit }

$newname = Read-Host 'Enter your new string'
if ([string]::IsNullOrWhiteSpace($newname)) { exit }

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

Get-ChildItem -Path $folder.self.Path -Filter '*.xlsx' -File | ForEach-Object {
    $workbook = $excel.Workbooks.Open($_.FullName)    
    foreach ($sheet in $workbook.Sheets) {
        $range = $sheet.UsedRange              
        $search = $range.Find($oldname)
        if ($search) {
            $firstFind = $search.Address
            do {
                $search.Value = $newname
                $search = $range.FindNext($search)
            } while ( $null -ne $search -and $search.Address -ne $firstFind)

        }
    }
    $workbook.Save()
    $workbook.Close()
}
$excel.Quit()    

# clean-up used Excel COM objects
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($sheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
[System.GC]::Collect() 
[System.GC]::WaitForPendingFinalizers() 

Read-Host -Prompt "Press Enter to exit"
  1. Установив для свойства Visible значение $ false, Excel не придется обновлять экран при каждой замене, что экономит много времени.
  2. Использование свойства листа UsedRange в сочетании с собственными методами Excels Find и FindNext быть более эффективным, чем перебирать каждую ячейку на листе самостоятельно.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...