六.python-docx向word中插入表格

一.简介

一个表格(table)对象由多个行(row)对象组成,一个行(row)对象又由多个单元格(cell)对象组成。单元格对象包含段落对象,有了段落对象我们就可以添加文字并设置样式。

二.插入表格

分为两种情况:
a:固定的行和列
b:不固定的行和列

1.固定的行和列

写法一:

from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import RGBColor
document = Document()
t1 = document.add_table(rows=4, cols=2, style='Colorful List')
# 添加表头
t1.rows[0].cells[0].text = "类别"
t1.rows[0].cells[1].text = "代号"

t1.rows[1].cells[0].text = "A"
t1.rows[1].cells[1].text = "001"

t1.rows[2].cells[0].text = "B"
t1.rows[2].cells[1].text = "002"

t1.rows[3].cells[0].text = "C"
t1.rows[3].cells[1].text = "003"

run1 = t1.rows[0].cells[0].paragraphs[0].add_run('类别')
t1.rows[0].cells[0].paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
run1.font.color.rgb = RGBColor(0, 255, 0)
run1.bold=True

# 保存表格
document.save('表格1.docx')

结果
六.python-docx向word中插入表格_第1张图片
写法二:循环添加内容

from docx import Document
import numpy as np
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import RGBColor

arr = np.array([['类别1', '代号1'], ['A', '001'], ['B', '002'], ['C', '003']])
document = Document()
t1 = document.add_table(rows=4, cols=2, style='Colorful List')


# 循环添加
for i, row in enumerate(t1.rows):
    print(i)
    for j, cell in enumerate(row.cells):
        # 获取单元格中的段落对象
        paragraph = cell.paragraphs[0]
        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
        # 这里的run可以设置一些属性
        run = paragraph.add_run(arr[i, j])
        if i == 2:
            run.font.color.rgb = RGBColor(0, 255, 0)

# 保存表格
document.save('表格2.docx')

结果:
六.python-docx向word中插入表格_第2张图片

1.不固定的行和列

提前并不确定表格的行列,需要根据数据情况临时添加。则可以先创建一个1*1的表格,然后向右增加列以及向下增加行

四.练习:利用python-docx自动生成表格简化工作流程

1.背景

不同的工作有时都会使用固定的表格,填写非固定的信息.比如:
六.python-docx向word中插入表格_第3张图片
六.python-docx向word中插入表格_第4张图片

2.工作流程

老的工作流程:
打开两个表,在表中对应位置填写个人信息,保存。这样一来,当需要填写的信息比较多的时候,工作就会繁琐

新的工作流程:

  1. 利用python-docx编写脚本,运行脚本-输入个人信息-自动生成两个word模板

  2. 脚本用到的python-docx库的功能:
    (1)、创建与合并表格
    (2)、添加文本
    (3)、设置文本属性(如大小、加粗、下划线、居中等)

  3. 安装python-docx已经说过了

  4. 创建一个新的文档

"""
创建一个新的文档
"""
document = Document()
"""
零.设置正文的字型
"""
document.styles['Normal'].font.name = "Times New Roman"
document.styles['Normal'].element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
  1. 创建and合并表格
    合并单元格涉及到下标问题,所以可以通过一段代码让每一个单元格显示所在的下标
document1 = Document('word模版1.docx')
table = document1.tables[0]
for row, obj_row in enumerate(table.rows):
	for col, cell in enumerate(obj_row.cells):
		cell.text = cell.text + "%d,%d" % (row, col)
document1.save("有行和列标记的word模版1.docx")
"""
一.添加一个37行,13列共481个单元格的表格
"""
table = document.add_table(rows=37, cols=13, style="Table Grid")

"""
二.合并单元格
"""
# 第一行
table.cell(0, 0).merge(table.cell(2, 2))
table.cell(0, 3).merge(table.cell(2, 6))
table.cell(0, 7).merge(table.cell(2, 9))
table.cell(0, 10).merge(table.cell(2, 12))

# 第二行
table.cell(3, 0).merge(table.cell(5, 2))
table.cell(3, 3).merge(table.cell(5, 5))
table.cell(3, 6).merge(table.cell(5, 6))
table.cell(3, 7).merge(table.cell(5, 9))
table.cell(3, 10).merge(table.cell(5, 10))
table.cell(3, 11).merge(table.cell(5, 12))

