@simplysm/excel 14.0.99 → 14.0.101

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 (184) hide show
  1. package/dist/biff/biff-model-factory.d.ts +32 -0
  2. package/dist/biff/biff-model-factory.d.ts.map +1 -0
  3. package/dist/biff/biff-model-factory.js +88 -0
  4. package/dist/biff/biff-model-factory.js.map +1 -0
  5. package/dist/biff/biff-ptg.d.ts +14 -0
  6. package/dist/biff/biff-ptg.d.ts.map +1 -0
  7. package/dist/biff/biff-ptg.js +277 -0
  8. package/dist/biff/biff-ptg.js.map +1 -0
  9. package/dist/biff/biff-records.d.ts +163 -0
  10. package/dist/biff/biff-records.d.ts.map +1 -0
  11. package/dist/biff/biff-records.js +579 -0
  12. package/dist/biff/biff-records.js.map +1 -0
  13. package/dist/biff/biff-shared-string-model.d.ts +13 -0
  14. package/dist/biff/biff-shared-string-model.d.ts.map +1 -0
  15. package/dist/biff/biff-shared-string-model.js +41 -0
  16. package/dist/biff/biff-shared-string-model.js.map +1 -0
  17. package/dist/biff/biff-style-model.d.ts +39 -0
  18. package/dist/biff/biff-style-model.d.ts.map +1 -0
  19. package/dist/biff/biff-style-model.js +182 -0
  20. package/dist/biff/biff-style-model.js.map +1 -0
  21. package/dist/biff/biff-workbook-model.d.ts +17 -0
  22. package/dist/biff/biff-workbook-model.d.ts.map +1 -0
  23. package/dist/biff/biff-workbook-model.js +64 -0
  24. package/dist/biff/biff-workbook-model.js.map +1 -0
  25. package/dist/biff/biff-worksheet-model.d.ts +69 -0
  26. package/dist/biff/biff-worksheet-model.d.ts.map +1 -0
  27. package/dist/biff/biff-worksheet-model.js +495 -0
  28. package/dist/biff/biff-worksheet-model.js.map +1 -0
  29. package/dist/biff/biff12-codec.d.ts +149 -0
  30. package/dist/biff/biff12-codec.d.ts.map +1 -0
  31. package/dist/biff/biff12-codec.js +262 -0
  32. package/dist/biff/biff12-codec.js.map +1 -0
  33. package/dist/excel-cell.d.ts +0 -6
  34. package/dist/excel-cell.d.ts.map +1 -1
  35. package/dist/excel-cell.js +2 -24
  36. package/dist/excel-cell.js.map +1 -1
  37. package/dist/excel-col.js.map +1 -1
  38. package/dist/excel-row.js.map +1 -1
  39. package/dist/excel-workbook.d.ts +4 -21
  40. package/dist/excel-workbook.d.ts.map +1 -1
  41. package/dist/excel-workbook.js +16 -49
  42. package/dist/excel-workbook.js.map +1 -1
  43. package/dist/excel-worksheet.d.ts +0 -11
  44. package/dist/excel-worksheet.d.ts.map +1 -1
  45. package/dist/excel-worksheet.js +9 -46
  46. package/dist/excel-worksheet.js.map +1 -1
  47. package/dist/excel-wrapper.d.ts +0 -10
  48. package/dist/excel-wrapper.d.ts.map +1 -1
  49. package/dist/excel-wrapper.js +0 -10
  50. package/dist/excel-wrapper.js.map +1 -1
  51. package/dist/models/excel-format.d.ts +3 -0
  52. package/dist/models/excel-format.d.ts.map +1 -0
  53. package/dist/models/excel-format.js +2 -0
  54. package/dist/models/excel-format.js.map +1 -0
  55. package/dist/models/excel-model-factory.d.ts +33 -0
  56. package/dist/models/excel-model-factory.d.ts.map +1 -0
  57. package/dist/models/excel-model-factory.js +2 -0
  58. package/dist/models/excel-model-factory.js.map +1 -0
  59. package/dist/models/excel-model.d.ts +12 -0
  60. package/dist/models/excel-model.d.ts.map +1 -0
  61. package/dist/models/excel-model.js +2 -0
  62. package/dist/models/excel-model.js.map +1 -0
  63. package/dist/models/i-content-type-model.d.ts +7 -0
  64. package/dist/models/i-content-type-model.d.ts.map +1 -0
  65. package/dist/models/i-content-type-model.js +2 -0
  66. package/dist/models/i-content-type-model.js.map +1 -0
  67. package/dist/models/i-drawing-model.d.ts +23 -0
  68. package/dist/models/i-drawing-model.d.ts.map +1 -0
  69. package/dist/models/i-drawing-model.js +2 -0
  70. package/dist/models/i-drawing-model.js.map +1 -0
  71. package/dist/models/i-relationship-model.d.ts +16 -0
  72. package/dist/models/i-relationship-model.d.ts.map +1 -0
  73. package/dist/models/i-relationship-model.js +2 -0
  74. package/dist/models/i-relationship-model.js.map +1 -0
  75. package/dist/models/i-shared-string-model.d.ts +9 -0
  76. package/dist/models/i-shared-string-model.d.ts.map +1 -0
  77. package/dist/models/i-shared-string-model.js +2 -0
  78. package/dist/models/i-shared-string-model.js.map +1 -0
  79. package/dist/models/i-style-model.d.ts +18 -0
  80. package/dist/models/i-style-model.d.ts.map +1 -0
  81. package/dist/models/i-style-model.js +2 -0
  82. package/dist/models/i-style-model.js.map +1 -0
  83. package/dist/models/i-workbook-model.d.ts +17 -0
  84. package/dist/models/i-workbook-model.d.ts.map +1 -0
  85. package/dist/models/i-workbook-model.js +2 -0
  86. package/dist/models/i-workbook-model.js.map +1 -0
  87. package/dist/models/i-worksheet-model.d.ts +39 -0
  88. package/dist/models/i-worksheet-model.d.ts.map +1 -0
  89. package/dist/models/i-worksheet-model.js +2 -0
  90. package/dist/models/i-worksheet-model.js.map +1 -0
  91. package/dist/models/shared/excel-cf-spec.d.ts +13 -0
  92. package/dist/models/shared/excel-cf-spec.d.ts.map +1 -0
  93. package/dist/models/shared/excel-cf-spec.js +2 -0
  94. package/dist/models/shared/excel-cf-spec.js.map +1 -0
  95. package/dist/models/shared/excel-style.d.ts +24 -0
  96. package/dist/models/shared/excel-style.d.ts.map +1 -0
  97. package/dist/models/shared/excel-style.js +38 -0
  98. package/dist/models/shared/excel-style.js.map +1 -0
  99. package/dist/types.d.ts +0 -13
  100. package/dist/types.d.ts.map +1 -1
  101. package/dist/types.js.map +1 -1
  102. package/dist/utils/excel-style-data.d.ts +3 -5
  103. package/dist/utils/excel-style-data.d.ts.map +1 -1
  104. package/dist/utils/excel-style-data.js +2 -16
  105. package/dist/utils/excel-style-data.js.map +1 -1
  106. package/dist/utils/zip-cache.d.ts +46 -9
  107. package/dist/utils/zip-cache.d.ts.map +1 -1
  108. package/dist/utils/zip-cache.js +138 -52
  109. package/dist/utils/zip-cache.js.map +1 -1
  110. package/dist/xml/excel-xml-content-type.d.ts +8 -4
  111. package/dist/xml/excel-xml-content-type.d.ts.map +1 -1
  112. package/dist/xml/excel-xml-content-type.js +13 -6
  113. package/dist/xml/excel-xml-content-type.js.map +1 -1
  114. package/dist/xml/excel-xml-drawing.d.ts +8 -4
  115. package/dist/xml/excel-xml-drawing.d.ts.map +1 -1
  116. package/dist/xml/excel-xml-drawing.js +14 -7
  117. package/dist/xml/excel-xml-drawing.js.map +1 -1
  118. package/dist/xml/excel-xml-relationship.d.ts +12 -4
  119. package/dist/xml/excel-xml-relationship.d.ts.map +1 -1
  120. package/dist/xml/excel-xml-relationship.js +22 -12
  121. package/dist/xml/excel-xml-relationship.js.map +1 -1
  122. package/dist/xml/excel-xml-shared-string.d.ts +8 -4
  123. package/dist/xml/excel-xml-shared-string.d.ts.map +1 -1
  124. package/dist/xml/excel-xml-shared-string.js +16 -9
  125. package/dist/xml/excel-xml-shared-string.js.map +1 -1
  126. package/dist/xml/excel-xml-style.d.ts +11 -22
  127. package/dist/xml/excel-xml-style.d.ts.map +1 -1
  128. package/dist/xml/excel-xml-style.js +66 -92
  129. package/dist/xml/excel-xml-style.js.map +1 -1
  130. package/dist/xml/excel-xml-unknown.d.ts +6 -5
  131. package/dist/xml/excel-xml-unknown.d.ts.map +1 -1
  132. package/dist/xml/excel-xml-unknown.js +7 -4
  133. package/dist/xml/excel-xml-unknown.js.map +1 -1
  134. package/dist/xml/excel-xml-workbook.d.ts +9 -4
  135. package/dist/xml/excel-xml-workbook.d.ts.map +1 -1
  136. package/dist/xml/excel-xml-workbook.js +28 -20
  137. package/dist/xml/excel-xml-workbook.js.map +1 -1
  138. package/dist/xml/excel-xml-worksheet.d.ts +12 -7
  139. package/dist/xml/excel-xml-worksheet.d.ts.map +1 -1
  140. package/dist/xml/excel-xml-worksheet.js +65 -50
  141. package/dist/xml/excel-xml-worksheet.js.map +1 -1
  142. package/dist/xml/xml-model-factory.d.ts +25 -0
  143. package/dist/xml/xml-model-factory.d.ts.map +1 -0
  144. package/dist/xml/xml-model-factory.js +66 -0
  145. package/dist/xml/xml-model-factory.js.map +1 -0
  146. package/package.json +2 -2
  147. package/src/biff/biff-model-factory.ts +101 -0
  148. package/src/biff/biff-ptg.ts +289 -0
  149. package/src/biff/biff-records.ts +686 -0
  150. package/src/biff/biff-shared-string-model.ts +52 -0
  151. package/src/biff/biff-style-model.ts +219 -0
  152. package/src/biff/biff-workbook-model.ts +83 -0
  153. package/src/biff/biff-worksheet-model.ts +545 -0
  154. package/src/biff/biff12-codec.ts +286 -0
  155. package/src/excel-cell.ts +12 -46
  156. package/src/excel-col.ts +3 -3
  157. package/src/excel-row.ts +3 -3
  158. package/src/excel-workbook.ts +26 -69
  159. package/src/excel-worksheet.ts +36 -107
  160. package/src/excel-wrapper.ts +0 -10
  161. package/src/models/excel-format.ts +2 -0
  162. package/src/models/excel-model-factory.ts +33 -0
  163. package/src/models/excel-model.ts +12 -0
  164. package/src/models/i-content-type-model.ts +7 -0
  165. package/src/models/i-drawing-model.ts +13 -0
  166. package/src/models/i-relationship-model.ts +13 -0
  167. package/src/models/i-shared-string-model.ts +9 -0
  168. package/src/models/i-style-model.ts +18 -0
  169. package/src/models/i-workbook-model.ts +17 -0
  170. package/src/models/i-worksheet-model.ts +40 -0
  171. package/src/models/shared/excel-cf-spec.ts +24 -0
  172. package/src/models/shared/excel-style.ts +65 -0
  173. package/src/types.ts +0 -13
  174. package/src/utils/excel-style-data.ts +4 -25
  175. package/src/utils/zip-cache.ts +189 -58
  176. package/src/xml/excel-xml-content-type.ts +18 -8
  177. package/src/xml/excel-xml-drawing.ts +19 -9
  178. package/src/xml/excel-xml-relationship.ts +28 -14
  179. package/src/xml/excel-xml-shared-string.ts +20 -11
  180. package/src/xml/excel-xml-style.ts +74 -116
  181. package/src/xml/excel-xml-unknown.ts +8 -4
  182. package/src/xml/excel-xml-workbook.ts +34 -22
  183. package/src/xml/excel-xml-worksheet.ts +73 -53
  184. package/src/xml/xml-model-factory.ts +83 -0
