친구가 SOS를 보냈다. 1 (feat. excel, python)

2020. 4. 10. 15:23

리버언니는 모 SNS에서 물건을 판매한다. 벌이가 꽤 괜찮은것 같다. 구조가 일반 몰과는 다르다. 돈을 먼저받고 그만큼만 발주를 넣어 중국에서 받아온 뒤 배송을 하는 방법이다. 예약판매라는 방식이라고 한다. 처음알았다.

 

각설하고, 한창 석사 논문을 쓰던 중 언니가 잠시 알바겸 도와달라고 했다. 그때 알바가 한번 발주를 와장창 잘못해서 (두배로 하고 난리도 아니었다) 너무 스트레스 받아해서 내 논문도 있지만 조금 도와주게 되었다. 내 코가 석자였으면서

 

아무튼 내 업무중 하나는 발주를 넣는것이었다. 주문폼도 어디 플랫폼을 쓰고 이 사이트가 만악의 근원이다. 웹모르는 내가 봐도 거지같이 코딩했다는거 느껴졌다. 학부생의 냄새가 났다. SNS에 글을 업로드해야하는건 사람이 해야하니 문제가 없었다. 앞에 여러 업무들은 실수가 생기면 고치면 된다. 하지만 발주는 가장 까다롭고, 돈에 관련된 업무였다. 더군다나 전임자가 발주실수를 와장창 했다니 더 무서웠다.

 

 

그래도 뭔가 방법이 있겠지... 싶었는데 컴알못 리버언니... 알바가 실수 할 만도 하다. 주문 폼받은걸 엑셀로 다운로드 받아 일일이 ctrl+F를 눌러가며 여태 카운트를 했다는 것이다. 환장! 발주는 매주 한번씩 진행되는데 일단 첫주는 그 사실을 몰랐으니 직접 해봤다. 안되겠다. 눈알빠지는 줄알았다. 3시간이 걸렸다. 돈은 벌어서 좋았지만 내시간..또륵

 

역시나! 만능파이썬씨. 엑셀파일 읽어오는 건 문제도아니고 값접근도 상당히 쉬웠다. 그럼 이제 파이썬으로 한번 사무자동화를 해보자! openpyxl !

 

문제의 주문폼이다. 전에 다 지워버려서 뭐가 없네

이렇게 되어있으니 문제점이 무엇이냐,

1. 사이즈가 별도인 아이템은 사이즈 마다 카운트를 따로해준다. (옷과 신발 위주니 색상과 사이즈가 많은건 당연)

2. 사이즈에 색깔까지 있으면 탐색 시간복잡도가 얼추 O(n^2)이 될것같다.

3. 암튼 옵션이 2-3중으로 된 경우 죽고 싶다. (일례로 한 치마가 색상/길이/사이즈 이렇게 옵션이 세개여서 미치는 줄알았다.)

4.이런식으로 물건이 n개있으니 시간복잡도 O(n^3)까지도 갈지도 모른다... 이렇게 계산해도 될까 ㅋㅋ

5. 맨끝엔 수량인데 가끔 2개 이상 사는 사람들이있을땐 생각없이 놓칠 수도 있다.

 

하지만 자세히 보면 그래도 주문폼에서 나름의 규칙을 만들어주었다. /로 구분되는 편이고, 안의 내용은 쉼표로 구분되어있다. 그러니까 간단히 생각해보면 쭉 같은 열을 돌면서 '\n'으로 아이템마다 구분해주며, 간단하게 옵션별로 한문장을 만들고 숫자만 세면 좋을것같았다. 예를들어, 숄 가디건,ONE SIZE,꽃 아이보리의 경우, 그냥 '숄가디건 ONE SIZE 꽃 아이보리' 로 한문장을 만들었다. 지금 생각하면 딕셔너리를 만들어서 key와 value로 아이템, 수량 할걸그랬나 싶기도 하다. 그러나 그냥 내가편하자고 쓰는 프로그램이니까 과감하게 삼중 for 문의 길을 걸었다 휴 이 죽일놈의 코더 근성. 그렇다면 숫자는 어떻게 처리했느냐? 맨 마지막은 수량이니 '개'자를 빼고 숫자만 int로 받아온뒤 그 수만큼 list에 넣어줬다.

