0
4

More than 3 years have passed since last update.

PowerShellで、特定のフォルダーにあるExcelファイルから特定の検索ワードを用いた検索を行い、結果の一覧をcsvに出力する

Posted at

複数のエクセルファイルの中から、特定のキーワードを用いて検索をかける。
この時、対象のファイルが少ない場合は手動で見てまわる事も、まぁ少数でも苦行なのですが、
多数の設計書の中からひたすら検索をかけて、検索結果をまた別のエクセルにまとめて
とにかくエクセルをたくさん触らせたい!みたいなお仕事を度々頂きます。
勉強になりますね。

あんまり勉強になるので、勉強がてらスクリプトにやってもらうことにしました。
オートシェイプの中は未対応なのですが、大好きなCtrl+Fでも見てないので、
この際無視することにしました。

searchExcel.ps1
Param(
    $targetDir ,
    $searchWord ,
    $resultCsvFileName
)

if($targetDir -eq $null) {
    '-targetDir オプションを指定して、検索対象のフォルダーを指定してください。'
    return
}

if($searchWord -eq $null) {
    '-searchWord オプションを指定して、検索対象のキーワードを指定してください。'
    return
}

if($resultCsvFileName -eq $null) {
    $resultCsvFileName = Split-Path $myInvocation.MyCommand.Path -Parent
    $resultCsvFileName = Join-Path $resultCsvFileName "defaultResultFile.csv"
}

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

$datas = New-Object System.Collections.ArrayList


Get-ChildItem $targetDir -Recurse -Include "*.xlsx" , "*.xls" | ForEach-Object {

    $fullName = $_.FullName
    $fullName

    $fileOpen = $true

    try {
        $workBook = $excel.Workbooks.open($fullName)
    } catch {
        Write-Host "$fullName のオープンに失敗しました。このファイルに対する処理はスキップします。" -ForegroundColor Red
        $fileOpen = $false
    }

    if($fileOpen) {
        $workBook.WorkSheets | ForEach-Object {
            $sheet = $_
            $sheetName = $sheet.Name
            $first = $result = $sheet.Cells.Find($searchWord)
            while ($result -ne $null) {
                $data = New-Object psobject | Select-Object FullName , SheetName , Column , Row , Value2 , Formula
                $data.FullName = $fullName
                $data.SheetName = $sheetName
                $data.Column = $result.Column
                $data.Row = $result.Row
                $data.Value2 = $result.Value2
                $data.Formula = $result.Formula

                [void]$datas.Add($data)
                $result = $sheet.Cells.FindNext($result)

                try {
                    $result.Address() | Out-Null
                } catch {
                    break
                }

                if(${result}.Address() -eq ${first}.Address()) {
                    break
                }
            }
        }
        [void]$workBook.close()
    }
}

$sheet = $null
$excel.quit()
[System.GC]::Collect([System.GC]::MaxGeneration)

$resultCsvFileNameParent = Split-Path $resultCsvFileName -Parent
if((Test-Path $resultCsvFileNameParent) -eq $false) {
    New-Item -ItemType Directory $resultCsvFileNameParent
}

$datas | Export-Csv $resultCsvFileName -Encoding Default -NoTypeInformation

検索部分の処理は、こちらを参考にさせていただいております。
PowerShellで複数のExcelファイルを一括検索する

実行時には、下記の引数が必要になります。

変数名 指定内容
-targetDir 検索対象のフォルダー名 C:\temp
-searchWord 検索キーワード test
-resultCsvFileName 結果を格納するCSVファイル名 C:\temp\result.csv

(上記の例で実行すると、C:\temp配下のフォルダー内にある.xlsx/.xlsファイルを開いて、
 test 文字列を検索し、その結果をC:\temp\result.csv に書き出します。)

出来上がったcsvファイルには下記の情報が含まれます。

FullName SheetName Column Row Value2 Formula
ファイルのフルパス(含むファイル名) シート名 Value2(表示上の値) 計算式

上記の情報からValue2とかFormulaとかを書き換えて、書き戻すことによって
単純な置換だと対応しきれないようなケースを処理したりしたいわけです。
なので、このcsvを同じように一覧舐めて、FullNameを元にエクセルを開いて
sheetNameのcolumn,rowのValue2とかFormulaとかを書き換えるスクリプトが
欲しいのですが、また今度にします。

読み取り専用のチェックとかパスワードとか、ファイル開くときに出てくる
ポップアップについては対応していないので、必要に応じて修正が必要になるかと思います。

0
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
4