Excel 수식이 너무 복잡하고 들여 쓰기를 원했을 때 한 일
개요
Excel의 수식란에 상당한 길이의 수식이 묻혀 있어, 읽어내기에도 수정하는데도 상당한 고생이 필요하게 되어 버렸기 때문에, 일단 빼내 해 해석을 시도한 이야기.
데이터 추출에는 Openpyxl을 사용했습니다.
이런 상황이었
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.)
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.)