반응형

출처: http://it205.tistory.com/21


VBA을 이용해서 Text 파일 (혹은 Xml등등)을 저장하는 방법입니다.

보통 VBA의 FileSystem을 이용한 [Open / Close를 활용 한 방법이 있습니다. 
(구글링 및 네이버를 이용해서 쉽게 찾을 수 있습니다.)

하지만 FileSystem은 ASCII 형태로 저장이 되어 일부 프로그램에서 로드할 때 깨지거나,
문제점이 발생할 수 있습니다. 
(회사에서 UTF-8 형태로 모두 바꾸는 바람에 기록 방법을 바꾸어야 했어요 ㅠㅠ)

이 때에는 Stream을 이용해서 File을 생성 기록 할 수 있습니다.

'Stream의 생성

Dim stmFileControl As Stream       'Stream 인자 생성
Set stmFileControl = New Strem     'Stream 저장공간 배치

stmFileControl .Open
stmFileControl.Position = 0             '기록, 혹은 읽을 위치를 0으로 맞춘다.
stmFileControl.Charset = "UTF-8"                   '저장시 [UTF-8]로 저장합니다.

'Stream에 기록

stmFileControl.WriteText("기록값을 String으로 넣습니다." & sString & " &로 묶어도 되요")

'Stream에서 파일로 저장

stmFileControl.SaveToFile "C:\Test.txt", adSaveCreateOverWrite
'C:\Test.txt에 저장(혹은 생성)하겠다는 것입니다.
'adSaveCreateOverWrite가 해당 옵션을 선택하는 것입니다. (다른 옵션도 있겠지만.. 확인하지 않았어요..

stmFileControl.Close
'stmFileControl을 닫습니다.


각 생성 및 소멸을 함수로 묶어서 만들면 편하게 사용할 수 있습니다. : )


--참고하세요!!--
Stream을 사용하려면
Microsoft ActiveX DataObject 2.8(이상)을 사용할 수 있어야 합니다.
VBA에서  [도구>참조] 를 눌러서 위의 라이브러리를 추가해주세요.


--2011년 5월 추가 내용
그냥 일반적으로 사용하는 Text형식은 아래와 같다. 
stmFileControl.Charset = "euc-kr"                  '저장시 [euc-kr8]로 저장합니다.


반응형
반응형

출처: http://m.blog.naver.com/rosa0189/60154415797


텍스트 파일 불러올 경우가 가끔 있으므로 미리 텍스트파일 불러오는 기본코드를 작성해 놓음.

intNo = 1 이라고 하면 모든 행을 불러오고, 1보다 클경우 intNo 숫자 만큼 행을 건너뛰면서 텍스트 파일을 불러온다. 

 

                
매크로 실행 전 (Sheet2는 비어 있는 상태임)           매크로 실행 후 결과 파일 (Sheet2)

매크로 실행 후 나타나는 파일 선택창 (가져오려는 텍스트파일을 선택하면 됨)
  

Option Explicit

Sub import_Text_With_Offset()                            '특정 행을 건너 뛰며 데이터 가져오기
    Dim strInput As String                                   '각 행을 읽어서 저장할 변수
    Dim cnt As Long                                          '카운터로 사용할 변수
    Dim strName As String                                  '읽어들일 파일이름 넣을 변수
    Dim r As Long                                             '행번호 늘려갈 변수
    Dim intNo As Integer                                     '몇번째 행마다 출력 할지 결정할 변수
   
    Application.ScreenUpdating = False               '화면 업데이트 (일시)중지
    Sheets(2).UsedRange.ClearContents             'Sheet2의 기존 데이터 삭제
    strName = Application.GetOpenFilename("텍스트파일,*.txt;*.csv;*.prn", _
        Title:="텍스트파일")                                   '파일을 열어서 파일명을 변수에 넣음
                                                     
    If strName = "False" Then                               '취소(Cancel) 선택 시
        MsgBox "취소(Cancel)하여 중단합니다.", 64, "파일선택 오류"  '오류메시지 출력
        Exit Sub                                                   '매크로 중단
    End If
   
    Open strName For Input As #1                        '선택한 파일 열기
   
    cnt = 1                                                         '카운트 1부터 시작
    r = 1                                                            '1행부터 시작
    intNo = 3                                                      '3번째 행마다 출력.
   
    Do Until EOF(1)                                            '파일의 마지막 행까지 실행
        Line Input #1, strInput                                '각 행을 읽어서 strInput에 저장
      
        If cnt Mod intNo = 0 Then                           '카운터를 intNo로 나눈 나머지가 0이면
            Sheets("Sheet2").Cells(r, 1) = strInput    '입력받은 데이터를 각 셀에 뿌림
            r = r + 1                                               '행번호 1씩 늘려감
        End If
      
        cnt = cnt + 1                                             '카운터 1씩 늘려감
    Loop                                                           '무한 반복
   
    Close #1                                                     '파일 닫기
