@simplysm/sd-claude 14.0.88 → 14.0.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/claude/references/sd-simplysm14/README.md +16 -17
  2. package/claude/references/sd-simplysm14/apis/angular/README.md +39 -43
  3. package/claude/references/sd-simplysm14/apis/angular/controls.md +174 -80
  4. package/claude/references/sd-simplysm14/apis/angular/crud.md +41 -50
  5. package/claude/references/sd-simplysm14/apis/angular/directives.md +60 -26
  6. package/claude/references/sd-simplysm14/apis/angular/features.md +109 -37
  7. package/claude/references/sd-simplysm14/apis/angular/infra.md +61 -44
  8. package/claude/references/sd-simplysm14/apis/angular/layout.md +39 -31
  9. package/claude/references/sd-simplysm14/apis/angular/overlay.md +73 -85
  10. package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +54 -39
  11. package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +55 -30
  12. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +71 -67
  13. package/claude/references/sd-simplysm14/apis/angular/sheet.md +82 -72
  14. package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +35 -36
  15. package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +71 -43
  16. package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +38 -30
  17. package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +45 -50
  18. package/claude/references/sd-simplysm14/apis/core-browser/README.md +42 -55
  19. package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +62 -0
  20. package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +39 -38
  21. package/claude/references/sd-simplysm14/apis/core-common/README.md +95 -103
  22. package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +59 -54
  23. package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +86 -0
  24. package/claude/references/sd-simplysm14/apis/core-common/datetime.md +57 -66
  25. package/claude/references/sd-simplysm14/apis/core-common/errors.md +86 -0
  26. package/claude/references/sd-simplysm14/apis/core-common/obj.md +60 -42
  27. package/claude/references/sd-simplysm14/apis/core-common/serialization.md +55 -0
  28. package/claude/references/sd-simplysm14/apis/core-node/README.md +10 -8
  29. package/claude/references/sd-simplysm14/apis/core-node/consola.md +29 -32
  30. package/claude/references/sd-simplysm14/apis/core-node/cpx.md +34 -22
  31. package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +29 -25
  32. package/claude/references/sd-simplysm14/apis/core-node/fsx.md +40 -53
  33. package/claude/references/sd-simplysm14/apis/core-node/pathx.md +22 -29
  34. package/claude/references/sd-simplysm14/apis/core-node/worker.md +31 -31
  35. package/claude/references/sd-simplysm14/apis/excel/README.md +26 -26
  36. package/claude/references/sd-simplysm14/apis/excel/cell.md +37 -29
  37. package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +29 -15
  38. package/claude/references/sd-simplysm14/apis/excel/style.md +33 -27
  39. package/claude/references/sd-simplysm14/apis/excel/utils.md +29 -19
  40. package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +78 -55
  41. package/claude/references/sd-simplysm14/apis/excel/wrapper.md +42 -45
  42. package/claude/references/sd-simplysm14/apis/lint/README.md +27 -21
  43. package/claude/references/sd-simplysm14/apis/lint/rules.md +89 -49
  44. package/claude/references/sd-simplysm14/apis/orm-common/README.md +6 -62
  45. package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +149 -67
  46. package/claude/references/sd-simplysm14/apis/orm-common/expr.md +111 -99
  47. package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +115 -72
  48. package/claude/references/sd-simplysm14/apis/orm-common/schema.md +134 -92
  49. package/claude/references/sd-simplysm14/apis/orm-common/types.md +67 -52
  50. package/claude/references/sd-simplysm14/apis/orm-node/README.md +63 -26
  51. package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +51 -40
  52. package/claude/references/sd-simplysm14/apis/sd-cli/README.md +10 -12
  53. package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +92 -45
  54. package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +226 -108
  55. package/claude/references/sd-simplysm14/apis/service-client/README.md +90 -88
  56. package/claude/references/sd-simplysm14/apis/service-client/orm.md +37 -29
  57. package/claude/references/sd-simplysm14/apis/service-client/transport.md +45 -20
  58. package/claude/references/sd-simplysm14/apis/service-common/README.md +89 -40
  59. package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +126 -34
  60. package/claude/references/sd-simplysm14/apis/service-common/protocol.md +109 -54
  61. package/claude/references/sd-simplysm14/apis/service-server/README.md +70 -66
  62. package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +47 -47
  63. package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +71 -34
  64. package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +31 -32
  65. package/claude/references/sd-simplysm14/apis/storage/README.md +34 -28
  66. package/claude/references/sd-simplysm14/manuals/client-app-structure.md +142 -140
  67. package/claude/references/sd-simplysm14/manuals/client-orm.md +1 -1
  68. package/claude/references/sd-simplysm14/manuals/client-service.md +19 -7
  69. package/claude/references/sd-simplysm14/manuals/client-shared-data.md +2 -2
  70. package/claude/references/sd-simplysm14/manuals/client-system-log.md +11 -3
  71. package/claude/references/sd-simplysm14/manuals/data-log.md +0 -1
  72. package/claude/references/sd-simplysm14/manuals/orm.md +16 -0
  73. package/claude/rules/sd-design-rules.md +10 -0
  74. package/claude/skills/sd-docs/SKILL.md +58 -46
  75. package/claude/skills/sd-docs/references/{doc-rules.md → subagent-prompt.md} +103 -103
  76. package/claude/skills/sd-impl/SKILL.md +1 -1
  77. package/claude/skills/sd-spec/SKILL.md +858 -858
  78. package/claude/skills/sd-spec/references/example-spec.md +26 -36
  79. package/package.json +1 -1
  80. package/claude/references/sd-simplysm14/apis/core-common/json-transfer.md +0 -47
  81. package/claude/references/sd-simplysm14/apis/orm-common/query-builder.md +0 -29
  82. package/claude/skills/sd-demo/evals/fixtures/inventory-list/.specs/inventory/spec.md +0 -99
  83. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/package.json +0 -12
  84. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/index.ts +0 -3
  85. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inbound/inbound.list.ts +0 -150
  86. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inventory/inventory-master.list.ts +0 -143
  87. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/outbound/outbound.list.ts +0 -150
  88. package/claude/skills/sd-demo/evals/fixtures/inventory-list/pnpm-workspace.yaml +0 -2
  89. package/claude/skills/sd-demo/evals/fixtures/inventory-list/sd.config.ts +0 -12
  90. package/claude/skills/sd-demo/evals/golden.jsonl +0 -1
  91. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/package.json +0 -8
  92. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/src/.gitkeep +0 -0
  93. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tests/.gitkeep +0 -0
  94. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tsconfig.json +0 -10
  95. package/claude/skills/sd-dev/evals/golden.jsonl +0 -1
  96. package/claude/skills/sd-docs/evals/fixtures/new-write/.claude/references/sd-simplysm14/README.md +0 -7
  97. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/package.json +0 -5
  98. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/src/index.ts +0 -3
  99. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/package.json +0 -6
  100. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/src/index.ts +0 -1
  101. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/package.json +0 -5
  102. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/src/index.ts +0 -8
  103. package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/README.md +0 -7
  104. package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/apis/foo/README.md +0 -3
  105. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/package.json +0 -5
  106. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/src/index.ts +0 -3
  107. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/package.json +0 -6
  108. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/src/index.ts +0 -1
  109. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/package.json +0 -5
  110. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/src/index.ts +0 -8
  111. package/claude/skills/sd-docs/evals/golden.jsonl +0 -2
  112. package/claude/skills/sd-impl/evals/fixtures/case-a-new-screen/.specs/260513120000_warehouse/spec.md +0 -101
  113. package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/.specs/260513120000_warehouse/spec.md +0 -101
  114. package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/packages/app/src/screens/box-register/box-register.view.ts +0 -46
  115. package/claude/skills/sd-impl/evals/fixtures/case-c-new-cross/.specs/260513120000_warehouse/spec.md +0 -89
  116. package/claude/skills/sd-impl/evals/fixtures/case-d-spec-modify/.specs/260513120000_warehouse/spec.md +0 -101
  117. package/claude/skills/sd-impl/evals/golden.jsonl +0 -4
  118. package/claude/skills/sd-manual/evals/fixtures/new-manual/src/notification.ts +0 -25
  119. package/claude/skills/sd-manual/evals/fixtures/update-manual/.claude/references/sd-simplysm14/manuals/notification.md +0 -14
  120. package/claude/skills/sd-manual/evals/fixtures/update-manual/src/notification.ts +0 -37
  121. package/claude/skills/sd-manual/evals/golden.jsonl +0 -2
  122. package/claude/skills/sd-review/evals/fixtures/code-review/src/foo.ts +0 -7
  123. package/claude/skills/sd-review/evals/fixtures/doc-review/docs/foo.md +0 -4
  124. package/claude/skills/sd-review/evals/golden.jsonl +0 -2
  125. package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +0 -14
  126. package/claude/skills/sd-skill/evals/fixtures/new-skill/.gitkeep +0 -0
  127. package/claude/skills/sd-skill/evals/golden.jsonl +0 -2
  128. package/claude/skills/sd-spec/evals/fixtures/case-a-split//355/232/214/354/235/230/353/241/235.md +0 -20
  129. package/claude/skills/sd-spec/evals/fixtures/case-b-detail/.specs/260513120000_warehouse/spec.md +0 -95
  130. package/claude/skills/sd-spec/evals/golden.jsonl +0 -2
  131. package/claude/skills/sd-unpack/evals/fixtures/eml-with-text-attachment/meeting.eml +0 -21
  132. package/claude/skills/sd-unpack/evals/fixtures/simple-eml/meeting.eml +0 -10
  133. package/claude/skills/sd-unpack/evals/golden.jsonl +0 -2
  134. package/claude/skills/sd-use/evals/fixtures/empty/.gitkeep +0 -0
  135. package/claude/skills/sd-use/evals/golden.jsonl +0 -6
