글목록

2021년 4월 6일

Module 1. 파일명 일괄 변경 매크로 (2)

이전 글에서는 파일 목록을 가져오는 프로시저를 작성했습니다. 이번에는 새파일명으로 파일명을 일괄적으로 변경하는 프로시저를 작성할 예정입니다.

우선 작성된 매크로를 먼저 보여드리겠습니다.

Sub ChangeFilename()
  On Error Resume Next
  Dim tSh As Worksheet, tFSO As New FileSystemObject, tDir As String, tStr(2) As String, tFN1() As String, tFN2() As String, tFNT() As String, tR() As Long
  Dim i As Long, n As Long, tRN As Long, tSN As Long
  Set tSh = ActiveSheet
  tRN = tSh.UsedRange.Rows.Count
  tDir = tSh.Cells(1, 2).Value
  n = -1
  tSN = 4
  For i = tSN + 1 To tRN
    tStr(1) = CombineFilenameExt(tSh.Cells(i, 1).Value, tSh.Cells(i, 2).Value)
    tStr(2) = CombineFilenameExt(tSh.Cells(i, 3).Value, tSh.Cells(i, 4).Value)
    If (Not (tStr(1) = "" Or tStr(2) = "")) And (tStr(1) <> tStr(2)) And tFSO.FileExists(tDir & tStr(1)) Then
      n = n + 1
      ReDim Preserve tFN1(n)
      ReDim Preserve tFN2(n)
      ReDim Preserve tR(n)
      tFN1(n) = tStr(1)
      tFN2(n) = tStr(2)
      tR(n) = i
    End If
    tSh.Cells(i, 5).Clear
    If tFSO.FileExists(tDir & tStr(1)) Then
      If tStr(1) = tStr(2) Or tStr(2) = "" Then
        tSh.Cells(i, 5).Value = "미변경"
      End If
    Else
      tSh.Cells(i, 5).Value = "파일 없음"
    End If
  Next
  If n < 0 Then GoTo ErrorHandler
  ReDim Preserve tFNT(n)
  For i = 0 To n
    tStr(0) = GetOtherFilename(tDir, tSh.Cells(tR(i), 1).Value & "_" & GetRandomString(10), tSh.Cells(tR(i), 2).Value)
    tFNT(i) = CombineFilenameExt(tStr(0), tSh.Cells(tR(i), 2).Value)
    Name tDir & tFN1(i) As tDir & tFNT(i)
    If tFSO.FileExists(tDir & tFNT(i)) Then
      tSh.Cells(tR(i), 5).Value = ">임시파일명으로 변경.."
    Else
      tFNT(i) = tFN1(i)
      tSh.Cells(tR(i), 5).Value = "미변경"
    End If
  Next
  For i = 0 To n
    tStr(0) = GetOtherFilename(tDir, tSh.Cells(tR(i), 3).Value, tSh.Cells(tR(i), 4).Value)
    tFN2(i) = CombineFilenameExt(tStr(0), tSh.Cells(tR(i), 4).Value)
    Name tDir & tFNT(i) As tDir & tFN2(i)
    If tFSO.FileExists(tDir & tFN2(i)) Then
      tSh.Cells(tR(i), 3).Value = tStr(0)
      tSh.Cells(tR(i), 5).Value = "변경 완료"
    Else
      tSh.Cells(tR(i), 3).Value = tSh.Cells(tR(i), 1).Value
      tSh.Cells(tR(i), 4).Value = tSh.Cells(tR(i), 2).Value
      tSh.Cells(tR(i), 5).Value = "오류"
    End If
  Next
ErrorHandler:
End Sub

Function CombineFilenameExt(iStr1, iStr2) As String
  Dim tStr As String, tFN As String, tFNExt As String
  tFN = Trim(iStr1)
  tFNExt = Trim(iStr2)
  If tFN = "" Or tFNExt = "" Then
    tStr = tFN & tFNExt
  Else
    tStr = tFN & "." & tFNExt
  End If
  CombineFilenameExt = tStr
End Function

Function GetOtherFilename(iDir, iFN, iFNExt) As String
  Dim tFSO As New FileSystemObject, tStr As String, tFN As String, n as Integer
  tFN = iFN
  tStr = iDir & CombineFilenameExt(tFN, iFNExt)
  If tFSO.FileExists(tStr) Then
    n = 0
    Do
      n = n + 1
      tFN = iFN & "_" & n
      tStr = iDir & CombineFilenameExt(iFN & "_" & n, iFNExt)
    Loop Until Not tFSO.FileExists(tStr)
  End If
  GetOtherFilename = tFN
