Search code examples
c#powerpointopenxmlopenxml-sdk

How to add border to cell with openxml in PowerPoint?


I am trying to change the top border of a table in PowerPoint via OpenXml, but it has not worked for me. The cell currently has a left, right, and bottom border, but when I try to copy the bottom border and add it to the top border, PowerPoint does not reflect the change.

What do I need to change or am I doing wrong to make it work?

I currently have the following code to copy the bottom border and replace it.

   BottomBorderLineProperties btp = (BottomBorderLineProperties)celda.TableCellProperties.BottomBorderLineProperties.CloneNode(true);

   TopBorderLineProperties tbp = new TopBorderLineProperties()
   {
         Alignment = btp.Alignment,
         CapType = btp.CapType,
         CompoundLineType = btp.CompoundLineType,
         MCAttributes = btp.MCAttributes,
         Width = btp.Width
    };

   foreach(OpenXmlElement element in btp.ChildElements)
   {
       tbp.Append(element.CloneNode(true));
   }

   celda.TableCellProperties.TopBorderLineProperties = tbp;

Thanks!

PS: Sorry for my english


Solution

  • In order to set the top border of a cell in the middle of a PowerPoint table, you have to complete 2 steps:

    Step 1: set the bottom border of the cell directly above the cell in question and

    Step 2: set the top border of the cell in question (you have that part)

    I determined this by using the OpenXML Productivity Tool. I took a simple 1 slide PowerPoint file named Before.pptx with a table cell that had the left, bottom and right borders.

    enter image description here

    Then I added the top border (using PowerPoint 2016) and saved the file as After.pptx. I then used the Productivity Tool to diff the 2 files and reverse engineer the C# code required to make Before.pptx look like After.pptx. The important code you need is displayed here:

            //STEP 1 CODE STARTS HERE
            A.Table table1=graphicData1.GetFirstChild<A.Table>();
    
            A.TableRow tableRow1=table1.GetFirstChild<A.TableRow>();
            A.TableRow tableRow2=table1.Elements<A.TableRow>().ElementAt(1);
    
            A.TableCell tableCell1=tableRow1.Elements<A.TableCell>().ElementAt(2);
    
            A.TableCellProperties tableCellProperties1=tableCell1.GetFirstChild<A.TableCellProperties>();
    
            A.BottomBorderLineProperties bottomBorderLineProperties1 = new A.BottomBorderLineProperties(){ Width = 12700, CapType = A.LineCapValues.Flat, CompoundLineType = A.CompoundLineValues.Single, Alignment = A.PenAlignmentValues.Center };
    
            A.SolidFill solidFill1 = new A.SolidFill();
            A.SchemeColor schemeColor1 = new A.SchemeColor(){ Val = A.SchemeColorValues.Text1 };
    
            solidFill1.Append(schemeColor1);
            A.PresetDash presetDash1 = new A.PresetDash(){ Val = A.PresetLineDashValues.Solid };
            A.Round round1 = new A.Round();
            A.HeadEnd headEnd1 = new A.HeadEnd(){ Type = A.LineEndValues.None, Width = A.LineEndWidthValues.Medium, Length = A.LineEndLengthValues.Medium };
            A.TailEnd tailEnd1 = new A.TailEnd(){ Type = A.LineEndValues.None, Width = A.LineEndWidthValues.Medium, Length = A.LineEndLengthValues.Medium };
    
            bottomBorderLineProperties1.Append(solidFill1);
            bottomBorderLineProperties1.Append(presetDash1);
            bottomBorderLineProperties1.Append(round1);
            bottomBorderLineProperties1.Append(headEnd1);
            bottomBorderLineProperties1.Append(tailEnd1);
            tableCellProperties1.Append(bottomBorderLineProperties1);
            //STEP 1 CODE ENDS HERE
    
    
            //STEP 2 CODE STARTS HERE
            A.TableCell tableCell2=tableRow2.Elements<A.TableCell>().ElementAt(2);
    
            A.TableCellProperties tableCellProperties2=tableCell2.GetFirstChild<A.TableCellProperties>();
    
            A.BottomBorderLineProperties bottomBorderLineProperties2=tableCellProperties2.GetFirstChild<A.BottomBorderLineProperties>();
    
            A.TopBorderLineProperties topBorderLineProperties1 = new A.TopBorderLineProperties(){ Width = 12700, CapType = A.LineCapValues.Flat, CompoundLineType = A.CompoundLineValues.Single, Alignment = A.PenAlignmentValues.Center };
    
            A.SolidFill solidFill2 = new A.SolidFill();
            A.SchemeColor schemeColor2 = new A.SchemeColor(){ Val = A.SchemeColorValues.Text1 };
    
            solidFill2.Append(schemeColor2);
            A.PresetDash presetDash2 = new A.PresetDash(){ Val = A.PresetLineDashValues.Solid };
            A.Round round2 = new A.Round();
            A.HeadEnd headEnd2 = new A.HeadEnd(){ Type = A.LineEndValues.None, Width = A.LineEndWidthValues.Medium, Length = A.LineEndLengthValues.Medium };
            A.TailEnd tailEnd2 = new A.TailEnd(){ Type = A.LineEndValues.None, Width = A.LineEndWidthValues.Medium, Length = A.LineEndLengthValues.Medium };
    
            topBorderLineProperties1.Append(solidFill2);
            topBorderLineProperties1.Append(presetDash2);
            topBorderLineProperties1.Append(round2);
            topBorderLineProperties1.Append(headEnd2);
            topBorderLineProperties1.Append(tailEnd2);
            tableCellProperties2.InsertBefore(topBorderLineProperties1,bottomBorderLineProperties2);
    

    I ran the code above against my Before.pptx file and the border was complete.

    enter image description here

    In an effort to double check that the two steps are necessary, I commented out the Step 1 code and ran it against a fresh version of Before.pptx file and the top border was missing. This verifies the problem you were seeing. Therefore, the two steps are necessary to paint the one border.