# 结构、样式与日期解释

需要 `fsys.openXml` 0.15.0+。以下增强均不改变原来的保存值/公式缓存契约，也不创建 Office 进程。

## 精确 A1 矩形

```aardio
import fsys.openXml.xlsx;
var data,err = fsys.openXml.xlsx.readSheet("/input.xlsx",1,{
    range = "$B$3:$M$8";
    includeStructure = true;
    includeStyles = true;
    parseDates = true;
});
if(!data) return null,err;
return data;
```

- `range` 只接受本页单格或有限矩形，支持小写、`$`。不接受工作表前缀、多区域、整行/整列、反向范围。
- 已通过参数 2 选择工作表，因此区域不带页名。`parseRange(ref)` 可独立解析/验证，返回规范 `ref,startRow,startColumn,endRow,endColumn,rowCount,columnCount`。
- `range` 不能和 `row/startRow/column/startColumn` 同时指定；`maxRows/maxColumns` 可进一步限制所选矩形，0 表示不取。
- 显式矩形保持空边界，即使空页上的 `B3:C4` 也返回 2×2 的 null 矩形；无 range 时仍按实际已存储 `<c>` 节点的边界读取。
- `actualRange` 是整页所有已存储格（含样式空格）的边界；`dimension` 是文件声明值；`selectedRange` 是返回矩形。三者互不代替。无格/空选区的相关范围为 null。
- 选择源数据子集或进一步限额会设 `truncated=true`。这是读取契约，不是“查询是否完整扫描指定选区”的含义；查询另用 `scanComplete`。

## 结构元信息

`includeStructure=true` 增加 `data.structure` 和 `data.definedNames`。整簿入口的顶层也有 `definedNames`。**结构描述是整页/整簿的，不受矩形行列限额过滤。**

| 字段 | 内容 |
|---|---|
| `structure.merges` | `ref`、起止行列、尺寸、左上角 `anchor` |
| `structure.rows` | 按源顺序记录已保存行的 `row,hidden,height,customHeight,styleIndex,customFormat,outlineLevel,collapsed` |
| `structure.columns` | 区间 `min,max,hidden,width,styleIndex,customWidth,outlineLevel,collapsed` |
| `defaultRowHidden/defaultRowHeight/defaultColumnWidth` | 保存的工作表默认行列属性 |
| `structure.tables` | 按本页关系读取的表对象：`name,displayName,id,partName,ref,range,headerRowCount,totalsRowCount,totalsRowShown,columns` |
| `structure.autoFilterRef` | 保存的自动筛选范围，**不执行筛选条件** |
| `definedNames` | `name,expression,scope,hidden,resolved`，本地名称有 1 起始 `sheetIndex` |

行高单位为 point；列宽是 Excel 保存的字符宽单位，不换算像素。行的 `hidden=null` 表示未显式指定，可使用 `defaultRowHidden`；列区间保留源顺序，重叠时查询使用后面的定义覆盖前面的定义。

名称只解析单个普通静态 A1 区域：成功时有 `range,targetSheetIndex,targetSheet`；支持带引号和双单引号转义的页名、本地名称的不带页名前缀引用。动态公式、联合范围、结构化引用、外部工作簿引用仅保留表达式，`resolved=false`，不求值、不访问外部资源。可以将已解析名称的 `targetSheetIndex` 和 `range.ref` 显式传给读取/查询入口。

表对象只提供元信息，不重算计算列或汇总行。缺失、外部或错误类型的表关系在请求结构时失败。合并格不复制主格值，不把隐藏行列与不存在的数据混为一谈。

## 保存样式

`includeStyles=true` 给返回的每个 cell 增加 `style`：

- `index,numFmtId,formatCode,formatKind,custom,xfId,applyNumberFormat`；
- 保存的 `fontId,font,alignment,fillId,borderId`；
- `font` 提供名称、字号、b/i/strike、下划线和颜色属性；颜色保留 rgb/theme/indexed/tint 等原始来源，不解析主题最终颜色；
- `alignment` 的水平/垂直对齐、换行等仍是原始属性字符串。

索引来自单元格 `s`，未指定按 cellXfs[0]；数字格式在有 xfId、明确 `applyNumberFormat=false` 时使用基样式。这里只解释保存的单元格 XF 子集，**不计算行列默认样式、条件格式、表样式、主题等叠加后的最终外观**；行列样式可通过结构信息另行检查。字体/对齐不是完整继承后的最终样式。

样式部件按需读取，并在一个 `readWorkbook` 调用内复用。默认原始读取不加载 styles.xml，因此旧读取行为保持不变；主动请求增强时会报告损坏样式/越界索引。

## 可选日期解释

`parseDates=true` 同时启用样式描述，只附加 `cell.interpretation`，**不修改 `cell.value/raw`，也不改变 `rows` 的数字值**。

| formatKind | interpretation |
|---|---|
| `date` | `kind,serial,dateSystem,iso,year,month,day,secondsOfDay` |
| `datetime` | 同上，ISO 含 `T` 和时分秒 |
| `time` | ISO 为时分秒，整数天不拼成日期；保留 `secondsOfDay` |
| `duration` | `kind,serial,totalSeconds`，允许负数和超过24小时 |
| `percentage/number/general/text/unsupported` | 不产生日期解释，保留原始值 |

- 同时支持 1900/1904 基准；序号 60 在 1900 系统表示 Excel 虚构的 `1900-02-29`，附 `isLeapDay1900=true` 和警告，不伪造正常公历时间对象。`secondsOfDay` 保留小数天信息，即便 date 格式的 ISO 不含时间。
- 1900 系统序号 0 在本解释器中是 `1899-12-31`，不是 Excel UI 的特殊“0日”显示。负日期序号不解释并警告；日期上限为9999年。累计时长不使用此日期上限。
- ISO 为**无时区的民用日期/时间**，不自动转 UTC，不经过本地夏令时，秒最多保留三位小数。不根据 Excel 日期格式决定 ISO 的排版。
- 常见内建日期/时间格式以及明确的单节自定义 `yyyy-mm-dd`、`hh:mm:ss`、`[h]:mm` 可解释；条件、多节、颜色/本地化等复杂自定义格式保留 `formatCode` 并警告为 unsupported，不猜最终显示字符串。
- 百分比 `0.25` 仍是 `0.25`，不是数值 `25`。`t="d"` 保留原有 ISO 字符串，不进行第二次序号转换。
- 公式日期只解释保存的缓存，不代表缓存最新。

需要 Excel/WPS **完全一致的显示文本**或公式重算时仍走 COM。

## 有界预览与摘要

```aardio
import fsys.openXml.xlsx;
var book,err = fsys.openXml.xlsx.inspectWorkbook("/input.xlsx",{
    maxSheets=3;maxRows=20;maxColumns=16;
});
if(!book) return null,err;
return book;
```

默认最多20表/20行/20列，自动开启结构、样式、日期解释。各页增加：

- `summary.scope="stored-cells-whole-sheet"`；`cellCount,valueCount,formulaCount,missingCacheCount,errorCount,storedRowCount` 统计整页已存储节点，不受预览矩形截取影响。
- `headerCandidates` 最多3个候选，按预览中的非空字符串数量、原始行号排序；含 `row,stringCells,sample`（最多8个文本）。这只是候选，查询不会自动拿它当表头。

预览矩形有界，但完整结构元信息仍受包/XML安全预算约束；不是只读取文件前几行，更不是流式解析。整簿坏页的 `keepErrors`、`partial`、`complete` 规则与 readWorkbook 相同。
