見出し画像

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

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

ふぅ。では次のお題ですね。
>β.ファイル一覧の出力プログラム仕様(Excel VBA)
ざっと仕様を見た限り、αと内容は殆どおなじだけど、メッセージボックスじゃなくて「ファイル一覧シートに出力」ってところと、「読取ボタンを設置」が大きな違いでしょうか。

そうですね。大きな違いはその2つでしょうか。順番としては「読取ボタン」が先に手を付けたほうが良いかもしれません。まずは、いつも通り検索エンジンで検索からですかね。

師匠

検索ワード・・・。いつも悩むのですよね・・・。「VBA ボタン 実行」とかでしょうか?

すごい良いですね!たぶんそれでHITすると思いますよ。

師匠

ふむふむ・・・。Excelの「開発」タブにあるのか・・・。見当たらない・・・!? ひさきのExcelは開発用じゃないから?

あー、最近のExcelだとデフォルトだと「開発」タブはたぶん非表示ですね。
Excelのオプションを開いて、「リボンのユーザー設定」を選択して、右側にある「メインタブ」内の「開発」にチェックボックスをONにすれば出てくると思いますよ。

師匠
開発タブにチェックを入れる

ありがとうございます!でてきました!ではでは・・・。

ボタン作成

できました!ボタンが作れました!
なんかボタンを作ると「プログラム開発」してる感が出てきて、元気になってきました!
じゃあ、さっきのVBSプログラムを「Private Sub test()」の中にコピペすればいいかな?
どうだろう。
うわぁ、エラーがでた!

うーん? 選択状態になってるから「WScript」がエラーってことなのかな?
そもそも「WScript」ってなんだろう・・・?

VBAとVBSは文法はほとんど同じでもやっぱり違うプログラム言語なので、細かいところが違ったりします。

その1個にVBSは「WScript」が宣言しなくても使えるというのがあります。VBAでもWScriptを使う手段はありますが、ちょっと書き方が変わってきたりします。

ですが、その「WScript.Echo strMsg」でやりたいことって
「変数をメッセージ表示」
なので、サンプルで使った「msgbox」に書き換えてみましょうか。

ちなみにExcelVBA側でしか使えないものも数多くあります。例えば、そもそもExcelを扱う前提の言語なので、現在のBook情報や、現在のワークシート情報などは、宣言しなくても扱えます。

師匠

なるほど。ありがとうございます!
おー、プログラムが動きました! メッセージ表示もされました!

Option Explicit

Private Sub test()

'宣言
Dim objFileSys
Dim objFolder
Dim objFileDim strMsg

'ファイルシステムを扱うオブジェクトを作成
Set objFileSys = CreateObject("Scripting.FileSystemObject")

'c:\temp フォルダのオブジェクトを取得
'Set objFolder = objFileSys.GetFolder("C:\temp")
Set objFolder = objFileSys.GetFolder("C:\work\VB")

'初期値設定
strMsg = ""

'FolderオブジェクトのFilesプロパティからFileオブジェクトを取得
For Each objFile In objFolder.Files

'取得したファイルのファイル名を表示
'WScript.Echo objFile.Name
'strMsg =  objFile.Name
strMsg = strMsg & vbLf & objFile.Name

Next

'変数をメッセージ表示
'WScript.Echo strMsg
MsgBox strMsg

Set objFolder = Nothing
Set objFileSys = Nothing

End Sub

プロシージャ

ここでちょっと説明をはさみますね。
Private Sub test()
についての説明です。

これのプログラムの単位を「プロシージャ」といいます。今書いているプログラムのひと塊は「Private Sub {プロシージャ名}」という形式で書いてあります。

プロシージャ名は任意に決められる「プログラムのひと塊の名前」です。名前って何?と思うかもしれませんが、ボタンや他のプロシージャから呼ぶ時の名称、って感じですね。「読取ボタン」からもプロシージャ名を設定することになります。

