sh-view 2.7.7 → 2.7.8

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.
@@ -1,929 +1,929 @@
1
- <script>
2
- import { defineComponent, computed, getCurrentInstance } from 'vue'
3
- import dataHook from '../js/data-hook'
4
- import dataProps from '../js/data-props'
5
- // import Spreadsheet from 'x-data-spreadsheet'
6
- import ExcelJS from 'exceljs'
7
- export default defineComponent({
8
- name: 'ShExcel',
9
- props: dataProps,
10
- emits: ['rendered', 'error'],
11
- setup(props, { emit }) {
12
- const { proxy } = getCurrentInstance()
13
- const { $vUtils } = proxy
14
-
15
- let defaultOption = {
16
- mode: 'read',
17
- showToolbar: false
18
- }
19
-
20
- const excelOptions = computed(() => {
21
- return Object.assign({}, defaultOption, props.options)
22
- })
23
-
24
- const domRender = async (data, container) => {
25
- if (!data) {
26
- container.innerHTML = ''
27
- return Promise.resolve()
28
- }
29
- const wb = new ExcelJS.Workbook()
30
- // 微软的 Excel ColorIndex 一个索引数字对应一个颜色
31
- let workbook = await wb.xlsx.load(data)
32
- let workbookData = []
33
- workbook.eachSheet(sheet => {
34
- // 构造x-data-spreadsheet 的 sheet 数据源结构
35
- let sheetData = { name: sheet.name, styles: [], rows: {}, merges: [] }
36
- // 收集合并单元格信息
37
- let mergeAddressData = []
38
- for (let mergeRange in sheet._merges) {
39
- sheetData.merges.push(sheet._merges[mergeRange].shortRange)
40
- let mergeAddress = {}
41
- // 合并单元格起始地址
42
- mergeAddress.startAddress = sheet._merges[mergeRange].tl
43
- // 合并单元格终止地址
44
- mergeAddress.endAddress = sheet._merges[mergeRange].br
45
- // Y轴方向跨度
46
- mergeAddress.YRange = sheet._merges[mergeRange].model.bottom - sheet._merges[mergeRange].model.top
47
- // X轴方向跨度
48
- mergeAddress.XRange = sheet._merges[mergeRange].model.right - sheet._merges[mergeRange].model.left
49
- mergeAddressData.push(mergeAddress)
50
- }
51
- sheetData.cols = {}
52
- for (let i = 0; i < sheet.columns.length; i++) {
53
- sheetData.cols[i.toString()] = {}
54
- if (sheet.columns[i].width) {
55
- // 不知道为什么从 exceljs 读取的宽度显示到 x-data-spreadsheet 特别小, 这里乘以8
56
- sheetData.cols[i.toString()].width = sheet.columns[i].width * 8
57
- } else {
58
- // 默认列宽
59
- sheetData.cols[i.toString()].width = 100
60
- }
61
- }
62
-
63
- // 遍历行
64
- sheet.eachRow((row, rowIndex) => {
65
- sheetData.rows[(rowIndex - 1).toString()] = { cells: {} }
66
- //includeEmpty = false 不包含空白单元格
67
- row.eachCell({ includeEmpty: true }, function (cell, colNumber) {
68
- let cellText = ''
69
- if (cell.value && cell.value.result) {
70
- // Excel 单元格有公式
71
- cellText = cell.value.result
72
- } else if (cell.value && cell.value.richText) {
73
- // Excel 单元格是多行文本
74
- for (let text in cell.value.richText) {
75
- // 多行文本做累加
76
- cellText += cell.value.richText[text].text
77
- }
78
- } else {
79
- // Excel 单元格无公式
80
- cellText = cell.value
81
- }
82
- //解析单元格,包含样式
83
- //*********************单元格存在背景色******************************
84
- // 单元格存在背景色
85
- let backGroundColor = null
86
- if (cell.style.fill && cell.style.fill.fgColor && cell.style.fill.fgColor.argb) {
87
- // 8位字符颜色先转rgb再转16进制颜色
88
- backGroundColor = (val => {
89
- val = val.trim().toLowerCase() //去掉前后空格
90
- let argb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(val)
91
- let rgb = `rgba(${parseInt(argb[2], 16)}, ${parseInt(argb[3], 16)}, ${parseInt(argb[4], 16)})`
92
- let percent = (parseInt(argb[1], 16) / 255) * 100
93
- return $vUtils.fade(rgb, percent)
94
- })(cell.style.fill.fgColor.argb)
95
- }
96
-
97
- if (backGroundColor) {
98
- cell.style.bgcolor = backGroundColor
99
- }
100
- //*************************************************************************** */
101
-
102
- //*********************字体存在背景色******************************
103
- // 字体颜色
104
- let fontColor = null
105
- if (cell.style.font && cell.style.font.color && cell.style.font.color.argb) {
106
- // 8位字符颜色先转rgb再转16进制颜色
107
- fontColor = (val => {
108
- val = val.trim().toLowerCase() //去掉前后空格
109
- let argb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(val)
110
- let rgb = `rgba(${parseInt(argb[2], 16)}, ${parseInt(argb[3], 16)}, ${parseInt(argb[4], 16)})`
111
- let percent = (parseInt(argb[1], 16) / 255) * 100
112
- return $vUtils.fade(rgb, percent)
113
- })(cell.style.font.color.argb)
114
- }
115
- if (fontColor) {
116
- cell.style.color = fontColor
117
- }
118
-
119
- // exceljs 对齐的格式转成 x-date-spreedsheet 能识别的对齐格式
120
- if (cell.style.alignment && cell.style.alignment.horizontal) {
121
- cell.style.align = cell.style.alignment.horizontal
122
- cell.style.valign = cell.style.alignment.vertical
123
- }
124
-
125
- //处理合并单元格
126
- let mergeAddress = _.find(mergeAddressData, function (o) {
127
- return o.startAddress === cell._address
128
- })
129
- if (mergeAddress) {
130
- // 遍历的单元格属于合并单元格
131
- if (cell.master.address !== mergeAddress.startAddress) {
132
- // 不是合并单元格中的第一个单元格不需要计入数据源
133
- return
134
- }
135
- // 说明是合并单元格区域的起始单元格
136
- sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()] = { text: cellText, style: 0, merge: [mergeAddress.YRange, mergeAddress.XRange] }
137
- sheetData.styles.push(cell.style)
138
- //对应的style存放序号
139
- sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()].style = sheetData.styles.length - 1
140
- } else {
141
- // 非合并单元格
142
- sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()] = { text: cellText, style: 0 }
143
- //解析单元格,包含样式
144
- sheetData.styles.push(cell.style)
145
- //对应的style存放序号
146
- sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()].style = sheetData.styles.length - 1
147
- }
148
- })
149
- })
150
- workbookData.push(sheetData)
151
- })
152
- // return new Spreadsheet(rootRef.value, excelOptions).loadData(workbookData)
153
- }
154
-
155
- const useData = dataHook(props, context, proxy, {
156
- domRender
157
- })
158
-
159
- return {
160
- ...useData
161
- }
162
- }
163
- })
164
- </script>
165
-
166
- <template>
167
- <div ref="rootRef" class="sh-office-excel"></div>
168
- </template>
169
-
170
- <style lang="scss" scoped>
171
- .x-spreadsheet {
172
- font-size: 13px;
173
- line-height: normal;
174
- user-select: none;
175
- -moz-user-select: none;
176
- font-family: 'Lato', 'Source Sans Pro', Roboto, Helvetica, Arial, sans-serif;
177
- box-sizing: content-box;
178
- background: #fff;
179
- -webkit-font-smoothing: antialiased;
180
- }
181
- .x-spreadsheet textarea {
182
- font: 400 13px Arial, 'Lato', 'Source Sans Pro', Roboto, Helvetica, sans-serif;
183
- }
184
- .x-spreadsheet-sheet {
185
- position: relative;
186
- overflow: hidden;
187
- }
188
- .x-spreadsheet-table {
189
- vertical-align: bottom;
190
- }
191
- .x-spreadsheet-tooltip {
192
- font-family: inherit;
193
- position: absolute;
194
- padding: 5px 10px;
195
- color: #fff;
196
- border-radius: 1px;
197
- background: #000000;
198
- font-size: 12px;
199
- z-index: 201;
200
- }
201
- .x-spreadsheet-tooltip:before {
202
- pointer-events: none;
203
- position: absolute;
204
- left: calc(50% - 4px);
205
- top: -4px;
206
- content: '';
207
- width: 8px;
208
- height: 8px;
209
- background: inherit;
210
- -webkit-transform: rotate(45deg);
211
- transform: rotate(45deg);
212
- z-index: 1;
213
- box-shadow: 1px 1px 3px -1px rgba(0, 0, 0, 0.3);
214
- }
215
- .x-spreadsheet-color-palette {
216
- padding: 5px;
217
- }
218
- .x-spreadsheet-color-palette table {
219
- margin: 0;
220
- padding: 0;
221
- border-collapse: separate;
222
- background: #fff;
223
- }
224
- .x-spreadsheet-color-palette table td {
225
- margin: 0;
226
- cursor: pointer;
227
- border: 1px solid transparent;
228
- }
229
- .x-spreadsheet-color-palette table td:hover {
230
- border-color: #ddd;
231
- }
232
- .x-spreadsheet-color-palette table td .x-spreadsheet-color-palette-cell {
233
- width: 16px;
234
- height: 16px;
235
- }
236
- .x-spreadsheet-border-palette {
237
- padding: 6px;
238
- }
239
- .x-spreadsheet-border-palette table {
240
- margin: 0;
241
- padding: 0;
242
- border-collapse: separate;
243
- border-spacing: 0;
244
- background: #fff;
245
- table-layout: fixed;
246
- }
247
- .x-spreadsheet-border-palette table td {
248
- margin: 0;
249
- }
250
- .x-spreadsheet-border-palette .x-spreadsheet-border-palette-left {
251
- border-right: 1px solid #eee;
252
- padding-right: 6px;
253
- }
254
- .x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell {
255
- width: 30px;
256
- height: 30px;
257
- cursor: pointer;
258
- text-align: center;
259
- }
260
- .x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell:hover {
261
- background-color: #eee;
262
- }
263
- .x-spreadsheet-border-palette .x-spreadsheet-border-palette-right {
264
- padding-left: 6px;
265
- }
266
- .x-spreadsheet-border-palette .x-spreadsheet-border-palette-right .x-spreadsheet-line-type {
267
- position: relative;
268
- left: 0;
269
- top: -3px;
270
- }
271
- .x-spreadsheet-dropdown {
272
- position: relative;
273
- }
274
- .x-spreadsheet-dropdown .x-spreadsheet-dropdown-content {
275
- position: absolute;
276
- z-index: 200;
277
- background: #fff;
278
- box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
279
- }
280
- .x-spreadsheet-dropdown.bottom-left .x-spreadsheet-dropdown-content {
281
- top: calc(100% + 5px);
282
- left: 0;
283
- }
284
- .x-spreadsheet-dropdown.bottom-right .x-spreadsheet-dropdown-content {
285
- top: calc(100% + 5px);
286
- right: 0;
287
- }
288
- .x-spreadsheet-dropdown.top-left .x-spreadsheet-dropdown-content {
289
- bottom: calc(100% + 5px);
290
- left: 0;
291
- }
292
- .x-spreadsheet-dropdown.top-right .x-spreadsheet-dropdown-content {
293
- bottom: calc(100% + 5px);
294
- right: 0;
295
- }
296
- .x-spreadsheet-dropdown .x-spreadsheet-dropdown-title {
297
- padding: 0 5px;
298
- display: inline-block;
299
- }
300
- /* resizer **/
301
- .x-spreadsheet-resizer {
302
- position: absolute;
303
- z-index: 11;
304
- }
305
- .x-spreadsheet-resizer .x-spreadsheet-resizer-hover {
306
- background-color: rgba(75, 137, 255, 0.25);
307
- }
308
- .x-spreadsheet-resizer .x-spreadsheet-resizer-line {
309
- position: absolute;
310
- }
311
- .x-spreadsheet-resizer.horizontal {
312
- cursor: row-resize;
313
- }
314
- .x-spreadsheet-resizer.horizontal .x-spreadsheet-resizer-line {
315
- border-bottom: 2px dashed #4b89ff;
316
- left: 0;
317
- bottom: 0;
318
- }
319
- .x-spreadsheet-resizer.vertical {
320
- cursor: col-resize;
321
- }
322
- .x-spreadsheet-resizer.vertical .x-spreadsheet-resizer-line {
323
- border-right: 2px dashed #4b89ff;
324
- top: 0;
325
- right: 0;
326
- }
327
- /* scrollbar */
328
- .x-spreadsheet-scrollbar {
329
- position: absolute;
330
- bottom: 0;
331
- right: 0;
332
- background-color: #f4f5f8;
333
- opacity: 0.9;
334
- z-index: 12;
335
- }
336
- .x-spreadsheet-scrollbar.horizontal {
337
- right: 15px;
338
- overflow-x: scroll;
339
- overflow-y: hidden;
340
- }
341
- .x-spreadsheet-scrollbar.horizontal > div {
342
- height: 1px;
343
- background: #ddd;
344
- }
345
- .x-spreadsheet-scrollbar.vertical {
346
- bottom: 15px;
347
- overflow-x: hidden;
348
- overflow-y: scroll;
349
- }
350
- .x-spreadsheet-scrollbar.vertical > div {
351
- width: 1px;
352
- background: #ddd;
353
- }
354
- /* @{css-prefix}-overlayer */
355
- .x-spreadsheet-overlayer {
356
- position: absolute;
357
- left: 0;
358
- top: 0;
359
- z-index: 10;
360
- }
361
- .x-spreadsheet-overlayer .x-spreadsheet-overlayer-content {
362
- position: absolute;
363
- overflow: hidden;
364
- pointer-events: none;
365
- width: 100%;
366
- height: 100%;
367
- }
368
- .x-spreadsheet-editor,
369
- .x-spreadsheet-selector {
370
- box-sizing: content-box;
371
- position: absolute;
372
- overflow: hidden;
373
- pointer-events: none;
374
- top: 0;
375
- left: 0;
376
- width: 100%;
377
- height: 100%;
378
- }
379
- /* @{css-prefix}-selector */
380
- .x-spreadsheet-selector .hide-input {
381
- position: absolute;
382
- z-index: 0;
383
- }
384
- .x-spreadsheet-selector .hide-input input {
385
- padding: 0;
386
- width: 0;
387
- border: none !important;
388
- }
389
- .x-spreadsheet-selector .x-spreadsheet-selector-area {
390
- position: absolute;
391
- border: 2px solid #4b89ff;
392
- background: rgba(75, 137, 255, 0.1);
393
- z-index: 5;
394
- }
395
- .x-spreadsheet-selector .x-spreadsheet-selector-clipboard,
396
- .x-spreadsheet-selector .x-spreadsheet-selector-autofill {
397
- position: absolute;
398
- background: transparent;
399
- z-index: 100;
400
- }
401
- .x-spreadsheet-selector .x-spreadsheet-selector-clipboard {
402
- border: 2px dashed #4b89ff;
403
- }
404
- .x-spreadsheet-selector .x-spreadsheet-selector-autofill {
405
- border: 1px dashed rgba(0, 0, 0, 0.45);
406
- }
407
- .x-spreadsheet-selector .x-spreadsheet-selector-corner {
408
- pointer-events: auto;
409
- position: absolute;
410
- cursor: crosshair;
411
- font-size: 0;
412
- height: 5px;
413
- width: 5px;
414
- right: -5px;
415
- bottom: -5px;
416
- border: 2px solid #ffffff;
417
- background: #4b89ff;
418
- }
419
- .x-spreadsheet-editor {
420
- z-index: 20;
421
- }
422
- .x-spreadsheet-editor .x-spreadsheet-editor-area {
423
- position: absolute;
424
- text-align: left;
425
- border: 2px solid #4b89ff;
426
- line-height: 0;
427
- z-index: 100;
428
- pointer-events: auto;
429
- }
430
- .x-spreadsheet-editor .x-spreadsheet-editor-area textarea {
431
- box-sizing: content-box;
432
- border: none;
433
- padding: 0 3px;
434
- outline: none;
435
- resize: none;
436
- text-align: start;
437
- overflow-y: hidden;
438
- font: 400 13px Arial, 'Lato', 'Source Sans Pro', Roboto, Helvetica, sans-serif;
439
- color: inherit;
440
- white-space: normal;
441
- word-wrap: break-word;
442
- line-height: 22px;
443
- margin: 0;
444
- }
445
- .x-spreadsheet-editor .x-spreadsheet-editor-area .textline {
446
- overflow: hidden;
447
- visibility: hidden;
448
- position: fixed;
449
- top: 0;
450
- left: 0;
451
- }
452
- .x-spreadsheet-item {
453
- user-select: none;
454
- background: 0;
455
- border: 1px solid transparent;
456
- outline: none;
457
- height: 26px;
458
- color: rgba(0, 0, 0, 0.9);
459
- line-height: 26px;
460
- list-style: none;
461
- padding: 2px 10px;
462
- cursor: default;
463
- text-align: left;
464
- overflow: hidden;
465
- }
466
- .x-spreadsheet-item.disabled {
467
- pointer-events: none;
468
- opacity: 0.5;
469
- }
470
- .x-spreadsheet-item:hover,
471
- .x-spreadsheet-item.active {
472
- background: rgba(0, 0, 0, 0.05);
473
- }
474
- .x-spreadsheet-item.divider {
475
- height: 0;
476
- padding: 0;
477
- margin: 5px 0;
478
- border: none;
479
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
480
- }
481
- .x-spreadsheet-item .label {
482
- float: right;
483
- opacity: 0.65;
484
- font-size: 1em;
485
- }
486
- .x-spreadsheet-item.state,
487
- .x-spreadsheet-header.state {
488
- padding-left: 35px !important;
489
- position: relative;
490
- }
491
- .x-spreadsheet-item.state:before,
492
- .x-spreadsheet-header.state:before {
493
- content: '';
494
- position: absolute;
495
- width: 10px;
496
- height: 10px;
497
- left: 12px;
498
- top: calc(50% - 5px);
499
- background: rgba(0, 0, 0, 0.08);
500
- border-radius: 2px;
501
- }
502
- .x-spreadsheet-item.state.checked:before,
503
- .x-spreadsheet-header.state.checked:before {
504
- background: #4b89ff;
505
- }
506
- .x-spreadsheet-checkbox {
507
- position: relative;
508
- display: inline-block;
509
- backface-visibility: hidden;
510
- outline: 0;
511
- vertical-align: baseline;
512
- font-style: normal;
513
- font-size: 1rem;
514
- line-height: 1em;
515
- }
516
- .x-spreadsheet-checkbox > input {
517
- position: absolute;
518
- top: 0;
519
- left: 0;
520
- opacity: 0 !important;
521
- outline: 0;
522
- z-index: -1;
523
- }
524
- .x-spreadsheet-suggest,
525
- .x-spreadsheet-contextmenu,
526
- .x-spreadsheet-sort-filter {
527
- position: absolute;
528
- box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
529
- background: #fff;
530
- z-index: 100;
531
- width: 260px;
532
- pointer-events: auto;
533
- overflow: auto;
534
- }
535
- .x-spreadsheet-suggest {
536
- width: 200px;
537
- }
538
- .x-spreadsheet-filter {
539
- border: 1px solid #e9e9e9;
540
- font-size: 12px;
541
- margin: 10px;
542
- }
543
- .x-spreadsheet-filter .x-spreadsheet-header {
544
- padding: 0.5em 0.75em;
545
- background: #f8f8f9;
546
- border-bottom: 1px solid #e9e9e9;
547
- border-left: 1px solid transparent;
548
- }
549
- .x-spreadsheet-filter .x-spreadsheet-body {
550
- height: 200px;
551
- overflow-y: auto;
552
- }
553
- .x-spreadsheet-filter .x-spreadsheet-body .x-spreadsheet-item {
554
- height: 20px;
555
- line-height: 20px;
556
- }
557
- .x-spreadsheet-sort-filter .x-spreadsheet-buttons {
558
- margin: 10px;
559
- }
560
- .x-spreadsheet-bottombar {
561
- height: 40px;
562
- padding: 0 30px;
563
- text-align: left;
564
- background: #f5f6f7;
565
- display: flex;
566
- }
567
- .x-spreadsheet-bottombar {
568
- position: relative;
569
- border-top: 1px solid #e0e2e4;
570
- }
571
- .x-spreadsheet-bottombar .x-spreadsheet-menu > li {
572
- line-height: 40px;
573
- height: 40px;
574
- padding-top: 0;
575
- padding-bottom: 0;
576
- vertical-align: middle;
577
- border-right: 1px solid #e8eaed;
578
- }
579
- .x-spreadsheet-menu {
580
- list-style: none;
581
- margin: 0;
582
- padding: 0;
583
- user-select: none;
584
- }
585
- .x-spreadsheet-menu > li {
586
- float: left;
587
- line-height: 1.25em;
588
- padding: 0.785em 1em;
589
- margin: 0;
590
- vertical-align: middle;
591
- text-align: left;
592
- color: #80868b;
593
- white-space: nowrap;
594
- cursor: pointer;
595
- transition: all 0.3s;
596
- font-weight: bold;
597
- }
598
- .x-spreadsheet-menu > li.active {
599
- background-color: #fff;
600
- color: rgba(0, 0, 0, 0.65);
601
- }
602
- .x-spreadsheet-menu > li .x-spreadsheet-dropdown {
603
- display: inline-block;
604
- }
605
- .x-spreadsheet-print {
606
- position: absolute;
607
- left: 0;
608
- top: 0;
609
- z-index: 100;
610
- width: 100%;
611
- height: 100%;
612
- display: flex;
613
- flex-direction: column;
614
- }
615
- .x-spreadsheet-print-bar {
616
- background: #424242;
617
- height: 60px;
618
- line-height: 60px;
619
- padding: 0 30px;
620
- }
621
- .x-spreadsheet-print-bar .-title {
622
- color: #fff;
623
- font-weight: bold;
624
- font-size: 1.2em;
625
- float: left;
626
- }
627
- .x-spreadsheet-print-bar .-right {
628
- float: right;
629
- margin-top: 12px;
630
- }
631
- .x-spreadsheet-print-content {
632
- display: flex;
633
- flex: auto;
634
- flex-direction: row;
635
- background: #d0d0d0;
636
- height: calc(100% - 60px);
637
- }
638
- .x-spreadsheet-print-content .-sider {
639
- flex: 0 0 300px;
640
- width: 300px;
641
- border-left: 2px solid #ccc;
642
- background: #fff;
643
- }
644
- .x-spreadsheet-print-content .-content {
645
- flex: auto;
646
- overflow-x: auto;
647
- overflow-y: scroll;
648
- height: 100%;
649
- }
650
- .x-spreadsheet-canvas-card-wraper {
651
- margin: 40px 20px;
652
- }
653
- .x-spreadsheet-canvas-card {
654
- background: #fff;
655
- margin: auto;
656
- page-break-before: auto;
657
- page-break-after: always;
658
- box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 3px rgba(0, 0, 0, 0.12), 0 4px 5px 0 rgba(0, 0, 0, 0.2);
659
- }
660
- .x-spreadsheet-calendar {
661
- color: rgba(0, 0, 0, 0.65);
662
- background: #ffffff;
663
- user-select: none;
664
- }
665
- .x-spreadsheet-calendar .calendar-header {
666
- font-weight: 700;
667
- line-height: 30px;
668
- text-align: center;
669
- width: 100%;
670
- float: left;
671
- background: #f9fafb;
672
- }
673
- .x-spreadsheet-calendar .calendar-header .calendar-header-left {
674
- padding-left: 5px;
675
- float: left;
676
- }
677
- .x-spreadsheet-calendar .calendar-header .calendar-header-right {
678
- float: right;
679
- }
680
- .x-spreadsheet-calendar .calendar-header .calendar-header-right a {
681
- padding: 3px 0;
682
- margin-right: 2px;
683
- border-radius: 2px;
684
- }
685
- .x-spreadsheet-calendar .calendar-header .calendar-header-right a:hover {
686
- background: rgba(0, 0, 0, 0.08);
687
- }
688
- .x-spreadsheet-calendar .calendar-body {
689
- border-collapse: collapse;
690
- border-spacing: 0;
691
- }
692
- .x-spreadsheet-calendar .calendar-body th,
693
- .x-spreadsheet-calendar .calendar-body td {
694
- width: 14.28571429%;
695
- min-width: 32px;
696
- text-align: center;
697
- font-weight: 700;
698
- line-height: 30px;
699
- padding: 0;
700
- }
701
- .x-spreadsheet-calendar .calendar-body td > .cell:hover {
702
- background: #ecf6fd;
703
- }
704
- .x-spreadsheet-calendar .calendar-body td > .cell.active,
705
- .x-spreadsheet-calendar .calendar-body td > .cell.active:hover {
706
- background: #ecf6fd;
707
- color: #2185d0;
708
- }
709
- .x-spreadsheet-calendar .calendar-body td > .cell.disabled {
710
- pointer-events: none;
711
- opacity: 0.5;
712
- }
713
- .x-spreadsheet-datepicker {
714
- box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
715
- position: absolute;
716
- left: 0;
717
- top: calc(100% + 5px);
718
- z-index: 10;
719
- width: auto;
720
- }
721
- .x-spreadsheet-buttons {
722
- display: flex;
723
- justify-content: flex-end;
724
- }
725
- .x-spreadsheet-buttons .x-spreadsheet-button {
726
- margin-left: 8px;
727
- }
728
- .x-spreadsheet-button {
729
- display: inline-block;
730
- border-radius: 3px;
731
- line-height: 1em;
732
- min-height: 1em;
733
- white-space: nowrap;
734
- text-align: center;
735
- cursor: pointer;
736
- font-size: 1em;
737
- font-weight: 700;
738
- padding: 0.75em 1em;
739
- color: rgba(0, 0, 0, 0.6);
740
- background: #e0e1e2;
741
- text-decoration: none;
742
- font-family: 'Lato', 'proxima-nova', 'Helvetica Neue', Arial, sans-serif;
743
- outline: none;
744
- vertical-align: baseline;
745
- zoom: 1;
746
- user-select: none;
747
- transition: all 0.1s linear;
748
- }
749
- .x-spreadsheet-button.active,
750
- .x-spreadsheet-button:hover {
751
- background-color: #c0c1c2;
752
- color: rgba(0, 0, 0, 0.8);
753
- }
754
- .x-spreadsheet-button.primary {
755
- color: #fff;
756
- background-color: #2185d0;
757
- }
758
- .x-spreadsheet-button.primary:hover,
759
- .x-spreadsheet-button.primary.active {
760
- color: #fff;
761
- background-color: #1678c2;
762
- }
763
- .x-spreadsheet-form-input {
764
- font-size: 1em;
765
- position: relative;
766
- font-weight: 400;
767
- display: inline-flex;
768
- color: rgba(0, 0, 0, 0.87);
769
- }
770
- .x-spreadsheet-form-input input {
771
- z-index: 1;
772
- margin: 0;
773
- max-width: 100%;
774
- flex: 1 0 auto;
775
- outline: 0;
776
- -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
777
- text-align: left;
778
- line-height: 30px;
779
- height: 30px;
780
- padding: 0 8px;
781
- background: #fff;
782
- border: 1px solid #e9e9e9;
783
- border-radius: 3px;
784
- transition: box-shadow 0.1s ease, border-color 0.1s ease;
785
- box-shadow: inset 0 1px 2px hsla(0, 0%, 4%, 0.06);
786
- }
787
- .x-spreadsheet-form-input input:focus {
788
- border-color: #4b89ff;
789
- box-shadow: inset 0 1px 2px rgba(75, 137, 255, 0.2);
790
- }
791
- .x-spreadsheet-form-select {
792
- position: relative;
793
- display: inline-block;
794
- background: #fff;
795
- border: 1px solid #e9e9e9;
796
- border-radius: 2px;
797
- cursor: pointer;
798
- color: rgba(0, 0, 0, 0.87);
799
- user-select: none;
800
- box-shadow: inset 0 1px 2px hsla(0, 0%, 4%, 0.06);
801
- }
802
- .x-spreadsheet-form-select .input-text {
803
- text-overflow: ellipsis;
804
- white-space: nowrap;
805
- min-width: 60px;
806
- width: auto;
807
- height: 30px;
808
- line-height: 30px;
809
- padding: 0 8px;
810
- }
811
- .x-spreadsheet-form-fields {
812
- display: flex;
813
- flex-direction: row;
814
- flex-wrap: wrap;
815
- }
816
- .x-spreadsheet-form-fields .x-spreadsheet-form-field {
817
- flex: 0 1 auto;
818
- }
819
- .x-spreadsheet-form-fields .x-spreadsheet-form-field .label {
820
- display: inline-block;
821
- margin: 0 10px 0 0;
822
- }
823
- .x-spreadsheet-form-field {
824
- display: block;
825
- vertical-align: middle;
826
- margin-left: 10px;
827
- margin-bottom: 10px;
828
- }
829
- .x-spreadsheet-form-field:first-child {
830
- margin-left: 0;
831
- }
832
- .x-spreadsheet-form-field.error .x-spreadsheet-form-select,
833
- .x-spreadsheet-form-field.error input {
834
- border-color: #f04134;
835
- }
836
- .x-spreadsheet-form-field .tip {
837
- color: #f04134;
838
- font-size: 0.9em;
839
- }
840
- .x-spreadsheet-dimmer {
841
- display: none;
842
- position: absolute;
843
- top: 0 !important;
844
- left: 0 !important;
845
- width: 100%;
846
- height: 100%;
847
- text-align: center;
848
- vertical-align: middle;
849
- background-color: rgba(0, 0, 0, 0.6);
850
- opacity: 0;
851
- -webkit-animation-fill-mode: both;
852
- animation-fill-mode: both;
853
- -webkit-animation-duration: 0.5s;
854
- animation-duration: 0.5s;
855
- transition: background-color 0.5s linear;
856
- user-select: none;
857
- z-index: 1000;
858
- }
859
- .x-spreadsheet-dimmer.active {
860
- display: block;
861
- opacity: 1;
862
- }
863
- .x-spreadsheet-modal,
864
- .x-spreadsheet-toast {
865
- font-size: 13px;
866
- position: fixed;
867
- z-index: 1001;
868
- text-align: left;
869
- line-height: 1.25em;
870
- min-width: 360px;
871
- color: rgba(0, 0, 0, 0.87);
872
- font-family: 'Lato', 'Source Sans Pro', Roboto, Helvetica, Arial, sans-serif;
873
- border-radius: 4px;
874
- border: 1px solid rgba(0, 0, 0, 0.1);
875
- background-color: #fff;
876
- background-clip: padding-box;
877
- box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 8px;
878
- }
879
- .x-spreadsheet-toast {
880
- background-color: rgba(255, 255, 255, 0.85);
881
- }
882
- .x-spreadsheet-modal-header,
883
- .x-spreadsheet-toast-header {
884
- font-weight: 600;
885
- background-clip: padding-box;
886
- background-color: rgba(255, 255, 255, 0.85);
887
- border-bottom: 1px solid rgba(0, 0, 0, 0.05);
888
- border-radius: 4px 4px 0 0;
889
- }
890
-
891
- .x-spreadsheet-toast-header {
892
- color: #f2711c;
893
- }
894
- .x-spreadsheet-modal-header {
895
- border-bottom: 1px solid #e0e2e4;
896
- background: rgba(0, 0, 0, 0.08);
897
- font-size: 1.0785em;
898
- }
899
- .x-spreadsheet-modal-header,
900
- .x-spreadsheet-modal-content,
901
- .x-spreadsheet-toast-header,
902
- .x-spreadsheet-toast-content {
903
- padding: 0.75em 1em;
904
- }
905
-
906
- .x-spreadsheet-menu li:first-child {
907
- display: none;
908
- }
909
- .sh-office-excel {
910
- form fieldset {
911
- border: none;
912
- }
913
- form fieldset label {
914
- display: block;
915
- margin-bottom: 0.5em;
916
- font-size: 1em;
917
- color: #666;
918
- }
919
- form fieldset select {
920
- font-size: 1.1em;
921
- width: 100%;
922
- background-color: #fff;
923
- border: none;
924
- border-bottom: 2px solid #ddd;
925
- padding: 0.5em 0.85em;
926
- border-radius: 2px;
927
- }
928
- }
929
- </style>
1
+ <script>
2
+ import { defineComponent, computed, getCurrentInstance } from 'vue'
3
+ import dataHook from '../js/data-hook'
4
+ import dataProps from '../js/data-props'
5
+ // import Spreadsheet from 'x-data-spreadsheet'
6
+ import ExcelJS from 'exceljs'
7
+ export default defineComponent({
8
+ name: 'ShExcel',
9
+ props: dataProps,
10
+ emits: ['rendered', 'error'],
11
+ setup(props, context) {
12
+ const { proxy } = getCurrentInstance()
13
+ const { $vUtils } = proxy
14
+
15
+ let defaultOption = {
16
+ mode: 'read',
17
+ showToolbar: false
18
+ }
19
+
20
+ const excelOptions = computed(() => {
21
+ return Object.assign({}, defaultOption, props.options)
22
+ })
23
+
24
+ const domRender = async (data, container) => {
25
+ if (!data || typeof data === 'string') {
26
+ container.innerHTML = data
27
+ return true
28
+ }
29
+ const buffer = await data.arrayBuffer()
30
+ const wb = new ExcelJS.Workbook()
31
+ // 微软的 Excel ColorIndex 一个索引数字对应一个颜色
32
+ let workbook = await wb.xlsx.load(buffer)
33
+ let workbookData = []
34
+ workbook.eachSheet(sheet => {
35
+ // 构造x-data-spreadsheet sheet 数据源结构
36
+ let sheetData = { name: sheet.name, styles: [], rows: {}, merges: [] }
37
+ // 收集合并单元格信息
38
+ let mergeAddressData = []
39
+ for (let mergeRange in sheet._merges) {
40
+ sheetData.merges.push(sheet._merges[mergeRange].shortRange)
41
+ let mergeAddress = {}
42
+ // 合并单元格起始地址
43
+ mergeAddress.startAddress = sheet._merges[mergeRange].tl
44
+ // 合并单元格终止地址
45
+ mergeAddress.endAddress = sheet._merges[mergeRange].br
46
+ // Y轴方向跨度
47
+ mergeAddress.YRange = sheet._merges[mergeRange].model.bottom - sheet._merges[mergeRange].model.top
48
+ // X轴方向跨度
49
+ mergeAddress.XRange = sheet._merges[mergeRange].model.right - sheet._merges[mergeRange].model.left
50
+ mergeAddressData.push(mergeAddress)
51
+ }
52
+ sheetData.cols = {}
53
+ for (let i = 0; i < sheet.columns.length; i++) {
54
+ sheetData.cols[i.toString()] = {}
55
+ if (sheet.columns[i].width) {
56
+ // 不知道为什么从 exceljs 读取的宽度显示到 x-data-spreadsheet 特别小, 这里乘以8
57
+ sheetData.cols[i.toString()].width = sheet.columns[i].width * 8
58
+ } else {
59
+ // 默认列宽
60
+ sheetData.cols[i.toString()].width = 100
61
+ }
62
+ }
63
+
64
+ // 遍历行
65
+ sheet.eachRow((row, rowIndex) => {
66
+ sheetData.rows[(rowIndex - 1).toString()] = { cells: {} }
67
+ //includeEmpty = false 不包含空白单元格
68
+ row.eachCell({ includeEmpty: true }, function (cell, colNumber) {
69
+ let cellText = ''
70
+ if (cell.value && cell.value.result) {
71
+ // Excel 单元格有公式
72
+ cellText = cell.value.result
73
+ } else if (cell.value && cell.value.richText) {
74
+ // Excel 单元格是多行文本
75
+ for (let text in cell.value.richText) {
76
+ // 多行文本做累加
77
+ cellText += cell.value.richText[text].text
78
+ }
79
+ } else {
80
+ // Excel 单元格无公式
81
+ cellText = cell.value
82
+ }
83
+ //解析单元格,包含样式
84
+ //*********************单元格存在背景色******************************
85
+ // 单元格存在背景色
86
+ let backGroundColor = null
87
+ if (cell.style.fill && cell.style.fill.fgColor && cell.style.fill.fgColor.argb) {
88
+ // 8位字符颜色先转rgb再转16进制颜色
89
+ backGroundColor = (val => {
90
+ val = val.trim().toLowerCase() //去掉前后空格
91
+ let argb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(val)
92
+ let rgb = `rgba(${parseInt(argb[2], 16)}, ${parseInt(argb[3], 16)}, ${parseInt(argb[4], 16)})`
93
+ let percent = (parseInt(argb[1], 16) / 255) * 100
94
+ return $vUtils.fade(rgb, percent)
95
+ })(cell.style.fill.fgColor.argb)
96
+ }
97
+
98
+ if (backGroundColor) {
99
+ cell.style.bgcolor = backGroundColor
100
+ }
101
+ //*************************************************************************** */
102
+
103
+ //*********************字体存在背景色******************************
104
+ // 字体颜色
105
+ let fontColor = null
106
+ if (cell.style.font && cell.style.font.color && cell.style.font.color.argb) {
107
+ // 8位字符颜色先转rgb再转16进制颜色
108
+ fontColor = (val => {
109
+ val = val.trim().toLowerCase() //去掉前后空格
110
+ let argb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(val)
111
+ let rgb = `rgba(${parseInt(argb[2], 16)}, ${parseInt(argb[3], 16)}, ${parseInt(argb[4], 16)})`
112
+ let percent = (parseInt(argb[1], 16) / 255) * 100
113
+ return $vUtils.fade(rgb, percent)
114
+ })(cell.style.font.color.argb)
115
+ }
116
+ if (fontColor) {
117
+ cell.style.color = fontColor
118
+ }
119
+
120
+ // exceljs 对齐的格式转成 x-date-spreedsheet 能识别的对齐格式
121
+ if (cell.style.alignment && cell.style.alignment.horizontal) {
122
+ cell.style.align = cell.style.alignment.horizontal
123
+ cell.style.valign = cell.style.alignment.vertical
124
+ }
125
+
126
+ //处理合并单元格
127
+ let mergeAddress = mergeAddressData.find(o => o.startAddress === cell._address)
128
+ if (mergeAddress) {
129
+ // 遍历的单元格属于合并单元格
130
+ if (cell.master.address !== mergeAddress.startAddress) {
131
+ // 不是合并单元格中的第一个单元格不需要计入数据源
132
+ return
133
+ }
134
+ // 说明是合并单元格区域的起始单元格
135
+ sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()] = { text: cellText, style: 0, merge: [mergeAddress.YRange, mergeAddress.XRange] }
136
+ sheetData.styles.push(cell.style)
137
+ //对应的style存放序号
138
+ sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()].style = sheetData.styles.length - 1
139
+ } else {
140
+ // 非合并单元格
141
+ sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()] = { text: cellText, style: 0 }
142
+ //解析单元格,包含样式
143
+ sheetData.styles.push(cell.style)
144
+ //对应的style存放序号
145
+ sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()].style = sheetData.styles.length - 1
146
+ }
147
+ })
148
+ })
149
+ workbookData.push(sheetData)
150
+ })
151
+ console.log(workbookData)
152
+ // return new Spreadsheet(container, excelOptions).loadData(workbookData)
153
+ }
154
+
155
+ const useData = dataHook(props, context, proxy, {
156
+ domRender
157
+ })
158
+
159
+ return {
160
+ ...useData
161
+ }
162
+ }
163
+ })
164
+ </script>
165
+
166
+ <template>
167
+ <div ref="rootRef" class="sh-office-excel"></div>
168
+ </template>
169
+
170
+ <style lang="scss" scoped>
171
+ .x-spreadsheet {
172
+ font-size: 13px;
173
+ line-height: normal;
174
+ user-select: none;
175
+ -moz-user-select: none;
176
+ font-family: 'Lato', 'Source Sans Pro', Roboto, Helvetica, Arial, sans-serif;
177
+ box-sizing: content-box;
178
+ background: #fff;
179
+ -webkit-font-smoothing: antialiased;
180
+ }
181
+ .x-spreadsheet textarea {
182
+ font: 400 13px Arial, 'Lato', 'Source Sans Pro', Roboto, Helvetica, sans-serif;
183
+ }
184
+ .x-spreadsheet-sheet {
185
+ position: relative;
186
+ overflow: hidden;
187
+ }
188
+ .x-spreadsheet-table {
189
+ vertical-align: bottom;
190
+ }
191
+ .x-spreadsheet-tooltip {
192
+ font-family: inherit;
193
+ position: absolute;
194
+ padding: 5px 10px;
195
+ color: #fff;
196
+ border-radius: 1px;
197
+ background: #000000;
198
+ font-size: 12px;
199
+ z-index: 201;
200
+ }
201
+ .x-spreadsheet-tooltip:before {
202
+ pointer-events: none;
203
+ position: absolute;
204
+ left: calc(50% - 4px);
205
+ top: -4px;
206
+ content: '';
207
+ width: 8px;
208
+ height: 8px;
209
+ background: inherit;
210
+ -webkit-transform: rotate(45deg);
211
+ transform: rotate(45deg);
212
+ z-index: 1;
213
+ box-shadow: 1px 1px 3px -1px rgba(0, 0, 0, 0.3);
214
+ }
215
+ .x-spreadsheet-color-palette {
216
+ padding: 5px;
217
+ }
218
+ .x-spreadsheet-color-palette table {
219
+ margin: 0;
220
+ padding: 0;
221
+ border-collapse: separate;
222
+ background: #fff;
223
+ }
224
+ .x-spreadsheet-color-palette table td {
225
+ margin: 0;
226
+ cursor: pointer;
227
+ border: 1px solid transparent;
228
+ }
229
+ .x-spreadsheet-color-palette table td:hover {
230
+ border-color: #ddd;
231
+ }
232
+ .x-spreadsheet-color-palette table td .x-spreadsheet-color-palette-cell {
233
+ width: 16px;
234
+ height: 16px;
235
+ }
236
+ .x-spreadsheet-border-palette {
237
+ padding: 6px;
238
+ }
239
+ .x-spreadsheet-border-palette table {
240
+ margin: 0;
241
+ padding: 0;
242
+ border-collapse: separate;
243
+ border-spacing: 0;
244
+ background: #fff;
245
+ table-layout: fixed;
246
+ }
247
+ .x-spreadsheet-border-palette table td {
248
+ margin: 0;
249
+ }
250
+ .x-spreadsheet-border-palette .x-spreadsheet-border-palette-left {
251
+ border-right: 1px solid #eee;
252
+ padding-right: 6px;
253
+ }
254
+ .x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell {
255
+ width: 30px;
256
+ height: 30px;
257
+ cursor: pointer;
258
+ text-align: center;
259
+ }
260
+ .x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell:hover {
261
+ background-color: #eee;
262
+ }
263
+ .x-spreadsheet-border-palette .x-spreadsheet-border-palette-right {
264
+ padding-left: 6px;
265
+ }
266
+ .x-spreadsheet-border-palette .x-spreadsheet-border-palette-right .x-spreadsheet-line-type {
267
+ position: relative;
268
+ left: 0;
269
+ top: -3px;
270
+ }
271
+ .x-spreadsheet-dropdown {
272
+ position: relative;
273
+ }
274
+ .x-spreadsheet-dropdown .x-spreadsheet-dropdown-content {
275
+ position: absolute;
276
+ z-index: 200;
277
+ background: #fff;
278
+ box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
279
+ }
280
+ .x-spreadsheet-dropdown.bottom-left .x-spreadsheet-dropdown-content {
281
+ top: calc(100% + 5px);
282
+ left: 0;
283
+ }
284
+ .x-spreadsheet-dropdown.bottom-right .x-spreadsheet-dropdown-content {
285
+ top: calc(100% + 5px);
286
+ right: 0;
287
+ }
288
+ .x-spreadsheet-dropdown.top-left .x-spreadsheet-dropdown-content {
289
+ bottom: calc(100% + 5px);
290
+ left: 0;
291
+ }
292
+ .x-spreadsheet-dropdown.top-right .x-spreadsheet-dropdown-content {
293
+ bottom: calc(100% + 5px);
294
+ right: 0;
295
+ }
296
+ .x-spreadsheet-dropdown .x-spreadsheet-dropdown-title {
297
+ padding: 0 5px;
298
+ display: inline-block;
299
+ }
300
+ /* resizer **/
301
+ .x-spreadsheet-resizer {
302
+ position: absolute;
303
+ z-index: 11;
304
+ }
305
+ .x-spreadsheet-resizer .x-spreadsheet-resizer-hover {
306
+ background-color: rgba(75, 137, 255, 0.25);
307
+ }
308
+ .x-spreadsheet-resizer .x-spreadsheet-resizer-line {
309
+ position: absolute;
310
+ }
311
+ .x-spreadsheet-resizer.horizontal {
312
+ cursor: row-resize;
313
+ }
314
+ .x-spreadsheet-resizer.horizontal .x-spreadsheet-resizer-line {
315
+ border-bottom: 2px dashed #4b89ff;
316
+ left: 0;
317
+ bottom: 0;
318
+ }
319
+ .x-spreadsheet-resizer.vertical {
320
+ cursor: col-resize;
321
+ }
322
+ .x-spreadsheet-resizer.vertical .x-spreadsheet-resizer-line {
323
+ border-right: 2px dashed #4b89ff;
324
+ top: 0;
325
+ right: 0;
326
+ }
327
+ /* scrollbar */
328
+ .x-spreadsheet-scrollbar {
329
+ position: absolute;
330
+ bottom: 0;
331
+ right: 0;
332
+ background-color: #f4f5f8;
333
+ opacity: 0.9;
334
+ z-index: 12;
335
+ }
336
+ .x-spreadsheet-scrollbar.horizontal {
337
+ right: 15px;
338
+ overflow-x: scroll;
339
+ overflow-y: hidden;
340
+ }
341
+ .x-spreadsheet-scrollbar.horizontal > div {
342
+ height: 1px;
343
+ background: #ddd;
344
+ }
345
+ .x-spreadsheet-scrollbar.vertical {
346
+ bottom: 15px;
347
+ overflow-x: hidden;
348
+ overflow-y: scroll;
349
+ }
350
+ .x-spreadsheet-scrollbar.vertical > div {
351
+ width: 1px;
352
+ background: #ddd;
353
+ }
354
+ /* @{css-prefix}-overlayer */
355
+ .x-spreadsheet-overlayer {
356
+ position: absolute;
357
+ left: 0;
358
+ top: 0;
359
+ z-index: 10;
360
+ }
361
+ .x-spreadsheet-overlayer .x-spreadsheet-overlayer-content {
362
+ position: absolute;
363
+ overflow: hidden;
364
+ pointer-events: none;
365
+ width: 100%;
366
+ height: 100%;
367
+ }
368
+ .x-spreadsheet-editor,
369
+ .x-spreadsheet-selector {
370
+ box-sizing: content-box;
371
+ position: absolute;
372
+ overflow: hidden;
373
+ pointer-events: none;
374
+ top: 0;
375
+ left: 0;
376
+ width: 100%;
377
+ height: 100%;
378
+ }
379
+ /* @{css-prefix}-selector */
380
+ .x-spreadsheet-selector .hide-input {
381
+ position: absolute;
382
+ z-index: 0;
383
+ }
384
+ .x-spreadsheet-selector .hide-input input {
385
+ padding: 0;
386
+ width: 0;
387
+ border: none !important;
388
+ }
389
+ .x-spreadsheet-selector .x-spreadsheet-selector-area {
390
+ position: absolute;
391
+ border: 2px solid #4b89ff;
392
+ background: rgba(75, 137, 255, 0.1);
393
+ z-index: 5;
394
+ }
395
+ .x-spreadsheet-selector .x-spreadsheet-selector-clipboard,
396
+ .x-spreadsheet-selector .x-spreadsheet-selector-autofill {
397
+ position: absolute;
398
+ background: transparent;
399
+ z-index: 100;
400
+ }
401
+ .x-spreadsheet-selector .x-spreadsheet-selector-clipboard {
402
+ border: 2px dashed #4b89ff;
403
+ }
404
+ .x-spreadsheet-selector .x-spreadsheet-selector-autofill {
405
+ border: 1px dashed rgba(0, 0, 0, 0.45);
406
+ }
407
+ .x-spreadsheet-selector .x-spreadsheet-selector-corner {
408
+ pointer-events: auto;
409
+ position: absolute;
410
+ cursor: crosshair;
411
+ font-size: 0;
412
+ height: 5px;
413
+ width: 5px;
414
+ right: -5px;
415
+ bottom: -5px;
416
+ border: 2px solid #ffffff;
417
+ background: #4b89ff;
418
+ }
419
+ .x-spreadsheet-editor {
420
+ z-index: 20;
421
+ }
422
+ .x-spreadsheet-editor .x-spreadsheet-editor-area {
423
+ position: absolute;
424
+ text-align: left;
425
+ border: 2px solid #4b89ff;
426
+ line-height: 0;
427
+ z-index: 100;
428
+ pointer-events: auto;
429
+ }
430
+ .x-spreadsheet-editor .x-spreadsheet-editor-area textarea {
431
+ box-sizing: content-box;
432
+ border: none;
433
+ padding: 0 3px;
434
+ outline: none;
435
+ resize: none;
436
+ text-align: start;
437
+ overflow-y: hidden;
438
+ font: 400 13px Arial, 'Lato', 'Source Sans Pro', Roboto, Helvetica, sans-serif;
439
+ color: inherit;
440
+ white-space: normal;
441
+ word-wrap: break-word;
442
+ line-height: 22px;
443
+ margin: 0;
444
+ }
445
+ .x-spreadsheet-editor .x-spreadsheet-editor-area .textline {
446
+ overflow: hidden;
447
+ visibility: hidden;
448
+ position: fixed;
449
+ top: 0;
450
+ left: 0;
451
+ }
452
+ .x-spreadsheet-item {
453
+ user-select: none;
454
+ background: 0;
455
+ border: 1px solid transparent;
456
+ outline: none;
457
+ height: 26px;
458
+ color: rgba(0, 0, 0, 0.9);
459
+ line-height: 26px;
460
+ list-style: none;
461
+ padding: 2px 10px;
462
+ cursor: default;
463
+ text-align: left;
464
+ overflow: hidden;
465
+ }
466
+ .x-spreadsheet-item.disabled {
467
+ pointer-events: none;
468
+ opacity: 0.5;
469
+ }
470
+ .x-spreadsheet-item:hover,
471
+ .x-spreadsheet-item.active {
472
+ background: rgba(0, 0, 0, 0.05);
473
+ }
474
+ .x-spreadsheet-item.divider {
475
+ height: 0;
476
+ padding: 0;
477
+ margin: 5px 0;
478
+ border: none;
479
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
480
+ }
481
+ .x-spreadsheet-item .label {
482
+ float: right;
483
+ opacity: 0.65;
484
+ font-size: 1em;
485
+ }
486
+ .x-spreadsheet-item.state,
487
+ .x-spreadsheet-header.state {
488
+ padding-left: 35px !important;
489
+ position: relative;
490
+ }
491
+ .x-spreadsheet-item.state:before,
492
+ .x-spreadsheet-header.state:before {
493
+ content: '';
494
+ position: absolute;
495
+ width: 10px;
496
+ height: 10px;
497
+ left: 12px;
498
+ top: calc(50% - 5px);
499
+ background: rgba(0, 0, 0, 0.08);
500
+ border-radius: 2px;
501
+ }
502
+ .x-spreadsheet-item.state.checked:before,
503
+ .x-spreadsheet-header.state.checked:before {
504
+ background: #4b89ff;
505
+ }
506
+ .x-spreadsheet-checkbox {
507
+ position: relative;
508
+ display: inline-block;
509
+ backface-visibility: hidden;
510
+ outline: 0;
511
+ vertical-align: baseline;
512
+ font-style: normal;
513
+ font-size: 1rem;
514
+ line-height: 1em;
515
+ }
516
+ .x-spreadsheet-checkbox > input {
517
+ position: absolute;
518
+ top: 0;
519
+ left: 0;
520
+ opacity: 0 !important;
521
+ outline: 0;
522
+ z-index: -1;
523
+ }
524
+ .x-spreadsheet-suggest,
525
+ .x-spreadsheet-contextmenu,
526
+ .x-spreadsheet-sort-filter {
527
+ position: absolute;
528
+ box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
529
+ background: #fff;
530
+ z-index: 100;
531
+ width: 260px;
532
+ pointer-events: auto;
533
+ overflow: auto;
534
+ }
535
+ .x-spreadsheet-suggest {
536
+ width: 200px;
537
+ }
538
+ .x-spreadsheet-filter {
539
+ border: 1px solid #e9e9e9;
540
+ font-size: 12px;
541
+ margin: 10px;
542
+ }
543
+ .x-spreadsheet-filter .x-spreadsheet-header {
544
+ padding: 0.5em 0.75em;
545
+ background: #f8f8f9;
546
+ border-bottom: 1px solid #e9e9e9;
547
+ border-left: 1px solid transparent;
548
+ }
549
+ .x-spreadsheet-filter .x-spreadsheet-body {
550
+ height: 200px;
551
+ overflow-y: auto;
552
+ }
553
+ .x-spreadsheet-filter .x-spreadsheet-body .x-spreadsheet-item {
554
+ height: 20px;
555
+ line-height: 20px;
556
+ }
557
+ .x-spreadsheet-sort-filter .x-spreadsheet-buttons {
558
+ margin: 10px;
559
+ }
560
+ .x-spreadsheet-bottombar {
561
+ height: 40px;
562
+ padding: 0 30px;
563
+ text-align: left;
564
+ background: #f5f6f7;
565
+ display: flex;
566
+ }
567
+ .x-spreadsheet-bottombar {
568
+ position: relative;
569
+ border-top: 1px solid #e0e2e4;
570
+ }
571
+ .x-spreadsheet-bottombar .x-spreadsheet-menu > li {
572
+ line-height: 40px;
573
+ height: 40px;
574
+ padding-top: 0;
575
+ padding-bottom: 0;
576
+ vertical-align: middle;
577
+ border-right: 1px solid #e8eaed;
578
+ }
579
+ .x-spreadsheet-menu {
580
+ list-style: none;
581
+ margin: 0;
582
+ padding: 0;
583
+ user-select: none;
584
+ }
585
+ .x-spreadsheet-menu > li {
586
+ float: left;
587
+ line-height: 1.25em;
588
+ padding: 0.785em 1em;
589
+ margin: 0;
590
+ vertical-align: middle;
591
+ text-align: left;
592
+ color: #80868b;
593
+ white-space: nowrap;
594
+ cursor: pointer;
595
+ transition: all 0.3s;
596
+ font-weight: bold;
597
+ }
598
+ .x-spreadsheet-menu > li.active {
599
+ background-color: #fff;
600
+ color: rgba(0, 0, 0, 0.65);
601
+ }
602
+ .x-spreadsheet-menu > li .x-spreadsheet-dropdown {
603
+ display: inline-block;
604
+ }
605
+ .x-spreadsheet-print {
606
+ position: absolute;
607
+ left: 0;
608
+ top: 0;
609
+ z-index: 100;
610
+ width: 100%;
611
+ height: 100%;
612
+ display: flex;
613
+ flex-direction: column;
614
+ }
615
+ .x-spreadsheet-print-bar {
616
+ background: #424242;
617
+ height: 60px;
618
+ line-height: 60px;
619
+ padding: 0 30px;
620
+ }
621
+ .x-spreadsheet-print-bar .-title {
622
+ color: #fff;
623
+ font-weight: bold;
624
+ font-size: 1.2em;
625
+ float: left;
626
+ }
627
+ .x-spreadsheet-print-bar .-right {
628
+ float: right;
629
+ margin-top: 12px;
630
+ }
631
+ .x-spreadsheet-print-content {
632
+ display: flex;
633
+ flex: auto;
634
+ flex-direction: row;
635
+ background: #d0d0d0;
636
+ height: calc(100% - 60px);
637
+ }
638
+ .x-spreadsheet-print-content .-sider {
639
+ flex: 0 0 300px;
640
+ width: 300px;
641
+ border-left: 2px solid #ccc;
642
+ background: #fff;
643
+ }
644
+ .x-spreadsheet-print-content .-content {
645
+ flex: auto;
646
+ overflow-x: auto;
647
+ overflow-y: scroll;
648
+ height: 100%;
649
+ }
650
+ .x-spreadsheet-canvas-card-wraper {
651
+ margin: 40px 20px;
652
+ }
653
+ .x-spreadsheet-canvas-card {
654
+ background: #fff;
655
+ margin: auto;
656
+ page-break-before: auto;
657
+ page-break-after: always;
658
+ box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 3px rgba(0, 0, 0, 0.12), 0 4px 5px 0 rgba(0, 0, 0, 0.2);
659
+ }
660
+ .x-spreadsheet-calendar {
661
+ color: rgba(0, 0, 0, 0.65);
662
+ background: #ffffff;
663
+ user-select: none;
664
+ }
665
+ .x-spreadsheet-calendar .calendar-header {
666
+ font-weight: 700;
667
+ line-height: 30px;
668
+ text-align: center;
669
+ width: 100%;
670
+ float: left;
671
+ background: #f9fafb;
672
+ }
673
+ .x-spreadsheet-calendar .calendar-header .calendar-header-left {
674
+ padding-left: 5px;
675
+ float: left;
676
+ }
677
+ .x-spreadsheet-calendar .calendar-header .calendar-header-right {
678
+ float: right;
679
+ }
680
+ .x-spreadsheet-calendar .calendar-header .calendar-header-right a {
681
+ padding: 3px 0;
682
+ margin-right: 2px;
683
+ border-radius: 2px;
684
+ }
685
+ .x-spreadsheet-calendar .calendar-header .calendar-header-right a:hover {
686
+ background: rgba(0, 0, 0, 0.08);
687
+ }
688
+ .x-spreadsheet-calendar .calendar-body {
689
+ border-collapse: collapse;
690
+ border-spacing: 0;
691
+ }
692
+ .x-spreadsheet-calendar .calendar-body th,
693
+ .x-spreadsheet-calendar .calendar-body td {
694
+ width: 14.28571429%;
695
+ min-width: 32px;
696
+ text-align: center;
697
+ font-weight: 700;
698
+ line-height: 30px;
699
+ padding: 0;
700
+ }
701
+ .x-spreadsheet-calendar .calendar-body td > .cell:hover {
702
+ background: #ecf6fd;
703
+ }
704
+ .x-spreadsheet-calendar .calendar-body td > .cell.active,
705
+ .x-spreadsheet-calendar .calendar-body td > .cell.active:hover {
706
+ background: #ecf6fd;
707
+ color: #2185d0;
708
+ }
709
+ .x-spreadsheet-calendar .calendar-body td > .cell.disabled {
710
+ pointer-events: none;
711
+ opacity: 0.5;
712
+ }
713
+ .x-spreadsheet-datepicker {
714
+ box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
715
+ position: absolute;
716
+ left: 0;
717
+ top: calc(100% + 5px);
718
+ z-index: 10;
719
+ width: auto;
720
+ }
721
+ .x-spreadsheet-buttons {
722
+ display: flex;
723
+ justify-content: flex-end;
724
+ }
725
+ .x-spreadsheet-buttons .x-spreadsheet-button {
726
+ margin-left: 8px;
727
+ }
728
+ .x-spreadsheet-button {
729
+ display: inline-block;
730
+ border-radius: 3px;
731
+ line-height: 1em;
732
+ min-height: 1em;
733
+ white-space: nowrap;
734
+ text-align: center;
735
+ cursor: pointer;
736
+ font-size: 1em;
737
+ font-weight: 700;
738
+ padding: 0.75em 1em;
739
+ color: rgba(0, 0, 0, 0.6);
740
+ background: #e0e1e2;
741
+ text-decoration: none;
742
+ font-family: 'Lato', 'proxima-nova', 'Helvetica Neue', Arial, sans-serif;
743
+ outline: none;
744
+ vertical-align: baseline;
745
+ zoom: 1;
746
+ user-select: none;
747
+ transition: all 0.1s linear;
748
+ }
749
+ .x-spreadsheet-button.active,
750
+ .x-spreadsheet-button:hover {
751
+ background-color: #c0c1c2;
752
+ color: rgba(0, 0, 0, 0.8);
753
+ }
754
+ .x-spreadsheet-button.primary {
755
+ color: #fff;
756
+ background-color: #2185d0;
757
+ }
758
+ .x-spreadsheet-button.primary:hover,
759
+ .x-spreadsheet-button.primary.active {
760
+ color: #fff;
761
+ background-color: #1678c2;
762
+ }
763
+ .x-spreadsheet-form-input {
764
+ font-size: 1em;
765
+ position: relative;
766
+ font-weight: 400;
767
+ display: inline-flex;
768
+ color: rgba(0, 0, 0, 0.87);
769
+ }
770
+ .x-spreadsheet-form-input input {
771
+ z-index: 1;
772
+ margin: 0;
773
+ max-width: 100%;
774
+ flex: 1 0 auto;
775
+ outline: 0;
776
+ -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
777
+ text-align: left;
778
+ line-height: 30px;
779
+ height: 30px;
780
+ padding: 0 8px;
781
+ background: #fff;
782
+ border: 1px solid #e9e9e9;
783
+ border-radius: 3px;
784
+ transition: box-shadow 0.1s ease, border-color 0.1s ease;
785
+ box-shadow: inset 0 1px 2px hsla(0, 0%, 4%, 0.06);
786
+ }
787
+ .x-spreadsheet-form-input input:focus {
788
+ border-color: #4b89ff;
789
+ box-shadow: inset 0 1px 2px rgba(75, 137, 255, 0.2);
790
+ }
791
+ .x-spreadsheet-form-select {
792
+ position: relative;
793
+ display: inline-block;
794
+ background: #fff;
795
+ border: 1px solid #e9e9e9;
796
+ border-radius: 2px;
797
+ cursor: pointer;
798
+ color: rgba(0, 0, 0, 0.87);
799
+ user-select: none;
800
+ box-shadow: inset 0 1px 2px hsla(0, 0%, 4%, 0.06);
801
+ }
802
+ .x-spreadsheet-form-select .input-text {
803
+ text-overflow: ellipsis;
804
+ white-space: nowrap;
805
+ min-width: 60px;
806
+ width: auto;
807
+ height: 30px;
808
+ line-height: 30px;
809
+ padding: 0 8px;
810
+ }
811
+ .x-spreadsheet-form-fields {
812
+ display: flex;
813
+ flex-direction: row;
814
+ flex-wrap: wrap;
815
+ }
816
+ .x-spreadsheet-form-fields .x-spreadsheet-form-field {
817
+ flex: 0 1 auto;
818
+ }
819
+ .x-spreadsheet-form-fields .x-spreadsheet-form-field .label {
820
+ display: inline-block;
821
+ margin: 0 10px 0 0;
822
+ }
823
+ .x-spreadsheet-form-field {
824
+ display: block;
825
+ vertical-align: middle;
826
+ margin-left: 10px;
827
+ margin-bottom: 10px;
828
+ }
829
+ .x-spreadsheet-form-field:first-child {
830
+ margin-left: 0;
831
+ }
832
+ .x-spreadsheet-form-field.error .x-spreadsheet-form-select,
833
+ .x-spreadsheet-form-field.error input {
834
+ border-color: #f04134;
835
+ }
836
+ .x-spreadsheet-form-field .tip {
837
+ color: #f04134;
838
+ font-size: 0.9em;
839
+ }
840
+ .x-spreadsheet-dimmer {
841
+ display: none;
842
+ position: absolute;
843
+ top: 0 !important;
844
+ left: 0 !important;
845
+ width: 100%;
846
+ height: 100%;
847
+ text-align: center;
848
+ vertical-align: middle;
849
+ background-color: rgba(0, 0, 0, 0.6);
850
+ opacity: 0;
851
+ -webkit-animation-fill-mode: both;
852
+ animation-fill-mode: both;
853
+ -webkit-animation-duration: 0.5s;
854
+ animation-duration: 0.5s;
855
+ transition: background-color 0.5s linear;
856
+ user-select: none;
857
+ z-index: 1000;
858
+ }
859
+ .x-spreadsheet-dimmer.active {
860
+ display: block;
861
+ opacity: 1;
862
+ }
863
+ .x-spreadsheet-modal,
864
+ .x-spreadsheet-toast {
865
+ font-size: 13px;
866
+ position: fixed;
867
+ z-index: 1001;
868
+ text-align: left;
869
+ line-height: 1.25em;
870
+ min-width: 360px;
871
+ color: rgba(0, 0, 0, 0.87);
872
+ font-family: 'Lato', 'Source Sans Pro', Roboto, Helvetica, Arial, sans-serif;
873
+ border-radius: 4px;
874
+ border: 1px solid rgba(0, 0, 0, 0.1);
875
+ background-color: #fff;
876
+ background-clip: padding-box;
877
+ box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 8px;
878
+ }
879
+ .x-spreadsheet-toast {
880
+ background-color: rgba(255, 255, 255, 0.85);
881
+ }
882
+ .x-spreadsheet-modal-header,
883
+ .x-spreadsheet-toast-header {
884
+ font-weight: 600;
885
+ background-clip: padding-box;
886
+ background-color: rgba(255, 255, 255, 0.85);
887
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
888
+ border-radius: 4px 4px 0 0;
889
+ }
890
+
891
+ .x-spreadsheet-toast-header {
892
+ color: #f2711c;
893
+ }
894
+ .x-spreadsheet-modal-header {
895
+ border-bottom: 1px solid #e0e2e4;
896
+ background: rgba(0, 0, 0, 0.08);
897
+ font-size: 1.0785em;
898
+ }
899
+ .x-spreadsheet-modal-header,
900
+ .x-spreadsheet-modal-content,
901
+ .x-spreadsheet-toast-header,
902
+ .x-spreadsheet-toast-content {
903
+ padding: 0.75em 1em;
904
+ }
905
+
906
+ .x-spreadsheet-menu li:first-child {
907
+ display: none;
908
+ }
909
+ .sh-office-excel {
910
+ form fieldset {
911
+ border: none;
912
+ }
913
+ form fieldset label {
914
+ display: block;
915
+ margin-bottom: 0.5em;
916
+ font-size: 1em;
917
+ color: #666;
918
+ }
919
+ form fieldset select {
920
+ font-size: 1.1em;
921
+ width: 100%;
922
+ background-color: #fff;
923
+ border: none;
924
+ border-bottom: 2px solid #ddd;
925
+ padding: 0.5em 0.85em;
926
+ border-radius: 2px;
927
+ }
928
+ }
929
+ </style>