需要帮助优化 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)
当使用带有单元格的表格时,这比您想象的要困难。 首先,您必须确保事先有足够的可用列,因为不能选择使用 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")