[excel - python - uipath] 엑셀 자동화에 대해서 알아보자(8-2)

루까까·2023년 9월 10일
0

Excel 자동화

목록 보기
16/25
post-thumbnail

이번 시간에는 Fill Range activity를 python 코드로 구현해보는 시간을 가져보자.
(uipath Fill Range activity 알아보기)

1. 전체코드

def fill_range(file_name: str, sheet_name: [str, int], range_value: str, value: [str, int], value_change: bool = True):

    wb = load_workbook(file_name)
    ws = wb[sheet_name]

    pattern = r'[a-z A-Z]+'
    column_result = re.findall(pattern, range_value)
    start_column = column_result[0]
    start_column = column_index_from_string(start_column)
    end_column = column_result[1]
    end_column = column_index_from_string(end_column)

    pattern = r'\d+'
    row_result = re.findall(pattern, range_value)
    start_row = int(row_result[0])
    end_row = int(row_result[1])

    if value_change:
        if type(value) == int:
            for row_idx, row in enumerate(range(start_row, end_row + 1)):
                for col_idx, col in enumerate(range(start_column, end_column + 1)):
                    new_value = value + col_idx
                    ws.cell(row=row, column=col, value=new_value)
                value = value + 1
        else:
            if '=' in value:
                pattern = r'[A-Z]+\d+'
                value_result = re.findall(pattern, value)
                dict = {}

                for row_idx, row in enumerate(range(start_row, end_row + 1)):
                    for col_idx, col in enumerate(range(start_column, end_column + 1)):
                        for i in value_result:
                            cell_colume_str = i[0]
                            cell_row_str = i[1:]
                            new_cell = get_column_letter(column_index_from_string(cell_colume_str) + col_idx)
                            new_cell = new_cell + str(cell_row_str)
                            if len(new_cell) != len(i):
                                new_cell = new_cell + ' '
                            dict[i] = new_cell
                        cell_key = ''.join(list(dict.keys()))
                        cell_value = ''.join(list(dict.values()))
                        new_col = value.translate(str.maketrans(cell_key, cell_value))
                        ws.cell(row=row, column=col, value=new_col)
                        dict = {}

                    pattern = r'[A-Z]+\d+'
                    value_result = re.findall(pattern, value)
                    for i in value_result:
                        cell_colume_str = i[0]
                        cell_row_str = i[1:]
                        new_cell = str(int(cell_row_str) + 1)
                        new_cell = str(cell_colume_str) + new_cell
                        dict[i] = new_cell
                    for i in dict.keys():
                        value = value.replace(i, dict[i])
                    dict = {}

            else:
                for row_idx, row in enumerate(range(start_row, end_row + 1)):
                    for col_idx, col in enumerate(range(start_column, end_column + 1)):
                        ws.cell(row=row, column=col, value=value)
    else:
        for row_idx, row in enumerate(range(start_row, end_row + 1)):
            for col_idx, col in enumerate(range(start_column, end_column + 1)):
                ws.cell(row=row, column=col, value=value)

    wb.save(file_name)

2. 코드 설명

2-1. 함수 인자 설명

def fill_range(file_name: str, sheet_name: [str, int], range_value: str, value: [str, int], value_change: bool = True):
  • file_name은 엑셀명 기입
  • sheet_name은 엑셀 시트명 기입(위치도 입력 가능)
  • range_value는 기입하고자 하는 범위(ex. A1:B2)
    • str형만 가능
  • values는 기입하고자 하는 값
    • 수식도 기입 가능(ex.=A1+B2)
    • 형식은 int형 혹은 str형으로 기입할 것
  • 자동 채움 기능을 사용할 것인지, 사용하지 않을 것인지에 대한 선택
    • 기본적으로 사용으로 되어 있음
    • 해당 기능을 사용시 엑셀 자동 채움 기능이 활성화 됨

2-2. 범위 추출

pattern = r'[a-z A-Z]+'
column_result = re.findall(pattern, range_value)
start_column = column_result[0]
start_column = column_index_from_string(start_column)
end_column = column_result[1]
end_column = column_index_from_string(end_column)

pattern = r'\d+'
row_result = re.findall(pattern, range_value)
start_row = int(row_result[0])
end_row = int(row_result[1])
  • 정규식을 이용해서 범위를 추출한다.
    • start_column
    • end_column
    • start_row
    • end_row
  • 예를 들어 'A1:B2'라는 범위라고 하였을 때,
    • start_column은 'A'
    • end_column은 'B'
    • start_row는 '1'
    • end_row는 '2'
    • 로 추출한다.
  • 특히, column의 경우 column_index_from_string 함수를 이용해서 컬럼 위치값으로 반환한다.
    • ex. 'A'컬럼의 경우 1

2-2. 엑셀 자동 채움 기능 여부

if value_change:
    ...
else:...
  • 자동 채움 기능 사용 여부에 따라 크게 두가지 갈래로 나뉜다.
  • 자동 채움 기능이란, 예를들어 'A1 cell'에 '1'이이라는 값이 있을 때,
    자동 채움 기능을 이용하여 'A2'는 '2' 'A3'는 '3' 이런식으로 자동으로 cell값을 채우는 기능을 말한다.
  • 물론, 수식도 지원한다.
    • 'A1'에 수식 '=A1+B2'일 경우, 'A2'는 '=A2+B3'
  • 자세한 건, 검색하는 것을 추천한다..(필자 또한 많이 사용해보지는 않은 기능이다..)

