Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

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

Posted on 2015-02-02
4
Medium Priority
?
463 Views
Last Modified: 2015-02-11
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;      
}
0
Comment
Question by:codequest
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
4 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40586650
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
0
 
LVL 2

Author Comment

by:codequest
ID: 40587036
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.

 Comparison of two powerpoints slides, one with shape with outline, one with shape without outline
Compare the two documents in the OpenXML SDK Productivity tool, looking at the difference in the XML:
Location of the differences in XML, in the SDK tool
Then look at the reflected code that would create the difference.
Differential code, from the SDK Tool
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
Snapshot showing the differential code added to the Generated code above
Run it both ways, with the differential code executed and not executed
snapshot showing PPT output with added code active
snapshot showing PPT output with added code bypassed (by if statement)
Compare the XML
Snapshot of SDK XML showing the comparative difference in the two generated PPTs
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
0
 
LVL 2

Accepted Solution

by:
codequest earned 0 total points
ID: 40595185
ANSWERED:  

The answer came from a different angle. Another element of the ShapeProperties object is the PresetGeometry , which has a ShapeTypeValue

   Dim presetGeometry1 As A.PresetGeometry = Nothing
  presetGeometry1 = New A.PresetGeometry() With { _
                       .Preset = A.ShapeTypeValues.Rectangle}
              shapeProperties1.Append(presetGeometry1)

While experimenting, I discovered that textboxes do not require ANY preset geometry.

I rewrote the code to not add the PresetGeometry for the textboxes, then set the applicable theme style to have a "dark, solid" outline instead of "no outline". The rectangles appear with outlines according to the theme, and the textboxes appear where they should, without outlines.
0
 
LVL 2

Author Closing Comment

by:codequest
ID: 40602724
I discovered the answer.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…

715 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question