ぽんこつプログラマーの日々のまとめ
vb_post_img


ホームページ作成やブログを作成している時に何かと不便に感じるのが、画像等の名前を決めること。
そんな鬱憤を晴らすべきVBサンプルを作ろうと思う。
このサンプルはディレクトリ(フォルダ)内のファイルを取得して、一斉にランダムな文字で置換するというもの。また、頭文字や末尾に任意の文字を追加できるようにする。

ただこのサンプルでは、システムファイル等の重要なファイルの検知は行っていないので、各自責任を持って実行してください。OSが吹っ飛んでも私は責任はとれませんので悪しからず。

1.プロジェクトの新規作成
Visual Stadioを起動し、プロジェクト名「Renamer」で作成。
工程が解らないばあいはこちらを参照。

デザイナを利用して、フォーム上にコントロールを配置していく。

12101900
・Form1
Text = Renamer (タイトル部分の文字
MaximizeBox = False (最大化ボタンを選択不可に
FormBorderStyle = FixdDialog (フォームのサイズを変更できないように

・TextBoxコントロール ... tPath
特に変更なし

・CheckBoxコントロール ... cFirst
Checkd = True (チェック状態をチェック済に変更
Text = 頭文字を使用

・TextBoxコントロール ... tFirst
特に変更なし

・CheckBoxコントロール ... cEnd
Checkd = True
Text = 末文字を使用

・TextBoxコントロール ... tEnd
特に変更なし

・Labelコントロール ... Label1
Text = ランダム文字数

・NumericUpDown ... nNum
Value = 5 (表示されている数値
TextAlign = Right (文字をどこに寄せるか
Maximum = 10 (最大数値
Minimum = 1 (最小数値

・Labelコントロール ... Label2
Text = 使用する文字

・CheckBoxコントロール ... cSmall
Checkd = True
Text =  a - z

・CheckBoxコントロール ... cLarge
Checkd = True
Text =  A - Z

・CheckBoxコントロール ... cNum
Checkd = True
Text =  0 - 9

・Buttonコントロール ... bOpen
Text = 参照

・Buttonコントロール ... bRun
Text = 変換実行


2.ディレクトリを選択する
bOpenボタンのクリックイベントに、ディレクトリを指定するソースを記述する。

  ' 参照ボタンイベント
  Private Sub bOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bOpen.Click
    ' OpenFileDialogのインスタンスを作成
    Dim fbd As New FolderBrowserDialog
    ' メッセージの設定
    fbd.Description = "フォルダを指定してください。"
    ' Rootディレクトリの設定
    fbd.RootFolder = Environment.SpecialFolder.Desktop
    ' 初期選択のディレクトリを設定
    fbd.SelectedPath = "C:\"
    ' 新規フォルダ作成のボタンを非表示に
    fbd.ShowNewFolderButton = False
    ' ダイアログを表示し、OKボタンが押されていたらパスをテキストボックスに入れる
    If fbd.ShowDialog() = DialogResult.OK Then Me.tPath.Text = fbd.SelectedPath
  End Sub
まずは、ディレクトリを選択してもらうための「FolderBrowerDialog」コントロールのインスタンスを作成する。インスタンスとは”実体”の事であり、型(クラス)を実際に使えるように生成する。
今までデザイナを使用してコントロールを配置していたが、このようにソースから直にコントロールのインスタンスを作成することができる。その気になればデザイナを一切使わずにソフトを作ることも可能。ここで注意して欲しいのが"New"というキーワード。これを入れないとインスタンスは作成されず、アクセスした際にエラーが起こる。
次にダイアログの設定を行い、「ShowDialog()」関数でダイアログを表示している。インスタンスを作成するだけでは表示しないので明示的に関数を実行する必要がある。

If fbd.ShowDialog() = DialogResult.OK Then Me.tPath.Text = fbd.SelectedPath
お馴染みのIf文だがこのように一行で書くことも可能。
この場合は「もしもOKボタンが押されたら、選択されたディレクトリのパス(場所)をTextBoxコントロールに入れる」という処理。ShowDialog関数には"戻り値"があり、OKボタンを押した場合は「DialogResult.OK」を返し、それ以外は「DialogResult.Cancel」を返す。

3.変更するファイルタイプ(拡張子)を選択するダイアログを実装する。
ディレクトリ内、全ファイルの名前を変更してしまうと何かと不味い事が起こると思うので、拡張子によって変換するか判定するようにする。

まずはソリューションエクスプローラ上で右クリックし、 追加>クラス を選択する。
12101901

ダイアログが表示されたら、一覧から「ダイアログ」を選択し、ファイル名を「CDialog.vb」にしてOKボタンを押す。
12101902

するとソリューションエクスプローラにCDialog.vbという項目が追加される。
そのアイコンをダブルクリックするとデザイナが表示され、フォームを設定したように、コントロールを配置することができる。

下図のようにコントロールを配置する。
12101903
・CDialog
Text = "変換するファイルの選択"

・CheckedListBoxコントロール ... clExtension
特になし


4.ファイル名を変更(Rename)する。
bRunのクリックイベントにファイル名を変更するソースを記述する。

 ' 変換実行ボタンイベント
  Private Sub bRun_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bRun.Click
    ' ディレクトリが選択されていない場合とディレクトリが存在しない場合処理終了
If Me.tPath.Text = "" Or Me.tPath.Text.Length = 0 Or System.IO.Directory.Exists(tPath.Text) = False Then
MsgBox("ディレクトリが存在しません。", MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation, "ERROR")
Exit Sub
End If ' ディレクトリ内に含まれるファイルのフルパスを取得 Dim files As String() = System.IO.Directory.GetFiles(tPath.Text, "*", System.IO.SearchOption.TopDirectoryOnly) If files.Length > 0 Then ' 拡張子により変換しないファイルを選択するダイアログのインスタンスを作成 Dim dExt As New CDialog ' ファイルが存在する場合はファイルの詳細を取得する為のF配列を作成 Dim fInfo(files.Length - 1) As System.IO.FileInfo ' 取得したファイルパスをFor文でまわす For i As Integer = 0 To files.Length - 1 ' ファイルパスから詳細を取得 fInfo(i) = New System.IO.FileInfo(files(i)) If dExt.clExtension.Items.IndexOf(fInfo(i).Extension) = -1 And fInfo(i).Extension.Length > 1 Then ' すでに拡張子リストに追加されてない場合と、不正拡張子で無い場合はリストに格納 Dim id As Integer = dExt.clExtension.Items.Add(fInfo(i).Extension) ' チェック状態の切り替え dExt.clExtension.SetItemChecked(id, True) End If Next i If dExt.ShowDialog = Windows.Forms.DialogResult.OK Then ' ダイアログを表示し、OKボタンが押された場合は処理 ' 取得したファイル詳細の数分まわす For i As Integer = 0 To fInfo.Length - 1 If dExt.clExtension.CheckedItems.IndexOf(fInfo(i).Extension) > -1 Then ' 拡張子リストでチェックの入っている項目のみ変換 ' 最終的にファイル名になる文字を格納する変数 Dim rn As String = "" ' 使用するランダム文字数まわす For j As Integer = 1 To nNum.Value ' 数値を入れる変数 Dim n As String = "" ' 文字を入れる変数 Dim s As String = "" ' 数値を使う場合は実行 If cNum.Checked Then n = Me.Random(10).ToString ' 文字列を使う場合は実行 If cSmall.Checked Or cLarge.Checked Then s = GetRandString() ' 文字列、数値を両方使う場合はどちらかをランダムに選択 If n.Length > 0 And s.Length > 0 Then rn &= IIf(Me.Random(2), n, s) Else rn &= n & s End If Next j '同一ファイル名がある場合はエラーとなるのでチェック Dim f As Boolean = False Dim cfInfo As String() = System.IO.Directory.GetFiles(tPath.Text, "*", System.IO.SearchOption.TopDirectoryOnly) For j As Integer = 0 To cfInfo.Length - 1 If InStr(cfInfo(j), rn) > 0 Then f = True Next j If Not f Then ' 同一ファイル名が存在しな場合はRename ' 頭文字を使う場合は文字列を取得 Dim sFirst As String = IIf(cFirst.Checked, tFirst.Text, "") ' 末文字を使う場合はry Dim sEnd As String = IIf(cEnd.Checked, tEnd.Text, "") ' 元の拡張子を取得 Dim ext As String = fInfo(i).Extension ' Renameする My.Computer.FileSystem.RenameFile(fInfo(i).FullName, sFirst & rn & sEnd & ext) Else '同一ファイル名が存在する場合はもう一度廻す i -= 1 End If End If Next i End If End If End Sub
少し長いソースだが慌てないで欲しい。ひたすら書いてたら何時かは終わるから。
まずエラー回避の為、ディレクトリが選択されていない場合と、ディレクトリが存在しない場合は処理を停止するように記述する。

If tPath.Text = "" Or tPath.Text.Length = 0 Or System.IO.Directory.Exists(tPath.Text) = False Then
tPath.Textは「tPath」コントロールの「Text」プロパティを参照するという意味。その値が""(文字が無い)の場合とLength(文字数)が0の場合、ディレクトリが存在しない場合は処理を抜ける。
そして今回初めて出てきた「Or」だが、If文はひとつの判定ではなく、複数の判定を一度に行うことができる。意味もそのまんまで「または」という意味。
このIf文は
もし パスの文字がない または 文字数が0 または ディレクトリが存在しない 場合は
という意味である。

Or」のほかに、「And」もある。こちらもそのまんまの意味で「それと」。使い方は「Or」と同じく、判定文の間に記述する。
例: If hoge > 0 And hoge < 2 Then この場合hogeが1ならTrue それ以外はFalse
使い方は同じだか、判定処理の動作が違うので注意すること。
Or」は判定のいずれかひとつが成立(True)すると処理を行うが、「And」はすべての判定が成立しないと処理を行わない。

例:
'---------
 hoge = 3

 If hoge > 0 And hoge < 2 Then
   処理されない
 End If

 If hoge > 0 Or hoge < 2 Then
   処理される
 End If
--------

※さらに「Orelse」や「Andalso」もあるがここでは混乱するので説明しない。

何らかの判定式が成立しなかった場合はメッセージボックスを表示して処理を抜ける。
MsgBox("ディレクトリが存在しません。", MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation, "ERROR")
これもまたよく使う関数。第一引数(引数とは関数の括弧内に与えるオブジェクトのこと)に表示する文字を、第二引数に表示するボタンとアイコン等を、第三引数にタイトルを与える事で、自動的にメッセージボックスを表示してくれる。
「Exit sub」は処理を抜けるよーというおまじない。

ディレクトリが選択され尚且つ存在する場合は、そのディレクトリに含まれるファイルのフルパスを取得する。
Dim files As String() = System.IO.Directory.GetFiles(tPath.Text, "*", System.IO.SearchOption.TopDirectoryOnly)
今回は、選択されたディレクトリの直下のファイルだけを対象とするが、「GetFiles」の第三引数の「TopDirectoryOnly」を「AllDirectories」に変更することで、再帰的にディレクトリを掘ってくれる。

次に先程作成したCDialogのインスタンスと、ファイルの詳細を格納するための配列変数を作成する。
配列とは、ひとつの変数で何個分も値を保持させる便利なもの。
宣言の仕方は普通の変数と同じく、
Dim hoge(1) As String
みたいな感じで行う。
この場合は、hoge(0) と hoge(1) のふたつのString型変数を作成した事になる。※プログラミングの数字は0から始まるので注意 (1)を要素数と呼び、宣言と同時に要素数を設定した配列を、静的配列と呼ぶ。静的があるのだからもちろん動的配列もある。動的配列の場合は、
Dim hoge() As String または Dim hoge As String()
のように記述し、後々要素数を設定して使う。



全体ソース
Public Class Form1

  ' 参照ボタンイベント
  Private Sub bOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bOpen.Click
    ' OpenFileDialogのインスタンスを作成
    Dim fbd As New FolderBrowserDialog
    ' メッセージの設定
    fbd.Description = "フォルダを指定してください。"
    ' Rootディレクトリの設定
    fbd.RootFolder = Environment.SpecialFolder.Desktop
    ' 初期選択のディレクトリを設定
    fbd.SelectedPath = "C:\"
    ' 新規フォルダ作成のボタンを非表示に
    fbd.ShowNewFolderButton = False
    ' ダイアログを表示し、OKボタンが押されていたらパスをテキストボックスに入れる
    If fbd.ShowDialog() = DialogResult.OK Then Me.tPath.Text = fbd.SelectedPath
  End Sub

  ' 変換実行ボタンイベント
  Private Sub bRun_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bRun.Click
    ' ディレクトリが選択されていない場合とディレクトリが存在しない場合処理終了
    If Me.tPath.Text = "" Or Me.tPath.Text.Length = 0 Or System.IO.Directory.Exists(tPath.Text) = False Then
      MsgBox("ディレクトリが存在しません。", MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation, "ERROR")
      Exit Sub
    End If

    ' ディレクトリ内に含まれるファイルのフルパスを取得
    Dim files As String() = System.IO.Directory.GetFiles(tPath.Text, "*", System.IO.SearchOption.TopDirectoryOnly)

    If files.Length > 0 Then
      ' 拡張子により変換しないファイルを選択するダイアログのインスタンスを作成
      Dim dExt As New CDialog
      ' ファイルが存在する場合はファイルの詳細を取得する為のF配列を作成
      Dim fInfo(files.Length - 1) As System.IO.FileInfo

      ' 取得したファイルパスをFor文でまわす
      For i As Integer = 0 To files.Length - 1
        ' ファイルパスから詳細を取得
        fInfo(i) = New System.IO.FileInfo(files(i))

        If dExt.clExtension.Items.IndexOf(fInfo(i).Extension) = -1 And fInfo(i).Extension.Length > 1 Then
          ' すでに拡張子リストに追加されてない場合と、不正拡張子で無い場合はリストに格納
          Dim id As Integer = dExt.clExtension.Items.Add(fInfo(i).Extension)
          ' チェック状態の切り替え
          dExt.clExtension.SetItemChecked(id, True)
        End If
      Next i

      If dExt.ShowDialog = Windows.Forms.DialogResult.OK Then
        ' ダイアログを表示し、OKボタンが押された場合は処理

        ' 取得したファイル詳細の数分まわす
        For i As Integer = 0 To fInfo.Length - 1

          If dExt.clExtension.CheckedItems.IndexOf(fInfo(i).Extension) > -1 Then
            ' 拡張子リストでチェックの入っている項目のみ変換
            ' 最終的にファイル名になる文字を格納する変数
            Dim rn As String = ""

            ' 使用するランダム文字数まわす
            For j As Integer = 1 To nNum.Value
              ' 数値を入れる変数
              Dim n As String = ""
              ' 文字を入れる変数
              Dim s As String = ""
              ' 数値を使う場合は実行
              If cNum.Checked Then n = Me.Random(10).ToString
              ' 文字列を使う場合は実行
              If cSmall.Checked Or cLarge.Checked Then s = GetRandString()
              ' 文字列、数値を両方使う場合はどちらかをランダムに選択
              If n.Length > 0 And s.Length > 0 Then
                rn &= IIf(Me.Random(2), n, s)
              Else
                rn &= n & s
              End If
            Next j

            '同一ファイル名がある場合はエラーとなるのでチェック
            Dim f As Boolean = False
            Dim cfInfo As String() = System.IO.Directory.GetFiles(tPath.Text, "*", System.IO.SearchOption.TopDirectoryOnly)
            For j As Integer = 0 To cfInfo.Length - 1
              If InStr(cfInfo(j), rn) > 0 Then f = True
            Next j

            If Not f Then
              ' 同一ファイル名が存在しな場合はRename
              ' 頭文字を使う場合は文字列を取得
              Dim sFirst As String = IIf(cFirst.Checked, tFirst.Text, "")
              ' 末文字を使う場合はry
              Dim sEnd As String = IIf(cEnd.Checked, tEnd.Text, "")
              ' 元の拡張子を取得
              Dim ext As String = fInfo(i).Extension
              ' Renameする
              My.Computer.FileSystem.RenameFile(fInfo(i).FullName, sFirst & rn & sEnd & ext)
            Else
              '同一ファイル名が存在する場合はもう一度廻す
              i -= 1
            End If
          End If
        Next i
      End If
    End If

  End Sub

  ' ランダムな文字を1文字返す
  Private Function GetRandString() As String
    ' まず使用文字を配列に小文字で格納
    Dim c() As String = {"a", "b", "c", "d", "e", "f", "g", _
                         "h", "i", "j", "k", "l", "m", "n", _
                         "o", "p", "q", "r", "s", "t", "u", _
                         "v", "w", "x", "y", "z"}
    ' ランダムな1文字を取得する
    Dim re As String = c(Me.Random(c.Length - 1))
    ' 大文字を使う場合と小文字を使わない場合は大文字に変換
    If cLarge.Checked Then
      If Random(2) Or cSmall.Checked = False Then re = re.ToUpper
    End If
    ' 値を返す
    Return re
  End Function

  ' ランダムな数値を返す関数
  ' 参考 http://dobon.net/vb/dotnet/programing/random.html#section2
  Private Function Random(Optional ByVal Max As Integer = 0) As Integer
    ' バイト型の配列を用意
    Dim bs As Byte() = New Byte(3) {}
    ' 暗号乱数ジェネレータのインスタンスを作成
    Dim rng As New System.Security.Cryptography.RNGCryptoServiceProvider()
    ' ランダムな値を設定
    rng.GetBytes(bs)
    ' バイト配列をInteger型に変換
    Dim i As Integer = System.BitConverter.ToInt32(bs, 0)
    If Max <> 0 Then
      ' Max値が入力されている場合は、Max値で割った余りを返すようにする
      Return Math.Abs(i Mod Max)
    Else
      ' 入力されてない場合はそのまま返す
      Return i
    End If
  End Function


End Class


Add Comments

名前
 
  絵文字
 
 
webmaster

Redmusk

最西端の地で釣りとギターとゲームをこよなく愛する本業ぽんこつプログラマー。今を生きるを座右の銘とし日々快楽だけを求め切磋琢磨しております。

soundcloud