@@ -1,54 +1,62 @@
1
1
  # @simplysm/excel — ExcelCell / ExcelRow / ExcelCol
2
2
 
3
- 개별 셀의 값·수식·병합·스타일을 읽고 쓰거나, 행/열 단위로 셀을 순회할 때 함께 읽는 묶음. 모든 I/O `async` 인 이유는 셀 타입별로 필요한 XML 파트(SharedStrings/Styles)만 lazy-load 하기 때문이다. 인스턴스는 `ws.cell(r,c)` / `ws.row(r)` / `ws.col(c)` 로 얻으며 좌표는 모두 0 기반.
3
+ 개별 셀의 값·수식·병합·스타일을 읽고 쓰거나, 행/열 단위로 셀을 순회하고 열 너비를 줄 때 함께 읽는 묶음. 셀 객체는 `ws.cell(r,c)` / `ws.row(r)` / `ws.col(c)` 로 얻으며(모두 0 기반, 동기 반환·인스턴스 캐시), 실제 I/O 는 셀의 `async` 메서드에서 일어난다.
4
4
 
5
5
  ## ExcelCell
6
6
 
7
- ```typescript
8
- readonly addr: ExcelAddressPoint // { r, c } 0 기반
9
- ```
7
+ `ws.cell(r, c)` 또는 `row.cell(c)` / `col.cell(r)` 로 얻는다.
8
+
9
+ - `readonly addr: ExcelAddressPoint` — 이 셀의 0 기반 좌표 `{ r, c }`. 병합·복사 인자로 재사용.
10
10
 
11
- ### 값/수식
11
+ 값/수식:
12
12
 
13
- - `setValue(val: ExcelValueType): Promise<void>` — 셀 설정. `val` 타입별 분기: string → SharedString 으로 등록, boolean → `"1"/"0"`, number숫자 셀, `DateOnly`/`DateTime`/`Time` Excel 날짜 시리얼 + 해당 numFmt 스타일 자동 적용, `undefined`/`null` 삭제. 타입은 throw.
14
- - `getValue(): Promise<ExcelValueType>` — 반환. 셀이면 `undefined`. 타입·numFmt 보고 string/boolean/number/`DateOnly`/`DateTime`/`Time` 복원. 타입이 `"e"`(에러)면 throw.
15
- - `setFormula(val: string | undefined): Promise<void>` — 수식 설정. `undefined` 면 삭제. 설정 셀 타입은 `str` 로.
16
- - `getFormula(): Promise<string | undefined>` — 셀 수식 반환(없으면 `undefined`).
13
+ - `getValue(): Promise<ExcelValueType>` — 셀 값을 타입 추론해 반환. SharedString→string, `b`→boolean, 숫자형 numFmtnumber, 날짜/시간 numFmt→`DateOnly`/`DateTime`/`Time`, 셀→`undefined`. 타입이 `e`(에러)이거나 시리얼 파싱 실패면 throw. 날짜 판별은스타일의 numFmtCode/numFmtId 본다.
14
+ - `setValue(val: ExcelValueType): Promise<void>` — 값 쓰기. `string`→SharedString 등록 `s` 타입, `boolean`→`b` 타입(`"1"`/`"0"`), `number`→숫자, `DateOnly`/`DateTime`/`Time`→시리얼 숫자 + 해당 날짜 numFmt 자동 부여, `undefined`/`null`→셀 삭제. 그 외 타입은 throw. 날짜형 화면이면 문자열 변환 없이 날짜 객체를 그대로 넘겨 자동 서식을 받는 게 단순.
15
+ - `getFormula(): Promise<string | undefined>` — 셀 수식 문자열 반환(없으면 `undefined`).
16
+ - `setFormula(val: string | undefined): Promise<void>` — 수식 설정. 타입을 `str` 로 두고 캐시 값(v)은 비운다. `undefined` 면 셀 삭제. 수식 문자열은 `=` 없이 본문만(예: `"SUM(A1:A3)"`).
17
17
 
18
- ### 병합
18
+ 병합:
19
19
 
20
- - `merge(r, c): Promise<void>` — 현재 셀을 시작점으로 끝 좌표 `(r, c)`(0 기반)까지 병합. 예: A1 에서 `merge(2, 2)` → A1:C3.
20
+ - `merge(r: number, c: number): Promise<void>` — 현재 셀(좌상단)부터 끝 좌표 `(r, c)`(0 기반, inclusive)까지 병합. 예: `ws.cell(0,0).merge(2,2)` → A1:C3(3×3) 병합.
21
21
 
22
- ### 스타일
22
+ 스타일:
23
23
 
24
- - `setStyle(opts: ExcelStyleOptions): Promise<void>` — 배경·테두리·정렬·숫자형식·폰트 적용. 기존 스타일이 있으면 clone 후 병합. 자세히: [style.md](./style.md).
25
- - `getStyleId(): Promise<string | undefined>` — 셀의 스타일 ID(없으면 `undefined`).
26
- - `setStyleId(styleId: string | undefined): Promise<void>` — 스타일 ID 직접 지정/해제. 이미 만들어진 스타일을 재사용할 때.
24
+ - `getStyleId(): Promise<string | undefined>` — 셀의 styles.xml cellXfs 인덱스 ID 반환.
25
+ - `setStyleId(styleId: string | undefined): Promise<void>` — 스타일 ID 직접 지정(다른 셀과 동일 스타일 공유 시). `undefined` 면 스타일 해제.
26
+ - `setStyle(opts: ExcelStyleOptions): Promise<void>` — 배경·테두리·정렬·숫자형식·폰트 적용. 기존 스타일이 있으면 clone 지정 필드만 병합한다(부분 갱신). 옵션 풀이는 [style.md](./style.md).
27
27
 
