EXCELのシート名取得、フォルダ名の取得マクロ完成版
前回の宿題事項の下記4点について対応できた。
思ったよりあっさりと実装できた。
フォームモジュール側
思ったよりあっさりと実装できた。
1.EXCELシートのシート名を引いてくるのと選択式にする。
→選択式にしやした。
2.ファイル名を再帰的に取得するのかしないのかを選択式にする
3.再帰的に取得する場合にフォルダ名も取得するのか選択式にする
4.フォルダ名の取得を選択式にする。
→フォルダを選択すれば再帰的に出力するように改修
モジュール以外にも手を入れるところがあったんで。
フォーム
フォームモジュール側
-----------------------------------------------------------------------------------------------------------------------
Option Explicit
Sub getFileName_Click()
'
' フォルダからファイル名を取得して一覧にして別のEXCELシートに保存する。
'
Dim dlg As Object
Dim dlgAns As Boolean
Dim getForder As Variant '取得対象フォルダ
Dim getFile As Variant '取得対象ファイル
Dim outSheet As Variant '出力用シート
Dim retVal As String
Dim optSelect As String
Dim startTime As Date '処理時間計測用
Dim endTime As Date '処理時間計測用
startTime = Now
'カレントディレクトリの指定
ChDir CurDir
'保存対象ファイルの指定
outSheet = Application.GetOpenFilename("EXCELファイル(*.xlsx),*.xlsx , EXCELファイル(*.xls),*.xls", Title:="保存先の指定")
If outSheet = False Then
MsgBox ("保存するEXCELファイルを選択してください。")
Exit Sub
End If
'モードの指定(今後のこと考えると要検討)
If OptionButton1.Value = True Then
optSelect = "E"
End If
If OptionButton2.Value = True Then
optSelect = "F"
End If
Select Case optSelect
Case "E"
'取得対象EXCELの場合
getFile = Application.GetOpenFilename("EXCELファイル(*.xlsx),*.xlsx,EXCELファイル(*.xls),*.xls")
If getFile = outSheet Then
MsgBox ("取得対象と出力先に同じEXCELファイルは指定できません。")
ElseIf VarType(getFile) <> vbBoolean Then
retVal = Module1.getSheetName(getFile, outSheet)
Else
MsgBox ("取得対象のEXCELファイルを選択してください。")
End If
Case "F"
'ファイル名取得対象フォルダの指定
Set dlg = Application.FileDialog(msoFileDialogFolderPicker)
dlgAns = dlg.Show
If dlgAns Then
getForder = dlg.SelectedItems(1)
Else
getForder = ""
End If
If getForder <> "" Then
retVal = Module1.getFileName(getForder, outSheet)
Else
MsgBox ("取得対象フォルダが選択されていません。")
End If
Case Else
MsgBox ("定義されていない設定です。システム管理者に連絡してください。")
End Select
endTime = Now
'Debug.Print DateDiff("s", startTime, endTime)
End Sub
--------------------------------------------------------------------------------------------------------------------------------
標準モジュール側
-------------------------------------------------------------------------------------------------------------------------------
Option Explicit
'refer
' http://ameblo.jp/gidgeerock/entry-11584846307.html
' https://oshiete.goo.ne.jp/qa/1828986.html
' http://officetanaka.net/excel/vba/file/file07.htm
' http://www.asahi-net.or.jp/~ef2o-inue/vba_o/sub05_110_080.html
' http://officetanaka.net/excel/vba/tips/tips39.htm
' https://gist.github.com/gitspopovic/2963865
' http://vba-geek.jp/blog-entry-294.html
' http://vbaexcel.seesaa.net/article/148305417.html
' http://d.hatena.ne.jp/bhunji2000/20091030/1258133771
' http://www.239-programing.com/excel-vba/func/func072.html
' v2 ref
' https://www.moug.net/tech/exvba/0150120.html
' http://officetanaka.net/excel/vba/sheet/sheet03.htm
' http://hensa40.cutegirl.jp/archives/705
' http://www.niji.or.jp/home/toru/notes/8.html
' http://officetanaka.net/excel/vba/tips/tips130.htm
' http://excel-ubara.com/excelvba4/EXCEL222.html
' http://www.officepro.jp/excelvba/sheet/index2.html
' https://support.microsoft.com/ja-jp/help/950220
' http://vba-geek.jp/blog-entry-269.html
' http://excelwork.info/excel/endproperty/
' http://www.atmarkit.co.jp/ait/articles/1402/24/news108.html
' v3 ref
' http://www.officepro.jp/excelvba/sub/index6.html
' http://officetanaka.net/excel/vba/statement/OnError.htm
' http://officetanaka.net/excel/vba/tips/tips104.htm
' http://officetanaka.net/excel/vba/tips/tips28.htm
' http://www.atmarkit.co.jp/ait/articles/1407/07/news011.html
' http://excelwork.info/excel/hyperlinks/
' http://officetanaka.net/excel/vba/tips/tips90.htm
'
' 対象のフォルダからファイル名一覧を取得してEXCELシートに保存する
'
Function getFileName(infile As Variant, outFile As Variant)
On Error GoTo Error_Sub
Const ROWA = "A" 'A列
Const ROWB = "B" 'B列
Const ROWC = "C" 'C列
Const ROWD = "D" 'D列
Dim saveBook As Object
Dim saveSheet As Object
Dim sheetsname As String
Dim fullPath As String
Dim firstSheet As Long '書込み対象シートのインデックス
Dim subFolderflg As String
Dim fileSetret As String
Dim saveWorksheet As Worksheet
'保存先指定
Set saveBook = Workbooks.Open(outFile)
Application.DisplayAlerts = False
Application.Visible = False
With CreateObject("Scripting.FileSystemObject")
'シート名設定
sheetsname = .GetFolder(infile).Name
sheetsname = sheetNameReplacer(sheetsname)
'保存先シートの設定
firstSheet = SheetChecker(saveBook, sheetsname)
If firstSheet = 0 Then
MsgBox ("シートの処理中にエラーが発生しました。")
Exit Function
End If
Set saveWorksheet = saveBook.Worksheets(firstSheet)
saveWorksheet.Activate
'タイトル
saveWorksheet.Range(ROWA & 1) = "NO"
saveWorksheet.Range(ROWB & 1) = "ファイル名"
saveWorksheet.Range(ROWC & 1) = "ファイルパス"
saveWorksheet.Range(ROWD & 1) = "最終更新日時"
fileSetret = FileSet(infile, saveWorksheet, 2)
End With
'シート名を変更し保存先EXCELを閉じる
If fileSetret = "True" Then
saveWorksheet.Name = sheetsname
End If
saveBook.Close Savechanges:=True
Set saveBook = Nothing
MsgBox ("処理が完了しました。")
'ActiveWorkbook.Close False
Application.Visible = True
Application.DisplayAlerts = True
Exit Function
Error_Sub:
MsgBox ("システム管理者に以下の内容を連絡してください。" & Err.Number & ":" & Err.Description)
End Function
'
' 対象のEXCELからシート名を取得する
'
Function getSheetName(infile As Variant, outFile As Variant)
On Error GoTo Error_Sub
Const ROWA = "A" 'A列
Const ROWB = "B" 'B列
Const ROWC = "C" 'C列
Dim readBook As Object
Dim readSheet As Object
Dim saveBook As Object
Dim saveSheet As Object
Dim sheetsname As String
Dim i As Long '行番号
Dim firstSheet As Long '書込み対象シートのインデックス
Dim hyperAddr As String 'ハイパーリンク先
Dim saveWorksheet As Worksheet
i = 2
Set readBook = GetObject(infile)
Set saveBook = Workbooks.Open(outFile)
Application.DisplayAlerts = False
Application.Visible = False
'シート名設定用
sheetsname = left(readBook.Name, InStrRev(readBook.Name, ".", -1, vbTextCompare) - 1)
sheetsname = sheetNameReplacer(sheetsname)
'保存先シートの設定
firstSheet = SheetChecker(saveBook, sheetsname)
If firstSheet = 0 Then
MsgBox ("シートの処理中にエラーが発生しました。")
Exit Function
End If
'指定したEXCEL内のシート名を取得してEXCELに出力
Set saveWorksheet = saveBook.Worksheets(firstSheet)
saveWorksheet.Activate
'タイトル
saveWorksheet.Range(ROWA & 1) = "NO"
saveWorksheet.Range(ROWB & 1) = "シート名"
saveWorksheet.Range(ROWC & 1) = "ファイル名"
For Each readSheet In readBook.Sheets
hyperAddr = "=HYPERLINK(" & """" & infile & "#" & readSheet.Name & "!A1""" & "," & _
"""" & readBook.Name & "_" & readSheet.Name & """)"
saveWorksheet.Range(ROWA & i) = i
saveWorksheet.Range(ROWB & i) = readSheet.Name
saveWorksheet.Range(ROWC & i) = hyperAddr
i = i + 1
Next
saveWorksheet.Range(ROWA & ":" & ROWC).EntireColumn.AutoFit
saveWorksheet.Name = sheetsname
'ファイルを閉じる
readBook.Close
Set readBook = Nothing
saveBook.Close Savechanges:=True
Set saveBook = Nothing
MsgBox ("処理が完了しました。")
' ActiveWorkbook.Close False
Application.Visible = True
Application.DisplayAlerts = True
Exit Function
Error_Sub:
MsgBox ("システム管理者に以下の内容を連絡してください。" & Err.Number & ":" & Err.Description)
readBook.Close
Set readBook = Nothing
End Function
'
' EXCELシート操作
' シートが存在しない場合はシートを追加
' 同一シート名がある場合は別名シートで追加
' 該当シートにデータが存在する場合はシート追加
'
' 引数 :チェック対象のシート
' 戻り値:シート番号
'
Function SheetChecker(checkBook As Object, sheetsname As String) As Long
On Error GoTo Error_Sub
Const LastCol = 5 '最終セル判定用
Dim i As Long
Dim chkRow As Long '最終セル文字列判定用カウンター
Dim chkcolumn As Long '最終セル文字列判定用カウンター
Dim cellCheck As Variant
For i = 1 To checkBook.Worksheets.Count
'同じシート名が存在する場合は別のシート名にする。
'EXCELのシート名は31文字までなので制限に引っかからないように文字数を制限
If sheetsname = checkBook.Worksheets(i).Name Then
sheetsname = left(sheetsname, 10) & "_" & Format(Now, "yyyymmddhhmmss")
End If
'終端セル確認(よほどのことがない限り5列程度の確認で問題ないと思われる。)
For chkcolumn = 1 To LastCol
chkRow = checkBook.Worksheets(i).Cells(Rows.Count, chkcolumn).End(xlUp).Row
cellCheck = checkBook.Worksheets(i).Cells(chkRow, chkcolumn).Value
If cellCheck <> "" Then
Exit For
End If
Next chkcolumn
'終端セルにデータがないので該当シートに追記
If cellCheck = "" Then
SheetChecker = i
Exit Function
End If
'追加が必要な場合はシートを追加する。
If i = checkBook.Worksheets.Count Then
checkBook.Worksheets.Add after:=checkBook.Worksheets(i)
SheetChecker = i + 1
Exit Function
End If
Next i
Error_Sub: 'あまりよろしくないが予期せぬエラー処理
SheetChecker = 0
MsgBox ("システム管理者に以下の内容を連絡してください。" & Err.Number & ":" & Err.Description)
End Function
'
'シート名対策用文字列置換
' シートが存在しない場合はシートを追加
' 同一シート名がある場合は別名シートで追加
' 該当シートにデータが存在する場合はシート追加
'
' 引数 :シート名
' 戻り値:変換後のシート名
'
Function sheetNameReplacer(sheetsname As Variant) As String
On Error GoTo Error_Sub
Const CHECK = 12
Dim replaceWork As String
Dim strLeng As Long
Dim i As Long
Dim Prohibition(CHECK) As String
'EXCELシート名の禁則文字
Prohibition(0) = ":"
Prohibition(1) = ":"
Prohibition(2) = "\"
Prohibition(3) = "¥"
Prohibition(4) = "/"
Prohibition(5) = "/"
Prohibition(6) = "?"
Prohibition(7) = "?"
Prohibition(8) = "*"
Prohibition(9) = "*"
Prohibition(10) = "["
Prohibition(11) = "]"
replaceWork = sheetsname
For i = 0 To CHECK
replaceWork = Replace(replaceWork, Prohibition(i), "★")
Next i
strLeng = Len(replaceWork)
If strLeng > 20 Then
replaceWork = left(replaceWork, 15)
End If
sheetNameReplacer = replaceWork
Exit Function
Error_Sub: 'あまりよろしくないが予期せぬエラー処理
replaceWork = "False"
MsgBox ("システム管理者に以下の内容を連絡してください。" & Err.Number & ":" & Err.Description)
End Function
'
' フォルダを取得しサブフォルダ名含めてEXCELに出力する。
' http://officetanaka.net/excel/vba/tips/tips36.htm まんま
'
Function FileSet(Path As Variant, setWorksheet As Worksheet, sCol As Long) As String
On Error GoTo Error_Sub
Const ROWA = "A" '番号
Const ROWB = "B" 'ファイル名
Const ROWC = "C" 'ファイルパス
Const ROWD = "D" '更新日時
Const ROWE = "E" '容量
Dim FSO As Object, Folder As Variant, File As Variant
Dim i As Long
Set FSO = CreateObject("Scripting.FileSystemObject")
i = sCol
'サブフォルダ探索
For Each Folder In FSO.GetFolder(Path).SubFolders
Call FileSet(Folder.Path, setWorksheet, i)
Next Folder
For Each File In FSO.GetFolder(Path).Files
setWorksheet.Range(ROWA & i) = i - 1 '番号を振るので-1しておく
setWorksheet.Range(ROWB & i) = File.Name
setWorksheet.Range(ROWC & i) = File.Path
setWorksheet.Hyperlinks.Add Anchor:=Range(ROWC & i), Address:=File.Path
setWorksheet.Range(ROWD & i) = File.DateLastModified
i = i + 1
Next File
sCol = i
'セルの整形
setWorksheet.Range(ROWA & ":" & ROWD).Columns.AutoFit
FileSet = "True"
Exit Function
Error_Sub: 'あまりよろしくないが予期せぬエラー処理
FileSet = "False"
MsgBox ("システム管理者に以下の内容を連絡してください。" & Err.Number & ":" & Err.Description)
End Function
-------------------------------------------------------------------------------------------------------------------------------
ひとまずこれで完成、後は容量とか属性とかの話なので
ほしいのがあったらここに順次足していけばよい。
これでフォルダからファイル一覧調べろとか
フォルダ内で容量くってるファイル調べろとか言うときに
時短できますな。

コメント