@lambo-design/shared 1.0.0-beta.314 → 1.0.0-beta.316

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambo-design/shared",
3
- "version": "1.0.0-beta.314",
3
+ "version": "1.0.0-beta.316",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "author": "lambo",
package/utils/excel.js CHANGED
@@ -5,6 +5,10 @@ XLSX.set_cptable(cpexcel);
5
5
  import {deepCopy} from "./assist";
6
6
  import XLSXStyle from '@lambo-design/xlsx-style'
7
7
 
8
+ /**
9
+ * 表头内容转换规则
10
+ * @type {{'': string, '#': string, 序号: string, 操作: string, 编号: string}}
11
+ */
8
12
  const titleRules = {
9
13
  '': '',
10
14
  '#': '#',
@@ -12,6 +16,10 @@ const titleRules = {
12
16
  '编号': '编号',
13
17
  '操作': '操作',
14
18
  }
19
+ /**
20
+ * 列类型转换规则
21
+ * @type {{'single-selection': string, select: string, selection: string, checkbox: string, index: string, radio: string}}
22
+ */
15
23
  const typeRules = {
16
24
  'index': 'index',
17
25
  'select': 'select',
@@ -21,6 +29,62 @@ const typeRules = {
21
29
  'radio': 'radio'
22
30
  }
23
31
 
32
+ /**
33
+ * 标题样式
34
+ * @type {{border: {top: {color: {rgb: string}, style: string}, left: {color: {rgb: string}, style: string}, bottom: {color: {rgb: string}, style: string}, right: {color: {rgb: string}, style: string}}, alignment: {horizontal: string, vertical: string}, fill: {fgColor: {rgb: string}, bgColor: {indexed: number}}}}
35
+ */
36
+ let titleStyle = {
37
+ border: {
38
+ left: {style: 'thin', color: {rgb: "000000"}},
39
+ top: {style: 'thin', color: {rgb: "000000"}},
40
+ right: {style: 'thin', color: {rgb: "000000"}},
41
+ bottom: {style: 'thin', color: {rgb: "000000"}},
42
+ },
43
+ font: { bold: true },
44
+ alignment: {horizontal: "center", vertical: "center"}
45
+ }
46
+ /**
47
+ * 表头样式
48
+ * @type {{border: {top: {color: {rgb: string}, style: string}, left: {color: {rgb: string}, style: string}, bottom: {color: {rgb: string}, style: string}, right: {color: {rgb: string}, style: string}}, alignment: {horizontal: string, vertical: string}, fill: {fgColor: {rgb: string}, bgColor: {indexed: number}}}}
49
+ */
50
+ let headStyle = {
51
+ border: {
52
+ left: {style: 'thin', color: {rgb: "000000"}},
53
+ top: {style: 'thin', color: {rgb: "000000"}},
54
+ right: {style: 'thin', color: {rgb: "000000"}},
55
+ bottom: {style: 'thin', color: {rgb: "000000"}},
56
+ },
57
+ alignment: {horizontal: "center", vertical: "center"},
58
+ fill: {bgColor: {indexed: 64}, fgColor: {rgb: "5A9BD5"}}
59
+ }
60
+ /**
61
+ * 表格斑马纹样式
62
+ * @type {{border: {top: {color: {rgb: string}, style: string}, left: {color: {rgb: string}, style: string}, bottom: {color: {rgb: string}, style: string}, right: {color: {rgb: string}, style: string}}, alignment: {vertical: string}, fill: {fgColor: {rgb: string}, bgColor: {indexed: number}}}}
63
+ */
64
+ let bodyPairStyle = {
65
+ border: {
66
+ left: {style: 'thin', color: {rgb: "000000"}},
67
+ top: {style: 'thin', color: {rgb: "000000"}},
68
+ right: {style: 'thin', color: {rgb: "000000"}},
69
+ bottom: {style: 'thin', color: {rgb: "000000"}},
70
+ },
71
+ alignment: {vertical: "center"},
72
+ fill: {bgColor: {indexed: 64}, fgColor: {rgb: "DDEBF7"}}
73
+ }
74
+ /**
75
+ * 表格普通样式
76
+ * @type {{border: {top: {color: {rgb: string}, style: string}, left: {color: {rgb: string}, style: string}, bottom: {color: {rgb: string}, style: string}, right: {color: {rgb: string}, style: string}}, alignment: {vertical: string}}}
77
+ */
78
+ let bodyStyle = {
79
+ border: {
80
+ left: {style: 'thin', color: {rgb: "000000"}},
81
+ top: {style: 'thin', color: {rgb: "000000"}},
82
+ right: {style: 'thin', color: {rgb: "000000"}},
83
+ bottom: {style: 'thin', color: {rgb: "000000"}},
84
+ },
85
+ alignment: {vertical: "center"}
86
+ }
87
+
24
88
  /**
25
89
  * 过滤掉filterData中titleRules、typeRules相关的列
26
90
  * @param filterData
@@ -266,30 +330,32 @@ function auto_width(ws, data) {
266
330
  ws['!cols'] = result;
267
331
  }
268
332
 
269
- function merge_title(ws,title) {
333
+
334
+
335
+ function merge_cell({ws,data,startRow}) {
270
336
  let mergeData = [];
271
337
 
272
- for (let i = 0; i < title.length; i++) {
273
- for (let j = 0; j < title[i].length; j++) {
274
- let currentCellValue = title[i][j];
275
- let merge = { s: { r: i, c: j }, e: { r: i, c: j } };
338
+ for (let i = 0; i < data.length; i++) {
339
+ for (let j = 0; j < data[i].length; j++) {
340
+ let currentCellValue = data[i][j];
341
+ let merge = { s: { r: i + startRow, c: j }, e: { r: i + startRow, c: j } };
276
342
 
277
343
  // Check horizontal direction for merges
278
344
  while (
279
- j + 1 < title[i].length &&
280
- title[i][j + 1] === currentCellValue &&
281
- !isCellMerged(mergeData, { r: i, c: j + 1 })
345
+ j + 1 < data[i].length &&
346
+ data[i][j + 1] === currentCellValue &&
347
+ !isCellMerged(mergeData, { r: i + startRow, c: j + 1 })
282
348
  ) {
283
349
  merge.e.c = j + 1;
284
350
  j++;
285
351
  }
286
352
 
287
353
  // Check vertical direction for merges
288
- let originalRow = i;
354
+ let originalRow = i + startRow;
289
355
  while (
290
- i + 1 < title.length &&
291
- title[i + 1][j] === currentCellValue &&
292
- !isCellMerged(mergeData, { r: i + 1, c: j })
356
+ i + 1 < data.length &&
357
+ data[i + 1][j] === currentCellValue &&
358
+ !isCellMerged(mergeData, { r: i + startRow + 1, c: j })
293
359
  ) {
294
360
  i++;
295
361
 
@@ -321,23 +387,23 @@ function merge_title(ws,title) {
321
387
  ws['!merges'] = mergeData;
322
388
  }
323
389
 
324
- // Helper function to check if a cell is already part of a merge range
325
- function isCellMerged(mergeData, cell) {
326
- for (let merge of mergeData) {
327
- if (
328
- cell.r >= merge.s.r &&
329
- cell.r <= merge.e.r &&
330
- cell.c >= merge.s.c &&
331
- cell.c <= merge.e.c
332
- ) {
333
- return true;
334
- }
390
+ }
391
+ // Helper function to check if a cell is already part of a merge range
392
+ function isCellMerged(mergeData, cell) {
393
+ for (let merge of mergeData) {
394
+ if (
395
+ cell.r >= merge.s.r &&
396
+ cell.r <= merge.e.r &&
397
+ cell.c >= merge.s.c &&
398
+ cell.c <= merge.e.c
399
+ ) {
400
+ return true;
335
401
  }
336
- return false;
337
402
  }
403
+ return false;
338
404
  }
339
405
 
340
- function merge_content(ws, tableData, spanColumnKeys, titleLen) {
406
+ function merge_content({ws, tableData, spanColumnKeys, startRow}) {
341
407
  if (spanColumnKeys == null || spanColumnKeys.length === 0) {
342
408
  return null;
343
409
  }
@@ -352,7 +418,7 @@ function merge_content(ws, tableData, spanColumnKeys, titleLen) {
352
418
  }
353
419
  for (let i = 0; i < dLen; i++) {
354
420
  for (let j = 0; j < kLen; j++) {
355
- let merge = {s: {r: i + titleLen, c: j}, e: {r: i + titleLen, c: j}}
421
+ let merge = {s: {r: i + startRow, c: j}, e: {r: i + startRow, c: j}}
356
422
  flag = false
357
423
  //如果单元格和右侧内容相同则合并
358
424
  let n = 1;
@@ -372,7 +438,7 @@ function merge_content(ws, tableData, spanColumnKeys, titleLen) {
372
438
  break
373
439
  }
374
440
  params[i + m][j].disable = true
375
- merge.e.r = i + titleLen + m
441
+ merge.e.r = i + startRow + m
376
442
  flag = true
377
443
  m++;
378
444
  }
@@ -385,7 +451,7 @@ function merge_content(ws, tableData, spanColumnKeys, titleLen) {
385
451
  ws['!merges'] = ws['!merges'].concat(mergeData)
386
452
  }
387
453
 
388
- function add_style(ws, title) {
454
+ function add_style({ws, title, startRow}) {
389
455
 
390
456
  // 补充空白数据
391
457
  let rangs = ws['!ref'].split(":");
@@ -408,55 +474,35 @@ function add_style(ws, title) {
408
474
  }
409
475
  })
410
476
 
411
- let titleStyle = {
412
- border: {
413
- left: {style: 'thin', color: {rgb: "000000"}},
414
- top: {style: 'thin', color: {rgb: "000000"}},
415
- right: {style: 'thin', color: {rgb: "000000"}},
416
- bottom: {style: 'thin', color: {rgb: "000000"}},
417
- },
418
- alignment: {horizontal: "center", vertical: "center"},
419
- fill: {bgColor: {indexed: 64}, fgColor: {rgb: "5A9BD5"}}
420
- }
421
- let bodyPairStyle = {
422
- border: {
423
- left: {style: 'thin', color: {rgb: "000000"}},
424
- top: {style: 'thin', color: {rgb: "000000"}},
425
- right: {style: 'thin', color: {rgb: "000000"}},
426
- bottom: {style: 'thin', color: {rgb: "000000"}},
427
- },
428
- alignment: {vertical: "center"},
429
- fill: {bgColor: {indexed: 64}, fgColor: {rgb: "DDEBF7"}}
430
- }
431
- let bodyStyle = {
432
- border: {
433
- left: {style: 'thin', color: {rgb: "000000"}},
434
- top: {style: 'thin', color: {rgb: "000000"}},
435
- right: {style: 'thin', color: {rgb: "000000"}},
436
- bottom: {style: 'thin', color: {rgb: "000000"}},
437
- },
438
- alignment: {vertical: "center"}
439
- }
477
+ let titleReg = new RegExp("^[A-Z]1$", "im");
478
+ let titleExtReg = new RegExp("^[A-Z][2-" + parseInt(startRow>0?startRow:2) + "]$", "im");
479
+ let headReg = new RegExp("^[A-Z]+[" + parseInt(startRow + 1) + "-" + parseInt(startRow + title.length) + "]$", "im");
480
+ let bodyReg = new RegExp("^[A-Z]+([" + parseInt(startRow + title.length) + "-9]|[1-9]\\d+)$", "im");
440
481
  Object.keys(ws).forEach(item => {
441
-
442
- /**
443
- * 加载表头样式:蓝色背景,水平垂直居中,边框
444
- */
445
- var reg = new RegExp("^[A-Z]+[1 -" + title.length + "]$", "gim");
446
- if (reg.test(item)) {
482
+ if(titleReg.test(item)&&startRow>0){
483
+ /**
484
+ * 加载标题样式:加粗,水平垂直居中,边框
485
+ */
447
486
  ws[item].s = titleStyle
448
- } else
449
-
450
- /**
451
- * 表体样式: 垂直居中,边框
452
- */
453
- if (/^[A-Z]+\d+$/.test(item)) {
487
+ }else if(titleExtReg.test(item)&&startRow>0){
488
+ /**
489
+ * 加载标题扩展信息样式:加粗,水平垂直居中,边框
490
+ */
491
+ ws[item].s = bodyStyle
492
+ } else if (headReg.test(item)) {
493
+ /**
494
+ * 加载表头样式:蓝色背景,水平垂直居中,边框
495
+ */
496
+ ws[item].s = headStyle
497
+ } else if (bodyReg.test(item)) {
498
+ /**
499
+ * 表体样式: 垂直居中,边框
500
+ */
454
501
  if (parseInt(item.replace(/[^0-9]/ig, "")) % 2 === 0) {
455
502
  ws[item].s = bodyStyle
456
503
  } else {
457
504
  ws[item].s = bodyPairStyle
458
505
  }
459
-
460
506
  }
461
507
  })
462
508
  /* ws.B2 = {
@@ -495,17 +541,24 @@ export const export_json_to_excel = ({data, key, title, filename, spanColumns, a
495
541
  const arr = json_to_array(key, data);
496
542
  auto_width(ws, arr);
497
543
  }
498
- merge_content(ws, data, spanColumns)
544
+ merge_content(ws, data, spanColumns, title.length)
499
545
  XLSX.utils.book_append_sheet(wb, ws, '');
500
546
  XLSX.writeFile(wb, filename + '.' + format);
501
547
  }
502
548
 
503
- export const export_array_to_excel = ({key, data, title, filename, spanColumns, autoWidth, format}) => {
549
+ export const export_array_to_excel = ({key, data, title, header = [], footer = [], filename, spanColumns, autoWidth, format}) => {
504
550
  const wb = XLSX.utils.book_new();
505
- const arr = json_to_array(key, data);
551
+ let arr = json_to_array(key, data);
506
552
  for (var i = title.length; i > 0; i--) {
507
553
  arr.unshift(title[i - 1])
508
554
  }
555
+ if(header){
556
+ arr = [...header,...arr]
557
+ }
558
+ if(footer){
559
+ arr = [...arr,...footer]
560
+ }
561
+
509
562
  const ws = XLSX.utils.aoa_to_sheet(arr);
510
563
  if (autoWidth) {
511
564
  auto_width(ws, arr);
@@ -513,10 +566,12 @@ export const export_array_to_excel = ({key, data, title, filename, spanColumns,
513
566
  // 合并表头
514
567
  if (!ws['!merges']) ws['!merges'] = [];
515
568
  if (title.length > 1) {
516
- merge_title(ws, title)
569
+ merge_cell({ws, data:title, startRow: header.length})
517
570
  }
518
- merge_content(ws, data, spanColumns, title.length)
519
- add_style(ws, title)
571
+ merge_cell({ws,data:header,startRow: 0 })
572
+ console.log(data)
573
+ merge_content(ws, data, spanColumns, title.length + header.length)
574
+ add_style({ws, title, startRow: header.length})
520
575
  XLSX.utils.book_append_sheet(wb, ws, '');
521
576
  if(format === 'csv'){
522
577
  XLSX.writeFile(wb, filename + '.' + format,{