# 第三行
table.cell(6, 0).merge(table.cell(8, 2))
table.cell(6, 3).merge(table.cell(8, 12))

# 第四行
table.cell(9, 0).merge(table.cell(12, 2))
table.cell(9, 3).merge(table.cell(12, 6))
table.cell(9, 7).merge(table.cell(10, 9))
table.cell(11, 7).merge(table.cell(12, 9))
table.cell(9, 10).merge(table.cell(10, 12))
table.cell(11, 10).merge(table.cell(12, 12))

# 第五行
table.cell(13, 0).merge(table.cell(18, 2))
table.cell(13, 3).merge(table.cell(18, 12))

# 第六行
table.cell(19, 0).merge(table.cell(24, 2))
table.cell(19, 3).merge(table.cell(24, 12))

# 第七行
table.cell(25, 0).merge(table.cell(30, 2))
table.cell(25, 3).merge(table.cell(30, 12))

# 第八行
table.cell(31, 0).merge(table.cell(36, 2))
table.cell(31, 3).merge(table.cell(36, 12))
  1. 接收用户输入的内容,也就是表格中非固定内容
"""
接收学生输入的内容
"""
departments = input('院系:')
specialty = input('专业:')
name = input('姓名:')
gender = input('性别:')
school_num = input('学号:')
school_time_year_month1 = input('在校起始时间年月:')
school_time_year_month2 = input('在校截止时间年月:')
home_address = input('家庭通讯地址:')
home_num = input('家庭联系方式:')
personal_tel = input('个人联系方式:')
reason = input('本人申请理由:')
  1. 获取合并后的每一行的单元格
# 1.获取合并单元格后的每一行的所有单元格
hdr_cells0 = table.rows[0].cells
hdr_cells3 = table.rows[3].cells
hdr_cells6 = table.rows[6].cells
hdr_cells9 = table.rows[9].cells
hdr_cells12 = table.rows[12].cells
hdr_cells15 = table.rows[15].cells
hdr_cells21 = table.rows[21].cells
hdr_cells27 = table.rows[27].cells
hdr_cells32 = table.rows[32].cells
  1. 定义两个函数功能分别是向单元格写入内容,一个加粗,一个不加粗
def add_content_center(cell, con):
    """
    填写非固定信息
    向单元格写入内容,字体不加粗
    :param cell: 
    :param con: 
    :return: 
    """
    p = cell.add_paragraph('')
    p.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    cell.text = con
    cell.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER


def add_content_center_bold(cell, con):
    """
    填写固定信息
    向单元格写入内容,字体加粗
    :param cell: 
    :param con: 
    :return: 
    """
    cell.text = con
    cell.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
    cell.vertical_alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    cell.paragraphs[0].runs[0].font.bold = True
  1. 依次向每一行的每一个合并后的单元格添加内容
# 第一行的内容
add_content_center_bold(hdr_cells0[0], "院(系)")
add_content_center(hdr_cells0[3], departments + '院')
add_content_center_bold(hdr_cells0[7], '专业班级')
add_content_center(hdr_cells0[10], specialty)

# 第二行的内容
add_content_center_bold(hdr_cells3[0], "姓名")
add_content_center(hdr_cells3[3], name)
add_content_center_bold(hdr_cells3[6], "性别")
add_content_center(hdr_cells3[7], gender)
add_content_center_bold(hdr_cells3[10], '学号')
add_content_center(hdr_cells3[11], school_num)

# 第三行内容
add_content_center_bold(hdr_cells6[0], "在校时间")
add_content_center(hdr_cells6[3], school_time_year_month1 + "-" + school_time_year_month2)
# 第四行
add_content_center_bold(hdr_cells9[0], "家庭通讯地址")
add_content_center(hdr_cells9[3], home_address)
add_content_center_bold(hdr_cells9[7], "家庭联系方式")
add_content_center(hdr_cells9[10], home_num)
add_content_center_bold(table.rows[12].cells[7], "个人联系方式")
add_content_center(table.rows[12].cells[10], personal_tel)

# 第五行
add_content_center_bold(hdr_cells15[0], "本人申请理由")
add_content_center(hdr_cells15[3], reason + "\n\n学生本人签名\n\n\t\t年\t月\t日")

