読者です 読者をやめる 読者になる 読者になる

tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

vbaでエクセルで管理しているある列のファイル名一覧が実際にあるかどうかチェックする的なやつ(データの最終行、連想配列、Dictionary、FileSystemObject)

タイトルのとおりなんですが、久しぶりにvba触ると覚えてない率100%なので
ありそうな実例とともにサンプルとそれを使った例の一連をすべてメモっておきます。
個人的なメモなのであしからず

たとえばの例

「エクセルで画像ファイルを管理していて、あるフォルダにそのファイルがあるかないかをvbaでチェックしよう」的な

例を実現するために使うvba的なやつ

  • データが入力されている最終行を取得
  • 連想配列(今回はDictionaryを使います
  • FileSystemObject
  • ファイルの存在チェック(FileSystemObject.FolderExistsかDir関数

vbaサンプルと参考

データが入力されている最終行を取得

そのまんまですが、データが入力されている行の最終行を取得します。
RowsコレクションとEndモードを組み合わせて取得。
sample

Sub sample()
    Dim LastRow As Long
    LastRow = Cells(Rows.Count, 1).End(xlUp).Row
    MsgBox "最終行は" & LastRow & "です"
End Sub

参考1→入力されているデータの最終セルを取得する

連想配列

vba連想配列を調べるとCollectionオブジェクトなんかが出てきます。
こんな感じ→http://www.moug.net/tech/exvba/0150118.html
こちらでも良いですが、今回はMicrosoft Scripting RuntimeのDictionaryを使います
※Collectionだと何かが使いにくかった気がしましたが忘れちゃいました汗。
※参照するキーが変数だった場合とかに使いにくかったような?
sample

Set dic = CreateObject("Scripting.Dictionary")
dic.Add "キー1", "値1です"

参考2→Scripting.Dictionary@Excel マクロ・VBA
参考3→Dictionary オブジェクト

FileSystemObjectとファイルの存在チェック

ドライブ・フォルダ・ファイルなどを操作できるオブジェクトです
これだけで結構なことができます。
今回は、下記のことに使ってます

  • フォルダの存在チェック※Dir関数でもいけるので両方使ってみました
  • ファイルの一覧を取得してforでまわす

sample

' 対象のフォルダー
Const FolderPath As String = "C:\Sample"

' ディレクトリの存在チェック(FileSystemObject)
If Not FSO.FolderExists(FolderPath) Then
  MsgBox "そんなフォルダないよ\n" & FolderPath
End If

' ディレクトリの存在チェック(Dir関数)
If Dir(FolderPath) <> "" Then
  MsgBox FolderPath & "は存在します"
End If

' FileSystemObjectを使ってあるディレクトリ内のファイル名を表示してみる
With CreateObject("Scripting.FileSystemObject")
  For Each f In .GetFolder(FolderPath).Files
    MsgBox  f.Name
  Next f
End With

参考4→FileSystemObjectのプロパティとメソッド
参考5→ファイルの一覧を取得する(下のほう)

エクセルのある列で管理しているファイル名が実際にあるかどうかチェックスクリプト

ってことで、一番最初に書いた例をサンプルを組み合わせてみます
とりあえず組み合わせただけなのでロジックや見栄えは結構適当w

Sub sample()
  'FileSystemObject
  Dim FSO As Object ' FileSystemObject
  Set FSO = CreateObject("Scripting.FileSystemObject")
  Const check_path As String = "C:\Sample"
  If Not FSO.FolderExists(check_path) Then
    MsgBox "そんなフォルダないよ\n" & check_path
    Exit Sub
  End If
  
  ' 定義
  Dim check_col As Integer      ' check_colする列の値(Aなら1、Bなら2)
  Dim check_col_char As String  ' check_colする列の名前(AとかBとか)
  Dim data_start_row As Integer ' データが入力されている最初の行番号
  Dim LastRow As Long           ' データが入力されている最終の行番号

  ' 初期化
  check_col = 3
  check_col_name = "AF"
  data_start_row = 3
  Set dic = CreateObject("Scripting.Dictionary")
  LastRow = Cells(Rows.Count, check_col).End(xlUp).Row
  
  ' ある列のデータ入力開始行から最終行までforでまわして連想配列に格納
  ' key:ファイル名、value:セル名
  ' 後で実ファイルの一覧でloopして、そのときのファイル名をキーとするため
  For i = data_start_row To LastRow
    dic.Add Range(check_col_name & i).Value, check_col_name & i
  Next
  
  ' 実際のファイルでloopしていろいろする
  With FSO.GetFolder(check_path)
    'MsgBox .Files.Count ' 無駄にファイル数を出してみる
    For Each f In .Files
      'MsgBox fname_cells_dic(f.Name)
      If dic(f.Name) <> "" Then
        MsgBox f.Name & "はエクセルの" & check_col_name & "列にあります"
      End If
    Next f
  End With
  
End Sub