I was recently struck with creating a Powerpoint presentation with a table in it using OpenXml, Googling did not help me a lot, so below is the solution.
I need to mention a thing here, I was struck ‘n’ number of times in between and a tool named ‘Open XML SDK 2.5 for Microsoft Office’ helped me solve the problems. I would seriously recommend this tool if you are trying to create your own structure using OpenXML. This accurately tells where the problem lies and what is expected and missing. (It isn't that easy to use this though!!!). It shows an XML node and you need to find that and add/remove as the tool tells.
You can download it from here.
Below, we will be able to see how to use OpenXml to create a Powerpoint presentation with table in it.
Hope you have prior knowledge of how to create a WCF service :0/ .
Kindly reference or add namespaces as below. You will also need to download OpenXml DLLs from Nuget.
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using P14 = DocumentFormat.OpenXml.Office2010.PowerPoint;
using System.Collections.Generic;
using System.Text;
using P = DocumentFormat.OpenXml.Presentation;
using D = DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using System.IO;
using System.ComponentModel;
Our Service will look as below:
[ServiceContract(Namespace = "")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[KnownType(typeof(Configuration))]
public class Service
{
string templateFilePath = Path.Combine(string.Format("{0}\\bin",
AppDomain.CurrentDomain.BaseDirectory), "Template.pptx");
string tempFilePath = Path.Combine(string.Format("{0}\\bin",
AppDomain.CurrentDomain.BaseDirectory),
string.Format("Template_{0}.pptx", new Guid()));
[OperationContract]
public byte[] CreateTableInLastSlide(List<Configuration> configurations)
{
CreatePresentation();
PresentationDocument presentationDocument = PresentationDocument.Open(tempFilePath, true);
PresentationPart presentationPart = presentationDocument.PresentationPart;
var slideIdList = presentationPart.Presentation.SlideIdList;
if (slideIdList == null)
{
throw new NullReferenceException
("The number of slide is empty,
please select a ppt with a slide at least again");
}
var list = slideIdList.ChildElements
.Cast<SlideId>()
.Select(x => presentationPart.GetPartById(x.RelationshipId))
.Cast<SlidePart>();
var tableSlidePart = (SlidePart)list.Last();
P.GraphicFrame graphicFrame = tableSlidePart.Slide.CommonSlideData.ShapeTree.AppendChild
(new P.GraphicFrame(new P.NonVisualGraphicFrameProperties
(new P.NonVisualDrawingProperties() { Id = 1, Name = "xyz" },
new P.NonVisualGraphicFrameDrawingProperties(),
new ApplicationNonVisualDrawingProperties())));
graphicFrame.Transform = new Transform(new D.Offset() { X = 10, Y = 10 });
graphicFrame.Graphic = new D.Graphic(new D.GraphicData(GenerateTable(configurations))
{ Uri = "http://schemas.openxmlformats.org/drawingml/2006/table" });
presentationPart.Presentation.Save();
presentationDocument.Close();
byte[] pptByte = File.ReadAllBytes(tempFilePath);
File.Delete(tempFilePath);
return pptByte;
}
private D.Table GenerateTable(List<Configuration> configurations)
{
D.Table table = new D.Table();
D.TableProperties tableProperties = new D.TableProperties()
{ FirstRow = true, BandRow = true };
D.TableStyleId tableStyleId = new D.TableStyleId();
tableStyleId.Text = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";
tableProperties.Append(tableStyleId);
D.TableGrid tableGrid1 = new D.TableGrid();
D.GridColumn gridColumn1 = new D.GridColumn() { Width = 1048000L };
D.GridColumn gridColumn2 = new D.GridColumn() { Width = 1048000L };
tableGrid1.Append(gridColumn1);
tableGrid1.Append(gridColumn2);
table.Append(tableProperties);
table.Append(tableGrid1);
D.TableRow tableRow1 = new D.TableRow() { Height = 370840L };
var list = GetPropertiesNameOfClass(configurations.FirstOrDefault());
foreach (var item in list)
{
tableRow1.Append(CreateTextCell(item.ToString()));
}
table.Append(tableRow1);
foreach (var config in configurations)
{
D.TableRow tableRow = new D.TableRow() { Height = 370840L };
foreach (var prop in config.GetType().GetProperties())
{
tableRow.Append(CreateTextCell(prop.GetValue(config, null).ToString()));
}
table.Append(tableRow);
}
return table;
}
public List<string> GetPropertiesNameOfClass(object pObject)
{
List<string> propertyList = new List<string>();
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(pObject);
foreach (PropertyDescriptor property in properties)
{
propertyList.Add(property.DisplayName);
}
return propertyList;
}
private D.TableCell CreateTextCell(string text)
{
if (string.IsNullOrEmpty(text))
{
text = string.Empty;
}
D.TableCell tableCell = new D.TableCell();
D.TextBody textBody = new D.TextBody();
D.BodyProperties bodyProperties = new D.BodyProperties();
D.ListStyle listStyle = new D.ListStyle();
D.Paragraph paragraph = new D.Paragraph();
D.Run run = new D.Run();
D.RunProperties runProperties = new D.RunProperties()
{ Language = "en-US", Dirty = false };
D.Text text2 = new D.Text();
text2.Text = text;
run.Append(runProperties);
run.Append(text2);
D.EndParagraphRunProperties endParagraphRunProperties =
new D.EndParagraphRunProperties() { Language = "en-US", Dirty = false };
paragraph.Append(run);
paragraph.Append(endParagraphRunProperties);
textBody.Append(bodyProperties);
textBody.Append(listStyle);
textBody.Append(paragraph);
D.TableCellProperties tableCellProperties = new D.TableCellProperties();
tableCell.Append(textBody);
tableCell.Append(tableCellProperties);
return tableCell;
}
[OperationContract]
public void CreatePresentation()
{
PresentationDocument presentationDoc = PresentationDocument.Create
(tempFilePath, PresentationDocumentType.Presentation);
PresentationPart presentationPart = presentationDoc.AddPresentationPart();
presentationPart.Presentation = new Presentation();
CreatePresentationParts(presentationPart);
presentationDoc.Close();
}
private void CreatePresentationParts(PresentationPart presentationPart)
{
SlideMasterIdList slideMasterIdList1 = new SlideMasterIdList(new SlideMasterId()
{ Id = (UInt32Value)2147483648U, RelationshipId = "rId1" });
SlideIdList slideIdList1 = new SlideIdList(new SlideId()
{ Id = (UInt32Value)256U, RelationshipId = "rId2" });
SlideSize slideSize1 = new SlideSize()
{ Cx = 9144000, Cy = 6858000, Type = SlideSizeValues.Screen4x3 };
NotesSize notesSize1 = new NotesSize()
{ Cx = 6858000, Cy = 9144000 };
DefaultTextStyle defaultTextStyle1 = new DefaultTextStyle();
presentationPart.Presentation.Append
(slideMasterIdList1, slideIdList1, slideSize1, notesSize1, defaultTextStyle1);
SlidePart slidePart1;
SlideLayoutPart slideLayoutPart1;
SlideMasterPart slideMasterPart1;
ThemePart themePart1;
slidePart1 = CreateSlidePart(presentationPart);
slideLayoutPart1 = CreateSlideLayoutPart(slidePart1);
slideMasterPart1 = CreateSlideMasterPart(slideLayoutPart1);
themePart1 = CreateTheme(slideMasterPart1);
slideMasterPart1.AddPart(slideLayoutPart1, "rId1");
presentationPart.AddPart(slideMasterPart1, "rId1");
presentationPart.AddPart(themePart1, "rId5");
}
private SlidePart CreateSlidePart(PresentationPart presentationPart)
{
SlidePart slidePart1 = presentationPart.AddNewPart<SlidePart>("rId2");
slidePart1.Slide = new Slide(
new CommonSlideData(
new ShapeTree(
new P.NonVisualGroupShapeProperties(
new P.NonVisualDrawingProperties()
{ Id = (UInt32Value)1U, Name = "" },
new P.NonVisualGroupShapeDrawingProperties(),
new ApplicationNonVisualDrawingProperties()),
new GroupShapeProperties(new D.TransformGroup()),
new P.Shape(
new P.NonVisualShapeProperties(
new P.NonVisualDrawingProperties()
{ Id = (UInt32Value)2U, Name = "Title 1" },
new P.NonVisualShapeDrawingProperties(new D.ShapeLocks()
{ NoGrouping = true }),
new ApplicationNonVisualDrawingProperties(new PlaceholderShape())),
new P.ShapeProperties(),
new P.TextBody(
new D.BodyProperties(),
new D.ListStyle(),
new D.Paragraph(new D.EndParagraphRunProperties()
{ Language = "en-US" }))))),
new ColorMapOverride(new D.MasterColorMapping()));
return slidePart1;
}
private SlideLayoutPart CreateSlideLayoutPart(SlidePart slidePart1)
{
SlideLayoutPart slideLayoutPart1 =
slidePart1.AddNewPart<SlideLayoutPart>("rId1");
SlideLayout slideLayout = new SlideLayout(
new CommonSlideData(new ShapeTree(
new P.NonVisualGroupShapeProperties(
new P.NonVisualDrawingProperties() { Id = (UInt32Value)1U, Name = "" },
new P.NonVisualGroupShapeDrawingProperties(),
new ApplicationNonVisualDrawingProperties()),
new GroupShapeProperties(new D.TransformGroup()),
new P.Shape(
new P.NonVisualShapeProperties(
new P.NonVisualDrawingProperties() { Id = (UInt32Value)2U, Name = "" },
new P.NonVisualShapeDrawingProperties(new D.ShapeLocks() { NoGrouping = true }),
new ApplicationNonVisualDrawingProperties(new PlaceholderShape())),
new P.ShapeProperties(),
new P.TextBody(
new D.BodyProperties(),
new D.ListStyle(),
new D.Paragraph(new D.EndParagraphRunProperties()))))),
new ColorMapOverride(new D.MasterColorMapping()));
slideLayoutPart1.SlideLayout = slideLayout;
return slideLayoutPart1;
}
private SlideMasterPart CreateSlideMasterPart(SlideLayoutPart slideLayoutPart1)
{
SlideMasterPart slideMasterPart1 =
slideLayoutPart1.AddNewPart<SlideMasterPart>("rId1");
SlideMaster slideMaster = new SlideMaster(
new CommonSlideData(new ShapeTree(
new P.NonVisualGroupShapeProperties(
new P.NonVisualDrawingProperties() { Id = (UInt32Value)1U, Name = "" },
new P.NonVisualGroupShapeDrawingProperties(),
new ApplicationNonVisualDrawingProperties()),
new GroupShapeProperties(new D.TransformGroup()),
new P.Shape(
new P.NonVisualShapeProperties(
new P.NonVisualDrawingProperties()
{ Id = (UInt32Value)2U, Name = "Title Placeholder 1" },
new P.NonVisualShapeDrawingProperties(new D.ShapeLocks()
{ NoGrouping = true }),
new ApplicationNonVisualDrawingProperties(new PlaceholderShape()
{ Type = PlaceholderValues.Title })),
new P.ShapeProperties(),
new P.TextBody(
new D.BodyProperties(),
new D.ListStyle(),
new D.Paragraph())))),
new P.ColorMap() { Background1 = D.ColorSchemeIndexValues.Light1,
Text1 = D.ColorSchemeIndexValues.Dark1, Background2 = D.ColorSchemeIndexValues.Light2,
Text2 = D.ColorSchemeIndexValues.Dark2, Accent1 = D.ColorSchemeIndexValues.Accent1,
Accent2 = D.ColorSchemeIndexValues.Accent2, Accent3 = D.ColorSchemeIndexValues.Accent3,
Accent4 = D.ColorSchemeIndexValues.Accent4, Accent5 = D.ColorSchemeIndexValues.Accent5,
Accent6 = D.ColorSchemeIndexValues.Accent6, Hyperlink = D.ColorSchemeIndexValues.Hyperlink,
FollowedHyperlink = D.ColorSchemeIndexValues.FollowedHyperlink },
new SlideLayoutIdList(new SlideLayoutId()
{ Id = (UInt32Value)2147483649U, RelationshipId = "rId1" }),
new TextStyles(new TitleStyle(), new BodyStyle(), new OtherStyle()));
slideMasterPart1.SlideMaster = slideMaster;
return slideMasterPart1;
}
}
You can further add theming to your PPT as below:
private ThemePart CreateTheme(SlideMasterPart slideMasterPart1)
{
ThemePart themePart1 = slideMasterPart1.AddNewPart<themepart>("rId5");
D.Theme theme1 = new D.Theme() { Name = "Office Theme" };
D.ThemeElements themeElements1 = new D.ThemeElements(
new D.ColorScheme(
new D.Dark1Color(new D.SystemColor()
{ Val = D.SystemColorValues.WindowText, LastColor = "000000" }),
new D.Light1Color(new D.SystemColor()
{ Val = D.SystemColorValues.Window, LastColor = "FFFFFF" }),
new D.Dark2Color(new D.RgbColorModelHex() { Val = "1F497D" }),
new D.Light2Color(new D.RgbColorModelHex() { Val = "EEECE1" }),
new D.Accent1Color(new D.RgbColorModelHex() { Val = "4F81BD" }),
new D.Accent2Color(new D.RgbColorModelHex() { Val = "C0504D" }),
new D.Accent3Color(new D.RgbColorModelHex() { Val = "9BBB59" }),
new D.Accent4Color(new D.RgbColorModelHex() { Val = "8064A2" }),
new D.Accent5Color(new D.RgbColorModelHex() { Val = "4BACC6" }),
new D.Accent6Color(new D.RgbColorModelHex() { Val = "F79646" }),
new D.Hyperlink(new D.RgbColorModelHex() { Val = "0000FF" }),
new D.FollowedHyperlinkColor(new D.RgbColorModelHex()
{ Val = "800080" })) { Name = "Office" },
new D.FontScheme(
new D.MajorFont(
new D.LatinFont() { Typeface = "Calibri" },
new D.EastAsianFont() { Typeface = "" },
new D.ComplexScriptFont() { Typeface = "" }),
new D.MinorFont(
new D.LatinFont() { Typeface = "Calibri" },
new D.EastAsianFont() { Typeface = "" },
new D.ComplexScriptFont() { Typeface = "" }))
{ Name = "Office" },
new D.FormatScheme(
new D.FillStyleList(
new D.SolidFill(new D.SchemeColor()
{ Val = D.SchemeColorValues.PhColor }),
new D.GradientFill(
new D.GradientStopList(
new D.GradientStop(new D.SchemeColor(new D.Tint()
{ Val = 50000 },
new D.SaturationModulation() { Val = 300000 })
{ Val = D.SchemeColorValues.PhColor }) { Position = 0 },
new D.GradientStop(new D.SchemeColor(new D.Tint()
{ Val = 37000 },
new D.SaturationModulation() { Val = 300000 })
{ Val = D.SchemeColorValues.PhColor }) { Position = 35000 },
new D.GradientStop(new D.SchemeColor(new D.Tint()
{ Val = 15000 },
new D.SaturationModulation() { Val = 350000 })
{ Val = D.SchemeColorValues.PhColor }) { Position = 100000 }
),
new D.LinearGradientFill() { Angle = 16200000, Scaled = true }),
new D.NoFill(),
new D.PatternFill(),
new D.GroupFill()),
new D.LineStyleList(
new D.Outline(
new D.SolidFill(
new D.SchemeColor(
new D.Shade() { Val = 95000 },
new D.SaturationModulation() { Val = 105000 })
{ Val = D.SchemeColorValues.PhColor }),
new D.PresetDash() { Val = D.PresetLineDashValues.Solid })
{
Width = 9525,
CapType = D.LineCapValues.Flat,
CompoundLineType = D.CompoundLineValues.Single,
Alignment = D.PenAlignmentValues.Center
},
new D.Outline(
new D.SolidFill(
new D.SchemeColor(
new D.Shade() { Val = 95000 },
new D.SaturationModulation() { Val = 105000 })
{ Val = D.SchemeColorValues.PhColor }),
new D.PresetDash() { Val = D.PresetLineDashValues.Solid })
{
Width = 9525,
CapType = D.LineCapValues.Flat,
CompoundLineType = D.CompoundLineValues.Single,
Alignment = D.PenAlignmentValues.Center
},
new D.Outline(
new D.SolidFill(
new D.SchemeColor(
new D.Shade() { Val = 95000 },
new D.SaturationModulation() { Val = 105000 })
{ Val = D.SchemeColorValues.PhColor }),
new D.PresetDash() { Val = D.PresetLineDashValues.Solid })
{
Width = 9525,
CapType = D.LineCapValues.Flat,
CompoundLineType = D.CompoundLineValues.Single,
Alignment = D.PenAlignmentValues.Center
}),
new D.EffectStyleList(
new D.EffectStyle(
new D.EffectList(
new D.OuterShadow(
new D.RgbColorModelHex(
new D.Alpha() { Val = 38000 }) { Val = "000000" })
{ BlurRadius = 40000L, Distance = 20000L,
Direction = 5400000, RotateWithShape = false })),
new D.EffectStyle(
new D.EffectList(
new D.OuterShadow(
new D.RgbColorModelHex(
new D.Alpha() { Val = 38000 }) { Val = "000000" })
{ BlurRadius = 40000L, Distance = 20000L,
Direction = 5400000, RotateWithShape = false })),
new D.EffectStyle(
new D.EffectList(
new D.OuterShadow(
new D.RgbColorModelHex(
new D.Alpha() { Val = 38000 }) { Val = "000000" })
{ BlurRadius = 40000L, Distance = 20000L,
Direction = 5400000, RotateWithShape = false }))),
new D.BackgroundFillStyleList(
new D.SolidFill(new D.SchemeColor()
{ Val = D.SchemeColorValues.PhColor }),
new D.GradientFill(
new D.GradientStopList(
new D.GradientStop(
new D.SchemeColor(new D.Tint() { Val = 50000 },
new D.SaturationModulation() { Val = 300000 })
{ Val = D.SchemeColorValues.PhColor }) { Position = 0 },
new D.GradientStop(
new D.SchemeColor(new D.Tint() { Val = 50000 },
new D.SaturationModulation() { Val = 300000 })
{ Val = D.SchemeColorValues.PhColor }) { Position = 0 },
new D.GradientStop(
new D.SchemeColor(new D.Tint() { Val = 50000 },
new D.SaturationModulation() { Val = 300000 })
{ Val = D.SchemeColorValues.PhColor }) { Position = 0 }),
new D.LinearGradientFill() { Angle = 16200000, Scaled = true }),
new D.GradientFill(
new D.GradientStopList(
new D.GradientStop(
new D.SchemeColor(new D.Tint() { Val = 50000 },
new D.SaturationModulation() { Val = 300000 })
{ Val = D.SchemeColorValues.PhColor }) { Position = 0 },
new D.GradientStop(
new D.SchemeColor(new D.Tint() { Val = 50000 },
new D.SaturationModulation() { Val = 300000 })
{ Val = D.SchemeColorValues.PhColor }) { Position = 0 }),
new D.LinearGradientFill() { Angle = 16200000, Scaled = true })))
{ Name = "Office" });
theme1.Append(themeElements1);
theme1.Append(new D.ObjectDefaults());
theme1.Append(new D.ExtraColorSchemeList());
themePart1.Theme = theme1;
return themePart1;
}
The Configuration
data contract is as shown below. I have 'display name' attribute associated to it so that I can show the same in my presentation Table header.
[DataContract]
public class Configuration
{
[DataMember]
[DisplayName("Value")]
public string Value { get; set; }
[DataMember]
[DisplayName("Name")]
public decimal Name{ get; set; }
}
Now we will look at the client side:
You can now add the service reference (as you do normally) and write the below code.
ServiceClient proxy = new ServiceClient();
Stream stream;
SaveFileDialog objSFD;
private void btnPowerpoint_Click(object sender, RoutedEventArgs e)
{
objSFD = new SaveFileDialog()
{
Filter = "Powerpoint Presentation (*.pptx)|*.pptx | All files (*.*)|*.*",
FilterIndex = 1,
};
if ( objSFD.ShowDialog()==true)
{
List<ServiceReference.Configuration>
obj = new List<ServiceReference.Configuration>();
foreach (var config in Data)
{
obj.Add(new ServiceReference.Configuration()
{
Value = Data.Value,
Name = Data.Name,
});
}
proxy.CreateTableInLastSlideAsync
(new System.Collections.ObjectModel.ObservableCollection<Configuration>(obj));
proxy.CreateTableInLastSlideCompleted +=
new EventHandler<CreateTableInLastSlideCompletedEventArgs>
(proxy_CreateTableInLastSlideCompleted);
}
}
void proxy_CreateTableInLastSlideCompleted
(object sender, CreateTableInLastSlideCompletedEventArgs e)
{
if (e.Result == null)
return;
using (System.IO.Stream stream = objSFD.OpenFile())
{
stream.Write(e.Result, 0, e.Result.Length);
}
}
You will be able to see the output as below:
Powerpoint with OpenXML