PDFMake库-如何在表中设置自动生成的列的默认宽度值

时间:2019-02-13 10:44:37

标签: css angular typescript pdf pdf-generation

我对使用称为PDFmake的库生成的PDF表中的列有问题。有时我有很多列,所以我想将列宽更改为当前已自动设置为文本长度的静态值,但是我不能这样做-我在代码中所做的每一次宽度更改都是错误的,并且没有不能改变任何观点。

这是pdf-generator.ts文件:

declare var $;
declare var canvg;
declare var pdfMake;

/**
* This JS module provides PDF generating functionality.
*/
export class PdfGenerator {
private logger = new LoggerService('PdfGenerator');
scripts: any = {
    '1': [
        new Script('js/pdfmake/pdfmake.min.js')
    ],
    '2': [
        new Script('js/pdfmake/pdfmake.fonts.js')
    ]
};

constructor(private filters: FilterService, private scriptService: ScriptService) {

}

isInternetExplorer = this.isIE();

/**
 * This function generates the PDF and saves it on user's disk.
 */
generatePDF(svg, database: Database, connectionState: EntityState<Connection>, statisticState: EntityState<StatisticData>, systemState: EntityState<System>, filteredData: FilteredData, tableColumns) {
    Overlay.showOverlay();
    from(this.scriptService.load(this.scripts['1']))
        .pipe(
            flatMap(response => from(this.scriptService.load(this.scripts['2']))),
            tap(response => {
                this.generatePDFDefinition(svg, database, connectionState, statisticState, systemState, filteredData, tableColumns, (pdfDefinition) => {
                    pdfMake.createPdf(pdfDefinition).download('Interface Scan.pdf');
                    Overlay.hideOverlay();
                });
            })
        ).subscribe();
}

/**
 * This function processes current diagram SVG into a PNG in a form of a data URI.
 * @param callback A function to invoke after processing the SVG. The first and the only argument is the PNG data URI.
 */
getDiagramAsPNG(svg, callback) {
    const canv = this.isInternetExplorer ? canvg : undefined;
    saveSvgAsPng.svgAsPngUri(document.getElementById('svg4'), {
        height: svg.height(),
        width: svg.width(),
        /*
        * This property is image quality - the higher the better.
        * Be careful, as better images weigh a lot more.
        * If CanvG is used, then use scale of 1,
        * because CanvG misunderstands this property and changes image proportions. Use 2 otherwise.
        */
        scale: canv ? 1 : 2,
        encoderOptions: 1,
        //CanvG only if IE
        canvg: canv
    }, callback);
}

/**
 * This function generates a PDF definition for PDFMake.
 * @param svg
 * @param database
 * @param callback A function to invoke after processing the SVG. The first and the only argument is the PDF definition.
 */
generatePDFDefinition(svg, database:Database, connectionState: EntityState<Connection>, statisticState: EntityState<StatisticData>, systemState: EntityState<System>, filteredData: FilteredData, tableColumns, callback) {
    //Create base PDF definition
    const pdf: any = {
        pageSize: 'A4',
        pageOrientation: 'landscape',
        pageMargins: 0,
        content: [],
        styles: {},
        /*
        * Properties below are not configuration properties.
        * They are put here to always have a reference with this PDF definition.
        */
        pageWidth: 841.89, //Taken from PDFMake source
        pageHeight: 595.28 //Taken from PDFMake source
    };

    //Set header and footer

    this.getDiagramAsPNG(svg, (diagramPngUri) => {
        //Set the diagram page definition
        diagram(svg, diagramPngUri);
        //Set the details table page definition
        detailsTable();

        //Invoke the callback function
        callback(pdf);
    });

    /**
     * This function sets the header definition.
     */
    let header = () => {
        /**
         * This function formats given date as a string.
         * @param date A date to format.
         * @param withTime Whether the result string should contain time or not.
         * @returns {string} A formatted date.
         */
        let formatDate = (date, withTime = null) => {
            //Make sure it is a date object
            date = new Date(date);

            //Get formatted date string
            const year = date.getFullYear();
            const month = date.getMonth() < 9 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1);
            const day = date.getDate();
            const dateString = [year, month, day].join('/');

            if (withTime) {
                //Get formatted time string
                const hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
                const minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
                const seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
                const timeString = [hours, minutes, seconds].join(':');

                //Return both strings joined with a space
                return [dateString, timeString].join(' ');
            } else {
                //Return only the date part
                return dateString;
            }
        };

        //Get current scan metadata
        // const scan = this.ifs.selectedIfsScan();

        //Create a style for the header
        pdf.styles.header = {
            fontSize: 10,
            margin: [20, 20, 20, 0]
        };

        //Add header to the PDF
        pdf.header = {
            columns: [
                {
                    text: 'Database \'' + database.name + '\'' ,
                    // text: 'Scan \'' + database.name + '\' from ' + formatDate(database.lastUpdate),
                    style: 'header'
                },
                {
                    text: 'Generated on ' + formatDate(Date.now(), true),
                    alignment: 'right',
                    style: 'header'
                }
            ]
        };
    };

    /**
     * This function sets the footer definition.
     */
    let footer = () => {
        //Create a style for the footer
        pdf.styles.footer = {
            fontSize: 10,
            margin: [20, 10, 20, 0]
        };

        /*
        * Add footer to the PDF.
        * It displays current page text in the bottom left corner, i.e.: "1 of 29".
        */
        pdf.footer = (currentPage, pageCount) => {
            return {
                text: currentPage + ' of ' + pageCount,
                style: 'footer'
            };
        };
    };