# 第六行
# hdr_cells21[0].vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
add_content_center_bold(hdr_cells21[0], "院系领导意见")
add_content_center(hdr_cells21[3], "\n\n领导签字\n\n\t\t年\t月\t日")

# 第七行
add_content_center_bold(hdr_cells27[0], "学生处意见")
add_content_center(hdr_cells27[3], "\n\n领导签字\n\n\t\t年\t月\t日")

# 第八行
add_content_center_bold(hdr_cells32[0], "主管校领导审批")
add_content_center(hdr_cells32[3], "\n\n领导签字\n\n\t\t年\t月\t日")

3.完整代码

from docx import Document
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_CELL_VERTICAL_ALIGNMENT
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn

from docx.shared import RGBColor, Pt

"""
接收学生输入的内容
"""
departments = input('院系:')
specialty = input('专业:')
name = input('姓名:')
gender = input('性别:')
school_num = input('学号:')
school_time_year_month1 = input('在校起始时间年月:')
school_time_year_month2 = input('在校截止时间年月:')
home_address = input('家庭通讯地址:')
home_num = input('家庭联系方式:')
personal_tel = input('个人联系方式:')
reason = input('本人申请理由:')
"""
创建一个新的文档
"""
document = Document()
"""
零.设置正文的字型
"""
document.styles['Normal'].font.name = "Times New Roman"
document.styles['Normal'].element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')

"""
一.添加一个37行,13列共481个单元格的表格
"""
table = document.add_table(rows=37, cols=13, style="Table Grid")

"""
二.合并单元格
"""
# 第一行
table.cell(0, 0).merge(table.cell(2, 2))
table.cell(0, 3).merge(table.cell(2, 6))
table.cell(0, 7).merge(table.cell(2, 9))
table.cell(0, 10).merge(table.cell(2, 12))

# 第二行
table.cell(3, 0).merge(table.cell(5, 2))
table.cell(3, 3).merge(table.cell(5, 5))
table.cell(3, 6).merge(table.cell(5, 6))
table.cell(3, 7).merge(table.cell(5, 9))
table.cell(3, 10).merge(table.cell(5, 10))
table.cell(3, 11).merge(table.cell(5, 12))

# 第三行
table.cell(6, 0).merge(table.cell(8, 2))
table.cell(6, 3).merge(table.cell(8, 12))

# 第四行
table.cell(9, 0).merge(table.cell(12, 2))
table.cell(9, 3).merge(table.cell(12, 6))
table.cell(9, 7).merge(table.cell(10, 9))
table.cell(11, 7).merge(table.cell(12, 9))
table.cell(9, 10).merge(table.cell(10, 12))
table.cell(11, 10).merge(table.cell(12, 12))

# 第五行
table.cell(13, 0).merge(table.cell(18, 2))
table.cell(13, 3).merge(table.cell(18, 12))

# 第六行
table.cell(19, 0).merge(table.cell(24, 2))
table.cell(19, 3).merge(table.cell(24, 12))

# 第七行
table.cell(25, 0).merge(table.cell(30, 2))
table.cell(25, 3).merge(table.cell(30, 12))

# 第八行
table.cell(31, 0).merge(table.cell(36, 2))
table.cell(31, 3).merge(table.cell(36, 12))

"""
三. 把模版的固定位置添加内容
1.获取合并单元格后的每一行的所有单元格
2.依次向每一行的每一个合并后的单元格添加内容
"""
# 1.获取合并单元格后的每一行的所有单元格
hdr_cells0 = table.rows[0].cells
hdr_cells3 = table.rows[3].cells
hdr_cells6 = table.rows[6].cells
hdr_cells9 = table.rows[9].cells
hdr_cells12 = table.rows[12].cells
hdr_cells15 = table.rows[15].cells
hdr_cells21 = table.rows[21].cells
hdr_cells27 = table.rows[27].cells
hdr_cells32 = table.rows[32].cells


# 2
def add_content_center(cell, con):
    """
    填写非固定信息
    向单元格写入内容,字体不加粗
    :param cell:
    :param con:
    :return:
    """
    p = cell.add_paragraph('')
    p.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    cell.text = con
    cell.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER


def add_content_center_bold(cell, con):
    """
    填写固定信息
    向单元格写入内容,字体加粗
    :param cell:
    :param con:
    :return:
    """
    cell.text = con
    cell.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
    cell.vertical_alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    cell.paragraphs[0].runs[0].font.bold = True


# 第一行的内容
add_content_center_bold(hdr_cells0[0], "院(系)")
add_content_center(hdr_cells0[3], departments + '院')
add_content_center_bold(hdr_cells0[7], '专业班级')
add_content_center(hdr_cells0[10], specialty)

# 第二行的内容
add_content_center_bold(hdr_cells3[0], "姓名")
add_content_center(hdr_cells3[3], name)
add_content_center_bold(hdr_cells3[6], "性别")
add_content_center(hdr_cells3[7], gender)
add_content_center_bold(hdr_cells3[10], '学号')
add_content_center(hdr_cells3[11], school_num)

# 第三行内容
add_content_center_bold(hdr_cells6[0], "在校时间")
add_content_center(hdr_cells6[3], school_time_year_month1 + "-" + school_time_year_month2)
# 第四行
add_content_center_bold(hdr_cells9[0], "家庭通讯地址")
add_content_center(hdr_cells9[3], home_address)
add_content_center_bold(hdr_cells9[7], "家庭联系方式")
add_content_center(hdr_cells9[10], home_num)
add_content_center_bold(table.rows[12].cells[7], "个人联系方式")
add_content_center(table.rows[12].cells[10], personal_tel)

# 第五行
add_content_center_bold(hdr_cells15[0], "本人申请理由")
add_content_center(hdr_cells15[3], reason + "\n\n学生本人签名\n\n\t\t年\t月\t日")

# 第六行
# hdr_cells21[0].vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
add_content_center_bold(hdr_cells21[0], "院系领导意见")
add_content_center(hdr_cells21[3], "\n\n领导签字\n\n\t\t年\t月\t日")

# 第七行
add_content_center_bold(hdr_cells27[0], "学生处意见")
add_content_center(hdr_cells27[3], "\n\n领导签字\n\n\t\t年\t月\t日")

# 第八行
add_content_center_bold(hdr_cells32[0], "主管校领导审批")
add_content_center(hdr_cells32[3], "\n\n领导签字\n\n\t\t年\t月\t日")

# document1 = Document('word模版1.docx')
# table = document1.tables[0]
# for row, obj_row in enumerate(table.rows):
#     for col, cell in enumerate(obj_row.cells):
#         cell.text = cell.text + "%d,%d" % (row, col)
# document1.save("有行和列标记的word模版1.docx")
document.save("word模版1.docx")

注意:先生成一个37行13列的表格写入word,然后用document1 = Document(‘word模版1.docx’)打开这个文档,在每个单元格中写入对应的下标,方便我们合并单元格
结果:
六.python-docx向word中插入表格_第5张图片

五.给单元格添加背景颜色

官方的pythondocx库仍然不支持该选项。 但是,您可以尝试自己实现它。您正在查找的属性名为cell shading,位于cell properties下
解决方案: 将着色元素(w:shd)添加到单元格属性(w:tcPr)
编写了一个简单的函数,它可以实现以下功能:

def _set_cell_background(cell, fill, color=None, val=None):
    """
    @fill: Specifies the color to be used for the background
    @color: Specifies the color to be used for any foreground
    pattern specified with the val attribute
    @val: Specifies the pattern to be used to lay the pattern
    color over the background color.
    """
    from docx.oxml.shared import qn  # feel free to move these out
    from docx.oxml.xmlchemy import OxmlElement

    cell_properties = cell._element.tcPr
    try:
        cell_shading = cell_properties.xpath('w:shd')[0]  # in case there's already shading
    except IndexError:
        cell_shading = OxmlElement('w:shd') # add new w:shd element to it
    if fill:
        cell_shading.set(qn('w:fill'), fill)  # set fill property, respecting namespace
    if color:
        pass # TODO
    if val:
        pass # TODO
    cell_properties.append(cell_shading)  # finally extend cell props with shading element

如果需要,可以随意扩展其他属性
因此,根据您的示例,一旦有了表,在保存文档之前,请添加以下行:

_set_cell_background(table.rows[0].cells[0], 'FF0000')
doc.save("Testing.docx")

你可能感兴趣的:(word,python)