4年ほど前に、PCに接続したスマートフォン等のWindows ポータブル デバイスからファイルやフォルダをコピーするマクロについて記事を書きました。
先日、上記マクロがWindows 10 Creators Update環境で動作しなくなったとのコメントをいただいたので、コードを書き直すことにしました。
このコードを参考にデジカメデータをコピーしていましたが,Windows10 1703 Cretors update に上げてから,Namespaceの部分が動かくなくなりました。
Shell32.dllが,2017/6/20のタイムスタンプになっており,差し変わったことが原因と推測します。
色々トライしましたが,回避策がなくて困っています。
Option Explicit
Public Sub Sample()
CopyWpdItems "内部ストレージ\data\jp.co.yahoo.android.yjwidget_sbm", _
"C:\Test\WPD", _
"Xperia Z Ultra"
MsgBox "処理が終了しました。", vbInformation + vbSystemModal
End Sub
Private Sub CopyWpdItems(ByVal SrcFolderPath As String, _
ByVal TargetFolderPath As Variant, _
Optional ByVal WpdName As String = "")
'Windows ポータブル デバイス(WPD)にあるフォルダの中身を指定したフォルダにコピー
'- SrcFolderPath:コピー元フォルダのパス
'- TargetFolderPath:コピー先フォルダのパス
'- WpdName:WPD名(接続されているWPDが一つしかない場合は指定する必要無し)
Dim Wpd As Object
Dim ParentFolder As Object
Dim Srcfolder As Object
Dim TargetFolder As Object
Dim itm As Object
Dim v As Variant
Dim i As Long
'コピー先フォルダチェック
With CreateObject("Scripting.FileSystemObject")
If .FolderExists(TargetFolderPath) = False Then
MsgBox "コピー先フォルダが見つかりませんでした。" & vbNewLine & _
"処理を中止します。", vbCritical + vbSystemModal
Exit Sub
End If
End With
'WPD取得
Set Wpd = GetWpd(WpdName)
If Wpd Is Nothing Then
MsgBox "ポータブル デバイスを取得できませんでした。" & vbNewLine & _
"処理を中止します。", vbCritical + vbSystemModal
Exit Sub
End If
Set ParentFolder = Wpd
'コピー元フォルダ取得
v = Split(SrcFolderPath, ChrW(&H5C))
For i = LBound(v) To UBound(v)
Set Srcfolder = GetWpdChildFolder(ParentFolder, v(i))
If Srcfolder Is Nothing Then
MsgBox "コピー対象のフォルダが見つかりません。" & vbNewLine & _
"処理を中止します。", vbCritical + vbSystemModal
Exit Sub
End If
Set ParentFolder = Srcfolder
Next
'ファイル/フォルダコピー
With CreateObject("Shell.Application")
Set TargetFolder = .Namespace(TargetFolderPath)
On Error Resume Next
For Each itm In Srcfolder.Items
TargetFolder.CopyHere itm 'フォルダー含めてコピー
Next
If Err.Number <> 0 Then
MsgBox "エラーが発生しました。" & vbNewLine & vbNewLine & _
"エラー番号:" & Err.Number & vbNewLine & _
"エラー内容:" & Err.Description, vbCritical + vbSystemModal
End If
On Error GoTo 0
End With
End Sub
Private Function GetWpd(Optional ByVal WpdName As String = "") As Object
'Windows ポータブル デバイス(WPD)を取得
'※WPDが複数接続されている場合は引数で名前を指定
Dim ret As Object
Dim itm As Object
Set ret = Nothing '初期化
With CreateObject("Shell.Application").Namespace("shell:MyComputerFolder")
For Each itm In .Items
Select Case itm.Type
Case "ポータブル メディア プレーヤー", "ポータブル デバイス"
If Len(Trim(WpdName)) < 1 Then
Set ret = itm.GetFolder
Else
If itm.Name = WpdName Then
Set ret = itm.GetFolder
End If
End If
End Select
Next
End With
Set GetWpd = ret
End Function
Private Function GetWpdChildFolder(ByVal ParentFolder As Object, _
ByVal ChildFolderName As String) As Object
Dim ret As Object
Dim itm As Object
Set ret = Nothing '初期化
For Each itm In ParentFolder.Items
If (itm.IsFolder = True) And (itm.Name = ChildFolderName) Then
Set ret = itm.GetFolder
Exit For
End If
Next
Set GetWpdChildFolder = ret
End Function
FolderItemオブジェクトのTypeプロパティによってポータブル メディア プレーヤー(ポータブル デバイス)かどうかを判別して目的のフォルダを取得、FolderオブジェクトのCopyHereメソッドによってファイルやフォルダのコピーを行っています。
Windows ポータブル デバイス上のファイルやフォルダをマクロから操作したい場合には、上記コードを参考にしていただければと思います。




















さっそくのCreators Update対応のソースコード掲載ありがとうございます。
昨日、自分のツールにも反映して、無事にスマホの写真をWindows PCにインポートできるようになりました。
最初は、コードが大きく変化したことに戸惑いましたが、Namespaceを使わないコーディングであることに気づいてからはすんなり移植できました。
ポータブルデバイスに対するVBAのソースコードは希少につき、最初に見つけた時はうれしく、今回の迅速なご対応にも深謝いたします。
Excel VBA でのスマホとPCでのファイルのやり取りで3年悩んでいましたが、大変助かりましたありがとうございます。感謝です。