28
- ### 사용
28
+ 읽기/쓰기 예:
29
29
 
30
30
  ```typescript
31
- await ws.cell(0, 0).setValue("이름");
32
- await ws.cell(1, 0).setValue(new DateOnly(2026, 6, 1)); // 날짜 numFmt 자동
33
- await ws.cell(0, 0).merge(0, 2); // A1:C1 병합
34
- const v = await ws.cell(1, 0).getValue(); // DateOnly 인스턴스
31
+ await ws.cell(0, 0).setValue("코드");
32
+ await ws.cell(1, 0).setValue(new DateOnly(2026, 6, 3)); // 날짜 numFmt 자동
33
+ await ws.cell(1, 1).setFormula("SUM(C2:C10)");
34
+ const v = await ws.cell(1, 0).getValue(); // DateOnly 로 복원
35
35
  ```
36
36
 
37
37
  ## ExcelRow
38
38
 
39
- ```typescript
40
- cell(c: number): ExcelCell // 이 행의 c열 셀(0 기반)
41
- getCells(): Promise<ExcelCell[]> // 데이터 범위 폭만큼 셀 배열(인덱스=열)
42
- ```
39
+ `ws.row(r)` 로 얻는다.
43
40
 
44
- - `getCells` 시트 데이터 범위의 시작~끝 열까지 셀을 채우며, 배열 인덱스가 번호와 일치(앞쪽 빈 열은 sparse).
41
+ - `cell(c: number): ExcelCell` 행의 0 기반`c` 반환.
42
+ - `getCells(): Promise<ExcelCell[]>` — 이 행에서 시트 range 의 열 범위에 해당하는 셀들을 배열로 반환(인덱스 = 열 번호, 앞쪽 빈 열은 비어 있음).
45
43
 
46
44
  ## ExcelCol
47
45
 
46
+ `ws.col(c)` 로 얻는다.
47
+
48
+ - `cell(r: number): ExcelCell` — 이 열의 0 기반 행 `r` 셀 반환.
49
+ - `getCells(): Promise<ExcelCell[]>` — 이 열에서 시트 range 의 행 범위에 해당하는 셀들을 배열로 반환(인덱스 = 행 번호).
50
+ - `setWidth(size: number): Promise<void>` — 열 너비 설정(엑셀 문자 너비 단위). 열 1개 단위로 cols 정의를 갱신.
51
+
52
+ 열 너비 예:
53
+
48
54
  ```typescript
49
- cell(r: number): ExcelCell // 이 열의 r행 셀(0 기반)
50
- getCells(): Promise<ExcelCell[]> // 데이터 범위 높이만큼 셀 배열(인덱스=행)
51
- setWidth(size: number): Promise<void> // 열 너비 설정
55
+ await ws.col(0).setWidth(20);
52
56
  ```
53
57
 
54
- - `setWidth` 의 `size` — Excel 열 너비 단위(문자 폭 기준). 컬럼 폭을 데이터에 맞게 넓힐 때.
58
+ ## 주의사항
59
+
60
+ - 행/열/셀 인덱스는 모두 0 기반(엑셀 화면의 1행/A열 = 인덱스 0).
61
+ - `getCells()` 가 반환하는 배열은 range 시작 인덱스부터 채워지므로 앞쪽 인덱스가 비어 있을 수 있다. `for..of` 보다 `range` 경계로 직접 순회하는 편이 안전.
62
+ - `setStyle` 은 누적 병합(기존 스타일 위에 지정 필드만 덮어씀)이고, `setStyleId(undefined)` 는 스타일 전체 해제다. 둘을 혼동하지 말 것.
@@ -1,25 +1,33 @@
1
1
  # @simplysm/excel — 조건부 서식
2
2
 
3
- 셀/범위에 값 비교·텍스트 매칭·수식 기반의 native CF(Excel 조건부 서식) 규칙을 추가할 때 함께 읽는 묶음. `ws.addConditionalFormat` `ExcelConditionalRule[]` 넘기며, 규칙은 `ExcelConditionalRuleStyle` 강조 스타일을 가진다.
3
+ 셀/범위에 값 비교·텍스트 매칭·수식 기반의 엑셀 native 조건부 서식(CF) 추가할 때 참조. `ws.addConditionalFormat({ ref, rules })` 메서드로 적용하며, 규칙은 `ExcelConditionalRule` 유니온으로 표현한다. 정적 셀 스타일과의 합성은 엑셀 native CF 오버레이에 위임된다(라이브러리가 직접 색을 칠하지 않음).
4
4
 
5
- ## ws.addConditionalFormat
5
+ ## addConditionalFormat
6
6
 
7
7
  ```typescript
8
- addConditionalFormat(opts: { ref: string; rules: ExcelConditionalRule[] }): Promise<void>
8
+ ws.addConditionalFormat(opts: { ref: string; rules: ExcelConditionalRule[] }): Promise<void>
9
9
  ```
10
10
 
11
- - `opts.ref: string` — 단일 셀(`"A1"`) 또는 범위(`"A1:B10"`) Excel 주소. 규칙 수식은 범위의 좌상단 기준으로 생성된다.
12
- - `opts.rules: ExcelConditionalRule[]` — 적용할 규칙 배열. 배열 순서가 priority(앞이 우선)이며, 호출 간에는 시트 전역 카운터로 이어붙는다. 빈 배열이면 no-op.
13
- - 같은 시트에 여러 번 호출하면 호출마다 `<conditionalFormatting>` 블록이 누적된다. 정적 셀 스타일과의 합성은 Excel native CF 오버레이에 위임.
11
+ - `opts.ref: string` — 적용 대상. 단일 셀(`"A1"`) 또는 범위(`"A1:B10"`) 엑셀 주소. text 규칙의 비교 기준 셀은 ref 의 좌상단 셀.
12
+ - `opts.rules: ExcelConditionalRule[]` — 적용 규칙 배열. 배열 순서가 priority(앞이 우선)이며, 같은 시트에 여러 번 호출하면 호출마다 `<conditionalFormatting>` 블록이 누적되고 priority 는 시트 전역 카운터로 이어붙는다. 빈 배열이면 no-op.
14
13
 
15
14
  ## ExcelConditionalRule
16
15
 
17
- 4개 변형의 유니온. 모든 변형이 `style: ExcelConditionalRuleStyle` 를 가진다.
16
+ 비교(단일):
18
17
 
19
- - `{ type: "cellIs"; op: "<" | ">" | "<=" | ">=" | "=" | "<>"; value: number | string; style }` — 단일 비교. `op` = 비교 연산자, `value` = 비교 대상(숫자는 raw formula, 문자열은 따옴표 리터럴 formula 로 emit).
20
- - `{ type: "cellIs"; op: "between" | "notBetween"; value: [number, number] | [string, string]; style }` — 구간 비교. `value` = `[a, b]` 튜플(양 끝 inclusive). `"between"` = 구간 안, `"notBetween"` = 구간 밖.
21
- - `{ type: "text"; op: "contains" | "notContains" | "beginsWith" | "endsWith"; value: string; style }` — 텍스트 매칭. `value` = 비교 문자열. `"contains"`/`"notContains"` = 포함/미포함, `"beginsWith"`/`"endsWith"` = 시작/끝 일치. SEARCH 기반 대소문자 무시 고정.
22
- - `{ type: "expression"; formula: string; style }` — 임의 수식 규칙. `formula` = Excel 수식 문자열(true 면 강조). 프리셋으로 표현 못하는 조건일 때.
18
+ - `{ type: "cellIs"; op: "<" | ">" | "<=" | ">=" | "=" | "<>"; value: number | string; style }` — 셀 값과 `value` 의 단일 비교. `op` = 비교 연산자(`"<>"` = 같지 않음). `value: number` 는 raw formula(`4999`), `value: string` 은 따옴표 리터럴(`"OK"`)로 emit. 수치 임계·특정 텍스트 일치 강조에.
19
+
20
+ 비교(구간):
21
+
22
+ - `{ type: "cellIs"; op: "between" | "notBetween"; value: [number, number] | [string, string]; style }` — 두 값 사이 구간 비교(양 끝 inclusive). `op` = 구간 안/밖. `value` = `[a, b]` 튜플.
23
+
24
+ 텍스트 매칭:
25
+
26
+ - `{ type: "text"; op: "contains" | "notContains" | "beginsWith" | "endsWith"; value: string; style }` — 문자열 매칭. `op` = 포함/미포함/시작/끝. 내부적으로 SEARCH 기반(대소문자 무시) formula 로 변환되며 비교 기준은 ref 좌상단 셀. 부분 문자열·접두/접미 강조에.
27
+
28
+ 수식:
29
+
30
+ - `{ type: "expression"; formula: string; style }` — 임의 엑셀 수식 기반. `formula` 가 TRUE 인 셀에 style 적용. `=` 없이 본문만(예 `"$B2>$C2"`). 다른 셀 참조·복합 조건 등 위 프리셋으로 안 되는 규칙에.
23
31
 