End Sub

 

 

'MultiSelect:= True일 경우

    Dim fileName As Variant                                '모든 파일 넣을 배열 변수
                
    fileName = Application.GetOpenFilename("Text Files (*.txt),*.txt", , _
    "텍스트파일을 선택", MultiSelect:=True)           '텍스트 파일을 선택
   
    If TypeName(fileName) = "Boolean" Then Exit Sub    '취소 선택 시 매크로 종료
        
    For i = 1 To UBound(fileName)                       '선택한 파일 개수만큼 반복
        Open fileName(i) For Input As #1                '각 파일을 열기
            
        Close #1                                                 '열은 파일 닫기
    Next i
 

 

'Tab으로 구분된 파일 불러오기

Option Explicit

Sub import_Tab_Limited_Textfile()
 
  Dim fileName As String                                     '파일 이름을 넣을 변수
  Dim strInput As String                                      '각 행의 불러온 문자 넣을 변수
  Dim varTemp As Variant                                   '각 행을 tab으로 쪼개어 넣을 배열 변수
  Dim r As Long                                                '행(r)ow을 1씩 늘려갈 변수
  Dim c As Integer                                             '열(c)olumn을 1씩 늘려갈 변수 

  Application.ScreenUpdating = False                  '화면 업데이트 (일시)중지
  
  fileName = Application.GetOpenFilename("Text Files (*.txt),*.txt", , _
           "탭으로 구분된 텍스트파일")                     '파일을 열어서 파일명을 변수에 넣음

  If fileName = "False" Then Exit Sub                    '취소를 선택시 매크로 종료
 
  Open fileName For Input As #1                          '첫 번째 파일을 열기
  Line Input #1, strInput                                      '각 행을 불러와 strInput에 넣음
 

  Do Until EOF(1)                                              '파일의 마지막까지 실행
     varTemp = Split(strInput, vbTab)                    '불러온 행을 tab으로 나누어 배열에 넣음     
     r = r + 1                                                      '행을 1씩 늘려감
    
     For c = LBound(varTemp) To UBound(varTemp)  '배열 개수만큼 반복
        Cells(r, c + 1) = Val(varTemp(c))                '배열값을 셀에 뿌림
     Next c
    'Cells(r, UBound(varTemp) + 1) = varTemp       '문자인 경우 윗줄의 코드 대신 사용
  

     Line Input #1, strInput                                   '다음 행을 불러옴
  Loop                                                             '무한 반복
 

  Close #1                                                        '불러온 파일 닫기
End Sub

 

 

'특정 데이터가 있는 행부터 데이터 가져오기

