如何确保文本完全适合表格中的单元格,防止文本在 PowerPoint 幻灯片上溢出?

问题描述 投票:0回答:1

需要帮助优化 PowerPoint 表格单元格中的文本放置以防止溢出。目标是将代码放置在第二列中,而不是溢出,如预期输出图像所示。为了清晰起见,共享相关代码和图像。感谢您的帮助!

数据:

代码:

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

# Assuming you have the small_grid DataFrame and ranking_definitions
small_grid = pd.read_excel("E:/Praveen/Technical team/WHG/WHG_process_phase_1_09272023.xlsx", sheet_name="Small_grid")

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

# 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

# Determine the number of columns
num_columns = len(ranking_definitions)

# Calculate column width
column_width = available_width / num_columns

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


shape = slide.shapes.add_table(rows=2, 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

# Set column widths
for i in range(num_columns):
    table.columns[i].width = int(column_width)

# Set header row style
header_row = table.rows[0]
header_row.height = Inches(0.7)
for i, (ranking_code, ranking_name) in enumerate(ranking_definitions.items()):
    cell = header_row.cells[i]  # No need to shift by 1 as there is no additional row
    cell.text = ranking_name
    cell.text_frame.paragraphs[0].font.size = Pt(12)  # 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 data
data_row = table.rows[1]
for j, (ranking_code, ranking_name) in enumerate(ranking_definitions.items()):
    key = ranking_name  # Adjust this line if needed
    tickers = '\n'.join(small_grid[small_grid['Rankings'] == ranking_code]['Tickers'].tolist())
    
    # Adjust the font size for data rows
    cell = data_row.cells[j]
    cell.text = tickers
    
    # Set font size for each paragraph in the cell
    for paragraph in cell.text_frame.paragraphs:
        paragraph.font.size = Pt(10)

我得到的输出

我想要的输出

python powerpoint python-pptx
1个回答
0
投票

当使用带有单元格的表格时,这比您想象的要困难。 首先,您必须确保事先有足够的可用列,因为不能选择使用 pptx python 包进行拆分。

就我而言,我为每个排名制作了 3 列:

num_columns = len(ranking_definitions)*3

然后你需要合并标题:

#creating 3 columns per ranking and the merge them
for i, (ranking_code, ranking_name) in enumerate(ranking_definitions.items()):

    cell = header_row.cells[3*i]  # No need to shift by 1 as there is no additional row
    cell.text = ranking_name
    cell.text_frame.paragraphs[0].font.size = Pt(12)  # 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
    # merge header columns into 1
    cell.merge(header_row.cells[i*3+2])

填充数据时,您必须限制列的大小(

size_column = 35
)。然后用一些条件填充该列。请参阅下面的代码:

for j, (ranking_code, ranking_name) in enumerate(ranking_definitions.items()):
    key = ranking_name  # Adjust this line if needed
    tickers_list=small_grid[small_grid['Rankings'] == ranking_code]['Tickers'].tolist()
    #max entrys per column
    column_counter= len(tickers_list) // size_column
    size_column = 35

    for i in range(column_counter+1):
        tickers = '\n'.join(tickers_list[size_column * i:size_column * (i + 1)])
        cell = data_row.cells[3 * j+i]
        cell.text =tickers

        # Set font size for each paragraph in the cell
        for paragraph in cell.text_frame.paragraphs:
            paragraph.font.size = Pt(9)

最后一步是删除单元格边框。 pptx python 包没有这方面的实现,但似乎有一个解决方法(https://github.com/scanny/python-pptx/issues/573 与 Utkarsh Sinha)

最后看起来像这样:

缺点是如果您有超过 3*35 个条目,您将会遇到问题。所以最好建立一些更多的限制等。在 pptx python 中使用表/单元格似乎是相当令人发指的。也许使用文本框会更好。这些框还有自动填充选项。

完整代码可以在这里找到:

import pandas as pd
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN
from pptx.oxml.xmlchemy import OxmlElement
from datetime import date

# Assuming you have the small_grid DataFrame and ranking_definitions
small_grid = pd.read_excel("book1.xlsx", sheet_name="Small_grid")

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

# 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

# Determine the number of columns times 3 to create 3 availabe colums per ranking
num_columns = len(ranking_definitions)*3

# Calculate column width
column_width = available_width / num_columns

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

shape = slide.shapes.add_table(rows=2, 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

# Set column widths
for i in range(num_columns):
    table.columns[i].width = int(column_width)


# Set header row style
header_row = table.rows[0]
header_row.height = Inches(0.7)

#creating 3 columns per ranking and the merge them
for i, (ranking_code, ranking_name) in enumerate(ranking_definitions.items()):

    cell = header_row.cells[3*i]  # No need to shift by 1 as there is no additional row
    cell.text = ranking_name
    cell.text_frame.paragraphs[0].font.size = Pt(12)  # 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
    # merge header columns into 1
    cell.merge(header_row.cells[i*3+2])


# Populate table with data
data_row = table.rows[1]



for j, (ranking_code, ranking_name) in enumerate(ranking_definitions.items()):
    key = ranking_name  # Adjust this line if needed
    tickers_list=small_grid[small_grid['Rankings'] == ranking_code]['Tickers'].tolist()
    #max entrys per column
    column_counter= len(tickers_list) // size_column
    size_column = 35

    for i in range(column_counter+1):
        tickers = '\n'.join(tickers_list[size_column * i:size_column * (i + 1)])
        cell = data_row.cells[3 * j+i]
        cell.text =tickers

        # Set font size for each paragraph in the cell
        for paragraph in cell.text_frame.paragraphs:
            paragraph.font.size = Pt(9)

#removing the cells border.
#src code from https://github.com/scanny/python-pptx/issues/573 with Utkarsh Sinha
def SubElement(parent, tagname, **kwargs):
    element = OxmlElement(tagname)
    element.attrib.update(kwargs)
    parent.append(element)
    return element

def _set_cell_border(cell, border_color="FFFFFF", border_width='12700'):
    """ Hack function to enable the setting of border width and border color
        - left border
        - right border
        - top border
        - bottom border
    """
    tc = cell._tc
    tcPr = tc.get_or_add_tcPr()

    # Right Cell Border
    lnR = SubElement(tcPr, 'a:lnR', w='3175', cap='flat', cmpd='sng', algn='ctr')
    lnR_solidFill = SubElement(lnR, 'a:solidFill')
    lnR_srgbClr = SubElement(lnR_solidFill, 'a:srgbClr', val=border_color)
    lnR_prstDash = SubElement(lnR, 'a:prstDash', val='solid')
    lnR_round_ = SubElement(lnR, 'a:round')
    lnR_headEnd = SubElement(lnR, 'a:headEnd', type='none', w='med', len='med')
    lnR_tailEnd = SubElement(lnR, 'a:tailEnd', type='none', w='med', len='med')

for c in range(num_columns):
    if c%3!=0:
        cell=data_row.cells[c-1]
        _set_cell_border(cell, border_color="FFFFFF", border_width="0")

presentation.save("test.pptx")
© www.soinside.com 2019 - 2024. All rights reserved.