| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- # -*- coding: utf-8 -*-
- from __future__ import annotations
- import html
- import os
- import shutil
- import zipfile
- from datetime import datetime, timezone
- from pathlib import Path
- BASE = Path(__file__).resolve().parent
- OUT = BASE / "订单与供应监测模块架构汇报.pptx"
- BUILD = BASE / "pptx-build-py"
- EMU = 9525
- def emu(px: float) -> int:
- return int(px * EMU)
- shape_id = 1
- def next_id() -> int:
- global shape_id
- shape_id += 1
- return shape_id
- def rgb(value: str) -> str:
- return value.strip("#").upper()
- def write(path: Path, content: str) -> None:
- path.parent.mkdir(parents=True, exist_ok=True)
- path.write_text(content, encoding="utf-8")
- def text_shape(text: str, x: int, y: int, w: int, h: int, size: int, color: str, bold: bool = False) -> str:
- sid = next_id()
- bold_attr = ' b="1"' if bold else ""
- paragraphs = []
- for line in str(text).splitlines() or [""]:
- paragraphs.append(
- f'<a:p><a:r><a:rPr lang="zh-CN" sz="{size * 100}"{bold_attr}>'
- f'<a:solidFill><a:srgbClr val="{rgb(color)}"/></a:solidFill>'
- f'<a:latin typeface="Microsoft YaHei"/><a:ea typeface="Microsoft YaHei"/></a:rPr>'
- f'<a:t>{html.escape(line)}</a:t></a:r>'
- f'<a:endParaRPr lang="zh-CN" sz="{size * 100}"/></a:p>'
- )
- return f"""
- <p:sp>
- <p:nvSpPr><p:cNvPr id="{sid}" name="Text {sid}"/><p:cNvSpPr txBox="1"/><p:nvPr/></p:nvSpPr>
- <p:spPr><a:xfrm><a:off x="{emu(x)}" y="{emu(y)}"/><a:ext cx="{emu(w)}" cy="{emu(h)}"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom><a:noFill/><a:ln><a:noFill/></a:ln></p:spPr>
- <p:txBody><a:bodyPr wrap="square" rtlCol="0"><a:spAutoFit/></a:bodyPr><a:lstStyle/>{''.join(paragraphs)}</p:txBody>
- </p:sp>
- """
- def rect_shape(x: int, y: int, w: int, h: int, fill: str, line: str = "FFFFFF", rounded: bool = False) -> str:
- sid = next_id()
- geom = "roundRect" if rounded else "rect"
- return f"""
- <p:sp>
- <p:nvSpPr><p:cNvPr id="{sid}" name="Box {sid}"/><p:cNvSpPr/><p:nvPr/></p:nvSpPr>
- <p:spPr><a:xfrm><a:off x="{emu(x)}" y="{emu(y)}"/><a:ext cx="{emu(w)}" cy="{emu(h)}"/></a:xfrm><a:prstGeom prst="{geom}"><a:avLst/></a:prstGeom><a:solidFill><a:srgbClr val="{rgb(fill)}"/></a:solidFill><a:ln w="9525"><a:solidFill><a:srgbClr val="{rgb(line)}"/></a:solidFill></a:ln></p:spPr>
- </p:sp>
- """
- def card(title: str, body: str, x: int, y: int, w: int, h: int, accent: str) -> str:
- return (
- rect_shape(x, y, w, h, "FFFFFF", "DDDDDD", True)
- + rect_shape(x, y, 8, h, accent, accent, False)
- + text_shape(title, x + 22, y + 16, w - 35, 34, 17, "17304A", True)
- + text_shape(body, x + 22, y + 58, w - 35, h - 68, 13, "555555", False)
- )
- def node(text: str, x: int, y: int, w: int, h: int, fill: str, line: str) -> str:
- return rect_shape(x, y, w, h, fill, line, True) + text_shape(text, x + 10, y + 15, w - 20, h - 20, 14, "17304A", True)
- def title(text: str, subtitle: str = "") -> str:
- body = text_shape(text, 70, 42, 980, 52, 30, "17304A", True)
- if subtitle:
- body += text_shape(subtitle, 72, 92, 980, 30, 14, "666666")
- body += rect_shape(70, 128, 1140, 3, "2B74B1", "2B74B1")
- return body
- slides = [
- {
- "bg": "FBFAF7",
- "body": text_shape("订单监测与供应监测", 90, 170, 900, 58, 38, "17304A", True)
- + text_shape("模块架构、功能逻辑与系统关联汇报", 92, 238, 880, 38, 20, "666666")
- + text_shape("面向管理层的简版说明", 94, 300, 420, 28, 15, "2B74B1", True)
- + card("汇报重点", "1. 两个模块分别解决什么问题\n2. 数据如何进入系统并形成分析结果\n3. 与库存、产品、生命周期等模块如何关联", 760, 170, 390, 250, "2B74B1"),
- },
- {
- "bg": "FFFFFF",
- "body": title("一页总览", "两个模块都采用:数据接入 -> 数据入库 -> 后端聚合 -> 前端看板展示")
- + card("订单监测", "关注销售侧:订单金额、商品贡献、渠道/平台表现、支付效率、退款漏损、连带购买。\n\n当前数据库已有核心表,具备较完整的数据分析基础。", 80, 170, 500, 320, "2B74B1")
- + card("供应监测", "关注采购侧:供应商履约、采购订单、入库金额、账期、准交率、付款计划。\n\n当前数据库只有部分基础数据,需补齐采购订单、账期和交付匹配数据。", 700, 170, 500, 320, "449B7A"),
- },
- {
- "bg": "FFFFFF",
- "body": title("整体模块架构", "前端页面保持稳定,后端逐步将文件依赖切换为数据库驱动")
- + node("数据文件上传\nCSV / Excel", 70, 220, 180, 78, "DAE7F4", "2B74B1")
- + text_shape("→", 268, 234, 50, 50, 28, "666666", True)
- + node("导入服务\n解析 / 清洗 / 校验", 330, 220, 210, 78, "EAF5EC", "449B7A")
- + text_shape("→", 558, 234, 50, 50, 28, "666666", True)
- + node("业务数据库\n订单 / 供应 / 库存", 620, 220, 210, 78, "F7F1E8", "E88B3A")
- + text_shape("→", 848, 234, 50, 50, 28, "666666", True)
- + node("分析服务\nMapper / 聚合逻辑", 910, 220, 210, 78, "F5F5F5", "666666")
- + text_shape("↓", 995, 305, 50, 50, 26, "666666", True)
- + node("管理看板\n图表 / 报表 / 对比", 910, 370, 210, 78, "FFFFFF", "2B74B1")
- + card("架构原则", "接口尽量保持不变,减少前端改造;数据统一入库,避免依赖本地路径;分析逻辑集中在 Service 和 Mapper 层。", 120, 500, 1030, 105, "2B74B1"),
- },
- {
- "bg": "FFFFFF",
- "body": title("订单监测:功能逻辑", "订单监测已经具备数据库化基础,重点是持续完善导入和统计口径")
- + card("核心功能", "订单价值分析:GMV、成交金额、退款金额\n商品分析:Top 商品、连带购买\n渠道分析:平台、渠道、业务单元贡献\n支付分析:平均支付耗时、支付漏斗\n经营报表:按日/月/年聚合", 70, 165, 360, 370, "2B74B1")
- + card("实现逻辑", "1. 订单和店铺价值数据进入数据库\n2. Mapper 查询订单主表和店铺价值明细表\n3. Service 聚合指标并返回统一结构\n4. 前端看板按日期范围展示结果", 460, 165, 360, 370, "449B7A")
- + card("当前基础", "dtm_order_main:订单主表\ndtm_shop_value_main:店铺价值明细表\n\n当前数据库中两张核心表已有较多数据,可支撑订单监测主要分析。", 850, 165, 360, 370, "E88B3A"),
- },
- {
- "bg": "FFFFFF",
- "body": title("供应监测:功能逻辑", "供应监测目标是从 Excel 文件读取升级为数据库驱动")
- + card("核心功能", "供应商统计:订单金额、入库金额、完成率、准交率\n供应商对比:多个供应商横向比较\n付款计划:账期 + 验收/入库日期计算预计付款\n数据导入:账期、订单、入库、匹配结果", 70, 165, 360, 370, "449B7A")
- + card("实现逻辑", "1. 上传供应监测相关 Excel\n2. 解析供应商、订单、入库、账期字段\n3. 写入供应监测数据表\n4. Service 从数据库聚合供应商指标\n5. 前端继续使用现有查询接口", 460, 165, 360, 370, "2B74B1")
- + card("当前缺口", "数据库已有:供应商基础表、采购入库基础表。\n\n仍缺:采购订单、供应商账期、计划交货日期、实际验收日期、订单入库匹配结果。", 850, 165, 360, 370, "E88B3A"),
- },
- {
- "bg": "FFFFFF",
- "body": title("模块关联关系", "两个监测模块不是孤立看板,而是与基础数据和分析模块共享数据资产")
- + card("订单监测关联", "产品模块:通过 SKU 关联商品、SPU、产品信息。\n生命周期模块:复用订单销售数据做热销、趋势、生命周期分析。\n店铺模块:复用平台、渠道、业务单元维度。", 90, 170, 500, 280, "2B74B1")
- + card("供应监测关联", "库存模块:复用采购入库和库存流转数据。\n产品模块:通过 SKU 关联采购产品。\n供应商资料:复用供应商编号和名称,扩展账期和履约指标。", 690, 170, 500, 280, "449B7A")
- + card("通用关联", "系统权限和操作日志可统一管理导入权限、导入记录和异常追踪;导入批次设计可在订单和供应两个模块复用。", 190, 495, 900, 95, "E88B3A"),
- },
- {
- "bg": "FFFFFF",
- "body": title("数据入库建设重点", "管理层需要关注的是数据完整性、稳定性和可追踪性")
- + card("订单监测", "建设重点:完善导入批次、重复数据处理、异常行反馈。\n\n收益:订单看板稳定、历史数据可追溯、跨模块复用能力强。", 90, 170, 500, 300, "2B74B1")
- + card("供应监测", "建设重点:补齐采购订单、账期、计划交货日期、实际验收日期、匹配结果。\n\n收益:供应商履约分析和付款计划可以稳定落地。", 690, 170, 500, 300, "449B7A"),
- },
- {
- "bg": "FFFFFF",
- "body": title("推进路径", "建议分阶段推进,先稳定数据,再扩展分析能力")
- + node("阶段一\n确认数据源和字段口径", 80, 220, 210, 85, "DAE7F4", "2B74B1")
- + text_shape("→", 308, 240, 50, 50, 28, "666666", True)
- + node("阶段二\n建设导入和入库表", 370, 220, 210, 85, "EAF5EC", "449B7A")
- + text_shape("→", 598, 240, 50, 50, 28, "666666", True)
- + node("阶段三\n切换 Service 查询数据库", 660, 220, 230, 85, "F7F1E8", "E88B3A")
- + text_shape("→", 908, 240, 50, 50, 28, "666666", True)
- + node("阶段四\n完善看板和管理报表", 970, 220, 210, 85, "FFFFFF", "2B74B1")
- + card("结论", "订单监测已有较好的数据库基础,重点是规范化导入和追踪。供应监测需要先补齐核心数据表,再将现有 Excel 分析迁移到数据库查询。", 120, 430, 1040, 130, "2B74B1"),
- },
- ]
- def slide_xml(slide: dict[str, str]) -> str:
- return f'''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
- <p:cSld>
- <p:bg><p:bgPr><a:solidFill><a:srgbClr val="{rgb(slide["bg"])}"/></a:solidFill><a:effectLst/></p:bgPr></p:bg>
- <p:spTree>
- <p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr>
- <p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr>
- {slide["body"]}
- </p:spTree>
- </p:cSld>
- <p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr>
- </p:sld>
- '''
- def build() -> None:
- if OUT.exists():
- OUT.unlink()
- if BUILD.exists():
- shutil.rmtree(BUILD)
- for folder in [
- "_rels",
- "docProps",
- "ppt/_rels",
- "ppt/slides/_rels",
- "ppt/slideMasters/_rels",
- "ppt/slideLayouts/_rels",
- "ppt/theme",
- ]:
- (BUILD / folder).mkdir(parents=True, exist_ok=True)
- overrides = [
- '<Override PartName="/ppt/presentation.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"/>',
- '<Override PartName="/ppt/slideMasters/slideMaster1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"/>',
- '<Override PartName="/ppt/slideLayouts/slideLayout1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"/>',
- '<Override PartName="/ppt/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>',
- '<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>',
- '<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>',
- ]
- for index, slide in enumerate(slides, start=1):
- overrides.append(f'<Override PartName="/ppt/slides/slide{index}.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/>')
- write(BUILD / f"ppt/slides/slide{index}.xml", slide_xml(slide))
- write(
- BUILD / f"ppt/slides/_rels/slide{index}.xml.rels",
- '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
- <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout1.xml"/>
- </Relationships>
- ''',
- )
- write(
- BUILD / "[Content_Types].xml",
- f'''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
- <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
- <Default Extension="xml" ContentType="application/xml"/>
- {' '.join(overrides)}
- </Types>
- ''',
- )
- write(
- BUILD / "_rels/.rels",
- '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
- <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="ppt/presentation.xml"/>
- <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
- <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
- </Relationships>
- ''',
- )
- slide_ids = []
- rels = ['<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster" Target="slideMasters/slideMaster1.xml"/>']
- for index in range(1, len(slides) + 1):
- rid = index + 1
- slide_ids.append(f'<p:sldId id="{255 + index}" r:id="rId{rid}"/>')
- rels.append(f'<Relationship Id="rId{rid}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="slides/slide{index}.xml"/>')
- write(
- BUILD / "ppt/presentation.xml",
- f'''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <p:presentation xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
- <p:sldMasterIdLst><p:sldMasterId id="2147483648" r:id="rId1"/></p:sldMasterIdLst>
- <p:sldIdLst>{''.join(slide_ids)}</p:sldIdLst>
- <p:sldSz cx="12192000" cy="6858000" type="wide"/>
- <p:notesSz cx="6858000" cy="9144000"/>
- <p:defaultTextStyle/>
- </p:presentation>
- ''',
- )
- write(BUILD / "ppt/_rels/presentation.xml.rels", f'''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
- {' '.join(rels)}
- </Relationships>
- ''')
- write(BUILD / "ppt/slideMasters/slideMaster1.xml", '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <p:sldMaster xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
- <p:cSld><p:spTree><p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr></p:spTree></p:cSld>
- <p:clrMap bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2" accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4" accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/>
- <p:sldLayoutIdLst><p:sldLayoutId id="2147483649" r:id="rId1"/></p:sldLayoutIdLst>
- <p:txStyles><p:titleStyle/><p:bodyStyle/><p:otherStyle/></p:txStyles>
- </p:sldMaster>
- ''')
- write(BUILD / "ppt/slideMasters/_rels/slideMaster1.xml.rels", '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
- <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout1.xml"/>
- <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="../theme/theme1.xml"/>
- </Relationships>
- ''')
- write(BUILD / "ppt/slideLayouts/slideLayout1.xml", '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <p:sldLayout xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" type="blank" preserve="1">
- <p:cSld name="Blank"><p:spTree><p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr></p:spTree></p:cSld>
- <p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr>
- </p:sldLayout>
- ''')
- write(BUILD / "ppt/slideLayouts/_rels/slideLayout1.xml.rels", '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
- <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster" Target="../slideMasters/slideMaster1.xml"/>
- </Relationships>
- ''')
- write(BUILD / "ppt/theme/theme1.xml", '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="DTM"><a:themeElements><a:clrScheme name="DTM"><a:dk1><a:srgbClr val="17304A"/></a:dk1><a:lt1><a:srgbClr val="FFFFFF"/></a:lt1><a:dk2><a:srgbClr val="666666"/></a:dk2><a:lt2><a:srgbClr val="FBFAF7"/></a:lt2><a:accent1><a:srgbClr val="2B74B1"/></a:accent1><a:accent2><a:srgbClr val="449B7A"/></a:accent2><a:accent3><a:srgbClr val="E88B3A"/></a:accent3><a:accent4><a:srgbClr val="8A8A8A"/></a:accent4><a:accent5><a:srgbClr val="DAE7F4"/></a:accent5><a:accent6><a:srgbClr val="F7F1E8"/></a:accent6><a:hlink><a:srgbClr val="2B74B1"/></a:hlink><a:folHlink><a:srgbClr val="449B7A"/></a:folHlink></a:clrScheme><a:fontScheme name="DTM"><a:majorFont><a:latin typeface="Microsoft YaHei"/><a:ea typeface="Microsoft YaHei"/></a:majorFont><a:minorFont><a:latin typeface="Microsoft YaHei"/><a:ea typeface="Microsoft YaHei"/></a:minorFont></a:fontScheme><a:fmtScheme name="DTM"><a:fillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:fillStyleLst><a:lnStyleLst><a:ln w="9525"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:ln></a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst/></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:bgFillStyleLst></a:fmtScheme></a:themeElements></a:theme>
- ''')
- stamp = datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
- write(BUILD / "docProps/core.xml", f'''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dc:title>订单与供应监测模块架构汇报</dc:title><dc:creator>Codex</dc:creator><cp:lastModifiedBy>Codex</cp:lastModifiedBy><dcterms:created xsi:type="dcterms:W3CDTF">{stamp}</dcterms:created><dcterms:modified xsi:type="dcterms:W3CDTF">{stamp}</dcterms:modified></cp:coreProperties>
- ''')
- write(BUILD / "docProps/app.xml", f'''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><Application>Codex OpenXML Generator</Application><PresentationFormat>Widescreen</PresentationFormat><Slides>{len(slides)}</Slides><Company>DTM</Company></Properties>
- ''')
- with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED) as zf:
- for root, _, files in os.walk(BUILD):
- for file in files:
- path = Path(root) / file
- zf.write(path, path.relative_to(BUILD).as_posix())
- shutil.rmtree(BUILD)
- if __name__ == "__main__":
- build()
- print(OUT)
|