Link to home
Start Free TrialLog in
Avatar of codequest
codequest

asked on

In PowerPoint openxml, add or subtract a text box outline style

Using VS2013 Premium, asp.net. vb.net, website, win7

I have a dictionary of class objects which describe graphic element (rectangles, arrows, text boxes) by position and text content. I merge this with a blank PowerPoint presentation.  The elements show up in the correct positions.  However, I can't figure out how to change some of the styling, starting with the text box outline style.

>  started with a PowerPoint 2013 document with one slide with one shape
>  used the OpenXML SDK Productivity Tool to reflect it to C#, converted that the VB.Net, wrapped a project around it.
>  located the code where the shape was added to the slide shape tree
>  replace that with a function call that imports the dictionary, translates the dictionary  class objects into openxml shapes, and adds the shapes to the shape tree.  

That all works fine.  

However, some of the shapes are graphic rectangles which need outlines, and others are text boxes that don't.

In a very simple SDK comparison of two documents, one with text box with outline, and the other with textbox with "no line", the only difference in the XML is this:

 <a:ln>    
    <a:solidFill>      
         <a:schemeClr val="tx1"/>      
    </a:solidFill>    
</a:ln>

So, I've spent maybe eight hours using the SDK and reflected code to look at the different text documents trying to figure out why the outlines are or are not added.   I eventually located the theme that contained the LineStyleList that contains the Outlines ( <a:ln> ), and was able to identify which theme outline was being applied to ALL the elements.  

However, I haven't figured out how to either:

1) turn off all the outlines in the theme (which I can do) and add them to particular shapes where needed (which I can't do), OR
2) leave the theme outline in place, and remove the outlines from particular elements.

I've gotten closer with 1), which seems to make more sense.  I actually do add the outline to certain of the shapes, and I can see in the Immediate Window that they have been added...but they don't show up in the output document.

I'm going to keep experimenting, however, it seems like the theme is overriding whatever I try to do at the individual shape level.  

I'm hoping someone might have some insights that would help me move this along.  I'm going to have to deal with similar issues with respect to font sizes, and perhaps similar issues in some Excel exports I also need to do, so this might be useful for the community to have a solution for.

Here's the key code:

 

===== FIRST APPROACH :  Theme default is "no outlines"

========== THIS CREATE A SHAPE PROPERTIES OBJECT TO ATTACH TO THE SHAPE

Public Function CreateShapeProperties( _

            dLeftX As Integer, dTopY As Integer, _

            dWidthX As Integer, dHeightY As Integer, _

            varSP As MapGraphicSubPart) As ShapeProperties  '---- MapGraphicSubPart is the class object that contains the graphic and text information

        Dim shapeProperties1 As New ShapeProperties

        '====== Transform Properties - top,left,width, height=============

        Dim transform2D1 As New A.Transform2D()

        Dim offset2 As New A.Offset() With { _

             .X = dLeftX, _

             .Y = dTopY _

        }

        Dim extents2 As New A.Extents() With { _

             .Cx = dWidthX, _

             .Cy = dHeightY _

        }

        transform2D1.Append(offset2)

        transform2D1.Append(extents2)

        '============   PRE-SET GEOMETRY (Rectangle)==================

        Dim presetGeometry1 As New A.PresetGeometry() With { _

             .Preset = A.ShapeTypeValues.Rectangle _

        }

        Dim adjustValueList1 As New A.AdjustValueList()

        presetGeometry1.Append(adjustValueList1)

 

'-----  this adds the outline for particular types of shapes -----------

                     Select Case varSP.SubPartType

                           Case "Graphic"

                                  wrkLableOutline = PPTX.GetSolidDarkOutline()

                                  shapeProperties1.Append(wrkLableOutline)

                     End Select

 

              '----- create Nofill for all shapes

              Dim wrkNoFillWholeShape As New A.NoFill()

              '=============  Add it all up ====================================

              shapeProperties1.Append(transform2D1)

              shapeProperties1.Append(presetGeometry1)

              shapeProperties1.Append(wrkNoFillWholeShape)    '---- becomes purple without this

 

              '------------------------This allows testing to see if the outline has been added ------------------------

              Dim outline1 As A.Outline = shapeProperties1.GetFirstChild(Of A.Outline)()

              Dim wrkStop As String = 1  ‘---- at breakpoint here, outline is present, with all detail

 

End function

 

'======== THIS CREATES THE OUTLINE THAT IS APPENDED TO THE SHAPE ABOVE ======
'---------------IT WAS COPIED FROM THE CODE THAT CREATES THE THEME-------------------------

Public Shared Function GetSolidDarkOutline() As A.Outline


Dim outline3 As New A.Outline() With { _.Width = 9525, _.CapType = A.LineCapValues.Flat, _      .CompoundLineType = A.CompoundLineValues.[Single], _      
.Alignment = A.PenAlignmentValues.Center  }

