본문 바로가기

파이썬-엑셀 자동화 기초

1. 파이썬으로 엑셀프로그램을 열고, 값을 입력해봅시다.

아래아한글 자동화기초 1번에서 아나콘다와 파이참을 설치했습니다.

엑셀 자동화도 동일한 프로그램으로 진행할 예정이므로 위 두 개의 프로그램을 먼저 설치해 주시기 바랍니다.

VSCode나 노트패드++ 등 기존에 익숙하게 사용하시는 에디터나 IDE가 있다면

굳이 파이참을 사용하지 않으셔도 됩니다.

다만 제가 단축키를 알려드리거나 할 때는 파이참 기준으로 설명을 드릴테니,

사용하시는 프로그램에서 해당하는 명령어를 사용하시면 되겠습니다.

 

우선 이번 기초 튜토리얼에서는 한/글과 마찬가지로 pywin32 패키지의 win32com 모듈을 통해서 엑셀을 열어봅니다.

첫 시간은 파이참이 아니라 프롬프트에서 실행해보겠습니다.

윈도우 시작 버튼을 누르고, "Anaconda Prompt (anaconda3)" 아이콘을 찾아서 실행해봅니다.

상단의 Anaconda Prompt (anaconda3)를 선택합니다.

혹시 아나콘다를 설치했는데, 해당 아이콘을 찾기 어렵다면,

1. 아래 화면처럼 Anaconda3 (64-bit) 폴더 안에 해당 아이콘이 있습니다.

직접 찾아가서 실행하는 방법

2. 시작버튼을 누르자마자 "anacon" 을 입력하다 보면 아래처럼 "가장 정확"한 앱으로 아나콘다 프롬프트를 보여줄 겁니다.

시작버튼을 누르자마 "an"만 입력했는데, 아나콘다프롬프트를 보여줍니다.

 

하여튼 이런 방법으로 아나콘다 프롬프트를 실행하면 아래와 같은 화면이 나옵니다.

아나콘다 프롬프트 초기화면

일반 명령프롬프트와는 다르게 아나콘다 프롬프트 좌측에는 (base) 라는 표시가 항상 붙어다닙니다.

이건 아나콘다에서 기본으로 제공하는 "가상환경"인데요. 아나콘다 프롬프트를 실행하자 마자

아래의 명령어가 백그라운드에서 자동으로 실행됩니다.

C:\anaconda3\Scripts\activate.bat C:\anaconda3

가상환경이 뭔지 궁금하신 분은 "virtualenv"나 "conda 가상환경"으로 구글링해보시길 추천드립니다.

하여튼 프롬프트에 "ipython"이라고 입력하고 엔터를 눌러 보시면, ipython 콘솔 창이 나타납니다.

한/글 자동화 기초 첫 예제를 실행할 때와는 콘솔 프롬프트의 모양이 조금 다릅니다.

python 콘솔 프롬프트의 모습(>>>)
ipython 콘솔의 모습

ipython이 python보다 유용한 부분이 참 많은데, 일일이 설명드리기보다는, 잘 정리된 포스팅을 하나 검색해 보시는 것을 추천드립니다. 개인적으로 python 콘솔보다 ipython을 좋아하는 가장 큰 이유는 %로 시작하는 매직메서드나, !로 시작하는 셸커맨드를 ipython 콘솔 내에서 실행할 수 있다는 점입니다. 예를 들면, 클립보드 데이터를 간편히 다룰 수 있는 pyperclip이나 clipboard 모듈은 아나콘다 패키지에 포함되어 있지 않습니다. 일반적으로는 "exit"를 실행해서 커맨드프롬프트로 빠져나온 후 "pip install pyperclip"을 실행하고 설치가 완료되면 다시 ipython을 실행해야 하지만,

ipython 콘솔에서는 아래 화면처럼 셸 커맨드를 실행해서 직접 모듈을 설치할 수도 있습니다.

!를 먼저 붙이고 셸 커맨드를 입력하면,
ipython 콘솔 위에서도 모듈의 설치가 가능하다.

특히 pip나 ls, copy 등 커맨드프롬프트용 명령어 일부는 !를 붙이지 않고도 작동합니다. (pip install pyperclip 가능) ipython의 활용 방법만 가지고도 책을 한 권 쓸 수 있을 정도로 유용한 기능들이 많으므로, 적절한 교재와 구글링을 통해서 한 번 알아보시기를 바랍니다.

이제 본론입니다.

ipython으로 엑셀을 열고, A1셀에 "Hello", A2셀에 "World!"를 입력해보겠습니다.

ipython에 아래 커맨드를 순서대로 입력합니다.

코드가 길더라도 가급적 복붙하지 마시고 익숙해지시길 바랍니다.

import win32com.client as win32
excel = win32.gencache.EnsureDispatch("Excel.Application")
excel.Visible = True
wb = excel.Workbooks.Add()
ws = wb.Worksheets(1)

 

 코드를 라인별로 간단히 설명드리면,

1. 윈도우 응용프로그램을 원격으로 제어하기 위한 win32com.client 모듈 임포트

2. excel 객체 생성(gencache.EnsureDispatch는 해당 객체의 메서드나 프로퍼티를 early-binding으로 로딩)

3. excel 프로그램 숨김해제(워크북이나 워크시트 없이 빈 화면임)

4. wb라는 워크북 생성(1개의 엑셀파일 개념)

5. 1번 워크시트를 ws로 지정. 다음과 같이 작성할 수도 있음: ws = wb.Worksheets("Sheet1")

이상입니다.

당장 여러 가지를 해 보고 싶지만,

