From 9b9bf244c12e8b69b04700792a29b7214b9503fa Mon Sep 17 00:00:00 2001 From: Sean Engelhardt Date: Tue, 16 Apr 2019 13:04:10 +0200 Subject: [PATCH] Enhance excel exporting --- client/package.json | 2 +- .../xlsx-export-service.service.ts | 26 +++++++++++- .../services/motion-xlsx-export.service.ts | 41 +++++++++++++++---- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/client/package.json b/client/package.json index 856b02b23..5d05919d5 100644 --- a/client/package.json +++ b/client/package.json @@ -43,7 +43,7 @@ "@tinymce/tinymce-angular": "^3.0.0", "core-js": "^2.6.5", "css-element-queries": "^1.1.1", - "exceljs": "1.8.0", + "exceljs": "1.9.0", "file-saver": "^2.0.1", "hammerjs": "^2.0.8", "material-icon-font": "git+https://github.com/petergng/materialIconFont.git", diff --git a/client/src/app/core/ui-services/xlsx-export-service.service.ts b/client/src/app/core/ui-services/xlsx-export-service.service.ts index 8cb288845..90f77eccb 100644 --- a/client/src/app/core/ui-services/xlsx-export-service.service.ts +++ b/client/src/app/core/ui-services/xlsx-export-service.service.ts @@ -1,8 +1,16 @@ import { Injectable } from '@angular/core'; -import { Worksheet, Workbook } from 'exceljs'; +import { Worksheet, Workbook, Color, FillPatterns } from 'exceljs/dist/exceljs.min.js'; import { saveAs } from 'file-saver'; +// interface required for filling cells (`cell.fill`) +export interface CellFillingDefinition { + type: 'pattern'; + pattern: FillPatterns; + fgColor: Partial; + bgColor: Partial; +} + @Injectable({ providedIn: 'root' }) @@ -78,4 +86,20 @@ export class XlsxExportServiceService { } } } + + /** + * Tries to calculate a fitting row hight for a given text + * + * @param title The text to analyse + * @param columnWidth the width of the column to fit the text in + */ + public calcRowHeight(title: string, columnWidth: number): number { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + ctx.font = '14pt Arial'; + const metricsWidth = Math.floor(ctx.measureText(title).width); + const factor = Math.ceil(metricsWidth / (columnWidth * 10)); + // add 1 for correction + return factor + 1; + } } diff --git a/client/src/app/site/motions/services/motion-xlsx-export.service.ts b/client/src/app/site/motions/services/motion-xlsx-export.service.ts index d99759d90..f25c509fd 100644 --- a/client/src/app/site/motions/services/motion-xlsx-export.service.ts +++ b/client/src/app/site/motions/services/motion-xlsx-export.service.ts @@ -1,12 +1,12 @@ import { Injectable } from '@angular/core'; -import { Workbook } from 'exceljs'; +import { Workbook } from 'exceljs/dist/exceljs.min.js'; import { InfoToExport } from './motion-pdf.service'; import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service'; import { TranslateService } from '@ngx-translate/core'; import { ViewMotion } from '../models/view-motion'; -import { XlsxExportServiceService } from 'app/core/ui-services/xlsx-export-service.service'; +import { XlsxExportServiceService, CellFillingDefinition } from 'app/core/ui-services/xlsx-export-service.service'; /** * Service to export motion elements to XLSX @@ -15,6 +15,20 @@ import { XlsxExportServiceService } from 'app/core/ui-services/xlsx-export-servi providedIn: 'root' }) export class MotionXlsxExportService { + /** + * Defines the head row style + */ + private headRowFilling: CellFillingDefinition = { + type: 'pattern', + pattern: 'solid', + fgColor: { + argb: 'FFFFE699' + }, + bgColor: { + argb: 'FFFFE699' + } + }; + /** * Constructor * @@ -37,8 +51,17 @@ export class MotionXlsxExportService { */ public exportMotionList(motions: ViewMotion[], infoToExport: InfoToExport[]): void { const workbook = new Workbook(); - const worksheet = workbook.addWorksheet(this.translate.instant('Motions')); const properties = ['identifier', 'title'].concat(infoToExport); + const worksheet = workbook.addWorksheet(this.translate.instant('Motions'), { + pageSetup: { + paperSize: 9, + orientation: 'portrait', + fitToPage: true, + fitToHeight: 5, + fitToWidth: properties.length, + printTitlesRow: '1:1' + } + }); // if the ID was exported as well, shift it to the first position if (properties[properties.length - 1] === 'id') { @@ -51,11 +74,13 @@ export class MotionXlsxExportService { }; }); - // style the header row - worksheet.getRow(1).font = { - underline: true, - bold: true - }; + worksheet.getRow(1).eachCell(cell => { + cell.font = { + underline: true, + bold: true + }; + cell.fill = this.headRowFilling; + }); // map motion data to properties const motionData = motions.map(motion =>