feat: integrate luckysheet inline and fullscreen

This commit is contained in:
liaibo
2025-11-23 17:22:35 +08:00
parent c8e479aeab
commit 994dd4e67c
529 changed files with 403413 additions and 201 deletions
@@ -0,0 +1,176 @@
/**
* config border info model 边框数据模型
*/
import { WorkerSheetModel } from "./WorkerSheet";
import { DataTypes, InferAttributes, Model, Sequelize } from "sequelize";
export class BorderInfoModel extends Model {
// 类型定义
declare config_border_id?: string;
declare worker_sheet_id: string;
declare rangeType: string; /** rangeType 合并单元格类型 range | cell */
declare borderType?: string; /** borderType 边框类型 */
declare style?: number; /** style 边框粗细 */
declare color?: string; /** color 边框颜色 */
// 范围
declare row_start?: number;
declare row_end?: number;
declare col_start?: number;
declare col_end?: number;
// 单个单元格
declare row_index?: number;
declare col_index?: number;
declare l_style?: number;
declare l_color?: string;
declare t_style?: number;
declare t_color?: string;
declare r_style?: number;
declare r_color?: string;
declare b_style?: number;
declare b_color?: string;
// 注册模型
static registerModule(sequelize: Sequelize) {
BorderInfoModel.init(
{
config_border_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "config_border_id 边框配置表唯一ID", // 描述
primaryKey: true,
defaultValue: DataTypes.UUIDV4, // 默认使用 uuid 作为 主键ID
},
worker_sheet_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "外键:关联 workersheets 的 worker_sheet_id", // 描述
references: {
model: WorkerSheetModel,
key: "worker_sheet_id",
},
},
rangeType: {
type: DataTypes.STRING,
allowNull: false,
comment: "rangeType 合并单元格类型 range | cell",
},
// 因此,下列属性需要兼容 range cell 不同类型的合并属性
borderType: {
type: DataTypes.STRING,
allowNull: true,
comment: "borderType 边框类型",
},
style: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "style 边框粗细",
},
color: {
type: DataTypes.STRING,
allowNull: true,
comment: "color 边框颜色",
},
/**
* range 行列信息数组
* "range": [{
* "row": [row_start, roe_end],
* "column": [col_start, col_end]
* }]
*/
row_start: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "row_start 行号",
},
row_end: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "row_end 行号",
},
col_start: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "col_start 列号",
},
col_end: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "col_end 列号",
},
/**
* {
* "row_index":7,
* "col_index":6,
* "l":{"style":1,"color":"#000000"},
* "r":{"style":1,"color":"#000000"},
* "t":{"style":1,"color":"#000000"},
* "b":{"style":1,"color":"#000000"}
* }
*/
row_index: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "row_index 行号",
},
col_index: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "col_index 列号",
},
l_style: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "l_style 边框粗细",
},
l_color: {
type: DataTypes.STRING,
allowNull: true,
comment: "l_color 边框颜色",
},
t_style: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "t_style 边框粗细",
},
t_color: {
type: DataTypes.STRING,
allowNull: true,
comment: "t_color 边框颜色",
},
r_style: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "r_style 边框粗细",
},
r_color: {
type: DataTypes.STRING,
allowNull: true,
comment: "r_color 边框颜色",
},
b_style: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "b_style 边框粗细",
},
b_color: {
type: DataTypes.STRING,
allowNull: true,
comment: "b_color 边框颜色",
},
},
{
sequelize, // 将模型与 Sequelize 实例关联
tableName: "borders", // 直接式提供数据库表名
}
);
}
}
// 导出类型
export type BorderInfoModelType = InferAttributes<BorderInfoModel>;
@@ -0,0 +1,70 @@
/**
* 公式链单独存储
*/
/**
* Config Merges 合并单元格数据模型
*
*/
import { WorkerSheetModel } from "./WorkerSheet";
import { DataTypes, InferAttributes, Model, Sequelize } from "sequelize";
export class CalcChainModel extends Model {
declare calcchain_id?: string;
declare worker_sheet_id: string;
declare r: number;
declare c: number;
declare func: string;
declare pos?: number;
// 注册模型
static registerModule(sequelize: Sequelize) {
CalcChainModel.init(
{
calcchain_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "公式连表 id", // 描述
primaryKey: true,
defaultValue: DataTypes.UUIDV4, // 默认使用 uuid 作为 主键ID
},
worker_sheet_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "外键:关联 worker_sheet_id, sheet index", // 描述
references: {
model: WorkerSheetModel,
key: "worker_sheet_id",
},
},
r: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "行号",
},
c: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "列号",
},
func: {
type: DataTypes.STRING,
allowNull: false,
comment: "公式",
},
pos: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "公式位置",
},
},
{
sequelize, // 将模型与 Sequelize 实例关联
tableName: "calcchains", // 直接式提供数据库表名
}
);
}
}
// 导出类型
export type CalcChainModelType = InferAttributes<CalcChainModel>;
@@ -0,0 +1,184 @@
/**
* CellData 数据模型
*/
import { WorkerSheetModel } from "./WorkerSheet";
import { DataTypes, InferAttributes, Model, Sequelize } from "sequelize";
/**
* Sequelize 模型是 ES6 类. 你可以非常轻松地添加自定义实例或类级别的方法.
*/
export class CellDataModel extends Model {
// 模型字段
declare cell_data_id?: string;
declare worker_sheet_id: string;
declare r: number;
declare c: number;
declare v?: string;
declare m?: string;
declare ctfa?: string;
declare ctt?: string;
declare cts?: string; // inline str
declare bg?: string;
declare ff?: string;
declare fc?: string;
declare fs?: number;
declare bl?: boolean;
declare it?: boolean;
declare cl?: boolean;
declare un?: boolean;
declare vt?: number;
declare ht?: number;
declare f?: string | null;
declare ps?: string | null;
declare tb?: number; // 文本换行方式
// 都需要导出一个 register 方法,用于注册模型
static registerModule(sequelize: Sequelize) {
CellDataModel.init(
{
cell_data_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "cell data id", // 描述
primaryKey: true,
defaultValue: DataTypes.UUIDV4, // 默认使用 uuid 作为 主键ID
},
worker_sheet_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "外键:关联 worksheets 的 worker_sheet_id", // 描述
references: {
model: WorkerSheetModel,
key: "worker_sheet_id",
},
},
r: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "行号",
},
c: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "列号",
},
/** ctfa + ctt ==> ct:{fa,t} 这两个字段共同构成 celldata.ct 字段的值,决定了如何显示单元格内容 */
ctfa: {
type: DataTypes.STRING,
allowNull: false,
comment: "ct:{fa} Format格式的定义串,'General'|'@'|'0'|'0.0'....",
defaultValue: "General",
},
ctt: {
type: DataTypes.STRING,
allowNull: false,
comment: "ct:{t} Type类型,'g'|'s'|'n'....",
defaultValue: "g",
},
cts: {
type: DataTypes.STRING,
allowNull: false,
comment: "ct:{s} inlineStr v 内容整体存储",
defaultValue: "",
},
bg: {
type: DataTypes.STRING,
allowNull: true,
comment: "背景色",
defaultValue: "#FFFFFF",
},
ff: {
type: DataTypes.STRING,
allowNull: true,
comment:
"0 Times New Roman、 1 Arial、2 Tahoma 、3 Verdana、4 微软雅黑、5 宋体(Song)、6 黑体(ST Heiti)、7 楷体(ST Kaiti)、 8 仿宋(ST FangSong)、9 新宋体(ST Song)、10 华文新魏、11 华文行楷、12 华文隶书",
defaultValue: "5",
},
fc: {
type: DataTypes.STRING,
allowNull: true,
comment: "字体颜色",
defaultValue: "#000000",
},
fs: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "字体大小",
defaultValue: 10,
},
bl: {
type: DataTypes.BOOLEAN,
allowNull: true,
comment: "是否加粗",
defaultValue: false,
},
it: {
type: DataTypes.BOOLEAN,
allowNull: true,
comment: "是否斜体",
defaultValue: false,
},
cl: {
type: DataTypes.BOOLEAN,
allowNull: true,
comment: "是否删除线",
defaultValue: false,
},
un: {
type: DataTypes.BOOLEAN,
allowNull: true,
comment: "是否下划线",
defaultValue: false,
},
vt: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "垂直居中 0 中间、1 上、2下",
defaultValue: 0,
},
ht: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "水平居中 0 居中、1 左、2右",
defaultValue: 0,
},
tb: {
type: DataTypes.INTEGER,
allowNull: true,
comment: "文本换行方式 0 自动换行、1 单行、2 多行",
defaultValue: 0,
},
// tr rt 不想实现了~ 大家自己拓展其他的数据类型吧
// v m 的取值逻辑由 ct{fa t} 决定
v: {
type: DataTypes.STRING,
allowNull: false,
comment: "原始值",
},
m: {
type: DataTypes.STRING,
allowNull: false,
comment: "显示值",
},
f: {
type: DataTypes.STRING,
allowNull: true,
comment: "公式",
},
ps: {
type: DataTypes.STRING,
allowNull: true,
comment: "批注",
},
},
{
sequelize, // 将模型与 Sequelize 实例关联
tableName: "celldatas", // 直接式提供数据库表名
}
);
}
}
export type CellDataModelType = InferAttributes<CellDataModel>;
@@ -0,0 +1,84 @@
/**
* 统计图
*/
import { Model, Sequelize, DataTypes, InferAttributes } from "sequelize";
import { WorkerSheetModel } from "./WorkerSheet";
export class ChartModel extends Model {
declare chart_id: string;
declare worker_sheet_id: string;
declare chartType: string;
declare width?: number | string;
declare height?: number | string;
declare left?: number | string;
declare top?: number | string;
declare needRangeShow?: boolean; // 目前不需要这个字段
declare chartOptions?: string;
static registerModule(sequelize: Sequelize) {
ChartModel.init(
{
chart_id: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false,
comment: "表ID",
},
worker_sheet_id: {
type: DataTypes.STRING,
allowNull: false,
comment: "所属工作表ID",
references: {
model: WorkerSheetModel,
key: "worker_sheet_id",
},
},
chartType: {
type: DataTypes.STRING,
allowNull: false,
comment: "图表类型",
defaultValue: "chartmix",
},
width: {
type: DataTypes.STRING,
allowNull: true,
comment: "width",
},
height: {
type: DataTypes.STRING,
allowNull: true,
comment: "height",
},
left: {
type: DataTypes.STRING,
allowNull: true,
comment: "left",
},
top: {
type: DataTypes.STRING,
allowNull: true,
comment: "top",
},
needRangeShow: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: false,
comment: "needRangeShow",
},
chartOptions: {
type: DataTypes.TEXT,
allowNull: true,
comment: "chartOptions",
},
},
{
sequelize,
tableName: "charts",
}
);
}
}
// 导出类型
export type ChartModelType = InferAttributes<ChartModel>;
@@ -0,0 +1,69 @@
/**
* config row/col hiddens model 配置行列隐藏
*/
import { WorkerSheetModel } from "./WorkerSheet";
import { DataTypes, InferAttributes, Model, Sequelize } from "sequelize";
export class HiddenAndLenModel extends Model {
// 类型定义
declare config_id?: string;
declare worker_sheet_id: string;
declare config_type: string; /** 隐藏类型 row/col */
declare config_index?: string; /** 隐藏的行号/列号 */
declare config_value?: number; /** 定义的行高列宽 */
// 注册模型
static registerModule(sequelize: Sequelize) {
HiddenAndLenModel.init(
{
config_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "config_id", // 描述
primaryKey: true,
defaultValue: DataTypes.UUIDV4, // 默认使用 uuid 作为 主键ID
},
worker_sheet_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "外键:关联 workersheet 的 worker_sheet_id", // 描述
references: {
model: WorkerSheetModel,
key: "worker_sheet_id",
},
},
config_type: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "隐藏类型 rowhidden/colhidden/rowlen/collen", // 描述
},
/**
* 根据下列字段,生成 下列配置对象
* "rowhidden": {
* "30": 0,
* "31": 0
* }
*/
config_index: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "隐藏的行号/列号", // 描述
},
config_value: {
type: DataTypes.INTEGER, // 类型
allowNull: false, // 非空
comment: "隐藏的行号/列号的长度", // 描述
defaultValue: 0,
},
},
{
sequelize, // 将模型与 Sequelize 实例关联
tableName: "hiddenandlens", // 直接式提供数据库表名
}
);
}
}
// 导出类型
export type HiddenAndLenModelType = InferAttributes<HiddenAndLenModel>;
@@ -0,0 +1,171 @@
/**
* Image 图片
*/
import { WorkerSheetModel } from "./WorkerSheet";
import { Model, Sequelize, DataTypes, InferAttributes } from "sequelize";
export class ImageModel extends Model {
declare image_id?: string;
declare worker_sheet_id: string; // 外键
declare image_type: string; // type 1移动并调整单元格大小 2移动并且不调整单元格的大小 3不要移动单元格并调整其大小
declare image_src: string; // 图片地址
declare image_key: string; // 图片唯一标识
declare in_cell?: string; // 是否在单元格内
declare image_originWidth: number; // 原始宽度
declare image_originHeight: number; // 原始高度
declare image_default_width: number; // 默认宽度
declare image_default_height: number; // 默认高度
declare image_default_left: number; // 默认左边距
declare image_default_top: number; // 默认上边距
declare image_crop_width: number; // 裁剪宽度
declare image_crop_height: number; // 裁剪高度
declare image_crop_offsetLeft: number; // 裁剪左边距
declare image_crop_offsetTop: number; // 裁剪上边距
declare image_isFixedPos: boolean; // 是否固定位置
declare image_fixedLeft: number; // 固定左边距
declare image_fixedTop: number; // 固定上边距
declare image_border_width: number; // 边框宽度
declare image_border_radius: number; // 圆角
declare image_border_style: string; // 边框样式
declare image_border_color: string; // 边框颜色
static registerModule(sequelize: Sequelize) {
ImageModel.init(
{
image_id: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false,
comment: "图片ID",
defaultValue: DataTypes.UUIDV4,
},
worker_sheet_id: {
type: DataTypes.STRING,
allowNull: false,
comment: "所属工作表ID",
references: {
model: WorkerSheetModel,
key: "worker_sheet_id",
},
},
image_type: {
type: DataTypes.STRING,
allowNull: false,
comment: "图片类型",
},
image_src: {
type: DataTypes.STRING,
allowNull: false,
comment: "图片地址",
},
in_cell: {
type: DataTypes.STRING,
allowNull: false,
comment: "单元格图片标识",
},
image_key: {
type: DataTypes.STRING,
allowNull: false,
comment: "图表标识",
},
image_originWidth: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "原始宽度",
},
image_originHeight: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "原始高度",
},
image_default_width: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "默认宽度",
},
image_default_height: {
type: DataTypes.INTEGER,
allowNull: false,
},
image_default_left: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "默认左边距",
},
image_default_top: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "默认上边距",
},
image_crop_width: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "裁剪宽度",
},
image_crop_height: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "裁剪高度",
},
image_crop_offsetLeft: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "裁剪左边距",
},
image_crop_offsetTop: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "裁剪上边距",
},
image_isFixedPos: {
type: DataTypes.BOOLEAN,
allowNull: false,
comment: "是否固定位置",
},
image_fixedLeft: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "固定左边距",
},
image_fixedTop: {
type: DataTypes.INTEGER,
allowNull: false,
},
image_border_width: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "边框宽度",
},
image_border_radius: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "圆角",
},
image_border_style: {
type: DataTypes.STRING,
allowNull: false,
},
image_border_color: {
type: DataTypes.STRING,
allowNull: false,
comment: "边框颜色",
},
},
{
sequelize,
tableName: "images",
}
);
}
}
// 导出类型
export type ImageModelType = InferAttributes<ImageModel>;
@@ -0,0 +1,77 @@
/**
* Config Merges 合并单元格数据模型
*
*/
import { WorkerSheetModel } from "./WorkerSheet";
import { DataTypes, InferAttributes, Model, Sequelize } from "sequelize";
export class MergeModel extends Model {
declare config_merge_id?: string;
declare worker_sheet_id: string;
declare r: number;
declare c: number;
declare rs: number;
declare cs: number;
// 注册模型
static registerModule(sequelize: Sequelize) {
MergeModel.init(
{
config_merge_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "config merge id", // 描述
primaryKey: true,
defaultValue: DataTypes.UUIDV4, // 默认使用 uuid 作为 主键ID
},
worker_sheet_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "外键:关联 cell_datas 的 worker_sheet_id", // 描述
references: {
model: WorkerSheetModel,
key: "worker_sheet_id",
},
},
/**
*
* 设置一个合并单元格,需要处理两个地方,一是单元格对象中设置mc属性,二是在config中设置merge
* "r": 0, //主单元格的行号
* "c": 0, //主单元格的列号
* "rs": 2, //合并单元格占的行数
* "cs": 2 //合并单元格占的列数
*
* 业务上的处理逻辑是:先查询这个表,如果有字段值,则反馈生成 celldata mc 属性字段
*/
r: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "r 主单元格的行号",
},
c: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "c 主单元格的列号",
},
rs: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "rs 合并单元格占的行数",
},
cs: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "cs 合并单元格占的列数",
},
},
{
sequelize, // 将模型与 Sequelize 实例关联
tableName: "merges", // 直接式提供数据库表名
}
);
}
}
// 导出类型
export type MergeModelType = InferAttributes<MergeModel>;
@@ -0,0 +1,44 @@
/**
* Worker Books 工作簿模型表
*/
import { DataTypes, InferAttributes, Model, Sequelize } from "sequelize";
export class WorkerBookModel extends Model {
declare gridKey: string; /** gridKey 是用户系统唯一文件ID 必须由用户传递 */
declare title?: string;
declare lang?: string;
static registerModule(sequelize: Sequelize) {
WorkerBookModel.init(
{
gridKey: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "gridKey", // 描述
primaryKey: true, // 主键
},
title: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "工作簿名称", // 描述
defaultValue: "未命名工作簿", // 默认值
},
lang: {
type: DataTypes.STRING(10), // 类型
allowNull: false, // 非空
comment: "语言", // 描述
defaultValue: "zh", // zh en
},
// ... 更多字段,根据项目实际情况添加
},
{
sequelize, // 将模型与 Sequelize 实例关联
tableName: "workerbooks", // 直接式提供数据库表名
}
);
}
}
// 导出类型
export type WorkerBookModelType = InferAttributes<WorkerBookModel>;
@@ -0,0 +1,113 @@
/**
* Worker Books 工作簿模型表
*/
import { WorkerBookModel } from "./WorkerBook";
import { DataTypes, InferAttributes, Model, Sequelize } from "sequelize";
export class WorkerSheetModel extends Model {
declare worker_sheet_id?: string; /** 有默认值,非必传 */
declare gridKey: string;
declare name: string;
declare order?: number;
declare status?: number;
declare hide?: boolean;
declare row?: number;
declare column?: number;
declare color?: string;
declare defaultRowHeight?: number;
declare defaultColWidth?: number;
declare deleteFlag?: boolean; // 是否被删除
static registerModule(sequelize: Sequelize) {
WorkerSheetModel.init(
{
worker_sheet_id: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "worker sheet id", // 描述
primaryKey: true, // 主键
defaultValue: DataTypes.UUIDV4, // 默认使用 uuid 作为 主键ID
},
gridKey: {
type: DataTypes.STRING, // 类型
allowNull: false, // 非空
comment: "外键:关联 workerbooks 的 gridKey", // 描述
// 外键
references: {
model: WorkerBookModel,
key: "gridKey",
},
},
name: {
type: DataTypes.STRING,
allowNull: false,
comment: "工作表名称",
},
order: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "工作表下标序号",
defaultValue: 0,
},
status: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "工作表激活状态,仅有一个激活状态的工作表,其他工作表为 0",
defaultValue: 0,
},
hide: {
type: DataTypes.BOOLEAN,
allowNull: false,
comment: "是否隐藏,0为不隐藏,1为隐藏",
defaultValue: false,
},
row: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "行数", // 描述
defaultValue: 30, // 默认值
},
column: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "列数", // 描述
defaultValue: 24, // 默认值
},
color: {
type: DataTypes.STRING,
allowNull: false,
comment: "表格颜色", // 描述
defaultValue: "", // 默认值
},
defaultRowHeight: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "默认行高",
defaultValue: 20,
},
defaultColWidth: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "默认列宽",
defaultValue: 80,
},
deleteFlag: {
type: DataTypes.BOOLEAN,
allowNull: false,
comment: "是否被删除",
defaultValue: false,
},
// ... 更多字段,根据项目实际情况添加
},
{
sequelize, // 将模型与 Sequelize 实例关联
tableName: "workersheets", // 直接式提供数据库表名
}
);
}
}
// 导出类型
export type WorkerSheetModelType = InferAttributes<WorkerSheetModel>;