Files
SignatureSystem/lib/__pycache__/field_codes.cpython-39.pyc

287 lines
23 KiB
Plaintext
Raw Normal View History

2026-07-20 13:16:17 +08:00
a
<00><>Yj-z<00>@s\dZddlZddlZddlmZddlmZddlmZddl m
Z
m Z e<02> e <0A>Ze<01>dej<10>Ze<01>d<08>Zd Zd
Zd Zd Zd Zdd<0F>Zdd<11>Zdd<13>Zdd<15>ZdEdd<18>Zdd<1A>Zdd<1C>Zdd<1E>ZdFd d!<21>Z d"Z!d#d$<24>Z"d%d&<26>Z#d'd(<28>Z$d)d*<2A>Z%d+d,<2C>Z&d-d.<2E>Z'd/d0<64>Z(d1d2<64>Z)d3d4<64>Z*d5Z+dGd7d8<64>Z,d9d:<3A>Z-d;d<<3C>Z.d=d><3E>Z/dHd?d@<40>Z0dIdAdB<64>Z1dCdD<64>Z2dS)JuDWord SET 域代码处理工具。
支持两类域代码定位:
1. ``w:fldSimple`` 简单域,``w:instr`` 属性内含 ``SET USER_xxx``。
2. ``w:instrText`` + ``w:fldChar`` 组合的复杂域。
提供:
- :func:`scan_user_markers` 扫描文档中所有 ``SET USER_<name>`` 标记。
- :func:`insert_image_after_field` 在指定标记的域之后插入签名图片。
- :func:`build_set_field_xml` 构造一段 ``SET USER_<name> \* MERGEFORMAT`` 域代码 XML。
- :func:`replace_text_with_set_field` 将段落中命中的可见文本替换为 SET 域 + 宽度补偿空格。
<EFBFBD>N)<01>deepcopy)<01>qn<71><01> OxmlElement)<02>Cm<43>Emuz\bSET\s+USER_(\S+)z^USER_(\S+?)\s*(?:\\.*)?$z<http://schemas.openxmlformats.org/wordprocessingml/2006/mainzFhttp://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawingz5http://schemas.openxmlformats.org/drawingml/2006/mainz8http://schemas.openxmlformats.org/drawingml/2006/picturezChttp://schemas.openxmlformats.org/officeDocument/2006/relationshipscCsB|dur dS|<00><00>}|<01>d<03>r*|dd<01>}|<01>dd<06>d}|<01><00>S)u<>去除 ``\* MERGEFORMAT`` 等 Word 开关,并 trim 末尾空白。
输入示例:
- ``USER_zhangsan`` -> ``zhangsan``
- ``USER_zhangsan \* MERGEFORMAT`` -> ``zhangsan``
N<><00>USER_<52><00>\<5C>r)<03>strip<69>
startswith<EFBFBD>split)<02>nameZtxt<78>r<00>`E:\projects\wxwx\projects_job\GeneralRequirement\SignatureSystem\BackEnd\Code\lib\field_codes.py<70>_strip_switches!s
 rc cs<>|jj}|j}|<01>td<01><01>D]}||fVq|jD]<5D>}|j|j|jfD]2}|durF|j}|j <09>td<01><01>D]}||fVqhqF|j
|j |j fD]2}|dur<>|j}|j <09>td<01><01>D]}||fVq<>q<EFBFBD>q2dS)u<>递归遍历文档中所有段落:正文、表格(含嵌套)、文本框、页眉页脚。
返回 ``(paragraph_element, part)`` 元组,``part`` 用于 ``add_picture`` 关系绑定。
zw:pN) <0A>element<6E>body<64>part<72>iterr<00>sections<6E>header<65>first_page_header<65>even_page_header<65>_element<6E>footer<65>first_page_footer<65>even_page_footer) <09>docr<00>doc_part<72>para<72>section<6F>hdrZhdr_part<72>ftrZftr_partrrr<00>_iter_all_paragraphs1s 
r&ccst|<00>D]\}}|VqdS)u)仅迭代段落元素(不带 part。N)r&)r r"<00>_partrrr<00>_iter_all_paragraph_elementsHsr(ccs<>|jj}|<01>td<01><01>D]
}|Vq|jD]x}|j|j|jfD](}|dur<|j<08>td<01><01>D]
}|VqXq<|j |j
|j fD](}|durv|j<08>td<01><01>D]
}|Vq<>qvq(dS)uW递归遍历所有表格包括正文、文本框、页眉页脚中的嵌套表格。zw:tblN) rrrrrrrrrrrr)r r<00>tblr#r$r%rrr<00>_iter_all_tablesNs

r*<00> 前端操作c CsNg}t<00>}t|<00>D<00>]\}}|<04><02>D<00>]}|j}|td<01>kr<>|<06>td<02><01>pLd}t<06>|<08>} | r<>t| <09> d<04><01>}
|
spq$|
<EFBFBD>
<EFBFBD>} | |vr<>q$|<03> | <0B>|<02> d|
<EFBFBD><00>|
dd<07><03>q$|td<08>kr$|j d ur<>d<03>|<06><0F><00>n|j } | s<>q$t<06>| <0C>} | r$t| <09> d<04><01>}
|
s<EFBFBD>q$|
<EFBFBD>
<EFBFBD>} | |v<00>r q$|<03> | <0B>|<02> d|
<EFBFBD><00>|
d
d<07><03>q$qtjd t|<02>d |id <0A>|S)ud扫描文档中所有 ``SET USER_<name>`` 标记,返回去重后的 ``[{marker, name}]`` 列表。<E8A1A8> w:fldSimple<6C>w:instrrr r <00>simple)<03>markerr<00>kind<6E> w:instrTextN<74>complexu1[auto扫描] 发现 %d 个 SET USER_<name> 标记<E6A087>
log_source<EFBFBD><01>extra)<13>setr&r<00>tagr<00>get<65>USER_MARKER_RE<52>searchr<00>group<75>lower<65>add<64>append<6E>text<78>join<69>itertext<78>logger<65>info<66>len) r r3<00>foundZ seen_keysr"r'<00>elemr7<00>instr<74>mr<00>keyr?rrr<00>scan_user_markers_sF 

 


 <06>rJcCs|}|<02>d<01>sd|<02><00>}n|}|<03>d<01>r4|dd<03>n|}|<04><01>}g}t|<00>D]<5D>\}}|<07><03>D]<5D>} | j}
|
td<04>kr<>| <09>td<05><01>p<>d} t<07>| <0B>} | r<>t | <0C>
d<07><01>} | <0A><01>|kr<>|<06> d|| |f<04>q\|
td <09>kr\| j p<>d}t<07>|<0E>} | r\t | <0C>
d<07><01>} | <0A><01>|kr\|<06> d
|| |f<04>q\qL|S) u<>根据 marker 名称(如 ``USER_zhangsan`` 或 ``zhangsan``)查找域代码宿主元素。
返回 ``(kind, parent_paragraph, fld_element_or_run, part)`` 列表,供插入图片使用。
r r
Nr,r-rr r.r1r2) rr<r&rr7rr8r9r:rr;r>r?)r <00> marker_name<6D>targetZ target_full<6C> target_nameZ target_lc<6C>resultsr"rrFr7rGrHrr?rrr<00>_find_field_elements_for_marker<65>s2
   
  

 rOcCs td<01>}|S)u<>构造一个包含图片 drawing 的 ``<w:r>`` 元素。
保留作为低层 helper正式插入使用 :func:`_insert_picture_into_paragraph_after_anchor`
通过 python-docx 的 ``Run.add_picture`` 完成关系绑定与 drawing XML。
<20>w:rr)<04>
image_path<EFBFBD>width_cm<63> height_cm<63>runrrr<00>_build_run_with_drawing<6E>srUc
CsNddlm}ddlm}|<00><04>}|||<07>}|<08><05>} | j|||<03>||<04>d<04>| S)u<>在指定段落元素的末尾添加一个图片 run。
使用 python-docx 的 Paragraph/Run 高层 API避免手动维护 rels。
r<00><01> Paragraph<70>r<00><02>width<74>height)<07>docx.text.paragraphrW<00> docx.sharedr<00> getparent<6E>add_run<75> add_picture)
<EFBFBD>paragraph_elementr!rQrRrSrW<00>_Cm<43>parent<6E>para_obj<62>run_objrrr<00>_add_picture_run_to_paragraph<70>s  
rfTc& Cs6|}|<07>d<01>r|dd<03>}t|<07>}t||<07>}|sHtjd|d|id<06>dSt|<00>} d}
ddlm} dd lm } |D<00>]<5D>\} }}}<10>zn| d
kr<>|}nt
||<0F>}|dur<>|n|}|}|}|r<>|dk<01>r<>t |<0E>}t |<0E>}|dur<>| }tj d |r<>|<16>nd d|id<06>t||<16>}z^dd lm}|<17>|<02><01>}|j\}}Wd<00>n1<00>s>0Y|<1A>r`|<13>r`|||}Wnt<13>yzd}Yn0tj d|<16>r<>|<16>nd |d|id<06>|<06>r<>|<13>r<>|dk<04>r<>t|||<05>t|||<05>t |<0E>}t|<0E>}t|<0E>\}}|<1C>r |<1D>s<>|<1E>r td|||<00>}t||||<1B>\}} || f||fk<03>r<>tj d|<14>p>d|<13>pFd|<1F>pNd| <20>pVd|<1B>rh|d<11>d<12>nd |<1C>r||d<11>d<12>nd ||d|id<06>
|<0E><1A>}!| ||<10>}"|"<22><1B>}#|#j|| |<1F>| | <20>d<13>|#j}$|<11>|$<24>|
d7}
tj d|d|id<06>Wqpt<13>y.}%z&tjd|t |%<25>d|id<06>WYd}%~%qpd}%~%00qp|
S)u<>在指定 ``USER_<name>`` 域之后插入签名图片。
返回插入的图片数量。
``relax_layout=True``(默认)时,若标记段落或所在表格行有固定高度约束
``lineRule="exact"`` / ``hRule="exact"``)小于签名需要的高度,
自动把约束放宽为 ``atLeast`` 并上调数值,避免 Word 硬裁剪图片。
设为 ``False`` 时严格保留原文档布局,仅靠等比例缩放把图片压进约束内。
r r
Nu,[Word处理] 未找到标记 %s 的域代码r3r4rrVrXr.uB[Word处理] 段落无显式字号,使用文档默认字号 %sptu<><01>Imageu@[Word处理] 自动尺寸: 字号=%spt → 推算 height=%.2f cm<63><00>?u<>[Word处理] 图片缩放以适配插入位置: %.2fx%.2f cm -> %.2fx%.2f cm (段落行高上限=%s, 单元格宽上限=%s, 左右缩进=%.2f+%.2fcm)z.2f<EFBFBD>cmrYr u,[Word处理] 在 %s 域后插入图片成功u&[Word处理] 插入图片失败 %s: %s)!rrrOrBZwarning<6E>_get_doc_default_font_size_ptr\rWr]r<00>_find_complex_field_end<6E>_detect_paragraph_max_height_cm<63>_detect_paragraph_font_size_ptrC<00>_auto_size_height_cmZPILrh<00>open<65>size<7A> Exception<6F>_relax_paragraph_for_image<67>_relax_table_row_for_image<67>_detect_table_cell_max_width_cm<63>_detect_paragraph_indent_cm<63>max<61> _scale_to_fitr^r_r`r<00>addnext<78>error<6F>str)&r r/rQrRrSr3<00> relax_layoutrM<00>matchesZdoc_default_ptZinsertedrWrbr0<00>para_xmlZ host_elemrZ anchor_elemZend_elemZcur_hZcur_wZmax_h_cm_initial<61>font_ptZ _PILImageZ_imZ_iwZ_ih<69>max_h_cm<63>max_w_cmZleft_cmZright_cmZfinal_wZfinal_hZ
parent_xmlrdreZ new_run_xml<6D>errr<00>insert_image_after_field<6C>s<> 
 
  
 <06>
  * 
