word文档内的一页:
将文本取出来,生成自定义格式的PDF文件:
从word取出文本时标题的标号和页码是取不出来的,要自己加。另外就是目录也要自己生成和添加:
代码和解释如下:
from reportlab.lib.styles import ParagraphStyle as PS # 段落格式from reportlab.platypus import PageBreak # 分页符from reportlab.platypus.paragraph import Paragraph # 生成段落用from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate # 用于生成页面模版,文档模版from reportlab.platypus.tableofcontents import TableOfContents # 用于生成目录from reportlab.platypus.frames import Frame # 生成页面模版是定义页面内的框架framefrom reportlab.lib.units import cm, inch # 尺度单位# 注册中文字体from reportlab.pdfbase.ttfonts import TTFontfrom reportlab.pdfbase import pdfmetricspdfmetrics.registerFont(TTFont('lively', '/Library/Fonts/Chinese/ChaoZiSheZengYuBoShouShuJian-2.ttf'))pdfmetrics.registerFont(TTFont('apple', '/Library/Fonts/Chinese/XiaoHuYao-2.ttf'))# 定义标题、普通段落和代码的段落格式h1 = PS(name = 'Heading1', fontSize = 16, leading = 24, fontName = 'lively', spaceAfter = 15)h2 = PS(name = 'Heading2', fontSize = 14, leading = 20, leftIndent = 10, fontName = 'lively', spaceBefore = 10, spaceAfter = 10)h3 = PS(name = 'Heading3', fontSize = 12, leading = 16, leftIndent = 20, fontName = 'lively', spaceBefore = 10, spaceAfter = 10)normalText = PS(name = 'normal', fontSize = 12, leading = 14, firstLineIndent = 25, fontName = 'apple')code = PS(name = 'code', fontSize = 10, leading = 14, leftIndent = 35,fontName = 'apple')class MyDocTemplate(BaseDocTemplate): # 是BaseDocTemplate的子类 def __init__(self, filename, **kw): BaseDocTemplate.__init__(self, filename, **kw) template = PageTemplate('normal', [Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1')], onPageEnd=self.footer) # 定义页面模版,页脚可有可无 self.addPageTemplates(template) # 加入页面模版 # 打开word取出文字内容,生成段落flowable放进story def feedContent(self, filename, story): from docx import Document # 帮忙处理word文档 docWord = Document(filename) # 打开word文档,生成word文档对象 h1Num = 0; h2Num = 0; h3Num = 0 # 因为要给标题加序号,三级序号,所以用变量记录所在层级的序号 for para in docWord.paragraphs: # 遍历word文档的各个段落 docStyle = para.style.name # 取出word文档中的段落格式 if docStyle == 'Heading 1': # 如果是第一级标题,先加上序号再填进story h1Num += 1 # 标记第一级标题的序号增1 seq = str(h1Num) + '、 ' # 第一级标题的格式为1、 story.append(Paragraph(seq + para.text, h1)) # 生成段落followable加入story elif docStyle == 'Heading 2': # 第二级标题 h2Num += 1 # 标记第二级标题的序号增1 seq = str(h1Num) + '.' + str(h2Num) + ' ' # 第二级标题格式1.1 story.append(Paragraph(seq + para.text, h2)) elif docStyle == 'Heading 3': # 第三级标题 h3Num += 1 # 标记第三级标题的序号增1 seq = str(h1Num) + '.' + str(h2Num) + '.' + str(h3Num) + ' ' # 第三级标题的序号1.1.1 story.append(Paragraph(seq + para.text, h3)) elif docStyle == 'Code': # 普通段落和代码直接填进story,对代码的处理效果不理想 story.append(Paragraph(para.text, code)) else: story.append(Paragraph(para.text, normalText)) # 生成一个flowable后判断是否为标题,是标题填进目录,二三级目录生成书签链接 def afterFlowable(self, flowable): # 注册目录的条目 if flowable.__class__.__name__ == 'Paragraph': text = flowable.getPlainText() # 取出文字 style = flowable.style.name # 取出段落格式 if style == 'Heading1': # 第一级标题 self.notify('TOCEntry', (0, text, self.page)) if style == 'Heading2': # 第二级标题 key = 'h2-{}'.format(self.seq.nextf('heading2')) # 生成书签名 self.canv.bookmarkPage(key) # 生成书签页 self.notify('TOCEntry', (1, text, self.page, key)) # 'TOCEntry':通知类型;(1, text, self.page, key): # (目录层级、文本内容、当前页数、可选的书签名) if style == 'Heading3': # 第三级标题 key = 'h3-{}'.format(self.seq.nextf('heading3')) self.canv.bookmarkPage(key) self.notify('TOCEntry', (2, text, self.page, key)) # 页脚给出第几页 def footer(self, myCanvas, myDoc): myCanvas.setFont('lively',10) # 设置字体 myCanvas.drawRightString(7.6*inch,.5*inch, "{}".format(self.page)) # 画页脚toc = TableOfContents() # 生成目录对象toc.levelStyles = [h1, h2, h3] # 定义目录的格式,三层,每层的格式用段落格式定义story = [] # 列表story存放生成的各个flowablestory.append(toc) # 将目录对象填进story,此时目录只是架子,内容还没填进去story.append(PageBreak()) # 分页符docPDF = MyDocTemplate('mintoc.pdf') # 生成PDF文档对象docPDF.feedContent('excerpt.docx', story) # 打开word文档,取出内容生成flowable放进story中docPDF.multiBuild(story)# 这个文档的生成要过两遍,第一遍加了个目录的空架子,# 文档内容生成之后才能把目录内容填进去,所以用multiBuild()而不是build()