Files
fmd26/build_canvas.py

201 lines
7.2 KiB
Python

# -*- coding: utf-8 -*-
from docx import Document
from docx.shared import Pt, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.section import WD_ORIENT
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
OUT = 'Метод_Дегтярева_канвас.docx'
GREEN = RGBColor(0x2E, 0x7D, 0x5B)
ROSE = RGBColor(0xB0, 0x3A, 0x55)
DARK = RGBColor(0x1A, 0x1A, 0x1A)
GRAY = RGBColor(0x5F, 0x66, 0x6B)
LIGHT = RGBColor(0x8A, 0x90, 0x95)
def set_run(run, name='Arial', size=9, bold=False, italic=False, color=DARK):
run.font.name = name
run.font.size = Pt(size)
run.font.bold = bold
run.font.italic = italic
run.font.color.rgb = color
rPr = run._element.get_or_add_rPr()
rFonts = rPr.find(qn('w:rFonts'))
if rFonts is None:
rFonts = OxmlElement('w:rFonts')
rPr.append(rFonts)
for attr in ('w:ascii', 'w:hAnsi', 'w:eastAsia', 'w:cs'):
rFonts.set(qn(attr), name)
def shade(cell, hex_color):
tcPr = cell._tc.get_or_add_tcPr()
shd = OxmlElement('w:shd')
shd.set(qn('w:val'), 'clear')
shd.set(qn('w:color'), 'auto')
shd.set(qn('w:fill'), hex_color)
tcPr.append(shd)
def cell_margins(table, top=60, bottom=60, left=140, right=140):
tblPr = table._tbl.tblPr
mar = OxmlElement('w:tblCellMar')
for tag, val in (('top', top), ('left', left), ('bottom', bottom), ('right', right)):
el = OxmlElement('w:' + tag)
el.set(qn('w:w'), str(val))
el.set(qn('w:type'), 'dxa')
mar.append(el)
tblPr.append(mar)
def table_borders(table, color='C9D6CF', size=6):
tblPr = table._tbl.tblPr
borders = OxmlElement('w:tblBorders')
for edge in ('top', 'left', 'bottom', 'right', 'insideH', 'insideV'):
el = OxmlElement('w:' + edge)
el.set(qn('w:val'), 'single')
el.set(qn('w:sz'), str(size))
el.set(qn('w:space'), '0')
el.set(qn('w:color'), color)
borders.append(el)
tblPr.append(borders)
def dotted_line(paragraph, color='C9D6CF'):
pPr = paragraph._p.get_or_add_pPr()
pBdr = OxmlElement('w:pBdr')
bottom = OxmlElement('w:bottom')
bottom.set(qn('w:val'), 'dotted')
bottom.set(qn('w:sz'), '4')
bottom.set(qn('w:space'), '1')
bottom.set(qn('w:color'), color)
pBdr.append(bottom)
pPr.append(pBdr)
def add_line_table(cell, lines=3, width_cm=12.4):
tbl = cell.add_table(rows=lines, cols=1)
tbl.autofit = False
tblPr = tbl._tbl.tblPr
borders = OxmlElement('w:tblBorders')
for edge in ('top', 'left', 'bottom', 'right', 'insideH', 'insideV'):
el = OxmlElement('w:' + edge)
el.set(qn('w:val'), 'none')
borders.append(el)
tblPr.append(borders)
for row in tbl.rows:
row.height = Cm(0.55)
c = row.cells[0]
c.width = Cm(width_cm)
tcPr = c._tc.get_or_add_tcPr()
tcBorders = OxmlElement('w:tcBorders')
bottom = OxmlElement('w:bottom')
bottom.set(qn('w:val'), 'dotted')
bottom.set(qn('w:sz'), '4')
bottom.set(qn('w:space'), '0')
bottom.set(qn('w:color'), 'AFC4B9')
tcBorders.append(bottom)
tcPr.append(tcBorders)
p = c.paragraphs[0]
p.paragraph_format.space_before = Pt(0)
p.paragraph_format.space_after = Pt(0)
p.paragraph_format.line_spacing = 1.0
def add_block(cell, num, title, prompt, color, fill, lines=3):
cell.text = ''
shade(cell, fill)
p = cell.paragraphs[0]
p.paragraph_format.space_before = Pt(0)
p.paragraph_format.space_after = Pt(2)
r = p.add_run(num + ' ')
set_run(r, size=8, bold=True, color=color)
r = p.add_run(title)
set_run(r, name='Georgia', size=12, bold=True, color=color)
p = cell.add_paragraph()
p.paragraph_format.space_before = Pt(0)
p.paragraph_format.space_after = Pt(6)
p.paragraph_format.line_spacing = 1.0
r = p.add_run(prompt)
set_run(r, size=8, color=GRAY)
add_line_table(cell, lines=lines)
def build():
doc = Document()
section = doc.sections[0]
section.orientation = WD_ORIENT.LANDSCAPE
section.page_width = Cm(29.7)
section.page_height = Cm(21.0)
section.top_margin = Cm(1.1)
section.bottom_margin = Cm(1.0)
section.left_margin = Cm(1.2)
section.right_margin = Cm(1.2)
normal = doc.styles['Normal']
normal.font.name = 'Arial'
normal.font.size = Pt(9)
normal.font.color.rgb = DARK
# Header
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(0)
p.paragraph_format.space_after = Pt(0)
r = p.add_run('КАНВАС «МЕТОД ДЕГТЯРЕВА»')
set_run(r, name='Georgia', size=18, bold=True, color=GREEN)
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(2)
p.paragraph_format.space_after = Pt(4)
r = p.add_run('Команда: ______________________________ Проблема: ______________________________________ Трек: «Метод Дегтярева»')
set_run(r, size=8.5, color=GRAY)
# Table
table = doc.add_table(rows=4, cols=2)
table.alignment = WD_TABLE_ALIGNMENT.CENTER
table.autofit = False
table_borders(table)
cell_margins(table)
for row in table.rows:
row.height = Cm(3.45)
for cell in row.cells:
cell.width = Cm(13.5)
blocks = [
('01', 'ЗАБОЙ', 'Что болит на самом деле? У кого? Доказательства: факты, интервью, данные.', GREEN, 'F3F9F6'),
('02', 'СМЕТА', 'Кому и насколько станет лучше? Сколько людей? Как измерим? 3 метрики.', GREEN, 'F3F9F6'),
('03', 'ЗАВОД', 'Что нужно, чтобы решалось системно? Люди, данные, партнёры, деньги.', GREEN, 'F3F9F6'),
('04', 'РОЗА', 'Как люди это почувствуют? Сценарий использования. Что скажут?', ROSE, 'FDF4F6'),
('05', 'ХОЗЯИН', 'Кто останется после форума? Модель, команда, первый шаг.', ROSE, 'FDF4F6'),
('06', 'РИСКИ', 'Что может пойти не так? Как снижаем?', ROSE, 'FDF4F6'),
('07', 'МЕТРИКИ', '3 цифры, по которым поймём, что получилось.', GREEN, 'F3F9F6'),
('08', 'ПИТЧ', 'Одна фраза, с которой начнём защиту.', GREEN, 'F3F9F6'),
]
for idx, (num, title, prompt, color, fill) in enumerate(blocks):
row = idx // 2
col = idx % 2
add_block(table.cell(row, col), num, title, prompt, color, fill, lines=3)
# Footer
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(4)
p.paragraph_format.space_after = Pt(0)
r = p.add_run('Заполняйте по шагам. Не переходите к следующему блоку, пока не закрыт предыдущий. • Метод Дегтярева • Форум молодёжи Донбасса, 2026')
set_run(r, size=7.5, color=LIGHT)
doc.save(OUT)
print('saved', OUT)
if __name__ == '__main__':
build()