    /**
     * This function adds a page with a diagram image to the PDF.
     * @param diagramPngUri A diagram in a form of a PNG data URI.
     */
    let diagram = (svg, diagramPngUri) => {
        /*
        * Compute image dimensions
        */
        const diagramImageHeight = pdf.pageHeight;
        const diagramImageWidth = svg.width() / svg.height() * pdf.pageHeight;

        /*
        * Add an image to the PDF.
        * The image has no margins and fills the whole page.
        * It fills page height and is centered horizontally.
        * The horizontal overflow is hidden - the image is not stretched.
        * The image should look nearly exactly as on the website.
        */
        pdf.content.push({
            image: diagramPngUri,
            //Vertically: align to top, Horizontally: center.
            absolutePosition: {
                x: (pdf.pageWidth - diagramImageWidth) / 2,
                y: (pdf.pageHeight - diagramImageHeight) / 2
            },
            //Fill page height, scale width
            height: diagramImageHeight,
            width: diagramImageWidth
        });
    };

    /**
     * This function adds a page with a details table to the PDF.
     * If the details table is too long to be fit in one page,
     * the rows that don't fill will be on the next page.
     */
    let detailsTable = () => {
        //Add needed styles to the PDF
        pdf.styles.detailsTable = {
            fontSize: 4,
        };
        pdf.styles.detailsTableHeader = {
            bold: true,
            fillColor: '#1abd9c',
            color: '#ffffff'
        };

        const columnDefinitions = () => {
            let columns = [];
            tableColumns.columns.forEach(tableColumn => {
                if(tableColumn.visible) {
                    columns.push({
                        text: tableColumn.name,
                        style: 'detailsTableHeader',
                        border: noBorders
                    })
                }
            });
            return columns;
        };

        /*
        * Create details table definition.
        * Details table is wrapped in 'columns' to center it, as 'alignment' does not work.
        * Do not remove '{width: "*", text: ""}' blocks, as they allow this trick to work.
        */
        const noBorders = [false, false, false, false];
        let pdfDetailsTable: any = {
            columns: [
                {width: '*', text: ''},
                {
                    width: 'auto',
                    style: 'detailsTable',
                    table: {
                        headerRows: 1,
                        width: new Array(tableColumns.columns.filter(column => column.visible).length).fill('auto'),
                        body: new Array(columnDefinitions())
                    },
                    layout: {
                        hLineColor: '#d2d2d2',
                        vLineColor: '#d2d2d2',
                        hLineWidth: () => {
                            return 0.5;
                        },
                        vLineWidth: () => {
                            return 0.5;
                        }
                    },
                    pageBreak: 'before'
                },
                {width: '*', text: ''}
            ]
        };

        /*
        * Fill the details table with proper content.
        * The data is fetched directly from the details table on the website,
        * so all filters, sorting and value formatting will be the same in PDF.
        */
        const noTopBorder = [true, false, true, true];
        const body = pdfDetailsTable.columns[1].table.body;

        const getSystemFieldValue = (field, connection: Connection) => {
            const system = connection[field.indexOf('sender') !== -1 ? 'sender' : 'receiver']
            if(systemState.entities[system]) {
                return systemState.entities[system][field.replace(/sender|receiver/gi, 'system')];
            }
            return '';
        };

        const getColumnValue = (id, column) => {
            const statisticData: StatisticData = statisticState.entities[id];
            const connection: Connection = connectionState.entities[statisticData.uniqueId];

            if(statisticData[column.key] !== undefined) return statisticData[column.key];
            else if(column.type === 'system') return getSystemFieldValue(column.key, connection);
            else return connection[column.key];
        };

        for(const id of filteredData.StatisticsByConnections) {
            let row = [];
            tableColumns.columns.forEach(column => {
                if(column.visible) {
                    row.push({
                        text: getColumnValue(id, column),
                        border: noTopBorder
                    })
                }
            });
            body.push(row);
        }

        //Push the definition to the PDF
        pdf.content.push(pdfDetailsTable);
    };


    header();
    footer();
}

isIE() {
    const userAgent = window.navigator.userAgent;

    const msie = userAgent.indexOf('MSIE ');
    if (msie > 0) {
        this.logger.debug('isIE', 'Browser: \'IE10\'!');
        //IE 10 or older => return version number
        return parseInt(userAgent.substring(msie + 5, userAgent.indexOf('.', msie)), 10);
    }

    const trident = userAgent.indexOf('Trident/');
    if (trident > 0) {
        this.logger.debug('isIE', 'Browser: \'IE11\'!');
        //IE 11 => return version number
        let rv = userAgent.indexOf('rv:');
        return parseInt(userAgent.substring(rv + 3, userAgent.indexOf('.', rv)), 10);
    }

    const edge = userAgent.indexOf('Edge/');
    if (edge > 0) {
        // Logger.debug("Browser: 'Edge'!");
        //Edge (IE 12+) => return version number
        return parseInt(userAgent.substring(edge + 5, userAgent.indexOf('.', edge)), 10);
    }

    // Logger.debug("Browser not IE/Edge.");
    //Other browser
    return false;
}

}

在pdfDetailsTable中,我已将表格中的宽度更改为100,但不会更改,也为以下内容添加了宽度:

tableColumns.columns.forEach(column => {
                if(column.visible) {
                    row.push({
  => HERE WIDTH: 100,
                        text: getColumnValue(id, column),
                        border: noTopBorder
                    })
                }
            });

但这也没有帮助我。有人可以知道我在做什么,因为该属性仍设置为auto吗?

0 个答案:

没有答案