銀河鉄道

【VBA】ドラッグアンドドロップできるユーザーフォーム|ListView

サムネイル
ユーザーフォームドラッグ&ドロップ

【ドラッグ&ドロップが必要な理由】

  • 他人と共有するExcelファイルにはマクロを設定しない
  • マクロ専用ブックから、他のファイルを操作する形にする
  • そのため、毎回、パスの取得が必須になる

ファイルをドラッグ&ドロップできる、ユーザーフォーム

ドラッグ&ドロップ後

ドラッグ&ドロップされたファイルの、ファイル名とパスを取得する

フォームモジュールに記述

キャンセルボタンが押されたとき用のラベル(lbl_IsCancel)を非表示で作ってます

Option Explicit
' 【ListViewの初期設定】
' ツールボックスを表示→ツールボックスの上で右クリック→その他のコントロール→「Microsoft ListView Control x.x」にチェック

Private Const AcceptCount As Long = 1 '取り込むファイル数制限
Public DDItems As Collection 'リストビューのコレクション:値取得用

'【色設定】
'※調べ方:Debug.PrintでRGBを出力する
'数字はパレットで出てくる上からの順
Private Const Gray2 As Long = 14540253 'RGB(221,221,221)
Private Const Gray5 As Long = 4210752 'RGB(64, 64, 64)
Private Const Red1 As Long = 13421823 'RGB(255,204,204)

Private Const Black As Long = 526344 'RGB(8,8,8) ※vbBlackは0,0,0
Private Const ColorBack As Long = Gray2
Private Const ColorHeader As Long = Gray5
Private Const ColorAccent As Long = Red1

Private lv As DDListView '※リストビューはクラスで扱う

Private Sub UserForm_Initialize()
    kFormNonCaption Me, True

    Set lv = New DDListView
    lv.Init Me.ListView1, AcceptCount
    
    'キャンセルボタンが押されたときIsCancelを表示するラベル:見た目では隠す
    With lbl_IsCancel
        .Caption = "NotCancel"
        .Visible = False
    End With
    
    '確認用テキストを非表示にする
    lbl_confirm_text.Visible = False
    
    '開始時の色設定
    SetStartColor
End Sub

Private Sub ListView1_OLEDragDrop(Data As MSComctlLib.DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)
    'クラスにデータを渡して値を取得する
    With lv
        .Go Data
        Set DDItems = .DDItems
        If .IsCancel Then Exit Sub
    End With
    
    '色変更
    SetAfterColor
    
    '確認用テキストを表示する
    lbl_confirm_text.Visible = True
    
    'OKボタンの有効化
    With btn_OK
        .BackColor = vbYellow
        .ForeColor = Black
        .Enabled = True
    End With
End Sub

'開始時の色設定
Private Sub SetStartColor()
    btn_OK.ForeColor = ColorHeader
End Sub

'ドロップ後の色設定
Private Sub SetAfterColor()
    'グレーアウトする
    lbl_target.ForeColor = ColorBack
    lbl_heading.ForeColor = ColorBack
    lbl_backHeading.BorderStyle = fmBorderStyleNone
    
    '目立たせる
    ListView1.BackColor = vbYellow
End Sub
Private Sub btn_OK_Click()
    '閉じるのではなく隠す ※変数を渡すため
    Me.Hide
End Sub
Private Sub btn_cancel_Click()
    Me.Hide
    lbl_IsCancel.Caption = "IsCancel"
End Sub

'labelをつかめるようにするための設定
Private Sub lbl_header_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    FormDrag Me, Button
End Sub
Private Sub lbl_ttl_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    FormDrag Me, Button
End Sub
'ユーザーフォームをつかめるようにするための設定
Private Sub UserForm_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    FormDrag Me, Button
End Sub

クラスモジュールに記述

1.DDListViewクラス|ListViewの設定

ユーザーフォームを複数作りたいときのために、ListView用のクラスを設定

Public WithEvents lv As MSComctlLib.ListView
Public DDItems As Collection
Public mListItems As listitems
Public IsCancel As Boolean

Private mAcceptCount As Long
Private mListItemsCount As Long
Private DDfiles As Object
Private Sub Class_initialize()
    Set DDItems = New Collection
