201 lines
7.2 KiB
Python
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()
|