#author("2025-11-14T16:55:20+09:00","","") #author("2025-11-14T17:01:05+09:00","","") [[ソフトウェア開発>SoftwareEngineering]] / [[PowerShell>PowerShell]] / [[FolderStructureCreator>./]] *FolderStructureCreator [#c00488d5] #highlightjs([powershell]) # ---------------------------------------------------------- # インポート # ---------------------------------------------------------- Add-Type -AssemblyName System.Drawing Add-Type -AssemblyName System.Windows.Forms . "${PSScriptRoot}\ExcelHelper.ps1" # ---------------------------------------------------------- # 定数定義 # ---------------------------------------------------------- $EXCEL_BACKGROUND_COLOR_FIX_ROW = [Convert]::ToInt32("D9D9D9", 16) $EXCEL_BACKGROUND_COLOR_FOLDER = [Convert]::ToInt32("CCFFFF", 16) $EXCEL_COLUMN_SPAN = 5 # ---------------------------------------------------------- # グローバル変数定義 # ---------------------------------------------------------- $entries = New-Object System.Collections.ArrayList # ---------------------------------------------------------- # メイン画面 # ---------------------------------------------------------- $form = New-Object System.Windows.Forms.Form $form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog $form.MaximizeBox = $false $form.StartPosition = 'CenterScreen' $form.Text = "フォルダー構成" $form.Width = 640 $form.Height = 120 # ---------------------------------------------------------- # # ---------------------------------------------------------- $bottomTableLayoutPanel = New-Object System.Windows.Forms.TableLayoutPanel $bottomTableLayoutPanel.Dock = [System.Windows.Forms.DockStyle]::Bottom $bottomTableLayoutPanel.Height = 50 $bottomTableLayoutPanel.RowCount = 1 $bottomTableLayoutPanel.ColumnCount = 2 $bottomTableLayoutPanel.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle([System.Windows.Forms.SizeType]::Percent, 100))) | Out-Null $bottomTableLayoutPanel.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle([System.Windows.Forms.SizeType]::AutoSize))) | Out-Null $form.Controls.Add($bottomTableLayoutPanel) # ---------------------------------------------------------- # 実行ボタン # ---------------------------------------------------------- $executeButton = New-Object System.Windows.Forms.Button $executeButton.Width = 80 $executeButton.Height = 30 $executeButton.Text = '実行' $executeButton.Anchor = [System.Windows.Forms.AnchorStyles]::None $executeButton.Margin = New-Object System.Windows.Forms.Padding(10, 0, 10, 0) $bottomTableLayoutPanel.Controls.Add($executeButton, 1, 0) # ---------------------------------------------------------- # # ---------------------------------------------------------- $fillTableLayoutPanel = New-Object System.Windows.Forms.TableLayoutPanel $fillTableLayoutPanel.Dock = [System.Windows.Forms.DockStyle]::Fill $fillTableLayoutPanel.Height = 50 $fillTableLayoutPanel.RowCount = 2 $fillTableLayoutPanel.ColumnCount = 2 $fillTableLayoutPanel.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle([System.Windows.Forms.SizeType]::Percent, 15))) | Out-Null $fillTableLayoutPanel.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle([System.Windows.Forms.SizeType]::Percent, 85))) | Out-Null $form.Controls.Add($fillTableLayoutPanel) # ---------------------------------------------------------- # # ---------------------------------------------------------- $targetLabel = New-Object System.Windows.Forms.Label $targetLabel.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left $targetLabel.Margin = New-Object System.Windows.Forms.Padding(5, 5, 5, 5) $targetLabel.AutoSize = $true $targetLabel.Text = 'パス' $fillTableLayoutPanel.Controls.Add($targetLabel, 0, 0) $targetTextBox = New-Object System.Windows.Forms.TextBox $targetTextBox.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left $targetTextBox.Margin = New-Object System.Windows.Forms.Padding(5, 5, 5, 5) $targetTextBox.Width = 515 $targetTextBox.Text = '' $targetTextBox.AllowDrop = $true $fillTableLayoutPanel.Controls.Add($targetTextBox, 1, 0) $targetTextBox.Add_DragDrop({ foreach ($filename in $_.Data.GetData([System.Windows.Forms.DataFormats]::FileDrop)) { $targetTextBox.Text = $filename break } }) $targetTextBox.Add_DragOver({ foreach ($filename in $_.Data.GetData([System.Windows.Forms.DataFormats]::FileDrop)) { $_.Effect = [System.Windows.Forms.DragDropEffects]::All } }) # ---------------------------------------------------------- # # ---------------------------------------------------------- $executeButton.Add_Click({ Create-FolderStructure -RootFolderPath $targetTextBox.Text $form.TopMost = $true [System.Windows.Forms.MessageBox]::Show($form, 'たいへんよくできました', '通知', 'OK', 'Information') $form.TopMost = $false }) # ---------------------------------------------------------- # Excel にフォルダー構成を出力します。 # ---------------------------------------------------------- function Write-ExcelFolderStructure { $worksheet = Get-ExcelFirstWorksheet $workbook $worksheet.Name = 'フォルダー構成' $worksheet.Cells.ColumnWidth = 2 $excel.ActiveWindow.DisplayGridlines = $false $maxIndentLevel = ($entries | ForEach-Object {$_.IndentLevel} | Measure-Object -Maximum).Maximum $endsColumnIndex = ($maxIndentLevel * $EXCEL_COLUMN_SPAN) + $EXCEL_COLUMN_SPAN $containerColumnIndex = $endsColumnIndex + 1 $startsDetailRowIndex = 2 $endsDetailRowIndex = $startsDetailRowIndex + $entries.Count - 1 # ---------------------------------------------------------- # ヘッダー # ---------------------------------------------------------- $worksheet.Cells(1, 1).Value = 'ルート' $outerBorderRange = $worksheet.Range($worksheet.Cells(1, 1), $worksheet.Cells(1, 1 + $EXCEL_COLUMN_SPAN - 1)) Draw-ExcelOuterBorder $outerBorderRange $backGroundColorRange = $worksheet.Range($worksheet.Cells(1, 1), $worksheet.Cells(1, 1 + $EXCEL_COLUMN_SPAN - 1)) Set-ExcelCellBackgroundColor $backGroundColorRange $EXCEL_BACKGROUND_COLOR_FIX_ROW for ($indentLevel = $firstIndentLevel; $indentLevel -le $maxIndentLevel; $indentLevel++) { $columnIndex = 1 + ($indentLevel * $EXCEL_COLUMN_SPAN) $worksheet.Cells(1, $columnIndex).Value = "第 ${indentLevel} 階層" $outerBorderRange = $worksheet.Range($worksheet.Cells(1, $columnIndex), $worksheet.Cells(1, $columnIndex + $EXCEL_COLUMN_SPAN - 1)) Draw-ExcelOuterBorder $outerBorderRange $backGroundColorRange = $worksheet.Range($worksheet.Cells(1, $columnIndex), $worksheet.Cells(1, $columnIndex + $EXCEL_COLUMN_SPAN - 1)) Set-ExcelCellBackgroundColor $backGroundColorRange $EXCEL_BACKGROUND_COLOR_FIX_ROW } # ---------------------------------------------------------- # 詳細 # ---------------------------------------------------------- $rowIndex = $startsDetailRowIndex foreach ($entry in $entries) { $columnIndex = 1 + ($entry.IndexLevel * $EXCEL_COLUMN_SPAN) $columnIndex = 1 + ($entry.IndentLevel * $EXCEL_COLUMN_SPAN) $topLeftRange = $worksheet.Cells($rowIndex, $columnIndex) $topLeftRange.Value = $entry.Name if ($entry.IsContainer) { $bottomRightRange = $worksheet.Cells($rowIndex + $entry.Count, $endsColumnIndex) $outerBorderRange = $worksheet.Range($topLeftRange, $bottomRightRange) Draw-ExcelOuterBorder $outerBorderRange $bottomRightRange = $worksheet.Cells($rowIndex + $entry.Count, $columnIndex + $EXCEL_COLUMN_SPAN - 1) $backGroundColorRange = $worksheet.Range($topLeftRange, $bottomRightRange) Set-ExcelCellBackgroundColor $backGroundColorRange $EXCEL_BACKGROUND_COLOR_FOLDER $bottomRightRange = $worksheet.Range($topLeftRange, $worksheet.Cells($rowIndex, $endsColumnIndex)) $backGroundColorRange = $worksheet.Range($topLeftRange, $bottomRightRange) Set-ExcelCellBackgroundColor $backGroundColorRange $EXCEL_BACKGROUND_COLOR_FOLDER } else { $bottomRightRange = $worksheet.Range($topLeftRange, $worksheet.Cells($rowIndex, $endsColumnIndex)) $outerBorderRange = $worksheet.Range($topLeftRange, $bottomRightRange) Draw-ExcelOuterBorder $outerBorderRange } $rowIndex++ } # ---------------------------------------------------------- # ウィンドウ枠を固定する # ---------------------------------------------------------- $worksheet.Range('2:2').Select() | Out-Null $excel.ActiveWindow.FreezePanes = $true Release-ExcelComObjectSafely $worksheet } # ---------------------------------------------------------- # フォルダー構成を作成するのに必要な情報を収集します。 # ---------------------------------------------------------- function Set-FolderStructure { param ( [string]$Path ,[int]$indentLevel = 0 ) $items = Get-ChildItem -Path $Path | Sort-Object @{Expression={$_.PSIsContainer}}, @{Expression={$_.Name}} foreach ($item in $items) { $count = 1 if ($item.PSIsContainer) { $count = Get-ItemCountRecursive $item.FullName } $entry = @{ IndentLevel = $indentLevel; FullName = $item.FullName; Name = $item.Name; LastWriteTime = $item.LastWriteTime; IsContainer = $item.PSIsContainer; Count = $count } $entries.Add($entry) | Out-Null if ($item.PSIsContainer) { Set-FolderStructure $item.FullName ($indentLevel + 1) } } } # ---------------------------------------------------------- # サブフォルダーを含めたフォルダーとファイルの数を取得します。 # ---------------------------------------------------------- function Get-ItemCountRecursive { param ( $Path ) return (Get-ChildItem -Path $Path -Recurse).Count } # ---------------------------------------------------------- # フォルダー構造を作成します。 # ---------------------------------------------------------- function Create-FolderStructure { param ( $RootFolderPath ) $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() $rootFolder = Get-Item -Path $RootFolderPath $entries.Clear() $rootIndentLevel = 0 $entry = @{ IndentLevel = $rootIndentLevel; FullName = $rootFolder.FullName; Name = $rootFolder.Name; LastWriteTime = $rootFolder.LastWriteTime; IsContainer = $rootFolder.PSIsContainer; Count = Get-ItemCountRecursive $rootFolder.FullName } $entries.Add($entry) | Out-Null $firstIndentLevel = 1 Set-FolderStructure $rootFolder.FullName $firstIndentLevel try { $excel = New-ExcelApplication $excel.Visible = $true $workbook = Add-ExcelWorkbook $excel Write-ExcelFolderStructure Reset-ExcelViewState $workbook } finally { Release-ExcelComObjectSafely $workbook Release-ExcelComObjectSafely $excel } Write-Host "処理時間:[$($stopwatch.ElapsedMilliseconds)]ms" } # ---------------------------------------------------------- # 画面表示 # ---------------------------------------------------------- $form.ShowDialog()