Excel 수식이 너무 복잡하고 들여 쓰기를 원했을 때 한 일
개요
Excel의 수식란에 상당한 길이의 수식이 묻혀 있어, 읽어내기에도 수정하는데도 상당한 고생이 필요하게 되어 버렸기 때문에, 일단 빼내 해 해석을 시도한 이야기.
데이터 추출에는 Openpyxl을 사용했습니다.
이런 상황이었
![](https://s1.md5.ltd/image/80fe054c90d21e3091584dbe41271bee.png)
Excel의 수식에 넣어 좋은 문자열은 75문자까지라든지 누군가 결정해 줘・・・w
(계산 결과의 도중을 어느 쪽의 셀에 내뿜는다든가···.)
특히 Excel의 IF는 읽기가 어렵습니다.
=IF(A1="これこれ", "xxxx", IF(B1="あれこれ", "yyyy", "zzzz"))
이런 쓰는 방법, 잘 하는군요・・・.
if (A1 === "これこれ") {
cell = "xxxx";
} elseif (B1 === "あれこれ") {
cell = "yyyy";
} else {
cell = "zzzz";
}
라는 느낌입니다만, 독자 함수 정의하면 매크로가・・・라고 이야기가 되고, 리팩토링도 어렵습니다. 그래서 들여쓰거나 해서 어떻게든 가독성을 줄 수밖에 없네요.
덧붙여서 Excel 수식에 있어서의 들여쓰기에, N() 함수를 더해 코멘트같이 쓸 수 있거나 배열 수식을 사용해 코멘트같이 쓰는 방법도 있는 것 같습니다・・・
→ 수식 작성에 유용한 기법
이번에는 값을 꺼내 ~ 들여 쓰기를 추가하는 곳을 시도합니다.
물론 매크로를 사용하여 해결하는 방법도 있네요.
→ Excel에서 중첩된 If 함수를 VBA로 들여쓰고 분석하기 쉽습니다.
파이썬으로 시도
이번에는 Openpyxl을 사용해 보겠습니다.
드디어, 수식의 해석은 Parsing Formula (을)를 사용해 할 수 있는 것 같습니다.
우선 써 있는 것을 시도해 봅시다.
>>> from openpyxl.formula import Tokenizer
>>> tok = Tokenizer("""=IF(A1="これこれ", "xxxx", IF(B1="あれこれ", "yyyy", "zzzz"))""")
>>> print("\n".join("%12s%11s%9s" % (t.value, t.type, t.subtype) for t in tok.items))
IF( FUNC OPEN
A1 OPERAND RANGE
=OPERATOR-INFIX
"これこれ" OPERAND TEXT
, SEP ARG
WHITE-SPACE
"xxxx" OPERAND TEXT
, SEP ARG
WHITE-SPACE
IF( FUNC OPEN
B1 OPERAND RANGE
=OPERATOR-INFIX
"あれこれ" OPERAND TEXT
, SEP ARG
WHITE-SPACE
"yyyy" OPERAND TEXT
, SEP ARG
WHITE-SPACE
"zzzz" OPERAND TEXT
) FUNC CLOSE
) FUNC CLOSE
과연. 선두로부터 각각의 파트가 함수(시작·종료)인지, 변수인지 등등으로 분해해 주는 것 같다.
라고 하는 것은 함수가 개시하면 개행해, 다음의 행에는 들여쓰기를 붙여, 함수가 종료할 때에 들여쓰기를 줄이고 나서 개행해 가면 된다고 하는 것이군요.
이해하기 쉽도록 들여 쓰기를 시각화하고 씁니다.
from openpyxl.formula import Tokenizer
# あとでindent_charはもちろんスペースに直すよ
def parse(formula, indent_char = "_"):
# 最終的に文字列として結合して返す
result = ""
tok = Tokenizer(formula)
# インデント数
n = 0
# 直前で処理したトークン
last = None
for t in tok.items:
if t.type == "FUNC":
if t.subtype == "OPEN":
if last is not None and (last.type == "FUNC" and last.subtype == "OPEN"):
n += 2
result += indent_char * n + t.value
else:
result += t.value
result += "\n"
else:
# function close。インデント数を戻す
n -= 2
result += "\n" + indent_char * n + t.value
else:
# それ以外は単純結合。直前が関数の場合はインデント
if last is not None and (last.type == "FUNC" and last.subtype == "OPEN"):
n += 2
result += indent_char * n + t.value
else:
result += t.value
last = t
return result
s = """=IF(A1="これこれ", "xxxx", IF(B1="あれこれ", "yyyy", "zzzz"))"""
print(parse(s))
IF(
__A1="これこれ", "xxxx", IF(
____B1="あれこれ", "yyyy", "zzzz"
__)
)
그래. 이것으로 좋을 것 같다.
나머지는 Excel의 지정된 셀 범위를 전달합니다.
wb = load_workbook(filename, data_only = False)
sheet_name = "Sheet1"
cell_range = "A2:C2"
for line in wb[sheet_name][cell_range]:
for cell in line:
# formula のみを抽出
if cell.data_type == "f":
f = parse(cell.value)
# cell.coordinateには「A1」などの表現が入る
with open(cell.coordinate + ".txt", mode='w') as fl:
fl.write(f)
이런 식으로 하면 수식이 묻혀 있는 셀만 A2.txt, C2.txt처럼 들여쓰기된 텍스트로 내뿜을 수 있습니다.
Reference
이 문제에 관하여(Excel 수식이 너무 복잡하고 들여 쓰기를 원했을 때 한 일), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tetsunosukeito/items/1df3f9e4e8d843992dfd
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
![](https://s1.md5.ltd/image/80fe054c90d21e3091584dbe41271bee.png)
Excel의 수식에 넣어 좋은 문자열은 75문자까지라든지 누군가 결정해 줘・・・w
(계산 결과의 도중을 어느 쪽의 셀에 내뿜는다든가···.)
특히 Excel의 IF는 읽기가 어렵습니다.
=IF(A1="これこれ", "xxxx", IF(B1="あれこれ", "yyyy", "zzzz"))
이런 쓰는 방법, 잘 하는군요・・・.
if (A1 === "これこれ") {
cell = "xxxx";
} elseif (B1 === "あれこれ") {
cell = "yyyy";
} else {
cell = "zzzz";
}
라는 느낌입니다만, 독자 함수 정의하면 매크로가・・・라고 이야기가 되고, 리팩토링도 어렵습니다. 그래서 들여쓰거나 해서 어떻게든 가독성을 줄 수밖에 없네요.
덧붙여서 Excel 수식에 있어서의 들여쓰기에, N() 함수를 더해 코멘트같이 쓸 수 있거나 배열 수식을 사용해 코멘트같이 쓰는 방법도 있는 것 같습니다・・・
→ 수식 작성에 유용한 기법
이번에는 값을 꺼내 ~ 들여 쓰기를 추가하는 곳을 시도합니다.
물론 매크로를 사용하여 해결하는 방법도 있네요.
→ Excel에서 중첩된 If 함수를 VBA로 들여쓰고 분석하기 쉽습니다.
파이썬으로 시도
이번에는 Openpyxl을 사용해 보겠습니다.
드디어, 수식의 해석은 Parsing Formula (을)를 사용해 할 수 있는 것 같습니다.
우선 써 있는 것을 시도해 봅시다.
>>> from openpyxl.formula import Tokenizer
>>> tok = Tokenizer("""=IF(A1="これこれ", "xxxx", IF(B1="あれこれ", "yyyy", "zzzz"))""")
>>> print("\n".join("%12s%11s%9s" % (t.value, t.type, t.subtype) for t in tok.items))
IF( FUNC OPEN
A1 OPERAND RANGE
=OPERATOR-INFIX
"これこれ" OPERAND TEXT
, SEP ARG
WHITE-SPACE
"xxxx" OPERAND TEXT
, SEP ARG
WHITE-SPACE
IF( FUNC OPEN
B1 OPERAND RANGE
=OPERATOR-INFIX
"あれこれ" OPERAND TEXT
, SEP ARG
WHITE-SPACE
"yyyy" OPERAND TEXT
, SEP ARG
WHITE-SPACE
"zzzz" OPERAND TEXT
) FUNC CLOSE
) FUNC CLOSE
과연. 선두로부터 각각의 파트가 함수(시작·종료)인지, 변수인지 등등으로 분해해 주는 것 같다.
라고 하는 것은 함수가 개시하면 개행해, 다음의 행에는 들여쓰기를 붙여, 함수가 종료할 때에 들여쓰기를 줄이고 나서 개행해 가면 된다고 하는 것이군요.
이해하기 쉽도록 들여 쓰기를 시각화하고 씁니다.
from openpyxl.formula import Tokenizer
# あとでindent_charはもちろんスペースに直すよ
def parse(formula, indent_char = "_"):
# 最終的に文字列として結合して返す
result = ""
tok = Tokenizer(formula)
# インデント数
n = 0
# 直前で処理したトークン
last = None
for t in tok.items:
if t.type == "FUNC":
if t.subtype == "OPEN":
if last is not None and (last.type == "FUNC" and last.subtype == "OPEN"):
n += 2
result += indent_char * n + t.value
else:
result += t.value
result += "\n"
else:
# function close。インデント数を戻す
n -= 2
result += "\n" + indent_char * n + t.value
else:
# それ以外は単純結合。直前が関数の場合はインデント
if last is not None and (last.type == "FUNC" and last.subtype == "OPEN"):
n += 2
result += indent_char * n + t.value
else:
result += t.value
last = t
return result
s = """=IF(A1="これこれ", "xxxx", IF(B1="あれこれ", "yyyy", "zzzz"))"""
print(parse(s))
IF(
__A1="これこれ", "xxxx", IF(
____B1="あれこれ", "yyyy", "zzzz"
__)
)
그래. 이것으로 좋을 것 같다.
나머지는 Excel의 지정된 셀 범위를 전달합니다.
wb = load_workbook(filename, data_only = False)
sheet_name = "Sheet1"
cell_range = "A2:C2"
for line in wb[sheet_name][cell_range]:
for cell in line:
# formula のみを抽出
if cell.data_type == "f":
f = parse(cell.value)
# cell.coordinateには「A1」などの表現が入る
with open(cell.coordinate + ".txt", mode='w') as fl:
fl.write(f)
이런 식으로 하면 수식이 묻혀 있는 셀만 A2.txt, C2.txt처럼 들여쓰기된 텍스트로 내뿜을 수 있습니다.
Reference
이 문제에 관하여(Excel 수식이 너무 복잡하고 들여 쓰기를 원했을 때 한 일), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tetsunosukeito/items/1df3f9e4e8d843992dfd
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
=IF(A1="これこれ", "xxxx", IF(B1="あれこれ", "yyyy", "zzzz"))
if (A1 === "これこれ") {
cell = "xxxx";
} elseif (B1 === "あれこれ") {
cell = "yyyy";
} else {
cell = "zzzz";
}
물론 매크로를 사용하여 해결하는 방법도 있네요.
→ Excel에서 중첩된 If 함수를 VBA로 들여쓰고 분석하기 쉽습니다.
파이썬으로 시도
이번에는 Openpyxl을 사용해 보겠습니다.
드디어, 수식의 해석은 Parsing Formula (을)를 사용해 할 수 있는 것 같습니다.
우선 써 있는 것을 시도해 봅시다.
>>> from openpyxl.formula import Tokenizer
>>> tok = Tokenizer("""=IF(A1="これこれ", "xxxx", IF(B1="あれこれ", "yyyy", "zzzz"))""")
>>> print("\n".join("%12s%11s%9s" % (t.value, t.type, t.subtype) for t in tok.items))
IF( FUNC OPEN
A1 OPERAND RANGE
=OPERATOR-INFIX
"これこれ" OPERAND TEXT
, SEP ARG
WHITE-SPACE
"xxxx" OPERAND TEXT
, SEP ARG
WHITE-SPACE
IF( FUNC OPEN
B1 OPERAND RANGE
=OPERATOR-INFIX
"あれこれ" OPERAND TEXT
, SEP ARG
WHITE-SPACE
"yyyy" OPERAND TEXT
, SEP ARG
WHITE-SPACE
"zzzz" OPERAND TEXT
) FUNC CLOSE
) FUNC CLOSE
과연. 선두로부터 각각의 파트가 함수(시작·종료)인지, 변수인지 등등으로 분해해 주는 것 같다.
라고 하는 것은 함수가 개시하면 개행해, 다음의 행에는 들여쓰기를 붙여, 함수가 종료할 때에 들여쓰기를 줄이고 나서 개행해 가면 된다고 하는 것이군요.
이해하기 쉽도록 들여 쓰기를 시각화하고 씁니다.
from openpyxl.formula import Tokenizer
# あとでindent_charはもちろんスペースに直すよ
def parse(formula, indent_char = "_"):
# 最終的に文字列として結合して返す
result = ""
tok = Tokenizer(formula)
# インデント数
n = 0
# 直前で処理したトークン
last = None
for t in tok.items:
if t.type == "FUNC":
if t.subtype == "OPEN":
if last is not None and (last.type == "FUNC" and last.subtype == "OPEN"):
n += 2
result += indent_char * n + t.value
else:
result += t.value
result += "\n"
else:
# function close。インデント数を戻す
n -= 2
result += "\n" + indent_char * n + t.value
else:
# それ以外は単純結合。直前が関数の場合はインデント
if last is not None and (last.type == "FUNC" and last.subtype == "OPEN"):
n += 2
result += indent_char * n + t.value
else:
result += t.value
last = t
return result
s = """=IF(A1="これこれ", "xxxx", IF(B1="あれこれ", "yyyy", "zzzz"))"""
print(parse(s))
IF(
__A1="これこれ", "xxxx", IF(
____B1="あれこれ", "yyyy", "zzzz"
__)
)
그래. 이것으로 좋을 것 같다.
나머지는 Excel의 지정된 셀 범위를 전달합니다.
wb = load_workbook(filename, data_only = False)
sheet_name = "Sheet1"
cell_range = "A2:C2"
for line in wb[sheet_name][cell_range]:
for cell in line:
# formula のみを抽出
if cell.data_type == "f":
f = parse(cell.value)
# cell.coordinateには「A1」などの表現が入る
with open(cell.coordinate + ".txt", mode='w') as fl:
fl.write(f)
이런 식으로 하면 수식이 묻혀 있는 셀만 A2.txt, C2.txt처럼 들여쓰기된 텍스트로 내뿜을 수 있습니다.
Reference
이 문제에 관하여(Excel 수식이 너무 복잡하고 들여 쓰기를 원했을 때 한 일), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tetsunosukeito/items/1df3f9e4e8d843992dfd
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
from openpyxl.formula import Tokenizer
# あとでindent_charはもちろんスペースに直すよ
def parse(formula, indent_char = "_"):
# 最終的に文字列として結合して返す
result = ""
tok = Tokenizer(formula)
# インデント数
n = 0
# 直前で処理したトークン
last = None
for t in tok.items:
if t.type == "FUNC":
if t.subtype == "OPEN":
if last is not None and (last.type == "FUNC" and last.subtype == "OPEN"):
n += 2
result += indent_char * n + t.value
else:
result += t.value
result += "\n"
else:
# function close。インデント数を戻す
n -= 2
result += "\n" + indent_char * n + t.value
else:
# それ以外は単純結合。直前が関数の場合はインデント
if last is not None and (last.type == "FUNC" and last.subtype == "OPEN"):
n += 2
result += indent_char * n + t.value
else:
result += t.value
last = t
return result
s = """=IF(A1="これこれ", "xxxx", IF(B1="あれこれ", "yyyy", "zzzz"))"""
print(parse(s))
IF(
__A1="これこれ", "xxxx", IF(
____B1="あれこれ", "yyyy", "zzzz"
__)
)
wb = load_workbook(filename, data_only = False)
sheet_name = "Sheet1"
cell_range = "A2:C2"
for line in wb[sheet_name][cell_range]:
for cell in line:
# formula のみを抽出
if cell.data_type == "f":
f = parse(cell.value)
# cell.coordinateには「A1」などの表現が入る
with open(cell.coordinate + ".txt", mode='w') as fl:
fl.write(f)
이런 식으로 하면 수식이 묻혀 있는 셀만 A2.txt, C2.txt처럼 들여쓰기된 텍스트로 내뿜을 수 있습니다.
Reference
이 문제에 관하여(Excel 수식이 너무 복잡하고 들여 쓰기를 원했을 때 한 일), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/tetsunosukeito/items/1df3f9e4e8d843992dfd텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)