Excel2md
.xlsx 엑셀 파일 읽기/변환 전문 스킬. JSON/마크다운 변환, 임베디드 이미지 자동 추출, 시트별 파일 생성. ".xlsx", "엑셀", "excel", "스프레드시트" 요청에 실행.From its SKILL.md
npx -y skills add Dannykkh/skill-olympus --skill excel2mdAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
5.6 KB, ~2.1k tokens by cl100k_base, as published. Nobody here has run it
Excel to JSON/Markdown
엑셀 파일을 구조화된 JSON 또는 마크다운으로 변환합니다. 임베디드 이미지도 자동 추출하여 해당 행에 매핑합니다.
Quick Start
/excel2md report.xlsx # JSON (기본)
/excel2md report.xlsx --format md # 마크다운
/excel2md data.xlsx --sheet "매출현황" # 특정 시트
/excel2md data.xlsx --output ./docs # 출력 디렉토리
/excel2md data.xlsx --no-images # 이미지 제외
Step 0: 구조 분석 (First Actions)
변환 전 엑셀 파일의 구조를 먼저 파악합니다.
import openpyxl
wb = openpyxl.load_workbook('data.xlsx', data_only=True)
for sheet_name in wb.sheetnames:
ws = wb[sheet_name]
print(f"\n=== {sheet_name} ===")
print(f" 크기: {ws.max_row}행 × {ws.max_column}열")
print(f" 병합 셀: {len(ws.merged_cells.ranges)}개")
# 헤더 자동 감지 (문자열 비율 기반)
for row_idx in range(1, min(6, ws.max_row + 1)):
row = [ws.cell(row_idx, c).value for c in range(1, ws.max_column + 1)]
str_ratio = sum(1 for v in row if isinstance(v, str)) / max(len(row), 1)
marker = " ← 헤더 후보" if str_ratio > 0.7 else ""
print(f" 행 {row_idx}: {row[:5]}...{marker}")
구조 분석 출력 예시
=== Sheet1 ===
크기: 150행 × 8열
병합 셀: 3개
행 1: ['번호', '이름', '부서', '직급', '입사일']... ← 헤더 후보
행 2: [1, '김철수', '개발팀', '대리', datetime(2020,3,1)]...
=== 매출현황 ===
크기: 50행 × 12열
병합 셀: 12개 (그룹 헤더)
행 1: ['', '', '2025년', None, None, '2026년']... ← 그룹 헤더
행 2: ['지역', '담당자', '1Q', '2Q', '3Q', '1Q']... ← 실제 헤더
Step 1: 데이터 타입 감지 + 변환
타입별 처리 규칙
| 엑셀 타입 | JSON 출력 | MD 출력 |
|---|---|---|
| 문자열 | "text" | text (파이프·줄바꿈 이스케이프) |
| 정수 | 123 | 천 단위 콤마 1,234 |
| 소수 | 3.14 | 1,234.56 (정수값이면 콤마 정수) |
| 날짜/일시 | "2020-03-01 00:00:00" (datetime을 str()로 — ISO 변환 안 함) | 동일 문자열 |
| 불리언 | true/false | Yes/No |
| 수식 | 계산 결과값 (data_only=True) | 계산 결과값 |
| 빈 셀 | null | (공백) |
JSON 셀 직렬화는
None/bool/int/float만 원형 유지하고 나머지(날짜·하이퍼링크 등)는 모두str()로 변환합니다. 하이퍼링크/통화/퍼센트를 구조화 객체({value, format})로 분리하는 기능은 없습니다 — 셀의 텍스트/숫자 값만 출력됩니다.
병합 셀·멀티 헤더(그룹 헤더)는 자동 처리하지 않습니다. 현재 CLI는
iter_rows(values_only=True)로 첫 행을 단일 헤더로 사용합니다 — 병합 값 전파나 그룹 헤더 평탄화는 미지원입니다. 그런 시트는 위 Step 0로 구조를 먼저 확인하고 수동 보정하세요.
Step 2: 이미지 추출
xlsx는 ZIP 아카이브이며, 내부 XML을 파싱하여 이미지를 추출합니다:
xl/worksheets/_rels/sheet*.xml.rels→ 시트→드로잉 매핑xl/drawings/_rels/drawing*.xml.rels→ rId→미디어 파일 매핑xl/drawings/drawing*.xml→ 앵커에서 row/col + rId 추출xl/media/*→ 이미지 바이너리 추출
Fallback: 드로잉 매핑 실패 시 media 폴더 전체 추출 (위치 없음 → "기타" 섹션 배치).
Step 3: 출력
JSON 구조
{
"source": "report.xlsx",
"sheet": "Sheet1",
"row_count": 150,
"headers": ["번호", "이름", "부서", "직급", "입사일"],
"rows": [
{"번호": 1, "이름": "김철수", "부서": "개발팀", "직급": "대리", "입사일": "2020-03-01 00:00:00"}
],
"images": [
{"filename": "image1.png", "row": 1, "col": 0}
]
}
Markdown 구조
# Sheet1
> Source: report.xlsx | Sheet: Sheet1 | Rows: 150 | Images: 5
| 번호 | 이름 | 부서 | 직급 | 입사일 |
|------|------|------|------|--------|
| 1 | 김철수 | 개발팀 | 대리 | 2020-03-01 00:00:00 |
## 첨부 이미지
### 행 1

특수 케이스 처리
| 케이스 | 처리 |
|---|---|
파이프(|) 포함 셀 | MD에서만 이스케이프 |
| 시트명 특수문자 | 안전한 파일명으로 변환 (/ → _) |
| 이미지 없는 xlsx | 텍스트만 변환 |
| twoCellAnchor + oneCellAnchor | 두 앵커 타입 모두 지원 |
| 빈 시트 | _(빈 시트)_ 표기 |
요구사항
pip install openpyxl
옵션
| 옵션 | 단축 | 설명 |
|---|---|---|
--format | json(기본) 또는 md | |
--sheet | -s | 특정 시트만 |
--output | -o | 출력 디렉토리 |
--overwrite | -f | 덮어쓰기 |
--no-images | 이미지 제외 |
Helper Scripts
| 스크립트 | 용도 |
|---|---|
excel2md.py | 메인 CLI |
scripts/excel_parser.py | openpyxl 파싱 헬퍼 |
Related Files
| 파일 | 역할 |
|---|---|
skills/pdf/SKILL.md | PDF 변환 |
skills/docx/SKILL.md | Word 문서 변환 |
skills/web-to-markdown/SKILL.md | 웹페이지 변환 |
What ships with it: 2 files
29.9 KB alongside SKILL.md, 2 of them executable
scripts/
- excel_parser.pyruns13.2 KB
- excel2md.pyruns16.7 KB