End Function

1개의 Sub 프로시저와 2개의 Function으로 구성됩니다. 이 매크로는 지난 글에서 파일목록을 작성하는 매크로를 이용해서 만든 목록에서만 작동합니다. 따라서, 2개의 Sub 프로시저를 함께 사용하는 것이 좋습니다.

함수 CombineFilenameExt는 파일명과 확장자를 합치는 함수입니다. 만약, 사용자가 확장자를 지워버리거나, 파일명을 공란으로 두었을 때 확장자를 연결하는 마침표 "."를 어떻게 처리할 것인지 정해줍니다. 여기에서는 파일명과 확장자가 모두 있다면 마침표로 연결하고, 아닌 경우에는 둘 중 하나만 남기는 것이지요.

두번째 함수인 GetOtherFilename는 새파일명에 대한 정보인 폴더명, 파일명, 확장자를 입력해주고, 이 파일이 이미 존재하는 파일이라면 숫자를 1씩 증가시켜서 새로운 파일명을 만들라는 뜻입니다. 파일명을 모두다 똑같이 만들어버리면, 이미 해당 폴더에 있는 파일명으로는 변경할 수 없기 때문에, 자동으로 숫자를 1씩 늘려가면서 파일명을 새로 생성하라는 것입니다.


실제 매크로로 사용될 Sub 프로시저는 이미 만들어진 파일목록에서 정보를 읽어오면서 파일을 순차적으로 변경합니다. 작동하는 순서는 다음과 같습니다.

우선 파일목록으로부터 기존파일명과 새파일명을 읽어옵니다.

새파일명 목록을 만드는 동안, 파일을 삭제하거나, 이동하거나, 파일명을 탐색기 등에서 변경해버렸다면, 이 파일에 대해서는 작업을 하지 않도록 파일이 존재하는지 확인합니다.

일단 존재하는 파일에 대해서, GetRandomString 함수를 써서 원래 파일명에 무작위 문자열을 붙여서 임시파일명으로 변경합니다. 굳이 이 단계를 포함시킨 이유는 파일명을 역순으로 변경할 때와 같이 기존 파일명이 중복되어 오류가 발생하는 것을 막기 위함입니다. 아래와 같이 파일명을 역순으로 변경하는 경우를 예를 들어보겠습니다. 만약, Random string을 붙여 변경하지 않고 바로 파일명을 변경하게 된다면, A1.txt 파일을 A9.txt로 변경할 때, 이미 해당 폴더에 A9.txt가 존재하기 때문에 파일명을 변경하려고 하면 오류가 발생됩니다. 따라서, 해당 폴더에는 존재하지 않는 임의의 파일명으로 모두 변경한 후, 다시 원하는 파일명으로 변경하면 윈도우에서 허용하는 한 어떠한 파일명으로도 변경이 가능해집니다.


여기에서는 무작위 문자열을 10자리로 했는데, 사실 이렇게 길 필요는 없습니다. 알파벳만으로 10자리 무작위 문자열을 만들었을 때 우연히 같은 파일명이 될 확률은 26^10승 분의 1이라.. 중복된 파일명이 될 가능성은 없습니다. 그렇더라도 GetOtherFilename에서와 같이 혹여라도 중복된 파일명이 존재할 가능성이 있기 때문에 중복된 경우에는 숫자를 하나씩 붙여 중복을 피하는 것입니다.

모든 파일명을 임시파일명으로 우선 교체가 되었다면, 최종 단계에서 지정한 새파일명으로 변경합니다. 파일을 변경하고 나서, 해당파일이 존재하면, 이상없이 변경되었음을 표시하고, 만약 파일명 변경작업이 완료되었는데에도 해당파일이 존재하지 않는다면, 어떠한 이유로든 오류가 발생했음을 표현해줍니다. 시스템파일이거나 사용중인 파일인 경우, 오류가 발생할 수 있기 때문에 이러한 표현을 해줍니다.

파일명을 변경하는 명령어는 VBA에서 지원하는 Name을 사용합니다. FileSystemObject에서도 파일명을 변경하는 명령이 있는데, 어느것을 사용하더라도 상관없습니다. FileSystemObject으로 파일명을 변경하려면,

tFSO.MoveFile 원본파일명, 변경파일명

으로 사용하시면 됩니다. 파일을 이동하라는 것이지만, 단순히 파일명 변경에도 사용할 수 있습니다.

이상 파일명 일괄 변경 매크로를 작성해보았습니다.

댓글 없음:

댓글 쓰기

의견이나 질문이 있으신 분은 언제든지 댓글을 달아주세요~

많이 본 글 :