NodeJS 使用数组和对象的PDFMake动态数据

vshtjzan  于 2023-04-11  发布在  Node.js
关注(0)|答案(3)|浏览(103)

所以我对PDFMake非常陌生,我正在寻找一种使用从DB返回的数据动态创建表的方法。我正在努力让数据显示出来,我不确定我应该如何在我的代码中渲染表数据。请参阅下面的代码,以及我如何尝试显示数据:

dummyServiceData = [
    { serviceType: "More", service: "Company Profile", quantity: 1, price: 250, discount: 0, total: 250 },
    { serviceType: "SARS", service: "Free Expert Accounting, Tax and/or Payroll Consultation (Optional) (Valued at R200)", quantity: 1, price: 0, discount: 0, total: 0 },
    { serviceType: "More", service: "Free Official BEE Affidavit (Optional) (Valued @ R200)", quantity: 1, price: 0, discount: 0, total: 0 },
    { serviceType: "More", service: "Free Tenders-4-Me App (5 Top Tenders for You) (Optional)", quantity: 1, price: 0, discount: 0, total: 0 },
    { serviceType: "SARS", service: "Free Invoice App (Optional)", quantity: 1, price: 0, discount: 0, total: 0 },
    { serviceType: "More", service: "Company Profile", quantity: 1, price: 650, discount: 0, total: 650 },
    { serviceType: "SARS", service: "Free Expert Accounting, Tax and/or Payroll Consultation (Optional) (Valued at R200)", quantity: 1, price: 0, discount: 0, total: 0 },
    { serviceType: "More", service: "Free Official BEE Affidavit (Optional) (Valued @ R200)", quantity: 1, price: 0, discount: 0, total: 0 },
    { serviceType: "More", service: "Free Tenders-4-Me App (5 Top Tenders for You) (Optional)", quantity: 1, price: 0, discount: 0, total: 0 },
    { serviceType: "SARS", service: "Free Invoice App (Optional)", quantity: 1, price: 0, discount: 0, total: 0 },
];
let dummyUser = { firstName: "John", lastName: "Doe", userCode: "JOHN1234", emailPrime: "john@gmail.com", numberPrime: "0798947345", vatNumber: "123456789" };

// [left, top, right, bottom] or [horizontal, vertical] or just a number for equal margins
let docDefinition = {
    pageMargins: [20, 20, 20, 40],
    styles: {
        smoll: {
            fontSize: 7,
            margin: [0, 0, 0, 0],
        },
    },
    footer: (currentPage, pageCount, pageSize) => {
        return {
            columns: [
                {
                    stack: [
                        { text: "www.companypartners.co.za", link: "www.companypartners.co.za", alignment: "center", fontSize: 9, margin: [0, 0, 0, 5] },
                        { text: "Page " + currentPage.toString() + " of " + pageCount, alignment: "center", color: "#7f7f7f", fontSize: 8 },
                    ],
                    margin: [20, 0],
                },
            ],
        };
    },
    content: [
        {
            columns: [
                {
                    margin: [10, 25, 0, 0],
                    ol: [{ height: 50, width: 200, image: logo }],
                },
                {
                    type: "none",
                    fontSize: 6,
                    margin: [50, 25, 0, 0],
                    ol: [
                        {
                            text: "Company",
                            bold: true,
                        },
                        "Reg. No: 2011/123456/01",
                        "VAT No: 4123456789",
                        "Email: accounts@company.com",
                        "Web: www.company.com",
                    ],
                },
                {
                    type: "none",
                    fontSize: 6,
                    margin: [0, 25, 0, 0],
                    ol: [
                        {
                            text: "ADDRES",
                            bold: true,
                        },
                        "Office 25B",
                        "Willowbrook Office Park",
                        "Van Hoof Street",
                        "Willowbrook, Roodepoort",
                        "1731",
                    ],
                },
            ],
        },
        { canvas: [{ type: "line", x1: 0, y1: 25, x2: 515, y2: 25, lineWidth: 3, color: "#D7DBDD" }] },
        {
            columns: [
                {
                    stack: [
                        { text: "CUSTOMER INFORMATION", bold: true, fontSize: 9 },
                        { text: dummyUser.firstName + " " + dummyUser.lastName, fontSize: 8 },
                        { text: "Code:" + " " + dummyUser.userCode, fontSize: 8 },
                        { text: "VAT No:" + " " + dummyUser.vatNumber, fontSize: 8 },
                        { text: "Tel:" + " " + dummyUser.numberPrime, fontSize: 8 },
                        { text: "Email:" + " " + dummyUser.emailPrime, fontSize: 8 },
                    ],
                    margin: [10, 20, 0, 0],
                    width: 150,
                },
                {
                    type: "none",
                    fontSize: 8,
                    margin: [0, 20, 0, 0],
                    width: 150,
                    ol: [
                        {
                            text: "CUSTOMER ADDRESS",
                            bold: true,
                            fontSize: 9,
                        },
                        "13 Wildeklawer",
                        "Welgevonden Estate",
                        "Stellenbosch",
                        "7600",
                    ],
                },
                {
                    type: "none",
                    fontSize: 8,
                    margin: [0, 15, 5, 0],
                    ol: [
                        {
                            text: "QUOTATION",
                            bold: true,
                            fontSize: 18,
                            alignment: "right",
                        },
                        {
                            style: "tableExample",
                            table: {
                                widths: [80, "*", "*", "*"],
                                heights: [15, 15, 15, 15],
                                body: [
                                    [
                                        { text: "QUOTATION NO", fontSize: 8 },
                                        { text: "CREATED", fontSize: 8 },
                                        { text: "DUE DATE", fontSize: 8 },
                                        { text: "TOTAL", fontSize: 8 },
                                    ],
                                    ["PRF1234", "31/03/2022", "31/03/2022", "R690.00"],
                                ],
                            },
                            layout: {
                                fillColor: function (rowIndex, node, columnIndex) {
                                    return rowIndex % 2 === 0 ? "#CCCCCC" : null;
                                },
                            },
                        },
                    ],
                },
            ],
        },
        { canvas: [{ type: "line", x1: 0, y1: 25, x2: 515, y2: 25, lineWidth: 3, color: "#D7DBDD" }] },

        {
            table: {
                headerRows: 1,
                widths: ["auto", "auto", "auto", "auto", "auto", "auto", "auto"],
                body: [
                    [
                        { text: "Service Type", style: "tableHeader" },
                        { text: "Service Item", style: "tableHeader" },
                        { text: "Qty", style: "tableHeader" },
                        { text: "Unit Price(VAT Incl)", style: "tableHeader" },
                        { text: "Discount", style: "tableHeader" },
                        { text: "Tax", style: "tableHeader" },
                        { text: "Total(VAT Incl)", style: "tableHeader" },
                    ],
                    dummyServiceData.map((data) => [data.serviceType, data.service, data.quantity.toString(), data.price.toString(), data.discount.toString(), data.total.toString()]),
                ],
            },
        },
    ],
    styles: {
        header: {
            fontSize: 18,
            bold: true,
            margin: [0, 0, 0, 10],
        },
        subheader: {
            fontSize: 16,
            bold: true,
            margin: [0, 10, 0, 5],
        },
        tableExample: {
            margin: [0, 5, 0, 15],
        },
        tableHeader: {
            bold: true,
            fontSize: 8,
            color: "white",
            fillColor: "black",
        },
    },
    defaultStyle: {
        // alignment: 'justify'
    },
};

