| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- # -*- coding: utf-8 -*-
- import sys
- from docx import Document
- from docx.shared import Pt, Cm, RGBColor
- from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_LINE_SPACING
- from docx.enum.table import WD_TABLE_ALIGNMENT
- from docx.enum.section import WD_SECTION
- from docx.oxml.ns import qn
- from docx.oxml import OxmlElement
- import docx.opc.constants
- sys.stdout.reconfigure(encoding="utf-8")
- OUT = r"C:\Users\aroun\Desktop\在线考试系统\在线考试系统开源方案调研与论文写作参考.docx"
- doc = Document()
- # ---------- page setup ----------
- sec = doc.sections[0]
- sec.page_width = Cm(21.0)
- sec.page_height = Cm(29.7)
- sec.top_margin = Cm(2.54)
- sec.bottom_margin = Cm(2.54)
- sec.left_margin = Cm(2.8)
- sec.right_margin = Cm(2.8)
- TEXT_W = 21.0 - 2.8 * 2 # 15.4 cm
- # ---------- styles ----------
- def set_cn_font(style_or_run, name_cn, name_ascii=None, size=None, bold=None, color=None):
- f = style_or_run.font
- f.name = name_ascii or name_cn
- if size is not None:
- f.size = Pt(size)
- if bold is not None:
- f.bold = bold
- if color is not None:
- f.color.rgb = color
- el = style_or_run.element if hasattr(style_or_run, "element") else style_or_run._element
- rPr = el.get_or_add_rPr()
- rFonts = rPr.find(qn("w:rFonts"))
- if rFonts is None:
- rFonts = OxmlElement("w:rFonts")
- rPr.append(rFonts)
- rFonts.set(qn("w:ascii"), name_ascii or name_cn)
- rFonts.set(qn("w:hAnsi"), name_ascii or name_cn)
- rFonts.set(qn("w:eastAsia"), name_cn)
- normal = doc.styles["Normal"]
- set_cn_font(normal, "宋体", "Times New Roman", 10.5)
- normal.paragraph_format.line_spacing_rule = WD_LINE_SPACING.ONE_POINT_FIVE
- normal.paragraph_format.space_before = Pt(0)
- normal.paragraph_format.space_after = Pt(4)
- BLACK = RGBColor(0, 0, 0)
- h1 = doc.styles["Heading 1"]
- set_cn_font(h1, "黑体", "Times New Roman", 16, True, BLACK)
- h1.paragraph_format.space_before = Pt(18)
- h1.paragraph_format.space_after = Pt(8)
- h2 = doc.styles["Heading 2"]
- set_cn_font(h2, "黑体", "Times New Roman", 13, True, BLACK)
- h2.paragraph_format.space_before = Pt(14)
- h2.paragraph_format.space_after = Pt(6)
- h3 = doc.styles["Heading 3"]
- set_cn_font(h3, "黑体", "Times New Roman", 11, True, BLACK)
- h3.paragraph_format.space_before = Pt(10)
- h3.paragraph_format.space_after = Pt(4)
- # ---------- helpers ----------
- def add_hyperlink(paragraph, url, text, size=9, bold=False):
- part = paragraph.part
- r_id = part.relate_to(url, docx.opc.constants.RELATIONSHIP_TYPE.HYPERLINK, is_external=True)
- hyperlink = OxmlElement("w:hyperlink")
- hyperlink.set(qn("r:id"), r_id)
- new_run = OxmlElement("w:r")
- rPr = OxmlElement("w:rPr")
- rFonts = OxmlElement("w:rFonts")
- rFonts.set(qn("w:ascii"), "Consolas")
- rFonts.set(qn("w:hAnsi"), "Consolas")
- rFonts.set(qn("w:eastAsia"), "宋体")
- rPr.append(rFonts)
- sz = OxmlElement("w:sz"); sz.set(qn("w:val"), str(int(size * 2))); rPr.append(sz)
- szcs = OxmlElement("w:szCs"); szcs.set(qn("w:val"), str(int(size * 2))); rPr.append(szcs)
- if bold:
- b = OxmlElement("w:b"); rPr.append(b)
- color = OxmlElement("w:color"); color.set(qn("w:val"), "1F4E79"); rPr.append(color)
- u = OxmlElement("w:u"); u.set(qn("w:val"), "single"); rPr.append(u)
- new_run.append(rPr)
- t = OxmlElement("w:t")
- t.text = text
- t.set(qn("xml:space"), "preserve")
- new_run.append(t)
- hyperlink.append(new_run)
- paragraph._p.append(hyperlink)
- return hyperlink
- def shade(cell, hexcolor):
- tcPr = cell._tc.get_or_add_tcPr()
- shd = OxmlElement("w:shd")
- shd.set(qn("w:val"), "clear")
- shd.set(qn("w:color"), "auto")
- shd.set(qn("w:fill"), hexcolor)
- tcPr.append(shd)
- def cell_margins(table, top=60, bottom=60, left=90, right=90):
- tblPr = table._tbl.tblPr
- mar = OxmlElement("w:tblCellMar")
- for tag, val in (("top", top), ("left", left), ("bottom", bottom), ("right", right)):
- el = OxmlElement("w:" + tag)
- el.set(qn("w:w"), str(val))
- el.set(qn("w:type"), "dxa")
- mar.append(el)
- tblPr.append(mar)
- def repeat_header(row):
- trPr = row._tr.get_or_add_trPr()
- el = OxmlElement("w:tblHeader")
- el.set(qn("w:val"), "true")
- trPr.append(el)
- def cant_split(row):
- trPr = row._tr.get_or_add_trPr()
- el = OxmlElement("w:cantSplit")
- el.set(qn("w:val"), "true")
- trPr.append(el)
- def set_cell_text(cell, text, size=9, bold=False, align=None, color=None):
- cell.text = ""
- p = cell.paragraphs[0]
- p.paragraph_format.line_spacing_rule = WD_LINE_SPACING.SINGLE
- p.paragraph_format.space_before = Pt(0)
- p.paragraph_format.space_after = Pt(0)
- if align is not None:
- p.alignment = align
- run = p.add_run(text)
- set_cn_font(run, "宋体", "Times New Roman", size, bold, color)
- def make_table(headers, rows, widths, link_col=None, font=8.5, head_font=8.5):
- table = doc.add_table(rows=1, cols=len(headers))
- table.style = "Table Grid"
- table.alignment = WD_TABLE_ALIGNMENT.CENTER
- table.autofit = False
- cell_margins(table)
- hdr = table.rows[0]
- repeat_header(hdr)
- cant_split(hdr)
- for i, h in enumerate(headers):
- c = hdr.cells[i]
- c.width = Cm(widths[i])
- shade(c, "D9D9D9")
- set_cell_text(c, h, head_font, True, WD_ALIGN_PARAGRAPH.CENTER)
- for r in rows:
- row = table.add_row()
- cant_split(row)
- for i, val in enumerate(r):
- c = row.cells[i]
- c.width = Cm(widths[i])
- if link_col is not None and i == link_col:
- c.text = ""
- p = c.paragraphs[0]
- p.paragraph_format.line_spacing_rule = WD_LINE_SPACING.SINGLE
- p.paragraph_format.space_before = Pt(0)
- p.paragraph_format.space_after = Pt(0)
- add_hyperlink(p, val[1], val[0], size=font - 0.5)
- else:
- set_cell_text(c, val, font)
- # force column widths on every cell (Word honours cell-level w)
- for row in table.rows:
- for i, c in enumerate(row.cells):
- c.width = Cm(widths[i])
- return table
- def para(text, size=10.5, bold=False, indent=True, space_after=4, align=None, color=None, first_indent=True):
- p = doc.add_paragraph()
- p.paragraph_format.space_after = Pt(space_after)
- if align is not None:
- p.alignment = align
- if indent and first_indent:
- p.paragraph_format.first_line_indent = Pt(21)
- run = p.add_run(text)
- set_cn_font(run, "宋体", "Times New Roman", size, bold, color)
- return p
- def bullet(text, size=10.5, level=0):
- p = doc.add_paragraph(style="List Bullet")
- p.paragraph_format.left_indent = Cm(0.75 + 0.6 * level)
- p.paragraph_format.first_line_indent = Cm(-0.4)
- p.paragraph_format.space_after = Pt(2)
- run = p.add_run(text)
- set_cn_font(run, "宋体", "Times New Roman", size)
- return p
- def numitem(n, title, text, size=10.5):
- p = doc.add_paragraph()
- p.paragraph_format.space_after = Pt(4)
- p.paragraph_format.left_indent = Cm(0.75)
- p.paragraph_format.first_line_indent = Cm(-0.75)
- r1 = p.add_run("%s " % n)
- set_cn_font(r1, "宋体", "Times New Roman", size, True)
- r2 = p.add_run(title)
- set_cn_font(r2, "黑体", "Times New Roman", size, True)
- if text:
- r3 = p.add_run(text)
- set_cn_font(r3, "宋体", "Times New Roman", size)
- return p
- def caption(text):
- p = doc.add_paragraph()
- p.alignment = WD_ALIGN_PARAGRAPH.CENTER
- p.paragraph_format.space_before = Pt(6)
- p.paragraph_format.space_after = Pt(3)
- run = p.add_run(text)
- set_cn_font(run, "黑体", "Times New Roman", 9, True)
- return p
- def note(text):
- p = doc.add_paragraph()
- p.paragraph_format.space_before = Pt(2)
- p.paragraph_format.space_after = Pt(10)
- p.paragraph_format.left_indent = Cm(0.2)
- run = p.add_run(text)
- set_cn_font(run, "楷体", "Times New Roman", 9.5, False, RGBColor(0x40, 0x40, 0x40))
- return p
- def quote_block(lines):
- for ln in lines:
- p = doc.add_paragraph()
- p.paragraph_format.left_indent = Cm(0.9)
- p.paragraph_format.right_indent = Cm(0.4)
- p.paragraph_format.space_after = Pt(4)
- p.paragraph_format.line_spacing_rule = WD_LINE_SPACING.ONE_POINT_FIVE
- run = p.add_run(ln)
- set_cn_font(run, "楷体", "Times New Roman", 10)
- return
- # footer page number
- footer = sec.footer
- fp = footer.paragraphs[0]
- fp.alignment = WD_ALIGN_PARAGRAPH.CENTER
- run = fp.add_run()
- fld1 = OxmlElement("w:fldChar"); fld1.set(qn("w:fldCharType"), "begin")
- instr = OxmlElement("w:instrText"); instr.set(qn("xml:space"), "preserve"); instr.text = " PAGE "
- fld2 = OxmlElement("w:fldChar"); fld2.set(qn("w:fldCharType"), "end")
- run._r.append(fld1); run._r.append(instr); run._r.append(fld2)
- set_cn_font(run, "宋体", "Times New Roman", 9)
- print("setup ok")
- doc.save(OUT)
- print("saved skeleton")
|