24
32
  ## ExcelConditionalRuleStyle
25
33
 
@@ -31,11 +39,11 @@ interface ExcelConditionalRuleStyle {
31
39
  }
32
40
  ```
33
41
 
34
- - `background?: string` — 강조 배경색. ARGB 8자리(예: `"00FFFF00"`).
35
- - `fontColor?: string` — 강조 글자색. ARGB 8자리.
36
- - `fontWeight?: "bold" | "normal"` — 글자 굵기. `"bold"` = 굵게, `"normal"` = base 가 bold 라도 강제 normal.
42
+ - `background?: string` — 강조 배경색(ARGB 8자리, `"00FFFF00"`). 미지정 시 base 셀 배경 유지.
43
+ - `fontColor?: string` — 강조 글자색(ARGB 8자리). 미지정 시 base 글자색 유지.
44
+ - `fontWeight?: "bold" | "normal"` — 글자 굵기. `"bold"` = 굵게, `"normal"` = base 가 bold 라도 강제 보통. 미지정 시 base 유지.
37
45
 
38
- 미지정 필드는 base 셀 스타일을 그대로 두고, 지정 필드만 OOXML dxf 로 emit 되어 native CF 오버레이로 합성된다.
46
+ 지정한 필드만 OOXML dxf 로 emit 되어 native CF 오버레이로 합성된다(미지정 필드는 base 그대로).
39
47
 
40
48
  ## 사용 예
41
49
 
@@ -49,3 +57,9 @@ await ws.addConditionalFormat({
49
57
  ],
50
58
  });
51
59
  ```
60
+
61
+ ## 주의사항
62
+
63
+ - `rules` 배열 순서 = priority(앞이 우선). 겹치는 조건은 앞 규칙이 이긴다.
64
+ - 여러 번 호출하면 블록이 누적되고 priority 카운터가 시트 전역으로 이어진다 — 한 범위의 규칙은 한 번의 호출에 모아 넣는 편이 우선순위 예측에 유리.
65
+ - `value: string` 과 `expression.formula` 의 따옴표/이스케이프는 라이브러리가 처리하므로 원문 그대로 전달.
@@ -1,6 +1,6 @@
1
1
  # @simplysm/excel — 셀 스타일
2
2
 
3
- 셀(`cell.setStyle`) 또는 워크북 default(`wb.setDefaultStyle`) 배경·테두리·정렬·숫자형식·폰트를 지정할함께 읽는 묶음. API 모두 `ExcelStyleOptions` 를 받으며 `font` `ExcelFont` 공유한다.
3
+ 셀(`cell.setStyle(opts)`)이나 워크북 default(`wb.setDefaultStyle(opts)`) 배경·테두리·정렬·숫자형식·폰트를 참조.호출 모두 동일한 `ExcelStyleOptions` 를 받는다. 미지정 필드는 emit 하지 않아 엑셀 기본값으로 표시되며, `cell.setStyle` 기존 셀 스타일을 clone 후 지정 필드만 병합(부분 갱신)한다.
4
4
 
5
5
  ## ExcelStyleOptions
6
6
 
@@ -16,13 +16,13 @@ interface ExcelStyleOptions {
16
16
  }
17
17
  ```
18
18
 
19
- - `background?: string` — 배경색. ARGB 8자리 16진수(예: `"00FF0000"` = 빨강). 셀 채우기 색이 필요할 때.
20
- - `border?: ExcelBorderPosition[]` — 테두리를 그릴 변 배열. 원소 = `"left" | "right" | "top" | "bottom"`. 4변 모두면 `["left","right","top","bottom"]`.
21
- - `horizontalAlign?: "center" | "left" | "right"` — 가로 정렬.
22
- - `verticalAlign?: "center" | "top" | "bottom"` — 세로 정렬.
23
- - `numberFormat?: "number" | "string" | "DateOnly" | "DateTime" | "Time"` — 숫자형식 프리셋. `"number"` = 일반 수치, `"string"` = 텍스트 형식, 나머지는 날짜/시간 표시 형식. 표준 형식 적용 시 사용.
24
- - `numberFormatCode?: string` — 커스텀 Excel formatCode(예: `"0.000000"`, `"#,##0.00"`, `"0.00%"`). `numberFormat` 과 동시 지정 시 **이 필드가 우선**. 프리셋에 없는 세밀한 형식이 필요할 때.
25
- - `font?: ExcelFont` — 폰트 묶음(아래). 미지정 속성은 워크북 default 폰트로 표시.
19
+ - `background?: string` — 배경 채움색. ARGB 8자리 16진수( 2자리 알파, 예 `"00FF0000"` = 빨강). 셀 강조·헤더색에 사용.
20
+ - `border?: ExcelBorderPosition[]` — 테두리를 그릴 변 배열. 원소는 `"left" | "right" | "top" | "bottom"`. 4변 전부면 4개를 모두 넣음(`["left","right","top","bottom"]`). 빈 배열·미지정은 테두리 없음.
21
+ - `horizontalAlign?: "center" | "left" | "right"` — 가로 정렬. `"center"` = 가운데, `"left"`/`"right"` = 좌/우. 미지정 시 셀 기본(엑셀 자동).
22
+ - `verticalAlign?: "center" | "top" | "bottom"` — 세로 정렬. `"center"` = 가운데, `"top"`/`"bottom"` = 위/아래. 행 높이가 큰 셀에서 의미.
23
+ - `numberFormat?: "number" | "string" | "DateOnly" | "DateTime" | "Time"` — 숫자형식 프리셋. `"number"` = 일반 수치(numFmtId 0), `"string"` = 텍스트(49), `"DateOnly"`(14)/`"DateTime"`(22)/`"Time"`(18) = 날짜/시간 표시. 표준 형식이면 이걸로 충분.
24
+ - `numberFormatCode?: string` — 커스텀 엑셀 formatCode( `"0.000000"`, `"#,##0.00"`, `"0.00%"`). `numberFormat` 과 동시 지정 시 필드가 우선. 천단위·소수 자릿수·퍼센트 세밀한 표시가 필요할 때.
25
+ - `font?: ExcelFont` — 폰트 묶음(아래). 일부 속성만 줘도 되며, 미지정 속성은 워크북 default 폰트로 표시.
26
26
 
27
27
  ## ExcelFont
28
28
 
@@ -39,29 +39,35 @@ interface ExcelFont {
39
39
  ```
40
40
 
41
41
  - `size?: number` — 폰트 크기(pt).