使用dummydata,我试图Map它,但我得到一个错误,说明 Cannot read properties of undefined(阅读'_calcWidth') 现在我明白了,我已经正确设置了列数(7),但我没有赢。有人能帮助我说明我在这里做错了什么吗?
先谢谢你了。
以下是完成后的表格外观:

qyuhtwio

qyuhtwio1#

问题是它将整个dummyServiceData作为一行。我也遇到了类似的问题,然后我这样做了:

const bodyData: any[] = [];

       // Here change bodyColumns to your column array
       bodyData.push(bodyColumns);

       // Here change bodyRowsData to your dummyServiceData array And then assign this body to your table body, do mapping or what ever other thing you want on dummyServiceData  before it 
       const body = bodyData.concat(bodyRowsData);
o8x7eapl

o8x7eapl2#

我是通过以下方式弄明白的:

function setColumns(data) {
    let tableData = [];
    for (const d of data) {
        tableData.push([
            { text: d.serviceType },
            { text: d.service },
            { text: d.quantity },
            { text: "R " + d.price.toFixed(2) },
            { text: "R " + d.discount.toFixed(2) },
            { text: 0 },
            { text: "R " + d.total.toFixed(2) },
        ]);
    }
    return tableData;
}

let columns = setColumns(dummyServiceData);

然后你就把这个阵列炸了

{
            style: "defaultTable",
            table: {
                headerRows: 1,
                widths: [55, 180, "*", 75, 45, "*", 70],
                heights: 30,

                body: [
                    [
                        { text: "Service Type", style: "tableHeader" },
                        { text: "Service Item", style: "tableHeader" },
                        { text: "Qty", style: "tableHeader" },
                        { text: "Unit Price(VAT Incl)", style: "tableHeader" },
                        { text: "Discount", style: "tableHeader" },
                        { text: "Tax", style: "tableHeader" },
                        { text: "Total(VAT Incl)", style: "tableHeader" },
                    ],

                    ...columns,
                ],
            },
            layout: "lightHorizontalLines",
        },
gopyfrb3

gopyfrb33#

使用@Niishaw答案,我做了类似的事情来从数组中动态创建一个Table:

var aKeys = Object.keys(dummyServiceData[0]);
var transformedData = dummyServiceData.map(
    function(icurrentValue) {
        return Object.values(icurrentValue);
        }
);
transformedData.unshift(aKeys);

或者你可以添加一些样式:

var transformedData = dummyServiceData.map(
    function(icurrentValue) {
        return Object.values(icurrentValue).map(
            function(jcurrentValue, jindex) {
                    return {text: icurrentValue[aKeys[jindex]], style:'tableText1'}
                        });
                
        }
);

在内容上:

table: {
                headerRows: 1,
                heights: 18,
                body: [
                  ...transformedData,
                ],
            },

相关问题