Sub import_Textfiles_From_Certain_Row()
 
    Dim strName As String                                  '검색할 단어를 넣을 변수
    Dim lngNo As Long                                      '전체 가져올 행을 넣을 변수
    Dim fileNames As Variant                              '모든 파일 넣을 배열 변수
    Dim i As Integer                                           '반복 구문에 사용할 변수
    Dim strInput As String                                   '각 행의 불러온 문자 넣을 변수
    Dim varTemp As Variant                                '각 행을 tab으로 쪼개어 넣을 배열 변수
    Dim r As Long                                              '행(r)ow을 1씩 늘려갈 변수
    Dim cnt As Integer                                        '행 개수 카운터로 사용할 변수
    Dim c As Integer                                           '열(c)olumn을 1씩 늘려갈 변수
    Dim blnTF As Boolean                                  '시작행 판단한 변수
   
    Application.ScreenUpdating = False               '화면 업데이트 (일시) 중지

    ActiveSheet.UsedRange.ClearContents          '기존 데이터 삭제
   
    strName = "found"                                        '검색할 단어를 변수에 넣음
    lngNo = 3                                                    '검색 일치한 행부터 가져올 행개수
   
    fileNames = Application.GetOpenFilename("텍스트파일,*.txt;*.csv;*.prn", _
        Title:="텍스트 파일을 선택", MultiSelect:=True)
                                                                     '파일을 열어서 파일명을 변수에 넣음
   
    If TypeName(fileNames) = "Boolean" Then Exit Sub    '취소 선택 시 매크로 종료
       
    For i = 1 To UBound(fileNames)                     '선택한 파일 개수만큼 반복
        Open fileNames(i) For Input As #1             '각 파일을 열기
        Line Input #1, strInput                              '각 행을 불러와 strInput에 넣음
           
        Do Until EOF(1)                                       '파일의 마지막까지 실행
       
            If InStr(strInput, strName) Then              '행에 strName 포함되어 있으면
                blnTF = True                                    'blnTF 를 참으로 바꿈
            End If
           
            If blnTF = True Then                             'blnTF가 참인 경우에
                varTemp = Split(strInput, vbTab)         '불러온 행을 tab으로 나누어 배열에 넣음
                r = r + 1                                           '행을 1씩 늘려감
                cnt = cnt + 1                                    '카운터 1씩 늘려감
               
                For c = LBound(varTemp) To UBound(varTemp)  '배열 개수만큼 반복
                    Cells(r, c + 1) = varTemp(c)          '배열값을 셀에 뿌림
                Next c
            End If
           
            If cnt = lngNo Then Exit Do                    'lngNo 만큼 행을 가져오면 do 구문 종료
           
            Line Input #1, strInput                           '다음 행을 불러옴
        Loop                                                      '무한 반복
           
        cnt = 0                                                    '재사용 위하여 카운터 초기화
        blnTF = False                                          '시작 판단행 변수를 초기화
        Close #1                                                '열은 파일 닫기
    Next i
   
End Sub


반응형
반응형

출처: http://simon-k.tistory.com/27


이번 예제는 엑셀에 값을 입력할 때 마다 지정한 값에 따라서 셀 색상이 바뀌는 엑셀 매크로입니다.