2-2-1. 자동 채움 기능을 사용하지 않는 경우

for row_idx, row in enumerate(range(start_row, end_row + 1)):
    for col_idx, col in enumerate(range(start_column, end_column + 1)):
        ws.cell(row=row, column=col, value=value)
  • 추출된 범위의 각 행과, 각 열을 조회하면서 기입하고자 했던 값을 기입한다.

2-2-2. 자동 채움 기능을 사용하는 경우

2-2-2-1. 단순 int형의 경우
if type(value) == int:
    for row_idx, row in enumerate(range(start_row, end_row + 1)):
        for col_idx, col in enumerate(range(start_column, end_column + 1)):
            new_value = value + col_idx
            ws.cell(row=row, column=col, value=new_value)
        value = value + 1
  • 자동 채움 기능의 경우 지원되는 경우가 크게 두가지 인데
    • 단순 int형 즉, 1, 2 같은 숫자이며
    • 다른 하나는, 수식이다.
  • 숫자과 수식의 자동 채움기능은 동작하는 구조가 다르기에 나뉘어져 있다.
  • 먼저 type함수를 이용하여 int형인지 str형인지 구분한다.
  • int형이면 추출된 범위의 각 행과, 각 열을 조회하면서 기입하고자 했던 값을 기입하는데
    • 각 행이 증가할때 마다 +1을 해준다.
      • 해당 코드는 value = value + 1 다.
    • 각 열이 증가할때 마다 원래 값에서 +1을 해준다.
      • 해당 코드는 new_value = value + col_idx다.

예를들어 범위가 A5:C8'이고 '8'이라는 값을 기입 하는 경우, 다음과 같은 결과값이 보인다.

2-2-2-1. 단순 str형의 경우
 if '=' in value:...
 else:
    for row_idx, row in enumerate(range(start_row, end_row + 1)):
        for col_idx, col in enumerate(range(start_column, end_column + 1)):
            ws.cell(row=row, column=col, value=value)
  • 수식이 아닌 단순 text를 기입하는 경우도 지원한다.
  • 엑셀 수식의 경우 '='가 있어야 수식으로 판단되기에 '='를 바탕으로 단순 text인지 수식인지 구분한다.
  • 단순 text의 경우, 추출된 범위의 각 행과, 각 열을 조회하면서 기입하고자 했던 값을 기입한다.
2-2-2-1. 수식의 경우
 if '=' in value:
    pattern = r'[A-Z]+\d+'
    value_result = re.findall(pattern, value)
    dict = {}

    for row_idx, row in enumerate(range(start_row, end_row + 1)):
        for col_idx, col in enumerate(range(start_column, end_column + 1)):
            for i in value_result:
                cell_colume_str = i[0]
                cell_row_str = i[1:]
                new_cell = get_column_letter(column_index_from_string(cell_colume_str) + col_idx)
                new_cell = new_cell + str(cell_row_str)
                if len(new_cell) != len(i):
                    new_cell = new_cell + ' '
                dict[i] = new_cell
            cell_key = ''.join(list(dict.keys()))
            cell_value = ''.join(list(dict.values()))
            new_col = value.translate(str.maketrans(cell_key, cell_value))
            ws.cell(row=row, column=col, value=new_col)
            dict = {}

        pattern = r'[A-Z]+\d+'
        value_result = re.findall(pattern, value)
        for i in value_result:
            cell_colume_str = i[0]
            cell_row_str = i[1:]
            new_cell = str(int(cell_row_str) + 1)
            new_cell = str(cell_colume_str) + new_cell
            dict[i] = new_cell
        for i in dict.keys():
            value = value.replace(i, dict[i])
        dict = {}
  • 수식의 경우, 자동 채움기능을 다음과 같이 지원한다.
  • 예를들어 '=A1+B2'라는 수식이 있다고 가정할때,
    1. 정규식을 이용하여 'A1','B2'로 분리한다.
    2. 정규식을 이용하여 'A','1','B','2'로 다시 분리한다.
    3. 컬럼의 경우, column_index_from_string함수를 이용하여 숫자로 변환한다.
    4. 각각의 int형값에다가 +1을 해준다.
    5. 컬럼의 경우, get_column_letter함수를 이용하여 컬럼으로 변환한다.
    6. 해당 값들을 dict형의 변수에다가 저장한다.
    7. value.translate(str.maketrans(cell_key, cell_value))를 통해 수식을 한번에 변환한다.
    8. 변환된 수식을 추출된 각 행과 각열을 조회하면서 기입한다.
  • 각 행이 증가할 때마다 수식의 숫자가 +1씩 늘어나며,
  • 각 열이 증가할 때마다 수식의 컬럼이 +1씩(A->B)로 증가한다.
    • 물론 열이 바뀔때마다 기존값에서 컬럼이 +1씩 증가하는 것이다.
    • 예를들어 'A1'의 수식이 '=A1+B2'일 경우, 'B2'의 수식은 '=B1+C2'이다.
profile
기타치는 개발자

0개의 댓글