locationCell.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. import { replaceHtml } from '../utils/util';
  2. import { getSheetIndex } from '../methods/get';
  3. import { isRealNull } from '../global/validate';
  4. import { isEditMode } from '../global/validate';
  5. import tooltip from '../global/tooltip';
  6. import { modelHTML } from './constant';
  7. import { selectHightlightShow } from './select';
  8. import conditionformat from './conditionformat';
  9. import Store from '../store';
  10. import locale from '../locale/locale';
  11. //定位
  12. const luckysheetLocationCell = {
  13. createDialog: function(){
  14. $("#luckysheet-modal-dialog-mask").show();
  15. $("#luckysheet-locationCell-dialog").remove();
  16. const _locale = locale();
  17. const locale_location = _locale.findAndReplace;
  18. const locale_button = _locale.button;
  19. let content = '<div class="listbox">'+
  20. '<div class="listItem">'+
  21. '<input type="radio" name="locationType" checked="checked" id="locationConstant">'+
  22. '<label for="locationConstant">'+locale_location.locationConstant+'</label>'+
  23. '<div class="subbox">'+
  24. '<div class="subItem">'+
  25. '<input type="checkbox" checked="checked" class="date" id="locationConstantDate">'+
  26. '<label for="locationConstantDate">'+locale_location.locationDate+'</label>'+
  27. '</div>'+
  28. '<div class="subItem">'+
  29. '<input type="checkbox" checked="checked" class="number" id="locationConstantNumber">'+
  30. '<label for="locationConstantNumber">'+locale_location.locationDigital+'</label>'+
  31. '</div>'+
  32. '<div class="subItem">'+
  33. '<input type="checkbox" checked="checked" class="string" id="locationConstantString">'+
  34. '<label for="locationConstantString">'+locale_location.locationString+'</label>'+
  35. '</div>'+
  36. '<div class="subItem">'+
  37. '<input type="checkbox" checked="checked" class="boolean" id="locationConstantBoolean">'+
  38. '<label for="locationConstantBoolean">'+locale_location.locationBool+'</label>'+
  39. '</div>'+
  40. '<div class="subItem">'+
  41. '<input type="checkbox" checked="checked" class="error" id="locationConstantError">'+
  42. '<label for="locationConstantError">'+locale_location.locationBool+'</label>'+
  43. '</div>'+
  44. '</div>'+
  45. '</div>'+
  46. '<div class="listItem">'+
  47. '<input type="radio" name="locationType" id="locationFormula">'+
  48. '<label for="locationFormula">'+locale_location.locationFormula+'</label>'+
  49. '<div class="subbox">'+
  50. '<div class="subItem">'+
  51. '<input type="checkbox" checked="checked" class="date" id="locationFormulaDate" disabled="true">'+
  52. '<label for="locationFormulaDate" style="color: #666">'+locale_location.locationDate+'</label>'+
  53. '</div>'+
  54. '<div class="subItem">'+
  55. '<input type="checkbox" checked="checked" class="number" id="locationFormulaNumber" disabled="true">'+
  56. '<label for="locationFormulaNumber" style="color: #666">'+locale_location.locationDigital+'</label>'+
  57. '</div>'+
  58. '<div class="subItem">'+
  59. '<input type="checkbox" checked="checked" class="string" id="locationFormulaString" disabled="true">'+
  60. '<label for="locationFormulaString" style="color: #666">'+locale_location.locationString+'</label>'+
  61. '</div>'+
  62. '<div class="subItem">'+
  63. '<input type="checkbox" checked="checked" class="boolean" id="locationFormulaBoolean" disabled="true">'+
  64. '<label for="locationFormulaBoolean" style="color: #666">'+locale_location.locationBool+'</label>'+
  65. '</div>'+
  66. '<div class="subItem">'+
  67. '<input type="checkbox" checked="checked" class="error" id="locationFormulaError" disabled="true">'+
  68. '<label for="locationFormulaError" style="color: #666">'+locale_location.locationError+'</label>'+
  69. '</div>'+
  70. '</div>'+
  71. '</div>'+
  72. '<div class="listItem">'+
  73. '<input type="radio" name="locationType" id="locationNull">'+
  74. '<label for="locationNull">'+locale_location.locationNull+'</label>'+
  75. '</div>'+
  76. '<div class="listItem">'+
  77. '<input type="radio" name="locationType" id="locationCF">'+
  78. '<label for="locationCF">'+locale_location.locationCondition+'</label>'+
  79. '</div>'+
  80. '<div class="listItem">'+
  81. '<input type="radio" name="locationType" id="locationStepRow">'+
  82. '<label for="locationStepRow">'+locale_location.locationRowSpan+'</label>'+
  83. '</div>'+
  84. '<div class="listItem">'+
  85. '<input type="radio" name="locationType" id="locationStepColumn">'+
  86. '<label for="locationStepColumn">'+locale_location.locationColumnSpan+'</label>'+
  87. '</div>'+
  88. '</div>';
  89. $("body").first().append(replaceHtml(modelHTML, {
  90. "id": "luckysheet-locationCell-dialog",
  91. "addclass": "luckysheet-locationCell-dialog",
  92. "title": locale_location.location,
  93. "content": content,
  94. "botton": '<button id="luckysheet-locationCell-dialog-confirm" class="btn btn-primary">'+locale_button.confirm+'</button><button class="btn btn-default luckysheet-model-close-btn">'+locale_button.cancel+'</button>',
  95. "style": "z-index:100003"
  96. }));
  97. let $t = $("#luckysheet-locationCell-dialog").find(".luckysheet-modal-dialog-content").css("min-width", 400).end(),
  98. myh = $t.outerHeight(),
  99. myw = $t.outerWidth();
  100. let winw = $(window).width(), winh = $(window).height();
  101. let scrollLeft = $(document).scrollLeft(), scrollTop = $(document).scrollTop();
  102. $("#luckysheet-locationCell-dialog").css({ "left": (winw + scrollLeft - myw) / 2, "top": (winh + scrollTop - myh) / 3 }).show();
  103. },
  104. init: function(){
  105. let _this = this;
  106. const locale_location = locale().findAndReplace;
  107. $(document).on("click", "#luckysheet-locationCell-dialog .listItem input:radio", function(e){
  108. $("#luckysheet-locationCell-dialog .listItem input:checkbox").prop("disabled", true);
  109. $("#luckysheet-locationCell-dialog .listItem .subbox label").css("color", "#666");
  110. $(this).siblings(".subbox").find("input:checkbox").removeAttr("disabled");
  111. $(this).siblings(".subbox").find("label").css("color", "#000");
  112. });
  113. $(document).off("click.locationCellConfirm").on("click.locationCellConfirm", "#luckysheet-locationCell-dialog #luckysheet-locationCell-dialog-confirm", function(){
  114. $("#luckysheet-modal-dialog-mask").hide();
  115. $("#luckysheet-locationCell-dialog").hide();
  116. let $radio = $("#luckysheet-locationCell-dialog .listItem input:radio:checked");
  117. let id = $radio.attr("id");
  118. if(id == "locationConstant" || id == "locationFormula"){
  119. let $checkbox = $radio.siblings(".subbox").find("input:checkbox:checked");
  120. let value;
  121. if($checkbox.length == 0){
  122. return;
  123. }
  124. else if($checkbox.length == 5){
  125. value = "all";
  126. }
  127. else{
  128. let arr = [];
  129. for(let i = 0; i < $checkbox.length; i++){
  130. if($($checkbox[i]).hasClass("date")){
  131. arr.push("d");
  132. }
  133. else if($($checkbox[i]).hasClass("number")){
  134. arr.push("n");
  135. }
  136. else if($($checkbox[i]).hasClass("string")){
  137. arr.push("s,g");
  138. }
  139. else if($($checkbox[i]).hasClass("boolean")){
  140. arr.push("b");
  141. }
  142. else if($($checkbox[i]).hasClass("error")){
  143. arr.push("e");
  144. }
  145. }
  146. value = arr.join(",");
  147. }
  148. let range;
  149. if(Store.luckysheet_select_save.length == 0 || (Store.luckysheet_select_save.length == 1 && Store.luckysheet_select_save[0].row[0] == Store.luckysheet_select_save[0].row[1] && Store.luckysheet_select_save[0].column[0] == Store.luckysheet_select_save[0].column[1])){
  150. //单个单元格
  151. range = [{"row": [0, Store.flowdata.length - 1], "column": [0, Store.flowdata[0].length - 1]}];
  152. }
  153. else{
  154. range = $.extend(true, [], Store.luckysheet_select_save);
  155. }
  156. _this.apply(range, id, value);
  157. }
  158. else if(id == "locationStepRow"){
  159. if(Store.luckysheet_select_save.length == 0 || (Store.luckysheet_select_save.length == 1 && Store.luckysheet_select_save[0].row[0] == Store.luckysheet_select_save[0].row[1])){
  160. if(isEditMode()){
  161. alert(locale_location.locationTiplessTwoRow);
  162. }
  163. else{
  164. tooltip.info("", locale_location.locationTiplessTwoRow);
  165. }
  166. return;
  167. }
  168. let range = $.extend(true, [], Store.luckysheet_select_save);
  169. _this.apply(range, "locationStepRow");
  170. }
  171. else if(id == "locationStepColumn"){
  172. if(Store.luckysheet_select_save.length == 0 || (Store.luckysheet_select_save.length == 1 && Store.luckysheet_select_save[0].column[0] == Store.luckysheet_select_save[0].column[1])){
  173. if(isEditMode()){
  174. alert(locale_location.locationTiplessTwoColumn);
  175. }
  176. else{
  177. tooltip.info("", locale_location.locationTiplessTwoColumn);
  178. }
  179. return;
  180. }
  181. let range = $.extend(true, [], Store.luckysheet_select_save);
  182. _this.apply(range, "locationStepColumn");
  183. }
  184. else{
  185. let range;
  186. if(Store.luckysheet_select_save.length == 0 || (Store.luckysheet_select_save.length == 1 && Store.luckysheet_select_save[0].row[0] == Store.luckysheet_select_save[0].row[1] && Store.luckysheet_select_save[0].column[0] == Store.luckysheet_select_save[0].column[1])){
  187. //单个单元格
  188. range = [{"row": [0, Store.flowdata.length - 1], "column": [0, Store.flowdata[0].length - 1]}];
  189. }
  190. else{
  191. range = $.extend(true, [], Store.luckysheet_select_save);
  192. }
  193. _this.apply(range, id);
  194. }
  195. });
  196. },
  197. apply: function(range, type, value){
  198. const locale_location = locale().findAndReplace;
  199. let rangeArr = [];
  200. if(type == "locationFormula" || type == "locationConstant" || type == "locationNull"){ //公式 常量 空值
  201. let minR = null, maxR = null, minC = null, maxC = null, cellSave = {};
  202. for(let s = 0; s < range.length; s++){
  203. let st_r = range[s].row[0],
  204. ed_r = range[s].row[1],
  205. st_c = range[s].column[0],
  206. ed_c = range[s].column[1];
  207. if(minR == null || minR < st_r){
  208. minR = st_r;
  209. }
  210. if(maxR == null || maxR > ed_r){
  211. maxR = ed_r;
  212. }
  213. if(minC == null || minC < st_c){
  214. minC = st_c;
  215. }
  216. if(maxC == null || maxC > ed_c){
  217. maxC = ed_c;
  218. }
  219. for(let r = st_r; r <= ed_r; r++){
  220. for(let c = st_c; c <= ed_c; c++){
  221. let cell = Store.flowdata[r][c];
  222. if(cell != null && cell.mc != null){
  223. cell = Store.flowdata[cell.mc.r][cell.mc.c];
  224. }
  225. if(type == 'locationFormula' && cell != null && !isRealNull(cell.v) && cell.f != null && (value == 'all' || (cell.ct != null && value.indexOf(cell.ct.t) > -1))){
  226. cellSave[r + '_' + c] = 0;
  227. }
  228. else if(type == 'locationConstant' && cell != null && !isRealNull(cell.v) && (value == 'all' || (cell.ct != null && value.indexOf(cell.ct.t) > -1))){
  229. cellSave[r + '_' + c] = 0;
  230. }
  231. else if(type == 'locationNull' && (cell == null || isRealNull(cell.v))){
  232. cellSave[r + '_' + c] = 0;
  233. }
  234. }
  235. }
  236. }
  237. rangeArr = this.getRangeArr(minR, maxR, minC, maxC, cellSave, rangeArr);
  238. }
  239. else if(type == "locationCF"){ //条件格式
  240. let index = getSheetIndex(Store.currentSheetIndex);
  241. let ruleArr = Store.luckysheetfile[index]["luckysheet_conditionformat_save"];
  242. let data = Store.luckysheetfile[index]["data"];
  243. if(ruleArr == null || ruleArr.length == 0){
  244. if(isEditMode()){
  245. alert(locale_location.locationTipNotFindCell);
  246. }
  247. else{
  248. tooltip.info("", locale_location.locationTipNotFindCell);
  249. }
  250. return;
  251. }
  252. computeMap = conditionformat.compute(ruleArr, data);
  253. if(Object.keys(computeMap).length == 0){
  254. if(isEditMode()){
  255. alert(locale_location.locationTipNotFindCell);
  256. }
  257. else{
  258. tooltip.info("", locale_location.locationTipNotFindCell);
  259. }
  260. return;
  261. }
  262. let minR = null, maxR = null, minC = null, maxC = null, cellSave = {};
  263. for(let s = 0; s < range.length; s++){
  264. let st_r = range[s].row[0],
  265. ed_r = range[s].row[1],
  266. st_c = range[s].column[0],
  267. ed_c = range[s].column[1];
  268. if(minR == null || minR < st_r){
  269. minR = st_r;
  270. }
  271. if(maxR == null || maxR > ed_r){
  272. maxR = ed_r;
  273. }
  274. if(minC == null || minC < st_c){
  275. minC = st_c;
  276. }
  277. if(maxC == null || maxC > ed_c){
  278. maxC = ed_c;
  279. }
  280. for(let r = st_r; r <= ed_r; r++){
  281. for(let c = st_c; c <= ed_c; c++){
  282. if((r + '_' + c) in computeMap){
  283. cellSave[r + '_' + c] = 0;
  284. }
  285. }
  286. }
  287. }
  288. rangeArr = this.getRangeArr(minR, maxR, minC, maxC, cellSave, rangeArr);
  289. }
  290. else if(type == "locationStepRow"){ //间隔行
  291. for(let s = 0; s < range.length; s++){
  292. if(range[s].row[0] == range[s].row[1]){
  293. continue;
  294. }
  295. let st_r = range[s].row[0], ed_r = range[s].row[1];
  296. let st_c = range[s].column[0], ed_c = range[s].column[1];
  297. for(let r = st_r; r <= ed_r; r++){
  298. if((r - st_r) % 2 == 0){
  299. rangeArr.push({"row": [r, r], "column": [st_c, ed_c]});
  300. }
  301. }
  302. }
  303. }
  304. else if(type == "locationStepColumn"){ //间隔列
  305. for(let s = 0; s < range.length; s++){
  306. if(range[s].column[0] == range[s].column[1]){
  307. continue;
  308. }
  309. let st_r = range[s].row[0], ed_r = range[s].row[1];
  310. let st_c = range[s].column[0], ed_c = range[s].column[1];
  311. for(let c = st_c; c <= ed_c; c++){
  312. if((c - st_c) % 2 == 0){
  313. rangeArr.push({"row": [st_r, ed_r], "column": [c, c]});
  314. }
  315. }
  316. }
  317. }
  318. if(rangeArr.length == 0){
  319. if(isEditMode()){
  320. alert(locale_location.locationTipNotFindCell);
  321. }
  322. else{
  323. tooltip.info("", locale_location.locationTipNotFindCell);
  324. }
  325. }
  326. else{
  327. Store.luckysheet_select_save = rangeArr;
  328. selectHightlightShow();
  329. let scrollLeft = $("#luckysheet-cell-main").scrollLeft(),
  330. scrollTop = $("#luckysheet-cell-main").scrollTop();
  331. let winH = $("#luckysheet-cell-main").height(),
  332. winW = $("#luckysheet-cell-main").width();
  333. let r1 = Store.luckysheet_select_save[0]["row"][0],
  334. r2 = Store.luckysheet_select_save[0]["row"][1],
  335. c1 = Store.luckysheet_select_save[0]["column"][0],
  336. c2 = Store.luckysheet_select_save[0]["column"][1];
  337. let row = Store.visibledatarow[r2],
  338. row_pre = r1 - 1 == -1 ? 0 : Store.visibledatarow[r1 - 1];
  339. let col = Store.visibledatacolumn[c2],
  340. col_pre = c1 - 1 == -1 ? 0 : Store.visibledatacolumn[c1 - 1];
  341. if (col - scrollLeft - winW + 20 > 0) {
  342. $("#luckysheet-scrollbar-x").scrollLeft(col - winW + 20);
  343. }
  344. else if (col_pre - scrollLeft - 20 < 0) {
  345. $("#luckysheet-scrollbar-x").scrollLeft(col_pre - 20);
  346. }
  347. if (row - scrollTop - winH + 20 > 0) {
  348. $("#luckysheet-scrollbar-y").scrollTop(row - winH + 20);
  349. }
  350. else if (row_pre - scrollTop - 20 < 0) {
  351. $("#luckysheet-scrollbar-y").scrollTop(row_pre - 20);
  352. }
  353. }
  354. },
  355. getRangeArr(minR, maxR, minC, maxC, cellSave, rangeArr){
  356. if(Object.keys(cellSave).length == 0){
  357. return rangeArr;
  358. }
  359. let _this = this;
  360. let stack_str = null,
  361. stack_edr = null,
  362. stack_stc = null,
  363. stack_edc = null;
  364. for(let r = minR; r <= maxR; r++){
  365. for(let c = minC; c <= maxC; c++){
  366. let cell = Store.flowdata[r][c];
  367. if((r + '_' + c) in cellSave){
  368. if(cell != null && cell.mc != null){
  369. if(stack_stc == null){
  370. let range = {
  371. 'row': [cell.mc.r, cell.mc.r + cell.mc.rs - 1],
  372. 'column': [cell.mc.c, cell.mc.c + cell.mc.cs - 1]
  373. };
  374. rangeArr.push(range);
  375. cellSave = _this.deleteCellInSave(cellSave, range);
  376. return _this.getRangeArr(minR, maxR, minC, maxC, cellSave, rangeArr);
  377. }
  378. else if(c < stack_edc){
  379. let range = {
  380. 'row': [stack_str, stack_edr],
  381. 'column': [stack_stc, stack_edc]
  382. }
  383. rangeArr.push(range);
  384. cellSave = _this.deleteCellInSave(cellSave, range);
  385. return _this.getRangeArr(minR, maxR, minC, maxC, cellSave, rangeArr);
  386. }
  387. else{
  388. break;
  389. }
  390. }
  391. else if(stack_stc == null){
  392. stack_stc = c;
  393. stack_edc = c;
  394. stack_str = r;
  395. stack_edr = r;
  396. }
  397. else if(c > stack_edc){
  398. stack_edc = c;
  399. }
  400. }
  401. else if(stack_stc != null){
  402. if(cell != null && cell.mc != null){
  403. break;
  404. }
  405. else if(c < stack_stc){
  406. }
  407. else if(c <= stack_edc){
  408. let range = {
  409. 'row': [stack_str, stack_edr],
  410. 'column': [stack_stc, stack_edc]
  411. }
  412. rangeArr.push(range);
  413. cellSave = _this.deleteCellInSave(cellSave, range);
  414. return _this.getRangeArr(minR, maxR, minC, maxC, cellSave, rangeArr);
  415. }
  416. else{
  417. stack_edr = r;
  418. }
  419. }
  420. }
  421. }
  422. if(stack_stc != null){
  423. let range = {
  424. 'row': [stack_str, stack_edr],
  425. 'column': [stack_stc, stack_edc]
  426. }
  427. rangeArr.push(range);
  428. cellSave = _this.deleteCellInSave(cellSave, range);
  429. return _this.getRangeArr(minR, maxR, minC, maxC, cellSave, rangeArr);
  430. }
  431. },
  432. deleteCellInSave(cellSave, range){
  433. for(let r = range.row[0]; r <= range.row[1]; r++){
  434. for(let c = range.column[0]; c <= range.column[1]; c++){
  435. delete cellSave[r + '_' + c];
  436. }
  437. }
  438. return cellSave;
  439. }
  440. }
  441. export default luckysheetLocationCell;