当前位置:   article > 正文

python处理doc文档总结_python doc

python doc

需求

需求总结为:

使用python处理doc文档,生成内容和格式,并将doc转成pdf. 这些要运行在Linux终端,并且不能使用收费的服务。

技术选择

  • python选择的包为 python-docx
  • doc转pdf选择的是 unoconv

面对的问题和解决

python-docx包相关

office 和 wps包都卸载的情况下,这个包python-docx还能用吗?

提前用这个包将功能写好了,卸载wps后看还能不能使用。

测试结果是毫无问题,程序依然能够运行,不依赖外置的office和wps安装的模块。

Linux 上面能够使用吗?

结论是可以的
测试系统是centos, python3.7环境
python-docx 包是 python-docx==0.8.11

# 创建虚拟环境
python -m venv env
# 安装包
 pip install python-docx==0.8.11
  • 1
  • 2
  • 3
  • 4

安装包的过程比较容易,没有过多的依赖
pip安装python-docx
运行代码, 文档依然可以正常的生成!

unoconv -f pdf 测试文档生成.docx
  • 1

生成pdf报告

doc 转pdf怎么使用

  1. 网上找了很多,完成该需求有些是需要依赖office的,比如最常见的docx2pdf 包,没有装office就忽略吧,换言之Linux系统上也先别想了!
from docx2pdf import convert

convert("input.docx", "output.pdf")
  • 1
  • 2
  • 3
  1. stackoverflow上推荐的在Linux端需要提前安装Libreoffice,调用Libreoffice的功能。
    libreoffice 依赖
  2. Aspose包直接有python包可供调用,只是生成的pdf带有水印,需要购买。
import aspose.words as aw

doc = aw.Document("in.docx")
doc.save("out.pdf")
  • 1
  • 2
  • 3
  • 4
  1. unoconv 也是需要依赖Libreoffice,在安装此命令的时候能自动解决Libreoffice的依赖,不需要单独安装Libreoffice进行使用,相对比较方便。
    处理依赖
  2. 常见问题
    生成pdf乱码问题,需要向Linux中添加字体!

将Windows路径C:\Windows\Fonts 下的字体拷贝到 Linux路径/usr/share/fonts/ 中就能解决。

python-docx包处理文档

读取文档并添加表格

如下code,添加默认的表格。