42
- - `family?: string` — 폰트명(예: `"맑은 고딕"`, `"Calibri"`).
43
- - `bold?: boolean` — 굵게. `true` 굵게.
44
- - `italic?: boolean` — 기울임. `true` 이탤릭.
45
- - `underline?: "single" | "double" | "singleAccounting" | "doubleAccounting"` — 밑줄 종류. OOXML `<u val="...">` val 그대로 매핑.
46
- - `color?: string` — 글자색. ARGB 8자리(예: `"00FF0000"`).
47
- - `strike?: boolean` — 취소선. `true` 가운데줄.
42
+ - `family?: string` — 폰트명( `"맑은 고딕"`, `"Calibri"`). 한글 문서면 보통 `"맑은 고딕"`.
43
+ - `bold?: boolean` — 굵게. `true` = 볼드, 미지정/`false` = 보통.
44
+ - `italic?: boolean` — 기울임. `true` = 이탤릭.
45
+ - `underline?: "single" | "double" | "singleAccounting" | "doubleAccounting"` — 밑줄 종류. `<u val="...">` val 그대로 emit. 회계용이면 `*Accounting`.
46
+ - `color?: string` — 글자색. ARGB 8자리( `"00FF0000"`).
47
+ - `strike?: boolean` — 취소선. `true` = 취소선 표시.
48
48
 
49
- 미지정 폰트 속성은 OOXML `<font>` 자식으로 emit 되지 않고 Excel 기본값으로 표시된다.
50
-
51
- ## cell.setStyle vs wb.setDefaultStyle
52
-
53
- - `cell.setStyle(opts)` — 해당 셀에만 스타일 적용. 기존 셀 스타일이 있으면 clone 후 옵션을 병합.
54
- - `wb.setDefaultStyle(opts)` — `xl/styles.xml` 의 `fonts[0]`/`fills[0]`/`borders[0]`(OOXML default 슬롯) 자체를 덮어써, fontId/fillId/borderId 를 명시하지 않은 모든 셀에 전역 적용. `horizontalAlign`/`verticalAlign`/`numberFormat`/`numberFormatCode` 는 0번 슬롯 개념이 없어 `cellXfs[0]` 에 박힌다. 옵션이 없는 자원은 0번 슬롯이 빈 슬롯으로 reset 되며, 미호출 시 원본이 보존된다.
55
-
56
- ### 사용 예
49
+ ## 사용
57
50
 
58
51
  ```typescript
59
- await wb.setDefaultStyle({ font: { family: "맑은 고딕", size: 10 }, horizontalAlign: "center" });
60
-
52
+ // 단위
61
53
  await ws.cell(0, 0).setStyle({
62
- background: "00FFFF00",
54
+ background: "00FFFF00", // 노랑 헤더
63
55
  border: ["left", "right", "top", "bottom"],
64
- font: { bold: true, color: "00FF0000" },
65
- numberFormatCode: "#,##0",
56
+ horizontalAlign: "center",
57
+ verticalAlign: "center",
58
+ font: { family: "맑은 고딕", bold: true },
66
59
  });
60
+
61
+ // 커스텀 숫자 형식
62
+ await ws.cell(1, 2).setStyle({ numberFormatCode: "#,##0.00" });
63
+
64
+ // 워크북 전역 default
65
+ await wb.setDefaultStyle({ font: { family: "맑은 고딕", size: 10 } });
67
66
  ```
67
+
68
+ ## 주의사항
69
+
70
+ - `setDefaultStyle` 은 styles.xml 의 0번 자원 슬롯(font/fill/border)을 덮어쓴다 — fontId/fillId/borderId 를 명시하지 않은 모든 셀이 영향을 받는다. 옵션에 없는 자원은 0번 슬롯이 빈 슬롯으로 reset 되므로, default 로 줄 항목은 한 번에 모아 호출.
71
+ - `numberFormat` 과 `numberFormatCode` 동시 지정 시 `numberFormatCode` 우선.
72
+ - 색상은 모두 ARGB 8자리(알파 포함). RGB 6자리만 주면 의도와 다르게 해석될 수 있다.
73
+ - 날짜/시간 셀은 값으로 `DateOnly`/`DateTime`/`Time` 을 넣으면 numFmt 가 자동 부여되므로 보통 `numberFormat` 을 따로 줄 필요가 없다.
@@ -1,35 +1,45 @@
1
1
  # @simplysm/excel — ExcelUtils
2
2
 
3
- 셀 주소(A1 표기) ↔ 좌표 변환, Excel 날짜 시리얼 ↔ 타임스탬프 변환, 숫자형식 코드/ID/이름 상호 변환이 필요할 때 읽는다. 모든 메서드는 `static` 이라 인스턴스 없이 `ExcelUtils.xxx()` 로 호출.
3
+ 셀 주소(A1 ↔ 좌표) 변환, 엑셀 날짜 시리얼 ↔ JS 타임스탬프 변환, 숫자형식 코드/ID/이름 상호 변환이 필요할 때 쓰는 static 유틸 클래스. 모든 메서드가 정적이므로 인스턴스 생성 없이 `ExcelUtils.xxx(...)` 로 호출. 일반 셀 API 가 내부적으로 쓰지만, 외부에서 주소 문자열 ↔ 좌표를 직접 다룰 때 유용하다.
4
4
 
5
5
  ## 주소 변환
6
6
 
7
- - `stringifyAddr(point: ExcelAddressPoint): string` 0 기반 좌표 `{r,c}` `"A1"`. 로그·범위 ref 조립에 사용.
8
- - `stringifyRowAddr(r: number): string` — 행 인덱스 → 행 문자열(0 → `"1"`).
9
- - `stringifyColAddr(c: number): string` — 열 인덱스 → 열 문자(0 → `"A"`, 26 → `"AA"`). 0~16383 범위 밖이면 throw.
10
- - `parseRowAddr(addr: string): number` — 주소 문자열에서 0 기반 행 인덱스(`"A3"` → 2). 파싱 실패 시 throw.
11
- - `parseColAddr(addr: string): number` — 주소 문자열에서 0 기반 열 인덱스(`"B3"` → 1).
12
- - `parseCellAddr(addr: string): ExcelAddressPoint` — 셀 주소 → 좌표(`"B3"` → `{r:2,c:1}`).
13
- - `parseRangeAddr(rangeAddr: string): ExcelAddressRangePoint` — 범위 주소 → 좌표 범위(`"A1:C3"` → `{s:{r:0,c:0}, e:{r:2,c:2}}`). `:` 없으면 단일 셀을 `s===e` 로.
14
- - `stringifyRangeAddr(point: ExcelAddressRangePoint): string` — 좌표 범위 → 문자열(`"A1:C3"`). `s===e` 면 단일 셀 문자열만 반환.
7
+ 좌표는 `ExcelAddressPoint`(`{ r, c }`, 0 기반), 범위는 `ExcelAddressRangePoint`(`{ s, e }`).
15
8
 
16
- ## 날짜 변환
9
+ - `stringifyAddr(point: ExcelAddressPoint): string` — 좌표를 `"A1"` 형식 문자열로. 예 `{r:0,c:0}` → `"A1"`.
10
+ - `stringifyRowAddr(r: number): string` — 0 기반 행 인덱스를 행 주소 문자열로(예 `0` → `"1"`).
11
+ - `stringifyColAddr(c: number): string` — 0 기반 열 인덱스를 열 문자로(예 `0` → `"A"`, `26` → `"AA"`). 범위 0~16383 밖이면 throw.
12
+ - `parseRowAddr(addr: string): number` — 셀 주소에서 0 기반 행 인덱스 추출(예 `"A3"` → `2`). 행 숫자 파싱 실패 시 throw.
13
+ - `parseColAddr(addr: string): number` — 셀 주소에서 0 기반 열 인덱스 추출(예 `"B3"` → `1`).
14
+ - `parseCellAddr(addr: string): ExcelAddressPoint` — 주소를 좌표로(예 `"B3"` → `{r:2,c:1}`).
15
+ - `parseRangeAddr(rangeAddr: string): ExcelAddressRangePoint` — 범위 주소를 좌표로(예 `"A1:C3"` → `{s:{r:0,c:0}, e:{r:2,c:2}}`). `:` 없는 단일 주소면 `s`=`e`.
16
+ - `stringifyRangeAddr(point: ExcelAddressRangePoint): string` — 범위 좌표를 문자열로. `s`=`e` 면 단일 주소 1개만 반환.
17
17
 
