見出し画像

6.[PG2]Excelで、ファイル一覧作成し、ファイル名変更してみよう.part4

こちら第6回「プログラマー養成講座」のパート1になります!
目次はこちらからご参照下さい!

いよいよ
γ.ファイル名変更プログラム仕様(Excel VBA)
に取り掛かります!

さて、日も変わりましたし、頑張っていきましょう!

今回の新技術は、「IF文」「ファイル存在チェック」「ファイル名の変更」くらいで、他は前回までのプログラムにだいたい書いてあることの応用でなんとかなると思います。

今日は工程数が多いので、今やってることを小見出しで明記しつつ、進めていきましょうか。やっていることが明確化されてわかりやすく、頭がこんがらがるのを防げるかもしれません。

師匠

頑張ります!

変更したいファイル名のセルの右隣のセル(つまりB行)に変更後のファイル名を記入

ん~、ファイル名の記入ってことは、ここはプログラムじゃないのかな。適当にファイル名を記入します!

シート上に「実行」ボタンを設置

次は実行ボタンの設置か。読取ボタンと同じですね!

A1から下に処理を実施し、空になったら終了とする

あー、まずはプロシージャ作って、実行ボタンに設定しておこう。

じゃん!

じゃん!じゃん!
ひとまず前に師匠が書いてくれた、前のシートの情報をクリアする処理と同じ感じで書いとけばいいのかな。

Public Sub Jikkou()

'宣言
Dim i As Integer

'初期値設定
i = 1

'ループしてA行が、空になるまで処理
Do Until Worksheets("ファイル一覧").Cells(i, 1).Value = ""

    i = i + 1
Loop

End Sub

こんな感じかな。

いいですね、ここまでスムーズに進むと、私からアドバイス必要なく今回はできちゃったりしますかね!?

師匠

「実行」ボタンを押したときに、変更後のファイル名に記入のあるファイルの名前を変更する

これは次の課題と一緒にやったほうがいいですね。ちなみに「ファイル名の記入がない場合」は、ファイル名を変更する必要がないものと考えて下さい。

結果はC行に表示する

この2個ですね。わかりました!
ループまでは書いてあるし、中身を作っていくんだよな。
B行の値は・・・
Worksheets("ファイル一覧").Cells(i, 2).Value
で取れるのかな?
どうすればそれが検証できるのかな・・・

プログラムの完成形には必要ないですが、動作確認は大事ですね。そういうときは「debug.print XXXXX」と書くと「イミディエイト」ウィンドウに内容が表示されますので便利です。

今回の場合は、ループ内に
Debug.Print Worksheets("ファイル一覧").Cells(i, 2).Value
と書いてみましょう。

師匠

動きました!
なるほど、空白の行も処理されてるのかな?

そういうときは
Debug.Print Worksheets("ファイル一覧").Cells(i, 1).Value
Debug.Print Worksheets("ファイル一覧").Cells(i, 2).Value
と連続して書いちゃったり、
Debug.Print Worksheets("ファイル一覧").Cells(i, 1).Value & ":" & Worksheets("ファイル一覧").Cells(i, 2).Value
と繋げて書いちゃうと便利ですよ!

師匠

うわー、繋げて書くとわかりやすい!
えっと、次は・・・。ファイル名の変更を書く感じかな?

その前に「セルに値があるか/ないか」の処理を書くのがいいかもですね。試しに
ファイル名の記入(B列の記入)の判定を、C列に「ある」「ない」
と表示してみるとわかりやすいんじゃないでしょうか。
その後で「ある」ときだけ「ファイル名の変更」を記述する感じで進めてみましょう。

師匠

「ファイル名の記入があるか場合」ですね。なんて検索すればいいか・・・。そのまま検索してみようかな。「VBA ファイル名の記入があるか場合」っと・・・。
思った結果とは違うけど、「ファイルやフォルダの存在チェック」とか引っかかった。これ後で使うやつじゃないかな。この検索結果はとっておこう。

ん~、「VBA セルに値があるか/ないか」とか?
このサイトいけそう。「[Excel VBA]セルが空欄かどうか調べるには?」ってやつがありました!

    If ActiveCell.Value = "" Then
        Worksheets("ファイル一覧").Cells(i, 3).Value = "あり"
    Else
        Worksheets("ファイル一覧").Cells(i, 3).Value = "なし"
    End If

