ソフトウェア開発 / PowerShell / FolderStructureCreator

FolderStructureCreator

# ----------------------------------------------------------
# インポート
# ----------------------------------------------------------
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) {
        $olumnIndex = 1 + ($entry.IndexLevel * $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.Cells($topLeftRange, $bottomRightRange)
            Set-ExcelCellBackgroundColor $backGroundColorRange $EXCEL_BACKGROUND_COLOR_FOLDER

            $bottomRightRange = $worksheet.Cells($topLeftRange, $worksheet.Cells($rowIndex, $endsColumnIndex))
            $backGroundColorRange = $worksheet.Range($topLeftRange, $bottomRightRange)
            Set-ExcelCellBackgroundColor $backGroundColorRange $EXCEL_BACKGROUND_COLOR_FOLDER
        } else {
            $bottomRightRange = $worksheet.Cells($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 Greate-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()

トップ   一覧 検索 最終更新   ヘルプ   最終更新のRSS