Python 实现office单个文件或整个文件夹(word,ppt,excel)转换成PDF文件,并获取PDF文件页数

Python 实现office单个文件或整个文件夹(word,ppt,excel)转换成PDF文件,并获取PDF文件页数

文件夹中获取需要转换的文件数,将其全部转换或可单独转换单个文件,并获取转成PDF的文件页数,具体实现如下:
用到的库:os,sys,pdfplumber,client22,pythoncom
库的安装方法:pip install pythoncom
代码:

# import pdfplumber
import os
import sys
import pdfplumber
from client22 import dynamic
import pythoncom
def __WrapDispatch(dispatch, userName = None, resultCLSID = None, typeinfo = None, \
                  UnicodeToString=None, clsctx = pythoncom.CLSCTX_SERVER,
                  WrapperClass = None):
  """
   Helper函数返回CLSID的makepy生成类(如果存在的话),否则使用CDispatch进行处理。
  """
  assert UnicodeToString is None, "this is deprecated and will go away"
  if resultCLSID is None:
    try:
      typeinfo = dispatch.GetTypeInfo()
      if typeinfo is not None: # 有些对象返回空值,有些引发异常。。。
        resultCLSID = str(typeinfo.GetTypeAttr()[0])
    except (pythoncom.com_error, AttributeError):
      pass

  if WrapperClass is None: WrapperClass = CDispatch
  return dynamic.Dispatch(dispatch, userName, WrapperClass, typeinfo, clsctx=clsctx)


def Dispatch(dispatch, userName = None, resultCLSID = None, typeinfo = None, UnicodeToString=None, clsctx = pythoncom.CLSCTX_SERVER):
  """创建基于调度的COM对象。
  """
  
  assert UnicodeToString is None, "这是不赞成的,将消失"
  dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
  return __WrapDispatch(dispatch, userName, resultCLSID, typeinfo, clsctx=clsctx)

class CDispatch(dynamic.CDispatch):
  """
    作为最后手段使用的动态类。重写dynamic.CDispatch的目的是使策略永久化
    使用makepy生成的包装器Python类而不是dynamic.CDispatch如果可能的话。
  """
  def _wrap_dispatch_(self, ob, userName = None, returnCLSID = None, UnicodeToString=None):
    assert UnicodeToString is None, "this is deprecated and will go away"
    return Dispatch(ob, userName, returnCLSID,None)

class Constants:
  """生成的COM常量的容器。
  """
  def __init__(self):
    self.__dicts__ = [] # A list of dictionaries
  def __getattr__(self, a):
    for d in self.__dicts__:
      if a in d:
        return d[a]
    raise AttributeError(a)

# And create an instance.
constants = Constants()