動かしてみよう。
あれ、全部「なし」になった!?
ん~、これかな。

'If ActiveCell.Value = "" Then
If Worksheets("ファイル一覧").Cells(i, 2).Value = "" Then
    Worksheets("ファイル一覧").Cells(i, 3).Value = "あり"
Else
    Worksheets("ファイル一覧").Cells(i, 3).Value = "なし"
End If

お、動いたけど、結果が逆だ。「あり」「なし」を入れ替えたらOKかな。

じゃぁ、いよいよファイル名変更かな。「vba ファイル名 変更」で検索してみようかな。

Name Oldpathname As Newpathname

これで出来るみたい。そしたらたぶん、

Name Worksheets("ファイル一覧").Cells(i, 2).Value As Worksheets("ファイル一覧").Cells(i, 3).Value

こういう感じかな?

あれ、駄目だった。
「ファイルが見つかりません。」ということは、
ファイルがないということ?
フォルダから見ると確かにファイルあるんだけど!?

Public Sub Jikkou()

'宣言
Dim i As Integer

'初期値設定
i = 1

'ループしてA行が、空になるまで処理
Do Until Worksheets("ファイル一覧").Cells(i, 1).Value = ""

'Debug.Print Worksheets("ファイル一覧").Cells(i, 1).Value & ":" & Worksheets("ファイル一覧").Cells(i, 2).Value

'If ActiveCell.Value = "" Then
If Worksheets("ファイル一覧").Cells(i, 2).Value = "" Then
    Worksheets("ファイル一覧").Cells(i, 3).Value = "なし"
Else
    Worksheets("ファイル一覧").Cells(i, 3).Value = "あり"
    Name Worksheets("ファイル一覧").Cells(i, 2).Value As Worksheets("ファイル一覧").Cells(i, 3).Value
End If

i = i + 1

Loop

End Sub

うーん、検索してみるか。
「VBA NAME ファイルが見つかりません」とかかな。
なるほど、存在しないファイル名が指定されているときに出るエラーメッセージらしいです。
うーんなんでだろう?
Name Worksheets("ファイル一覧").Cells(i, 2).Value As Worksheets("ファイル一覧").Cells(i, 3).Value
ここなんだろうけど、わかんないなぁ。

試しに、そのコマンド行で使っている内容をDebug.Printしてみてはどうでしょうか?

師匠

あぁ!! 指定がずれてました・・・。

'Name Worksheets("ファイル一覧").Cells(i, 2).Value As Worksheets("ファイル一覧").Cells(i, 3).Value
Name Worksheets("ファイル一覧").Cells(i, 1).Value As Worksheets("ファイル一覧").Cells(i, 2).Value

これで動くかな? あれ、まだ駄目かぁ・・・。
もうちょっと検索してみようかな。
わからない・・・。
候補ワードに今のひさきと同じ気持ちが出てきた・・・。

あるのに・・・。

結構順調に来ていましたが、つまづいちゃいましたか。色々と試してみて、頑張ってほしいですが、今までの参照するだけのプログラムとは今回は違っています。今回は「ファイル移動」を行っていますので、指定方法を間違えてしまうと、ファイルが想定外の場所に移動してしまったり、削除してはいけないファイルを削除してしまったりする可能性があります。
その可能性があるから、WEBからプログラムをコピーするときは気をつけてね、と改めて言っておきますね。

師匠

もうちょっと、頑張ってみます・・・。
「VBA ファイル名変更 うまくいかない」
「VBA NAME ファイルが見つかりません」
ん、これかな?

フルパスで書いていない場合は、プログラムの実行しているカレントフォルダ上にファイルがないから「ファイルが見つかりません」と言われていることが多い。

とあるWEBサイトより

フルパス・・・?

絶対パス=フルパスは、ドライブ名からファイル名までのフォルダを省略せずに全部書くことです。
カレントパスは、プログラムが実行されているフォルダ。
相対パスは、実行プログラムのある場所から、相対的にパスを書く形式。
あとはルートパスとかもありますが、要するに「パス」とはフォルダの場所を表すときの、起点となる場所指定方法みたいな感じですね。

師匠

