LuckySheet.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. import React from 'react';
  2. import { Button, message } from 'antd';
  3. import exportExcel, { getExcelBolob } from '@/utils/exportExcl';
  4. import LuckyExcel from 'luckyexcel';
  5. import { getToken, GetTokenFromUrl } from '@/utils/utils';
  6. import GoalSeek from '@/utils/GoalSeek';
  7. const hintText = '禁止编辑!请先点击编辑按钮。';
  8. const DIFF_COLOR = '#ff0000';
  9. const ADD_COLOR = '#00ff00';
  10. class LuckySheet extends React.Component {
  11. constructor(props) {
  12. super(props);
  13. this.sheetRef = React.createRef();
  14. this.luckysheet = null;
  15. this.updateTimer = null;
  16. this.currentSheetIndex = null;
  17. this.updateCell = {
  18. add: [],
  19. diff: [],
  20. };
  21. this.renderTimer = null;
  22. this.chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
  23. }
  24. componentWillUnmount() {
  25. this.luckysheet?.destroy();
  26. }
  27. componentDidUpdate(prveProps) {
  28. const prevVersion = prveProps.version || {};
  29. const curVersion = this.props.version || {};
  30. if (prevVersion?.id != curVersion?.id || prevVersion?.flow_id != curVersion.flow_id) {
  31. console.log(prevVersion, curVersion);
  32. this.renderSheet();
  33. }
  34. }
  35. getUUID(len = 8, radix = 16) {
  36. var chars = this.chars;
  37. var uuid = [],
  38. i;
  39. radix = radix || chars.length;
  40. if (len) {
  41. // Compact form
  42. for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
  43. } else {
  44. // rfc4122, version 4 form
  45. var r;
  46. // rfc4122 requires these characters
  47. uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
  48. uuid[14] = '4';
  49. // Fill in random data. At i==19 set the high bits of clock sequence as
  50. // per rfc4122, sec. 4.1.5
  51. for (i = 0; i < 36; i++) {
  52. if (!uuid[i]) {
  53. r = 0 | (Math.random() * 16);
  54. uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
  55. }
  56. }
  57. }
  58. return uuid.join('');
  59. }
  60. renderSheet(currentData) {
  61. const {
  62. onClickCell,
  63. version,
  64. getUser,
  65. onUpdate,
  66. templateId,
  67. onDelSheet,
  68. permissions,
  69. node,
  70. } = this.props;
  71. const data = currentData || this.props.data;
  72. const _this = this;
  73. if (!this.luckysheet) {
  74. clearTimeout(this.renderTimer);
  75. this.renderTimer = setTimeout(() => {
  76. this.renderSheet(currentData);
  77. }, 300);
  78. return;
  79. }
  80. let token = GetTokenFromUrl() || getToken();
  81. let option = {
  82. lang: 'zh',
  83. showinfobar: false,
  84. showstatisticBar: false,
  85. // forceCalculation: true,
  86. hook: {
  87. cellMousedown: (cell, position, sheet) => {
  88. console.log(cell, position, sheet);
  89. onClickCell && onClickCell(cell, position, sheet);
  90. },
  91. cellPasteBefore: cell => {
  92. console.log(cell);
  93. if (!cell) return;
  94. if (cell.cid) delete cell.cid;
  95. if (cell.bg == DIFF_COLOR || cell.bg == ADD_COLOR) {
  96. delete cell.bg;
  97. }
  98. },
  99. updated(operate) {
  100. if (operate.type == 'datachange') {
  101. if (_this.currentSheetIndex != operate.sheetIndex) {
  102. _this.currentSheetIndex = operate.sheetIndex;
  103. return;
  104. }
  105. // 延迟1秒
  106. clearTimeout(_this.updateTimer);
  107. _this.updateTimer = setTimeout(() => {
  108. onUpdate.bind(_this);
  109. onUpdate();
  110. }, 1000);
  111. }
  112. },
  113. // 修改批注后保存sheet
  114. commentUpdateAfter() {
  115. clearTimeout(_this.updateTimer);
  116. _this.updateTimer = setTimeout(() => {
  117. onUpdate.bind(_this);
  118. onUpdate(true);
  119. }, 1000);
  120. },
  121. sheetActivate: sheet => {
  122. console.log(sheet);
  123. setTimeout(() => {
  124. this.luckysheet.setCellFormat(0, 0, 'bg', '#fff');
  125. }, 100);
  126. },
  127. sheetDeleteAfter: sheet => {
  128. onDelSheet && onDelSheet(sheet?.sheet.id);
  129. },
  130. sheetActivate: sheet => {
  131. console.log(sheet);
  132. setTimeout(() => {
  133. this.luckysheet.setCellFormat(0, 0, 'bg', '#fff');
  134. }, 100);
  135. },
  136. workbookCreateAfter: options => {
  137. setTimeout(() => {
  138. this.luckysheet.refreshFormula();
  139. }, 800);
  140. },
  141. },
  142. };
  143. if (version) {
  144. const wsUrl =
  145. process.env.NODE_ENV == 'development'
  146. ? 'ws://47.96.12.136:8896/'
  147. : `ws://${location.host}/`;
  148. option = {
  149. ...option,
  150. allowUpdate: true,
  151. gridKey: version.id,
  152. templateId: templateId,
  153. // flowId: version.flow_id,
  154. loadUrl: `/api/v1/purchase/record/sheet?gridKey=${version.id}&JWT-TOKEN=${token}`,
  155. updateUrl: wsUrl + `api/v1/ws?id=${version.id}&sid=${templateId}&JWT-TOKEN=${token}`,
  156. // updateUrl: `ws://47.96.12.136:8896/api/v1/ws?id=${version.id}&sid=${templateId}&JWT-TOKEN=${token}`,
  157. // updateUrl: `ws://120.55.44.4:8896/api/v1/ws?id=${version.id}&sid=${templateId}&JWT-TOKEN=${token}`,
  158. authorityUrl: `/api/v1/purchase/bom/user/excel/col?depId=${localStorage.depId ||
  159. 0}&JWT-TOKEN=${token}`,
  160. getUser,
  161. permissions,
  162. // workbookCreateBefore(luckysheet) {
  163. // console.log('===============================', luckysheet);
  164. // let oldConfig = JSON.parse(JSON.stringify(luckysheet.getConfig()));
  165. // setTimeout(() => {
  166. // luckysheet.setConfig({
  167. // ...oldConfig,
  168. // authority: { sheet: true, hintText },
  169. // });
  170. // }, 300);
  171. // },
  172. };
  173. console.log(version);
  174. const unableEdit = option => {
  175. option.showtoolbar = false;
  176. option.enableAddRow = false;
  177. option.sheetFormulaBar = false;
  178. option.enableAddBackTop = false;
  179. option.showsheetbarConfig = {
  180. add: false,
  181. menu: false,
  182. // sheet: false,
  183. };
  184. option.cellRightClickConfig = {
  185. copy: false, // 复制
  186. copyAs: false, // 复制为
  187. paste: false, // 粘贴
  188. insertRow: false, // 插入行
  189. insertColumn: false, // 插入列
  190. deleteRow: false, // 删除选中行
  191. deleteColumn: false, // 删除选中列
  192. deleteCell: false, // 删除单元格
  193. hideRow: false, // 隐藏选中行和显示选中行
  194. hideColumn: false, // 隐藏选中列和显示选中列
  195. rowHeight: false, // 行高
  196. columnWidth: false, // 列宽
  197. clear: false, // 清除内容
  198. matrix: false, // 矩阵操作选区
  199. sort: false, // 排序选区
  200. filter: false, // 筛选选区
  201. chart: false, // 图表生成
  202. image: false, // 插入图片
  203. link: false, // 插入链接
  204. data: false, // 数据验证
  205. cellFormat: false, // 设置单元格格式
  206. };
  207. };
  208. if (version.flow_id && node?.node_type_psr != 6) {
  209. option.authority = {
  210. sheet: true,
  211. hintText: '当前处于审批节点,禁止编辑!',
  212. };
  213. unableEdit(option);
  214. } else if (version.last_version) {
  215. option.authority = {
  216. sheet: true,
  217. hintText: '该清单已设置为最终版本,禁止编辑!',
  218. };
  219. unableEdit(option);
  220. } else if (
  221. node?.node_type_psr != 6 &&
  222. ((version.audit_status != 0 && version.audit_status != 5) || version.status == 1)
  223. ) {
  224. option.authority = {
  225. sheet: true,
  226. hintText: '当前清单不可编辑!',
  227. };
  228. unableEdit(option);
  229. } else if (node?.node_type_psr == 1 || node?.node_type_psr == 2 || node?.node_type_psr == 5) {
  230. option.authority = {
  231. sheet: true,
  232. hintText: '流程已完结,不可编辑!',
  233. };
  234. unableEdit(option);
  235. }
  236. } else if (data && data.length > 0) {
  237. option.data = JSON.parse(JSON.stringify(data));
  238. option.data.forEach(item => {
  239. if (item.celldata) {
  240. item.celldata.forEach(cell => {
  241. // 生成uuid
  242. if (!cell.v.cid) cell.v.cid = this.getUUID();
  243. });
  244. }
  245. // 默认禁止编辑
  246. // item.config.authority = { sheet: true, hintText };
  247. });
  248. } else {
  249. // 默认sheet页数据
  250. data.data = [
  251. {
  252. name: 'sheet1',
  253. // config: {
  254. // authority: { sheet: true, hintText },
  255. // },
  256. },
  257. ];
  258. }
  259. this.luckysheet.destroy();
  260. this.luckysheet.create(option);
  261. // 比对模式会导致单元格出现[Object object]的情况 任意编辑后才会正常显示
  262. // 所以默认设置第一个单元格的背景色
  263. setTimeout(() => {
  264. this.luckysheet.setCellFormat(0, 0, 'bg', '#fff');
  265. this.luckysheet.refreshFormula();
  266. }, 500);
  267. }
  268. // componentDidUpdate(prevProps) {
  269. // const { data } = this.props;
  270. // if (prevProps.data != data) {
  271. // this.renderSheet(data);
  272. // }
  273. // }
  274. handleLoad() {
  275. const { version } = this.props;
  276. let contentWindow = this.sheetRef.current.contentWindow;
  277. this.luckysheet = contentWindow.luckysheet;
  278. // this.luckysheet = this.luckysheet;
  279. // version存在 则需调用render
  280. if (version) {
  281. this.renderSheet();
  282. }
  283. // onLoad && onLoad();
  284. }
  285. selectCell(row, col, order) {
  286. this.luckysheet.setRangeShow({ row: [row, row], column: [col, col] }, { order });
  287. }
  288. toggleSheet(order) {
  289. this.luckysheet.setSheetActive(order);
  290. }
  291. getSheetJson() {
  292. let data = JSON.parse(JSON.stringify(this.luckysheet.toJson()));
  293. data.data.forEach(sheet => {
  294. let allCell = {},
  295. unknowCid = [];
  296. // 将cell以cid为界分别存储
  297. (sheet.celldata || []).forEach(cell => {
  298. if (!cell.v.cid) {
  299. unknowCid.push(cell);
  300. } else if (!allCell[cell.v.cid]) {
  301. allCell[cell.v.cid] = cell;
  302. } else {
  303. // 当存在相同cid时
  304. // 做异常处理
  305. delete cell.v.cid;
  306. unknowCid.push(cell);
  307. }
  308. if (cell.v.tb) cell.v.tb = Number(cell.v.tb);
  309. // 清除比对样式
  310. if (cell.v.bg == DIFF_COLOR || cell.v.bg == ADD_COLOR) {
  311. delete cell.v.bg;
  312. }
  313. });
  314. unknowCid.forEach(cell => {
  315. // 根据坐标生成唯一key,重复则增加后缀直至不重复
  316. let key = `${cell.r}-${cell.c}`;
  317. while (allCell[key]) {
  318. key += '|c';
  319. }
  320. cell.v.cid = key;
  321. allCell[key] = cell;
  322. });
  323. sheet.celldata = Object.values(allCell);
  324. });
  325. return data;
  326. }
  327. // 切换编辑状态
  328. toggleEdit(edit) {
  329. let luckysheet = this.luckysheet;
  330. if (edit) {
  331. let config = luckysheet.getConfig();
  332. luckysheet.setConfig({
  333. ...config,
  334. authority: { sheet: !edit, hintText },
  335. });
  336. } else {
  337. luckysheet.exitEditMode();
  338. }
  339. }
  340. // 切换比对状态
  341. toggleCompare(isCompare, compareData, callback) {
  342. let luckysheet = this.luckysheet;
  343. let diff = [];
  344. let add = [];
  345. const { onCompareSuccess } = this.props;
  346. // 判断dom是否加载完成
  347. if (!luckysheet) {
  348. setTimeout(() => {
  349. this.toggleCompare(isCompare, compareData, callback);
  350. }, 300);
  351. return;
  352. }
  353. if (isCompare) {
  354. // let currentData = this.luckysheet.toJson();
  355. let currentData = JSON.parse(JSON.stringify(this.props.data));
  356. currentData.forEach((sheet, index) => {
  357. let celldata1 = sheet.celldata;
  358. let celldata2 = compareData[index]?.celldata || [];
  359. celldata1.forEach(item => {
  360. // 不判断空字符串
  361. if (this.isEmpty(item)) return;
  362. var d2Item = celldata2.find(item2 => item2.v.cid == item.v.cid);
  363. if (d2Item && !this.isEmpty(d2Item)) {
  364. // v.ct.s相同,不做处理
  365. if (item.v.ct?.s && JSON.stringify(item.v.ct?.s) == JSON.stringify(d2Item.v.ct?.s))
  366. return;
  367. // v.v相同,不做处理
  368. if (d2Item.v.v == item.v.v) return;
  369. // 内容不同,标记diff颜色
  370. diff.push({
  371. ...item,
  372. sheetOrder: index,
  373. });
  374. item.v.bg = DIFF_COLOR;
  375. // luckysheet.setCellFormat(item.r, item.c, 'bg', DIFF_COLOR);
  376. } else {
  377. // 找不到同cid的单元格,标记add颜色
  378. add.push({
  379. ...item,
  380. sheetOrder: index,
  381. });
  382. item.v.bg = ADD_COLOR;
  383. // luckysheet.setCellFormat(item.r, item.c, 'bg', ADD_COLOR);
  384. }
  385. });
  386. });
  387. console.log(currentData);
  388. this.renderSheet(currentData);
  389. // luckysheet.refresh()
  390. } else {
  391. this.renderSheet(this.props.data);
  392. }
  393. this.updateCell = {
  394. diff,
  395. add,
  396. };
  397. callback && callback(this.updateCell);
  398. }
  399. isEmpty(item) {
  400. return (item?.v?.v ?? '') === '' && !item?.v?.ct?.s;
  401. }
  402. mergeExcl(updateCell = {}) {
  403. const { diff = [], add = [] } = updateCell;
  404. let currentData = this.luckysheet.toJson().data;
  405. let luckysheet = this.luckysheet;
  406. console.log(updateCell);
  407. diff.forEach(item => {
  408. let sheet = currentData[item.sheetOrder];
  409. let d1Item = sheet.celldata.find(item2 => item2.v.cid == item.v.cid);
  410. // 将差异项覆盖至当前文档
  411. d1Item.v = {
  412. ...item.v,
  413. bg: undefined,
  414. };
  415. });
  416. add.forEach(item => {
  417. // 将新增项添加至当前文档
  418. let sheet = currentData[item.sheetOrder];
  419. let d1Item = sheet.celldata.find(item2 => item2.r == item.r && item2.c == item.c);
  420. if (d1Item) {
  421. d1Item.v = {
  422. ...item.v,
  423. bg: undefined,
  424. };
  425. } else {
  426. sheet.celldata.push({
  427. ...item,
  428. sheetOrder: undefined,
  429. });
  430. }
  431. });
  432. currentData.forEach(sheet => {
  433. delete sheet.data;
  434. });
  435. this.renderSheet(currentData);
  436. // currentData.data.forEach((sheet, index) => {
  437. // if (!mergeData[index]) return;
  438. // let celldata1 = sheet.celldata;
  439. // let celldata2 = mergeData[index].celldata;
  440. // celldata2.forEach(item => {
  441. // let bg = item.v?.bg;
  442. // let d1Item;
  443. // if (bg == DIFF_COLOR) {
  444. // delete item.v.bg;
  445. // d1Item = celldata1.find(item2 => item2.v.cid == item.v.cid);
  446. // // 将差异项覆盖至当前文档
  447. // d1Item.v = item.v;
  448. // // luckysheet.setCellValue(d1Item.r, d1Item.c, item.v);
  449. // } else if (bg == ADD_COLOR) {
  450. // delete item.v.bg;
  451. // // 将新增项添加至当前文档
  452. // // luckysheet.setCellValue(item.r, item.c, item.v);
  453. // d1Item = celldata1.find(item2 => item2.r == item.r && item2.c == item.c);
  454. // if (d1Item) {
  455. // d1Item.v = item.v;
  456. // } else {
  457. // celldata1.push(item);
  458. // }
  459. // }
  460. // });
  461. // });
  462. // this.renderSheet(currentData);
  463. }
  464. /**
  465. * 导入excl
  466. * @param {*} files input:file的evt.target.files
  467. * @returns
  468. */
  469. uploadExcel(files, callback) {
  470. if (files == null || files.length == 0) {
  471. return;
  472. }
  473. let name = files[0].name;
  474. let suffixArr = name.split('.'),
  475. suffix = suffixArr[suffixArr.length - 1];
  476. if (suffix != 'xlsx') {
  477. alert('Currently only supports the import of xlsx files');
  478. message.error('只支持xlsx格式的文件!');
  479. return;
  480. }
  481. LuckyExcel.transformExcelToLucky(files[0], (exportJson, luckysheetfile) => {
  482. if (exportJson.sheets == null || exportJson.sheets.length == 0) {
  483. message.error('读取xlsx文件失败!');
  484. return;
  485. }
  486. // this.luckysheet.destroy();
  487. // 同步当前文档内容
  488. let data = this.props.data;
  489. exportJson.sheets.forEach((sheet, index) => {
  490. if (!data || !data[index]) return;
  491. sheet.celldata.forEach(cell => {
  492. if (this.isEmpty(cell)) return;
  493. // return (item.v.v ?? '') === '' && !item.v.ct?.s;
  494. let dCell = (data[index].celldata || []).find(dCell => {
  495. return dCell.r == cell.r && dCell.c == cell.c;
  496. });
  497. if (this.isEmpty(dCell)) return;
  498. // 判断v.ct是否相同
  499. // if (cell?.v?.ct?.s && dCell.v.ct?.s && cell.v.ct?.s.join('') != dCell.v.ct?.s.join('')) return;
  500. if (cell?.v?.ct?.s && dCell.v.ct?.s) {
  501. if (cell.v.ct?.s.join('') != dCell.v.ct?.s.join('')) return;
  502. let cellS = cell.v.ct.s;
  503. let dCellS = dCell.v.ct.s;
  504. let isEqul = cellS.every((cur, idx) => {
  505. return JSON.stringify(cur) === JSON.stringify(dCellS[idx]);
  506. });
  507. if (!isEqul) return;
  508. }
  509. // 判断v.v是否相同
  510. if (cell?.v?.v && dCell.v.v != cell.v.v) return;
  511. // 内容相同则复制cid
  512. cell.cid = dCell.cid;
  513. });
  514. });
  515. this.renderSheet(exportJson.sheets);
  516. callback && callback();
  517. });
  518. }
  519. // 根据url导入excl
  520. // selectExcel(item) {
  521. // const {value,name} = item
  522. // if (value == '') {
  523. // return;
  524. // }
  525. // LuckyExcel.transformExcelToLuckyByUrl(value, name, (exportJson, luckysheetfile) => {
  526. // if (exportJson.sheets == null || exportJson.sheets.length == 0) {
  527. // alert(
  528. // 'Failed to read the content of the excel file, currently does not support xls files!'
  529. // );
  530. // return;
  531. // }
  532. // this.luckysheet.destroy();
  533. // this.luckysheet.create({
  534. // container: 'luckysheet', //luckysheet is the container id
  535. // showinfobar: false,
  536. // data: exportJson.sheets,
  537. // title: exportJson.info.name,
  538. // userInfo: exportJson.info.name.creator,
  539. // });
  540. // });
  541. // }
  542. getExcelData(checkValue = null) {
  543. let resultList = [];
  544. console.log(this.luckysheet.getAllSheets());
  545. let currentData = this.luckysheet.getAllSheets();
  546. currentData.forEach(sheet => {
  547. let data = sheet.data;
  548. let celldata = sheet.celldata;
  549. let colList = [];
  550. data[0]?.forEach((rowOneItem, colIdx) => {
  551. if (rowOneItem) {
  552. if (!checkValue || checkValue.indexOf(rowOneItem.cid) !== -1) {
  553. colList.indexOf(colIdx) == -1 ? colList.push(colIdx) : true;
  554. }
  555. }
  556. });
  557. const newData = [];
  558. data.forEach(item => {
  559. if (item !== null) {
  560. let arr = item.filter((cur, idx) => {
  561. return item && colList.includes(idx);
  562. });
  563. newData.push(arr);
  564. }
  565. });
  566. sheet.data = newData;
  567. //消除空列后都列下标
  568. let newColIdxList = colList.map((cur, idx) => {
  569. return idx;
  570. });
  571. //处理celldata
  572. const newCellData = [];
  573. celldata.forEach(item => {
  574. let idx = colList.indexOf(item.c);
  575. if (idx !== -1) {
  576. item.c = newColIdxList[idx];
  577. newCellData.push(item);
  578. }
  579. });
  580. sheet.celldata = newCellData;
  581. });
  582. return currentData;
  583. }
  584. getExcelBolb() {
  585. let currentData = this.getExcelData();
  586. return getExcelBolob(currentData);
  587. }
  588. downloadExcel(checkValue) {
  589. let currentData = this.getExcelData(checkValue);
  590. exportExcel(currentData, '下载');
  591. }
  592. // 获取批注
  593. getComment() {
  594. let sheets = this.luckysheet.toJson().data;
  595. let comment = [];
  596. sheets.forEach(sheet => {
  597. sheet.celldata.forEach(cell => {
  598. // 判断是否含有批注
  599. if (cell?.v?.ps?.value) {
  600. comment.push({
  601. sheet: sheet.name,
  602. r: cell.r,
  603. c: cell.c,
  604. value: cell.v.ps.value || '',
  605. });
  606. }
  607. });
  608. });
  609. return comment;
  610. }
  611. async goalSeek(type, goal, setting) {
  612. const luckysheet = this.luckysheet;
  613. const sheet = this.luckysheet.getSheet({
  614. name: '毛利概算',
  615. });
  616. const order = sheet.order;
  617. try {
  618. let defaultValue = luckysheet.getCellValue(9, 2, {
  619. order,
  620. });
  621. const result = await GoalSeek({
  622. goal,
  623. fn: fn,
  624. fnParams: [defaultValue, sheet.data, type],
  625. maxIterations: 1000,
  626. independentVariableIdx: 0,
  627. ...setting,
  628. });
  629. luckysheet.setCellValue(9, 2, result, {
  630. order,
  631. });
  632. console.log(result);
  633. luckysheet.refreshFormula();
  634. message.success('计算成功');
  635. } catch (error) {
  636. message.error('计算失败');
  637. console.log(error);
  638. }
  639. }
  640. render() {
  641. return (
  642. <iframe
  643. onLoad={e => {
  644. this.handleLoad(e);
  645. }}
  646. ref={this.sheetRef}
  647. src="/luckysheet.html"
  648. ></iframe>
  649. );
  650. }
  651. }
  652. function fn(C10, data, type) {
  653. let C50 = data[49][2].v || 0;
  654. let C49 = data[48][2].v || 0;
  655. let C20 = data[19][2].v || 0;
  656. let C21 = data[20][2].v || 0;
  657. let C9 = data[8][2].v || 0;
  658. let C15 = data[14][2].v || 0;
  659. let C16 = data[15][2].v || 0;
  660. let C17 = data[16][2].v || 0;
  661. let C18 = data[17][2].v || 0;
  662. let C19 = data[18][2].v || 0;
  663. let C51 = data[50][2].v || 0;
  664. let G42 = data[41][6].v || 0;
  665. let G12 = data[11][6].v || 0;
  666. let G13 = data[12][6].v || 0;
  667. let G7 = data[6][6].v || 0;
  668. let G8 = data[7][6].v || 0;
  669. switch (type) {
  670. case 1:
  671. // 净利率
  672. return C3() / C59();
  673. case 2:
  674. // 贡献毛利率
  675. return C4() / C59();
  676. case 3:
  677. // 合同总价
  678. return C59();
  679. }
  680. function C59() {
  681. return C58() + C57() + C56() + C54();
  682. }
  683. function C4() {
  684. return C3() + C50 + C49 + C48() + G42 + C43();
  685. }
  686. function C48() {
  687. return C59() * G12;
  688. }
  689. function C58() {
  690. return (C56() + C57()) * 0.12;
  691. }
  692. function C57() {
  693. return (((C20 + C21) * C10) / (1 + G7)) * G7 - ((C20 + C21) / (1 + G8)) * G8;
  694. }
  695. function C56() {
  696. return (
  697. (((C15 + C16 + C17 + C18 + C19) * C10) / (1 + G7)) * G7 -
  698. ((C15 + C16 + C17 + C18 + C19) / (1 + G7)) * G7
  699. );
  700. }
  701. function C54() {
  702. return SUM(2, [14, 20]) * C10;
  703. }
  704. function C3() {
  705. return C55() - C53();
  706. }
  707. function C55() {
  708. return C59() / (1 + G7);
  709. }
  710. function C53() {
  711. return C52() - ((SUM(2, [14, 18]) / (1 + G7)) * G7 + (SUM(2, [19, 20]) / (1 + G8)) * G8);
  712. }
  713. function C52() {
  714. return SUM(2, [14, 50]);
  715. }
  716. function C43() {
  717. return C59() * G13;
  718. }
  719. function C44() {
  720. return C59() * C9;
  721. }
  722. function SUM(x, [y1, y2]) {
  723. let total = 0;
  724. for (let i = y1; i <= y2; i++) {
  725. const item = data[i][x];
  726. if (!isNaN(item.v)) {
  727. total += item.v;
  728. }
  729. }
  730. return total;
  731. }
  732. }
  733. export default LuckySheet;