「Sub」の部分は「他から呼ばれたときに、結果を返すかどうか」により変わります。結果を返す必要がない、実行だけする場合は「Sub」を使います。結果を返す必要がある場合は「Function」というものを使います。今回は実行するだけなので「Sub」のまま大丈夫です。
よく意味が分からないかもせんが、Functionは日本語だと「関数」という意味です。ここで関数を作るとExcelのシート上でも自分で作ったプログラムが「関数」としてSUMとかIFみたいに使うことができるようになります。現状はこれくらいの認識で大丈夫ですが、興味があれば今度シート上から読み出せるプロシージャを作ってみましょう。

最後に「Private」の部分です。プライベート、つまり狭い範囲でのみ実行可能という意味になりまして、このままだとボタンからはtestプロシージャは見えません。「Private」から「Public」に変えると、公開範囲が広くなり「読取ボタン」からも参照できるようになります。

師匠

な、なるほど。そういう意味があったのですね。ではPublicに変更すると、読取ボタンから見えるようになるっと・・・。お、でてきました!

マクロの登録

質問なのですが、たまに聞くんですけど「マクロ」って、今やってる何かが「マクロを作っている」ことになるんですか?今のtestプロシージャをボタンに設定するのも「マクロの登録」ってメニューからやってるんですけど、間違ってないですよね?

マクロは、広い意味で「自動業務」を行うような行為のことですね。Excelの場合、「人間の挙動を記録してプログラムを自動的に作る」という「マクロの記録」という機能があります。その自動記録されたものも実際はプログラムとして保存されていて、繰り返し同じような業務をするときに便利に利用することができます。ここらへんはあまり深く考えずに「マクロ」と「プログラム」は大体同じものか~、くらいの認識で大丈夫だと思います。

人に話す場合は「俺マクロ作れるんだ」というと、「あ~、Excelの自動記録のやつね」って思われがちなので「俺VBAでプログラム組めるんだ」って言ったほうがいいですね。

師匠

なるほど、わかりました。とりあえず、無事にメッセージボックスではファイル一覧が出力できるようになったので、これをエクセルのシート上に表示するようにプログラムを変更するわけですね。そしたらたぶん

strMsg = strMsg & vbLf & objFile.Name

を変更すればいいんですよね。もう一度、仕様を確認するか・・・。現時点で足りないっぽいのは、以下の3個かな。

・「C:\work\VB」フォルダの中にあるファイルを「ファイル一覧」シートに出力する
・A1から、下へ1行に1ファイル名を出力していく
・実行時に、以前の情報を「ファイル一覧」シートから削除すること

これを見る限り「ファイル一覧」シートの作成、とは書いてないので今のシートをそのまま名前変更して大丈夫かな?「Sheet1」を「ファイル一覧」に変更しておこう。(駄目なら止められるだろう…)

あとはセルの位置を変数に保存していけばいいのかな。”A1”、”A2”って足し算していく方法はあるのかな。検索してみるか。
「A1 A2 プログラム」とかかな?
(・・・)
「A1 A2 VBA」のほうがいいかな?
(・・・)
お、これ良さそう!!

Worksheets("Sheet1").Cells(1, 1).Value = "ABC"

Cellsってやつだと"A1"じゃなくて、1,1 とか列も数字で書いてあるのかな?Aが1で、Bが2とかかな? じゃぁ、1個ずつ足し算していけばできるかも!?

Worksheets("Sheet1").Cells(1, 1+1).Value=objFile.Name

あ、たぶんSheet1はシート名かな。そしたらこっちかな。

Worksheets("ファイル一覧").Cells(1, 1 + 1).Value = objFile.Name

ドキドキ。ボタンを押してみよう。えいっ

ううむ?

strMsgにはもう何も入れていないので、
MsgBox strMsg
はコメントアウトして大丈夫だと思いますよ

師匠

