def read_paragraph(self, paragraph: _Paragraph) -> 'PPTXParagraphStyle': """Read attributes from a _Paragraph object.""" self.alignment = paragraph.alignment self.level = paragraph.level self.line_spacing = paragraph.line_spacing self.space_before = paragraph.space_before self.space_after = paragraph.space_after self.font_style = PPTXFontStyle().read_font(paragraph.font) return self
def run(save_dir: str): pp = PPTXCreator(TemplateExample()) slide_01 = pp.add_slide("Table style example 01 - slide 01") slide_02 = pp.add_slide("Table style example 01 - slide 02") slide_03 = pp.add_slide("Table style example 01 - slide 03") slide_04 = pp.add_slide("Table style example 01 - slide 04") slide_05 = pp.add_slide("Table style example 01 - slide 05") slide_06 = pp.add_slide("Table style example 01 - slide 06") # data for a table with 5 rows and 3 cols. table_data = [] table_data.append([1, "The second column is longer."]) # rows can have different length table_data.append([2, "Table entries don't have to be strings,"]) # there is specific type needed for entries (implemented as text=f"{entry}") table_data.append([3, "because its implemented as text=f'{entry}'"]) table_data.append([4, "also note: the number of entries per row is", " not fixed"]) table_data.append([5, "That's it for now."]) # We can add these data as a table title_slide with PPTXCreator.add_table()... table_01 = pp.add_table(slide_01, table_data) # ... but if you open the slide in PowerPoint there are a few issues: # 1) the table is positioned in the top left corner - overlapping the title # 2) the first row is formated differently (like a column header) # 3) all columns have the same width (1 inch) # 4) the table width is too small (for the used paragraph size) # Lets handle the the position first using optional PPTXPosition parameter table_02 = pp.add_table(slide_02, table_data, PPTXPosition(0.02, 0.14)) # for more control we use PPTXTableStyle table_style = PPTXTableStyle() table_style.first_row_header = False table_style.width = 6.1 # table width in inches table_style.col_ratios = [0.3, 5, 1.3] table_03 = pp.add_table(slide_03, table_data, PPTXPosition(0.02, 0.14), table_style) # It's also possible to add the position directly to the table style: table_style.position = PPTXPosition(0.02, 0.14) # or to set the table width as a fraction of slide width: table_style.set_width_as_fraction(0.49) # change row/col bending table_style.col_banding = True table_style.row_banding = False table_04 = pp.add_table(slide_04, table_data, table_style=table_style) # we could also add a paragraph-style and a cell-style table_style.font_style = PPTXFontStyle().set(italic=True, name="Arial", color_rgb=(100, 200, 30)) # todo: cell-style table_05 = pp.add_table(slide_05, table_data, table_style=table_style) # you could also use a table style on an existing table table_06 = pp.add_table(slide_06, table_data) table_style.write_shape(table_06) pp.save(os.path.join(save_dir, "table_style_example_01.pptx"), overwrite=True)
def add_text_box(self, slide, text: str, position: PPTXPosition = None, font: PPTXFontStyle = None) -> Shape: """ Add a text box with given text using given position and paragraph. Uses self.default_position if no position is given. """ width = height = Inches( 1) # no auto-resizing of shape -> has to be done inside PowerPoint if position is None: position = self.default_position result = slide.shapes.add_textbox(**position.dict(), width=width, height=height) result.text_frame.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT result.text_frame.text = text # first paragraph if font: font.write_shape(result) return result
def change_paragraph_text_to(paragraph, text): """ Change text of paragraph to text, but keep format of first run. :param paragraph: :param text: :return: """ from pptx_tools.font_style import PPTXFontStyle # local import to prevent circle import error font = PPTXFontStyle() font.read_font(paragraph.runs[0].font) paragraph.text = text font.write_paragraph(paragraph)
def copy_font(_from: 'Font', _to: 'Font') -> None: """Copies settings from one pptx.text.text.Font to another.""" from pptx_tools.font_style import PPTXFontStyle # local import to prevent circle import error font_style = PPTXFontStyle() font_style.read_font(_from) font_style.write_font(_to)
class PPTXParagraphStyle: """ Helper class to deal with paragraphs in python-pptx. """ def __init__(self): # the following values cannot be inherited from parent object(?) ----------------------------------------------- self.alignment: Optional[PP_PARAGRAPH_ALIGNMENT] = None # PP_PARAGRAPH_ALIGNMENT.CENTER/JUSTIFY/LEFT/RIGHT/... self.level: Optional[int] = None # 0 .. 8 (indentation level) self.line_spacing: Optional[float] = None self.space_before: Optional[float] = None self.space_after: Optional[float] = None # -------------------------------------------------------------------------------------------------------------- self.font_style: Optional[PPTXFontStyle] = None def read_paragraph(self, paragraph: _Paragraph) -> 'PPTXParagraphStyle': """Read attributes from a _Paragraph object.""" self.alignment = paragraph.alignment self.level = paragraph.level self.line_spacing = paragraph.line_spacing self.space_before = paragraph.space_before self.space_after = paragraph.space_after self.font_style = PPTXFontStyle().read_font(paragraph.font) return self def set(self, alignment: Optional[PP_PARAGRAPH_ALIGNMENT] = _DO_NOT_CHANGE, level: Optional[int] = _DO_NOT_CHANGE, line_spacing: Optional[float] = _DO_NOT_CHANGE, space_before: Optional[float] = _DO_NOT_CHANGE, space_after: Optional[float] = _DO_NOT_CHANGE ) -> 'PPTXParagraphStyle': """Convenience method to set several paragraph attributes together.""" if alignment is not _DO_NOT_CHANGE: self.alignment = alignment if level is not _DO_NOT_CHANGE: self.level = level if line_spacing is not _DO_NOT_CHANGE: self.line_spacing = line_spacing if space_before is not _DO_NOT_CHANGE: self.space_before = space_before if space_after is not _DO_NOT_CHANGE: self.space_after = space_after return self def write_paragraph(self, paragraph: _Paragraph) -> None: """Write paragraph style to given paragraph.""" if self.alignment is not None: paragraph.alignment = self.alignment if self.level is not None: paragraph.level = self.level if self.line_spacing is not None: paragraph.line_spacing = self.line_spacing if self.font_style is not None: self.font_style.write_paragraph(paragraph) def write_shape(self, shape: Shape) -> None: """ Write attributes to all paragraphs in given pptx.shapes.autoshape.Shape. Raises TypeError if given shape has no text_frame or table. """ if shape.has_text_frame: self.write_text_frame(shape.text_frame) elif shape.has_table: for cell in shape.table.iter_cells(): if not cell.is_spanned: self.write_text_frame(cell.text_frame) else: raise TypeError("Cannot write paragraph for given shape (has no text_frame or table)") def write_text_frame(self, text_frame): """ Write attributes to all paragraphs in given text_frame. """ for paragraph in text_frame.paragraphs: self.write_paragraph(paragraph)
def font_default() -> PPTXFontStyle: # paragraph for normal text result = PPTXFontStyle() # result.language_id = MY_DEFAULT_LANGUAGE # result.name = MY_DEFAULT_FONT_NAME result.size = 14 return result
def run(save_dir: str): filename_pptx = os.path.join(save_dir, "font_style_example_01.pptx") pp = PPTXCreator(TemplateExample()) # default language and paragraph-type for all created PPTXFontStyle instances: PPTXFontStyle.lanaguage_id = MSO_LANGUAGE_ID.ENGLISH_UK PPTXFontStyle.name = "Roboto" title_slide = pp.add_title_slide("Font style example presentation") font = font_title( ) # returns a PPTXFontStyle instance with bold paragraph and size = 32 Pt font.write_shape( title_slide.shapes.title ) # change paragraph attributes for all paragraphs in shape text_01 = "This text has four paragraphs. This is the first.\n" \ "Das ist der zweite ...\n" \ "... the third ...\n" \ "... and the last." my_font = PPTXFontStyle() my_font.size = 16 text_shape_01 = pp.add_text_box(title_slide, text_01, PPTXPosition(0.02, 0.24), my_font) my_font.set(size=22, bold=True, language_id=MSO_LANGUAGE_ID.GERMAN, strikethrough=TEXT_STRIKE_VALUES.SingleStrike, caps=TEXT_CAPS_VALUES.All) my_font.write_paragraph(text_shape_01.text_frame.paragraphs[1]) my_font.set(size=18, bold=False, italic=True, name="Vivaldi", language_id=MSO_LANGUAGE_ID.ENGLISH_UK, underline=MSO_TEXT_UNDERLINE_TYPE.WAVY_DOUBLE_LINE, color_rgb=(255, 0, 0), strikethrough=None, caps=None) my_font.write_paragraph(text_shape_01.text_frame.paragraphs[2]) my_font = PPTXFontStyle() my_font.set(size=52, bold=True) my_fill = PPTXFillStyle() my_fill.fill_type = FillType.PATTERNED my_fill.fore_color_rgb = (255, 0, 0) my_fill.back_color_rgb = (0, 0, 255) from pptx.enum.dml import MSO_PATTERN_TYPE my_fill.pattern = MSO_PATTERN_TYPE.PERCENT_50 my_font.fill_style = my_fill my_font.write_paragraph(text_shape_01.text_frame.paragraphs[3]) text_02 = "This text uses copied paragraph." my_copied_font = PPTXFontStyle() my_copied_font.read_font(text_shape_01.text_frame.paragraphs[1].font) text_shape_02 = pp.add_text_box(title_slide, text_02, PPTXPosition(0.42, 0.24), my_copied_font) pp.save(filename_pptx, overwrite=True)