微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用python docx在Word中自定义编号样式?

如何解决如何使用python docx在Word中自定义编号样式?

在 Word 文件添加段落时,我尝试使用 python docx 自定义编号样式。

例如,我不想在段落开头添加 '1. ',而是要执行 'class #1. '

有可能吗?有可以直接使用的功能吗?

解决方法

此示例将参数传递给示例文档:

# generate_roombill_docx.py
import re
from pathlib import Path

from models.earning import RoomBill,c_room_bills_serializer
from models.nezha import get_community_name

from .create_docx_by_sample import docx_replace
from .helper import create_sn,verbose_price


async def gen_docx(roombill: RoomBill,host: str,r2=None,target=None):
    # 创建docx文件,返回文件路径target,指定让r2/c2采取二合一打印

    community_name = await get_community_name(roombill.community)
    room_name = roombill.room_name
    host = host.replace("www.esoaru.net","esoaru.net")
    img = qrcode_path(host,community_name,roombill.room_slug)
    where = Path(__file__).parent
    sample = where / "sample_模板2.docx"
    bills,total = await c_room_bills_serializer([roombill])
    params = build_params(
        bills,room_name,total,roombill.name,roombill.remark,roombill.period,)
    img_data = {"img_paycode": img}
    if community_name == "xxx":
        params["who"] = (
            "深圳艺坤家园物业管理有限公司"
            "\n"
            "服务中心电话: 0755-28281233 (8:30-21:00)"
            "\n"
            "监控中心电话: 0755-28283118 (7*24小时)"
        )
    else:
        params["who"] = ""
    if r2:
        # TODO 2.2: 两个单打印在同一张纸
        where = Path(__file__).parent
        sample = where / "double_sample.docx"
    if target is None:
        media = Path("media")
        name = f"{room_name}_{r2}.docx" if r2 else f"{room_name}.docx"
        target = media / community_name / "通知单" / name
        target.parent.exists() or target.parent.mkdir(parents=True)
    docx_replace(sample,target,params,img_data)
    return str(target)


def doc_fmt(detail):
    if not detail:
        return ""
    d = re.sub(r"<[a-z /]+>","",detail)
    d = re.sub(r"&nbsp;?"," ",d)
    d = re.sub(r"\s{2,}",d)
    return d


def build_params(
    bills: dict,unit: str,community_name: str,total: str,bill_name: str,remark: str = "",period: str = "",# 计费周期备注
) -> dict:
    """构造出模板需要的参数"""
    sn = create_sn()
    d = {"room": unit,"community": community_name,"sn": sn}
    d["total"] = str(total)
    d["verbose"] = total and verbose_price(total) or ""
    d["bill_name"] = bill_name
    d["period_tip"] = "计费周期备注:" if period else ""
    d["period"] = period or ""
    d["tip"] = "备注:" if remark else ""
    d["remark"] = remark or ""
    line_num = 1
    for bill_id,bill_data in bills.items():
        for charge_item in bill_data["charges"]:
            for i in charge_item["items"]:
                a,b,c = f"n{line_num}1",f"n{line_num}2",f"n{line_num}3"
                d[a],d[b],d[c] = i["title"],i["amount"],i["detail"]
                line_num += 1
    for i in range(1,10):
        for j in range(1,4):
            k = f"n{i}{j}"
            d.setdefault(k,"")
    return d


def qrcode_path(host: str,room_slug: str) -> str:
    """返回二维码图片地址,如果图片不存在就调用qrcode生成它"""
    media = "media"
    p = Path(media) / "qrcodes" / community_name / f"{room_slug}.jpg"
    if not p.exists():
        if not p.parent.exists():
            p.parent.mkdir(parents=True)
        import qrcode

        if "wanghai" not in host:
            qr_host = "https://www.esoaru.com"
        else:
            qr_host = host.replace("wanghai","www")
        link = f"{qr_host}/dist/bill/{room_slug}/paper"
        qrcode.make(link).save(p)
    return str(p)

create_docx_by_sample.py

#!/usr/bin/env python
from pathlib import Path
from typing import Optional,Union

from docx import Document
from docx.shared import Cm


def docx_replace(
    sample_path: Union[str,Path],savepath: Union[str,params: dict,images: Optional[dict] = None,) -> None:
    """根据给定模板和参数,构造新的Word文档,并保存在本地"""

    document = Document(sample_path)
    if images is None:
        images = {}

    for paragraph in document.paragraphs:

        for run in paragraph.runs:
            rtext = run.text
            for k,v in params.items():
                vname = "${%s}" % k
                if vname in rtext:
                    run.text = rtext.replace(vname,v)

            for k,v in images.items():
                vname = "${%s}" % k

                if vname in rtext:
                    run.clear()
                    run.add_picture(v,height=Cm(4.75))

    for paragraph in document.paragraphs:
        ptext = paragraph.text
        # print(ptext)
        for k,v in params.items():
            vname = "${%s}" % k
            if vname in ptext:
                paragraph.text = ptext.replace(vname,v)

    for table in document.tables:
        for row in table.rows:
            for cell in row.cells:
                for paragraph in cell.paragraphs:
                    ptext = paragraph.text
                    for k,v in params.items():
                        vname = "${%s}" % k
                        if vname in ptext:
                            paragraph.text = ptext.replace(vname,v)

                    for k,v in images.items():
                        vname = "${%s}" % k

                        if vname in ptext:
                            # print(ptext)
                            paragraph.clear()
                            run = paragraph.add_run()
                            run.add_picture(v,height=Cm(4.0))
    document.save(savepath)


def main() -> None:
    params = {
        "room": "10-005","sn": "5213","n11": "历史账单:","n12": "物业费","n13": "100.00","n21": "","n22": "停车费","n23": "200","n31": "7月账单:","n32": "物业费","n33": "100.00","n41": "","n42": "停车费","n43": "200","n51": "8月账单:","n52": "物业费","n53": "100.00","n61": "","n62": "停车费","n63": "200","n71": "","n72": "总计:","n73": "5320.00",}
    where = Path(__file__).parent
    docx_replace(
        where / "sample.docx",where / "cuishoudan_demo.docx",{"img_paycode": str(where / "gyy.jpg")},)

if __name__ == '__main__':
    import sys
    if 'test' in sys.argv:
        main()

sample.docx:https://waketzheng.top/public/docx/sample.docx

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。