XLSX 생성, 편집 및 분석
| 작업 | 접근 방식 |
|---|---|
| 생성 또는 편집 (수식/서식 포함) | openpyxl — 아래 주의사항 참고 |
| 대량 데이터 입/출력 | pandas (read_excel, to_excel) |
| 시트 빠른 확인 | markitdown file.xlsx — 시트당 ## SheetName; .xlsm도 읽음. 셀 좌표는 제공되지 않으므로 이를 기반으로 편집 계획을 세우지 마세요 |
| 모델 읽기 (수식 및 값) | load_workbook 두 번 — 주의사항 참고 |
openpyxl,pandas,markitdown은 사전 설치되어 있습니다. 먼저pip install을 실행하지 말고 스크립트를 작성하여 직접 import 하세요. import가 실패하거나markitdown명령어가 없는 경우에만pip install로 누락된 패키지를 설치하세요.
아래 스크립트 경로는 이 스킬의 디렉터리를 기준으로 합니다.
모든 출력에 대한 요구 사항
- 전문적인 글꼴(Arial, Times New Roman)을 전체에 사용하세요. 사용자가 다른 지시를 하지 않는 한.
- 수식 오류 제로.
recalc.py가errors_found를 보고하는 상태에서 절대 배포하지 마세요. 오류가 이전부터 존재했다고 생각되면 증명하세요:data_only=True로 원본을 로드하고 해당 셀을 확인하세요. 사용자가 도입한 오류는 기존 오류와 똑같이 보입니다. - 수식을 사용하고, 하드코딩된 결과를 사용하지 마세요.
sheet['B10'] = '=SUM(B2:B9)'와 같이 작성하고, Python으로 계산된 합계를 사용하지 마세요. 시트는 입력이 변경될 때 다시 계산되어야 합니다. - 사용자의 명세를 문자 그대로 따르세요. 정확한 탭 이름, 정확한 열 헤더, 사용자가 지정한 수식을 그대로 사용하세요. 다른 것을 계산하는 재설계는 아무리 우아해도 실패입니다.
- 모든 가정과 하드코딩된 숫자를 문서화하세요. 독자가 볼 수 있는 위치(셀 주석, 테이블 끝의 인접 셀)에 기록하세요. 실제 출처가 있으면 인용하세요(
출처: 회사 10-K, FY2024, 45페이지, 수익 주석, [SEC EDGAR URL]); 숫자가 사용자로부터 온 경우 명확히 명시하세요. - 사용자가 작성할 새 통합 문서에는 편집할 셀을 지정하는 짧은 범례와 예상 형식을 보여주는 현실적인 예제 행 하나가 포함되어야 합니다. 편집을 요청받은 파일에는 이러한 행을 추가하지 마세요.
- 기존 파일 편집: 해당 파일의 규칙을 정확히 따르세요. 이 규칙은 여기의 모든 지침보다 우선합니다. 먼저 지정된 입력 셀(구분되는 글꼴 색상, 채우기 또는 음영으로 표시됨)을 찾아 해당 셀에만 쓰고, 기존 수식은 모두 그대로 두세요.
재계산 (파일에 수식이 포함된 경우 필수)
openpyxl은 수식을 문자열로 작성하지만 캐시된 값이 없습니다. 재계산하기 전까지 모든 수식 셀은 캐시된 값을 읽는 pandas, load_workbook(data_only=True) 및 대부분의 미리보기 도구에 None으로 반환됩니다.
python scripts/recalc.py output.xlsx [시간제한_초] # 기본 30
LibreOffice가 모든 수식을 계산하고, 파일은 제자리에서 다시 작성되며 JSON이 반환됩니다: status (success | errors_found), total_formulas, total_errors, 각 오류 유형별 최대 100개 셀을 명명하는 error_summary (locations_truncated는 보류된 셀 수를 나타냄 — 목록 길이가 아닌 total_errors를 신뢰하세요). 오류가 명명된 셀을 수정하고 다시 실행하세요. status 대신 error 키가 있는 JSON은 재계산되지 않았음을 의미하며, 이 경우에만 0이 아닌 종료 코드를 반환합니다. errors_found는 0을 반환하므로 깨끗한 종료를 깨끗한 통합 문서로 간주하지 마세요.
초록색 재계산은 수식이 평가된다는 것을 증명할 뿐, 올바르다는 것을 증명하지 않습니다. 범위가 하나 벗어나거나 잘못된 행을 참조하면 깨끗하고 오류 없는 파일이지만 잘못된 숫자가 생성됩니다. 먼저 2~3개의 수식을 작성하고 예상한 값을 가져오는지 확인한 후 전체 그리드를 구성하세요.
다른 파일에 연결된 통합 문서는 openpyxl로 다시 저장한 후 재계산하면 해당 연결이 손실됩니다. 이러한 수식은 ='[1]Returns Analysis'!$B$2로 읽힙니다. 여기서 [1]은 통합 문서의 외부 참조 목록 인덱스로, 시트가 아닌 디스크의 별도 파일을 가리킵니다. 그 파일은 여기에 거의 존재하지 않으므로 셀의 캐시된 값이 유일한 데이터 소스입니다. openpyxl은 저장 시 해당 값을 제거하고, LibreOffice는 참조를 실제로 확인해야 하며 실패하여 #NAME?을 쓰고 모든 링크를 삭제합니다. recalc.py는 이 상태에서 실행을 거부합니다. 저장하기 전에 원본에서 해당 셀의 값을 복사해 두세요 (--force는 덮어쓰며 손실을 수락합니다).
검증에 성공할 수식을 선택하는 방법
LibreOffice는 Excel보다 적은 함수를 지원하며, 평가할 수 없는 함수는 배달하는 파일에 그대로 #NAME?으로 저장됩니다.
- Excel 2007 시대 함수를 선호하세요 — 접두사가 필요 없는
SUMIFS,INDEX,MATCH,IFERROR,SUMPRODUCT. - 2007 이후의 6가지 함수는
_xlfn.접두사와 함께만 작동합니다. openpyxl이 수식을 XML에 그대로 쓰고 Excel은 2007 이후 이름을 접두사와 함께 저장하기 때문입니다(UI는 접두사를 숨깁니다):_xlfn.TEXTJOIN,_xlfn.CONCAT,_xlfn.IFS,_xlfn.SWITCH,_xlfn.MAXIFS,_xlfn.MINIFS. 접두사 없이 쓰면 각각#NAME?이 발생합니다. XLOOKUP,XMATCH,SORT,FILTER,UNIQUE,SEQUENCE는 절대 사용하지 마세요. 런타임의 LibreOffice는 어떤 접두사로도 이를 평가할 수 없습니다. 최신 빌드에서는 평가할 수 있지만, 이는 분산 배열 함수이며 openpyxl로 작성된 파일에는 분산 메타데이터가 없으므로 범위의 왼쪽 위 셀만 값을 얻고recalc.py는 잘린 결과에 대해total_errors: 0을 보고합니다. 조회에는INDEX/MATCH를 사용하고, Python에서 정렬, 필터링, 중복 제거를 수행한 후 셀에 쓰세요.- LibreOffice가 구문 분석할 수 없는 수식은 소문자로 다시 작성됩니다. 이는
#NAME?옆에서 빠르게 확인할 수 있는 신호입니다.
openpyxl 주의사항
- 모델을 읽는 데는 두 번 로드가 필요합니다.
data_only=True는 수식이 없는 캐시된 값을 제공하고, 기본값은 값이 없는 수식 문자열을 제공합니다. 한 번의 패스로 둘 다 얻을 수 없습니다. data_only=True는 저장하면 파괴적입니다. 해당 통합 문서에는 수식이 더 이상 없으므로 저장하면 모든 수식이 리터럴 값으로 영구히 대체됩니다.- openpyxl이 방금 쓴 파일에 대해
data_only=True를 실행하면 모든 곳에서None이 반환됩니다 — 먼저recalc.py를 실행하세요. (결과가""인 수식도None으로 읽힙니다.) - 병합된 셀: 왼쪽 위 앵커에만 쓰세요. 범위의 다른 모든 셀은
.value가 읽기 전용인MergedCell입니다. .xlsm파일은load_workbook에keep_vba=True를 전달하지 않으면 매크로가 손실됩니다.- 공백이 포함된 시트 이름은 교차 시트 참조에서 따옴표로 묶어야 합니다:
='Assumptions Inputs'!$B$5. 따옴표가 없으면#VALUE!로 평가됩니다.
재무 모델
사용자가 다른 지시를 하거나 기존 파일이 다른 방식을 사용하지 않는 한 다음을 따르세요.
색상: 하드코딩된 입력 및 시나리오 레버는 파란색 텍스트(0,0,255) · 수식은 검은색 · 다른 시트 링크는 녹색(0,128,0) · 다른 파일 링크는 빨간색(255,0,0) · 주요 가정 및 사용자가 채워야 할 셀은 노란색 채우기(255,255,0).
숫자: 통화 $#,##0, 단위는 헤더에 명시(Revenue ($mm)) · 0은 -로 표시(백분율 포함, $#,##0;($#,##0);-) · 음수는 괄호 안에 · 백분율 0.0%, 분수로 저장 (0.15는 15.0%로 표시; 15를 저장하면 1500.0%로 표시) · 평가 배수 0.0x · 연도는 텍스트로 ("2024", 절대 2,024 아님).
구조: 모든 가정은 자체 레이블이 지정된 셀에 배치하고, 해당 가정을 사용하는 수식에서 참조(=B5*(1+$B$6), 절대 =B5*1.05 아님) · 모든 예측 기간에 걸쳐 수식은 일관되어야 함(행 중간에 단독으로 편집된 셀이 가장 흔한 무음 오류) · 0이 될 수 있는 분모는 보호하세요.
종속성
openpyxl, pandas, markitdown (pip, 사전 설치됨 — import 실패하거나 명령어가 없는 경우에만 설치) · LibreOffice (soffice, 샌드박스 환경에 맞게 scripts/office/soffice.py를 통해 자동 구성됨)