Browse Source

Merge branch 'master' of https://github.com/mengshukeji/Luckysheet into master

master
wpxp123456 5 years ago
parent
commit
cb26ede26b
  1. 3
      README-zh.md
  2. 6
      README.md
  3. 22
      docs/guide/FAQ.md
  4. 20
      docs/zh/guide/FAQ.md
  5. 502
      docs/zh/guide/api.md
  6. 145
      docs/zh/guide/operate.md
  7. 23
      docs/zh/guide/sheet.md
  8. 13
      src/controllers/controlHistory.js
  9. 250
      src/controllers/freezen.js
  10. 12
      src/controllers/handler.js
  11. 3
      src/controllers/menuButton.js
  12. 6
      src/controllers/server.js
  13. 60
      src/controllers/sheetmanage.js
  14. 51
      src/controllers/zoom.js
  15. 4400
      src/demoData/sheetCell.js
  16. 3
      src/demoData/sheetFormula.js
  17. 16
      src/global/formula.js
  18. 8
      src/utils/util.js

3
README-zh.md

@ -148,6 +148,9 @@ npm run build
})
</script>
```
## 加入共建
如果你想为 Luckysheet 实现一个重要功能,需要先撰写 RFC 文档,按照Luckysheet的 [RFC](https://github.com/mengshukeji/Luckysheet-rfcs) 机制进行操作,在经过社区讨论完善后才可以进行代码的提交。
## 联系
- 欢迎提交 PR 或者 [Issues](https://github.com/mengshukeji/Luckysheet/issues/new/choose)

6
README.md

@ -3,6 +3,9 @@
![logo](/docs/.vuepress/public/img/logo_text.png)
[![Join the chat at https://gitter.im/mengshukeji/Luckysheet](https://badges.gitter.im/mengshukeji/Luckysheet.svg)](https://gitter.im/mengshukeji/Luckysheet?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<a href="https://twitter.com/intent/follow?screen_name=luckysheet">
<img src="https://img.shields.io/twitter/follow/luckysheet?style=social&logo=twitter"
alt="follow on Twitter"></a>
</div>
@ -151,6 +154,9 @@ Create a table
})
</script>
```
## Join the co-construction
If you want to implement an important function for Luckysheet, you need to write an RFC document first, follow Luckysheet's [RFC](https://github.com/mengshukeji/Luckysheet-rfcs) to operate, and submit the code after community discussion and improvement.
## Contact
- Welcome to submit PR or [Issues](https://github.com/mengshukeji/Luckysheet/issues/new/choose)

22
docs/guide/FAQ.md

@ -1,6 +1,6 @@
# FAQ
## What is the difference between data and celldata in luckysheetfile?
## **<span style="font-size:20px;">Q</span>** What is the difference between data and celldata in luckysheetfile?
**<span style="font-size:20px;">A</span>**: Use one-dimensional array format [celldata](/zh/guide/sheet.html#celldata), after the initialization is completed, the data converted into a two-dimensional array format is used for storage and update, and celldata is no longer used.
@ -18,20 +18,32 @@ luckysheet.buildGridData(luckysheetfile)
------------
## What are the cell types?
## **<span style="font-size:20px;">Q</span>** What are the cell types?
**<span style="font-size:20px;">A</span>**: Refer to [Cell Format List](/zh/guide/cell.html), with examples of available cell formats
------------
## How to use Luckysheet in vue project?
## **<span style="font-size:20px;">Q</span>** How to use Luckysheet in vue project?
**<span style="font-size:20px;">A</span>** : Reference [Luckysheet-vue-demo](https://github.com/Dushusir/vue-demo)
------------
## Why will the formula in the table not be triggered after initialization?
## **<span style="font-size:20px;">Q</span>** Why will the formula in the table not be triggered after initialization?
**<span style="font-size:20px;">A</span>** : Refer to [Table data format](/zh/guide/sheet.html#calcchain) ,just set the calcChain corresponding to the cell data.
------------
------------
## **<span style="font-size:20px;">Q</span>** Is the remote loading data loadUrl or updateUrl?
**<span style="font-size:20px;">A</span>**: [loadUrl](/zh/guide/config.html#loadurl). Configure loadUrl, Luckysheet will request the entire table data through ajax, and updateUrl will be used as the interface address for collaborative editing in real-time saving.
------------
## **<span style="font-size:20px;">Q</span>** How to understand the `index` and `order` of each worksheet?
**<span style="font-size:20px;">A</span>**: Each worksheet has a unique id, which is `index`, which can be incremented by numbers or a random string. And `order` is the order of all worksheets, starting from 0.
------------

20
docs/zh/guide/FAQ.md

@ -1,6 +1,6 @@
# FAQ
## luckysheetfile中的data和celldata有什么区别?
## **<span style="font-size:20px;">Q</span>** luckysheetfile中的data和celldata有什么区别?
**<span style="font-size:20px;">A</span>** : 表格初始化时使用一维数组格式的 [celldata](/zh/guide/sheet.html#celldata),初始化完成后转化为二维数组格式的data作为存储更新使用,celldata不再使用。
@ -18,20 +18,32 @@ luckysheet.buildGridData(luckysheetfile)
------------
## 单元格的类型有哪些?
## **<span style="font-size:20px;">Q</span>** 单元格的类型有哪些?
**<span style="font-size:20px;">A</span>** : 参考[单元格格式列表](/zh/guide/cell.html),例举了可用的单元格格式
------------
## 如何在vue项目中使用Luckysheet?
## **<span style="font-size:20px;">Q</span>** 如何在vue项目中使用Luckysheet?
**<span style="font-size:20px;">A</span>** : 参考 [Luckysheet-vue-demo](https://github.com/Dushusir/vue-demo)
------------
## 为什么初始化后表格里面的公式不会被触发?
## **<span style="font-size:20px;">Q</span>** 为什么初始化后表格里面的公式不会被触发?
**<span style="font-size:20px;">A</span>** : 参考 [表格数据格式](/zh/guide/sheet.html#calcchain) ,设置单元格数据对应的calcChain即可。
------------
## **<span style="font-size:20px;">Q</span>** 远端加载数据是loadUrl还是updateUrl?
**<span style="font-size:20px;">A</span>** : [loadUrl](/zh/guide/config.html#loadurl)。配置了loadUrl,Luckysheet会通过ajax请求整个表格数据,而updateUrl会作为协同编辑实时保存的接口地址。
------------
## **<span style="font-size:20px;">Q</span>** 如何理解每个sheet页的`index`和`order`?
**<span style="font-size:20px;">A</span>** : 每个sheet页都有一个唯一id,就是`index`,可以用数字递增,也可以使用随机字符串,而`order`是所有的sheet的排序情况,从0开始,即为索引。
------------

502
docs/zh/guide/api.md

@ -9,7 +9,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
## 单元格操作
### getCellValue(row, column [,setting])
### getCellValue(row, column [,setting])<div id='getCellValue'></div>
- **参数**
@ -143,7 +143,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
- **示例**:
- 当前工作表查找`"value"`字符串并替换为`"out"`
`luckysheet.find("value", "out)`
`luckysheet.replaces("value", "out)`
------------
@ -159,7 +159,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
+ `"false"`: 冻结首行
+ `"true"`: 冻结行到选区
- {PlainObject} [setting]: 可选参数
+ {Array | Object | String} [range]: `isRange`为`true`的时候设置,开启冻结的选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区
+ {Array | Object | String} [range]: `isRange`为`true`的时候设置,开启冻结的单元格位置,格式为`{ row_focus:0, column_focus:0 }`,意为当前激活的单元格的行数和列数;默认从当前选区最后的一个选区中取得
+ {Number} [order]: 工作表索引;默认值为当前工作表索引
+ {Function} [success]: 操作结束的回调函数
@ -167,7 +167,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
冻结行操作
特别注意,只有在`isRange`设置为`true`的时候,才需要设置`setting`中的`range`。
特别注意,只有在`isRange`设置为`true`的时候,才需要设置`setting`中的`range`,且与一般的range格式不同
- **示例**:
@ -191,7 +191,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
+ `"false"`: 冻结首列
+ `"true"`: 冻结列到选区
- {PlainObject} [setting]: 可选参数
+ {Array | Object | String} [range]: `isRange`为`true`的时候设置,开启冻结的选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区
+ {Array | Object | String} [range]: `isRange`为`true`的时候设置,开启冻结的单元格位置,格式为`{ row_focus:0, column_focus:0 }`,意为当前激活的单元格的行数和列数;默认从当前选区最后的一个选区中取得
+ {Number} [order]: 工作表索引;默认值为当前工作表索引
+ {Function} [success]: 操作结束的回调函数
@ -199,7 +199,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
冻结列操作
特别注意,只有在`isRange`设置为`true`的时候,才需要设置`setting`中的`range`。
特别注意,只有在`isRange`设置为`true`的时候,才需要设置`setting`中的`range`,且与一般的range格式不同
- **示例**:
@ -219,7 +219,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
+ `"false"`: 冻结行列
+ `"true"`: 冻结行列到选区
- {PlainObject} [setting]: 可选参数
+ {Array | Object | String} [range]: `isRange`为`true`的时候设置,开启冻结的选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区
+ {Array | Object | String} [range]: `isRange`为`true`的时候设置,开启冻结的单元格位置,格式为`{ row_focus:0, column_focus:0 }`,意为当前激活的单元格的行数和列数;默认从当前选区最后的一个选区中取得
+ {Number} [order]: 工作表索引;默认值为当前工作表索引
+ {Function} [success]: 操作结束的回调函数
@ -227,7 +227,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
冻结行列操作
特别注意,只有在`isRange`设置为`true`的时候,才需要设置`setting`中的`range`。
特别注意,只有在`isRange`设置为`true`的时候,才需要设置`setting`中的`range`,且与一般的range格式不同
- **示例**:
@ -257,7 +257,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
------------
### insertRow( row [,setting])
### insertRow(row [,setting])
- **参数**
@ -504,10 +504,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
[
{
"v": "vaule1",
"ct": {
"fa": "General",
"t": "g"
},
"ct": { "fa": "General", "t": "g" },
"m": "vaule1",
"bg": "rgba(255,255,255)",
"bl": 0,
@ -520,10 +517,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
},
{
"v": "value3",
"ct": {
"fa": "General",
"t": "g"
},
"ct": { "fa": "General", "t": "g" },
"m": "value3",
"bg": "rgba(255,255,255)",
"bl": 0,
@ -538,10 +532,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
[
{
"v": "vaule2",
"ct": {
"fa": "General",
"t": "g"
},
"ct": { "fa": "General", "t": "g" },
"m": "vaule2",
"bg": "rgba(255,255,255)",
"bl": 0,
@ -554,10 +545,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
},
{
"v": "value4",
"ct": {
"fa": "General",
"t": "g"
},
"ct": { "fa": "General", "t": "g" },
"m": "value4",
"bg": "rgba(255,255,255)",
"bl": 0,
@ -637,9 +625,34 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
+ {Number} [order]: 工作表索引;默认值为当前工作表索引
- **说明**
复制指定工作表指定单元格区域的数据,返回`json`格式的数据
- **示例**:
- 当前选区为"A1:B2",首行为标题取得json
`luckysheet.getRangeJson(true)`
则返回结果为:
```json
[
{ "A": "value1", "B": "value3" },
{ "A": "value2", "B": "value4" }
]
```
- 当前选区为"A1:B2",首行不为标题取得json
`luckysheet.getRangeJson(false)`
则返回结果为:
```json
[
{ "value1": "value2", "value3": "value4" }
]
```
------------
### getRangeArray(dimensional [,setting])
@ -652,7 +665,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
+ `"oneDimensional"`: 一维数组
+ `"twoDimensional"`: 二维数组
+ `"custom"`: 自定义维数组
+ `"custom"`: 自定义行列数的二维数组
- {PlainObject} [setting]: 可选参数
+ {Number} [row]: `dimensional`为`custom`的时候设置,多维数组的行数
+ {Number} [column]: `dimensional`为`custom`的时候设置,多维数组的列数
@ -661,10 +674,80 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
- **说明**
复制指定工作表指定单元格区域的数据,返回一维、二维或者自定义维数组格式的数据。
复制指定工作表指定单元格区域的数据,返回一维、二维或者自定义行列数的二维数组的数据。
特别注意,只有在`dimensional`设置为`custom`的时候,才需要设置`setting`中的`row`和`column`
- **示例**:
- 当前选区为"A1:B2",一维数组
`luckysheet.getRangeArray('oneDimensional')`
则返回结果为:
```json
["value1","value3","value2","value4"]
```
- 当前选区为"A1:B2",二维数组
`luckysheet.getRangeArray('twoDimensional')`
则返回结果为:
```json
[
[ "value1", "value3" ],
[ "value2", "value4" ]
]
```
- 当前选区为"A1:C5",由 'value1'到'value15'的值组成,得到3
行2列的二维数组数据
`luckysheet.getRangeArray('custom', { row: 3, column: 2 })`
则返回结果为:
```json
[
[
{
"m": "value1",
"ct": { "fa": "General", "t": "g" },
"v": "value1"
},
{
"ct": { "fa": "General", "t": "g" },
"v": "value6",
"m": "value6"
}
],
[
{
"ct": { "fa": "General", "t": "g" },
"v": "value11",
"m": "value11"
},
{
"m": "value2",
"ct": { "fa": "General", "t": "g" },
"v": "value2"
}
],
[
{
"ct": { "fa": "General", "t": "g" },
"v": "value7",
"m": "value7"
},
{
"ct": { "fa": "General", "t": "g" },
"v": "value12",
"m": "value12"
}
]
]
```
------------
### getRangeDiagonal(type [,setting])
@ -676,6 +759,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
`type`可能的值有:
+ `"normal"`: 对角线
+ `"anti"`: 反对角线
+ `"offset"`: 对角线偏移
- {PlainObject} [setting]: 可选参数
- {Number} [column]: `type`为`offset`的时候设置,对角偏移的列数
@ -688,6 +772,61 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
特别注意,只有在`type`设置为`offset`的时候,才需要设置`setting`中的`column`。
- **示例**:
- 当前选区为"A1:B2",对角线
`luckysheet.getRangeDiagonal('normal')`
则返回结果为:
```json
[
{
"m": "value1",
"ct": { "fa": "General", "t": "g" },
"v": "value1"
},
{
"m": "value4",
"ct": { "fa": "General", "t": "g" },
"v": "value4"
}
]
```
- 当前选区为"A1:B2",反对角线
`luckysheet.getRangeDiagonal('anti')`
则返回结果为:
```json
[
{
"m": "value3",
"ct": { "fa": "General", "t": "g" },
"v": "value3"
},
{
"m": "value2",
"ct": { "fa": "General", "t": "g" },
"v": "value2"
}
]
```
- 当前选区为"A1:B2",对角线偏移1列
`luckysheet.getRangeDiagonal('offset', { column: 1 })`
则返回结果为:
```json
[
{
"m": "value3",
"ct": { "fa": "General", "t": "g" },
"v": "value3"
}
]
```
------------
### getRangeBoolean([setting])
@ -702,6 +841,20 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
复制指定工作表指定单元格区域的数据,返回布尔值的数据
- **示例**:
- 当前选区为"A1:B2"
`luckysheet.getRangeBoolean()`
则返回结果为:
```json
[
[ false, false ],
[ false, false ]
]
```
------------
### setRangeShow(range [,setting])<div id='setRangeShow'></div>
@ -757,6 +910,52 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
将一个单元格数组数据赋值到指定的区域,数据格式同`getRangeValue`方法取到的数据。
- **示例**:
+ 赋值到当前选区
```js
const data = [
[
{
"m": "value1",
"ct": {
"fa": "General",
"t": "g"
},
"v": "value1"
},
{
"m": "value3",
"ct": {
"fa": "General",
"t": "g"
},
"v": "value3"
}
],
[
{
"m": "value2",
"ct": {
"fa": "General",
"t": "g"
},
"v": "value2"
},
{
"m": "value4",
"ct": {
"fa": "General",
"t": "g"
},
"v": "value4"
}
]
]
luckysheet.setRangeValue(data)
```
------------
### setRangeFormat(attr, value [,setting])
@ -791,9 +990,11 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
- **示例**:
- 设置当前工作表`"A1:B2"`范围的单元格文本加粗
`luckysheet.setRangeFormat("bl", 1, {range:"A1:B2"})`
`luckysheet.setRangeFormat("bl", 1, {range:"A1:B2"})`
- 设置第二个工作表的`"B2"`和`"C4:D5"`范围的单元格背景为红色
`luckysheet.setRangeFormat("bg", "#ff0000", {range:["B2","C4:D5"], order:1})`
`luckysheet.setRangeFormat("bg", "#ff0000", {range:["B2","C4:D5"], order:1})`
------------
@ -825,6 +1026,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
### setRangeMerge(type [,setting])
- **参数**
- {String} [type]: 合并单元格类型
`type`可能的值有:
@ -832,6 +1034,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
+ `"all"`: 全部合并,区域内所有单元格合并成一个大的单元格
+ `"horizontal"`: 水平合并,区域内在同一行的单元格合并成一个单元格
+ `"vertical"`: 垂直合并,区域内在同一列的单元格合并成一个单元格
- {PlainObject} [setting]: 可选参数
+ {Array | Object | String} [range]: 选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,允许多个选区组成的数组;默认为当前选区
+ {Number} [order]: 工作表索引;默认值为当前工作表索引
@ -841,6 +1044,36 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
为指定索引的工作表,选定的范围设定合并单元格
- **示例**:
- 当前选区 'A1:B2' 设置为合并单元格,类型为全部合并
`luckysheet.setRangeMerge("all")`
得到 'A1:B1' 的数据为:
```json
[
[
{
"m": "value1",
"ct": { "fa": "General", "t": "g" },
"v": "value1",
"mc": { "r": 0, "c": 0, "rs": 2, "cs": 2 }
},
{
"mc": { "r": 0, "c": 0 }
}
],
[
{
"mc": { "r": 0, "c": 0 }
},
{
"mc": { "r": 0, "c": 0 }
}
]
]
```
------------
### cancelRangeMerge( [setting])
@ -856,6 +1089,12 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
为指定索引的工作表,选定的范围取消合并单元格
- **示例**:
- 当前选区 'A1:B2' 已为合并单元格,现在要取消合并
`luckysheet.cancelRangeMerge()`
------------
### setRangeSort(type [,setting])
@ -1004,10 +1243,10 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
`luckysheet.setRangeConditionalFormatDefault("lastPercent",{ type: 'value', content: [15] })`
- 突出显示高于平均值的单元格
luckysheet.setRangeConditionalFormatDefault("AboveAverage",{ type: 'value', content: ['AboveAverage'] })`
`luckysheet.setRangeConditionalFormatDefault("AboveAverage",{ type: 'value', content: ['AboveAverage'] })`
- 突出显示低于平均值的单元格
luckysheet.setRangeConditionalFormatDefault("SubAverage",{ type: 'value', content: ['SubAverage'] })`
`luckysheet.setRangeConditionalFormatDefault("SubAverage",{ type: 'value', content: ['SubAverage'] })`
------------
@ -1122,6 +1361,11 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
为指定索引的工作表,选定的范围开启条件格式,返回开启条件格式后的数据。
- **示例**:
- 当前选区范围开启条件格式,显示渐变色
`luckysheet.setRangeConditionalFormat("dataBar", { format: ["#63c384", "#ffffff"] })`
------------
### deleteRangeConditionalFormat(itemIndex [,setting])
@ -1142,7 +1386,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
- **示例**:
- 删除第三个条件格式规则
`luckysheet.editRangeConditionalFormat(2)`
`luckysheet.deleteRangeConditionalFormat(2)`
------------
@ -1159,6 +1403,11 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
清除指定工作表指定单元格区域的内容,返回清除掉的数据,不同于删除选区的功能,不需要设定单元格移动情况
- **示例**:
- 清空当前选区内容
`luckysheet.clearRange()`
------------
### deleteRange(move [,setting])
@ -1180,6 +1429,11 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
删除指定工作表指定单元格区域,返回删除掉的数据,同时,指定是右侧单元格左移还是下方单元格上移
- **示例**:
- 删除当前选区并且在删除后,右侧单元格左移
`luckysheet.deleteRange('left')`
------------
### insertRange(move [,setting])
@ -1208,6 +1462,11 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
在指定工作表指定单元格区域,赋值单元格数据,或者新建一块空白区域,返回data数据,同时,指定活动单元格右移或者下移
- **示例**:
- 当前选区位置插入空白单元格,并且插入后当前选区单元格右移
`luckysheet.insertRange('right')`
------------
### matrixOperation(type [,setting])
@ -1237,6 +1496,20 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
指定工作表指定单元格区域的数据进行矩阵操作,返回操作成功后的结果数据
- **示例**:
- 当前选区上下翻转
`luckysheet.matrixOperation('flipUpDown')`
原来的选区复制为二维数组:
`[["value1","value3"],["value2","value4"]]`
上下翻转后选区复制为二维数组:
`[["value2","value4"],["value1","value3"]]`
------------
### matrixCalculation(type, number [,setting])
@ -1253,9 +1526,6 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
+ `"power"`: 次方
+ `"root"`: 次方根
+ `"log"`: log
+ `"removeDuplicateByRow"`: 按行删除重复值
+ `"removeDuplicateByColumn"`: 按列删除重复值
+ `"newMatrix"`: 生产新矩阵
- {Number} [number]: 计算数值,如: 2
- {PlainObject} [setting]: 可选参数
+ {Array | Object | String} [range]: 选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区
@ -1266,6 +1536,20 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
指定工作表指定单元格区域的数据进行矩阵计算,返回计算成功后的结果数据
- **示例**:
- 当前选区所有单元格值加2
`luckysheet.matrixCalculation('plus', 2)`
原来的选区复制为二维数组:
`[[1,2],[3,4]]`
加2后选区复制为二维数组:
`[[3,4],[5,6]]`
------------
## 工作表操作
@ -1303,12 +1587,44 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
------------
### getSheetData()
### getSheetData([setting])
- **参数**
- {PlainObject} [setting]: 可选参数
+ {Number} [order]: 工作表索引;默认值为当前工作表索引
- **说明**
快捷获取当前表格的数据,同 `luckysheetfile[i].data`
快捷返回指定工作表的数据,同 `luckysheetfile[i].data`
------------
### getConfig([setting])
- **参数**
- {PlainObject} [setting]: 可选参数
+ {Number} [order]: 工作表索引;默认值为当前工作表索引
- **说明**
快捷返回指定工作表的config配置,同 `luckysheetfile[i].config`
------------
### setConfig([setting])
- **参数**
- {PlainObject} [setting]: 可选参数
+ {Number} [order]: 工作表索引;默认值为当前工作表索引
+ {Function} [success]: 操作结束的回调函数
- **说明**
快捷设置当前表格config配置
------------
### setSheetAdd([setting])
@ -1509,7 +1825,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
- **说明**
初始化一个luckysheet,可包含多个工作表,参考 [配置列表](/zh/guide/config.html)
初始化一个Luckysheet,可包含多个工作表,参考 [配置列表](/zh/guide/config.html)
------------
@ -1526,6 +1842,19 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
------------
### destroy([setting])
- **参数**
- {PlainObject} [setting]: 可选参数
+ {Function} [success]: 表格释放成功后的回调函数
- **说明**
删除并释放表格
------------
### getScreenshot([setting])
- **参数**
@ -1651,10 +1980,8 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
## 公共方法
### transToCellData(data [,setting])<div id='transToCellData'></div>
- **参数**
- {Array} [data]: data数据
@ -1682,19 +2009,58 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
celldata => data ,celldata一维数组数据转化成表格所需二维数组
------------
## 旧版API
::: warning
为保持兼容性,仍然支持旧版API,但是已不推荐使用。
:::
### getcellvalue([r] [,c] [,data] [,type])
- **参数**
- {Number} [r]:单元格所在行数;可选值;从0开始的整数,0表示第一行
- {Number} [c]:单元格所在列数;可选值;从0开始的整数,0表示第一列
- {Array} [data]:表数据,二维数组;可选值;默认值为当前表格数据
- {String} [type]:单元格属性值;可选值;默认值为'v',表示获取单元格的实际值
- **说明**
此方法为获取单元格的值。
- luckysheet.getcellvalue():返回当前工作表的所有数据;
- luckysheet.getcellvalue(0):返回当前工作表第1行数据;
- luckysheet.getcellvalue(null,0):返回当前工作表第1列数据;
- luckysheet.getcellvalue(0,0):返回当前工作表第1行第1列单元格的数据的v值;
- luckysheet.getcellvalue(1,1,null,'m'): 返回指定data数据的第2行第2列单元格的原始值。
特殊情况:单元格格式为yyyy-MM-dd,type为'v'时会强制取'm'显示值
> 推荐使用新API: <a href='#getCellValue'>getCellValue</a>
------------
### getluckysheetfile()
- **说明**
返回所有表格数据结构的一维数组`luckysheetfile`
> 推荐使用新API: [getLuckysheetfile](#getLuckysheetfile())
------------
### getconfig()
- **说明**
快捷返回当前表格config配置,每个工作表的config信息仍然包含在luckysheetfile。
> 推荐使用新API: [getConfig](#getConfig([setting]))
------------
## getluckysheet_select_save()
### getluckysheet_select_save()
- **说明**
返回当前选区对象的数组,可能存在多个选区。
@ -1703,7 +2069,8 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
------------
## getdatabyselection([range] [,sheetOrder])
### getdatabyselection([range] [,sheetOrder])
- **参数**
- {Object} [range]:选区对象,`object: { row: [r1, r2], column: [c1, c2] }`;默认为当前第一个选区。
- {Number} [sheetOrder]:表格下标,从0开始的整数,0表示第一个表格;默认为当前表格下标。
@ -1717,7 +2084,8 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
------------
## luckysheetrefreshgrid(scrollWidth, scrollHeight)
### luckysheetrefreshgrid(scrollWidth, scrollHeight)
- **参数**
- {Number} [scrollWidth]:横向滚动值。默认为当前横向滚动位置。
- {Number} [scrollHeight]:纵向滚动值。默认为当前纵向滚动位置。
@ -1727,17 +2095,36 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
------------
## jfrefreshgrid()
### setcellvalue(r, c, d, v)
- **参数**
- {Number} [r]:单元格所在行数;从0开始的整数,0表示第一行。
- {Number} [c]:单元格所在列数;从0开始的整数,0表示第一列。
- {Array} [d]:表数据;可选值;二维数组。
- {Object | String | Number} [v]:要设置的值;可为对象,对象是是要符合单元格对象格式。
- **说明**
设置某个单元格的值。可配合`luckysheet.jfrefreshgrid()`刷新查看单元格值改变。
```js
luckysheet.setcellvalue(0, 0, luckysheet.flowdata(), 'abc');
luckysheet.jfrefreshgrid();
```
------------
### jfrefreshgrid()
- **说明**
刷新canvas
> 推荐使用新API: [refresh](#refresh([setting]))
------------
## setluckysheet_select_save(v)
### setluckysheet_select_save(v)
- **参数**
- {Array} [v]:要设置的选区值(数组)。符合选区格式规则,如`[{ row: [r1, r2], column: [c1, c2] }]`。
- **说明**
@ -1752,7 +2139,8 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
------------
## selectHightlightShow()
### selectHightlightShow()
- **说明**
高亮当前选区
@ -1761,7 +2149,8 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
------------
## flowdata()
### flowdata()
- **说明**
快捷获取当前表格的数据
@ -1770,7 +2159,8 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
------------
## buildGridData(file)
### buildGridData(file)
- **参数**
- {Object} [file]:[luckysheetfile](/zh/guide/sheet.html)
- **说明**
@ -1780,17 +2170,13 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开
> 推荐使用新API:<a href='#transToData'>transToData</a>
------------
## getGridData(data)
### getGridData(data)
- **参数**
- {Array} [data]:工作表的二维数组数据
- **说明**
二维数组数据转化成 `{r, c, v}` 格式 一维数组
> 推荐使用新API:<a href='#transToCellData'>transToCellData</a>
------------
## destroy()
- **说明**
删除并释放表格
> 推荐使用新API:<a href='#transToCellData'>transToCellData</a>

145
docs/zh/guide/operate.md

@ -8,30 +8,6 @@
以下为所有的支持传输到后台的操作类型,并且以MongoDB做存储示例,讲解如何做前后端交互。
## 格式
- **配置**
配置 `updateUrl` 的地址,发送到后台的参数为json的字符串。
- **格式**
```json
{
compress: false,
gridKey:10004,
data: [更新json数据]
}
```
- **说明**
| 参数 | 说明 | 举例 |
| ------------ | ------------ | ------------ |
| compress | Luckysheet采用客户端pako进行zlib参数压缩,如果浏览器支持压缩则为true,否则为false。后台可以根据此参数决定是否解压data中的内容 | 服务端获取参数过程:1. 序列化json字符串 2. 判断compress字段如果为TRUE则解压data字段 3. 解码data字符串URLDecoder.decode(utf-8) |
| gridKey | Luckysheet文件的标识符 | 无 |
| data | 一个包含更新数据的数组,数组中的参数格式请看下面的介绍。实例中:`t`表示更新类型、`i`为sheet的索引、`c`为列号、`r`为行号,`v`为值 | `data: [{ t : 'v', i:0, c : 0, r : 0 , v: 2 }]` |
## 单元格刷新
- **格式**
@ -39,10 +15,14 @@
```json
{
"t": "v",
"i": 3,
"v": "good",
"r": 5,
"c": 7
"i": "Sheet_0554kKiKl4M7_1597974810804",
"v": {
"v": 233,
"ct": { "fa": "General", "t": "n" },
"m": "233"
},
"r": 0,
"c": 1
}
```
@ -52,13 +32,13 @@
| ------------ | ------------ |
|t|操作类型表示符号|
|i|当前sheet的索引值|
|v|单元格的值,参考 [单元格属性表](/zh/guide/cell.html#基本单元格)|
|v|单元格的值,数字、字符串或着对象格式,对象参考 [单元格属性表](/zh/guide/cell.html#基本单元格)|
|r|单元格的行号|
|c|单元格的列号|
- **后台更新**
前端维护luckysheetfile[i].data,而单元格更新到后台,继续维护`luckysheetfile[i].celldata` 参数,该参数是一个一维数组:
前端维护luckysheetfile[i].data,而单元格更新到后台,继续维护`luckysheetfile[i].celldata` 参数,celldata是一个一维数组:
```json
[
{r:0, c:1, v: "值1"},
@ -66,25 +46,25 @@
{r:10, c:11, v:{f:"=sum", v:"100"}}
]
```
后台在保存前台推送的数据时,首先需要把参数转换为 `{r:0, c:1:v:100}` 的格式,然后更新 `luckysheetfile[i].celldata` 字段,如果存在该单元格则更新,如果没有则添加,如果存在该单元格但是`v`为null则删除该单元格。
- **前台查看**
可以修改任意单元格的数值,然后到chrome控制台中查看`"t"=="v"`的操作。
后台在保存前台推送的数据时,会更新 `luckysheetfile[i].celldata` 字段,如果存在该单元格则更新,如果没有则添加,如果存在该单元格但是`v`为null则删除该单元格。
## config操作
- **格式**
```json
{
"t": "cg",
"i": 3,
"v": {
"7": 192
},
"k": "rowlen"
}
{
"t": "cg",
"i": "Sheet_0554kKiKl4M7_1597974810804",
"v": [ {
"rangeType": "range",
"borderType": "border-all",
"color": "#000",
"style": "1",
"range": [ {"row": [ 0, 1 ], "column": [ 1, 1 ] } ]
} ],
"k": "borderInfo"
}
```
- **说明**
@ -93,40 +73,68 @@
| ------------ | ------------ |
|t|操作类型表示符号|
|i|当前sheet的index值|
|v|需要更新的内部key-value|
|k|操作的key名称|
|v|需要更新value|
|k|操作的key值,可选 边框:`'borderInfo'` / :行隐藏:`'rowhidden'` / 列隐藏:`'columnhidden'` / 行高:`'rowlen'` / 列宽:`'columnlen'` |
- **后台更新**
更新 `luckysheetfile[i].config.[k][v.key] = v.value` ,如果`config`中不存在`k`,则新建一个`k`属性并设置为空,如果`k`中不存在`v.key`,则新建一个`v.key`再更新`v.value`
更新 `luckysheetfile[i].config.[k] = v` ,如果`config`中不存在`k`,则新建一个`k`属性并设置为空。
1. 修改行高度举例:
- 输入:`{"t":"cg","i":3,"v":{"3":10, "5":70, "10":100},"k":" rowlen"}`
- 更新:`luckysheetfile[3].config.["rowlen"]["3"] = 10`
注意一点,修改config中的某个配置时,会把这个配置全部传输到后台,比如修改borderInfo,本来已经有一个含边框的单元格了,再新设置一个单元格边框,这时候会把这两个单元格边框信息都传输到后台,而不做更细颗粒的操作。
2. 修改列宽度举例:
- 输入:`{"t":"cg","i":1,"v":{"20":74, "15":170, "6":40},"k":" columnlen"}`
- 更新:`luckysheetfile[1].config.["columnlen"]["20"] = 74`
3. 合并单元格举例:
- 输入:`{"t":"cg","i":1,"v":{"5_10":{row:[1,3], column:[3,5]},"k":" merge "}`
- 更新:`luckysheetfile[1].config.["merge"]["5_10"] = {row:[1,3], column:[3,5]}`
1. 行隐藏:
- 发送到后台:
```json
{
"t": "cg",
"i": "Sheet_0554kKiKl4M7_1597974810804",
"v": { "5": 0, "6": 0, "13": 0, "14": 0 }, // 包含所有隐藏行信息
"k": "rowhidden"
}
```
- 后台更新:`luckysheetfile["Sheet_0554kKiKl4M7_1597974810804"].config.["rowhidden"] = { "5": 0, "6": 0, "13": 0, "14": 0 }`
2. 修改行高:
- 发送到后台:
```json
{
"t": "cg",
"i": "Sheet_0554kKiKl4M7_1597974810804",
"v": { "9": 20, "11": 71, "15": 58 }, // 包含所有修改过高度的单元格信息
"k": "rowlen"
}
```
- 后台更新:`luckysheetfile["Sheet_0554kKiKl4M7_1597974810804"].config.["rowlen"] = { "9": 20, "11": 71, "15": 58 }`
3. 修改列宽:
- 发送到后台:
```json
{
"t": "cg",
"i": "Sheet_0554kKiKl4M7_1597974810804",
"v": { "2": 135 },
"k": "columnlen"
}
```
- 后台更新:`luckysheetfile["Sheet_0554kKiKl4M7_1597974810804"].config.["columnlen"] = { "2": 135 }`
## 通用保存
- **格式**
```json
{
"t": "all",
"i": 3,
"v": {
"v": 1,
"m":1,
},
"k": "freezen",
"s": false
}
{
"t": "all",
"i": 0,
"v": {
"type": "rangeRow",
"range": {
"row_focus": 1,
"column_focus": 1
}
},
"k": "frozen"
}
```
- **说明**
@ -135,9 +143,8 @@
| ------------ | ------------ |
|t|操作类型表示符号|
|i|当前sheet的index值|
|v|需要更新的内部key-value|
|k|需要保存的key-value中的`value`|
|s|如果是`true`则`v`保存为字符串,否则按照对象进行保存|
|v|需要更新value值|
|k|操作的key值|
- **后台更新**

23
docs/zh/guide/sheet.md

@ -37,7 +37,7 @@ options.data示例如下:
"luckysheet_alternateformat_save": [], //交替颜色
"luckysheet_alternateformat_save_modelCustom": [], //自定义交替颜色
"luckysheet_conditionformat_save": {},//条件格式
"freezen": {}, //冻结行列
"frozen": {}, //冻结行列
"chart": [], //图表配置
},
{
@ -711,7 +711,7 @@ type: "default": 突出显示单元格规则和项目选区规则,
```
------------
### frozen(TODO)
### frozen
- 类型:Array
- 默认值:[]
- 作用: 冻结行列设置,分为6种类型
@ -721,7 +721,14 @@ type: "default": 突出显示单元格规则和项目选区规则,
4. "rangeRow": 冻结行到选区
5. "rangeColumn": 冻结列到选区
6. "rangeBoth": 冻结行列到选区
当设置冻结到选区的时候,需要设置选区范围`range`,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;如果已经设置了`luckysheet_select_save`,则直接取当前第一个选区,不用再设置选区。
7. "cancel": 取消冻结
当设置冻结到选区的时候,需要设置开启冻结的单元格位置,格式为`{ row_focus:0, column_focus:0 }`,意为当前激活的单元格的行数和列数。
sheet新的配置属性,存储更语义化的配置,用于初始化和传给后端。
注意一点,luckysheetfile中还有一个配置freezen,其中的freezenhorizontaldata仍然用作本地数据,但是不发给后台存储,只做本地调试。
- 示例:
- 冻结首行
```json
@ -729,18 +736,18 @@ type: "default": 突出显示单元格规则和项目选区规则,
type: 'row'
}
```
- 冻结行到`'B2'`选区
- 冻结行到`'A1'`选区
```json
{
type: 'rangeRow',
range: {row:[1,1],column:[1,1]}
range: {row_focus: 0, column_focus: 0}
}
```
- 冻结行列到`'B3:D4'`选区
- 冻结行列到`'B2'`选区
```json
{
type: 'rangeBoth',
range: "B3:D4"
range: {row_focus: 1, column_focus: 1}
}
```
@ -756,7 +763,7 @@ type: "default": 突出显示单元格规则和项目选区规则,
初始化所需要的参数,会从简洁的角度出发来考虑设计,但是本地存储的参数则不同。
Luckysheet在初始化完成之后进行的一系列操作,会将更多本地参数存储在luckysheetfile中,作为本地使用的参数,实现一些类似Store数据中心的作用。
Luckysheet在初始化完成之后进行的一系列操作,会将更多本地参数存储在luckysheetfile中,作为本地使用的参数,实现一些类似Store数据中心的作用。比如,freezen的参数格式也会变化。
此时的luckysheetfile包含很多非初始化使用的本地参数,可用于调试代码、本地状态分析。如下展示了更丰富luckysheetfile信息,可通过方法 `luckysheet.getluckysheetfile()`获得:

13
src/controllers/controlHistory.js

@ -3,6 +3,7 @@ import server from './server';
import pivotTable from './pivotTable';
import conditionformat from './conditionformat';
import luckysheetPostil from './postil';
import {zoomRefreshView,zoomNumberDomBind} from './zoom';
import { createFilter, createFilterOptions, labelFilterOptionState } from './filter';
import formula from '../global/formula';
import json from '../global/json';
@ -326,6 +327,12 @@ const controlHistory = {
}
}
}
else if (ctr.type=="zoomChange"){
Store.zoomRatio = ctr.zoomRatio;
server.saveParam("all", ctr.currentSheetIndex, ctr.zoomRatio, { "k": "zoomRatio" });
zoomNumberDomBind();
zoomRefreshView();
}
cleargridelement(e);
Store.clearjfundo = true;
@ -549,6 +556,12 @@ const controlHistory = {
}
}
}
else if (ctr.type=="zoomChange"){
Store.zoomRatio = ctr.curZoomRatio;
server.saveParam("all", ctr.currentSheetIndex, ctr.curZoomRatio, { "k": "zoomRatio" });
zoomNumberDomBind();
zoomRefreshView();
}
Store.clearjfundo = true;
}

250
src/controllers/freezen.js

@ -58,8 +58,8 @@ const luckysheetFreezen = {
currentSheet.freezen.vertical = null;
}
if(currentSheet.freezen != null && isvertical){
server.saveParam("all", sheetIndex, currentSheet.freezen, { "k": "freezen" });
if(currentSheet.frozen != null && isvertical){
server.saveParam("all", sheetIndex, currentSheet.frozen, { "k": "frozen" });
}
},
createFreezenVertical: function (freezenverticaldata, left) {
@ -149,13 +149,21 @@ const luckysheetFreezen = {
currentSheet.freezen.vertical.left = left;
}
if(currentSheet.freezen != null){
server.saveParam("all", Store.currentSheetIndex, currentSheet.freezen, { "k": "freezen" });
// if(currentSheet.freezen != null){
// server.saveParam("all", Store.currentSheetIndex, currentSheet.freezen, { "k": "freezen" });
// }
// use new property frozen
if(currentSheet.frozen != null){
server.saveParam("all", Store.currentSheetIndex, currentSheet.frozen, { "k": "frozen" });
}
},
initialFreezen: function (sheetIndex) {
let _this = this;
// when init ,we get frozen, but here, we need freezen,so tranform it
_this.frozenTofreezen();
let currentSheet = Store.luckysheetfile[getSheetIndex(sheetIndex)];
if (currentSheet.freezen != null && currentSheet.freezen.horizontal != null && currentSheet.freezen.horizontal.freezenhorizontaldata != null) {
_this.createFreezenHorizontal(currentSheet.freezen.horizontal.freezenhorizontaldata, currentSheet.freezen.horizontal.top);
@ -284,8 +292,8 @@ const luckysheetFreezen = {
currentSheet.freezen.horizontal = null;
}
if(currentSheet.freezen != null && ishorizontal){
server.saveParam("all", sheetIndex, currentSheet.freezen, { "k": "freezen" });
if(currentSheet.frozen != null && ishorizontal){
server.saveParam("all", sheetIndex, currentSheet.frozen, { "k": "frozen" });
}
},
createFreezenHorizontal: function (freezenhorizontaldata, top) {
@ -1500,6 +1508,236 @@ const luckysheetFreezen = {
$("#luckysheet-filter-options-sheet"+ Store.currentSheetIndex).empty();
createFilterOptions(Store.luckysheetfile[getSheetIndex(Store.currentSheetIndex)].filter_select);
}
},
/**
*
* @param {string} operate "freezenRow"/ "freezenColumn"......
*/
saveFrozen: function(operate) {
// New configuration attribute of sheet: frozen, which stores more semantic configuration for initialization and transmission to the backend. freezenhorizontaldata is still used as local data
const select_save = Store.luckysheet_select_save[Store.luckysheet_select_save.length - 1];
const row_focus = select_save["row_focus"] == null ? select_save["row"][0] : select_save["row_focus"];
const column_focus = select_save["column_focus"] == null ? select_save["column"][0] : select_save["column_focus"];
const range = {
row_focus: row_focus,
column_focus: column_focus
}
const frozen = {
"freezenRow": {
type: 'row'
},
"freezenColumn": {
type: 'column'
},
"freezenRC": {
type: 'both'
},
"freezenRowRange": {
type: 'rangeRow',
range: range
},
"freezenColumnRange": {
type: 'rangeColumn',
range: range
},
"freezenRCRange": {
type: 'rangeBoth',
range: range
},
"freezenCancel": {
type: 'cancel'
}
}
// store frozen
Store.luckysheetfile[getSheetIndex(Store.currentSheetIndex)]["frozen"] = frozen[operate];
},
frozenTofreezen: function() {
// get frozen type
const frozen = Store.luckysheetfile[getSheetIndex(Store.currentSheetIndex)]["frozen"];
if(frozen == null){
return;
}
let freezen = null;
// transform to freezen
if(frozen.type === 'row'){
let scrollTop = $("#luckysheet-cell-main").scrollTop();
let row_st = luckysheet_searcharray(Store.visibledatarow, scrollTop);
if(row_st == -1){
row_st = 0;
}
let top = Store.visibledatarow[row_st] - 2 - scrollTop + Store.columeHeaderHeight;
let freezenhorizontaldata = [Store.visibledatarow[row_st], row_st + 1, scrollTop, luckysheetFreezen.cutVolumn(Store.visibledatarow, row_st + 1), top];
freezen = {
horizontal:{
freezenhorizontaldata: freezenhorizontaldata,
top: top
}
}
}
else if(frozen.type === 'column'){
let scrollLeft = $("#luckysheet-cell-main").scrollLeft();
let col_st = luckysheet_searcharray(Store.visibledatacolumn, scrollLeft);
if(col_st == -1){
col_st = 0;
}
let left = Store.visibledatacolumn[col_st] - 2 - scrollLeft + Store.rowHeaderWidth;
let freezenverticaldata = [Store.visibledatacolumn[col_st], col_st + 1, scrollLeft, luckysheetFreezen.cutVolumn(Store.visibledatacolumn, col_st + 1), left];
freezen = {
vertical:{
freezenverticaldata: freezenverticaldata,
left: left
}
}
}
else if(frozen.type === 'both'){
let scrollTop = $("#luckysheet-cell-main").scrollTop();
let row_st = luckysheet_searcharray(Store.visibledatarow, scrollTop);
if(row_st == -1){
row_st = 0;
}
let top = Store.visibledatarow[row_st] - 2 - scrollTop + Store.columeHeaderHeight;
let freezenhorizontaldata = [Store.visibledatarow[row_st], row_st + 1, scrollTop, luckysheetFreezen.cutVolumn(Store.visibledatarow, row_st + 1), top];
freezen = {
}
let scrollLeft = $("#luckysheet-cell-main").scrollLeft();
let col_st = luckysheet_searcharray(Store.visibledatacolumn, scrollLeft);
if(col_st == -1){
col_st = 0;
}
let left = Store.visibledatacolumn[col_st] - 2 - scrollLeft + Store.rowHeaderWidth;
let freezenverticaldata = [Store.visibledatacolumn[col_st], col_st + 1, scrollLeft, luckysheetFreezen.cutVolumn(Store.visibledatacolumn, col_st + 1), left];
freezen = {
horizontal:{
freezenhorizontaldata: freezenhorizontaldata,
top: top
},
vertical:{
freezenverticaldata: freezenverticaldata,
left: left
}
}
}
else if(frozen.type === 'rangeRow'){
let scrollTop = $("#luckysheet-cell-main").scrollTop();
let row_st = luckysheet_searcharray(Store.visibledatarow, scrollTop);
let row_focus = frozen.range["row_focus"];
if(row_focus > row_st){
row_st = row_focus;
}
if(row_st == -1){
row_st = 0;
}
let top = Store.visibledatarow[row_st] - 2 - scrollTop + Store.columeHeaderHeight;
let freezenhorizontaldata = [Store.visibledatarow[row_st], row_st + 1, scrollTop, luckysheetFreezen.cutVolumn(Store.visibledatarow, row_st + 1), top];
freezen = {
horizontal:{
freezenhorizontaldata: freezenhorizontaldata,
top: top
}
}
}
else if(frozen.type === 'rangeColumn'){
let scrollLeft = $("#luckysheet-cell-main").scrollLeft();
let col_st = luckysheet_searcharray(Store.visibledatacolumn, scrollLeft);
let column_focus = frozen.range["column_focus"];
if(column_focus > col_st){
col_st = column_focus;
}
if(col_st == -1){
col_st = 0;
}
let left = Store.visibledatacolumn[col_st] - 2 - scrollLeft + Store.rowHeaderWidth;
let freezenverticaldata = [Store.visibledatacolumn[col_st], col_st + 1, scrollLeft, luckysheetFreezen.cutVolumn(Store.visibledatacolumn, col_st + 1), left];
freezen = {
vertical:{
freezenverticaldata: freezenverticaldata,
left: left
}
}
}
else if(frozen.type === 'rangeBoth'){
let scrollTop = $("#luckysheet-cell-main").scrollTop();
let row_st = luckysheet_searcharray(Store.visibledatarow, scrollTop);
let row_focus = frozen.range["row_focus"];
if(row_focus > row_st){
row_st = row_focus;
}
if(row_st == -1){
row_st = 0;
}
let top = Store.visibledatarow[row_st] - 2 - scrollTop + Store.columeHeaderHeight;
let freezenhorizontaldata = [Store.visibledatarow[row_st], row_st + 1, scrollTop, luckysheetFreezen.cutVolumn(Store.visibledatarow, row_st + 1), top];
let scrollLeft = $("#luckysheet-cell-main").scrollLeft();
let col_st = luckysheet_searcharray(Store.visibledatacolumn, scrollLeft);
let column_focus = frozen.range["column_focus"];
if(column_focus > col_st){
col_st = column_focus;
}
if(col_st == -1){
col_st = 0;
}
let left = Store.visibledatacolumn[col_st] - 2 - scrollLeft + Store.rowHeaderWidth;
let freezenverticaldata = [Store.visibledatacolumn[col_st], col_st + 1, scrollLeft, luckysheetFreezen.cutVolumn(Store.visibledatacolumn, col_st + 1), left];
freezen = {
horizontal:{
freezenhorizontaldata: freezenhorizontaldata,
top: top
},
vertical:{
freezenverticaldata: freezenverticaldata,
left: left
}
}
}
else if(frozen.type === 'cancel'){
freezen = {
horizontal: null,
vertical: null
}
}
Store.luckysheetfile[getSheetIndex(Store.currentSheetIndex)]["freezen"] = freezen;
}
}

12
src/controllers/handler.js

@ -3417,6 +3417,9 @@ export default function luckysheetHandler() {
//冻结行列
$("#luckysheet-freezen-btn-horizontal").click(function () {
if ($.trim($(this).text()) == locale().freezen.freezenCancel) {
luckysheetFreezen.saveFrozen("freezenCancel");
if (luckysheetFreezen.freezenverticaldata != null) {
luckysheetFreezen.cancelFreezenVertical();
luckysheetFreezen.createAssistCanvas();
@ -3432,6 +3435,9 @@ export default function luckysheetHandler() {
luckysheetFreezen.scrollAdapt();
}
else {
luckysheetFreezen.saveFrozen("freezenRow");
if (luckysheetFreezen.freezenverticaldata != null) {
luckysheetFreezen.cancelFreezenVertical();
luckysheetFreezen.createAssistCanvas();
@ -3447,10 +3453,16 @@ export default function luckysheetHandler() {
$("#luckysheet-freezen-btn-vertical").click(function () {
if (luckysheetFreezen.freezenverticaldata != null) {
luckysheetFreezen.saveFrozen("freezenCancel");
luckysheetFreezen.cancelFreezenVertical();
luckysheetrefreshgrid();
}
else {
luckysheetFreezen.saveFrozen("freezenColumn");
luckysheetFreezen.createFreezenVertical();
}
luckysheetFreezen.createAssistCanvas();

3
src/controllers/menuButton.js

@ -1520,6 +1520,9 @@ const menuButton = {
let $t = $(this), itemvalue = $t.attr("itemvalue");
_this.focus($menuButton, itemvalue);
// store frozen
luckysheetFreezen.saveFrozen(itemvalue);
if(itemvalue == "freezenRow"){ //首行冻结
let scrollTop = $("#luckysheet-cell-main").scrollTop();
let row_st = luckysheet_searcharray(Store.visibledatarow, scrollTop);

6
src/controllers/server.js

@ -326,7 +326,11 @@ const server = {
else if(k == "pivotTable"){ //PivotTable
// luckysheet.pivotTable.changePivotTable(index);
}
else if(k == "freezen"){ //freezen row and column
else if(k == "frozen"){ //freezen row and column
// tranform frozen
luckysheetFreezen.frozenTofreezen();
if(index == Store.currentSheetIndex){
const _locale = locale();
const locale_freezen = _locale.freezen;

60
src/controllers/sheetmanage.js

@ -151,6 +151,22 @@ const sheetmanage = {
return Store.luckysheetfile[i];
},
getSheetByName: function(name) {
let _this = this;
if(name == null){
return null;
}
for(let i=0;i<Store.luckysheetfile.length;i++){
let file = Store.luckysheetfile[i];
if(file.name==name){
return file;
}
}
return null;
},
getCurSheetnoset: function() {
let curindex = 0;
@ -731,7 +747,18 @@ const sheetmanage = {
let loadSheetUrl = server.loadSheetUrl;
if(sheetindex.length == 0 || loadSheetUrl == ""){
if(sheetindex.length == 0 && loadSheetUrl == ""){
execF();
}
else if(sheetindex.length>0 && loadSheetUrl == ""){
for(let i = 0;i<sheetindex.length;i++){
let item = sheetindex[i];
let otherfile = Store.luckysheetfile[_this.getSheetIndex(item)];
if(otherfile["load"] == null || otherfile["load"] == "0"){
otherfile["data"] = _this.buildGridData(otherfile);
otherfile["load"] = "1";
}
}
execF();
}
else{
@ -1004,21 +1031,42 @@ const sheetmanage = {
let ret= [], cache = {};
ret.push(file.index);
cache[file.index.toString()] = 1;
if(calchain != null){
let dataNameList = {};
for(let i = 0; i < calchain.length; i++){
let func = calchain[i];
let dataindex = func.index;
let f = calchain[i];
let dataindex = f.index, func = f.func;
formula.functionParser(func[2], (str)=>{
if(str.indexOf("!")>-1){
let name = str.substr(0, str.indexOf('!'));
dataNameList[name] = true;
}
});
if(dataindex == null){
continue;
}
if(cache[dataindex.toString()] == null){
ret.push(dataindex);
cache[dataindex.toString()] = 1;
}
}
}
for(let n in dataNameList){
let sheet = this.getSheetByName(n);
if(sheet==null){
continue;
}
let dataindex = sheet.index;
if(cache[dataindex.toString()] == null){
ret.push(dataindex);
cache[dataindex.toString()] = 1;
}
}
}
if(chart != null){

51
src/controllers/zoom.js

@ -3,6 +3,7 @@ import locale from '../locale/locale';
import { replaceHtml } from '../utils/util';
import {changeSheetContainerSize} from './resize';
import { jfrefreshgrid_rhcw } from '../global/refresh';
import server from './server';
@ -13,27 +14,39 @@ export function zoomChange(ratio){
return;
}
Store.zoomRatio = ratio;
clearTimeout(luckysheetZoomTimeout);
luckysheetZoomTimeout = setTimeout(() => {
if (Store.clearjfundo) {
Store.jfredo.push({
"type": "zoomChange",
"zoomRatio": Store.zoomRatio,
"curZoomRatio": ratio,
"sheetIndex": Store.currentSheetIndex,
});
}
Store.zoomRatio = ratio;
server.saveParam("all", Store.currentSheetIndex, Store.zoomRatio, { "k": "zoomRatio" });
let $scrollLeft = $("#luckysheet-scrollbar-x"), $scrollTop = $("#luckysheet-scrollbar-y");
let sl = $scrollLeft.scrollLeft(), st = $scrollTop.scrollTop();
zoomRefreshView();
}, 100);
}
let wp = $scrollLeft.find("div").width(), hp = $scrollTop.find("div").height();
export function zoomRefreshView(){
let $scrollLeft = $("#luckysheet-scrollbar-x"), $scrollTop = $("#luckysheet-scrollbar-y");
let sl = $scrollLeft.scrollLeft(), st = $scrollTop.scrollTop();
jfrefreshgrid_rhcw(Store.flowdata.length, Store.flowdata[0].length);
changeSheetContainerSize();
let wp = $scrollLeft.find("div").width(), hp = $scrollTop.find("div").height();
let wc = $scrollLeft.find("div").width(), hc = $scrollTop.find("div").height();
jfrefreshgrid_rhcw(Store.flowdata.length, Store.flowdata[0].length);
changeSheetContainerSize();
$scrollLeft.scrollLeft(sl+wc-wp);
$scrollTop.scrollTop(st+hc-hp);
let wc = $scrollLeft.find("div").width(), hc = $scrollTop.find("div").height();
}, 100);
$scrollLeft.scrollLeft(sl+wc-wp);
$scrollTop.scrollTop(st+hc-hp);
}
@ -58,7 +71,7 @@ export function zoomInitial(){
currentRatio = 0.1;
}
Store.zoomRatio = currentRatio;
// Store.zoomRatio = currentRatio;
zoomChange(currentRatio);
zoomNumberDomBind(currentRatio);
});
@ -82,16 +95,16 @@ export function zoomInitial(){
currentRatio = 4;
}
Store.zoomRatio = currentRatio;
// Store.zoomRatio = currentRatio;
zoomChange(currentRatio);
zoomNumberDomBind(currentRatio);
});
$("#luckysheet-zoom-slider").click(function(e){
$("#luckysheet-zoom-slider").mousedown(function(e){
let xoffset = $(this).offset().left, pageX = e.pageX;
let currentRatio = positionToRatio(pageX-xoffset);
Store.zoomRatio = currentRatio;
// Store.zoomRatio = currentRatio;
zoomChange(currentRatio);
zoomNumberDomBind(currentRatio);
});
@ -118,7 +131,7 @@ export function zoomInitial(){
pos = 0;
}
Store.zoomRatio = currentRatio;
// Store.zoomRatio = currentRatio;
zoomChange(currentRatio);
let r = Math.round(currentRatio*100) + "%";
$("#luckysheet-zoom-ratioText").html(r);
@ -136,7 +149,7 @@ export function zoomInitial(){
});
$("#luckysheet-zoom-ratioText").click(function(){
Store.zoomRatio = 1;
// Store.zoomRatio = 1;
zoomChange(1);
zoomNumberDomBind(1);
});

4400
src/demoData/sheetCell.js

File diff suppressed because one or more lines are too long

3
src/demoData/sheetFormula.js

@ -6594,7 +6594,8 @@ const sheetFormula = {
}],
"luckysheet_selection_range": [],
"scrollLeft": 0,
"scrollTop": 0
"scrollTop": 0,
"frozen": {"type":"row"}
}
export default sheetFormula

16
src/global/formula.js

@ -3600,7 +3600,7 @@ const luckysheetformula = {
"+": 2,
"-": 2
},
functionParser: function(txt) {
functionParser: function(txt, cellRangeFunction) {
let _this = this;
if (_this.operatorjson == null) {
@ -3672,7 +3672,7 @@ const luckysheetformula = {
let bt = bracket.pop();
if(bracket.length == 0){
function_str += _this.functionParser(str) + ")";
function_str += _this.functionParser(str,cellRangeFunction) + ")";
str = "";
}
else{
@ -3699,7 +3699,7 @@ const luckysheetformula = {
}
else if (s == ',' && matchConfig.dquote == 0 && matchConfig.braces == 0) {
if(bracket.length <= 1){
function_str += _this.functionParser(str) + ",";
function_str += _this.functionParser(str,cellRangeFunction) + ",";
str = "";
}
else{
@ -3717,7 +3717,7 @@ const luckysheetformula = {
if ((s + s_next) in _this.operatorjson) {
if(bracket.length == 0){
if($.trim(str).length > 0){
cal2.unshift(_this.functionParser($.trim(str)));
cal2.unshift(_this.functionParser($.trim(str),cellRangeFunction));
}
else if($.trim(function_str).length > 0){
cal2.unshift($.trim(function_str));
@ -3746,7 +3746,7 @@ const luckysheetformula = {
else {
if(bracket.length == 0){
if($.trim(str).length > 0){
cal2.unshift(_this.functionParser($.trim(str)));
cal2.unshift(_this.functionParser($.trim(str),cellRangeFunction));
}
else if($.trim(function_str).length > 0){
cal2.unshift($.trim(function_str));
@ -3790,7 +3790,11 @@ const luckysheetformula = {
let endstr = "";
if (_this.iscelldata($.trim(str))) {
endstr = "luckysheet_getcelldata('" + $.trim(str) + "')";
let str_nb = $.trim(str);
endstr = "luckysheet_getcelldata('" +str_nb + "')";
if(typeof(cellRangeFunction)=="function"){
cellRangeFunction(str_nb);
}
}
else {
str = $.trim(str);

8
src/utils/util.js

@ -385,7 +385,13 @@ function luckysheetactiveCell() {
//单元格编辑聚焦
function luckysheetContainerFocus() {
$("#" + Store.container).attr("tabindex", 0).focus({
// $("#" + Store.container).attr("tabindex", 0).focus({
// preventScroll: true
// });
// fix jquery error: Uncaught TypeError: ((n.event.special[g.origType] || {}).handle || g.handler).apply is not a function
$("#" + Store.container).focus({
preventScroll: true
});
}

Loading…
Cancel
Save