설명을 하니 말이 좀 이상한데, 주문을 모두 정리하는 하나의 큰 list를 만들었다. 예를 들겠다.

주문자 a : 빨강 스웨터 s 2개, 초록 스웨터 xl 1개

주문자 b : 빨강 스웨터 l 1개, 초록 스웨터 xl 2개, 반지 원사이즈 1개

이렇게 있으면, 반복문을 통해 물건의 갯수만큼 list에 추가했다. 즉 정리하지 않은 list의 모습은 이렇게 될것이다.

빨강 스웨터 s

빨강 스웨터 s

초록 스웨터 xl

빨강 스웨터 l

초록 스웨터 xl

초록 스웨터 xl

반지 원사이즈

총 7품목. 이렇게 완성된 list를 중복된 값들은 값을 세어주어 같이 띄우면 편리할 것이다. 도와줘요 collection 모둘!

collection의 Counter() 를 사용하면, 컨네이너에 동일한 값의 자료가 몇개 있는지 확인해주는 객체이다. list dictionary 등등 넣어줄 수 있나보다. list를 넣으면 dictionary로 반환해 준다. 하지만 먼저나온 순서대로 정렬하기 때문에 우선 sort()를 통해 list를 가나다 순으로 정리하였다. 그리고 Counter()이용하여 새로운 dictionary를 출력해준다. (어차피 사람이 수량 체크만 해주면 되는것이기에 print로만 보기좋게 출력해주었다. Counter()를 이용한 결과값은 다음과 같다.

반지 원사이즈 1

빨강 스웨터 s 2

빨강 스웨터 l 1

초록 스웨터 xl 3

그렇게 하여 리버언니의 사업은 날로 번창~~ 하는 듯 보였으나, 어제 또 연락이 왔다. 친구의 SOS 2편에서 계속~>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from openpyxl import load_workbook
from collections import Counter
 
load_wb = load_workbook("파일 경로", data_only = True) #파일위치 넣기
load_ws = load_wb['시트 명'#시트 명
colE = load_ws['L'#읽어올 열
items = [] #결과가 될 배열
cnt = True #첫줄 여부 확인할 bool
itemSTR = ''
 
for line in colE :
    if cnt: #첫줄은 넘어간다 (이름/주소/비고 등등이 써있어서 ㅎ)
        a =1
        cnt = False
    else :
        
        orders = line.value.split('\n'#물건 별로 주문 분리
        
        for i in orders :
            
            item = i.split('/'# 마감날짜/옵션/갯수
            #물건 갯수를 세어봅시다.
            itemCNT = item[-1#항상 맨마지막은 갯수
            itemCNT = int( itemCNT.replace("개",'') ) #숫자만 int로 남기기
            for idx  in range(1,len(item)-1) : 
                itemSTR = itemSTR + item[idx] + '   ||  ' #옵션이 3개가 될지 2개가 될지 모른다. 그래서 item의 길이를 확실히 모르기 때문에 for문사용
            for k in range(0,itemCNT) : 
                items.append(itemSTR) #갯수에 맞게 list에 추가
            itemSTR = '' #다음 상품을 위해 초기화
 
result = Counter(items) #중복 카운트
 
for key in result: #출력부
    print ( key, result[key] )
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

 

+) 사족. 원래는 나쁜 생각도 들었다. 이거 돌리고 알바시간 한 3시간 써둘까 했는데 그건 넘 양애취 같아서 ^^ 그냥 리버언니에게 오픈했다. 언니 근데,,, 이거 한 10만원은 주라,,, 알바들 매주 3시간 줄었자나.... 나 그래도 석산데 ^.T