18
- Excel 은 1900-01-01 을 1 로 계산(1899-12-30 이 날짜 0). 변환 시 로컬 타임존을 보정한다.
18
+ ## 날짜 시리얼 변환
19
19
 
20
- - `convertTimeTickToNumber(tick: number): number` JS 타임스탬프(ms) Excel 날짜 시리얼 숫자.
21
- - `convertNumberToTimeTick(value: number): number` — Excel 날짜 시리얼 숫자 → JS 타임스탬프(ms).
20
+ 엑셀은 1900-01-01 1 세는 시리얼 날짜 체계(1899-12-30 = 0) 쓴다. 로컬 타임존 보정을 포함한다.
21
+
22
+ - `convertTimeTickToNumber(tick: number): number` — JS 타임스탬프(ms)를 엑셀 날짜 시리얼 숫자로. 셀에 날짜를 쓸 때 내부적으로 사용.
23
+ - `convertNumberToTimeTick(value: number): number` — 엑셀 날짜 시리얼 숫자를 JS 타임스탬프(ms)로. 셀에서 날짜를 읽을 때 사용.
22
24
 
23
25
  ## 숫자형식 변환
24
26
 
25
- - `convertNumFmtCodeToName(numFmtCode: string): ExcelNumberFormat` formatCode 문자열을 분석해 `"number"`/`"DateOnly"`/`"DateTime"`/`"Time"`/`"string"` 판별. `"General"` `"number"`. 시간 문맥의 `mm`(분)은 날짜 판별에서 제외. 어디에도 해당 안 되면 throw.
26
- - `convertNumFmtIdToName(numFmtId: number): ExcelNumberFormat` — Excel 내장 numFmtId 를 형식명으로. 범위: 0~13·37~40·48 → `"number"`, 14~17·27~31·34~36·50~58 → `"DateOnly"`, 22 → `"DateTime"`, 18~21·32~33·45~47 → `"Time"`, 49 → `"string"`. 범위 밖이면 throw.
27
- - `convertNumFmtNameToId(numFmtName: ExcelNumberFormat): number` — 역방향. `"number"` 0, `"DateOnly"` → 14, `"DateTime"` 22, `"Time"` 18, `"string"` 49.
27
+ `ExcelNumberFormat` = `"number" | "string" | "DateOnly" | "DateTime" | "Time"` 엑셀 formatCode/numFmtId 사이 변환.
28
+
29
+ - `convertNumFmtCodeToName(numFmtCode: string): ExcelNumberFormat` — formatCode 문자열을 형식 이름으로. `"General"`→`"number"`, yy/dd/mm·h/ss 패턴 조합으로 `"DateOnly"`/`"DateTime"`/`"Time"` 판별(시간 문맥의 `mm` 분으로 제외), 숫자 패턴이면 `"number"`. 미해석 코드면 throw.
30
+ - `convertNumFmtIdToName(numFmtId: number): ExcelNumberFormat` — 엑셀 내장 형식 ID 를 이름으로. 0~13·37~40·48→`"number"`, 14~17·27~31·34~36·50~58→`"DateOnly"`, 22→`"DateTime"`, 18~21·32~33·45~47→`"Time"`, 49→`"string"`. 그 외 ID 면 throw.
31
+ - `convertNumFmtNameToId(numFmtName: ExcelNumberFormat): number` — 이름을 내장 형식 ID 로. `"number"`→0, `"DateOnly"`→14, `"DateTime"`→22, `"Time"`→18, `"string"`→49.
28
32
 
29
33
  ## 사용 예
30
34
 
31
35
  ```typescript
32
- const { r, c } = ExcelUtils.parseCellAddr("C5"); // { r: 4, c: 2 }
33
- const ref = ExcelUtils.stringifyRangeAddr({ s: { r: 0, c: 0 }, e: { r: 9, c: 1 } }); // "A1:B10"
34
- const serial = ExcelUtils.convertTimeTickToNumber(Date.now()); // Excel 날짜 숫자
36
+ ExcelUtils.parseRangeAddr("A1:C3"); // { s:{r:0,c:0}, e:{r:2,c:2} }
37
+ ExcelUtils.stringifyAddr({ r: 1, c: 2 }); // "C2"
38
+ ExcelUtils.convertNumFmtIdToName(22); // "DateTime"
35
39
  ```
40
+
41
+ ## 주의사항
42
+
43
+ - 행/열 인덱스는 0 기반(엑셀 표기 A1 = `{r:0,c:0}`). 엑셀 화면 숫자와 1 차이.
44
+ - `stringifyColAddr` 의 유효 열 범위는 0~16383(엑셀 최대 16384열, XFD). 벗어나면 throw.
45
+ - 날짜 변환은 시리얼 1 = 1900-01-01 기준이며 타임존 보정이 들어가므로, 직접 산술하지 말고 이 메서드로 왕복.
@@ -1,6 +1,6 @@
1
1
  # @simplysm/excel — ExcelWorkbook / ExcelWorksheet
2
2
 
3
- .xlsx 파일을 열거나 새로 만들고, 시트를 추가·조회하고, 시트 단위로 데이터 테이블/매트릭스/이미지/뷰를 다루고, 바이트/Blob 로 내보낼 함께 읽는 묶음. 워크북은 내부 ZIP 리소스를 lazy-load 하므로 사용 후 반드시 `close()` 해야 한다.
3
+ .xlsx 파일을 열거나 새로 만들고, 시트를 추가/조회하고, 시트 단위로 데이터 테이블·매트릭스·레코드 쓰기·행 복사/삽입·이미지·뷰를 다룬 뒤 바이트/Blob 로 내보내는 진입 흐름. 워크북은 내부적으로 ZIP 리소스를 잡으므로 사용 후 반드시 `close()` 해야 한다(미해제 시 리소스 누수).
4
4
 
5
5
  ## ExcelWorkbook
6
6
 
@@ -8,28 +8,40 @@
8
8
  new ExcelWorkbook(arg?: Blob | Bytes)
