完成标题分级样式配置,添加横向页面,设计添加金风图片表格的函数。更改某些函数的样式获取等。

This commit is contained in:
Voge1imkafig 2025-07-31 18:10:56 +08:00
parent 8402a2cb7f
commit 78ab1e3962
14 changed files with 445 additions and 86 deletions

View File

@ -31,7 +31,7 @@ def main():
elif merged['json2']['choose_template'] == 'JF':
asyncio.run(generate_jf_report(merged['json1'], merged['json2']))
else:
print('指定了不存在的,请检查配置文件')
print('指定了不存在的模板,请检查配置文件')
print('文档生成完毕')
if __name__ == '__main__':

View File

@ -1,15 +1,15 @@
# 文档处理工具
from tools.document_tools import (
create_document, add_documents,add_table_and_replace,
add_table_to_document,add_dynamic_table,
add_table_to_document,add_dynamic_table,add_section,
process_server_images_table,add_header,add_landscape_section,
merge_documents,add_table,add_defect_info_table,add_table_title
merge_documents,add_table,add_defect_info_table,add_table_title,
add_title,change_heading,add_auto_toc_at_end
)
# 内容处理工具
from tools.content_tools import (
add_picture,split_table_by_row_content,
search_and_replace
search_and_replace,add_heading
)
from tools.get_pictures import (
@ -146,6 +146,7 @@ async def generate_jf_report(base_info, baogao_info):
neirong2 = []
use_tool_table = []
table_index = 1
typical_picture_description = []
#获取对应枚举字段
if if_waibu:
baogao_label.append("外观")
@ -166,6 +167,7 @@ async def generate_jf_report(base_info, baogao_info):
jiancha.append("无人机外观检查")
neirong.append(f"".join(Y_Code) + f"{len(Y_Code)}支叶片的前缘、后缘、迎风面、背风面。")
neirong2.append("前缘、后缘、迎风面、背风面。")
typical_picture_description.extend(TEMPLATE_HEADER.JINFENG_HEADER.WAIBU.TYPICAL_LIST)
if if_neibu:
baogao_label.append("内部")
image_source_to_find.append(baogao_info['neibu_enum'])
@ -184,6 +186,7 @@ async def generate_jf_report(base_info, baogao_info):
jiancha.append("叶片内部检查")
neirong.append(f"".join(Y_Code) + f"{len(Y_Code)}支叶片的内部导雷卡、腹板、透光、人孔盖版、叶根盖板...")
neirong2.append("内部导雷卡、腹板、透光、人孔盖版、叶根盖板...")
typical_picture_description.extend(TEMPLATE_HEADER.JINFENG_HEADER.NEIBU.TYPICAL_LIST)
if if_fanglei:
baogao_label.append("防雷")
image_source_to_find.append(baogao_info['fanglei_enum'])
@ -202,7 +205,8 @@ async def generate_jf_report(base_info, baogao_info):
jiancha.append("叶片导通测试")
neirong.append(f"轮毂至塔基导通、内部导线线阻、外部导线线阻...")
neirong2.append("轮毂至塔基导通、内部导线线阻、外部导线线阻...")
typical_picture_description.extend(TEMPLATE_HEADER.JINFENG_HEADER.FANGLEI.TYPICAL_LIST)
#获取缺陷图列表和典型图列表
filtered_picture_data, total_picture_num = process_picture_data(picture_data, image_source_to_find)
#获取所有缺陷记录
@ -223,7 +227,8 @@ async def generate_jf_report(base_info, baogao_info):
if not os.path.exists(shengcheng_dir):
print(f"生成路径{shengcheng_dir}不存在")
return
baogao_name = "叶片" + "".join(baogao_label) + "检查报告"
output_dir = os.path.normpath(f"{shengcheng_dir}/{project_name}项目{baogao_name}{jizu_bianhao}{baogao_date.split(' ')[0]}版.docx")
@ -254,6 +259,10 @@ async def generate_jf_report(base_info, baogao_info):
"top_margin" : JF_T_MARGIN,
"bottom_margin" : JF_B_MARGIN,
}))
#标题样式
change_heading(output_dir, "Heading 1")
change_heading(output_dir, "Heading 2", HEADING_2_CONFIG)
change_heading(output_dir, "Heading 3", HEADING_3_CONFIG)
#加封面
merge_documents(output_dir, add_list)
#页眉
@ -299,14 +308,55 @@ async def generate_jf_report(base_info, baogao_info):
#缺陷信息表格2
table_list = tree_dict_to_table_data(defect_part_type_list)
table_list = defect_list_addtitle(table_list, jizu_bianhao)
print(table_list)
add_table_title(output_dir, DEFECT_TABLE_TITLE)
table_json = list_to_json_with_merges(table_list, style_config=STYLE_CONFIG, merge_columns=2)
json_to_docx(table_json, output_dir).save(output_dir)
table_list = tree_dict_to_table_data(defect_part_type_list) # 服务器获取的树形结构转化为表格数据
table_list = defect_list_addtitle(table_list, jizu_bianhao) # 增加每列标题,机组
add_table_title(output_dir, DEFECT_TABLE_TITLE) # 增加表格标题
table_json = list_to_json_with_merges(table_list, style_config=STYLE_CONFIG, merge_columns=2) #将list转换为json形式前两列检查相同合并
json_to_docx(table_json, output_dir).save(output_dir) #jsontodocx
#使用器具记录表
add_table_title(output_dir, USE_TOOL_TABLE_TITLE)
print(use_tool_table)
json_to_docx(list_to_json_with_merges(use_tool_table, style_config=STYLE_CONFIG, detect_merges=False),output_dir).save(output_dir)
add_table_title(output_dir, USE_TOOL_TABLE_TITLE)
json_to_docx(list_to_json_with_merges(use_tool_table, style_config=STYLE_CONFIG, detect_merges=False),output_dir).save(output_dir)
#添加目录节
add_section(output_dir).save(output_dir)
#添加目录
#add_auto_toc_at_end(output_dir)
#添加横向节(展示图片)
add_landscape_section(output_dir).save(output_dir)
print(add_heading(output_dir, f"1. 机组号:{jizu_bianhao}", 1))
print(add_heading(output_dir, f"1.1 叶片编号:{Y_Code[0]}", 2))
#add_header(output_dir, TEMPLATE_HEADER.JINFENG_HEADER.ENUM, if_section=False, text = " " + TEMPLATE_HEADER.JINFENG_HEADER.PARA)
add_table_to_document(
output_dir,
get_resource_path(MUBAN_DIR + '/jfempty.docx'),
3,
5,
total_table_num,
if_merge=False,
Report_Enum=TEMPLATE_HEADER.JINFENG_HEADER.ENUM,
if_para=False
)
"""
典型图片dict 典型图片的描述固定
{
图片描述 : 图片地址, #情况一
描述部位缺陷数量 : 缺陷类型数量, #情况二
...
}
缺陷图片dict 缺陷图片的描述从信息来源获取
{
图片描述 : 图片地址,
}
"""
typical_picture_list = []
typical_picture_dict = {}
for description, url in zip(typical_picture_description, typical_picture_list):
typical_picture_dict[description] = url
print(typical_picture_dict)
defect_picture_dict = {}