@@ -0,0 +1,41 @@
1
+ import { concatBytes, REC } from "./biff12-codec.js";
2
+ import { encodeBrtBeginSst, encodeBrtSSTItem, encodeMarker, readSharedStrings, } from "./biff-records.js";
3
+ /** sharedStrings.bin (BIFF12) 읽기/쓰기 모델. */
4
+ export class BiffSharedStringModel {
5
+ _strings;
6
+ _indexMap = new Map();
7
+ constructor(bytes) {
8
+ this._strings = bytes != null ? readSharedStrings(bytes) : [];
9
+ for (let i = 0; i < this._strings.length; i++) {
10
+ if (!this._indexMap.has(this._strings[i])) {
11
+ this._indexMap.set(this._strings[i], i);
12
+ }
13
+ }
14
+ }
15
+ getStringById(id) {
16
+ return this._strings[id];
17
+ }
18
+ getIdByString(str) {
19
+ return this._indexMap.get(str);
20
+ }
21
+ add(str) {
22
+ const existing = this._indexMap.get(str);
23
+ if (existing != null)
24
+ return existing;
25
+ const idx = this._strings.length;
26
+ this._strings.push(str);
27
+ this._indexMap.set(str, idx);
28
+ return idx;
29
+ }
30
+ serialize() {
31
+ const parts = [
32
+ encodeBrtBeginSst(this._strings.length, this._strings.length),
33
+ ];
34
+ for (const s of this._strings) {
35
+ parts.push(encodeBrtSSTItem(s));
36
+ }
37
+ parts.push(encodeMarker(REC.BrtEndSst));
38
+ return concatBytes(parts);
39
+ }
40
+ }
41
+ //# sourceMappingURL=biff-shared-string-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biff-shared-string-model.js","sourceRoot":"","sources":["../../src/biff/biff-shared-string-model.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAExB,2CAA2C;AAC3C,MAAM,OAAO,qBAAqB;IACf,QAAQ,CAAW;IACnB,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvD,YAAY,KAAa;QACvB,IAAI,CAAC,QAAQ,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;IAED,aAAa,CAAC,EAAU;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,aAAa,CAAC,GAAW;QACvB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,GAAG,CAAC,GAAW;QACb,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,QAAQ,IAAI,IAAI;YAAE,OAAO,QAAQ,CAAC;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACjC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC7B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,SAAS;QACP,MAAM,KAAK,GAAiB;YAC1B,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;SAC9D,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;QACxC,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;CACF"}
@@ -0,0 +1,39 @@
1
+ import type { Bytes } from "@simplysm/core-common";
2
+ import type { IStyleModel } from "../models/i-style-model";
3
+ import type { ExcelStyle } from "../models/shared/excel-style";
4
+ import type { ExcelConditionalRuleStyle } from "../types";
5
+ /**
6
+ * styles.bin (BIFF12) 읽기/쓰기 모델.
7
+ *
8
+ * **읽기**: 셀 iStyleRef(cellXFs 인덱스) → numFmtId 매핑 + numFmt 코드 디코드(날짜/숫자 포맷 판정용).
9
+ * 원본을 읽은 경우 직렬화는 원본 바이트를 그대로 보존한다(스타일 손실 방지).
10
+ *
11
+ * **쓰기**(새 워크북, 빈 모델): numberFormat 만 지원. 기본 슬롯(font/fill/border/cellStyleXF)을
12
+ * 정답지 byte 로 고정하고, cellXFs 만 numFmtId 별로 추가하여 styles.bin 을 재생성한다.
13
+ * 배경·테두리·폰트·정렬은 후속 단계.
14
+ */
15
+ export declare class BiffStyleModel implements IStyleModel {
16
+ private readonly _raw;
17
+ private readonly _numFmts;
18
+ private readonly _cellXfNumFmtIds;
19
+ private readonly _dxfs;
20
+ constructor(bytes?: Bytes);
21
+ private _decode;
22
+ /**
23
+ * BrtDXF([MS-XLSB] 2.4.359) payload → 조건부 서식 스타일.
24
+ * header(2) + XFProps(reserved 2 + cprops 2 + XFProp[]). bg color(0x02)→background,
25
+ * text color(0x05)→fontColor, Bold(0x19, >=700)→bold. 그 외 prop(border/numFmt 등)은 무시.
26
+ */
27
+ private _decodeDxf;
28
+ get(id: string): ExcelStyle;
29
+ getNumFmtCode(numFmtId: string): string | undefined;
30
+ add(style: ExcelStyle): string;
31
+ addWithClone(_id: string, style: ExcelStyle): string;
32
+ addDxf(style: ExcelConditionalRuleStyle): string;
33
+ /** @internal 테스트용 — 디코드된 dxf 목록. */
34
+ get dxfs(): ExcelConditionalRuleStyle[];
35
+ setDefaultStyle(): void;
36
+ private _setNumFmtCode;
37
+ serialize(): Bytes;
38
+ }
39
+ //# sourceMappingURL=biff-style-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biff-style-model.d.ts","sourceRoot":"","sources":["../../src/biff/biff-style-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AA4B1D;;;;;;;;;GASG;AACH,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IACtD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAW;IAC5C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;gBAE7C,KAAK,CAAC,EAAE,KAAK;IAUzB,OAAO,CAAC,OAAO;IAmBf;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAuBlB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU;IAM3B,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAInD,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM;IAsB9B,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM;IAKpD,MAAM,CAAC,KAAK,EAAE,yBAAyB,GAAG,MAAM;IAShD,oCAAoC;IACpC,IAAI,IAAI,IAAI,yBAAyB,EAAE,CAEtC;IAED,eAAe,IAAI,IAAI;IAIvB,OAAO,CAAC,cAAc;IAWtB,SAAS,IAAI,KAAK;CAgDnB"}
@@ -0,0 +1,182 @@
1
+ import { concatBytes, encodeRecord, readAllRecords, readXLWideString, REC } from "./biff12-codec.js";
2
+ import { encodeBeginCount, encodeBrtDXF, encodeBrtFmt, encodeCellXF, encodeMarker } from "./biff-records.js";
3
+ const HEX = (n) => n.toString(16).padStart(2, "0").toUpperCase();
4
+ const READONLY_WRITE = "기존 xlsb 의 스타일 수정은 아직 지원되지 않습니다 (후속 예정).";
5
+ const STYLE_WRITE_LIMIT = "xlsb 는 numberFormat 외 셀 스타일(배경/테두리/폰트/정렬) 쓰기를 아직 지원하지 않습니다 (후속 예정).";
6
+ const hexBytes = (h) => Uint8Array.from(h.split(" ").map((x) => parseInt(x, 16)));
7
+ // boa-sample.xlsb 정답지에서 추출한 기본 슬롯 (Calibri 11 / none·gray125 fill / empty border / General xf).
8
+ const SLOT_FONT = hexBytes("dc 00 00 00 90 01 00 00 00 02 00 00 07 01 00 00 00 00 00 ff 02 07 00 00 00 43 00 61 00 6c 00 69 00 62 00 72 00 69 00");
9
+ const SLOT_FILL_NONE = hexBytes("00 00 00 00 03 40 00 00 00 00 00 ff 03 41 00 00 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
10
+ const SLOT_FILL_GRAY125 = hexBytes("11 00 00 00 03 40 00 00 00 00 00 ff 03 41 00 00 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
11
+ const SLOT_BORDER = hexBytes("00 00 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00");
12
+ const SLOT_CELLSTYLEXF = hexBytes("ff ff 00 00 00 00 00 00 00 00 00 00 10 10 00 00");
13
+ /**
14
+ * styles.bin (BIFF12) 읽기/쓰기 모델.
15
+ *
16
+ * **읽기**: 셀 iStyleRef(cellXFs 인덱스) → numFmtId 매핑 + numFmt 코드 디코드(날짜/숫자 포맷 판정용).
17
+ * 원본을 읽은 경우 직렬화는 원본 바이트를 그대로 보존한다(스타일 손실 방지).
18
+ *
19
+ * **쓰기**(새 워크북, 빈 모델): numberFormat 만 지원. 기본 슬롯(font/fill/border/cellStyleXF)을
20
+ * 정답지 byte 로 고정하고, cellXFs 만 numFmtId 별로 추가하여 styles.bin 을 재생성한다.
21
+ * 배경·테두리·폰트·정렬은 후속 단계.
22
+ */
23
+ export class BiffStyleModel {
24
+ _raw;
25
+ _numFmts = new Map();
26
+ _cellXfNumFmtIds;
27
+ _dxfs = [];
28
+ constructor(bytes) {
29
+ this._raw = bytes;
30
+ if (bytes != null) {
31
+ this._cellXfNumFmtIds = [];
32
+ this._decode(bytes);
33
+ }
34
+ else {
35
+ this._cellXfNumFmtIds = [0]; // cellXF[0] = General
36
+ }
37
+ }
38
+ _decode(buf) {
39
+ let inCellXfs = false;
40
+ for (const rec of readAllRecords(buf)) {
41
+ if (rec.type === REC.BrtFmt) {
42
+ const id = rec.payload[0] | (rec.payload[1] << 8);
43
+ this._numFmts.set(id, readXLWideString(rec.payload, 2).value);
44
+ }
45
+ else if (rec.type === REC.BrtBeginCellXFs) {
46
+ inCellXfs = true;
47
+ }
48
+ else if (rec.type === REC.BrtEndCellXFs) {
49
+ inCellXfs = false;
50
+ }
51
+ else if (inCellXfs && rec.type === REC.BrtXF) {
52
+ // BrtXF(16B): ixfeParent(u16@0) + iFmt(u16@2) + iFont(@4) + iFill(@6) + ixBorder(@8) + ...
53
+ this._cellXfNumFmtIds.push(rec.payload[2] | (rec.payload[3] << 8));
54
+ }
55
+ else if (rec.type === REC.BrtDXF) {
56
+ this._dxfs.push(this._decodeDxf(rec.payload));
57
+ }
58
+ }
59
+ }
60
+ /**
61
+ * BrtDXF([MS-XLSB] 2.4.359) payload → 조건부 서식 스타일.
62
+ * header(2) + XFProps(reserved 2 + cprops 2 + XFProp[]). bg color(0x02)→background,
63
+ * text color(0x05)→fontColor, Bold(0x19, >=700)→bold. 그 외 prop(border/numFmt 등)은 무시.
64
+ */
65
+ _decodeDxf(p) {
66
+ const dxf = {};
67
+ if (p.length < 6)
68
+ return dxf;
69
+ const cprops = p[4] | (p[5] << 8);
70
+ // XFPropColor(8B) → "AARRGGBB" (LongRGBA = R,G,B,A @blob[4..7])
71
+ const argb = (blob) => `${HEX(blob[7])}${HEX(blob[4])}${HEX(blob[5])}${HEX(blob[6])}`;
72
+ let off = 6;
73
+ for (let k = 0; k < cprops && off + 4 <= p.length; k++) {
74
+ const type = p[off] | (p[off + 1] << 8);
75
+ const cb = p[off + 2] | (p[off + 3] << 8);
76
+ if (cb < 4)
77
+ break;
78
+ const blob = p.subarray(off + 4, off + cb);
79
+ if (type === 0x02 && blob.length >= 8)
80
+ dxf.background = argb(blob);
81
+ else if (type === 0x05 && blob.length >= 8)
82
+ dxf.fontColor = argb(blob);
83
+ else if (type === 0x19 && blob.length >= 2 && (blob[0] | (blob[1] << 8)) >= 700) {
84
+ dxf.fontWeight = "bold";
85
+ }
86
+ off += cb;
87
+ }
88
+ return dxf;
89
+ }
90
+ get(id) {
91
+ const idx = parseInt(id, 10);
92
+ if (idx < 0 || idx >= this._cellXfNumFmtIds.length)
93
+ return {};
94
+ return { numFmtId: this._cellXfNumFmtIds[idx].toString() };
95
+ }
96
+ getNumFmtCode(numFmtId) {
97
+ return this._numFmts.get(parseInt(numFmtId, 10));
98
+ }
99
+ add(style) {
100
+ if (this._raw != null)
101
+ throw new Error(READONLY_WRITE);
102
+ if (style.background != null ||
103
+ style.border != null ||
104
+ style.font != null ||
105
+ style.horizontalAlign != null ||
106
+ style.verticalAlign != null) {
107
+ throw new Error(STYLE_WRITE_LIMIT);
108
+ }
109
+ let numFmtId = 0;
110
+ if (style.numFmtCode != null)
111
+ numFmtId = this._setNumFmtCode(style.numFmtCode);
112
+ else if (style.numFmtId != null)
113
+ numFmtId = parseInt(style.numFmtId, 10);
114
+ const existing = this._cellXfNumFmtIds.indexOf(numFmtId);
115
+ if (existing >= 0)
116
+ return existing.toString();
117
+ this._cellXfNumFmtIds.push(numFmtId);
118
+ return (this._cellXfNumFmtIds.length - 1).toString();
119
+ }
120
+ addWithClone(_id, style) {
121
+ // 현재 numberFormat 만 지원하므로 clone 은 numFmt 교체와 동일하다.
122
+ return this.add(style);
123
+ }
124
+ addDxf(style) {
125
+ if (this._raw != null)
126
+ throw new Error(READONLY_WRITE);
127
+ const key = JSON.stringify(style);
128
+ const idx = this._dxfs.findIndex((d) => JSON.stringify(d) === key);
129
+ if (idx >= 0)
130
+ return idx.toString();
131
+ this._dxfs.push(style);
132
+ return (this._dxfs.length - 1).toString();
133
+ }
134
+ /** @internal 테스트용 — 디코드된 dxf 목록. */
135
+ get dxfs() {
136
+ return this._dxfs;
137
+ }
138
+ setDefaultStyle() {
139
+ throw new Error(STYLE_WRITE_LIMIT);
140
+ }
141
+ _setNumFmtCode(code) {
142
+ for (const [id, c] of this._numFmts) {
143
+ if (c === code)
144
+ return id;
145
+ }
146
+ // 사용자 정의 numFmt 는 180+ 부터.
147
+ let next = 180;
148
+ while (this._numFmts.has(next))
149
+ next++;
150
+ this._numFmts.set(next, code);
151
+ return next;
152
+ }
153
+ serialize() {
154
+ if (this._raw != null)
155
+ return this._raw;
156
+ const parts = [encodeMarker(REC.BrtBeginStyleSheet)];
157
+ if (this._numFmts.size > 0) {
158
+ parts.push(encodeBeginCount(REC.BrtBeginFmts, this._numFmts.size));
159
+ for (const [id, code] of this._numFmts)
160
+ parts.push(encodeBrtFmt(id, code));
161
+ parts.push(encodeMarker(REC.BrtEndFmts));
162
+ }
163
+ parts.push(encodeBeginCount(REC.BrtBeginFonts, 1), encodeRecord(REC.BrtFont, SLOT_FONT), encodeMarker(REC.BrtEndFonts));
164
+ parts.push(encodeBeginCount(REC.BrtBeginFills, 2), encodeRecord(REC.BrtFill, SLOT_FILL_NONE), encodeRecord(REC.BrtFill, SLOT_FILL_GRAY125), encodeMarker(REC.BrtEndFills));
165
+ parts.push(encodeBeginCount(REC.BrtBeginBorders, 1), encodeRecord(REC.BrtBorder, SLOT_BORDER), encodeMarker(REC.BrtEndBorders));
166
+ parts.push(encodeBeginCount(REC.BrtBeginCellStyleXFs, 1), encodeRecord(REC.BrtXF, SLOT_CELLSTYLEXF), encodeMarker(REC.BrtEndCellStyleXFs));
167
+ parts.push(encodeBeginCount(REC.BrtBeginCellXFs, this._cellXfNumFmtIds.length));
168
+ for (const numFmtId of this._cellXfNumFmtIds)
169
+ parts.push(encodeCellXF(numFmtId));
170
+ parts.push(encodeMarker(REC.BrtEndCellXFs));
171
+ if (this._dxfs.length > 0) {
172
+ parts.push(encodeBeginCount(REC.BrtBeginDXFs, this._dxfs.length));
173
+ for (const d of this._dxfs) {
174
+ parts.push(encodeBrtDXF(d.background, d.fontColor, d.fontWeight === "bold"));
175
+ }
176
+ parts.push(encodeMarker(REC.BrtEndDXFs));
177
+ }
178
+ parts.push(encodeMarker(REC.BrtEndStyleSheet));
179
+ return concatBytes(parts);
180
+ }
181
+ }
182
+ //# sourceMappingURL=biff-style-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biff-style-model.js","sourceRoot":"","sources":["../../src/biff/biff-style-model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Bytes } from "@simplysm/core-common";
2
+ import type { IWorkbookModel } from "../models/i-workbook-model";
3
+ /** workbook.bin (BIFF12) 읽기 모델. 시트 목록·관계 ID 조회. */
4
+ export declare class BiffWorkbookModel implements IWorkbookModel {
5
+ private readonly _sheets;
6
+ constructor(bytes?: Bytes);
7
+ get sheetNames(): string[];
8
+ get lastWsRelId(): number | undefined;
9
+ getWsRelIdByName(name: string): number | undefined;
10
+ getWsRelIdByIndex(index: number): number | undefined;
11
+ getWorksheetNameById(id: number): string | undefined;
12
+ addWorksheet(name: string): this;
13
+ setWorksheetNameById(): void;
14
+ initializeView(): void;
15
+ serialize(): Bytes;
16
+ }
17
+ //# sourceMappingURL=biff-workbook-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biff-workbook-model.d.ts","sourceRoot":"","sources":["../../src/biff/biff-workbook-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAcjE,mDAAmD;AACnD,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;gBAEhD,KAAK,CAAC,EAAE,KAAK;IAIzB,IAAI,UAAU,IAAI,MAAM,EAAE,CAEzB;IAED,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAOpC;IAED,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKlD,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKpD,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKpD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMhC,oBAAoB,IAAI,IAAI;IAI5B,cAAc,IAAI,IAAI;IAItB,SAAS,IAAI,KAAK;CAiBnB"}
@@ -0,0 +1,64 @@
1
+ import { concatBytes, REC } from "./biff12-codec.js";
2
+ import { encodeBrtBookView, encodeBrtBundleSh, encodeBrtFileVersion, encodeBrtWbProp, encodeMarker, parseRelId, readWorkbookSheets, } from "./biff-records.js";
3
+ const WRITE_NOT_SUPPORTED = "xlsb 쓰기는 아직 지원되지 않습니다 (Stage 3 이후 예정).";
4
+ /** workbook.bin (BIFF12) 읽기 모델. 시트 목록·관계 ID 조회. */
5
+ export class BiffWorkbookModel {
6
+ _sheets;
7
+ constructor(bytes) {
8
+ this._sheets = bytes != null ? readWorkbookSheets(bytes) : [];
9
+ }
10
+ get sheetNames() {
11
+ return this._sheets.map((s) => s.name);
12
+ }
13
+ get lastWsRelId() {
14
+ let max;
15
+ for (const s of this._sheets) {
16
+ const n = parseRelId(s.relId);
17
+ if (n != null && (max == null || n > max))
18
+ max = n;
19
+ }
20
+ return max;
21
+ }
22
+ getWsRelIdByName(name) {
23
+ const s = this._sheets.find((x) => x.name === name);
24
+ return s != null ? parseRelId(s.relId) : undefined;
25
+ }
26
+ getWsRelIdByIndex(index) {
27
+ if (index < 0 || index >= this._sheets.length)
28
+ return undefined;
29
+ return parseRelId(this._sheets[index].relId);
30
+ }
31
+ getWorksheetNameById(id) {
32
+ const s = this._sheets.find((x) => parseRelId(x.relId) === id);
33
+ return s?.name;
34
+ }
35
+ addWorksheet(name) {
36
+ const relId = (this.lastWsRelId ?? 0) + 1;
37
+ this._sheets.push({ name, relId: `rId${relId}` });
38
+ return this;
39
+ }
40
+ setWorksheetNameById() {
41
+ throw new Error(WRITE_NOT_SUPPORTED);
42
+ }
43
+ initializeView() {
44
+ // xlsb 는 별도 bookView 초기화가 필요 없다(기본 bookView 사용). no-op.
45
+ }
46
+ serialize() {
47
+ const parts = [
48
+ encodeMarker(REC.BrtBeginBook),
49
+ encodeBrtFileVersion(),
50
+ encodeBrtWbProp(),
51
+ encodeMarker(REC.BrtBeginBookViews),
52
+ encodeBrtBookView(),
53
+ encodeMarker(REC.BrtEndBookViews),
54
+ encodeMarker(REC.BrtBeginBundleShs),
55
+ ];
56
+ for (let i = 0; i < this._sheets.length; i++) {
57
+ // iTabID 는 1-base 고유 탭 id (0 은 Excel 이 무효로 보고 복구한다).
58
+ parts.push(encodeBrtBundleSh(this._sheets[i].relId, this._sheets[i].name, i + 1));
59
+ }
60
+ parts.push(encodeMarker(REC.BrtEndBundleShs), encodeMarker(REC.BrtEndBook));
61
+ return concatBytes(parts);
62
+ }
63
+ }
64
+ //# sourceMappingURL=biff-workbook-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biff-workbook-model.js","sourceRoot":"","sources":["../../src/biff/biff-workbook-model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import type { Bytes } from "@simplysm/core-common";
2
+ import type { IWorksheetModel } from "../models/i-worksheet-model";
3
+ import type { ICfRuleSpec } from "../models/shared/excel-cf-spec";
4
+ import type { ExcelAddressPoint, ExcelAddressRangePoint, ExcelCellType } from "../types";
5
+ /** worksheets/sheetN.bin (BIFF12) 읽기 모델. 셀 값/타입/범위 조회. */
6
+ export declare class BiffWorksheetModel implements IWorksheetModel {
7
+ private readonly _cellMap;
8
+ private readonly _merges;
9
+ private readonly _cfs;
10
+ private readonly _formulas;
11
+ private readonly _colWidths;
12
+ private _autoFilter;
13
+ private _zoom;
14
+ private _freeze;
15
+ private _tabColor;
16
+ private _drawingRelId;
17
+ private _maxRow;
18
+ private _maxCol;
19
+ constructor(bytes?: Bytes);
20
+ private _decode;
21
+ /**
22
+ * BrtBeginCFRule([MS-XLSB] 2.4.23) payload → CF 규칙 spec.
23
+ * cellIs/expression/text 만 복원. 미지원 rgce(함수 등)는 decodeFormula 실패 시 formula 를 비움
24
+ * (외부 파일 best-effort 읽기 — 셀 데이터 보존 우선).
25
+ */
26
+ private _decodeCfRule;
27
+ get range(): ExcelAddressRangePoint;
28
+ getCellVal(addr: ExcelAddressPoint): string | undefined;
29
+ getCellType(addr: ExcelAddressPoint): ExcelCellType | undefined;
30
+ getCellStyleId(addr: ExcelAddressPoint): string | undefined;
31
+ getCellFormula(addr: ExcelAddressPoint): string | undefined;
32
+ getMergeCells(): ExcelAddressRangePoint[];
33
+ setCellType(addr: ExcelAddressPoint, type: ExcelCellType | undefined): void;
34
+ setCellVal(addr: ExcelAddressPoint, val: string | undefined): void;
35
+ deleteCell(addr: ExcelAddressPoint): void;
36
+ setCellStyleId(addr: ExcelAddressPoint, styleId: string | undefined): void;
37
+ setCellFormula(addr: ExcelAddressPoint, val: string | undefined): void;
38
+ private _grow;
39
+ setMergeCells(startAddr: ExcelAddressPoint, endAddr: ExcelAddressPoint): void;
40
+ shiftMergeCells(fromRow: number, delta: number): void;
41
+ copyRow(sourceR: number, targetR: number, options?: {
42
+ skipMerge?: boolean;
43
+ }): void;
44
+ copyCell(sourceAddr: ExcelAddressPoint, targetAddr: ExcelAddressPoint): void;
45
+ addConditionalFormatting(sqref: string, rules: {
46
+ dxfId: string;
47
+ cfRule: ICfRuleSpec;
48
+ }[]): void;
49
+ /** @internal 테스트용 — 디코드된 조건부 서식. */
50
+ get conditionalFormats(): {
51
+ sqref: string;
52
+ rules: {
53
+ dxfId: string;
54
+ cfRule: ICfRuleSpec;
55
+ }[];
56
+ }[];
57
+ setTabColor(rgb: string): void;
58
+ setZoom(percent: number): void;
59
+ freezeAt(point: {
60
+ r?: number;
61
+ c?: number;
62
+ }): void;
63
+ setAutoFilter(range: ExcelAddressRangePoint): void;
64
+ setColWidth(colIndex: string, width: string): void;
65
+ setDrawingRelId(relId: string): void;
66
+ serialize(): Bytes;
67
+ private _encodeCell;
68
+ }
69
+ //# sourceMappingURL=biff-worksheet-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biff-worksheet-model.d.ts","sourceRoot":"","sources":["../../src/biff/biff-worksheet-model.ts"],"names":[],"mappings":"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"}