9
9
  ```
10
10
 
11
- - 생성자 `arg` — 기존 .xlsx 데이터(`Blob` 또는 `Uint8Array`). 생략하면 빈 워크북(ContentTypes/rels/workbook 골격)을 새로 만든다. 기존 파일 편집이면 전달, 파일 생성이면 생략.
11
+ - `arg?: Blob | Bytes` — 기존 .xlsx 파일 데이터. 생략하면 빈 워크북을 새로 만든다(ContentTypes/rels/workbook 기본 파트 자동 구성). 파일을 읽을 바이트나 Blob 그대로 전달.
12
12
 
13
13
  메서드:
14
14
 
15
- - `getWorksheetNames(): Promise<string[]>` — 워크북의 모든 시트 이름을 정의 순서로 반환.
16
- - `addWorksheet(name: string): Promise<ExcelWorksheet>` — 새 시트를 만들어 반환. ContentTypes·workbook rels 함께 갱신. `name` = 추가할 시트 이름.
17
- - `getWorksheet(nameOrIndex: string | number): Promise<ExcelWorksheet>` — 이름(string) 또는 0 기반 인덱스(number)로 시트 조회. 같은 시트는 캐시돼 동일 인스턴스 반환. 없으면 throw.
18
- - `setDefaultStyle(opts: ExcelStyleOptions): Promise<void>` — 워크북 전역 default 셀 스타일. fontId/fillId/borderId 를 명시하지 않은 모든 셀에 적용. 자세히: [style.md](./style.md).
19
- - `toBytes(): Promise<Bytes>` — 워크북을 ZIP 직렬화해 바이트로 반환.
20
- - `toBlob(): Promise<Blob>` — `toBytes()` 결과를 xlsx MIME 의 `Blob` 으로 래핑. 브라우저 다운로드용.
21
- - `close(): Promise<void>` — ZIP 리더·내부 캐시 해제. 호출 워크북 사용 불가. 이미 닫혔으면 no-op(안전). 미호출 리소스 누수.
22
- - `readonly zipCache: ZipCache` — 내부 ZIP 캐시. 일반 사용에서는 직접 다루지 않음.
15
+ - `getWorksheetNames(): Promise<string[]>` — 워크북의 모든 시트 이름을 정의 순서로 반환. 시트 존재 여부·선택지를 미리 알아야 할 때.
16
+ - `addWorksheet(name: string): Promise<ExcelWorksheet>` — 새 시트를 만들어 반환. workbook/ContentTypes/rels 파트를 함께 갱신한다. 파일 쓰기 시작점.
17
+ - `getWorksheet(nameOrIndex: string | number): Promise<ExcelWorksheet>` — 이름(string) 또는 0 기반 인덱스(number)로 시트 조회. 없으면 throw. 같은 시트는 캐시되어 동일 인스턴스를 반환한다.
18
+ - `setDefaultStyle(opts: ExcelStyleOptions): Promise<void>` — 워크북 전역 기본 셀 스타일. `styles.xml` 의 0번 자원 슬롯(font/fill/border)을 덮어써, fontId/fillId/borderId 를 따로 지정하지 않은 모든 셀에 적용된다. 옵션 풀이는 [style.md](./style.md) 참조.
19
+ - `toBytes(): Promise<Bytes>` — 워크북을 ZIP 바이트로 직렬화. 파일 저장·서버 전송용.
20
+ - `toBlob(): Promise<Blob>` — 워크북을 `.sheet` MIME 의 Blob 으로 직렬화. 브라우저 다운로드용.
21
+ - `close(): Promise<void>` — ZIP 리더·내부 캐시 해제. 이후 인스턴스 사용 불가. 이미 닫혔으면 no-op(중복 호출 안전). 모든 작업을 `try/finally` 로 감싸 반드시 호출.
22
+ - `readonly zipCache: ZipCache` — 내부 ZIP 캐시 핸들(저수준). 일반 사용에서 직접 만질 일 없음.
23
23
 
24
- `close()` 외 모든 메서드는 닫힌 워크북에서 호출 시 throw.
25
-
26
- ### 사용 예
24
+ 읽기 예:
27
25
 
28
26
  ```typescript
29
- const wb = new ExcelWorkbook(bytes); // 기존 파일 열기
27
+ const wb = new ExcelWorkbook(bytes);
30
28
  try {
31
29
  const ws = await wb.getWorksheet(0);
32
- const table = await ws.getDataTable({ checkEndColIndex: 0 });
30
+ const rows = await ws.getDataTable();
31
+ } finally {
32
+ await wb.close();
33
+ }
34
+ ```
35
+
36
+ 쓰기 예:
37
+
38
+ ```typescript
39
+ const wb = new ExcelWorkbook();
40
+ try {
41
+ await wb.setDefaultStyle({ font: { family: "맑은 고딕", size: 10 } });
42
+ const ws = await wb.addWorksheet("결과");
43
+ await ws.setRecords([{ 코드: "A1", 수량: 3 }]);
44
+ return await wb.toBytes();
33
45
  } finally {
34
46
  await wb.close();
35
47
  }