End Sub
Private Sub Class_Terminate()
    Set DDItems = Nothing
End Sub
Public Sub Init( _
                            ByVal vLV As MSComctlLib.ListView, _
                            ByVal vAcceptCount As Long)
    Set lv = vLV
    mAcceptCount = vAcceptCount

    With lv
        .OLEDropMode = ccOLEDropManual '★これが一番重要:ファイルをドロップできるようにする設定
        .View = lvwReport '一覧表示
        .AllowColumnReorder = True '列幅の変更を許可
        .LabelEdit = lvwManual 'ラベル編集負荷
        .MultiSelect = True '複数選択
        .Gridlines = False 'グリッド線
        .FullRowSelect = False '行全体を選択
        .CheckBoxes = False 'チェックボックス

        '列の見出しと幅
        .ColumnHeaders.Add , "key1", "", 20, lvwColumnLeft
        .ColumnHeaders.Add , "key2", "name", 300, lvwColumnLeft
        .ColumnHeaders.Add , "key3", "path", 500, lvwColumnLeft
    End With
End Sub
'リストビューにファイルがドロップされた時にDataを受け取る
Public Sub Go(ByVal Data As Object)
    IsCancel = False
    Set DDfiles = Data.files
    Dim DDCount As Long: DDCount = DDfiles.count
    
    'オブジェクトにする:ローカルウィンドウで確認できるようにするため
    Set mListItems = lv.listitems
    mListItemsCount = mListItems.count
    
    'ドロップするたびに全書き換えしない場合は、「DDCount + mListItemsCount」にする
    If DDCount > mAcceptCount Then
        Call MsgRedoMacro("ドロップできるファイルは" & mAcceptCount & "個のみです")
        IsCancel = True
        Exit Sub
    End If
    
    '既存のリストをクリアする:ドロップするたびに全書き換えする場合
    mListItems.Clear
    
    'Dataの値を取得
    Dim DDItem As DDItem
    Dim i As Long
    For i = 1 To DDCount
        'コレクションに追加 ★DDItemクラスを用意
        Set DDItem = New DDItem
        DDItems.Add DDItem
        With DDItem
            .filePath = DDfiles(i)
            .fileName = GetFileNameFromFullPath(.filePath)
            .folderPath = CutAfterLastStr(.filePath, "\") '\前までのテキストにする
            
            '開いていたら閉じる:開きっぱなしでもエラーにならない場合は不要
            Call CloseOpenedBook(.filePath)
        End With
        Set DDItem = Nothing
    Next
    
    'リストビューに表示する
    DispItems
End Sub
'リストビューにアイテムを表示する
Private Sub DispItems()
    Dim count As Long: count = DDItems.count
    Dim i As Long: i = 1
    Dim v As Variant
    For Each v In DDItems
        With mListItems.Add
            .text = i
            .SubItems(1) = v.fileName
            .SubItems(2) = v.filePath
        End With
        i = i + 1
    Next
End Sub

2.DDItemクラス|メンバのみ

メンバのみのDDItemクラス

Public fileName As String
Public filePath As String
Public folderPath As String

標準モジュールに記述

ユーザーフォームを呼び出す設定

    With UserForm 'ユーザーフォーム名
        .lbl_target.Caption = "ファイルA" 'アップするファイル名
        .Show
        
        'Me.Hideで戻り後、キャンセル判定
        If .lbl_IsCancel.Caption = "IsCancel" Then
            Exit Sub
        End If
        
        'タイムはここから計測
        StartTimer = Timer  '(パブリック変数使用:Public StartTimer As Double)
        
        'フォーム内の値を取得
        Dim fileName As String
        Dim folderPath As String
        Dim filePath As String

        fileName = .DDItems(1).fileName
        folderPath = .DDItems(1).folderPath
        filePath = .DDItems(1).filePath
        
        Unload UserForm
    End With

開始と終了の間で、ユーザーフォーム呼び出し

タイトルバーを非表示にする方法

タイトルバーは、こちらの方法で非表示に

関連記事

著者

author
月うさぎ

編集後記:
この記事の内容がベストではないかもしれません。

記事一覧