from docx import Document
# 读取文档
document = Document('测试文档.docx')
# 添加表格
table = document.add_table(rows=7, cols=6)
# 将文档保存
document.save(os.path.join(os.getcwd(), '测试文档生成.docx'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

添加的表格如下图:
默认添加的表格
这肯定不是我们想要的表格, 我们想要的表格是:

  • 有实线的边框
  • 字体可以居中
  • 能够根据数据来调整行数

下面是我写的代码:

import math
import os
from xml.dom.minidom import Element
from docx import Document
from docx.opc.oxml import parse_xml
from docx.oxml import OxmlElement
from docx.oxml.ns import qn, nsdecls
from docx.shared import RGBColor
from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT, WD_TABLE_ALIGNMENT
import random


def set_cell_border(cell, **kwargs):
    """
    Set cell`s border
    Usage:
    set_cell_border(
        cell,
        top={"sz": 12, "val": "single", "color": "#FF0000", "space": "0"},
        bottom={"sz": 12, "color": "#00FF00", "val": "single"},
        left={"sz": 24, "val": "dashed", "shadow": "true"},
        right={"sz": 12, "val": "dashed"},
    )
    """
    tc = cell._tc
    tcPr = tc.get_or_add_tcPr()

    # check for tag existnace, if none found, then create one
    tcBorders = tcPr.first_child_found_in("w:tcBorders")
    if tcBorders is None:
        tcBorders = OxmlElement('w:tcBorders')
        tcPr.append(tcBorders)

    # list over all available tags
    for edge in ('left', 'top', 'right', 'bottom', 'insideH', 'insideV'):
        edge_data = kwargs.get(edge)
        if edge_data:
            tag = 'w:{}'.format(edge)

            # check for tag existnace, if none found, then create one
            element = tcBorders.find(qn(tag))
            if element is None:
                element = OxmlElement(tag)
                tcBorders.append(element)

            # looks like order of attributes is important
            for key in ["sz", "val", "color", "space", "shadow"]:
                if key in edge_data:
                    element.set(qn('w:{}'.format(key)), str(edge_data[key]))


def add_table(table, data: dict):
    pre = ['科目', '得分']
    keys = list(data.keys())
    cnt = 0
    key = keys[0]
    # 添加内容
    for i, row in enumerate(table.rows):
        for j, cell in enumerate(row.cells):
        	# 设置可以居中
            cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
            set_cell_border(
                cell,
                top={"sz": 0.5, "val": "single", "color": "#000000", "space": "0"},
                bottom={"sz": 0.5, "val": "single", "color": "#000000", "space": "0"},
                left={"sz": 0.5, "val": "single", "color": "#000000", "space": "0"},
                right={"sz": 0.5, "val": "single", "color": "#000000", "space": "0"},
                # 注释的这两个参数能调整内边框
                # insideH={"sz": 0.5, "val": "single", "color": "#000000", "space": "0"},
                # end={"sz": 0.5, "val": "single", "color": "#000000", "space": "0"}
            )
            # 获取单元格中的段落对象
            paragraph = cell.paragraphs[0]
            paragraph.alignment = WD_TABLE_ALIGNMENT.CENTER
            if i == 0:
            	# 给边框填充背景
                color: Element = parse_xml(r'<w:shd {} w:fill="{color_value}"/>'.format(
                    nsdecls('w'), color_value=RGBColor(0, 0, 139)))
                cell._tc.get_or_add_tcPr().append(color)
                # 和上面一样,这里的run可以设置一些属性
                run = paragraph.add_run(pre[j % 2])
                continue

            if cnt < len(data):
                if j % 2 == 0:
                    key = keys[cnt]
                    paragraph.add_run(key)
                else:
                    paragraph.add_run(str(data[key]))
                    cnt += 1


document = Document('测试文档.docx')

data = {
    'python': random.randint(80, 100),
    'c++': random.randint(80, 100),
    'golang': random.randint(80, 100),
    'c': random.randint(80, 100),
    'sql': random.randint(80, 100),
    'java': random.randint(80, 100),
    'javascript': random.randint(80, 100),
    'mysql': random.randint(80, 100),
    'neo4j': random.randint(80, 100),
    'hive': random.randint(80, 100),
}
table = document.add_table(rows=math.ceil(len(data) / 3) + 1, cols=6)
add_table(table, data)

document.save(os.path.join(os.getcwd(), '测试文档生成.docx'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110

插入到docx文件的表格如下图所示:
格式优化过的表格

借助docx中的样式添加内容

在模板docx中添加样式
添加新的样式
添加了新的列表项目符号样式
新样式
效果如下,给添加的内容加上 ·
样式效果
代码中加载该文档,给需要生成的内容添加该样式:

from docx import Document
from docx.shared import Pt
# 读取文档
document = Document('测试文档.docx')
_ = document.add_paragraph(
    'first item in unordered list', style='List Bullet'
)
# 设置段前和段后的间距
_.paragraph_format.space_before = Pt(0)
_.paragraph_format.space_after = Pt(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

添加其他样式同理。

表格单元格的宽度设置

from docx.shared import Cm, Inches
document = Document('测试文档.docx')
table = document.add_table(rows=7, cols=6)
table.autofit = False
table.columns[0].width = Inches(1.4)
table.columns[1].width = Inches(0.6)
table.columns[3].width = Inches(0.6)
table.columns[2].width = Inches(1.4)
table.columns[5].width = Inches(0.6)
table.columns[4].width = Inches(1.4)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

插入图片

# 向已经有的段落添加图片
# width 参数用来调整图片的大小
document.paragraphs[2].add_run().add_picture("../qrcode.png", width=Cm(2.8))
# 直接插入图片
document.add_paragraph("在下面插入一张图片")
document.add_picture("../qrcode.png", width=Cm(2.8))
# 清理原有段落图片
document.paragraphs[1].clear()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

欢迎关注,共同交流,后续有优化还会更新。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/661005
推荐阅读
相关标签
  

闽ICP备14008679号