Unable to Arrange Tickers Side-by-Side in PowerPoint Table Cells

50 Views Asked by At

I am working on a Python script that generates a PowerPoint presentation with a table containing tickers. I am using the python-pptx library for this task. However, I am facing an issue in arranging the tickers side-by-side within each cell of the table.

I have a dictionary (segregated_data) containing sectors and their respective rankings, where each combination has a list of tickers. The tickers are currently displayed in a column within each cell, but I want them to be arranged side-by-side.

import pandas as pd
from pptx import Presentation
from pptx.util import Inches
from pptx.enum.text import PP_ALIGN
from pptx.enum.text import MSO_AUTO_SIZE
from pptx.util import Pt
from datetime import date

big_grid = pd.read_excel("Testing.xlsx")


sector_definitions = {
    100: 'Energy',
    200: 'Basic Materials',
    300: 'Industrial Manufacturing',
    400: 'Utilities',
    500: 'Services',
    600: 'Financials',
    700: 'Transportation',
    800: 'HealthCare',
    900: 'Consumer Staples',
    1000: 'Consumer Cyclicals',
    1200: 'Technology',
    1400: 'Communication / Media'
}

ranking_definitions = {
    1: 'Bottom Fishing',
    2: 'Positive Developing',
    3: 'Positive Trending',
    4: 'Pullback Opportunity',
    5: 'Negative Developing',
    6: 'Negative Trending'
}

# Segregate the data based on sector and ranking definitions
segregated_data = {}
for sector_code, sector_name in sector_definitions.items():
    sector_data = big_grid[big_grid['Sector'] == sector_code]
    for ranking_code, ranking_name in ranking_definitions.items():
        ranking_data = sector_data[sector_data['Ranking'] == ranking_code]
        if not ranking_data.empty:
            key = f'{ranking_name} - {sector_name}'
            segregated_data[key] = ranking_data['Tickers'].tolist()
            

# Create a PowerPoint presentation
presentation = Presentation()
slide = presentation.slides.add_slide(presentation.slide_layouts[6])

# Get the dimensions of the slide
slide_width = presentation.slide_width
slide_height = presentation.slide_height

# Set the margins and padding
margin_left = Inches(0.3)
margin_right = Inches(0.3)
margin_top = Inches(1.2)
margin_bottom = Inches(0.7)

# Calculate the available width and height for the table
available_width = slide_width - margin_left - margin_right
available_height = slide_height - margin_top - margin_bottom

top_left_text = slide.shapes.add_textbox(left=Inches(0.3), top=Inches(0.3), width=Inches(2), height=Inches(0.1)).text_frame
top_left_text.text = "Macro Research | Technical Research"
for paragraph in top_left_text.paragraphs:
    paragraph.font.size = Pt(12)
    paragraph.font.bold = True

top_right_text = slide.shapes.add_textbox(left=Inches(8.7), top=Inches(0.3), width=Inches(2), height=Inches(0.1)).text_frame
top_right_text.text = date.today().strftime('%B %d, %Y')
for paragraph in top_right_text.paragraphs:
    paragraph.font.size = Pt(8)
    
title = slide.shapes.add_textbox(left=margin_left, top=margin_top / 2, width=available_width, height=Inches(0.5)).text_frame
title.text = "Weekly Homework Grids"
title.paragraphs[0].alignment = PP_ALIGN.CENTER
for paragraph in title.paragraphs:
    paragraph.font.size = Pt(16)
    paragraph.font.bold = True
    

# Determine the number of columns and rows based on the data
num_columns = len(ranking_definitions) + 1
num_rows = len(sector_definitions) + 1

# Add a table to the slide
table_left = margin_left
table_top = margin_top
table_width = available_width
table_height = available_height

shape = slide.shapes.add_table(rows=num_rows, cols=num_columns, left=table_left, top=table_top, width=table_width, height=table_height)
tbl =  shape._element.graphic.graphicData.tbl
style_id = "{5940675A-B579-460E-94D1-54222C63F5DA}"
tbl[0][-1].text = style_id

table = shape.table

for row in table.rows:
    for cell in row.cells:
        cell.text_frame.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT
        cell.text_frame.word_wrap = True

# Set header row style
header_row = table.rows[0]
for i, (ranking_code, ranking_name) in enumerate(ranking_definitions.items()):
    cell = header_row.cells[i + 1]  # Shift by 1 to accommodate row names
    cell.text = ranking_name
    cell.text_frame.paragraphs[0].font.size = Pt(7)  # Adjust the font size for the header row
    cell.text_frame.paragraphs[0].font.bold = True
    cell.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER

# Populate table with sector data
for i, (sector_code, sector_name) in enumerate(sector_definitions.items()):
    row = table.rows[i + 1]
    row.cells[0].text = sector_name
    row.cells[0].text_frame.text = sector_name
    row.cells[0].text_frame.paragraphs[0].font.size = Pt(7)  # Adjust the font size for data rows
    row.cells[0].text_frame.paragraphs[0].font.bold = True
    row.cells[0].text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER

    for j, (ranking_code, ranking_name) in enumerate(ranking_definitions.items()):
        key = f'{ranking_name} - {sector_name}'
        tickers = segregated_data.get(key, [])
        cell = row.cells[j + 1]  # Shift by 1 to accommodate row names
        
        cell.text = "\n".join(tickers)
        for paragraph in cell.text_frame.paragraphs:
            paragraph.font.size = Pt(5)

I have tried adjusting paragraph alignment and using line breaks ("\n"), but I haven't been successful in achieving the desired side-by-side arrangement.

Current output: enter image description here

Desired output: enter image description here

Any guidance on how to modify the code to arrange tickers side-by-side within each table cell would be greatly appreciated. Thank you!

0

There are 0 best solutions below