0
votes

I've managed to read an existing .pptx file in Python using python-pptx and i can access the tables in the powerpoint slides.

What i fail to do: Get the border color of a cell.

I want to insert data in table cells depending on the tables border color, e. g. in a table cell with green borders, insert "111" and in a cell with red borders insert "222".

Inserting values works, but without checking the tables (or cells) border color, the data ends up in wrong places.

There is more than one table on a ppt slide. The tables are all in unique border colors, e. g. one table has solid green borders all around, another one is completely green, another one blue, and so on.

This is how i iterate the page tables and access cells:

from pptx import Presentation

pptx_file = r"my_file_here"
with open(pptx_file, "rb") as pptx:
    prs = Presentation(pptx)
    for slide in prs.slides:
        for shape in slide.shapes:
            if not shape.has_table:
                continue
            table = shape.table

            my_input_field = table.cell(0, 1)

I want to insert in my_input_field based on the color, but don't know how to get/check/read it's border color?

I'm afraid i'm too stupid to handle the infos there, that doesn't help me: https://python-pptx.readthedocs.io/en/latest/api/dml.html#pptx.dml.color.ColorFormat

Can someone point me in the right direction?

Edit:

I'm pretty sure there is a way to access the color. The docs state:

cell

A cell has a background fill, borders, margins, and several other formatting settings that can be customized on a cell-by-cell basis.

But i couldn't figure how to access this properties. I've had a look at the code snippets that set a color, but i can't make any sense out of this examples.

Edit 2: My Workaround

I've still no solution, but in case someone stumbles upon this - here is my little workaround: I put the color name of a table in the table itself, as text.

When iterating all tables, i read this text from the table and delete it there. This way i can distinguish the tables and add the correct informations.

It's not really nice, but it works.

1

1 Answers

2
votes

python-pptx does not seem to support cell borders in the current version, but there is an alternative:

PPTX files use XML and python-pptx can be used to access that XML and find the data that you want if you know where to look.

I used a simple presentation with only one table and two cells like this:

Red and green cells

Notice that the middle line between the cells has to be either red or green.

Using this code I got the XML of the two cells:

# Here goes the code of the question

# Iterate over the rows of the table
for i, row in enumerate(table.rows):
    # Iterate over the cells of the row
    for j, cell in enumerate(row.cells):
        # Get the table cell properties (tcPr) from the table cell (tc)
        tcPr = cell._tc.get_or_add_tcPr()
        print(f"XML of tcPR of cell ({i}, {j}):")
        print(tcPr.xml)

XML:

<a:tcPr xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
  <a:lnL w="12700" cap="flat" cmpd="sng" algn="ctr">
    <a:solidFill>
      <a:srgbClr val="FF0000"/> <!-- This is the color (RGB in hex format) -->
    </a:solidFill>
    <a:prstDash val="solid"/>
    <a:round/>
    <a:headEnd type="none" w="med" len="med"/>
    <a:tailEnd type="none" w="med" len="med"/>
  </a:lnL>
  <a:lnR w="12700" cap="flat" cmpd="sng" algn="ctr">
    <!-- Omitted for brevity -->
  </a:lnR>
  <a:lnT w="12700" cap="flat" cmpd="sng" algn="ctr">
    <!-- Omitted for brevity -->
  </a:lnT>
  <a:lnB w="12700" cap="flat" cmpd="sng" algn="ctr">
    <!-- Omitted for brevity -->
  </a:lnB>
</a:tcPr>

<a:tcPr xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
  <!-- Omitted for brevity -->
</a:tcPr>

The colors are specified for every line: left (lnL), right (lnR), top (lnT), bottom (lnB).

To get the color of one of the lines you can use XPath:

# Here goes the code of the question

# Iterate over the rows of the table
for i, row in enumerate(table.rows):
    # Iterate over the cells of the row
    for j, cell in enumerate(row.cells):
        # Get the table cell properties (tcPr) from the table cell (tc)
        tcPr = cell._tc.get_or_add_tcPr()
        # Use XPath to find the color
        result = tcPr.xpath("./a:lnL/a:solidFill/a:srgbClr/@val")
        # results is a list
        # Get the first element if it exists
        left_line_color = result[0] if result else None
        print(f"Left line color of cell ({i}, {j}): {left_line_color}")

# Output:
# Left line color of cell (0, 0): FF0000
# Left line color of cell (0, 1): 00FF00

Demo in Colab