View File

@ -116,6 +116,21 @@ def copy_table(source_table, target_doc, ifadjustheight=True, height = 1, if_mer
"""
# Create a new table with the same dimensions
new_table = target_doc.add_table(rows=len(source_table.rows), cols=len(source_table.columns))
# 获取表格属性
tbl_pr = new_table._tbl.tblPr
# 设置表格边框
tbl_borders = OxmlElement('w:tblBorders')
for border_name in ('top', 'left', 'bottom', 'right', 'insideH', 'insideV'):
border = OxmlElement(f'w:{border_name}')
border.set(qn('w:val'), 'single') # 边框类型
border.set(qn('w:sz'), '4') # 边框粗细(1-968代表1磅)
border.set(qn('w:space'), '0') # 边框间距
border.set(qn('w:color'), 'auto') # 边框颜色
tbl_borders.append(border)
tbl_pr.append(tbl_borders)
# Try to apply the same style
try:
if source_table.style:
@ -145,7 +160,7 @@ def copy_table(source_table, target_doc, ifadjustheight=True, height = 1, if_mer
#new_table.cell(i,j).width = cell.width
if REPORT_ENUM == 'JF':
new_table.cell(i,j).paragraphs[0].runs[0]._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体') #设置中文字体
new_table.cell(i,j).paragraphs[0].runs[0].font.size = Pt(12) # 字体大小
new_table.cell(i,j).paragraphs[0].runs[0].font.size = Pt(8) # 字体大小
"""
待添加如何让表格自适应大小autofit目前不知为何没有作用
"""

BIN
muban/jfempty.docx Normal file

Binary file not shown.

117
test.py Normal file
View File

@ -0,0 +1,117 @@
from typing import Dict
import os
from docx import Document
from tools.document_tools import add_picture_to_table, add_table_to_document
def add_jf_picture_table(
typical_picture_dict: Dict[str, str],
defect_picture_dict: Dict[str, str],
TYPICAL_MUBAN_DIR: str,
DEFECT_MUBAN_DIR: str,
output_dir: str,
):
"""添加金风版本的图片展示表格"""
# 初始化文档对象
doc = Document()
target_filename = os.path.join(output_dir, "output.docx")
# 处理典型图
typical_data = []
defect_keys = [] # 记录有缺陷的典型图key
# 准备典型图数据
for key, value in typical_picture_dict.items():
if "损伤" in key or "损伤" in value:
# 情况二:有缺陷
defect_count = int(value.split("损伤类型")[1].split("")[0])
typical_data.append([key, "损伤{}处,详见下表".format(defect_count), value])
defect_keys.append((key, defect_count))
else:
# 情况一:正常图片
typical_data.append([key, value, ""]) # 第三行留空
# 添加典型图表格
if typical_data:
# 将数据转换为适合表格的格式3行×n列
# 需要将数据从行优先转为列优先
cols = len(typical_data)
table_data = [[], [], []]
for col_data in typical_data:
for i in range(3):
table_data[i].append(col_data[i] if i < len(col_data) else "")
# 添加典型图表格
add_table_to_document(
target_filename=target_filename,
source_filename=TYPICAL_MUBAN_DIR,
rows=3,
cols=cols,
table_num=0,
data=table_data
)
# 添加典型图中的图片
doc = Document(target_filename)
for col_idx, (key, value) in enumerate(typical_picture_dict.items()):
if "损伤" not in key and "损伤" not in value: # 只有正常图片才添加
add_picture_to_table(
target_doc=doc,
target_filename=target_filename,
row=1, # 第二行是图片
col=col_idx,
image_path=value
)
doc.save(target_filename)
# 处理缺陷图
if defect_keys:
# 遍历所有有缺陷的典型图
for typical_key, defect_count in defect_keys:
# 计算需要多少个缺陷图表格每表5列
table_count = (defect_count + 4) // 5 # 向上取整
for table_idx in range(table_count):
# 计算当前表格的列数
cols_in_table = min(5, defect_count - table_idx * 5)
# 准备缺陷图数据
defect_data = []
for i in range(cols_in_table):
defect_idx = table_idx * 5 + i
defect_key = list(defect_picture_dict.keys())[defect_idx]
defect_value = list(defect_picture_dict.values())[defect_idx]
defect_data.append([defect_key, defect_value])
# 将数据转换为适合表格的格式2行×n列
table_data = [[], []]
for col_data in defect_data:
for i in range(2):
table_data[i].append(col_data[i] if i < len(col_data) else "")
# 添加缺陷图表格
add_table_to_document(
target_filename=target_filename,
source_filename=DEFECT_MUBAN_DIR,
rows=2,
cols=cols_in_table,
table_num=0,
data=table_data
)
# 添加缺陷图中的图片
doc = Document(target_filename)
for col_idx in range(cols_in_table):
defect_idx = table_idx * 5 + col_idx
defect_value = list(defect_picture_dict.values())[defect_idx]
add_picture_to_table(
target_doc=doc,
target_filename=target_filename,
row=1, # 第二行是图片
col=col_idx,
image_path=defect_value
)
doc.save(target_filename)
return target_filename
add_jf_picture_table({""})

View File

@ -138,7 +138,7 @@ def split_table_by_row_content(
return f"处理表格时出错: {str(e)}"
async def add_heading(filename: str, text: str, level: int = 1) -> str:
def add_heading(filename: str, text: str, level: int = 1) -> str:
"""对文档增加标题
Args:
@ -179,10 +179,10 @@ async def add_heading(filename: str, text: str, level: int = 1) -> str:
doc.save(filename)
return f"Heading '{text}' (level {level}) added to {filename}"
except Exception as style_error:
print("style-based approach fails, use direct formatting")
# If style-based approach fails, use direct formatting
paragraph = doc.add_paragraph(text)
paragraph.style = doc.styles['Normal']
run = paragraph.runs[0]
paragraph = doc.add_paragraph()
run = paragraph.add_run(text)
run.bold = True
rPr = run.element.get_or_add_rPr()
rFonts = rPr.get_or_add_rFonts()
@ -657,3 +657,38 @@ def search_and_replace(filename: str, find_text: str, replace_text: str) -> str:
except Exception as e:
return f"Failed to search and replace: {str(e)}"
def add_jf_picture_table(
typical_picture_dict : dict,
defect_picture_dict : dict,
TYPICAL_MUBAN_DIR : str,
DEFECT_MUBAN_DIR : str,
output_dir : str,
):
"""添加金风版本的图片展示表格
逻辑
典型图模板是三行五列的表格一列对应一张典型图图片信息
缺陷图模板是二行五列的表格一列对应一张缺陷图图片信息
1.每次循环添加一次典型图片
第一行为dict的key
第二行为图片如有缺陷则不是图片url而是字符串 损伤n处详见下表此时要有变量记录总损伤数
第三行看情况如果正常则保持默认如果有缺陷则字段为 损伤类型n处
2.如果上一次循环没有缺陷图则回到1否则前往3
3.如果上一次循环中有缺陷图存在则进入对应的缺陷图添加模式,使用缺陷图表格模板
根据上一行每列的总缺陷数遍历缺陷字典
当缺陷数大于5时也要调用模板进行下一行的添加
缺陷图表格使用缺陷图模板第一行为defect_picture_dict的key第二行为图片url第三行为损伤类型
Args:
typical_picture_dict: #有两种情况
{
str(图片描述) : str(图片地址), #情况一
str(损伤有n处见下表) : str({缺陷类型}n处), #情况二
...
}
defect_picture_dict: #只有一种情况
{
str(图片描述) : str(图片地址),
}
TYPICAL_MUBAN_DIR: 典型图模板路径
DEFECT_MUBAN_DIR: 缺陷图模板路径
"""

View File

@ -67,6 +67,28 @@ class TEMPLATE_HEADER:
QN = qn('w:eastAsia')
FONT = 'Arial'
PT = Pt(9)
class FANGLEI:
TYPICAL_LIST = [
"防雷导通测试\n叶尖至塔基测试阻值({Resistance}",
"防雷导通测试\n叶尖与无人吊篮平台接触良好",
"防雷导通测试\n叶尖至塔基检测导线线组值"
]
class WAIBU:
TYPICAL_LIST = [
"外观检查(迎、背风面是否有漆面脱落、裂纹等)",
"外观检查(前、后缘;如前缘漆面脱落、合模缝开裂等)",
"叶片防雨环检查",
"叶尖接闪器、排水孔检查,如接闪器损伤、雷击熔融;流水孔堵塞",
]
class NEIBU:
TYPICAL_LIST = [
"叶片铭牌",
"根部检查(挡板、盖板检查是否损坏、金属件是否丢失等)",
"避雷系统检查(避雷线是否断裂、雷电记录卡是否缺失等)",
"前后缘检查(前缘粘接及补强是否有开裂、裂纹)",
"上下蒙皮检查(蒙皮是否有褶皱、发白、折痕、分层、裂纹等)",
"腹板检查(腹板是否变形、偏移,腹板粘接是否开裂、裂纹等)",
]
class DT_HEADER:
ENUM = 'DT'
@ -92,7 +114,7 @@ STYLE_CONFIG = {
"alignment": "center",
"font": {
"name": "宋体",
"size": 12,
"size": 8,
"bold": False,
},
"border": {
@ -109,7 +131,7 @@ TITLE_STYLE_CONFIG = {
"alignment": "center",
"font": {
"name": "宋体",
"size": 12,
"size": 9,
"bold": False,
},
"border": {
@ -122,6 +144,8 @@ TITLE_STYLE_CONFIG = {
"color": "FFFFFF"
}
}
DEFECT_TABLE_TITLE = '叶片故障信息表'
DEFECT_TABLE = ['机组号', '叶片编号', '损伤名称', '损坏描述', '面积/S', '备注']
@ -147,4 +171,65 @@ class USE_TOOL_ENUM:
["活动扳手", "17-19", "2", "拆卸·禁锢盖板螺栓"],
["手机", "/", "2", "拍照记录"],
["叶片内部爬壁机器人", "DT02", "1", "拍照记录"]
]
]
from enum import Enum
from docx.shared import RGBColor
class DocxColors(Enum):
"""常用颜色枚举"""
BLACK = RGBColor(0, 0, 0)
WHITE = RGBColor(255, 255, 255)
RED = RGBColor(255, 0, 0)
GREEN = RGBColor(0, 255, 0)
BLUE = RGBColor(0, 0, 255)
YELLOW = RGBColor(255, 255, 0)
PURPLE = RGBColor(128, 0, 128)
ORANGE = RGBColor(255, 165, 0)
GRAY = RGBColor(128, 128, 128)
DARK_RED = RGBColor(139, 0, 0)
DARK_GREEN = RGBColor(0, 100, 0)
DARK_BLUE = RGBColor(0, 0, 139)
LIGHT_BLUE = RGBColor(173, 216, 230)
PINK = RGBColor(255, 192, 203)
BROWN = RGBColor(165, 42, 42)
# 微软Office常用颜色
MS_BLUE = RGBColor(46, 116, 181)
MS_ORANGE = RGBColor(247, 150, 70)
MS_GREEN = RGBColor(80, 175, 74)
MS_RED = RGBColor(217, 83, 79)
MS_GRAY = RGBColor(166, 166, 166)
# 获取颜色值
@property
def rgb(self):
return self.value
HEADING_1_CONFIG = {
"alignment": "left",
"font" : {
"name" : "宋体",
"size" : Pt(11),
"bold" : True,
"color" : DocxColors.BLACK.rgb
},
}
HEADING_2_CONFIG = {
"alignment": "left",
"font" : {
"name" : "宋体",
"size" : Pt(10),
"bold" : True,
"color" : DocxColors.BLACK.rgb
},
}
HEADING_3_CONFIG = {
"alignment": "left",
"font" : {
"name" : "宋体",
"size" : Pt(9),
"bold" : True,
"color" : DocxColors.BLACK.rgb
},
}

View File

@ -219,6 +219,7 @@ def write_table(target_filename: str, rows: int, cols: int, table_num: int, data
data: 表格数据二维列表每个单元格为字符串
ifadjustheight: bool为真则表格行高自动调整
"""
table_num = -1
target_filename = ensure_docx_extension(target_filename)
# Check if target file is writeable
is_writeable, error_message = check_file_writeable(target_filename)
@ -289,7 +290,7 @@ def set_document_para(target_doc: Document) -> Document:
return target_doc
def add_table_to_document(target_filename: str, source_filename: str, rows: int, cols: int, table_num: int, data: Optional[List[List[str]]] = None, ifadjustheight: Optional[bool] = True, height: Optional[float] = 1, key_words: re.Pattern[str] = None, ALIGMENT: Optional[str] = 'CENTER') -> str:
def add_table_to_document(target_filename: str, source_filename: str, rows: int, cols: int, table_num: int, data: Optional[List[List[str]]] = None, ifadjustheight: Optional[bool] = True, height: Optional[float] = 1, key_words: re.Pattern[str] = None, ALIGMENT: Optional[str] = 'CENTER', if_merge : Optional[bool] = True, Report_Enum = 'DT', if_para : Optional[bool] = True) -> str:
"""复制源文件中的文字与表格(先文字后表格格式)到目标文档
Args:
target_filename: 目标文档路径
@ -305,62 +306,59 @@ def add_table_to_document(target_filename: str, source_filename: str, rows: int,
source_filename = ensure_docx_extension(source_filename)
source_doc = Document(source_filename)
target_doc = Document(target_filename)
target_doc.add_paragraph()
try:
# Copy all paragraphs
for paragraph in source_doc.paragraphs:
# Create a new paragraph with the same text and style
new_paragraph = target_doc.add_paragraph(paragraph.text)
new_paragraph.style = target_doc.styles['Normal'] # Default style
#获取合并等样式2025427
new_paragraph.alignment = paragraph.alignment
if if_para:
try:
# Copy all paragraphs
for paragraph in source_doc.paragraphs:
# Create a new paragraph with the same text and style
new_paragraph = target_doc.add_paragraph(paragraph.text)
new_paragraph.style = target_doc.styles['Normal'] # Default style
#获取合并等样式2025427
new_paragraph.alignment = paragraph.alignment
# 复制段落分页属性
new_paragraph.paragraph_format.page_break_before = paragraph.paragraph_format.page_break_before
# Try to match the style if possible
try:
if paragraph.style and paragraph.style.name in target_doc.styles:
new_paragraph.style = target_doc.styles[paragraph.style.name]
except:
pass
# Copy run formatting
for i, run in enumerate(paragraph.runs):
if i < len(new_paragraph.runs):
new_run = new_paragraph.runs[i]
# Copy basic formatting
new_run.bold = run.bold
new_run.italic = run.italic
new_run.underline = run.underline
#添加同时合并字体2025427
new_run.font.name = run.font.name
rPr = new_run.element.get_or_add_rPr()
rFonts = rPr.get_or_add_rFonts()
# 检查 run.font.name 是否为 None
if run.font.name is None:
# 设置默认的中文字体名称
run.font.name = '宋体(中文正文)' # 或者使用其他你喜欢的中文字体
rFonts.set(qn('w:eastAsia'), run.font.name)
new_run.font.color.rgb = run.font.color.rgb
# 复制段落分页属性
new_paragraph.paragraph_format.page_break_before = paragraph.paragraph_format.page_break_before
# Try to match the style if possible
try:
if paragraph.style and paragraph.style.name in target_doc.styles:
new_paragraph.style = target_doc.styles[paragraph.style.name]
except:
pass
# Copy run formatting
for i, run in enumerate(paragraph.runs):
if i < len(new_paragraph.runs):
new_run = new_paragraph.runs[i]
# Copy basic formatting
new_run.bold = run.bold
new_run.italic = run.italic
new_run.underline = run.underline
#添加同时合并字体2025427
new_run.font.name = run.font.name
rPr = new_run.element.get_or_add_rPr()
rFonts = rPr.get_or_add_rFonts()
# 检查 run.font.name 是否为 None
if run.font.name is None:
# 设置默认的中文字体名称
run.font.name = '宋体(中文正文)' # 或者使用其他你喜欢的中文字体
rFonts.set(qn('w:eastAsia'), run.font.name)
new_run.font.color.rgb = run.font.color.rgb
# Font size if specified
if run.font.size:
new_run.font.size = run.font.size
# Font size if specified
if run.font.size:
new_run.font.size = run.font.size
except Exception as e:
print(f"添加表格前文章失败:{str(e)}")
except Exception as e:
print(f"添加表格前文章失败:{str(e)}")
try:# Copy all tables
copy_table(source_doc.tables[0], target_doc, ifadjustheight, height)
copy_table(source_doc.tables[0], target_doc, ifadjustheight, height, if_merge, REPORT_ENUM=Report_Enum)
except Exception as e:
print(f"添加表格失败:{str(e)}")
print(f"{target_doc}写入表格{source_doc.tables[0]}成功")
target_doc = set_document_para(target_doc)
target_doc.save(target_filename)
target_doc = Document(target_filename)
if data:
try:
target_doc = write_table(target_filename, rows, cols, table_num, data, ifadjustheight, height, key_words, ALIGMENT)
@ -755,7 +753,7 @@ async def process_server_images_table(data_list, image_source_list, output_dir,
print(message)
return i # 返回最后使用的表格序号
def add_header(target_dir : str, report_enum : str, if_clear_header : Optional[bool] = True):
def add_header(target_dir : str, report_enum : str, if_clear_header : Optional[bool] = True, if_section : Optional[bool] = True, text : str = None):
"""添加页眉,添加封面后调用此函数,会分离页面和后续页面的节。
Args:
@ -770,35 +768,43 @@ def add_header(target_dir : str, report_enum : str, if_clear_header : Optional[b
for section in document.sections: # 遍历所有节的页眉
clear_header(section) # 清除页眉的段落
print(f"文档节数:{len(document.sections)},开始往当前节后添加页眉")
document.sections[0].header.is_linked_to_previous = False # 取消页眉与上一页关联
if if_section:
print(f"文档节数:{len(document.sections)},开始往当前节后添加页眉")
document.sections[0].header.is_linked_to_previous = False # 取消页眉与上一页关联
document.add_section(WD_SECTION.NEW_PAGE)
header = document.sections[1].header
document.add_section(WD_SECTION.NEW_PAGE)
header = document.sections[1].header
header.is_linked_to_previous = False # 取消页眉与上一页关联
header.is_linked_to_previous = False # 取消页眉与上一页关联
else:
header = document.sections[-1].header
header.is_linked_to_previous = False # 取消页眉与上一页关联
paragraph = header.paragraphs[0] # 获取页眉的第一个段落
run = paragraph.add_run()
if report_enum == 'JF':
print("添加金风模板的页眉")
pic = run.add_picture(get_template_pic(TEMPLATE_HEADER.JINFENG_HEADER.PIC_DIR))
run = paragraph.add_run(TEMPLATE_HEADER.JINFENG_HEADER.PARA)
if text:
run = paragraph.add_run(text)
else:
run = paragraph.add_run(TEMPLATE_HEADER.JINFENG_HEADER.PARA)
run.font.name = TEMPLATE_HEADER.JINFENG_HEADER.FONT
run.font.size = TEMPLATE_HEADER.JINFENG_HEADER.PT
document.save(target_dir) # 保存文档
elif report_enum == 'DT':
print("添加迪特模板的页眉")
pic = run.add_picture(get_template_pic(TEMPLATE_HEADER.DT_HEADER.PIC_DIR))
run = paragraph.add_run(TEMPLATE_HEADER.DT_HEADER.PARA)
if text:
run = paragraph.add_run(text)
else:
run = paragraph.add_run(TEMPLATE_HEADER.DT_HEADER.PARA)
run.font.name = TEMPLATE_HEADER.DT_HEADER.FONT
run.font.size = TEMPLATE_HEADER.DT_HEADER.PT
document.save(target_dir) # 保存文档
else:
print("未知模板,不添加页眉")
# 定义边框的 XML 字符串
# 定义边框的 XML 字符串
border_xml = """
<w:pBdr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:bottom w:val="single" w:sz="8" w:space="1" w:color="000000"/>
@ -811,17 +817,37 @@ def add_header(target_dir : str, report_enum : str, if_clear_header : Optional[b
pPr.append(pBdr)
print(f"文档节数:{len(document.sections)}")
document.save(target_dir) # 保存文档
from docx.enum.section import WD_ORIENT
from docx.enum.text import WD_BREAK
from docx.document import Document as Document_
def add_landscape_section(target_dir : str):
# 添加横向节
doc = Document(target_dir)
section = doc.add_section()
section.orientation = WD_ORIENT.LANDSCAPE
section.page_width, section.page_height = section.page_height, section.page_width
print(f"文档:{target_dir},添加了新横向节,页宽:{section.page_width}, 页高:{section.page_height}")
return doc
def add_section(target_dir : str) -> Document_:
doc = Document(target_dir)
section = doc.add_section()
return doc
def add_title(target_dir : str, title : str, style_config : dict = {}):
doc = Document(target_dir)
para = doc.add_paragraph()
run = para.add_run(title)
font_config = style_config.get('font', {})
run.font.name = font_config.get('name', "宋体")
run.element.get_or_add_rPr().get_or_add_rFonts().set(qn('w:eastAsia'), font_config.get('name', "宋体"))
run.font.size = font_config.get('size', Pt(14))
run.bold = font_config.get('bold', False)
para.alignment = style_config.get('alignment', WD_ALIGN_PARAGRAPH.CENTER)
print(f"添加新标题:{title},字体:{run.font.name},大小:{run.font.size},是否加粗:{run.bold}")
return doc
def merge_documents(target_dir : str, source_dirs : List[str]):
"""合并多个文档、图片
@ -924,11 +950,42 @@ def add_defect_info_table(output_dir, defect_info, MUBAN_DIR, total_table_num, R
return total_table_num
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import RGBColor
def add_table_title(output_dir, TITLE):
doc = Document(output_dir)
table = doc.add_table(rows=1, cols=6, style='Table Grid')
table.cell(0,0).merge(table.cell(0,5))
para = table.cell(0,0).paragraphs[0]
para.text = TITLE
run = para.add_run(TITLE)
run.font.name = "宋体"
run.font.size = Pt(9)
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
doc.save(output_dir)
print(f"添加了标题表格:{TITLE}")
doc.save(output_dir)
def change_heading(output_dir, style_name, style_config = {}):
doc = Document(output_dir)
heading_style = doc.styles[style_name]
font_config = style_config.get('font', {})
heading_style.font.name = font_config.get('name', "宋体")
heading_style.element.get_or_add_rPr().get_or_add_rFonts().set(qn('w:eastAsia'), font_config.get('name', "宋体"))
heading_style.font.size = font_config.get('size', Pt(11))
heading_style.bold = font_config.get('bold', True)
heading_style.font.color.rgb = font_config.get('color', DocxColors.BLACK.rgb)
print(f"修改了标题样式:{style_name},字体:{heading_style.font.name},大小:{heading_style.font.size},是否加粗:{heading_style.bold}")
doc.save(output_dir)
from docxtpl import DocxTemplate
def add_auto_toc_at_end(doc_path):
"""使用 python-docx-template 在末尾自动生成目录"""
doc = DocxTemplate(doc_path)
# 渲染模板r.toc=True 会触发目录生成)
context = {
'r': {
'toc': True # 自动生成目录
}
}
doc.render(context)
doc.save(doc_path)