You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							181 lines
						
					
					
						
							6.3 KiB
						
					
					
				
			
		
		
	
	
							181 lines
						
					
					
						
							6.3 KiB
						
					
					
				import json
 | 
						|
import sys
 | 
						|
 | 
						|
from docx import Document
 | 
						|
from docx.shared import Inches
 | 
						|
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
 | 
						|
 | 
						|
def get_command_argv_by_sys():
 | 
						|
    # 默认值-用于测试
 | 
						|
    template_path = "template.docx"
 | 
						|
    #template_path = "test.docx"
 | 
						|
    filename_path = "demo.docx"
 | 
						|
    datafile_path = "data.json"
 | 
						|
    #datafile_path = "data_1.json"
 | 
						|
    cycle = 0
 | 
						|
    # 读取参数
 | 
						|
    number = len(sys.argv)
 | 
						|
    if 2 == number:
 | 
						|
        template_path = sys.argv[1]
 | 
						|
    if 3 == number:
 | 
						|
        template_path = sys.argv[1]
 | 
						|
        filename_path = sys.argv[2]
 | 
						|
    if 4 == number:
 | 
						|
        template_path = sys.argv[1]
 | 
						|
        filename_path = sys.argv[2]
 | 
						|
        datafile_path = sys.argv[3]
 | 
						|
    if 5 == number:
 | 
						|
        template_path = sys.argv[1]
 | 
						|
        filename_path = sys.argv[2]
 | 
						|
        datafile_path = sys.argv[3]
 | 
						|
        cycle = sys.argv[4]
 | 
						|
    return template_path, filename_path, datafile_path,cycle
 | 
						|
 | 
						|
 | 
						|
def read_data(filepath):
 | 
						|
    content = []
 | 
						|
    if filepath != "":
 | 
						|
        try:
 | 
						|
            with open(filepath, "r", encoding="utf-8") as file:
 | 
						|
                content = json.load(file)
 | 
						|
        finally:
 | 
						|
            return content
 | 
						|
 | 
						|
 | 
						|
def replace(template_path, filename_path, data_json):
 | 
						|
    try:
 | 
						|
        document_file = Document(template_path)
 | 
						|
    except:
 | 
						|
        return 2
 | 
						|
    # 段落替换
 | 
						|
    for paragraph in document_file.paragraphs:
 | 
						|
        for datum in data_json:
 | 
						|
            if datum["key"] in paragraph.text:
 | 
						|
                if "text" == datum["type"]:
 | 
						|
                    paragraph.text = paragraph.text.replace(datum["key"], datum["value"])
 | 
						|
                elif "picture" == datum["type"]:
 | 
						|
                    paragraph.clear()
 | 
						|
                    paragraph.add_run().add_picture(datum["value"], width=Inches(datum["width"]))
 | 
						|
                elif "number" == datum["type"]:
 | 
						|
                    paragraph.text = paragraph.text.replace(datum["key"], str(datum["value"]))
 | 
						|
 | 
						|
    # 表格替换
 | 
						|
    for table in document_file.tables:
 | 
						|
        # 字段
 | 
						|
        row = table.rows[0]
 | 
						|
        group = None
 | 
						|
        fields = []
 | 
						|
        for cell in row.cells:
 | 
						|
            split = cell.text.replace("}","").split(".")
 | 
						|
            group = split[0] + "}"
 | 
						|
            field = split[1]
 | 
						|
            fields.append(field.strip())
 | 
						|
 | 
						|
        # 替换
 | 
						|
        for datum in data_json:
 | 
						|
            if datum["key"] in group:
 | 
						|
                rows = len(table.rows)
 | 
						|
                values = datum["value"]
 | 
						|
                for z in range(0, len(values)):
 | 
						|
                    if z < rows:
 | 
						|
                       row = table.rows[z]
 | 
						|
                    else:
 | 
						|
                        row = table.add_row()
 | 
						|
 | 
						|
                    item = values[z]
 | 
						|
                    for i in range(0, len(fields)):
 | 
						|
                        field = fields[i]
 | 
						|
                        if item.get(field) is not None:
 | 
						|
                            row.cells[i].text = str(item.get(field))
 | 
						|
 | 
						|
    document_file.save(filename_path)
 | 
						|
    return 0
 | 
						|
 | 
						|
