question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Problem with loop over new page

See original GitHub issue

Bug Report

When adding text in a loop which is creating an overflow (new page) the text is not placed correctly on the new pages and will create an new page for every doc.text() function

Description of the problem

I add some details on a page using an async loop. Every iteration use the same doc.y height. At the end of the iteration I will move down and use the new y position. That’s works correctly until the end the page. Pdfkit is automatically creating a new page which is great, but is repeating that for every single time that doc.text() is called for a few times. Then, the rest of the text is printed correctly at the last page. You can see it on the attached PDF file with dummy data,

Code sample

var pdf = new PDFDocument({
                size: doc.size,
                layout: 'landscape',
                margins: {
                    top: 50,
                    bottom: 50,
                    left: 50,
                    right: 50
                }
            })

            pdf.info['Author'] = 'Author';
            pdf.info['Title'] = 'Purchase Order';
            pdf.lineWidth(0.5);

            pdf.fontSize(20);
            pdf.font('Helvetica-Bold');
            pdf.text('Purchase Order', doc.margins.left, doc.margins.top);
            pdf.font('Helvetica');

            pdf.moveDown(1);
            pdf.fontSize(10);

            pdf.text('Supplier: ' + purchaseOrder.company.name);
            pdf.moveUp(1);
            pdf.text('Status: ' + purchaseOrder.status[purchaseOrder.status.length - 1].status, doc.margins.right, pdf.y, { align: 'right' });

            pdf.moveDown(2);
            pdf.text('Delivery Address:');
            pdf.text('Foo Lane 23');
            pdf.text('1234AB Foo city');
            pdf.text('Netherlands');

            pdf.moveDown(2);
            var pageWidth = pdf.page.width - doc.margins.right - doc.margins.left;

            var numberWidth = Math.round(((12 / 100) * pageWidth) * 100 / 100);
            var nameWidth = Math.round(((40 / 100) * pageWidth) * 100 / 100);
            var amountWidth = Math.round(((12 / 100) * pageWidth) * 100 / 100);
            var receivedWidth = Math.round(((12 / 100) * pageWidth) * 100 / 100);
            var priceWidth = Math.round(((12 / 100) * pageWidth) * 100 / 100);
            var stockWidth = Math.round(((12 / 100) * pageWidth) * 100 / 100);

            pdf.font('Helvetica-Bold');
            pdf.text('Products');
            pdf.font('Helvetica');
            var y = pdf.y;
            pdf.text('Number', doc.margins.left, y, { width: numberWidth, height: 60 })
            pdf.text('Article name', doc.margins.left + numberWidth, y, { width: nameWidth, height: 60 })
            pdf.text('Amount', doc.margins.left + numberWidth + nameWidth, y, { width: amountWidth, height: 60 })
            pdf.text('Received', doc.margins.left + numberWidth + nameWidth + amountWidth, y, { width: receivedWidth, height: 60 });
            pdf.text('Retail price', doc.margins.left + numberWidth + nameWidth + amountWidth + receivedWidth, y, { width: priceWidth, height: 60 })
            pdf.text('In stock', doc.margins.left + numberWidth + nameWidth + amountWidth + receivedWidth + priceWidth, y, { width: stockWidth, height: 60 });
            pdf.moveDown(0.8)
            pdf.lineCap("butt").moveTo(doc.margins.left, pdf.y).lineTo(pdf.page.width - doc.margins.right, pdf.y).stroke();
            pdf.moveDown(0.5)
            var y = pdf.y;
            var totalAmount = 0, totalReceived = 0, totalPrice = 0, totalStock = 0;
            async.forEachOf(purchaseOrder.items, function (item, key, itemsDone) {

                var text = item.product_id ? item.product_id.variants[0].productNumber : item.number ? item.number : '';
                pdf.text(text, doc.margins.left, y, { width: numberWidth});
                pdf.text(item.name, doc.margins.left + numberWidth, y, { width: nameWidth});
                pdf.text(item.price, doc.margins.left + numberWidth + nameWidth, y, { width: amountWidth,});
                pdf.text(item.receivedQuantity, doc.margins.left + numberWidth + nameWidth + amountWidth, y, { width: receivedWidth});
                pdf.text(item.price, doc.margins.left + numberWidth + nameWidth + amountWidth + receivedWidth, y, { width: priceWidth});
                pdf.text(item.stock, doc.margins.left + numberWidth + nameWidth + amountWidth + receivedWidth + priceWidth, y, { width: stockWidth});

                totalAmount += parseFloat(item.price);
                totalReceived += parseInt(item.receivedQuantity);
                totalPrice += parseFloat(item.price);
                totalStock += parseInt(item.stock);

                pdf.moveDown();
                y = pdf.y;
                itemsDone();

            }, function () {
                pdf.moveUp(0.5);
                pdf.lineCap("butt").moveTo(doc.margins.left, pdf.y).lineTo(pdf.page.width - doc.margins.right, pdf.y).stroke();
                pdf.moveDown(0.5);
                var y = pdf.y;
                pdf.text("Total", doc.margins.left + numberWidth, y, { width: nameWidth});
                pdf.text(totalAmount, doc.margins.left + numberWidth + nameWidth, y, { width: amountWidth});
                pdf.text(totalReceived, doc.margins.left + numberWidth + nameWidth + amountWidth, y, { width: receivedWidth });
                pdf.text(totalPrice, doc.margins.left + numberWidth + nameWidth + amountWidth + receivedWidth, y, { width: priceWidth});
                pdf.text(totalStock, doc.margins.left + numberWidth + nameWidth + amountWidth + receivedWidth + priceWidth, y, { width: stockWidth});

                pdf.end();
                 pdf.pipe(res);
            })

purchaseorder_20191-1(16).pdf

Your environment

  • pdfkit version: 0.9.0
  • Node version: 8.11.3
  • Operating System: Windows 10

Issue Analytics

  • State:open
  • Created 5 years ago
  • Comments:10 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
nonowdcommented, Mar 19, 2020

Hey I just found something which work for me:

You need to keep the track of you current Y position In my case, if more than 680, I create a new page and reset the Y position to 50.

if (this.itemPositionY > 680) {
        doc.addPage();
        this.itemPositionY = 50;
      }
1reaction
Flo0806commented, Jul 29, 2020

Hi all, the problem is the async foreach. The moveDown is not syncing the doc.y every call. My way is make the “complete” PDF generation procedure in a async void/Promise.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Opening the page fails in for loop when called more than 1 time
page.open() is an asynchronous function. If you call it in a loop, then it the loop will be fully executed before even the...
Read more >
Problem: Loop for each Tab in Web page does not Sa...
I start a new flow → launched new iteration of chrome browser with web page → extracted data from web page as the...
Read more >
Smartform - Loop and newpage issue - SAP Community
Passing my inertnal table to smartfom, inside smart form I am looping on this internal table. But the form is only showing one...
Read more >
JavaScript For Loop Click Event ← Issues & Solutions Explained
When you attach multiple click events inside a for loop in JavaScript, It always gives the last index regardless of what button is...
Read more >
Looping code - Learn web development | MDN
Here we'll look at the loop structures available in JavaScript that ... each one of which draws a circle in a random position...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found