# -*- 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()