diff --git a/README-zh.md b/README-zh.md index 08004af..02a94a4 100644 --- a/README-zh.md +++ b/README-zh.md @@ -20,7 +20,8 @@ ## 在线案例 -- [协同编辑Demo](http://luckysheet.lashuju.com/demo/)(注意:官方Java后台待整理后也会开源,采用OT算法。请大家别操作频繁,防止搞崩服务器) +- [协同编辑Demo](http://luckysheet.lashuju.com/demo/) +- [Java后台Luckysheet Server](https://github.com/mengshukeji/LuckysheetServer) ## 插件 - excel导入导出库: [Luckyexcel](https://github.com/mengshukeji/Luckyexcel) diff --git a/README.md b/README.md index c516739..043fcf7 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ English| [简体中文](./README-zh.md) ## Online Case -- [Cooperative editing demo](http://luckysheet.lashuju.com/demo/)(Note: The official Java backend will also be open source after finishing,using OT algorithm. Please do not operate frequently to prevent the server from crashing) +- [Cooperative editing demo](http://luckysheet.lashuju.com/demo/) +- [Java backend Luckysheet Server](https://github.com/mengshukeji/LuckysheetServer) ## Plugins - Excel import and export library: [Luckyexcel](https://github.com/mengshukeji/Luckyexcel) diff --git a/docs/guide/config.md b/docs/guide/config.md index 59bfe9f..c1d9a69 100644 --- a/docs/guide/config.md +++ b/docs/guide/config.md @@ -567,7 +567,7 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - Default: null - Usage: Frame selection or trigger before setting selection - Parameter: - - {Object || Array} [range]: Selection area, may be multiple selection areas + - {Object | Array} [range]: Selection area, may be multiple selection areas ------------ ### rangeSelectAfter @@ -575,7 +575,7 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - Default: null - Usage: Frame selection or trigger after setting selection - Parameter: - - {Object || Array} [range]: Selection area, may be multiple selection areas + - {Object | Array} [range]: Selection area, may be multiple selection areas ------------ ### rangeMoveBefore @@ -600,7 +600,7 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - Default: null - Usage: Before the selection - Parameter: - - {Object || Array} [range]: Selection area, may be multiple selection areas + - {Object | Array} [range]: Selection area, may be multiple selection areas - {Object} [data]: Data corresponding to the selection area ------------ @@ -609,7 +609,7 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - Default: null - Usage: After the selection is modified - Parameter: - - {Object || Array} [range]: Selection area, may be multiple selection areas + - {Object | Array} [range]: Selection area, may be multiple selection areas - {Object} [oldData]: Before modification, the data corresponding to the selection area - {Object} [newData]: After modification, the data corresponding to the selection area @@ -619,7 +619,7 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - Default: null - Usage: Before copying selection - Parameter: - - {Object || Array} [range]: Selection area, may be multiple selection areas + - {Object | Array} [range]: Selection area, may be multiple selection areas - {Object} [data]: Data corresponding to the selection area ------------ @@ -628,7 +628,7 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - Default: null - Usage: After copying selection - Parameter: - - {Object || Array} [range]: Selection area, may be multiple selection areas + - {Object | Array} [range]: Selection area, may be multiple selection areas - {Object} [data]: Data corresponding to the selection area ------------ @@ -637,7 +637,7 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - Default: null - Usage: Before pasting the selection - Parameter: - - {Object || Array} [range]: Selection area, may be multiple selection areas + - {Object | Array} [range]: Selection area, may be multiple selection areas - {Object} [data]: The data corresponding to the selection area to be pasted ------------ @@ -646,7 +646,7 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - Default: null - Usage: After pasting the selection - Parameter: - - {Object || Array} [range]: Selection area, may be multiple selection areas + - {Object | Array} [range]: Selection area, may be multiple selection areas - {Object} [originData]: The data corresponding to the selection area to be pasted - {Object} [pasteData]: Data to paste @@ -692,7 +692,7 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - Default: null - Usage: Before the selection is cleared - Parameter: - - {Object || Array} [range]: Selection area, may be multiple selection areas + - {Object | Array} [range]: Selection area, may be multiple selection areas - {Object} [data]: The data corresponding to the selection area to be cleared ------------ @@ -701,7 +701,7 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - Default: null - Usage: After the selection is cleared - Parameter: - - {Object || Array} [range]: Selection area, may be multiple selection areas + - {Object | Array} [range]: Selection area, may be multiple selection areas - {Object} [data]: The data corresponding to the selection area to be cleared ------------ diff --git a/docs/guide/resource.md b/docs/guide/resource.md index 783c4ab..3066fc3 100644 --- a/docs/guide/resource.md +++ b/docs/guide/resource.md @@ -12,6 +12,9 @@ If you have written or found an excellent tutorial and want to recommend it to u ## Back-end +### Official case +- [Java backend Luckysheet Server](https://github.com/mengshukeji/LuckysheetServer) + ### Community Case - [Luckysheet save and restore](https://gitee.com/ichiva/luckysheet-saved-in-recovery) (Java version) - [Online form for collaborative editing based on Luckysheet](https://github.com/DilemmaVi/ecsheet) (Java version) diff --git a/docs/zh/guide/api.md b/docs/zh/guide/api.md index 2ce1d6e..bdf87b0 100644 --- a/docs/zh/guide/api.md +++ b/docs/zh/guide/api.md @@ -2440,7 +2440,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ------------ -## 公共方法 +## 工具方法 ### transToCellData(data [,setting])
@@ -2481,6 +2481,43 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ------------ +### getRangeByTxt([txt]) + +- **说明**: + + 将字符串格式的工作表范围转换为数组形式 + +- **参数**: + + + {String} [txt]: 选区范围,支持选区的格式为`"A1:B2"`或者指定工作表名称的写法`"sheetName!A1:B2"`,只支持单个选区;默认为当前最后一个选区 + +- **示例**: + + - 当前选区为`A1:B2`,`luckysheet.getRangeByTxt()`返回:`{column: (2) [0, 1],row: (2) [0, 1]}` + - `luckysheet.getRangeByTxt("A1:B2")`返回:`{column: (2) [0, 1],row: (2) [0, 1]}` + - `luckysheet.getRangeByTxt("Cell!A1:B2")`返回:`{column: (2) [0, 1],row: (2) [0, 1]}` + +------------ + +### getTxtByRange([range]) + +- **说明**: + + 将数组格式的工作表范围转换为字符串格式的形式 + +- **参数**: + + + {Array | Object} [range]: 选区范围,支持选区的格式为`{row:[0,1],column:[0,1]}`,允许多个选区组成的数组;默认为当前选区 + +- **示例**: + + - 当前选区为`A1:B3`,`luckysheet.getTxtByRange()`返回:当前选区`"A1:B3"` + - `luckysheet.getTxtByRange({column:[0,1],row:[0,2]})`返回:`"A1:B3"` + - `luckysheet.getTxtByRange([{column:[0,1],row:[0,2]}])`返回:`"A1:B3"` + - `luckysheet.getTxtByRange([{column:[0,1],row:[0,2]},{column:[1,1],row:[1,2]}])`返回:`"A1:B3,B2:B3"` + +------------ + ## 旧版API diff --git a/docs/zh/guide/config.md b/docs/zh/guide/config.md index 53ad21c..f8cb44f 100644 --- a/docs/zh/guide/config.md +++ b/docs/zh/guide/config.md @@ -607,7 +607,7 @@ Luckysheet开放了更细致的自定义配置选项,分别有 > 使用案例可参考源码 [src/index.html](https://github.com/mengshukeji/Luckysheet/blob/master/src/index.html) -## 单元格 +## 单元格渲染 ### cellRenderBefore @@ -844,24 +844,15 @@ Luckysheet开放了更细致的自定义配置选项,分别有 ------------ -## 选区 +## 选区操作(包括单元格) -### rangeSelectBefore -(TODO) -- 类型:Function -- 默认值:null -- 作用:框选或者设置选区前触发 -- 参数: - - {Object || Array} [range]: 选区范围,可能为多个选区 +### rangeSelect ------------- -### rangeSelectAfter -(TODO) - 类型:Function - 默认值:null - 作用:框选或者设置选区后触发 - 参数: - - {Object || Array} [range]: 选区范围,可能为多个选区 + - {Object | Array} [range]: 选区范围,可能为多个选区 ------------ ### rangeMoveBefore @@ -889,7 +880,7 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - 默认值:null - 作用:选区修改前 - 参数: - - {Object || Array} [range]: 选区范围,可能为多个选区 + - {Object | Array} [range]: 选区范围,可能为多个选区 - {Object} [data]: 选区范围所对应的数据 ------------ @@ -899,7 +890,7 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - 默认值:null - 作用:选区修改后 - 参数: - - {Object || Array} [range]: 选区范围,可能为多个选区 + - {Object | Array} [range]: 选区范围,可能为多个选区 - {Object} [oldData]: 修改前选区范围所对应的数据 - {Object} [newData]: 修改后选区范围所对应的数据 @@ -910,7 +901,7 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - 默认值:null - 作用:选区复制前 - 参数: - - {Object || Array} [range]: 选区范围,可能为多个选区 + - {Object | Array} [range]: 选区范围,可能为多个选区 - {Object} [data]: 选区范围所对应的数据 ------------ @@ -920,7 +911,7 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - 默认值:null - 作用:选区复制后 - 参数: - - {Object || Array} [range]: 选区范围,可能为多个选区 + - {Object | Array} [range]: 选区范围,可能为多个选区 - {Object} [data]: 选区范围所对应的数据 ------------ @@ -930,7 +921,7 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - 默认值:null - 作用:选区粘贴前 - 参数: - - {Object || Array} [range]: 选区范围,可能为多个选区 + - {Object | Array} [range]: 选区范围,可能为多个选区 - {Object} [data]: 要被粘贴的选区范围所对应的数据 ------------ @@ -940,7 +931,7 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - 默认值:null - 作用:选区粘贴后 - 参数: - - {Object || Array} [range]: 选区范围,可能为多个选区 + - {Object | Array} [range]: 选区范围,可能为多个选区 - {Object} [originData]: 要被粘贴的选区范围所对应的数据 - {Object} [pasteData]: 要粘贴的数据 @@ -991,7 +982,7 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - 默认值:null - 作用:选区清除前 - 参数: - - {Object || Array} [range]: 选区范围,可能为多个选区 + - {Object | Array} [range]: 选区范围,可能为多个选区 - {Object} [data]: 要被清除的选区范围所对应的数据 ------------ @@ -1001,7 +992,7 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - 默认值:null - 作用:选区清除后 - 参数: - - {Object || Array} [range]: 选区范围,可能为多个选区 + - {Object | Array} [range]: 选区范围,可能为多个选区 - {Object} [data]: 被清除的选区范围所对应的数据 ------------ diff --git a/docs/zh/guide/resource.md b/docs/zh/guide/resource.md index c05f156..e41b939 100644 --- a/docs/zh/guide/resource.md +++ b/docs/zh/guide/resource.md @@ -12,10 +12,13 @@ ## 后台 +### 官方案例 +- [Java 后台 Luckysheet Server](https://github.com/mengshukeji/LuckysheetServer) + ### 社区案例 - [Luckysheet保存与恢复](https://gitee.com/ichiva/luckysheet-saved-in-recovery)(Java版) - [基于Luckysheet实现的协同编辑在线表格](https://github.com/DilemmaVi/ecsheet)(Java版) -- [使用.net core 3.1和Npoi 制作基于LuckSheet的基础导出](https://blog.csdn.net/DCDC2020/article/details/108486525) +- [使用.net core 3.1和Npoi 制作基于LuckSheet的基础导出](https://blog.csdn.net/DCDC2020/article/details/108486525)(.NET 版本) ## 学习资料 diff --git a/src/controllers/conditionformat.js b/src/controllers/conditionformat.js index 235d9c2..599babb 100644 --- a/src/controllers/conditionformat.js +++ b/src/controllers/conditionformat.js @@ -1470,7 +1470,6 @@ const conditionformat = { range.push(formula.getcellrange(txt)); } } - return range; }, colorSelectInit: function(){ diff --git a/src/controllers/handler.js b/src/controllers/handler.js index f44c8e1..1f5b192 100644 --- a/src/controllers/handler.js +++ b/src/controllers/handler.js @@ -1063,7 +1063,7 @@ export default function luckysheetHandler() { }); } else { - Store.luckysheet_select_save = []; + Store.luckysheet_select_save.length = 0; Store.luckysheet_select_save.push({ "left": col_pre, "width": col - col_pre - 1, @@ -1095,10 +1095,8 @@ export default function luckysheetHandler() { luckysheetactiveCell(); } - if (server.allowUpdate) { - //允许编辑后的后台更新时 - server.saveParam("mv", Store.currentSheetIndex, Store.luckysheet_select_save); - } + //允许编辑后的后台更新时 + server.saveParam("mv", Store.currentSheetIndex, Store.luckysheet_select_save); } //交替颜色 diff --git a/src/controllers/listener.js b/src/controllers/listener.js index 5c5ad1e..f253d22 100644 --- a/src/controllers/listener.js +++ b/src/controllers/listener.js @@ -4,10 +4,9 @@ import {createProxy} from '../utils/util' import Store from '../store/index' const initListener = function(){ - createProxy(Store,['jfredo']) + createProxy(Store,['jfredo']); } - export { initListener } \ No newline at end of file diff --git a/src/controllers/rowColumnOperation.js b/src/controllers/rowColumnOperation.js index 9889929..65aa8c0 100644 --- a/src/controllers/rowColumnOperation.js +++ b/src/controllers/rowColumnOperation.js @@ -323,7 +323,7 @@ export function rowColumnOperationInitial(){ }); } else{ - Store.luckysheet_select_save = []; + Store.luckysheet_select_save.length = 0; Store.luckysheet_select_save.push({ "left": colLocationByIndex(0)[0], "width": colLocationByIndex(0)[1] - colLocationByIndex(0)[0] - 1, @@ -343,10 +343,8 @@ export function rowColumnOperationInitial(){ selectHightlightShow(); - if(server.allowUpdate){ - //允许编辑后的后台更新时 - server.saveParam("mv", Store.currentSheetIndex, Store.luckysheet_select_save); - } + //允许编辑后的后台更新时 + server.saveParam("mv", Store.currentSheetIndex, Store.luckysheet_select_save); } selectHelpboxFill(); @@ -737,7 +735,7 @@ export function rowColumnOperationInitial(){ }); } else{ - Store.luckysheet_select_save = []; + Store.luckysheet_select_save.length = 0; Store.luckysheet_select_save.push({ "left": left, "width": width, @@ -757,10 +755,8 @@ export function rowColumnOperationInitial(){ selectHightlightShow(); - if(server.allowUpdate){ - //允许编辑后的后台更新时 - server.saveParam("mv", Store.currentSheetIndex, Store.luckysheet_select_save); - } + //允许编辑后的后台更新时 + server.saveParam("mv", Store.currentSheetIndex, Store.luckysheet_select_save); } selectHelpboxFill(); diff --git a/src/controllers/select.js b/src/controllers/select.js index a4c1b01..5ab5653 100644 --- a/src/controllers/select.js +++ b/src/controllers/select.js @@ -7,6 +7,7 @@ import dataVerificationCtrl from './dataVerificationCtrl'; import { getSheetIndex, getRangetxt } from '../methods/get'; import Store from '../store'; import locale from '../locale/locale'; +import method from '../global/method'; //公式函数 选区实体框 function seletedHighlistByindex(id, r1, r2, c1, c2) { @@ -182,6 +183,15 @@ function selectHightlightShow(isRestore=false) { } Store.luckysheetfile[getSheetIndex(Store.currentSheetIndex)].luckysheet_select_save = Store.luckysheet_select_save; + + // Hook function, change the range selection box, selectHightlightShow will be triggered multiple times when mousemove is moused, and the historical value is used here to throttle + const luckysheet_select_save_previous = JSON.stringify(Store.luckysheet_select_save); + + if(Store.luckysheet_select_save_previous == null || Store.luckysheet_select_save_previous !== luckysheet_select_save_previous){ + method.createHookFunction('rangeSelect', Store.currentSheetIndex, Store.luckysheet_select_save); + } + + Store.luckysheet_select_save_previous = luckysheet_select_save_previous; } //选区标题栏 diff --git a/src/controllers/server.js b/src/controllers/server.js index 6075c48..264531f 100644 --- a/src/controllers/server.js +++ b/src/controllers/server.js @@ -13,6 +13,7 @@ import Store from '../store'; import locale from '../locale/locale'; import dayjs from "dayjs"; import imageCtrl from './imageCtrl'; +import method from '../global/method'; const server = { gridKey: null, @@ -76,6 +77,7 @@ const server = { } }, saveParam: function (type, index, value, params) { + let _this = this; if(!_this.allowUpdate){ @@ -96,6 +98,7 @@ const server = { return; } + if (type == "rv") { //单元格批量更新 d.range = params.range; } diff --git a/src/controllers/sheetBar.js b/src/controllers/sheetBar.js index 897813e..e49bc0b 100644 --- a/src/controllers/sheetBar.js +++ b/src/controllers/sheetBar.js @@ -206,8 +206,8 @@ export function initialSheetBar(){ let $t = $(this), $cur = $(e.target); luckysheetsheetrightclick($t, $cur, e); - let result = Store.result - server.websocket.onmessage(result) + // let result = Store.result + // server.websocket.onmessage(result) }); let luckysheetsheetnameeditor = function ($t) { diff --git a/src/function/functionImplementation.js b/src/function/functionImplementation.js index dc41cef..a3b37b5 100644 --- a/src/function/functionImplementation.js +++ b/src/function/functionImplementation.js @@ -19560,7 +19560,8 @@ const functionImplementation = { var value_if_error = func_methods.getFirstValue(arguments[1], "text"); var value = func_methods.getFirstValue(arguments[0], "text"); - if(valueIsError(value)){ + // (getObjType(value) === 'string' && $.trim(value) === ''It means that the cell associated with IFERROR has been deleted by keyboard + if(valueIsError(value) || (getObjType(value) === 'string' && $.trim(value) === '' )){ return value_if_error; } diff --git a/src/global/api.js b/src/global/api.js index 36cfb8a..d76dabb 100644 --- a/src/global/api.js +++ b/src/global/api.js @@ -5901,3 +5901,39 @@ export function toJson(){ return toJsonOptions; } + +/** + * 根据范围字符串转换为range数组 + * @param {String} txt 范围字符串 + */ +export function getRangeByTxt(txt){ + + // 默认取当前第一个范围 + if(txt == null){ + return { + column:Store.luckysheet_select_save[Store.luckysheet_select_save.length - 1].column, + row:Store.luckysheet_select_save[Store.luckysheet_select_save.length - 1].row + } + } + + const range = conditionformat.getRangeByTxt(txt); + + return { + column:range[0].column, + row:range[0].row + }; +} + + +/** + * 根据范围数组转换为范围字符串 + * @param {Object | Array} range 范围数组 + */ +export function getTxtByRange(range=Store.luckysheet_select_save){ + + // 单个范围 + if(getObjType(range) === 'object'){ + range = [range]; + } + return conditionformat.getTxtByRange(range); +} \ No newline at end of file diff --git a/src/global/formula.js b/src/global/formula.js index 6f4e9bb..cdc6a55 100644 --- a/src/global/formula.js +++ b/src/global/formula.js @@ -1610,9 +1610,6 @@ const luckysheetformula = { } } - // 退出编辑模式后,发送后台取消“正在输入”提示 - // server.saveParam("mv", Store.currentSheetIndex, "exitEdit"); - if(isRefresh){ jfrefreshgrid(d, [{ "row": [r, r], "column": [c, c] }], allParam, isRunExecFunction); // Store.luckysheetCellUpdate.length = 0; //clear array @@ -4001,7 +3998,8 @@ const luckysheetformula = { } else { if (matchConfig.dquote == 0 && matchConfig.squote==0) { - str += $.trim(s); + // str += $.trim(s); + str += s; //Do not use $.trim(s). When obtaining the worksheet name that contains spaces, you should keep the spaces } else { str += s; diff --git a/src/global/method.js b/src/global/method.js index 3096da0..ec774f3 100644 --- a/src/global/method.js +++ b/src/global/method.js @@ -369,7 +369,7 @@ const method = { luckysheetcreatesheet(data[0].length, data.length, data, null, false); file["load"] = "1"; - Store.luckysheet_select_save = []; + Store.luckysheet_select_save.length = 0; Store.luckysheet_selection_range = []; server.saveParam("shs", null, Store.currentSheetIndex); diff --git a/src/index.html b/src/index.html index bd7ca9d..1c1c8d5 100644 --- a/src/index.html +++ b/src/index.html @@ -114,6 +114,9 @@ }, sheetActivate:function(index, isPivotInitial, isNewSheet){ // console.info(index, isPivotInitial, isNewSheet) + }, + rangeSelect:function(index, range){ + // console.info(index, range) }