つまり、ひさきのプログラムだと、シート上にはファイル名しかないので、パスがいっさい書いていないことがエラーの原因になっている? そしたらこんな感じがいいんでしょうか?

Name "C:\work\VB\" & Worksheets("ファイル一覧").Cells(i, 1).Value As Worksheets("ファイル一覧").Cells(i, 2).Value

あ、それは良くないですね!!

AS の後ろの、変更後のファイル名のところにもパスが必要ですね。
それを省略すると多分、
C:\work\VB\テストファイルA.txt
が、
C:\Program Files (x86)\Microsoft Office\root\Office16\{変更後のファイル名}
みたいな場所に飛ばされちゃいますね。
ちなみにExcelプログラムのある場所は、
タスクマネージャーを開いて、Excelのプロパティを見ると書いてあります。

師匠
Excelのプロパティ

ありがとうございます、たぶん一人でやっていたら
「ファイルがどこかに飛んで行ってしまいました・・・」ってなっていたと思います・・・。では、修正して実行してみます!

動いた、動きました!ありがとうございます!!

そしたら改めて、できたところ、まだなところをまとめると、

〇ファイルは「ファイル操作.xlsm」に機能追加とする
〇変更したいファイル名のセルの右隣のセル(つまりB行)に変更後のファイル名を記入
〇シート上に「実行」ボタンを設置
〇A1から下に処理を実施し、空になったら終了とする
〇「実行」ボタンを押したときに、変更後のファイル名に記入のあるファイルの名前を変更する
△:結果はC行に表示する
 成功した場合は青字で「成功」
 ファイルが変更できない場合などのエラー時は赤字で「エラー」
 実行前と実行後で同じファイル名の場合は黒字で「変更なし」
未:「ファイル操作.xlsm」のファイル名は変更しない
未:ファイル名変更前に、ファイル存在チェックを実施し、すでにファイルが存在する場合はエラーとして、「既にそのファイル名は存在します」といったメッセージを結果セルに表示する

半分は、いってるかな?では続いて、ぱっとみでわかりやすい
「ファイル操作.xlsm」のファイル名は変更しない
からやっていこうかな。
たぶん

If Worksheets("ファイル一覧").Cells(i, 2).Value = "" Then

ここの””を変えるだけでできるんじゃないかな?

素晴らしい!よくプログラムコードの意味を理解しているのが伝わってきますね。

師匠
If Worksheets("ファイル一覧").Cells(i, 2).Value = "" Then
    Worksheets("ファイル一覧").Cells(i, 3).Value = "なし"
Else
    If Worksheets("ファイル一覧").Cells(i, 2).Value = "ファイル操作.xlsm" Then
        Worksheets("ファイル一覧").Cells(i, 3).Value = "ファイル名は変更しない"
    Else
    End If
    
    Worksheets("ファイル一覧").Cells(i, 3).Value = "あり"
    
    'Name Worksheets("ファイル一覧").Cells(i, 2).Value As Worksheets("ファイル一覧").Cells(i, 3).Value
    'Name Worksheets("ファイル一覧").Cells(i, 1).Value As Worksheets("ファイル一覧").Cells(i, 2).Value
    'Name "C:\work\VB\" & Worksheets("ファイル一覧").Cells(i, 1).Value As "C:\work\VB\" & Worksheets("ファイル一覧").Cells(i, 2).Value
    Name ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 1).Value As ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 2).Value
End If

こんな感じですかね!

あー、そうなりましたか。あ、まずは「読取」ボタン押したときに、
A列の初期化していますが、BとC列も初期化しましょうか。

i = 1
Do Until Worksheets("ファイル一覧").Cells(i, 1).Value = ""
   Worksheets("ファイル一覧").Cells(i, 1).Value = ""
   Worksheets("ファイル一覧").Cells(i, 2).Value = ""
   Worksheets("ファイル一覧").Cells(i, 3).Value = ""
   i = i + 1
Loop

こんな感じですね。
次にひさきさんが先ほど書いたプログラムコードですが、
プログラムコードから、やりたいことは読み取れました。
Do Until ループの中で、すでに「空白でない場合は処理する」条件になっているので、

処理の順番としては、最初に
①「ファイル操作.xlsm」のファイル名は変更しないとC列に記載
②B列が空白の場合、C列は”記入なし”と記載
③B列に文字がある場合、ファイル名を変更し、C列に結果を記載