あ、そうか。値を入れるところは修正したけど、メッセージボックス表示するところが残ってたんだ。何もないメッセージボックスも表示してくれるものなのですね。なんか勝手な思い込みですけど、何もない場合は表示しないのかと思ってました。

その気持ちはわかります。コンピューター=プログラムと考えると、賢くて便利にいろんなことをしてくれる印象がありますよね。ですが、プログラムを書くということは、自動車のマニュアル運転をしているようなものなのです。

車は赤信号で勝手に止まらず、
運転者がブレーキを踏まないと止まらない。ということですね。

スピード違反も、歩道を走ることも、信号無視も、操縦者次第なのです。

師匠

納得しました、プログラマーの腕次第ってことですね・・・。
とりあえず、strMsgはもう使わないみたいだし、コメントアウトしておきます。そして、出力する位置が変なところは直さないとですね。

そうしたら、
・実行時に、以前の情報を「ファイル一覧」シートから削除すること
を私が書いてみましょうか?
人のプログラムソースを見て、理解して、自分で使えるようにすることも勉強になりますので、どうでしょうか?

師匠

是非お願いしたいです!

では、宣言のあたりにこれを入れて

Dim i As Integer

Fileオブジェクトをループさせている前あたりにこれを追加して、

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

これで出来たと思います。
なるべく、ひさきさんが書いたプログラムと似せて書いてみたのでそこまで難しくはないと思いますが、今回は「Do Until」のループを使っているところが前とは違いますね。とりあえずA1からA10くらいまで適当に文字を入力した後に、プログラムを実行してみて下さい。
実行した後に、プログラムの1行1行を見て、考えてみて下さい。
ここは何をしてるっぽいとか、
ここを少し変えたら、どう動くか、とか、
色々試し、動かし、自分の頭の中で納得してから、次のステップに進みましょう。

師匠

当たり前でしょうけど、ちゃんとA1からA10までの文字がリセットされました!
なるほど、セルの位置の数字自体に、変数を使うんですね。
この1を2に変えると、たぶんB列に書くんだよな。
(・・・)
思い通りに動くと面白いかも・・・。ふむふむ・・・。
じゃぁ、これでβの課題、クリアじゃないですかね!?

Option Explicit

Public Sub test()

'宣言
Dim objFileSys
Dim objFolder
Dim objFile
'Dim strMsg
Dim i As Integer

'ファイルシステムを扱うオブジェクトを作成
Set objFileSys = CreateObject("Scripting.FileSystemObject")

'c:\temp フォルダのオブジェクトを取得
'Set objFolder = objFileSys.GetFolder("C:\temp")
Set objFolder = objFileSys.GetFolder("C:\work\VB")

'初期値設定
'strMsg = ""

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

'FolderオブジェクトのFilesプロパティからFileオブジェクトを取得
i = 1
For Each objFile In objFolder.Files

  '取得したファイルのファイル名を表示
  'WScript.Echo objFile.Name
  'strMsg =  objFile.Name
  'strMsg = strMsg & vbLf & objFile.Name
  Worksheets("ファイル一覧").Cells(i, 1).Value = objFile.Name
  i = i + 1
Next

'変数をメッセージ表示
'WScript.Echo strMsg
'MsgBox strMsg

Set objFolder = Nothing
Set objFileSys = Nothing

End Sub

良いですね!素晴らしい!課題βはOKですね。

この1行ずつループして処理をすることは、プログラムの醍醐味みたいなところがあります。マクロの自動記録ではループ処理は生成できないので、より精密な作業をマクロ化しようとすると、どうしても手動でプログラムする必要がでてきます。

さぁ、いよいよ、次は今回の目玉処理ですね。
今までは、「ファイル名の取得」がメイン処理でしたが、
次のメインは「ファイル名の変更」になります。
実用性が1段階あがったプログラムになりますね。

師匠

疲れましたけど、思い通りに動くと楽しかったです!
次回のパート4で「Excelで、ファイル一覧作成し、ファイル名変更してみよう」は完結予定です!

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