@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 @@
1
+ {"version":3,"file":"xml-model-factory.d.ts","sourceRoot":"","sources":["../../src/xml/xml-model-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAmBnE,qCAAqC;AACrC,qBAAa,eAAgB,YAAW,kBAAkB;IACxD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAU;IAEtC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAItC,cAAc,IAAI,cAAc;IAGhC,eAAe,IAAI,eAAe;IAGlC,WAAW,IAAI,WAAW;IAG1B,kBAAkB,IAAI,kBAAkB;IAGxC,iBAAiB,IAAI,iBAAiB;IAGtC,kBAAkB,IAAI,kBAAkB;IAGxC,aAAa,IAAI,aAAa;IAI9B,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,WAAW;CAsBnD"}
@@ -0,0 +1,66 @@
1
+ import { xml as xmlU } from "@simplysm/core-common";
2
+ import { ExcelXmlContentType } from "./excel-xml-content-type.js";
3
+ import { ExcelXmlDrawing } from "./excel-xml-drawing.js";
4
+ import { ExcelXmlRelationship } from "./excel-xml-relationship.js";
5
+ import { ExcelXmlSharedString } from "./excel-xml-shared-string.js";
6
+ import { ExcelXmlStyle } from "./excel-xml-style.js";
7
+ import { ExcelXmlUnknown } from "./excel-xml-unknown.js";
8
+ import { ExcelXmlWorkbook } from "./excel-xml-workbook.js";
9
+ import { ExcelXmlWorksheet } from "./excel-xml-worksheet.js";
10
+ /** xlsx(OOXML XML) 포맷의 파트 모델 팩토리. */
11
+ export class XmlModelFactory {
12
+ format = "xlsx";
13
+ isModelPart(filePath) {
14
+ return filePath.endsWith(".xml") || filePath.endsWith(".rels");
15
+ }
16
+ createWorkbook() {
17
+ return new ExcelXmlWorkbook();
18
+ }
19
+ createWorksheet() {
20
+ return new ExcelXmlWorksheet();
21
+ }
22
+ createStyle() {
23
+ return new ExcelXmlStyle();
24
+ }
25
+ createSharedString() {
26
+ return new ExcelXmlSharedString();
27
+ }
28
+ createContentType() {
29
+ return new ExcelXmlContentType();
30
+ }
31
+ createRelationship() {
32
+ return new ExcelXmlRelationship();
33
+ }
34
+ createDrawing() {
35
+ return new ExcelXmlDrawing();
36
+ }
37
+ parse(filePath, bytes) {
38
+ const fileText = new TextDecoder().decode(bytes);
39
+ const xml = xmlU.parse(fileText, { stripTagPrefix: true });
40
+ if (filePath.endsWith(".rels")) {
41
+ return new ExcelXmlRelationship(xml);
42
+ }
43
+ else if (filePath === "[Content_Types].xml") {
44
+ return new ExcelXmlContentType(xml);
45
+ }
46
+ else if (filePath === "xl/workbook.xml") {
47
+ return new ExcelXmlWorkbook(xml);
48
+ }
49
+ else if (filePath.startsWith("xl/worksheets/sheet") && filePath.endsWith(".xml")) {
50
+ return new ExcelXmlWorksheet(xml);
51
+ }
52
+ else if (filePath.startsWith("xl/drawings/drawing") && filePath.endsWith(".xml")) {
53
+ return new ExcelXmlDrawing(xml);
54
+ }
55
+ else if (filePath === "xl/sharedStrings.xml") {
56
+ return new ExcelXmlSharedString(xml);
57
+ }
58
+ else if (filePath === "xl/styles.xml") {
59
+ return new ExcelXmlStyle(xml);
60
+ }
61
+ else {
62
+ return new ExcelXmlUnknown(xml);
63
+ }
64
+ }
65
+ }
66
+ //# sourceMappingURL=xml-model-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xml-model-factory.js","sourceRoot":"","sources":["../../src/xml/xml-model-factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,IAAI,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAoBpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,qCAAqC;AACrC,MAAM,OAAO,eAAe;IACjB,MAAM,GAAgB,MAAM,CAAC;IAEtC,WAAW,CAAC,QAAgB;QAC1B,OAAO,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjE,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,gBAAgB,EAAE,CAAC;IAChC,CAAC;IACD,eAAe;QACb,OAAO,IAAI,iBAAiB,EAAE,CAAC;IACjC,CAAC;IACD,WAAW;QACT,OAAO,IAAI,aAAa,EAAE,CAAC;IAC7B,CAAC;IACD,kBAAkB;QAChB,OAAO,IAAI,oBAAoB,EAAE,CAAC;IACpC,CAAC;IACD,iBAAiB;QACf,OAAO,IAAI,mBAAmB,EAAE,CAAC;IACnC,CAAC;IACD,kBAAkB;QAChB,OAAO,IAAI,oBAAoB,EAAE,CAAC;IACpC,CAAC;IACD,aAAa;QACX,OAAO,IAAI,eAAe,EAAE,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,QAAgB,EAAE,KAAY;QAClC,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;QAE3D,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,oBAAoB,CAAC,GAA+B,CAAC,CAAC;QACnE,CAAC;aAAM,IAAI,QAAQ,KAAK,qBAAqB,EAAE,CAAC;YAC9C,OAAO,IAAI,mBAAmB,CAAC,GAA8B,CAAC,CAAC;QACjE,CAAC;aAAM,IAAI,QAAQ,KAAK,iBAAiB,EAAE,CAAC;YAC1C,OAAO,IAAI,gBAAgB,CAAC,GAA2B,CAAC,CAAC;QAC3D,CAAC;aAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACnF,OAAO,IAAI,iBAAiB,CAAC,GAA4B,CAAC,CAAC;QAC7D,CAAC;aAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACnF,OAAO,IAAI,eAAe,CAAC,GAA0B,CAAC,CAAC;QACzD,CAAC;aAAM,IAAI,QAAQ,KAAK,sBAAsB,EAAE,CAAC;YAC/C,OAAO,IAAI,oBAAoB,CAAC,GAA+B,CAAC,CAAC;QACnE,CAAC;aAAM,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;YACxC,OAAO,IAAI,aAAa,CAAC,GAAwB,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,eAAe,CAAC,GAA8B,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/excel",
3
- "version": "14.0.99",
3
+ "version": "14.0.101",
4
4
  "description": "심플리즘 패키지 - 엑셀 (neutral)",
5
5
  "author": "심플리즘",
6
6
  "license": "Apache-2.0",
@@ -23,6 +23,6 @@
23
23
  "dependencies": {
24
24
  "mime": "^4.1.0",
25
25
  "zod": "^4.4.3",
26
- "@simplysm/core-common": "14.0.99"
26
+ "@simplysm/core-common": "14.0.101"
27
27
  }
28
28
  }