<08>    <06>

2r<>g<>v<EFBFBD><76>n<EFBFBD><6E>@c Cs<>|<00>td<01><01>}|durdS|<01>td<03><01>}|dur4dS|<02>td<04><01>}|<02>td<05><01>}|r\|dkr`dSzt|<03>tWSttfy<>YdS0dS)u从段落属性读取固定行高lineRule="exact"),返回 cm 或 None。
Word 段落 ``<w:pPr><w:spacing w:line="..." w:lineRule="exact"/></w:pPr>`` 中,
line 字段在 exact 模式下单位为 1/20 pt (twips)。其他模式auto/atLeast不视为硬约束。
<20>w:pPrN<72> w:spacing<6E>w:line<6E>
w:lineRule<6C>exact<63><07>findrr8<00>int<6E> _TWIPS_PER_CM<43>
ValueError<EFBFBD> TypeError)r~<00>pPr<50>spacing<6E>line<6E> line_rulerrrrm)s rmc Cs<>|<00><00>}|dur(|jtd<02>kr(|<01><00>}q|dus>|jtd<02>krBdS|<01>td<04><01>}|dur\dS|<02>td<05><01>}|durvdS|<03>td<06><01>}|<03>td<07><01>p<>d}|s<>d|fSzt|<04>t}Wnttfy<>d|fYS0||fS) uQ读取段落所在表格行的固定高度约束。
向上查找最近的 ``<w:tr>``,读 ``<w:trPr><w:trHeight w:val w:hRule/></w:trPr>``。
返回 ``(val_cm, rule)`` —— ``rule ∈ {'exact', 'atLeast', None}``。
按 OOXML 规范,``hRule`` 缺省为 ``atLeast``(不裁剪),仅 ``exact`` 视为硬约束。
N<>w:tr)NN<4E>w:trPr<50>
w:trHeight<68>w:val<61>w:hRule<6C>atLeast<73> r^r7rr<>r8r<>r<>r<>r<>)r~rc<00>trPr<50>trHeight<68>val<61>rule<6C>val_cmrrr<00>_detect_table_row_height_rule?s(
r<>c Cs<>|<00>td<01><01>}|durdS|<01>td<04><01>}|dur4dS|<02>td<05><01>pR|<02>td<06><01>pRd}|<02>td<08><01>pr|<02>td <09><01>prd}zt|<03>tt|<04>tfWSttfy<>YdS0dS)
uT读段落左右缩进 ``<w:ind w:left w:right>``,返回 ``(left_cm, right_cm)``。r<E38082>N)<02>r<>zw:indzw:leftzw:start<72>0zw:rightzw:endr<64>)r~r<><00>ind<6E>left<66>rightrrrrv\s  rvc Cs|ddl}|r|dkrdSt|<03>|t<00><01>}|<00>td<04><01>}|durTtd<04>}|<00>d|<05>|<05>td<05><01>}|dur<>td<05>}|<06>td<06>t |<04><01>|<06>td<07>d<08>|<05>
|<06>t j d ||t|d
|id <0B>d S|<06> td<06><01>}|<06> td<07><01>p<>d }|<07>r&z&t|<07>} |dv<00>r
| |k<05>r
WdSWnttf<02>y$Yn0|}
|<07>p2d } |<06>td<07>d<08>|<06>td<06>t |<04><01>t j d|
| ||t|d
|id <0B>d S)uI确保段落行高至少能容纳签名高度,避免 inline 图片被行盒子裁切。
inline 图片默认骑在文字 baseline 上方,所需高度 = 图片高度。
若段落行高(由 spacing/@line + lineRule 决定,或基于字号默认推算)小于该值,
baseline 上方会溢出并被 Word 裁掉(典型表现:图片上方被切)。
处理所有 spacing 状态:
- 无 pPr / 无 spacing → 主动创建 ``spacing line=needed atLeast``
- ``lineRule='exact'`` 且 line < needed → 改 ``atLeast`` + 上调 line
- ``lineRule='atLeast'`` 且 line < needed → 上调 line
- ``lineRule='auto'`` / 缺省 → 改 ``atLeast`` + 设 line = needed
(默认行高基于字号,对 inline 图片通常不够)
- 已 ≥ needed → no-op
返回是否发生过改动。
rNFr<46>r<>r<>r<>r<>uh[Word处理] 段落无显式行高,新增 spacing atLeast/%d twips (%.2fcm) 以容纳 %.2fcm 高签名r3r4T<>auto)r<>r<>un[Word处理] 放宽段落行高: lineRule %s→atLeast, line %s→%d twips (%.2fcm) 以容纳 %.2fcm 高签名)<10>mathr<68><00>ceilr<6C>r<>rr<00>insertr6r{r>rBrCr8r<>r<>) r~<00> needed_h_cmr3r<><00> needed_twipsr<73>r<>r<>r<><00>
line_twipsZold_ruleZold_linerrrrslsL  

<06>

<06>rsc CsNddl}|r|dkrdS|<00><01>}|dur@|jtd<04>kr@|<04><01>}q |dusV|jtd<04>krZdS|<04>td<05><01>}|durtdS|<05>td<06><01>}|dur<>dS|<06>td<07><01>}|<06>td<08><01>p<>d }|d
ks<>|s<>dSzt|<07>t} Wntt fy<>YdS0| |kr<>dSt|<03>
|t<00><01>}
|<06> td<08>d <09>|<06> td<07>t |
<EFBFBD><01>t jd ||
| |
t|d |id <0A>dS)u)放宽表格行**硬高度约束**,避免图片被表格行盒子裁切。
OOXML 规范下表格行高规则:
- ``hRule='exact'``:行高**精确**为 val超过部分被裁切 ← 硬约束
- ``hRule='atLeast'`` 或缺省:行高**至少**为 val可自动撑高 ← 软约束,不裁切
因此本函数仅在 ``hRule='exact'`` 且 ``val < needed_h_cm`` 时介入:
- 改 ``hRule`` 为 ``atLeast`` + 上调 ``val`` 到 needed_h_cm
其他情况(无 trHeight、atLeast、已 ≥ needed、auto → no-op。
rNFr<46>r<>r<>r<>r<>r<>r<>ux[Word处理] 放宽表格行高: hRule exact→atLeast, val %s→%d twips (%.2fcm → %.2fcm) 以容纳 %.2fcm 高签名r3r4T)r<>r^r7rr<>r8r<>r<>r<>r<>r<>r6r{rBrC) r~r<>r3r<>rcr<>r<>r<>r<>r<>r<>rrrrt<00>s@  
 <06>rtc Cs<>|<00><00>}|dur(|jtd<02>kr(|<01><00>}q|dus>|jtd<02>krBdS|<01>td<03><01>}|dur\dS|<02>td<04><01>}|durvdS|<03>td<05><01>}|<03>td<06><01>}|r<>|dkr<>dSzt|<04>tWSttfy<>YdS0dS)uQ若段落位于表格单元格内,读取单元格宽度,返回 cm 或 None。Nzw:tczw:tcPrzw:tcWzw:wzw:type<70>pctr<74>)r~rc<00>tcPr<50>tcWZw_valZw_typerrrru<00>s&
 rucCsX|r|s||fSd}|r.||kr.t|||<00>}|rH||krHt|||<00>}||||fS)uU等比例缩放图片,使其宽高都不超过约束。返回 (final_w, final_h)。g<00>?)<01>min)rRrSr<>r<>Zratiorrrrx<00>s  rxc
CsN|<00>td<01><01>D]<5D>}|<01>td<02><01>}|dur*q|<02>td<04><01>}|dur|<03>td<05><01>}|r<>z2t|<04>d}d|krtdkr<>nn
|WSWnttfy<>Yn0q<>q|<00>td <09><01>}|du<01>rJ|<06>td<02><01>}|du<01>rJ|<02>td<04><01>}|du<01>rJ|<03>td<05><01>}|<04>rJz2t|<04>d}d|k<01>r$dk<01>r.nn|WSWnttf<02>yHYn0dS)
u%读取段落字体大小point
优先级:
1. 段落第一个有 ``<w:rPr><w:sz>`` 的 run
2. 段落标记的 rPr``<w:pPr><w:rPr><w:sz>``
``w:sz`` 的 val 是 half-points如 21 = 10.5pt)。
找不到返回 None由调用方决定 fallback
rP<00>w:rPrN<72>w:szr<7A><00>@<40>@<40>X@r<>)rrr<>r8r<>r<>r<>)r~<00>r<>rPr<50>szr<7A><00>ptr<74>rrrrn<00>s<
 


 
rnc
Cs<>z |jj}Wnty YdS0|<01>td<02><01>D]<5D>}|<02>td<03><01>dkrHq0|<02>td<05><01>}|dur<>|<03>td<06><01>}|dur<>|<04>td<07><01>}|r<>z2t|<05>d}d |kr<>d
kr<>nn
|WSWntt fy<>Yn0q<>q0|<01>td <0B><01>}|dur<>dS|<07>td <0C><01>}|du<00>r dS|<08>td<05><01>}|du<00>r(dS|<03>td<06><01>}|du<00>rDdS|<04>td<07><01>}|<05>s\dSz2t|<05>d}d |k<01>r<>d
k<01>r<>nn|WSWntt f<02>y<>YdS0dS) uE读文档级默认字号,按 Word 实际渲染优先级。
优先级:
1. ``Normal`` 样式(默认段落样式)的 ``<w:sz>`` —— Word 渲染段落时实际使用
2. ``<w:docDefaults><w:rPrDefault><w:rPr><w:sz>`` —— 全局兜底
找不到返回 None由调用方做最终 fallback
Nzw:stylez w:styleId<49>Normalr<6C>r<>r<>r<>r<>r<>z w:docDefaultsz w:rPrDefault)
<EFBFBD>stylesrrrrrr8r<>r<>r<>r<>) r Zstyles_element<6E>styler<65>r<>r<>r<>Z doc_defaultsZ rPr_defaultrrrrk*sT    


 
rkge<67><65><EFBFBD><EFBFBD><0F>?r<>cCs||r6d|krdkr6nnttt|dd<04>d<05>d<06>S|rVd|krNdkrVnn|nd }|dt}ttt|d<04>d<05>d<06>S)
u9根据段落行高和字号自动推算签名高度cm
优先级:
1. 段落 exact line height → 用其 95%(留 5% 安全裕量,避免顶满行)
2. 字号 → 用 2 倍字号高度(中文文档常见签名比例:四号 14pt → 0.99cm
视觉自然不抢戏,又能看清笔画)
3. 字号缺失 → 用 10.5pt(中文 Word 通用默认)按 2 倍推算兜底,
避免 fallback 到 default_cm 导致过大
4. 默认 default_cm
范围约束:返回值 clamp 到 [0.5, 5.0] cm避免极端值。
g333333<33>?g$@gffffff<66>?rig@<40>g@gR@<40>%@)<04>roundr<64>rw<00>
_CM_PER_PT)Zline_height_cmrZ
default_cmZ effective_ptrjrrrrofs
$ rocCsr|}d}|<00><00>D]\}||urq|jtd<02>kr|<04>td<03><01>}|dkrHd}q|dkr\|r\|S|dkr|SqdS)uB从 instrText 开始向后查找同段落的 fldChar end 元素。F<E38082> w:fldChar<61> w:fldCharType<70>separateT<65>endN)rr7rr8)<06> paragraphZinstr_text_elem<65>currentZ found_seprFZftyperrrrlzs  
rlc
Cs<><00>z<>ddl}ddlm}ddlm}ddlm}t|d<06><02>}|<07><08>}Wd<00>n1sX0Y|<04> |<08>} t
|j d<07>r<>|j <0B> | <09>nd}
|
dur<>|<05> | |j j<0E>}
|j <0B>|
|j<10>} n*d} |j j<11><12>D]} | j|
ur<>| j} q<>q<EFBFBD>|<01>td<08><01>} | dur<>WdS| <0A>td <09><01>}|du<00>rWdS|<0E>td
<EFBFBD><01>}|du<00>r4WdS|<0F>td <0B><01>}|du<00>rRWdS|<10>td <0C><01>}|du<00>rpWdStd <0A>}td<0E>}|<13>td<0F>| <0B>|<12>|<13>|<11>d|<12>Wn6t<1B>y<>}zt<1C>dt|<14><01>WYd}~n
d}~00dS)uE通过 python-docx 的 part 接口建立图片关系并补充 blip。rNrg)<01> ImagePart)<01>RELATIONSHIP_TYPE<50>rb<72>related_part_lookup_by_imagez w:drawingz wp:inlinez a:graphicz a:graphicDatazpic:picz pic:blipFillza:blipzr:embedu)[Word处理] 绑定图片关系失败: %s)<1F>osZdocx.image.imagerh<00>docx.parts.imager<65><00>docx.opc.constantsr<73>rp<00>read<61> from_blob<6F>hasattrrr<><00>
from_image<EFBFBD>package<67> relate_to<74>IMAGE<47>rels<6C>values<65> target_part<72>rIdr<64>rrr6r>r<>rrrBrzr{)r Zrun_elemrQr<>rhr<><00>RT<52>fZ
image_data<EFBFBD>image<67>
image_partr<EFBFBD><00>rel<65>drawing<6E>inline<6E>graphicZ graphic_data<74>picZ blip_fill<6C>blipr<70>rrr<00>_attach_image_relationship<69>sN    &






r<>c Cs g}td<01>}td<02>}|<03>td<03>d<04>|<02>|<03>|<01>|<02>td<01>}td<05>}|<05>td<06>d<07>d|<00>d <09>|_|<04>|<05>|<01>|<04>td<01>}td<02>}|<07>td<03>d
<EFBFBD>|<06>|<07>|<01>|<06>td<01>}td <0B>} | <09>td<06>d<07>d | _|<08>| <09>|<01>|<08>td<01>}
td<02>} | <0B>td<03>d <0A>|
<EFBFBD>| <0B>|<01>|
<EFBFBD>|S)u<>构造一段复杂域 XML表示 ``SET USER_<name> \* MERGEFORMAT``。
返回三个 ``<w:r>`` 元素begin / instrText / separate / 空白 result / end。
合并为一个 list 返回,调用方依次追加到段落。
rPr<>r<>Zbeginr1<00> xml:space<63>preservez
SET USER_z \* MERGEFORMAT r<><00>w:trr<>)rr6rr>r?) r<00>runsZr1Z fld_beginZr2rGZr3Zfld_sepZr4Zt4Zr5Zfld_endrrr<00>build_set_field_runs<6E>s:









r<>cCs|pd}t|dd<00>S)u<>估算单字符宽度EMU用于补偿空格宽度。
Word 默认正文字号 10.5pt(小四),半角空格宽度约为字号的 0.25 倍。
r<>g<00>?i<>1)r<>)Z font_size_ptr<74>rrr<00>_approx_char_width_emu<6D>sr<>c Cst|<00>td<01><01>}|t|<08>krdS||} | <09>td<03><01>}
|
dur@dS||k<02>r|
jpRd} | d|<02>} | |d<04>} t| <0C>}t| <0A>}t|<06>}|r<>tdt|<05><00>nd}| <09><07>}t|<12><01> | <09>}|<12>
| <09>|}|g||r<>|gng|gD]"}|dur<>q<EFBFBD>|<12> ||<15>|d7}q<>dSg}t ||d<00>D]>}||}|<18>td<03><01>}|<16> |du<01>rN|j<04>rN|jnd<05><00>q|d }|d|<02>} |d
}||d<04>} t| <0C>}t| <0A>}t|<06>}d<05>|<16>}||td d <0C>|dd
<EFBFBD>D<00><01>|<00>}|<07>r<>tdt|<1D><00>nd}|}|||d<00>}|d }t|<12><01> |<1F>}|D]}|<12>
|<18><00>q|}|g||<07>r:|gng|gD](}|du<00>rX<72>qF|<12> ||<15>|d7}<14>qFdS) u在段落 XML 中将指定 Run 区间内的字符替换为 SET 域 + 可选补偿空格。
参数:
- ``paragraph_element``: ``<w:p>`` lxml 元素。
- ``start_run_idx``/``end_run_idx``: 起止 ``<w:r>`` 在段落中的索引。
- ``start_offset``/``end_offset``: 起止 ``<w:t>`` 内字符偏移。
- ``captured_text``: 被替换的原始可见文本(用于估算补偿宽度)。
- ``name``: 用于 ``USER_<name>`` 的标识。
- ``compensate_spaces``: 是否插入普通空格补偿原宽度。
rPFr<46>Nr<00> r Tr<00><><EFBFBD><EFBFBD><EFBFBD>css|]}t|<01>VqdS)N)rD)<02>.0<EFBFBD>prrr<00> <genexpr>(<00>z.replace_text_with_set_field.<locals>.<genexpr>)<10>findallrrDr<>r?<00>_make_text_runr<6E>r^<00>list<73>index<65>remover<65><00>ranger>r@<00>sum) raZ start_run_idxZ start_offsetZ end_run_idxZ
end_offsetZ captured_textrZcompensate_spacesr<73>Z start_runZstart_tZ original_text<78>head<61>tailZhead_runZtail_runZ
field_runsZcompensate_runrc<00>idxZ
insert_idxrFZoriginal_text_partsZridxr<78><00>tZ
first_textZ last_textZ full_textZcapturedZ to_remove<76>anchorrrr<00>replace_text_with_set_field<6C>sn  

  
" 
&  
<1C>$
  r<>cCsL|dur dS|dkrdStd<02>}td<03>}|<02>td<04>d<05>||_|<01>|<02>|S)NrrPr<>r<>r<>)rr6rr?r>)r?r<>r<>rrrr<>;s
r<>)r+)r+T)r<>)N)T)3<>__doc__<5F>re<72>logging<6E>copyr<00> docx.oxml.nsr<00> docx.oxmlrr]rr<00> getLogger<65>__name__rB<00>compile<6C>
IGNORECASEr9ZUSER_MARKER_RE_CLEANZW_NSZWP_NSZA_NSZPIC_NSZR_NSrr&r(r*rJrOrUrfr<>r<>rmr<>rvrsrtrurxrnrkr<>rorlr<>r<>r<>r<>r<>rrrr<00><module>sV    


($
<00>
c>2 +9
.+
<00>
M