Dim solidFill5 As New A.SolidFill()

Dim schemeColor21 As New A.SchemeColor() With {
_      .Val = A.SchemeColorValues.PhColor _      }      Dim shade4 As New A.Shade() With { _      .Val = 95000 _      }      Dim saturationModulation5 As New A.SaturationModulation() With { _      .Val = 105000 _      }

schemeColor21.Append(shade4)      schemeColor21.Append(saturationModulation5)

solidFill5.Append(schemeColor21)

Dim presetDash2 As New A.PresetDash() With { _      .Val = A.PresetLineDashValues.Solid _      }

Outline3.Append(solidFill5)      outline3.Append(presetDash2)

Return outline3

End Function

 

===========================================

THE SECOND APPROACH:  Try to remove outline

>  This can't find the outline when the shapeproperties is produced (i.e = nothing)

THE THIRD APPROACH:  Try to write in a new outline:  (Unconverted C#;  I implemented something like this in VB.NET in a variation of the first function above)

>  This causes the text to be blanked out.   The text is can still be found  in the document, via the SDK,  it just isn't visible any more in PowerPoint

 public Outline GenerateOutline()        {
          Outline outline1 = new Outline();  
         NoFill noFill1 = new NoFill();
         outline1.Append(noFill1);            
        return outline1;      
}
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

Let's review to make certain that I understand the issue.

I created a PowerPoint XML, with a single shape that has a style applied:

	
<p:sp>
	<p:nvSpPr>
		<p:cNvPr id="4" name="Rectangle 3"/>
		<p:cNvSpPr/>
		<p:nvPr/>
	</p:nvSpPr>
	<p:spPr>
		<a:xfrm>
			<a:off x="633046" y="597877"/>
			<a:ext cx="3789485" cy="2277208"/>
		</a:xfrm>
		<a:prstGeom prst="rect">
			<a:avLst/>
		</a:prstGeom>
	</p:spPr>
	<p:style>
		<a:lnRef idx="2">
			<a:schemeClr val="accent1">
				<a:shade val="50000"/>
			</a:schemeClr>
		</a:lnRef>
		<a:fillRef idx="1">
			<a:schemeClr val="accent1"/>
		</a:fillRef>
		<a:effectRef idx="0">
			<a:schemeClr val="accent1"/>
		</a:effectRef>
		<a:fontRef idx="minor">
			<a:schemeClr val="lt1"/>
		</a:fontRef>
	</p:style>
	<p:txBody>
		<a:bodyPr rtlCol="0" anchor="ctr"/>
		<a:lstStyle/>
		<a:p>
			<a:pPr algn="ctr"/>
			<a:endParaRPr lang="en-US"/>
		</a:p>
	</p:txBody>
</p:sp>

Open in new window


1) The Shape class is <p:sp>

Shape class
https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.presentation.shape.aspx

2) It has a ShapeStyle child <p:style>

ShapeStyle class
https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.presentation.shapestyle.aspx

3) The ShapeStyle has a LineReference property <a:lnRef>.

LineReference class
https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.drawing.linereference.aspx

The LineReference class has different properties for color:

LineReference properties
https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.drawing.linereference_properties.aspx

hslClr (Hue, Saturation, Luminance Color Model)
LineReference.HslColor

prstClr (Preset Color)
LineReference.PresetColor

schemeClr (Scheme Color)
LineReference.SchemeColor

scrgbClr (RGB Color Model - Percentage Variant)
RgbColorModelPercentage

srgbClr (RGB Color Model - Hex Variant)
LineReference.RgbColorModelHex

sysClr (System Color)
LineReference.SystemColor
Avatar of codequest
codequest

ASKER

Thanks for your attention to this.   This is a test setup:

Here is the starting point:  create a PPT with a textbox without an outline;  copy it; add an outline to the textbox.

 User generated image
Compare the two documents in the OpenXML SDK Productivity tool, looking at the difference in the XML:
User generated image
Then look at the reflected code that would create the difference.
User generated image
Open the PPT without the outline in the SDK, and Reflect the full code required to generate that entire PPT.  Put that code in a class in a new website project.  Create a webform that will execute that code on page load.
(see attached)

Snapshot showing the differential code added to the Generated code above
User generated image
Run it both ways, with the differential code executed and not executed
User generated image
User generated image
Compare the XML
User generated image
The comparative XML of the output documents looks the same as it did in the comparison of the starting documents, however, the output PPT that should have the shape with outline shows nothing.  Strangely, the XML shows that the shape is in the pptx, but does not show in the PPT GUI.

The goal is to be able to generate an entire PPTX using code, and to be able to interject changes into that code, somewhat like was done in the text example above.   However, I cannot get even this very simple change to work.  That's the problem.
GenPPT-wo-outline.cs
ASKER CERTIFIED SOLUTION
Avatar of codequest
codequest

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I discovered the answer.