@@ -37,61 +49,72 @@ try {
37
49
 
38
50
  ## ExcelWorksheet
39
51
 
40
- `wb.getWorksheet` / `wb.addWorksheet` 얻는다. 행/열/셀 접근, 복사, 데이터 변환, 뷰, 조건부 서식, 이미지를 제공.
52
+ `wb.addWorksheet` / `wb.getWorksheet` 로만 얻는다(직접 생성 함). 0 기반 행/열 인덱스를 쓴다.
41
53
 
42
- ### 이름
54
+ 이름:
43
55
 
44
- - `getName(): Promise<string>` — 시트 이름 반환(못 찾으면 throw).
56
+ - `getName(): Promise<string>` — 시트 이름 반환.
45
57
  - `setName(newName: string): Promise<void>` — 시트 이름 변경.
46
58
 
47
- ### 셀/행/열 접근 (모두 0 기반)
59
+ 접근:
60
+
61
+ - `cell(r: number, c: number): ExcelCell` — 0 기반 행 `r`·열 `c` 의 셀 객체 반환(동기, 인스턴스 캐시). 값/스타일 실제 I/O 는 ExcelCell 의 async 메서드에서. 상세 [cell.md](./cell.md).
62
+ - `row(r: number): ExcelRow` — 0 기반 행 객체 반환.
63
+ - `col(c: number): ExcelCol` — 0 기반 열 객체 반환.
64
+
65
+ 범위:
66
+
67
+ - `getRange(): Promise<ExcelAddressRangePoint>` — 시트의 데이터 범위(`{s,e}`, 양끝 inclusive) 반환. 전체 셀 순회 루프 경계로 사용.
68
+ - `getCells(): Promise<ExcelCell[][]>` — 데이터 범위 전체 셀을 행 우선 2차원 배열로 반환. 채워지는 인덱스는 range 기준(앞쪽 빈 행/열은 비어 있음).
48
69
 
49
- - `row(r): ExcelRow` — `r` 행 객체(캐시). 행 단위 순회·셀 접근. 자세히: [cell.md](./cell.md).
50
- - `col(c): ExcelCol` — `c` 열 객체(캐시). 열 단위 순회·너비 설정.
51
- - `cell(r, c): ExcelCell` — 단일 셀 객체(캐시). 값/수식/스타일/병합.
52
- - `getRange(): Promise<ExcelAddressRangePoint>` — 시트의 데이터 범위(`{s, e}`).
53
- - `getCells(): Promise<ExcelCell[][]>` — 데이터 범위 전체를 행 우선 2차원 셀 배열로.
70
+ 데이터(테이블/매트릭스/레코드):
54
71
 
55
- ### 복사
72
+ - `getDataTable(opt?): Promise<Record<string, ExcelValueType>[]>` — 헤더 행을 키로 한 레코드 배열로 읽기.
73
+ - `opt.headerRowIndex?: number` — 헤더로 쓸 행 인덱스. 미지정 시 range 시작 행. 상단에 제목 행이 있으면 실제 헤더 행 인덱스를 지정.
74
+ - `opt.checkEndColIndex?: number` — 데이터 끝 판정 열. 그 열 셀이 비면 이후 행을 더 읽지 않고 종료. 빈 행으로 데이터가 끊기는 양식에서 사용.
75
+ - `opt.usableHeaderNameFn?: (headerName: string) => boolean` — 헤더 채택 필터. `true` 인 헤더만 키로 사용. 일부 열만 읽을 때. 채택된 헤더가 중복이면 throw.
76
+ - `setDataMatrix(matrix: ExcelValueType[][]): Promise<void>` — 2차원 배열을 0,0 부터 행 우선으로 쓰기. 헤더 없이 좌표 그대로 채울 때. `undefined` 원소는 해당 셀 삭제.
77
+ - `setRecords(records: Record<string, ExcelValueType>[]): Promise<void>` — 0행에 헤더(전 레코드 키 합집합, 빈 키 제외)를 자동 생성하고 1행부터 값 기록. 키 순서는 첫 등장 순. 표 형태 출력의 기본 수단.
56
78
 
57
- - `copyCellStyle(srcAddr, targetAddr): Promise<void>` — 셀 스타일 ID 만 복사(값 미복사). `srcAddr`/`targetAddr` = `ExcelAddressPoint`.
58
- - `copyRowStyle(srcR, targetR): Promise<void>` — 데이터 범위 폭만큼 한 행의 셀 스타일을 다른 행에 복사.
59
- - `copyCell(srcAddr, targetAddr): Promise<void>` — 셀 전체(값·수식·스타일) 복사.
60
- - `copyRow(srcR, targetR): Promise<void>` — 한 행을 다른 행으로 복사(대상 덮어쓰기).
61
- - `insertCopyRow(srcR, targetR): Promise<void>` — `srcR` 행을 `targetR` 위치에 삽입 복사. `targetR` 이하 기존 행은 한 칸 아래로 밀리고, 삽입 지점을 관통하는 다중행 병합은 1행 확장된다. 행 추가 삽입(기존 보존)이 필요할 때 `copyRow`(덮어쓰기) 대신 사용.
79
+ 뷰:
62
80
 
63
- ### 데이터 변환
81
+ - `setTabColor(color: string): Promise<void>` — 시트 탭 색(ARGB 8자리, 예 `"00FF0000"`). 시트 구분 강조용.
82
+ - `setZoom(percent: number): Promise<void>` — 확대/축소 비율(퍼센트). 워크북 뷰를 함께 초기화한다.
83
+ - `freezeAt(point: { r?: number; c?: number }): Promise<void>` — 틀 고정. `r` = 위쪽 고정할 행 분할 지점, `c` = 왼쪽 고정할 열 분할 지점(0 기반). 헤더 한 줄 고정이면 `{ r: 0 }`(0행까지 위가 고정되고 1행부터 스크롤).
64
84
 
65
- - `getDataTable(opt?): Promise<Record<string, ExcelValueType>[]>` — 헤더 행을 키로, 이후 행을 레코드로 변환.
66
- - `opt.headerRowIndex?: number` — 헤더로 쓸 행 인덱스. 미지정 시 데이터 범위 첫 행.
67
- - `opt.checkEndColIndex?: number` — 데이터 끝 판정 열. 이 열이 비면 그 행에서 중단. 빈 행 뒤 잡음 데이터를 끊을 때 지정.
68
- - `opt.usableHeaderNameFn?: (headerName: string) => boolean` — `true` 반환한 헤더만 컬럼으로 채택. 일부 컬럼만 읽을 때.
69
- - 헤더 문자열이 중복되면 throw.
70
- - `setDataMatrix(matrix: ExcelValueType[][]): Promise<void>` — 0행 0열부터 행 우선으로 2차원 배열을 그대로 기록.
71
- - `setRecords(records: Record<string, ExcelValueType>[]): Promise<void>` — 0행에 헤더(전 레코드 키의 distinct, 빈 키 제외) 자동 생성 후 1행부터 값 기록.
85
+ 조건부 서식:
72
86
 
73
- ###
87
+ - `addConditionalFormat(opts: { ref: string; rules: ExcelConditionalRule[] }): Promise<void>` — 셀/범위에 native CF 규칙 추가. 상세 [conditional-format.md](./conditional-format.md).
74
88
 
75
- - `setTabColor(color): Promise<void>` — 시트 탭 색. `color` = ARGB 8자리(예: `"00FF0000"`).
76
- - `setZoom(percent): Promise<void>` — 확대/축소 비율(퍼센트).
77
- - `freezeAt(point: { r?: number; c?: number }): Promise<void>` — 틀 고정. `r` = 이 행 위에서 고정, `c` = 이 열 왼쪽에서 고정. 둘 다/하나만 지정 가능.
89
+ 복사/삽입:
78
90
 
79
- ### 조건부 서식 / 이미지
91
+ - `copyCellStyle(srcAddr: ExcelAddressPoint, targetAddr: ExcelAddressPoint): Promise<void>` — 셀 스타일 ID 만 복사(값 제외). 원본에 스타일이 없으면 무변경.
92
+ - `copyRowStyle(srcR: number, targetR: number): Promise<void>` — range 내 모든 열에 대해 행 스타일 복사.
93
+ - `copyCell(srcAddr, targetAddr): Promise<void>` — 셀(값+스타일)을 대상에 복사.
94
+ - `copyRow(srcR: number, targetR: number): Promise<void>` — 행 전체를 대상 행에 복사(대상 기존 내용 덮어쓰기).
95
+ - `insertCopyRow(srcR: number, targetR: number): Promise<void>` — 원본 행을 대상 위치에 "삽입" 복사. 대상 이하 기존 행은 1칸 아래로 밀리고, 삽입 지점을 관통하는 다중행 병합은 1행 확장, 원본의 단일행 병합은 대상 행에 복제된다. 템플릿 행을 반복 펼칠 때 사용(덮어쓰기 방지).
80
96
 
81
- - `addConditionalFormat(opts): Promise<void>` — 셀/범위에 native CF 규칙 추가. 자세히: [conditional-format.md](./conditional-format.md).
82
- - `addImage(opts): Promise<void>` — 이미지 삽입.
97
+ 이미지:
98
+
99
+ - `addImage(opts): Promise<void>` — 시트에 이미지 삽입.
83
100
  - `opts.bytes: Bytes` — 이미지 바이너리.
84
- - `opts.ext: string` — 확장자(png/jpg 등). MIME 결정 불가 시 throw.
85
- - `opts.from: { r, c, rOff?, cOff? }` — 시작 앵커(0 기반 행/열, `rOff`/`cOff` 는 EMU 오프셋).
86
- - `opts.to?: { r, c, rOff?, cOff? }` — 끝 앵커. 생략 시 `from` 기준 1행·1 크기로 배치.
87
- - 같은 시트의 기존 drawing 이 있으면 재사용하고 없으면 새로 만든다.
101
+ - `opts.ext: string` — 확장자(`"png"`, `"jpg"` 등). MIME 미해석 시 throw.
102
+ - `opts.from: { r: number; c: number; rOff?: number | string; cOff?: number | string }` — 시작 위치(0 기반 행/열, `rOff`/`cOff` 는 셀 내부 EMU 오프셋).
103
+ - `opts.to?: { r; c; rOff?; cOff? }` — 끝 위치. 생략 시 `from` 한 칸 우하단(`from.r+1, from.c+1`)에 배치되어 약 1셀 크기로 들어간다. 명시하면 두 셀 앵커 사이로 늘려 배치.
88
104
 
89
- ### 사용
105
+ 데이터 읽기 예:
90
106
 
91
107
  ```typescript
92
- const ws = await wb.addWorksheet("매출");
93
- await ws.setRecords([{ 품목: "사과", 수량: 10 }]);
94
- await ws.setZoom(85);
95
- await ws.freezeAt({ r: 0 });
96
- await ws.addImage({ bytes, ext: "png", from: { r: 0, c: 3 } });
108
+ const ws = await wb.getWorksheet("입력");
109
+ const rows = await ws.getDataTable({
110
+ headerRowIndex: 1,
111
+ checkEndColIndex: 0,
112
+ usableHeaderNameFn: (h) => ["코드", "수량"].includes(h),
113
+ });
97
114
  ```
115
+
116
+ ## 주의사항
117
+
118
+ - 모든 셀/시트 I/O 메서드는 `async` — lazy XML 로드 때문. 반복 쓰기는 await 누적이 필요하다.
119
+ - `ExcelWorkbook` 은 반드시 `close()` 해야 한다. 닫힌 워크북의 모든 메서드는 throw.
120
+ - `setRecords` 헤더는 레코드 키에서 자동 생성되므로 열 순서를 고정하려면 모든 레코드의 키 등장 순을 일정하게 유지하거나 `setDataMatrix` 를 사용.