そしてそれができたあとには、
①「ファイル操作.xlsm」のファイル名は変更しないとC列に記載
②B列が空白の場合、C列は”記入なし”と記載
③B列に文字がある場合で、ファイル名変更前にチェック
 ③-1.A列のファイルが存在するか
 ③-2.B列のファイルが存在するか
 ③-3.1と2の結果問題なければ、ファイル名変更
と修正していきましょう。
本当は、ファイル名の不正文字チェックなども行うといいのですが、本日はそこらへんは省略しましょう。

師匠

なんか、すごいわかりやすい感じがする。かける気がする!
文章の書き方が違うからですかね?なんでだろう?

仕様書的な書き方から、プログラム設計書寄りの書き方に少し近づけました。これでわかりやすいと感じるなら、頭の中が少し「プログラマー」になってきているということです!

師匠

(もくもくとコーディング中・・・)
ちゃんと動いたし、まず最初の①②③はこれであってるかな。

'If ActiveCell.Value = "" Then
If Worksheets("ファイル一覧").Cells(i, 1).Value = "ファイル操作.xlsm" Then
    Worksheets("ファイル一覧").Cells(i, 3).Value = "ファイル名は変更しない"
Else
    If Worksheets("ファイル一覧").Cells(i, 2).Value = "" Then
        Worksheets("ファイル一覧").Cells(i, 3).Value = "記入なし"
    Else
        
        'Name Worksheets("ファイル一覧").Cells(i, 2).Value As Worksheets("ファイル一覧").Cells(i, 3).Value
        'Name Worksheets("ファイル一覧").Cells(i, 1).Value As Worksheets("ファイル一覧").Cells(i, 2).Value
        'Name "C:\work\VB\" & Worksheets("ファイル一覧").Cells(i, 1).Value As "C:\work\VB\" & Worksheets("ファイル一覧").Cells(i, 2).Value
        Name ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 1).Value As ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 2).Value
        Worksheets("ファイル一覧").Cells(i, 3).Value = "ファイル名を変更しました"
    
    End If
End If

お、いいですね。ちゃんと順番通りに、IF文が書けててイケてますね。

師匠

ん~、あとは、「ファイルが存在するか」のプログラムか。
「excel ファイル存在」まで入力すると予測?候補で
「excel ファイル存在チェック 関数」って出てきたから、これで検索してみよう。Dir関数ってのを使えばできるのかな?
(もくもくもく)
なんかIFが多くてわかりにくくなってきたな・・・。
とりあえずこんな感じでしょうか?

'If ActiveCell.Value = "" Then
If Worksheets("ファイル一覧").Cells(i, 1).Value = "ファイル操作.xlsm" Then
    Worksheets("ファイル一覧").Cells(i, 3).Value = "ファイル名は変更しない"
Else
    If Worksheets("ファイル一覧").Cells(i, 2).Value = "" Then
        Worksheets("ファイル一覧").Cells(i, 3).Value = "記入なし"
    Else
        If Dir(ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 1).Value) = "" Then
            Worksheets("ファイル一覧").Cells(i, 3).Value = "A列のファイルが存在しません"
        Else
            If Dir(ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 2).Value) <> "" Then
                Worksheets("ファイル一覧").Cells(i, 3).Value = "B列のファイルが存在しています"
            Else
                'Name Worksheets("ファイル一覧").Cells(i, 2).Value As Worksheets("ファイル一覧").Cells(i, 3).Value
                'Name Worksheets("ファイル一覧").Cells(i, 1).Value As Worksheets("ファイル一覧").Cells(i, 2).Value
                'Name "C:\work\VB\" & Worksheets("ファイル一覧").Cells(i, 1).Value As "C:\work\VB\" & Worksheets("ファイル一覧").Cells(i, 2).Value
                Name ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 1).Value As ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 2).Value
                Worksheets("ファイル一覧").Cells(i, 3).Value = "ファイル名を変更しました"
            End If
        End If
    
    End If
End If

あーーー、ちゃんと一発で動いたー!!!!!
すっごい嬉しいーー!!!!

おぉー、すごいですね。本格的なプログラミング初めてまだ少しなのに、考え方がプログラマーに向いているのかもしれませんね!

師匠

今回は、なんか、手ごたえがあります。つくった感が!

