[reportlab-users] RE: page x of y using DocTemplate

Henning von Bargen reportlab-users@reportlab.com
Mon, 13 May 2002 09:05:29 +0200


Another option is to generate a helper file
containing tag-names and the corresponding page number.
This is similar to what LaTeX does.

I tried this out for a little example and it worked for me.

Henning

Note:
I'm sure this is spaghetti code,
but it was one of my first python programs...
I also use my own version of the Table class, 
where I tested some variants for splitting the table at page breaks.

...
...	
...    
def writeDoc(name, elem):
    global numPages
    doc = SimpleDocTemplate(name,showBoundary='showboundary' in sys.argv)
    doc.allowSplitting = not 'nosplitting' in sys.argv
    doc.pagesize = A4
    doc.leftMargin = 2*cm
    doc.rightMargin = 2*cm
    doc.topMargin = 3*cm
    doc.bottomMargin = 3*cm
    doc.title = Title
    doc.author = Author
    doc.build(elem,myFirstPage,myLaterPages)
    return doc.page

def run():
    global aW,aH, numPages
    
    fn = 'beispiel.txt'

    # Datei zeilenweise einlesen und Text ausgeben.
    data = open(fn,'r').readlines()
    
    for durchlauf in range(30):
      print "Durchlauf %d" % (durchlauf)
      Elements.append (Paragraph ("Durchlauf %d" % durchlauf, H2Style))
      
      for line in data:
           p(line)

      mytab( Paragraph ("Kopfzeile %d" % durchlauf, KopfStyle),
             [Paragraph ("Zeile 1", DatenStyle), 
              Paragraph ("Zeile 2", DatenStyle),
              Paragraph ("Zeile 3", DatenStyle),
              Paragraph ("Zeile 4", DatenStyle),
              Tabelle ( Paragraph ("geschachtelte Tabelle!", DatenStyle),
                        [ Paragraph ("aaa", DatenStyle),
                          Paragraph ("bbb", DatenStyle),
                          Paragraph ("ccc", DatenStyle)
                        ],
                        None
                      ),
              Paragraph ("Zeile 5", DatenStyle)
             ], Paragraph ("Fusszeile", FussStyle) )

###
### Here comes the "page x of y" code:
###
### If we know the number of pages from the last run (even if not perfect),
### we use it. Otherwise we use the default value 0.
    try:
       cacheIndx = open ("hvb3.xref_cache", "r").readlines()
       for zeile in cacheIndx:
            numPages = string.atoi(zeile)
    except:
       numPages = 0

###
### Variable "Elements" contains the story.
### Now we render the document, using the last known value for numPages.
### At the end of the document, we know the number of pages we actually
needed.
### If the values are equal, we are finished.
### Otherwise, we store the number of pages in the xref_cache file and start
again.
### 
### This way we need at most 3 runs for a fresh generated document,
### (Worst Case: numPages=0 --> run 1 --> numPages=99 --> run 2 -->
numPages=100) --> run 3 --> numPages=101)
### Average case: 2 runs for a fresh generated document.
###
### After applying small changes to an existing document,
### we usually only need one new run.
###
### The xref_cache file could also be used to store the intra-sentence
cross-references ("see xxx on page yyy").
###
### When I look at it now that I know Python a little better, 
### I think the xref_cache file should implemented with pickle...
###
### Replace hvb3 with the filename of the input file.
###
    x = 0
    while 1:
        x = x + 1
        print "Run %d" % x
        elm = copy.deepcopy (Elements)
        numPagesAlt = numPages
        print "numPagesAlt=%d" % numPagesAlt
        numPages = writeDoc ("hvb3_%d.pdf" % x, elm)
        print "numPages=%d" % numPages
        if (numPages == numPagesAlt):
            break
        else:
            cacheIndx = open ("hvb3.xref_cache", "w")
            cacheIndx.write ("%d" % numPages)
            cacheIndx.close ()
    print "Runs needed: %d" % x