class PDFConverter:                #在类中,将word,excel,ppt文件路径、pdf文件路径和word,excel,ppt后台进程实例作为类的属性。
    def __init__(self, pathname, export='.'):  
        self._handle_postfix = ['doc','docx','xls','xlsx','pptx','ppt']  #处理文件后缀的list
        self._filename_list = list()    #list()是将元组转换成list,元组的元素值不能修改
        self._export_folder = os.path.join(os.path.abspath('.'), 'pdfconver')  #将转换成pdf的文件放到这个路径中,.os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略。 
        if not os.path.exists(self._export_folder):  #如果文件夹存在,返回True;如果path不存在,返回False。 
                os.mkdir(self._export_folder)    #创建目录的路径,自动创建C:\xxx\xxx\pdfconver的文件夹
        self._enumerate_filename(pathname)       #调用函数

    def _enumerate_filename(self, pathname):
        '''
        读取所有文件名
        '''
        full_pathname = os.path.abspath(pathname)  #返回path规范化的绝对路径
        if os.path.isfile(full_pathname):  #如果full_pathname是一个存在的文件,返回True。否则返回False。 
 
            if self._is_legal_postfix(full_pathname):   #如果是合法的后缀
                self._filename_list.append(full_pathname)    #将文件添加到文件名list中
            else:
                raise TypeError('文件 {} 后缀名不合法!仅支持如下文件类型:{}。'.format(pathname, '、'.join(self._handle_postfix)))
        elif os.path.isdir(full_pathname):  #如果full_pathname是一个存在的目录,则返回True。否则返回False。 
            for relpath, _, files in os.walk(full_pathname):  #遍历文件、目录
                for name in files:   
                    filename = os.path.join(full_pathname, relpath, name)  #将目录、文件、名字组合成一个路径
                    if self._is_legal_postfix(filename):   #判断文件名的后缀是否合法
                        self._filename_list.append(os.path.join(filename))
        else:
            raise TypeError('文件/文件夹 {} 不存在或不合法!'.format(pathname))

    def _is_legal_postfix(self, filename):
        return filename.split('.')[-1].lower() in self._handle_postfix and not os.path.basename(filename).startswith('~')
    
    def run_conver(self):
        '''
        进行批量处理,根据后缀名调用函数执行转换
        '''
        print('需要转换的文件数:', len(self._filename_list))  
        for filename in self._filename_list:   
            postfix = filename.split('.')[-1].lower()   #split()分隔符对字符串进行切片,分割次数,默认为 -1, 即分隔所有,lower() 将所有大写都转换成小写
            funcCall = getattr(self, postfix)   #返回对象的属性值
            print('原文件:', filename)
            funcCall(filename)
        print('转换完成!')
        
    
    def doc(self, filename):
        '''
        doc 和 docx 文件转换
        '''
        try: 
            
            name = os.path.basename(filename).split('.')[0] + '.pdf'  # 返回filename最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素。 
            exportfile = os.path.join(self._export_folder, name)   #将多个路径组合在一起
            print('保存 PDF 文件:', exportfile)
            w = Dispatch("Word.Application")    #首先使用dispatch函数创建一个word程序的后台进程,默认是不显示,只在后台处理。
            doc = w.Documents.Open(filename)    #Documents.Open函数打开word文件,返回一个文件对象
            doc.ExportAsFixedFormat(exportfile, 17)       
        except Exception as e:
            print("转换异常,异常1为:{}".format(e))
        finally:        #关闭打开的word后台进程。
            w.Quit()
    
    def docx(self, filename):
        self.doc(filename)
    
    def xls(self, filename):
        '''
        xls 和 xlsx 文件转换
        '''
        try:   
            name = os.path.basename(filename).split('.')[0] + '.pdf'
            exportfile = os.path.join(self._export_folder, name)
            # xlApp = DispatchEx("Excel.Application")  #创建一个新的Excel进程
            xlApp = Dispatch("Excel.Application")  #,初始化,试图寻找并复用一个已有的Excel进程(比如你已经在运行着的Excel程序)
            xlApp.Visible = True          #excel可编辑的窗口不可见    
            xlApp.DisplayAlerts = False   #属性关闭,Excel就不会弹出确认窗,而是直接覆盖同名文件。   
            books = xlApp.Workbooks.Open(filename,False)
            books.ExportAsFixedFormat(0, exportfile)      #调用文件对象的ExportAsFixedFormat函数将文件内容输出
            books.Close(False)
            print('保存 PDF 文件:', exportfile)
            f = pdfplumber.open(exportfile)   #打开pdf文件
            page = len(f.pages)                    #pdf的页数
            print("文件",filename,"的页数为:",page)
        except Exception as e:
            print("转换异常,异常2为:{}".format(e))
        finally:        #关闭打开excel的后台进程。           
            xlApp.Quit()
    
    def xlsx(self, filename):
        self.xls(filename)
    
    def ppt(self, filename):
        '''
        ppt 和 pptx 文件转换
        '''
        try:
            name = os.path.basename(filename).split('.')[0] + '.pdf'
            exportfile = os.path.join(self._export_folder, name)
            p = Dispatch("PowerPoint.Application")   #创建一个ppt程序的后台进程,默认是不显示,只在后台处理。
            ppt = p.Presentations.Open(filename, False, False, False)
            ppt.ExportAsFixedFormat(exportfile, 2, PrintRange=None)   #导出固定格式
            print('保存 PDF 文件:', exportfile)
            f = pdfplumber.open(exportfile)   #打开pdf文件
            page = len(f.pages)                    #pdf的页数
            print("文件",filename,"的页数为:",page)
        except Exception as e:
            print("转换异常,异常3为:{}".format(e))
        finally:        #关闭打开的ppt后台进程。           
            p.Quit()
    
    def pptx(self, filename):
        self.ppt(filename)

if __name__ == "__main__":
    
    # 文件夹批量导入转换
    # folder = 'Desktop\py\office' 
    # pathname = os.path.join(os.path.abspath('.'), folder)

    # 单个文件的转换
    pathname = "C:/Users/Weibo/Desktop/12.pptx"

    pdfConverter = PDFConverter(pathname)
    pdfConverter.run_conver()

实现效果:
在这里插入图片描述
参考文献:https://blog.csdn.net/XnCSD/article/details/85208303?depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-1&utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-1

  • 1
    点赞
  • 1
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值