def foreach(template_path, filename_path, data_json):
 | 
						|
    try:
 | 
						|
        document_file = Document(template_path)
 | 
						|
    except:
 | 
						|
        return 2
 | 
						|
 | 
						|
    placeholder = []
 | 
						|
    loop = False
 | 
						|
    i = 0
 | 
						|
    for paragraph in document_file.paragraphs:
 | 
						|
        text = paragraph.text
 | 
						|
        if "$[" == text:
 | 
						|
            loop = True
 | 
						|
            paragraph.clear()
 | 
						|
            p = paragraph._element
 | 
						|
            p.getparent().remove(p)
 | 
						|
            p._p = p._element = None
 | 
						|
            continue
 | 
						|
        elif "]$" == text:
 | 
						|
            loop = False
 | 
						|
            paragraph.clear()
 | 
						|
            p = paragraph._element
 | 
						|
            p.getparent().remove(p)
 | 
						|
            p._p = p._element = None
 | 
						|
            z = 0
 | 
						|
            for datum in data_json:
 | 
						|
                for item in placeholder:
 | 
						|
                    key = item["paragraph"].text.replace("{", "").replace("}", "")
 | 
						|
                    style = item["paragraph"].style
 | 
						|
                    if key == datum["key"]:
 | 
						|
                        if "text" == datum["type"]:
 | 
						|
                            paragraph = document_file.add_paragraph(datum["value"], style=style)
 | 
						|
                            paragraph._element.getparent().insert(z, paragraph._element)
 | 
						|
                        elif "picture" == datum["type"]:
 | 
						|
                            paragraph = document_file.add_paragraph(style=style)
 | 
						|
                            paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
 | 
						|
                            paragraph.add_run().add_picture(datum["value"], width=Inches(datum["width"]))
 | 
						|
                            paragraph._element.getparent().insert(z, paragraph._element)
 | 
						|
                        elif "number" == datum["type"]:
 | 
						|
                            paragraph = document_file.add_paragraph(str(datum["value"]), style=style)
 | 
						|
                            paragraph._element.getparent().insert(z, paragraph._element)
 | 
						|
                    # else:
 | 
						|
                    #     paragraph = document_file.add_paragraph(item["text"], style=style)
 | 
						|
                    #     paragraph._element.getparent().insert(z, paragraph._element)
 | 
						|
                z += 1
 | 
						|
 | 
						|
            placeholder = []
 | 
						|
 | 
						|
 | 
						|
 | 
						|
        if loop:
 | 
						|
            placeholder.append({"paragraph": paragraph, "key": text.replace("{", "").replace("}", ""), "style": paragraph.style,"text":text, "index": i})
 | 
						|
            p = paragraph._element
 | 
						|
            p.getparent().remove(p)
 | 
						|
            p._p = p._element = None
 | 
						|
        else:
 | 
						|
            if text.startswith("{") and text.endswith("}"):
 | 
						|
                for datum in data_json:
 | 
						|
                    if datum["key"] in text:
 | 
						|
                        key = "{" + datum["key"] + "}"
 | 
						|
                        if "text" == datum["type"]:
 | 
						|
                            paragraph.text = paragraph.text.replace(key, datum["value"])
 | 
						|
                        elif "picture" == datum["type"]:
 | 
						|
                            paragraph.clear()
 | 
						|
                            paragraph.add_run().add_picture(datum["value"], width=Inches(datum["width"]))
 | 
						|
                        elif "number" == datum["type"]:
 | 
						|
                            paragraph.text = paragraph.text.replace(key, str(datum["value"]))
 | 
						|
        i += 1
 | 
						|
 | 
						|
    document_file.save(filename_path)
 | 
						|
    return 0
 | 
						|
 | 
						|
 | 
						|
def main():
 | 
						|
    params = get_command_argv_by_sys()
 | 
						|
    [template, filename, datafile, cycle] = params
 | 
						|
    data = read_data(datafile)
 | 
						|
    if len(data) == 0:
 | 
						|
        return 1
 | 
						|
    else:
 | 
						|
        if cycle == 0:
 | 
						|
            return replace(template, filename, data)
 | 
						|
        else:
 | 
						|
            return foreach(template, filename, data)
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    print(main())
 |