@@ -0,0 +1,101 @@
1
+ import type { Bytes } from "@simplysm/core-common";
2
+ import type { ExcelFormat } from "../models/excel-format";
3
+ import type { IExcelModel } from "../models/excel-model";
4
+ import type { IExcelModelFactory } from "../models/excel-model-factory";
5
+ import type { IContentTypeModel } from "../models/i-content-type-model";
6
+ import type { IDrawingModel } from "../models/i-drawing-model";
7
+ import type { IRelationshipModel } from "../models/i-relationship-model";
8
+ import type { ISharedStringModel } from "../models/i-shared-string-model";
9
+ import type { IStyleModel } from "../models/i-style-model";
10
+ import type { IWorkbookModel } from "../models/i-workbook-model";
11
+ import type { IWorksheetModel } from "../models/i-worksheet-model";
12
+ import type { ExcelXmlContentTypeData } from "../types";
13
+ import { ExcelXmlContentType } from "../xml/excel-xml-content-type";
14
+ import { ExcelXmlDrawing } from "../xml/excel-xml-drawing";
15
+ import { ExcelXmlRelationship } from "../xml/excel-xml-relationship";
16
+ import { XmlModelFactory } from "../xml/xml-model-factory";
17
+ import { BiffSharedStringModel } from "./biff-shared-string-model";
18
+ import { BiffStyleModel } from "./biff-style-model";
19
+ import { BiffWorkbookModel } from "./biff-workbook-model";
20
+ import { BiffWorksheetModel } from "./biff-worksheet-model";
21
+
22
+ /** 새 xlsb 워크북의 [Content_Types].xml 기본 골격. workbook.bin 은 Default bin(main) 으로 매핑된다. */
23
+ function createXlsbContentTypeData(): ExcelXmlContentTypeData {
24
+ return {
25
+ Types: {
26
+ $: { xmlns: "http://schemas.openxmlformats.org/package/2006/content-types" },
27
+ Default: [
28
+ {
29
+ $: {
30
+ Extension: "bin",
31
+ ContentType: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
32
+ },
33
+ },
34
+ {
35
+ $: {
36
+ Extension: "rels",
37
+ ContentType: "application/vnd.openxmlformats-package.relationships+xml",
38
+ },
39
+ },
40
+ { $: { Extension: "xml", ContentType: "application/xml" } },
41
+ ],
42
+ Override: [],
43
+ },
44
+ };
45
+ }
46
+
47
+ /**
48
+ * xlsb(BIFF12) 포맷의 파트 모델 팩토리.
49
+ *
50
+ * - workbook/sharedStrings/worksheet `.bin` → BIFF12 모델로 디코드.
51
+ * - `[Content_Types].xml`·`*.rels`·drawing `.xml` → xlsb 도 OOXML XML 이므로 `XmlModelFactory` 에 위임.
52
+ * - styles.bin 은 Stage 4 까지 모델로 다루지 않음(원시 바이트 passthrough).
53
+ */
54
+ export class BiffModelFactory implements IExcelModelFactory {
55
+ readonly format: ExcelFormat = "xlsb";
56
+ private readonly _xml = new XmlModelFactory();
57
+
58
+ isModelPart(filePath: string): boolean {
59
+ if (filePath.endsWith(".rels") || filePath.endsWith(".xml")) return true;
60
+ if (
61
+ filePath === "xl/workbook.bin" ||
62
+ filePath === "xl/sharedStrings.bin" ||
63
+ filePath === "xl/styles.bin"
64
+ ) {
65
+ return true;
66
+ }
67
+ return /^xl\/worksheets\/sheet\d+\.bin$/.test(filePath);
68
+ }
69
+
70
+ parse(filePath: string, bytes: Bytes): IExcelModel {
71
+ if (filePath === "xl/workbook.bin") return new BiffWorkbookModel(bytes);
72
+ if (filePath === "xl/sharedStrings.bin") return new BiffSharedStringModel(bytes);
73
+ if (filePath === "xl/styles.bin") return new BiffStyleModel(bytes);
74
+ if (/^xl\/worksheets\/sheet\d+\.bin$/.test(filePath)) return new BiffWorksheetModel(bytes);
75
+ // .xml / .rels / [Content_Types].xml → XML 위임
76
+ return this._xml.parse(filePath, bytes);
77
+ }
78
+
79
+ createWorkbook(): IWorkbookModel {
80
+ return new BiffWorkbookModel();
81
+ }
82
+ createWorksheet(): IWorksheetModel {
83
+ return new BiffWorksheetModel();
84
+ }
85
+ createStyle(): IStyleModel {
86
+ return new BiffStyleModel();
87
+ }
88
+ createSharedString(): ISharedStringModel {
89
+ return new BiffSharedStringModel();
90
+ }
91
+ // [Content_Types].xml·*.rels·drawing 은 xlsb 도 XML → xml 구현 재사용.
92
+ createContentType(): IContentTypeModel {
93
+ return new ExcelXmlContentType(createXlsbContentTypeData());
94
+ }
95
+ createRelationship(): IRelationshipModel {
96
+ return new ExcelXmlRelationship();
97
+ }
98
+ createDrawing(): IDrawingModel {
99
+ return new ExcelXmlDrawing();
100
+ }
101
+ }
@@ -0,0 +1,289 @@
1
+ /**
2
+ * BIFF12 수식 Ptg 토큰 (부분집합) 인코더/디코더.
3
+ *
4
+ * 지원: 정수/실수 상수, 문자열 상수("..."), 단일 셀 참조(A1/$A$1), 이항 연산(+ - * / ^ & = < > <= >= <>),
5
+ * 단항 마이너스, 괄호. 함수 호출·범위(A1:B2)·시트 참조 등은 미지원 → throw.
6
+ *
7
+ * Ptg ID 는 [MS-XLS] 2.5.198 / [MS-XLSB] 2.5.97 기준. 셀참조 loc 는 BIFF12 RgceLoc
8
+ * (row u32 + col u16{col14b, fColRel, fRowRel}). 문자열/프레이밍은 인코더↔디코더 자기일관.
9
+ */
10
+
11
+ const PTG = {
12
+ Add: 0x03,
13
+ Sub: 0x04,
14
+ Mul: 0x05,
15
+ Div: 0x06,
16
+ Power: 0x07,
17
+ Concat: 0x08,
18
+ Lt: 0x09,
19
+ Le: 0x0a,
20
+ Eq: 0x0b,
21
+ Ge: 0x0c,
22
+ Gt: 0x0d,
23
+ Ne: 0x0e,
24
+ UMinus: 0x13,
25
+ Str: 0x17,
26
+ Int: 0x1e,
27
+ Num: 0x1f,
28
+ Ref: 0x24,
29
+ } as const;
30
+
31
+ const BIN_OP: Record<string, { ptg: number; prec: number }> = {
32
+ "=": { ptg: PTG.Eq, prec: 1 },
33
+ "<>": { ptg: PTG.Ne, prec: 1 },
34
+ "<=": { ptg: PTG.Le, prec: 1 },
35
+ ">=": { ptg: PTG.Ge, prec: 1 },
36
+ "<": { ptg: PTG.Lt, prec: 1 },
37
+ ">": { ptg: PTG.Gt, prec: 1 },
38
+ "&": { ptg: PTG.Concat, prec: 2 },
39
+ "+": { ptg: PTG.Add, prec: 3 },
40
+ "-": { ptg: PTG.Sub, prec: 4 - 1 },
41
+ "*": { ptg: PTG.Mul, prec: 4 },
42
+ "/": { ptg: PTG.Div, prec: 4 },
43
+ "^": { ptg: PTG.Power, prec: 5 },
44
+ };
45
+ const PTG_TO_OP = new Map<number, string>(
46
+ Object.entries(BIN_OP).map(([op, v]) => [v.ptg, op]),
47
+ );
48
+ const PTG_TO_PREC = new Map<number, number>(
49
+ Object.entries(BIN_OP).map(([, v]) => [v.ptg, v.prec]),
50
+ );
51
+
52
+ type Tok =
53
+ | { k: "num"; v: number }
54
+ | { k: "str"; v: string }
55
+ | { k: "ref"; v: string }
56
+ | { k: "op"; v: string }
57
+ | { k: "("; v: "(" }
58
+ | { k: ")"; v: ")" };
59
+
60
+ function tokenize(formula: string): Tok[] {
61
+ const out: Tok[] = [];
62
+ let i = 0;
63
+ const s = formula;
64
+ while (i < s.length) {
65
+ const ch = s[i];
66
+ if (ch === " ") {
67
+ i++;
68
+ continue;
69
+ }
70
+ if (ch === "(") {
71
+ out.push({ k: "(", v: "(" });
72
+ i++;
73
+ continue;
74
+ }
75
+ if (ch === ")") {
76
+ out.push({ k: ")", v: ")" });
77
+ i++;
78
+ continue;
79
+ }
80
+ if (ch === '"') {
81
+ let j = i + 1;
82
+ let val = "";
83
+ while (j < s.length) {
84
+ if (s[j] === '"') {
85
+ if (s[j + 1] === '"') {
86
+ val += '"';
87
+ j += 2;
88
+ continue;
89
+ }
90
+ break;
91
+ }
92
+ val += s[j];
93
+ j++;
94
+ }
95
+ out.push({ k: "str", v: val });
96
+ i = j + 1;
97
+ continue;
98
+ }
99
+ const two = s.slice(i, i + 2);
100
+ if (two === "<=" || two === ">=" || two === "<>") {
101
+ out.push({ k: "op", v: two });
102
+ i += 2;
103
+ continue;
104
+ }
105
+ if ("+-*/^&=<>".includes(ch)) {
106
+ out.push({ k: "op", v: ch });
107
+ i++;
108
+ continue;
109
+ }
110
+ const ref = /^\$?[A-Za-z]{1,3}\$?[0-9]+/.exec(s.slice(i));
111
+ if (ref != null && !/[A-Za-z0-9_.]/.test(s[i + ref[0].length] ?? "")) {
112
+ out.push({ k: "ref", v: ref[0].toUpperCase() });
113
+ i += ref[0].length;
114
+ continue;
115
+ }
116
+ const num = /^[0-9]+\.?[0-9]*([eE][+-]?[0-9]+)?/.exec(s.slice(i));
117
+ if (num != null) {
118
+ out.push({ k: "num", v: parseFloat(num[0]) });
119
+ i += num[0].length;
120
+ continue;
121
+ }
122
+ throw new Error(`xlsb 수식: 지원하지 않는 토큰 "${s.slice(i)}" (함수/범위 참조 미지원)`);
123
+ }
124
+ return out;
125
+ }
126
+
127
+ interface RefLoc {
128
+ row: number;
129
+ col: number;
130
+ colRel: boolean;
131
+ rowRel: boolean;
132
+ }
133
+
134
+ function parseRef(ref: string): RefLoc {
135
+ const m = /^(\$?)([A-Z]{1,3})(\$?)([0-9]+)$/.exec(ref);
136
+ if (m == null) throw new Error(`xlsb 수식: 잘못된 셀 참조 "${ref}"`);
137
+ const colRel = m[1] !== "$";
138
+ let col = 0;
139
+ for (const c of m[2]) col = col * 26 + (c.charCodeAt(0) - 64);
140
+ col -= 1;
141
+ const rowRel = m[3] !== "$";
142
+ const row = parseInt(m[4], 10) - 1;
143
+ return { row, col, colRel, rowRel };
144
+ }
145
+
146
+ function colName(col: number): string {
147
+ let n = col + 1;
148
+ let out = "";
149
+ while (n > 0) {
150
+ const r = (n - 1) % 26;
151
+ out = String.fromCharCode(65 + r) + out;
152
+ n = Math.floor((n - 1) / 26);
153
+ }
154
+ return out;
155
+ }
156
+
157
+ /** A1 수식 문자열 → rgce(Ptg 토큰 바이트). 앞의 "=" 는 있어도 무시. */
158
+ export function encodeFormula(formula: string): Uint8Array {
159
+ const f = formula.startsWith("=") ? formula.slice(1) : formula;
160
+ const toks = tokenize(f);
161
+
162
+ // Shunting-yard → RPN(Ptg 출력)
163
+ const out: number[] = [];
164
+ const ops: { ptg: number; prec: number; unary?: boolean }[] = [];
165
+ const emit = (bytes: number[]): void => {
166
+ for (const b of bytes) out.push(b);
167
+ };
168
+ const u16 = (v: number): number[] => [v & 0xff, (v >>> 8) & 0xff];
169
+ const u32 = (v: number): number[] => [
170
+ v & 0xff,
171
+ (v >>> 8) & 0xff,
172
+ (v >>> 16) & 0xff,
173
+ (v >>> 24) & 0xff,
174
+ ];
175
+
176
+ let prevVal = false; // 직전 토큰이 피연산자면 true (단항/이항 구분)
177
+ for (const t of toks) {
178
+ if (t.k === "num") {
179
+ if (Number.isInteger(t.v) && t.v >= 0 && t.v <= 0xffff) {
180
+ emit([PTG.Int, ...u16(t.v)]);
181
+ } else {
182
+ const buf = new Uint8Array(8);
183
+ new DataView(buf.buffer).setFloat64(0, t.v, true);
184
+ emit([PTG.Num, ...buf]);
185
+ }
186
+ prevVal = true;
187
+ } else if (t.k === "str") {
188
+ const chars: number[] = [];
189
+ for (const c of t.v) chars.push(...u16(c.charCodeAt(0)));
190
+ emit([PTG.Str, ...u16(t.v.length), ...chars]);
191
+ prevVal = true;
192
+ } else if (t.k === "ref") {
193
+ const loc = parseRef(t.v);
194
+ const colField = (loc.col & 0x3fff) | (loc.colRel ? 0x4000 : 0) | (loc.rowRel ? 0x8000 : 0);
195
+ emit([PTG.Ref, ...u32(loc.row), ...u16(colField)]);
196
+ prevVal = true;
197
+ } else if (t.k === "(") {
198
+ ops.push({ ptg: -1, prec: 0 });
199
+ prevVal = false;
200
+ } else if (t.k === ")") {
201
+ while (ops.length > 0 && ops[ops.length - 1].ptg !== -1) popOp(ops, emit);
202
+ if (ops.length === 0) throw new Error("xlsb 수식: 괄호 불일치");
203
+ ops.pop();
204
+ prevVal = true;
205
+ } else {
206
+ // op
207
+ if (!prevVal && t.v === "-") {
208
+ ops.push({ ptg: PTG.UMinus, prec: 6, unary: true });
209
+ } else {
210
+ if (!(t.v in BIN_OP)) {
211
+ throw new Error(`xlsb 수식: 지원하지 않는 연산자 "${t.v}"`);
212
+ }
213
+ const info = BIN_OP[t.v];
214
+ while (
215
+ ops.length > 0 &&
216
+ ops[ops.length - 1].ptg !== -1 &&
217
+ ops[ops.length - 1].prec >= info.prec
218
+ ) {
219
+ popOp(ops, emit);
220
+ }
221
+ ops.push({ ptg: info.ptg, prec: info.prec });
222
+ }
223
+ prevVal = false;
224
+ }
225
+ }
226
+ while (ops.length > 0) {
227
+ if (ops[ops.length - 1].ptg === -1) throw new Error("xlsb 수식: 괄호 불일치");
228
+ popOp(ops, emit);
229
+ }
230
+ return Uint8Array.from(out);
231
+ }
232
+
233
+ function popOp(
234
+ ops: { ptg: number; prec: number; unary?: boolean }[],
235
+ emit: (b: number[]) => void,
236
+ ): void {
237
+ const op = ops.pop()!;
238
+ emit([op.ptg]);
239
+ }
240
+
241
+ /** rgce(Ptg 토큰 바이트) → A1 수식 문자열 (정규화된 infix). */
242
+ export function decodeFormula(rgce: Uint8Array): string {
243
+ const stack: { str: string; prec: number }[] = [];
244
+ let i = 0;
245
+ const dv = new DataView(rgce.buffer, rgce.byteOffset, rgce.byteLength);
246
+ while (i < rgce.length) {
247
+ const ptg = rgce[i++];
248
+ if (ptg === PTG.Int) {
249
+ stack.push({ str: String(rgce[i] | (rgce[i + 1] << 8)), prec: 99 });
250
+ i += 2;
251
+ } else if (ptg === PTG.Num) {
252
+ stack.push({ str: String(dv.getFloat64(i, true)), prec: 99 });
253
+ i += 8;
254
+ } else if (ptg === PTG.Str) {
255
+ const cch = rgce[i] | (rgce[i + 1] << 8);
256
+ i += 2;
257
+ let str = "";
258
+ for (let k = 0; k < cch; k++) {
259
+ str += String.fromCharCode(rgce[i] | (rgce[i + 1] << 8));
260
+ i += 2;
261
+ }
262
+ stack.push({ str: `"${str.replace(/"/g, '""')}"`, prec: 99 });
263
+ } else if (ptg === PTG.Ref) {
264
+ const row = rgce[i] | (rgce[i + 1] << 8) | (rgce[i + 2] << 16) | (rgce[i + 3] << 24);
265
+ const colField = rgce[i + 4] | (rgce[i + 5] << 8);
266
+ i += 6;
267
+ const col = colField & 0x3fff;
268
+ const colRel = (colField & 0x4000) !== 0;
269
+ const rowRel = (colField & 0x8000) !== 0;
270
+ const a1 = `${colRel ? "" : "$"}${colName(col)}${rowRel ? "" : "$"}${row + 1}`;
271
+ stack.push({ str: a1, prec: 99 });
272
+ } else if (ptg === PTG.UMinus) {
273
+ const a = stack.pop()!;
274
+ stack.push({ str: `-${a.prec < 6 ? `(${a.str})` : a.str}`, prec: 6 });
275
+ } else if (PTG_TO_OP.has(ptg)) {
276
+ const prec = PTG_TO_PREC.get(ptg)!;
277
+ const op = PTG_TO_OP.get(ptg)!;
278
+ const b = stack.pop()!;
279
+ const a = stack.pop()!;
280
+ const left = a.prec < prec ? `(${a.str})` : a.str;
281
+ const right = b.prec <= prec ? `(${b.str})` : b.str;
282
+ stack.push({ str: `${left}${op}${right}`, prec });
283
+ } else {
284
+ throw new Error(`xlsb 수식: 디코드 미지원 Ptg 0x${ptg.toString(16)}`);
285
+ }
286
+ }
287
+ if (stack.length !== 1) throw new Error("xlsb 수식: 디코드 스택 불일치");
288
+ return stack[0].str;
289
+ }