1. Introduction
A table (table) object is composed of multiple row (row) objects, and a row (row) object is composed of multiple cell (cell) objects. Cell objects contain paragraph objects, and with paragraph objects we can add text and set styles.
2. Insert table
Divided into two situations:
a: Fixed rows and columns
b: Unfixed rows and columns
1. Fixed rows and columns
Writing method one:
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') #Add header t1.rows[0].cells[0].text = "Category" t1.rows[0].cells[1].text = "code name" 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('category') t1.rows[0].cells[0].paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER run1.font.color.rgb = RGBColor(0, 255, 0) run1.bold=True # Save form document.save('Form 1.docx')
result
Writing method two: add content in a loop
from docx import Document import numpy as np from docx.enum.text import WD_PARAGRAPH_ALIGNMENT from docx.shared import RGBColor arr = np.array([['Category 1', 'Code 1'], ['A', '001'], ['B', '002'], ['C', '003']]) document = Document() t1 = document.add_table(rows=4, cols=2, style='Colorful List') # Add in loop for i, row in enumerate(t1.rows): print(i) for j, cell in enumerate(row.cells): # Get the paragraph object in the cell paragraph = cell.paragraphs[0] paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # The run here can set some properties run = paragraph.add_run(arr[i, j]) if i == 2: run.font.color.rgb = RGBColor(0, 255, 0) # Save form document.save('Form 2.docx')
result:
1. Unfixed rows and columns
The rows and columns of the table are not determined in advance and need to be added temporarily based on the data situation. You can first create a 1*1 table, then add columns to the right and rows to the bottom.
4. Exercise: Use python-docx to automatically generate tables to simplify the workflow
1.Background
Different jobs sometimes use fixed forms to fill in non-fixed information. For example:
2. Workflow
Old workflow:
Open the two tables, fill in the personal information in the corresponding positions in the table, and save. In this way, when there is a lot of information to be filled in, the work will be cumbersome.
New workflow:
-
Use python-docx to write a script, run the script – enter personal information – automatically generate two word templates
-
Functions of the python-docx library used in the script:
(1) Create and merge tables
(2), add text
(3) Set text attributes (such as size, bold, underline, center, etc.) -
Installing python-docx has already been said
-
Create a new document
""" Create a new document """ document = Document() """ Zero.Set the font of the text """ document.styles['Normal'].font.name = "Times New Roman" document.styles['Normal'].element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
- Create and merge tables
Merging cells involves subscripts, so you can use a piece of code to make each cell display its subscript.
document1 = Document('word template 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 template 1.docx with row and column marks")
""" 1. Add a table with 37 rows and 13 columns with a total of 481 cells """ table = document.add_table(rows=37, cols=13, style="Table Grid") """ 2. Merge cells """ # first row 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)) # second line 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)) # The third row table.cell(6, 0).merge(table.cell(8, 2)) table.cell(6, 3).merge(table.cell(8, 12)) # fourth line 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)) # The fifth line table.cell(13, 0).merge(table.cell(18, 2)) table.cell(13, 3).merge(table.cell(18, 12)) # sixth line table.cell(19, 0).merge(table.cell(24, 2)) table.cell(19, 3).merge(table.cell(24, 12)) # the seventh line table.cell(25, 0).merge(table.cell(30, 2)) table.cell(25, 3).merge(table.cell(30, 12)) # eighth line table.cell(31, 0).merge(table.cell(36, 2)) table.cell(31, 3).merge(table.cell(36, 12))
- Receive the content entered by the user, that is, the non-fixed content in the table
""" Receive input from students """ departments = input('Departments:') specialty = input('specialty:') name = input('Name:') gender = input('Gender:') school_num = input('Student number:') school_time_year_month1 = input('School start time year and month:') school_time_year_month2 = input('School deadline year and month:') home_address = input('Home address:') home_num = input('Home contact information:') personal_tel = input('Personal contact information:') reason = input('My reason for applying:')
- Get the merged cells of each row
# 1. Get all the cells of each row after the merged cells 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
- Define two functions to write content to the cell, one is bold and the other is not bold
def add_content_center(cell, con): """ Fill in non-fixed information Write content to the cell without making the font bold :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): """ Fill in fixed information Write content to the cell and make the font bold :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 to each merged cell of each row in turn
# Contents of the first line add_content_center_bold(hdr_cells0[0], "College (Department)") add_content_center(hdr_cells0[3], departments + 'house') add_content_center_bold(hdr_cells0[7], 'professional class') add_content_center(hdr_cells0[10], specialty) # Contents of the second line add_content_center_bold(hdr_cells3[0], "Name") add_content_center(hdr_cells3[3], name) add_content_center_bold(hdr_cells3[6], "Gender") add_content_center(hdr_cells3[7], gender) add_content_center_bold(hdr_cells3[10], 'student number') add_content_center(hdr_cells3[11], school_num) # The third line of content add_content_center_bold(hdr_cells6[0], "school time") add_content_center(hdr_cells6[3], school_time_year_month1 + "-" + school_time_year_month2) # Fourth line add_content_center_bold(hdr_cells9[0], "Home mailing address") add_content_center(hdr_cells9[3], home_address) add_content_center_bold(hdr_cells9[7], "Family Contact Information") add_content_center(hdr_cells9[10], home_num) add_content_center_bold(table.rows[12].cells[7], "personal contact information") add_content_center(table. rows[12]. cells[10], personal_tel) # The fifth line add_content_center_bold(hdr_cells15[0], "The reason for my application") add_content_center(hdr_cells15[3], reason + "\ \ Student's signature\ \ \t\tyear\tmonth\tday") # Line 6 # hdr_cells21[0].vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER add_content_center_bold(hdr_cells21[0], "Department leader's opinion") add_content_center(hdr_cells21[3], "\ \ leadership signature\ \ \t\tyear\tmonth\tday") # Line 7 add_content_center_bold(hdr_cells27[0], "Student Office Opinions") add_content_center(hdr_cells27[3], "\ \ leadership signature\ \ \t\tyear\tmonth\tday") # Line 8 add_content_center_bold(hdr_cells32[0], "Approval by the head of the school") add_content_center(hdr_cells32[3], "\ \ leadership signature\ \ \t\tyear\tmonth\tday")
3. Complete code
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 """ Receive input from students """ departments = input('Department:') specialty = input('Professional:') name = input('Name:') gender = input('Gender:') school_num = input('student number: ') school_time_year_month1 = input('School start time year and month:') school_time_year_month2 = input('School deadline year and month:') home_address = input('Home correspondence address:') home_num = input('Home contact information:') personal_tel = input('Personal contact information:') reason = input('My reason for applying:') """ Create a new document """ document = Document() """ Zero.Set the font of the text """ document.styles['Normal'].font.name = "Times New Roman" document.styles['Normal'].element.rPr.rFonts.set(qn('w:eastAsia'), u'Arial') """ 1. Add a table with 37 rows and 13 columns with a total of 481 cells """ table = document.add_table(rows=37, cols=13, style="Table Grid") """ 2. Merge cells """ # first row 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)) # second line 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)) # The third row table.cell(6, 0).merge(table.cell(8, 2)) table. cell(6, 3). merge(table. cell(8, 12)) # Fourth line 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)) # The fifth line table.cell(13, 0).merge(table.cell(18, 2)) table.cell(13, 3).merge(table.cell(18, 12)) # Line 6 table.cell(19, 0).merge(table.cell(24, 2)) table.cell(19, 3).merge(table.cell(24, 12)) # Line 7 table.cell(25, 0).merge(table.cell(30, 2)) table.cell(25, 3).merge(table.cell(30, 12)) # Line 8 table.cell(31, 0).merge(table.cell(36, 2)) table.cell(31, 3).merge(table.cell(36, 12)) """ 3. Add content to the fixed position of the template 1. Get all the cells in each row after the merged cells 2. Add content to each merged cell in each row in turn """ # 1. Get all the cells of each row after the merged cells 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): """ Fill in non-fixed information Write content to the cell, the font is not bold :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): """ Fill in fixed information Write content to the cell, the font is bold :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 # Contents of the first line add_content_center_bold(hdr_cells0[0], "College (Department)") add_content_center(hdr_cells0[3], departments + 'hoard') add_content_center_bold(hdr_cells0[7], 'Professional class') add_content_center(hdr_cells0[10], specialty) # Contents of the second line add_content_center_bold(hdr_cells3[0], "Name") add_content_center(hdr_cells3[3], name) add_content_center_bold(hdr_cells3[6], "gender") add_content_center(hdr_cells3[7], gender) add_content_center_bold(hdr_cells3[10], 'student number') add_content_center(hdr_cells3[11], school_num) # The third line of content add_content_center_bold(hdr_cells6[0], "school time") add_content_center(hdr_cells6[3], school_time_year_month1 + "-" + school_time_year_month2) # Fourth line add_content_center_bold(hdr_cells9[0], "Home correspondence address") add_content_center(hdr_cells9[3], home_address) add_content_center_bold(hdr_cells9[7], "Family Contact Information") add_content_center(hdr_cells9[10], home_num) add_content_center_bold(table.rows[12].cells[7], "Personal contact information") add_content_center(table.rows[12].cells[10], personal_tel) # The fifth line add_content_center_bold(hdr_cells15[0], "Reason for my application") add_content_center(hdr_cells15[3], reason + "\ \ Signature of student\ \ \t\tYear\tMonth\tDay") # Line 6 # hdr_cells21[0].vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER add_content_center_bold(hdr_cells21[0], "Opinions of department leaders") add_content_center(hdr_cells21[3], "\ \ Leader's signature\ \ \t\tYear\tMonth\tDay") # Line 7 add_content_center_bold(hdr_cells27[0], "Opinions of the Student Affairs Office") add_content_center(hdr_cells27[3], "\ \ Leader's signature\ \ \t\tYear\tMonth\tDay") # Line 8 add_content_center_bold(hdr_cells32[0], "Approval by the school leader") add_content_center(hdr_cells32[3], "\ \ Leader's signature\ \ \t\tYear\tMonth\tDay") # document1 = Document('word template 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 template 1.docx with row and column marks") document.save("word template 1.docx")
Note: First create a table with 37 rows and 13 columns and write it into word, then use document1 = Document(‘word template 1.docx’) to open the document, and write the corresponding subscript in each cell, so that we can merge the units grid
result:
5. Add background color to the cell
The official pythondocx library still does not support this option. However, you can try to implement it yourself. The property you are looking for is called cell shading and is located under cell properties
Solution: Add the shading element (w:shd) to the cell property (w:tcPr)
Wrote a simple function that does the following:
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
Feel free to extend other properties if needed
So based on your example, once you have the table, before saving the document, add the following lines:
_set_cell_background(table.rows[0].cells[0], 'FF0000') doc. save("Testing. docx")