Reputation: 879
I'm updating software that cuts up and stitches PowerPoint slides together for end users. The slides contain charts. I need to find a way of hiding the raw chart data from the users that receive the files.
Is there anyway of doing this natively within the PowerPoint interop? I've tried Read-Only but the user can still get at the data.
Upvotes: 0
Views: 952
Reputation: 879
Ok. Here is my final answer to my question. This shows the completed code that can perfectly replicate the slide while keeping the charts from being edited i.e. buy turning it into a .png.
This also solves the previous problem of the placeholders being left.
Hopefully some of this code is helpful to someone trawling the internet like I did.
//Open the slides presentation
var pres = _application.Presentations.Open2007(item.PresentationPath,
Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoFalse);
//For slide ranges
foreach (var i in range)
{
//Get the old slide
var oldSlide = pres.Slides[i];
oldSlide.Copy();
//Paste the slide into the new presentation
var newSlide = newPresentation.Slides.Paste(totalSlides + 1);
newSlide.Design = oldSlide.Design;
newSlide.ColorScheme = oldSlide.ColorScheme;
/* The shapes haven't retained their content because we are not in slide...
view because there is no window. */
//Delete all the shapes that were just pasted in because of the slide paste.
for (int k = newSlide.Shapes.Count; k > 0; k--)
{
newSlide.Shapes[k].Delete();
}
//Put in our shapes
//Loop forwards, because we arn't editing the list and forward is required to
//maintain the zorder we want on some slides.
for (int j = 1; j <= oldSlide.Shapes.Count; j++)
{
var oldShape = oldSlide.Shapes[j];
oldShape.Copy();
//Paste Put it where it should be on the page
/* This is a special case where the client have put textboxes in the
Powerpoint and rotated throwing off the position, so we need treat as rotated
shapes to make it right. */
if (oldShape.HasTextFrame == MsoTriState.msoTrue && Math.Abs(oldShape.Rotation) > 0)
{
//Paste as a shape because it's a more complex object
//set ALL THE PROPERTIES just in case.
var newShape = newSlide.Shapes.PasteSpecial(PpPasteDataType.ppPasteShape);
newShape.Rotation = oldShape.Rotation;
newShape.Top = oldShape.Top;
newShape.Left = oldShape.Left;
newShape.TextFrame.Orientation = oldShape.TextFrame.Orientation;
newShape.TextFrame.WordWrap = oldShape.TextFrame.WordWrap;
newShape.TextFrame.VerticalAnchor = oldShape.TextFrame.VerticalAnchor;
}
else // Act normally
{
//Paste the old shape into the new slide as an image to ENSURE FORMATTING
var newShape = newSlide.Shapes.PasteSpecial(PpPasteDataType.ppPastePNG);
newShape.Top = oldShape.Top;
newShape.Left = oldShape.Left;
}
}
totalSlides += ((item.EndIndex - item.StartIndex) + 1);
pres.Close();
}
After the new presentation has been compiled, you must delete all placeholders.
//Loop through all slides
foreach (Slide exportSlide in newPresentation.Slides)
{
//Delete the placeholders
for (int i = exportSlide.Shapes.Placeholders.Count; i > 0; i--)
{
exportSlide.Shapes.Placeholders[i].Delete();
}
}
Upvotes: 2
Reputation: 879
Using the principals of Steve's code I've created a bespoke one for my use. As I am interacting with PowerPoint as a Component Service, I don't have an ActiveWindow or anything.
//Loop through all slides
foreach (Slide exportSlide in newPresentation.Slides)
{
//Loop through all shapes
foreach (Shape shape in exportSlide.Shapes)
{
//If the shape is a chart
if (shape.HasChart == MsoTriState.msoTrue)
{
//Copy to clipboard
shape.Copy();
//Paste as an image
var newShape = exportSlide.Shapes.PasteSpecial(PpPasteDataType.ppPastePNG);
//Move back to chart position
newShape.Left = shape.Left;
newShape.Top = shape.Top;
//Delete the original shape
shape.Delete();
}
}
}
This works fine for replacing the charts with images (no data at all). The only issue now is that because the slides where created with a layout containing chart, when you open the slide in Powerpoint the GUI displays an "Insert Chart" box. I've tried:
exportSlide.Layout = PpSlideLayout.ppLayoutBlank;
However because of my clients custom templates this is not blank, so it's not usable.
Upvotes: 0
Reputation: 14809
VBA to ungroup a chart (in order to remove any connection to the original data)
Sub UngroupAChart()
Dim oSh As Shape
Dim oNewSh As Shape
Dim oNewShapes As ShapeRange
Dim oSl As Slide
' for demo purposes, use the currently selected
' shape; up to tester to select a chart
Set oSh = ActiveWindow.Selection.ShapeRange(1)
' Get a reference to the shape's parent slide
' We'll need it later
Set oSl = oSh.Parent
' put the shape on the clipboard
oSh.Copy
Set oNewSh = oSl.Shapes.PasteSpecial(ppPasteEnhancedMetafile)(1)
oNewSh.Ungroup
' once you're done testing, delete the original chart
'oSh.Delete
End Sub
Upvotes: 0