2017-07-27 137 views
2

我想用Python轉換xlsx。我使用模塊tablib和xtopdf來構建一個結構良好的表格。非常棒!不幸的是,這些內容不適用於一個PDF頁面。所以我想將pagesize和格式更改爲水平A3。但我不知道如何工作。我的代碼:(Python)更改使用xtopdf生成的PDF文件的頁面大小和格式

import random 
import tablib 
from openpyxl import load_workbook 
from xtopdf import PDFWriter 
from pyPdf import PdfFileWriter, PdfFileReader 


workbook = load_workbook('C:/Users/user1/Testexcel.xlsx', guess_types=True, data_only=True) 
worksheet = workbook.get_sheet_by_name('Testsheet') 
ws_range = worksheet.iter_rows('A4:H6') 

# Helper function to output a string to both screen and PDF. 
def print_and_write(pw, strng): 
    print strng 
    pw.writeLine(strng) 

# Create an empty Dataset and set its headers. 
data = tablib.Dataset() 
data.headers = ['col1', 'col2', 'col3', 'col4'] 
widths = [30, 20, 10, 20] # Display widths for columns. 

for row in ws_range: 
    col1 = str(row[0].value) 
    col2 = str(row[1].value) 
    col3 = str(row[2].value) 
    col4 = str(row[3].value) 
    columns = [col1, col2, col3, col4] 
    row = [ str(col).center(widths[idx]) for idx, col in enumerate(columns) ] 
    data.append(row) 

# Set up the PDFWriter. 
pw = PDFWriter('C:/Users/user1/Test.pdf') 
pw.setFont('Courier', 10) 
pw.setHeader('Test') 
pw.setFooter('Test') 

# Generate header and data rows as strings; output them to screen and PDF. 

separator = '-' * sum(widths) 
print_and_write(pw, separator) 

# Output headers 
header_strs = [ header.center(widths[idx]) for idx, header in enumerate(data.headers) ] 
print_and_write(pw, ''.join(header_strs)) 
print_and_write(pw, separator) 

# Output data 
for row in data: 
    print_and_write(pw, ''.join(row)) 

print_and_write(pw, separator) 
pw.close() 

發現從xtopdf本身的PDFWriter實例化了reportlab庫的畫布對象。在畫布類中聲明瞭默認設置爲「A4」的屬性pagesize。但如果我將條目更改爲'A3',結果pdf仍然是'A4'。

class Canvas(textobject._PDFColorSetter): 
    from reportlab.pdfgen import canvas 
    c = canvas.Canvas("hello.pdf") 
    from reportlab.lib.units import inch 
    # move the origin up and to the left 
    c.translate(inch,inch) 
    # define a large font 
    c.setFont("Helvetica", 80) 
    # choose some colors 
    c.setStrokeColorRGB(0.2,0.5,0.3) 
    c.setFillColorRGB(1,0,1) 
    # draw a rectangle 
    c.rect(inch,inch,6*inch,9*inch, fill=1) 
    # make text go straight up 
    c.rotate(90) 
    # change color 
    c.setFillColorRGB(0,0,0.77) 
    # say hello (note after rotate the y coord needs to be negative!) 
    c.drawString(3*inch, -3*inch, "Hello World") 
    c.showPage() 
    c.save() 
    """ 

    def __init__(self,filename, 
       pagesize='A3', 
       bottomup = 1, 
       pageCompression=None, 
       encoding = None, 
       invariant = None, 
       verbosity=0): 
     """Create a canvas of a given size. etc. 

     You may pass a file-like object to filename as an alternative to 
     a string. 

     Most of the attributes are private - we will use set/get methods 
     as the preferred interface. Default page size is A4.""" 
     if pagesize is None: pagesize = 'A3' 
     if encoding is None: encoding = rl_config.defaultEncoding 
     if invariant is None: invariant = rl_config.invariant 
     self._filename = filename 
     self._encodingName = encoding 
     self._doc = pdfdoc.PDFDocument(encoding, 
             compression=pageCompression, 
             invariant=invariant, filename=filename) 


     #this only controls whether it prints 'saved ...' - 0 disables 
     self._verbosity = verbosity 

     #this is called each time a page is output if non-null 
     self._onPage = None 

     self._pagesize = pagesize 
     self._pageRotation = 0 
     #self._currentPageHasImages = 0 
     self._pageTransition = None 
     self._pageDuration = None 
     self._destinations = {} # dictionary of destinations for cross indexing. 

     self.setPageCompression(pageCompression) 
     self._pageNumber = 1 # keep a count 
     #self3 = [] #where the current page's marking operators accumulate 
     # when we create a form we need to save operations not in the form 
     self._codeStack = [] 
     self._restartAccumulators() # restart all accumulation state (generalized, arw) 
     self._annotationCount = 0 

     self._outlines = [] # list for a name tree 
     self._psCommandsBeforePage = [] #for postscript tray/font commands 
     self._psCommandsAfterPage = [] #for postscript tray/font commands 

     #PostScript has the origin at bottom left. It is easy to achieve a top- 
     #down coord system by translating to the top of the page and setting y 
     #scale to -1, but then text is inverted. So self.bottomup is used 
     #to also set the text matrix accordingly. You can now choose your 
     #drawing coordinates. 
     self.bottomup = bottomup 
     self.imageCaching = rl_config.defaultImageCaching 
     self._make_preamble() 
     self.init_graphics_state() 
     self.state_stack = [] 

編輯:我認爲reportlab模塊的變化不被系統接受。試圖刪除字典reportlab,並試圖導入它,然後在命令行。諷刺的是,它的工作原理雖然python不應該再找到這個模塊。

+0

未經測試:'PW .__ canv = canvas.Canvas( 'C:/Users/user1/Test.pdf', 'A3')' –

+0

這產生一個名稱錯誤:'的Python異常:名稱'canvas'未定義'也試圖在instanciate後PDFWriter:'pw .__ canv.setPageSize(4961,3508)'但沒有成功,因爲它說'Python異常:PDFWriter實例沒有屬性' __canv''具有諷刺意味的是PDFWriter類具有一個名爲__canv的屬性 – Felix

回答

0

只是forked a project named xtopdf at bitbucket並提出了以下變化:

##------------------------ PDFWriter.__init__ ---------------------------- 

- def __init__(self, pdf_fn): 
+ def __init__(self, pdf_fn, pagesize='A4'): 
    ''' 
    Constructor. 
    "pdf_fn" arg is the name of the PDF file to be created. 
    ''' 

     self.__pdf_fn = pdf_fn   # file name of PDF file 
-  self.__canv = canvas.Canvas(pdf_fn)  # canvas to write on 
+  self.__canv = canvas.Canvas(pdf_fn, pagesize)  # canvas to write on 
     self.__font_name = None  # font name 
     self.__font_size = None  # font size 
     self.__header_str = None  # header string (partial) 

你能試試嗎?使用pw = PDFWriter('C:/Users/user1/Test.pdf', 'A3')

1

試試這個

from reportlab.pdfgen import canvas 
from reportlab.lib.units import mm 
c = canvas.Canvas("hello.pdf", pagesize = (297 * mm, 420 * mm)) 
# or (420 * mm, 297 * mm) if you want it in portrait format 
# values for inch: 11.69 * inch , 16.53 * inch 

#the following would create an empty page 
c.showPage() 
c.save()