reingart / pyfpdf

Simple PDF generation for Python (FPDF PHP port)
https://code.google.com/p/pyfpdf/
GNU Lesser General Public License v3.0
857 stars 526 forks source link

draw on the previous page #30

Closed ghost closed 9 years ago

ghost commented 9 years ago

I need to draw a document with two column. The problem is that the content of both column are independent of each other. So the perfect scenario is the possibility to draw all the first column content, and the get back to the top of first page and draw the other column, because the the two columns have "dynamic" heights: some time the column 1 need 3 pages and column 2 just one.

I've searched over the API and didn't found a function to select the page we want to draw on, but there is anyway to that with the other functions available? (I could not understand would be possible)

thanks

RomanKharin commented 9 years ago

Ramon, there 2 scenarios: 1. use html (also this seems to be required fix layout rendering). 2. Write custom layout render.

ghost commented 9 years ago

Yeah. I've written a custom layout render to achieve it. The trick is to manipulate the self.page attribute and re-written the accept_page_break function.

To get back to the first page just set the self.page to 1 self.page = 1. So now there will be a trick issue here because the library will work normal thinking you just started the document from scratch this means that when you reach the page limit you will get a new page which is blank. So all your previous work just gone to space. To avoid that you need to control it's time to really add a new page or just adjust (again) the self.page to the next page.

Since my issue was to create a two columns document i created an boolean control variable to know when i'm building column 1 or 2.

class BaseFPDF(FPDF, HTMLMixin):

    def __init__(self):
        super(BaseFPDF, self).__init__()
        self.draw_column1 = False # control var.

The second part is that the we need to know how many pages the process of building colum 2 have created so our custom function accept_page_break can work.

class BaseFPDF(FPDF, HTMLMixin):

    def __init__(self):
        super(BaseFPDF, self).__init__()
        self.draw_column1 = False # control var.
        self.pages_created_for_column2 = 0 #

Now we play with the self.page variable to know when it's time for a new blank page!

class BaseFPDF(FPDF, HTMLMixin):

    def __init__(self):
        super(BaseFPDF, self).__init__()
        self.draw_column1 = False # control var.
        self.pages_created_for_column2 = 0 #

    def accept_page_break(self):
        if self.draw_column1 :
            if self.page < self.pages_created_for_column2 :

                self.page += 1

                return False

            else :

                return True

        else :
            self.pages_created_for_column2 += 1 # we are working on column 2
            return True

First i will draw all the column 2 content (which requires to readjust the x position much more than column 1), then go back to first page and flag that i'am done building column 1.

class BaseFPDF(FPDF, HTMLMixin):

    def __init__(self):
        super(BaseFPDF, self).__init__()
        self.draw_column1 = False # control var.
        self.pages_created_for_column2 = 0 #

    def accept_page_break(self):
        if self.draw_column1 :
            if self.page < self.pages_created_for_column2 :

                self.page += 1 # we reached the limit of the actual page but we already have another page to draw on

                return False

            else :

                return True

        else :
            self.pages_created_for_column2 += 1 # we are working on column 2
            return True
    def draw_column2(self, content):
        (...)
        self.page = 1
        self.draw_column1 = True
    def draw_column1(self, content):
        (...)

Finally

pdf = BasePDF()
pdf.draw_column2()
pdf.draw_column1()
RomanKharin commented 9 years ago

Ramon. This can be used example?

ghost commented 9 years ago

Yeah, why not? :)