@shival99/z-ui 1.0.15 → 1.0.16

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,6 +1,10 @@
1
- import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
2
1
  import * as i0 from '@angular/core';
3
- import { inject, signal, Injectable, InjectionToken, PLATFORM_ID, effect } from '@angular/core';
2
+ import { Injectable, inject, signal, InjectionToken, PLATFORM_ID, effect } from '@angular/core';
3
+ import { zFormatNumExcel, zConvertColorToArgb } from '@shival99/z-ui/utils';
4
+ import * as ExcelJS from 'exceljs';
5
+ import { saveAs } from 'file-saver';
6
+ import * as XLSX from 'xlsx';
7
+ import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
4
8
  import { Router } from '@angular/router';
5
9
  import { firstValueFrom, from, switchMap, of, catchError, throwError, tap, map, defer, BehaviorSubject, Subject } from 'rxjs';
6
10
  import { TranslateService } from '@ngx-translate/core';
@@ -156,6 +160,763 @@ class ZCacheService {
156
160
  }
157
161
  }
158
162
 
163
+ const Z_EXCEL_COLORS = {
164
+ 'green-50': 'FFF0FDF4',
165
+ 'green-100': 'FFDCFCE7',
166
+ 'green-200': 'FFBBF7D0',
167
+ 'green-300': 'FF86EFAC',
168
+ 'green-400': 'FF4ADE80',
169
+ 'green-500': 'FF22C55E',
170
+ 'blue-50': 'FFEFF6FF',
171
+ 'blue-100': 'FFDBEAFE',
172
+ 'blue-200': 'FFBFDBFE',
173
+ 'blue-300': 'FF93C5FD',
174
+ 'blue-400': 'FF60A5FA',
175
+ 'blue-500': 'FF3B82F6',
176
+ 'gray-50': 'FFF9FAFB',
177
+ 'gray-100': 'FFF3F4F6',
178
+ 'gray-200': 'FFE5E7EB',
179
+ 'gray-300': 'FFD1D5DB',
180
+ 'gray-400': 'FF9CA3AF',
181
+ 'gray-500': 'FF6B7280',
182
+ 'yellow-50': 'FFFFFBEB',
183
+ 'yellow-100': 'FFFEF3C7',
184
+ 'yellow-200': 'FFFDE68A',
185
+ 'yellow-300': 'FFFCD34D',
186
+ 'red-50': 'FFFEF2F2',
187
+ 'red-100': 'FFFEE2E2',
188
+ 'red-200': 'FFFECACA',
189
+ 'red-300': 'FFFCA5A5',
190
+ white: 'FFFFFFFF',
191
+ black: 'FF000000',
192
+ transparent: '00000000',
193
+ };
194
+ const Z_EXCEL_DEFAULT_CONFIG = {
195
+ font: {
196
+ name: 'Calibri',
197
+ size: 11,
198
+ },
199
+ headerFont: {
200
+ name: 'Calibri',
201
+ size: 11,
202
+ bold: true,
203
+ },
204
+ headerColors: {
205
+ level0: Z_EXCEL_COLORS['green-300'],
206
+ level1: Z_EXCEL_COLORS['blue-200'],
207
+ },
208
+ };
209
+ const Z_EXCEL_BORDER_THIN = {
210
+ top: { style: 'thin' },
211
+ left: { style: 'thin' },
212
+ bottom: { style: 'thin' },
213
+ right: { style: 'thin' },
214
+ };
215
+ const Z_EXCEL_CHAR_WIDTH_MAP = {
216
+ W: 1.4,
217
+ M: 1.4,
218
+ D: 1.2,
219
+ O: 1.2,
220
+ Q: 1.2,
221
+ A: 1.1,
222
+ B: 1.1,
223
+ C: 1.1,
224
+ G: 1.1,
225
+ H: 1.1,
226
+ N: 1.1,
227
+ R: 1.1,
228
+ S: 1.1,
229
+ U: 1.1,
230
+ V: 1.1,
231
+ X: 1.1,
232
+ Y: 1.1,
233
+ Z: 1.1,
234
+ E: 1.0,
235
+ F: 1.0,
236
+ K: 1.0,
237
+ P: 1.0,
238
+ T: 1.0,
239
+ J: 0.9,
240
+ L: 0.9,
241
+ I: 0.6,
242
+ i: 0.5,
243
+ l: 0.5,
244
+ t: 0.6,
245
+ f: 0.6,
246
+ j: 0.5,
247
+ '1': 0.8,
248
+ '!': 0.5,
249
+ '.': 0.5,
250
+ ',': 0.5,
251
+ ':': 0.5,
252
+ ';': 0.5,
253
+ '|': 0.5,
254
+ ' ': 0.5,
255
+ };
256
+ const Z_EXCEL_FONT_MULTIPLIERS = {
257
+ 'Times New Roman': 1.0,
258
+ Arial: 0.95,
259
+ Calibri: 0.95,
260
+ 'Courier New': 1.2,
261
+ 'Comic Sans MS': 1.15,
262
+ Verdana: 1.05,
263
+ Tahoma: 0.9,
264
+ Georgia: 1.05,
265
+ Impact: 0.85,
266
+ 'Trebuchet MS': 0.95,
267
+ };
268
+ const Z_EXCEL_WIDTH_LIMITS = {
269
+ min: 5,
270
+ max: 50,
271
+ tableMin: 8,
272
+ tableMax: 30,
273
+ default: 20,
274
+ };
275
+
276
+ class ZExcelService {
277
+ static _isHeaderConfig(config) {
278
+ if (!config || typeof config !== 'object') {
279
+ return false;
280
+ }
281
+ return config.constructor === Object;
282
+ }
283
+ static _getHeaderConfig(col) {
284
+ const empty = {
285
+ content: undefined,
286
+ class: undefined,
287
+ style: undefined,
288
+ align: undefined,
289
+ tooltip: undefined,
290
+ rowSpan: undefined,
291
+ colSpan: undefined,
292
+ };
293
+ if (!col) {
294
+ return empty;
295
+ }
296
+ if (!ZExcelService._isHeaderConfig(col.header)) {
297
+ return { ...empty, content: col.header };
298
+ }
299
+ return {
300
+ content: col.header.content,
301
+ class: undefined,
302
+ style: undefined,
303
+ align: col.header.align,
304
+ tooltip: undefined,
305
+ rowSpan: undefined,
306
+ colSpan: undefined,
307
+ };
308
+ }
309
+ async exportExcel(config, options = {}) {
310
+ try {
311
+ const result = await ZExcelService.exportExcelStatic(config);
312
+ await this._saveFile(result, options);
313
+ }
314
+ catch (error) {
315
+ console.error('Error exporting Excel:', error);
316
+ options.toast?.error?.('Failed to export Excel file');
317
+ throw error;
318
+ }
319
+ }
320
+ async exportFromTable(config, options = {}) {
321
+ try {
322
+ const excelColumns = this._convertTableColumnsToExcel(config);
323
+ const excelConfig = {
324
+ fileName: config.fileName,
325
+ columns: excelColumns,
326
+ source: config.source,
327
+ };
328
+ await this.exportExcel(excelConfig, options);
329
+ }
330
+ catch (error) {
331
+ console.error('Error exporting from table:', error);
332
+ options.toast?.error?.('Failed to export Excel file');
333
+ throw error;
334
+ }
335
+ }
336
+ async exportFromElement(elementId, fileName = 'export', options = {}) {
337
+ try {
338
+ const result = await ZExcelService.exportFromElementStatic(elementId, fileName);
339
+ await this._saveFile(result, options);
340
+ }
341
+ catch (error) {
342
+ console.error('Error exporting from element:', error);
343
+ options.toast?.error?.('Failed to export Excel file');
344
+ throw error;
345
+ }
346
+ }
347
+ async exportFromElementXlsx(elementId, fileName = 'export', options = {}) {
348
+ try {
349
+ const element = document.getElementById(elementId);
350
+ if (!element) {
351
+ throw new Error(`Element with id "${elementId}" not found`);
352
+ }
353
+ const table = element.querySelector('table') || element;
354
+ if (table.tagName !== 'TABLE') {
355
+ throw new Error('Element must be a table or contain a table');
356
+ }
357
+ const workbook = XLSX.utils.table_to_book(table, { sheet: 'Sheet1' });
358
+ const { addTimestamp = true } = options;
359
+ let finalFileName = `${fileName}.xlsx`;
360
+ if (addTimestamp) {
361
+ finalFileName = `${fileName}_${ZExcelService._formatTimestamp()}.xlsx`;
362
+ }
363
+ XLSX.writeFile(workbook, finalFileName);
364
+ if (options.showNotification !== false) {
365
+ options.toast?.success?.(`File "${finalFileName}" has been downloaded`);
366
+ }
367
+ }
368
+ catch (error) {
369
+ console.error('Error exporting from element with XLSX:', error);
370
+ options.toast?.error?.('Failed to export Excel file');
371
+ throw error;
372
+ }
373
+ }
374
+ static async exportExcelStatic(config) {
375
+ const workbook = new ExcelJS.Workbook();
376
+ const { fileName = 'export', columns, source } = config;
377
+ for (const sheetSource of source) {
378
+ const sheet = workbook.addWorksheet(sheetSource.sheetName || 'Sheet1');
379
+ const flatColumns = ZExcelService._flattenColumns(columns);
380
+ const headerLevels = ZExcelService._calculateHeaderLevels(columns);
381
+ sheet.columns = flatColumns.map(col => ({
382
+ key: col.id,
383
+ header: col.header || col.id,
384
+ width: col.width || Z_EXCEL_WIDTH_LIMITS.default,
385
+ style: { font: Z_EXCEL_DEFAULT_CONFIG.font },
386
+ }));
387
+ ZExcelService._createHeaderRows(sheet, columns, headerLevels);
388
+ const dataStartRow = headerLevels + 1;
389
+ const mergedCells = new Set();
390
+ const mergeRegions = ZExcelService._processMergeRegions(flatColumns, sheetSource.data, dataStartRow);
391
+ sheetSource.data.forEach((dataItem, rowIndex) => {
392
+ const row = sheet.addRow([]);
393
+ flatColumns.forEach((col, colIndex) => {
394
+ const cell = row.getCell(colIndex + 1);
395
+ const cellValue = ZExcelService._getCellValue(col, dataItem, rowIndex, sheetSource.data);
396
+ cell.value = cellValue;
397
+ });
398
+ row.eachCell((cell, colNumber) => {
399
+ const colConfig = flatColumns[colNumber - 1];
400
+ const currentRow = dataStartRow + rowIndex + 1;
401
+ const cellKey = `${currentRow}:${colNumber}`;
402
+ if (mergedCells.has(cellKey)) {
403
+ return;
404
+ }
405
+ cell.font = {
406
+ name: Z_EXCEL_DEFAULT_CONFIG.font.name,
407
+ size: Z_EXCEL_DEFAULT_CONFIG.font.size,
408
+ ...(cell.font || {}),
409
+ };
410
+ if (colConfig.formatNum) {
411
+ const rawValue = ZExcelService._getCellValue(colConfig, dataItem, rowIndex, sheetSource.data);
412
+ zFormatNumExcel(cell, rawValue, colConfig.formatNum);
413
+ }
414
+ if (!colConfig.formatNum && colConfig.format) {
415
+ const context = {
416
+ row: dataItem,
417
+ rowIndex,
418
+ data: sheetSource.data,
419
+ cell: cell,
420
+ };
421
+ colConfig.format(context);
422
+ }
423
+ if (colConfig.align) {
424
+ cell.alignment = {
425
+ horizontal: colConfig.align,
426
+ vertical: 'middle',
427
+ ...(cell.alignment || {}),
428
+ };
429
+ }
430
+ if (colConfig.note) {
431
+ const noteText = colConfig.note(dataItem, rowIndex, sheetSource.data);
432
+ if (noteText) {
433
+ cell.note = noteText;
434
+ }
435
+ }
436
+ cell.border = Z_EXCEL_BORDER_THIN;
437
+ });
438
+ });
439
+ mergeRegions.forEach(region => {
440
+ try {
441
+ sheet.mergeCells(region.startRow, region.startCol, region.endRow, region.endCol);
442
+ const mergedCell = sheet.getCell(region.startRow, region.startCol);
443
+ if (!mergedCell.alignment) {
444
+ mergedCell.alignment = { vertical: 'middle' };
445
+ }
446
+ for (let r = region.startRow; r <= region.endRow; r++) {
447
+ for (let c = region.startCol; c <= region.endCol; c++) {
448
+ mergedCells.add(`${r}:${c}`);
449
+ }
450
+ }
451
+ }
452
+ catch (error) {
453
+ console.warn(`Failed to merge cells:`, error);
454
+ }
455
+ });
456
+ ZExcelService._applyAutoFitWidth(sheet, flatColumns);
457
+ }
458
+ const buffer = await workbook.xlsx.writeBuffer();
459
+ return { buffer: buffer, fileName: `${fileName}.xlsx` };
460
+ }
461
+ static async exportFromElementStatic(elementId, fileName = 'export') {
462
+ const workbook = new ExcelJS.Workbook();
463
+ const element = document.getElementById(elementId);
464
+ if (!element) {
465
+ throw new Error(`Element with id "${elementId}" not found`);
466
+ }
467
+ const sheet = workbook.addWorksheet('Sheet1');
468
+ const table = element.querySelector('table') || element;
469
+ if (table.tagName !== 'TABLE') {
470
+ throw new Error('Element must be a table or contain a table');
471
+ }
472
+ ZExcelService._processTableElement(sheet, table);
473
+ ZExcelService._applyAutoFitWidthForTable(sheet);
474
+ const buffer = await workbook.xlsx.writeBuffer();
475
+ return { buffer: buffer, fileName: `${fileName}.xlsx` };
476
+ }
477
+ async _saveFile(result, options) {
478
+ const { addTimestamp = true, showNotification = true } = options;
479
+ let finalFileName = result.fileName;
480
+ if (addTimestamp) {
481
+ const timestamp = ZExcelService._formatTimestamp();
482
+ if (!finalFileName.includes(timestamp.slice(0, 8))) {
483
+ finalFileName = finalFileName.replace('.xlsx', `_${timestamp}.xlsx`);
484
+ }
485
+ }
486
+ const blob = new Blob([result.buffer], {
487
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
488
+ });
489
+ saveAs(blob, finalFileName);
490
+ if (showNotification) {
491
+ options.toast?.success?.(`File "${finalFileName}" has been downloaded`);
492
+ }
493
+ }
494
+ _convertTableColumnsToExcel(config) {
495
+ const { tableColumns, excelOverrides = {}, excludeColumns = [], headerResolver } = config;
496
+ const convertColumn = (col) => {
497
+ if (excludeColumns.includes(col.id)) {
498
+ return null;
499
+ }
500
+ if (['select', 'expand', 'actions'].includes(col.id)) {
501
+ return null;
502
+ }
503
+ const headerConfig = ZExcelService._getHeaderConfig(col);
504
+ let headerText = '';
505
+ headerText = col.id;
506
+ if (headerResolver) {
507
+ headerText = headerResolver(col);
508
+ }
509
+ if (!headerResolver && typeof headerConfig.content === 'string') {
510
+ headerText = headerConfig.content;
511
+ }
512
+ if (!headerResolver && typeof headerConfig.content === 'function') {
513
+ const result = headerConfig.content();
514
+ headerText = typeof result === 'string' ? result : col.id;
515
+ }
516
+ const excelCol = {
517
+ id: col.id,
518
+ header: headerText,
519
+ accessorKey: col.accessorKey,
520
+ accessorFn: col.accessorFn ? (row) => col.accessorFn(row) : undefined,
521
+ width: col.size,
522
+ align: headerConfig.align,
523
+ visible: typeof col.visible === 'boolean' ? col.visible : true,
524
+ };
525
+ const override = excelOverrides[col.id];
526
+ if (override) {
527
+ Object.assign(excelCol, override);
528
+ }
529
+ if (col.columns && col.columns.length > 0) {
530
+ excelCol.columns = col.columns
531
+ .map((childCol) => convertColumn(childCol))
532
+ .filter((c) => c !== null);
533
+ if (excelCol.columns && excelCol.columns.length > 0) {
534
+ excelCol.headerColSpan = ZExcelService._getLeafCount(excelCol.columns);
535
+ }
536
+ }
537
+ return excelCol;
538
+ };
539
+ return tableColumns
540
+ .map((col) => convertColumn(col))
541
+ .filter((c) => c !== null);
542
+ }
543
+ static _flattenColumns(columns) {
544
+ const result = [];
545
+ const flatten = (cols) => {
546
+ for (const col of cols) {
547
+ if (col.visible === false) {
548
+ continue;
549
+ }
550
+ if (col.columns && col.columns.length > 0) {
551
+ flatten(col.columns);
552
+ continue;
553
+ }
554
+ result.push(col);
555
+ }
556
+ };
557
+ flatten(columns);
558
+ return result;
559
+ }
560
+ static _calculateHeaderLevels(columns) {
561
+ const getLevel = (cols, currentLevel = 1) => {
562
+ let maxLevel = currentLevel;
563
+ for (const col of cols) {
564
+ let currentColLevel = currentLevel;
565
+ if (col.headerRowSpan && col.headerRowSpan > 1) {
566
+ currentColLevel = currentLevel + col.headerRowSpan - 1;
567
+ }
568
+ if (col.columns && col.columns.length > 0) {
569
+ if (!col.headerRowSpan || col.headerRowSpan <= 1) {
570
+ const childLevel = getLevel(col.columns, currentLevel + 1);
571
+ currentColLevel = Math.max(currentColLevel, childLevel);
572
+ }
573
+ }
574
+ maxLevel = Math.max(maxLevel, currentColLevel);
575
+ }
576
+ return maxLevel;
577
+ };
578
+ return getLevel(columns);
579
+ }
580
+ static _createHeaderRows(sheet, columns, maxLevels) {
581
+ const headerStructure = [];
582
+ for (let i = 0; i < maxLevels; i++) {
583
+ headerStructure[i] = [];
584
+ }
585
+ ZExcelService._buildHeaderStructure(columns, headerStructure, 0, maxLevels);
586
+ const processedMergeRegions = new Set();
587
+ headerStructure.forEach((row, rowIndex) => {
588
+ const headerRow = sheet.getRow(rowIndex + 1);
589
+ const sortedRow = row.sort((a, b) => (a.startCol || 0) - (b.startCol || 0));
590
+ sortedRow.forEach((headerCell) => {
591
+ if (headerCell.isProcessed || headerCell.isEmpty) {
592
+ return;
593
+ }
594
+ const colIndex = (headerCell.startCol || 0) + 1;
595
+ const cell = headerRow.getCell(colIndex);
596
+ cell.value = headerCell.header;
597
+ if (headerCell.colSpan > 1 || headerCell.rowSpan > 1) {
598
+ const startRow = rowIndex + 1;
599
+ const endRow = startRow + headerCell.rowSpan - 1;
600
+ const startCol = colIndex;
601
+ const endCol = colIndex + headerCell.colSpan - 1;
602
+ const mergeKey = `${startRow}:${startCol}-${endRow}:${endCol}`;
603
+ if (!processedMergeRegions.has(mergeKey)) {
604
+ try {
605
+ sheet.mergeCells(startRow, startCol, endRow, endCol);
606
+ processedMergeRegions.add(mergeKey);
607
+ headerCell.isProcessed = true;
608
+ }
609
+ catch (error) {
610
+ console.warn(`Failed to merge header cells:`, error);
611
+ }
612
+ }
613
+ }
614
+ const defaultColor = rowIndex === 0 ? Z_EXCEL_DEFAULT_CONFIG.headerColors.level0 : Z_EXCEL_DEFAULT_CONFIG.headerColors.level1;
615
+ cell.fill = {
616
+ type: 'pattern',
617
+ pattern: 'solid',
618
+ fgColor: { argb: defaultColor },
619
+ };
620
+ cell.font = Z_EXCEL_DEFAULT_CONFIG.headerFont;
621
+ cell.alignment = { horizontal: 'center', vertical: 'middle' };
622
+ cell.border = Z_EXCEL_BORDER_THIN;
623
+ if (headerCell.formatHeader) {
624
+ headerCell.formatHeader(cell);
625
+ }
626
+ });
627
+ });
628
+ }
629
+ static _buildHeaderStructure(columns, headerStructure, level, maxLevels, startCol = 0) {
630
+ let currentCol = startCol;
631
+ for (const col of columns) {
632
+ if (col.visible === false) {
633
+ continue;
634
+ }
635
+ if (col.columns && col.columns.length > 0) {
636
+ const childrenLeafCount = ZExcelService._getLeafCount(col.columns);
637
+ const colSpan = col.headerColSpan || childrenLeafCount;
638
+ const rowSpan = col.headerRowSpan || 1;
639
+ headerStructure[level].push({
640
+ header: col.header || col.id,
641
+ colSpan,
642
+ rowSpan,
643
+ formatHeader: col.formatHeader,
644
+ startCol: currentCol,
645
+ endCol: currentCol + colSpan - 1,
646
+ });
647
+ if (col.headerRowSpan && col.headerRowSpan > 1) {
648
+ currentCol += colSpan;
649
+ continue;
650
+ }
651
+ ZExcelService._buildHeaderStructure(col.columns, headerStructure, level + 1, maxLevels, currentCol);
652
+ currentCol += colSpan;
653
+ continue;
654
+ }
655
+ const colSpan = col.headerColSpan || 1;
656
+ const rowSpan = col.headerRowSpan || maxLevels - level;
657
+ headerStructure[level].push({
658
+ header: col.header || col.id,
659
+ colSpan,
660
+ rowSpan,
661
+ formatHeader: col.formatHeader,
662
+ startCol: currentCol,
663
+ endCol: currentCol + colSpan - 1,
664
+ });
665
+ currentCol += colSpan;
666
+ }
667
+ return currentCol;
668
+ }
669
+ static _getLeafCount(columns) {
670
+ let count = 0;
671
+ for (const col of columns) {
672
+ if (col.visible === false) {
673
+ continue;
674
+ }
675
+ if (col.columns && col.columns.length > 0) {
676
+ count += ZExcelService._getLeafCount(col.columns);
677
+ continue;
678
+ }
679
+ count++;
680
+ }
681
+ return count;
682
+ }
683
+ static _getCellValue(col, row, rowIndex, data) {
684
+ if (col.accessorFn) {
685
+ return col.accessorFn(row, rowIndex, data);
686
+ }
687
+ if (col.accessorKey) {
688
+ return row[col.accessorKey];
689
+ }
690
+ return '';
691
+ }
692
+ static _processMergeRegions(flatColumns, data, dataStartRow) {
693
+ const mergeRegions = [];
694
+ const dataLength = data.length;
695
+ flatColumns.forEach((colConfig, colIndex) => {
696
+ const colNumber = colIndex + 1;
697
+ if (colConfig.rowSpan || colConfig.colSpan) {
698
+ let currentGroupStart = 0;
699
+ while (currentGroupStart < dataLength) {
700
+ const currentItem = data[currentGroupStart];
701
+ const rowSpan = typeof colConfig.rowSpan === 'function'
702
+ ? colConfig.rowSpan(currentItem, currentGroupStart, data)
703
+ : colConfig.rowSpan || 1;
704
+ const colSpan = typeof colConfig.colSpan === 'function'
705
+ ? colConfig.colSpan(currentItem, currentGroupStart, data)
706
+ : colConfig.colSpan || 1;
707
+ const hasRowSpan = rowSpan > 1;
708
+ const hasColSpan = colSpan > 1;
709
+ if (hasRowSpan || hasColSpan) {
710
+ const startRow = dataStartRow + currentGroupStart;
711
+ const endRow = hasRowSpan ? Math.min(startRow + rowSpan - 1, dataStartRow + dataLength - 1) : startRow;
712
+ const startCol = colNumber;
713
+ const endCol = hasColSpan ? colNumber + colSpan - 1 : colNumber;
714
+ if ((endRow > startRow || endCol > startCol) && endRow < dataStartRow + dataLength) {
715
+ mergeRegions.push({
716
+ startRow,
717
+ startCol,
718
+ endRow,
719
+ endCol,
720
+ firstItemIndex: currentGroupStart,
721
+ });
722
+ }
723
+ }
724
+ currentGroupStart += Math.max(1, rowSpan);
725
+ }
726
+ }
727
+ });
728
+ return mergeRegions;
729
+ }
730
+ static _applyAutoFitWidth(sheet, flatColumns) {
731
+ flatColumns.forEach((col, index) => {
732
+ const colNumber = index + 1;
733
+ const column = sheet.getColumn(colNumber);
734
+ if (col.autoFit && !col.width) {
735
+ let maxWidth = 0;
736
+ sheet.eachRow((row) => {
737
+ const cell = row.getCell(colNumber);
738
+ if (cell.value) {
739
+ const cellWidth = ZExcelService._calculateCellWidth(cell, String(cell.value));
740
+ maxWidth = Math.max(maxWidth, cellWidth);
741
+ }
742
+ });
743
+ const calculatedWidth = Math.max(Z_EXCEL_WIDTH_LIMITS.min, Math.min(Z_EXCEL_WIDTH_LIMITS.max, maxWidth + 1));
744
+ column.width = calculatedWidth;
745
+ }
746
+ });
747
+ }
748
+ static _applyAutoFitWidthForTable(sheet) {
749
+ const { columnCount } = sheet;
750
+ for (let colNumber = 1; colNumber <= columnCount; colNumber++) {
751
+ const column = sheet.getColumn(colNumber);
752
+ let maxWidth = 0;
753
+ sheet.eachRow((row) => {
754
+ const cell = row.getCell(colNumber);
755
+ if (cell.value) {
756
+ const cellWidth = ZExcelService._calculateCellWidth(cell, String(cell.value));
757
+ maxWidth = Math.max(maxWidth, cellWidth);
758
+ }
759
+ });
760
+ const calculatedWidth = Math.max(Z_EXCEL_WIDTH_LIMITS.tableMin, Math.min(Z_EXCEL_WIDTH_LIMITS.tableMax, maxWidth * 0.8 + 2));
761
+ column.width = calculatedWidth;
762
+ }
763
+ }
764
+ static _calculateCellWidth(cell, text) {
765
+ const font = cell.font || {};
766
+ const fontSize = font.size || Z_EXCEL_DEFAULT_CONFIG.font.size;
767
+ const fontFamily = font.name || Z_EXCEL_DEFAULT_CONFIG.font.name;
768
+ const isBold = font.bold || false;
769
+ const isItalic = font.italic || false;
770
+ const fontSizeMultiplier = fontSize / 11;
771
+ const fontMultiplier = Z_EXCEL_FONT_MULTIPLIERS[fontFamily] || 1.0;
772
+ let adjustedWidth = 0;
773
+ for (const char of text) {
774
+ const charWidth = Z_EXCEL_CHAR_WIDTH_MAP[char] || 1.0;
775
+ adjustedWidth += charWidth;
776
+ }
777
+ adjustedWidth *= fontSizeMultiplier * fontMultiplier;
778
+ if (isBold) {
779
+ adjustedWidth *= 1.1;
780
+ }
781
+ if (isItalic) {
782
+ adjustedWidth *= 1.05;
783
+ }
784
+ return Math.ceil(adjustedWidth * 1.2);
785
+ }
786
+ static _processTableElement(sheet, table) {
787
+ const rows = Array.from(table.rows);
788
+ const mergedCells = new Set();
789
+ rows.forEach((row, rowIndex) => {
790
+ const cells = Array.from(row.cells);
791
+ let colOffset = 0;
792
+ cells.forEach((cell, cellIndex) => {
793
+ const computedStyle = window.getComputedStyle(cell);
794
+ if (computedStyle.display === 'none' || computedStyle.visibility === 'hidden') {
795
+ return;
796
+ }
797
+ const rect = cell.getBoundingClientRect();
798
+ if (rect.width === 0 && rect.height === 0) {
799
+ return;
800
+ }
801
+ while (mergedCells.has(`${rowIndex + 1}:${cellIndex + colOffset + 1}`)) {
802
+ colOffset++;
803
+ }
804
+ const excelRow = sheet.getRow(rowIndex + 1);
805
+ const colIndex = cellIndex + colOffset;
806
+ const excelCell = excelRow.getCell(colIndex + 1);
807
+ const cellContent = cell.textContent?.trim() || '';
808
+ excelCell.value = ZExcelService._parseContentValue(cellContent);
809
+ if (!excelCell.font) {
810
+ excelCell.font = Z_EXCEL_DEFAULT_CONFIG.font;
811
+ }
812
+ ZExcelService._applyCellFormatFromHTML(excelCell, cell);
813
+ const rowSpan = parseInt(cell.getAttribute('rowspan') || '1');
814
+ const colSpan = parseInt(cell.getAttribute('colspan') || '1');
815
+ if (rowSpan > 1 || colSpan > 1) {
816
+ const startRow = rowIndex + 1;
817
+ const startCol = colIndex + 1;
818
+ const endRow = startRow + rowSpan - 1;
819
+ const endCol = startCol + colSpan - 1;
820
+ const mergeKey = `${startRow}:${startCol}-${endRow}:${endCol}`;
821
+ if (!mergedCells.has(mergeKey)) {
822
+ sheet.mergeCells(startRow, startCol, endRow, endCol);
823
+ mergedCells.add(mergeKey);
824
+ for (let r = startRow; r <= endRow; r++) {
825
+ for (let c = startCol; c <= endCol; c++) {
826
+ mergedCells.add(`${r}:${c}`);
827
+ }
828
+ }
829
+ }
830
+ }
831
+ });
832
+ });
833
+ }
834
+ static _parseContentValue(content) {
835
+ if (!content || content.trim() === '') {
836
+ return '';
837
+ }
838
+ const trimmedContent = content.trim();
839
+ if (/^-?\d+(\.\d+)?$/.test(trimmedContent)) {
840
+ const parsed = parseFloat(trimmedContent);
841
+ if (!isNaN(parsed) && isFinite(parsed)) {
842
+ return parsed;
843
+ }
844
+ }
845
+ if (/^-?\d+(\.\d+)?%$/.test(trimmedContent)) {
846
+ const numberPart = trimmedContent.replace('%', '');
847
+ const parsed = parseFloat(numberPart);
848
+ if (!isNaN(parsed) && isFinite(parsed)) {
849
+ return parsed / 100;
850
+ }
851
+ }
852
+ return trimmedContent;
853
+ }
854
+ static _applyCellFormatFromHTML(excelCell, htmlCell) {
855
+ const computedStyle = window.getComputedStyle(htmlCell);
856
+ excelCell.font = {
857
+ name: Z_EXCEL_DEFAULT_CONFIG.font.name,
858
+ bold: computedStyle.fontWeight === 'bold' || parseInt(computedStyle.fontWeight) >= 600,
859
+ italic: computedStyle.fontStyle === 'italic',
860
+ size: parseInt(computedStyle.fontSize) || Z_EXCEL_DEFAULT_CONFIG.font.size,
861
+ color: { argb: zConvertColorToArgb(computedStyle.color) },
862
+ };
863
+ if (computedStyle.backgroundColor && computedStyle.backgroundColor !== 'rgba(0, 0, 0, 0)') {
864
+ excelCell.fill = {
865
+ type: 'pattern',
866
+ pattern: 'solid',
867
+ fgColor: { argb: zConvertColorToArgb(computedStyle.backgroundColor) },
868
+ };
869
+ }
870
+ excelCell.alignment = {
871
+ horizontal: ZExcelService._getExcelAlignment(computedStyle.textAlign),
872
+ vertical: ZExcelService._getExcelVerticalAlignment(computedStyle.verticalAlign),
873
+ };
874
+ excelCell.border = Z_EXCEL_BORDER_THIN;
875
+ }
876
+ static _getExcelAlignment(textAlign) {
877
+ switch (textAlign) {
878
+ case 'center':
879
+ return 'center';
880
+ case 'right':
881
+ return 'right';
882
+ case 'left':
883
+ return 'left';
884
+ default:
885
+ return undefined;
886
+ }
887
+ }
888
+ static _getExcelVerticalAlignment(verticalAlign) {
889
+ switch (verticalAlign) {
890
+ case 'middle':
891
+ return 'middle';
892
+ case 'top':
893
+ return 'top';
894
+ case 'bottom':
895
+ return 'bottom';
896
+ default:
897
+ return 'middle';
898
+ }
899
+ }
900
+ static _formatTimestamp() {
901
+ const now = new Date();
902
+ const year = now.getFullYear();
903
+ const month = String(now.getMonth() + 1).padStart(2, '0');
904
+ const day = String(now.getDate()).padStart(2, '0');
905
+ const hours = String(now.getHours()).padStart(2, '0');
906
+ const minutes = String(now.getMinutes()).padStart(2, '0');
907
+ const seconds = String(now.getSeconds()).padStart(2, '0');
908
+ return `${year}${month}${day}_${hours}${minutes}${seconds}`;
909
+ }
910
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZExcelService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
911
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZExcelService, providedIn: 'root' });
912
+ }
913
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZExcelService, decorators: [{
914
+ type: Injectable,
915
+ args: [{
916
+ providedIn: 'root',
917
+ }]
918
+ }] });
919
+
159
920
  const Z_INDEXDB_DEFAULT_CONFIG = {
160
921
  dbName: 'ZDatabase',
161
922
  version: 1,
@@ -1237,5 +1998,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
1237
1998
  * Generated bundle index. Do not edit.
1238
1999
  */
1239
2000
 
1240
- export { ZCacheService, ZHttpAbstractService, ZIndexDbService, ZSubjectService, ZThemeService, ZTranslateService, Z_DARK_MODE_CACHE_KEY, Z_DEFAULT_THEME, Z_THEME_CACHE_KEY, Z_THEME_CONFIG, Z_THEME_CSS_MAP };
2001
+ export { ZCacheService, ZExcelService, ZHttpAbstractService, ZIndexDbService, ZSubjectService, ZThemeService, ZTranslateService, Z_DARK_MODE_CACHE_KEY, Z_DEFAULT_THEME, Z_EXCEL_BORDER_THIN, Z_EXCEL_CHAR_WIDTH_MAP, Z_EXCEL_COLORS, Z_EXCEL_DEFAULT_CONFIG, Z_EXCEL_FONT_MULTIPLIERS, Z_EXCEL_WIDTH_LIMITS, Z_THEME_CACHE_KEY, Z_THEME_CONFIG, Z_THEME_CSS_MAP };
1241
2002
  //# sourceMappingURL=shival99-z-ui-services.mjs.map