[엑셀 VBA 강의 #15]에서 강의한 내용을 응용했습니다.






위와 같은 시트에서, 거래금액 란의 금액에 따라 색깔이 자동적으로 바뀌는 매크로를 만들어 보고자 합니다.


Private Sub worksheet_change(ByVal Target As Range)


Dim i As Integer

Dim n As Integer

Dim m As Integer


If Not Intersect(Range("c2:c9"), Target) Is Nothing Then

'----------------------여기부터 범위가 1보다 클 경우

If Target.Count > 1 Then            '타겟의 범위가 1보다 크다면(바뀌는 값의 범위가 한개가 아니라면)


n =  Target.Row                    '값을 수정하는 범위의 첫 행 (가장 윗행)

m = n + Target.Count - 1            '값을 수정하는 범위의 마지막 행(첫 행 + 범위 크기 - 1)


For i = n To m                            '범위의 첫 행부터 마지막 행까지 반복


    Select Case Cells(i, 3).Value            '셀의 값을 조건으로 한 조건문

    Case 0                                        '값이 0이라면(없다면)

    Cells(i, 3).Interior.color = xlNone        '셀을 투명하게(초기화)

    Case Is < 300000                            '값이 300000보다 작다면

    Cells(i, 3).Interior.color = RGB(255, 0, 0)        'red 색상으로 변경

    Case 300000 To 10000000                '값이 300000과 10000000 사이라면

    Cells(i, 3).Interior.color = RGB(0, 255, 0)        'green 색상으로 변경

    Case Is > 10000000                        '값이 10000000보다 크다면

    Cells(i, 3).Interior.color = RGB(0, 0, 255)        'blue 색상으로 변경

    End Select

Next i                    '다음 셀에서 반복


Exit Sub                '프로시져 종료

else

End If

'-------------------------여기까지 범위가 1보다 클 경우


'-------------------------여기부터 범위가 1일경우(한개의 셀만 수정할 경우)



    Select Case Target

        Case 0

        Target.Interior.color = xlNone

        Case Is < 300000

        Target.Interior.color = RGB(255, 0, 0)

        Case 300000 To 10000000

        Target.Interior.color = RGB(0, 255, 0)

        Case Is > 10000000

        Target.Interior.color = RGB(0, 0, 255)

    End Select

End If


End Sub





※ 이해가 안된다면 [엑셀 VBA #15] 강의를 읽어보세요.





Target의 범위가 무엇을 뜻하는 것인가요?


셀의 값을 수정할 경우, 일반적으로 한 개의 셀을 선택한 후 값을 집어넣지만,

복사 붙혀넣기를 통해 여러 값을 한번에 넣을 수도 있고, 셀을 드래그 블록지정 한 후 삭제를 해서 값을 없앨 수도 있습니다.


이러한 경우 Select Case Target으로 조건문을 만든다면, 타겟의 범위가 넓고, 값이 여러개이기 때문에 에러가 나게 됩니다.

따라서, Range 범위가 1일 경우와 1보다 큰 경우를 따로 설정하여 에러를 방지하기 위함입니다.


범위가 1보다 클 경우 반복문을 사용해 셀을 하나씩 읽어들이는 방법을 사용합니다.





반응형
반응형

출처: http://simon-k.tistory.com/11


실무적인 엑셀 VBA에 관한 질문이 들어와서, 엑셀 VBA 기초 강의와는 별개로 실전 예제도 연재해 보려고 합니다.

익숙하지 않은 내용들이겠지만 실전 예제를 통해 공부하는 것도 큰 도움이 될 것이라 생각합니다.

같이 진행되는 엑셀 VBA 기초 강의와는 번외적인 내용으로, 진도에 맞지 않는 점 인지하여 주시기 바랍니다.




엑셀 VBA는 매우 강력한 프로그래밍 툴으로써, 외부파일과 연계도 가능합니다.


이번 포스팅은 텍스트 파일을 엑셀에 입력하는 예제를 소개해드리도록 하겠습니다.





위와 같이 열과 열이 일정한 관계를 갖고 있는 텍스트 파일의 경우, 동일한 배열으로 엑셀에 옮겨담을 수 있습니다.


위의 텍스트 파일은 열 간의 간격이 탭키로 설정되어 있지만, 콤마( , ), 세미콜론( ; ) 등 뿐만 아니라 어떠한 규칙도 그 규칙이 일정 하다면 충분히 엑셀로 옮길 수 있습니다.


이 텍스트 파일의 첫번째 줄을 제외하고 숫자부분을 열에 맞춰서 엑셀에 옮기고자 합니다.


이 명령을 실행하는 엑셀 VBA 코드는 아래와 같습니다.


Sub text_to_excel()

    Const loadf As Long = 2             '텍스트 파일 속에서 가져와야 하는 시작하는 행 위치

    Const loadt As Long = 99999            '텍스트 파일 속에서 가져와야 하는 마지막 행 위치보다 큰 값을 설정

    Dim strFileName As String              '텍스트 파일 이름 설정

    Dim objText As Object           '텍스트 문서 값 개체변수

    Dim i As Long                       '변하는 행값 변수

    Dim varValue As Variant           '엑셀에 입력되는 값

    

    

    

    Application.ScreenUpdating = False


    With Application.FileDialog(msoFileDialogFilePicker)

                             .Show              '파일피커 열기

        If .SelectedItems.Count = 0 Then        '아무것도 선택되지 않았을 경우 프로시저 종료

            Exit Sub

        Else

            strFileName = .SelectedItems(1)        '파일 이름 지정

        End If

    End With

    

    If Len(strFileName) > 0 Then                   '파일 이름의 길이가 0보다 크면 (파일이 존재하면)

        

        Set objText = CreateObject("Scripting.FileSystemObject").OpenTextFile(strFileName, _

        IOMode:=1, Create:=False, Format:=-2)           '지정된 이름의 파일을 열기

        

        For i = 1 To loadt                      '지정한 행 수 만큼 반복하기

            If Not objText.AtEndOfStream Then           '텍스트파일의 끝이 아니라면

            If i < loadf Then                            '행의 위치가 지정된 시작 행(loadf)보다 작다면

            objText.skipline                            '그 행을 뛰어 넘는다

            Else

                varValue = Split(objText.ReadLine, vbTab)         '텍스트파일의 한 행의 값을 탭으로 분리해서 가져온다    

'vbTab을 "," ";" " " 등으로 바꿔서 사용할 수 있다.

                Cells(Rows.Count, 1).End(3)(2).Resize(, UBound(varValue) + 1) = varValue        '셀에 텍스트파일 값을 넣기                  

            End If

            End If

        Next i

    End If

       objText.Close

    Set objText = Nothing

    

End Sub



위 엑셀 vba 프로시저를 끝낸 후 엑셀에 출력되는 값은 아래와 같습니다.




만약에 특정 열의 값만 추출하고 싶다면 파란색으로 표시된 varValue 를 varValue(숫자) 로 바꿔주시고, 주황색으로 표시된 UBound(varValue)+1 부분을 1로 바꿔주시면 됩니다.   


varValue의 숫자값은 0부터 시작하는 정수가 되어야 합니다.


예를 들자면, varValue(1)는 2번째 열만 가져오게 됩니다.


이러한 방법을 통해서 텍스트 파일을 엑셀으로 옮겨올 수 있습니다.





그냥 넘어가긴 아쉬우니 제가 엑셀 VBA에서 자주 쓰는 간단한 편법을 하나 공개하도록 하겠습니다.


엑셀 VBA에서는 Worksheetfunction을 사용해서 엑셀 고유의 함수 기능을 구현할 수 있습니다.


하지만 Worksheetfunction을 굳이 사용하지 않고 엑셀 함수를 적용할 수 있는 방법 또한 존재합니다.


예를 들어 텍스트 파일의 2번째 열만 추출해서 평균값을 "E2"셀에 넣고, 평균값을 제외한 모든 값을 삭제해 보겠습니다.


Sub text_to_excel()

    Const loadf As Long = 2             '텍스트 파일 속에서 가져와야 하는 시작하는 행 위치

    Const loadt As Long = 99999            '텍스트 파일 속에서 가져와야 하는 마지막 행 위치보다 큰 값을 설정

    Dim strFileName As String              '텍스트 파일 이름 설정

    Dim objText As Object           '텍스트 문서 값 개체변수

    Dim i As Long                       '변하는 행값 변수

    Dim varValue As Variant           '엑셀에 입력되는 값

    

    

    

    Application.ScreenUpdating = False


    With Application.FileDialog(msoFileDialogFilePicker)

                             .Show              '파일피커 열기

        If .SelectedItems.Count = 0 Then        '아무것도 선택되지 않았을 경우 프로시저 종료

            Exit Sub

        Else

            strFileName = .SelectedItems(1)        '파일 이름 지정

        End If

    End With

    

    If Len(strFileName) > 0 Then                   '파일 이름의 길이가 0보다 크면 (파일이 존재하면)

        

        Set objText = CreateObject("Scripting.FileSystemObject").OpenTextFile(strFileName, _

        IOMode:=1, Create:=False, Format:=-2)           '지정된 이름의 파일을 열기

        

        For i = 1 To loadt                      '지정한 행 수 만큼 반복하기

            If Not objText.AtEndOfStream Then           '텍스트파일의 끝이 아니라면

            If i < loadf Then

            objText.skipline

            Else

                varValue = Split(objText.ReadLine, vbTab)         '텍스트파일의 한 행의 값을 탭으로 분리해서 가져온다

                Cells(Rows.Count, 1).End(3)(2).Resize(, 1) = varValue(1)        '셀에 텍스트파일 값을 넣기      '

            End If

            End If

        Next i

    End If

        objText.Close

  '(a2:a99999) 값은 평균 낼 데이터를 포함하는 범위

        Cells(2, 5).value = "=average(a2:a99999)"                'average 함수식을 셀(E5)에 집어넣는다

        Cells(2, 5).value = Cells(2, 5).value                         '출력된 함수값을 일반 형식의 값으로 바꾼다.

        Range("a2:a99999").Value = ""                                 '텍스트파일에서 추출한 데이터를 삭제한다

    Set objText = Nothing

    

End Sub


초록색으로 표시된 부분이 추가된 부분입니다.


특정 셀에 함수식을 넣는 것만으로 함수식의 결과값을 얻어낼 수 있습니다.


average 함수 뿐만 아니라 엑셀의 모든 함수를 사용할 수 있습니다.


하지만 편법이다 보니 광범위하게 사용하기는 힘듭니다.


이런 방법도 있구나.. 하고 알아두시면 됩니다.


Worksheetfunction에 대한 내용은 추후에 엑셀 기초강의에서 다루도록 하겠습니다.


반응형

+ Recent posts