さきほどひさきさんが
「なんかIFが多くてわかりにくくなってきたな・・・。」の改善案ですが、今使っているIF文は、
IF ~~ ELSE ~~ END IF
って書き方ですけど、この中にIFをいっぱい書くとEND IFが量産されてわかりづらくなるんですね。そうならないためにELSE IFというものがあります。

師匠
If Worksheets("ファイル一覧").Cells(i, 1).Value = "ファイル操作.xlsm" Then
    Worksheets("ファイル一覧").Cells(i, 3).Value = "ファイル名は変更しない"
Else
    If Worksheets("ファイル一覧").Cells(i, 2).Value = "" Then
        Worksheets("ファイル一覧").Cells(i, 3).Value = "記入なし"
    Else
        If Dir(ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 1).Value) = "" Then
            Worksheets("ファイル一覧").Cells(i, 3).Value = "A列のファイルが存在しません"
        Else
            If Dir(ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 2).Value) <> "" Then
                Worksheets("ファイル一覧").Cells(i, 3).Value = "B列のファイルが存在しています"
            Else
                Name ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 1).Value As ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 2).Value
                Worksheets("ファイル一覧").Cells(i, 3).Value = "ファイル名を変更しました"
            End If
        End If
    
    End If
End If
If Worksheets("ファイル一覧").Cells(i, 1).Value = "ファイル操作.xlsm" Then
    Worksheets("ファイル一覧").Cells(i, 3).Value = "ファイル名は変更しない"

ElseIf Worksheets("ファイル一覧").Cells(i, 2).Value = "" Then
    Worksheets("ファイル一覧").Cells(i, 3).Value = "記入なし"

ElseIf Dir(ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 1).Value) = "" Then
    Worksheets("ファイル一覧").Cells(i, 3).Value = "A列のファイルが存在しません"

ElseIf Dir(ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 2).Value) <> "" Then
    Worksheets("ファイル一覧").Cells(i, 3).Value = "B列のファイルが存在しています"
        
Else
    Name ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 1).Value As ThisWorkbook.Path & "\" & Worksheets("ファイル一覧").Cells(i, 2).Value
    Worksheets("ファイル一覧").Cells(i, 3).Value = "ファイル名を変更しました"
End If

こんな感じで書き直せますね。今回のロジックはほぼ同じで、書き方だけ修正しました。
インデントっていう、1個の処理ごとに、右に少しずれていくスペースの書き方は、複雑になってくると、どんどんインデント数が増えていってしまうので、ELSEIFで書いたり、複雑な処理は関数化したりします。
ちなみにELSEIFにまとめると、END IFも1個にまとまるんで、そこらへんとっても行数が少し減ってるんでスマートに見えるかもしれません。

師匠

同じ結果になるのに、書き方が幾通りもあるものなんですね。
今までプログラムって、絶対正しいコードがあって、
それを探すみたいなことだと思ってました。

その部分はほんとに「言語」なんですよね。
わかりやすい/わかりにくい/みやすい/みにくい、
色んな書き方があります。

それを文学に近いという人もいるし、
パズルに近いという人もいるし、
できるだけ短いコードが正義だっていう人もいるのです。

そこらへんは、是非これから、色んな人が書いているフリープログラムを見て勉強して欲しいと思います。

私から見ても、きれいなコードを配布している人と、
これは真似しちゃ駄目だってコードを配布している人もいるし、
そもそも書いている人が意味を理解しないで、コピペ繋げてるだけっぽいなとかもわかるものです。

自分がガムシャラにプログラムを書くのも大事なことですが、
配布プログラムを見ることも勉強になるし、
配布プログラムを自分の思い通りに修正してみるのも結構勉強になります。

ただし、これだけは気をつけて欲しいのですが、
VBAなどはコンピューターウィルスが紛れていることもあります。
何も理解せずに、OSインストールされているCドライブをフォーマットされる危険もあります。
そこだけは十二分に気をつけて下さい。

今日はこんなところで終了ですかね。

師匠

はい、ありがとうございました!
漫画や小説みたいに、
プログラムにも書く人の癖がでるなんて知らなかったので目から鱗です。
次までに少し配布プログラムを見てみたいと思います。

今日はありがとうございました!

この記事が気に入ったらサポートをしてみませんか?