우선 워크시트명인 Sheet1을 바꿔봅시다. 저는 "RawData"라고 바꿔보고 싶은데요, 여러분도 자유롭게 바꿔보세요.

ws.Name = "RawData"

이렇게 실행하면 시트명이 간단히 바뀝니다.

이번에는 파이썬 문법을 조금 응용해서 A1셀에 "Hello", B1셀에 "World"를 입력해보겠습니다.

가장 기본이 되는 입력은 아래와 같이 Cells와 Range 메서드를 이용하는 방법입니다.

ws.Range("A1").Value = "Hello"
ws.Cells(1, 2).Value = "World"

Cells 안에 들어가는 인덱스 두 개는 차례대로 행,렬입니다. B1셀이면 ws.Cells(1,2)로 나타낼 수 있습니다.

위 두 줄의 코드를 아래처럼 한 줄로 표현할 수도 있습니다.

ws.Range("A1:B1").Value = "Hello", "World"

실행결과는 둘 다 아래와 같습니다.

A1셀과 B1셀에 문자열 입력

 

자, 이제 다음 단계로 가 봅시다.

위의 예제를 보면서 유심히 고민해 보신 분들 중에, 이런 궁금증이 들지 않으셨나요?

1. 'Range 지정을 저렇게 문자열로 "A1:B1"하는 방법 밖에 없을까? 범위를 동적으로 지정하고 싶을 때 번거롭겠다..'

2. '가로 말고 세로로 A1, A2 셀에 입력할 때도 같은 방식으로 하면 되나?'

이 두 가지 문제만 해결을 하고 마칩시다.

우선 1번, 범위설정은 문자열이 아닌, 코드로 가능합니다.

Range 메서드는 아래처럼 다양한  방식으로 표현할 수 있습니다. Range 안에 Cells가 들어가는 방식입니다.

ws.Range("A1:B1").Value = "Hello", "World"
ws.Range(ws.Cells(2,1), ws.Cells(2,2)).Value = "Hello", "World"  # == "A2:B2"
start, end = 3, 6
ws.Range(ws.Cells(start,1), ws.Cells(end,2)).Value = "Hello", "World"  # "A3:B6"

참고로 #을 포함한 뒤의 문자는 파이썬 내에서 주석으로 처리되므로 타이핑하지 않으셔도 됩니다.

결과는 아래와 같습니다.

실행결과

궁금증(?)이 해결되었나요? Range 메서드 안에 Cells 메서드를 입력하고 그 안에 변수를 활용하면

for문과 변수를 활용해서 동적으로 다양한 Range에 값을 넣을 수 있다는 사실도 유추하실 수 있겠죠?

특히 한 가지 재미있는 점은, 네 번째 라인 코드의 Range는 4x2 배열인데,

입력값이 1x2 배열인데도 오류없이 잘 입력되었습니다. (넘파이 array의 BroadCasting처럼요.)

이 부분은 다음 시간에 좀 더 상세하게 다뤄보겠습니다만,

엑셀입력을 최적화하려면, 2중 for문으로 한땀한땀 개별입력하지 마시고,

파이썬 단에서 2차원 배열로 입력할 값을 정리해서 위처럼 한 번에 쏴주시면 더 쾌적한 느낌입니다.

 

그럼 이번엔 두 번째 궁금증, 세로로 A1셀에 "Hello", A2셀에 World"를 입력해 보고 싶은데,

같은 방법으로 하면 될까요?

답부터 말씀드립니다. 안됩니다. 엑셀에 입력된 기존 값들을 지우고 나서 아래의 코드를 실행해보면,

ws.Range("A1:A2").Value = "Hello", "World"

결과가 예상했던 것과 좀 다릅니다???

Hello, Hello? World는 어디 갔나?

이 문제의 원인은, 엑셀의 Range가 2차원 배열을 받아야 해서 그렇습니다.

무슨 뜻인지 잘 이해가 안 되신다고요? 아래의 코드를 참고하시길 바랍니다.

아래처럼 실행하면 원했던 대로 잘 입력됩니다. 

결과를 꼭 한 번 예측해 보신 후에 스크롤을 내리거나 코드를 실행해 보실 것을 추천합니다.

 

ws.Range("A1:A2").Value = ("Hello",), ("World",)  # 가장 바깥쪽의 괄호가 생략되었지만 2차원(2x1) 튜플임
ws.Range("B1:B2").Value = [["Hello"], ["World"]]  # 2x1 리스트
ws.Range(ws.Cells(1,3), ws.Cells(2,7)).Value = [i for i in "Hello"], [i for i in "World"]  # 2차원리스트(2행5열)

 

 

 

 

위 코드의 실행결과는 아래와 같습니다.

2차원 튜플과 리스트를 이용한 여러 행 입력

 

파이썬-엑셀 자동화기초 첫 번째 포스팅인데 조금 길어졌네요..

이번 포스팅은 여기서 마치겠습니다.

ipython으로 엑셀을 열고 특정 Range에 2차원 튜플과 리스트를 이용하여 텍스트를 삽입하는 방법을 보여드렸습니다.

 

다음 포스팅은 이번과 반대로, 범위가 주어지지 않고 2차원 튜플이나 리스트만 생성되어 있을 때 

해당 자료를 동일한 사이즈의 엑셀범위에 그대로 입력하는 방법을 알아보겠습니다.

 

np.array나 pd.DataFrame 등 파이썬 유저들에게 익숙한 배열자료형을 사용하는 예제는

추후 응용편에서 다뤄보겠습니다.

 

긴 글 읽어주셔서 감사합니다.

행복한 하루 되세요!

반응형