Adding links and styled text to Power-Point presentation
Formatting paragraphs in OpenXML documents is playing crucial part in proper implementation as the very common requirement is to change PowerPoint files programmatically during the business workflow processes.
I have recently received lot of queries about how to insert formatted text and links into the presentation. Hence, in this article I will show you how to do it.
In the past I have written article about auto generating Power-Point documents from the template file, in this part I will extend the functionality I have implemented before.
Let’s start with defining placeholder paragraphs we will use to insert our formatted texts and links:
var templ = new PowerPointTemplate(); templ.PowerPointParameters.Add(new PowerPointParameter() { Name = "[#Paragraph1#]", Text = "Slide 1" }); templ.PowerPointParameters.Add(new PowerPointParameter() { Name = "[#Paragraph2#]", Text = "Slide 2" }); templ.PowerPointParameters.Add(new PowerPointParameter() { Name = "[#List1(string[])#]", Text = "test1 n test2 n test3 n test4" }); templ.PowerPointParameters.Add(new PowerPointParameter() { Name = "[#List2(string[])#]", Text = "test1 n test2 n test3 n test4" }); templ.PowerPointParameters.Add(new PowerPointParameter() { Name = "[#Link1(#link#)#]", Text = "My link - to Microsoft; https://microsoft.com" }); templ.PowerPointParameters.Add(new PowerPointParameter() { Name = "[#Link2(#link#)#]", Text = "My link - to Google; https://google.com" });
As you can see, we will handle text lists and single links defined in our template. Of course the names and params will depend on your requirements.
I will skip describing how the process works as this can be read in my previous article. I will go straight to the styled paragraph creation.
Function below returns new paragraph with the styles we have defined in parameters. The RunProperties class is created, then we are assigning the styles – please note that the color needs to be converted to HEX before adding it to run properties. Next we need to define the text-box object containing paragraph’s text. At the end we simply need to append run properties and text to the run and finally append run to the paragraph object.
If you need multiple colors within one paragraph, simply create multiple texts, runs and run properties and configure it separately before assigning it to the paragraph object.
public Paragraph CreateStyledParagraph(string text, System.Drawing.Color color, bool isBold, bool isItalic, int fontSize = 2000) { var runProperties = new RunProperties(); //set basic styles for paragraph runProperties.Bold = isBold; runProperties.Italic = isItalic; runProperties.FontSize = fontSize; runProperties.Dirty = false; var hexColor = color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");//convert color to hex var solidFill = new SolidFill(); var rgbColorModelHex = new RgbColorModelHex() { Val = hexColor }; solidFill.Append(rgbColorModelHex); runProperties.Append(solidFill); //use this to assign the font family runProperties.Append(new LatinFont() { Typeface = "Arial Black" }); var textBody = new Drawing.Text(); textBody.Text = text; //assign text var run = new Drawing.Run(); var newParagraph = new Paragraph(); run.Append(runProperties);//append styles run.Append(textBody);//append text newParagraph.Append(run);//append run to paragraph return newParagraph; }
Creating links is a little bit different. In order to do it we first need to create HyperlinkRelationship in the slide, the HyperlinkOnClick class contained within the run will then map to it on user click event. Please note that link color is not supported.
public Paragraph CreateStyledLinkParagraph(SlidePart slidePart, string url, string text, bool isBold, bool isItalic, int fontSize = 2000) { //note: HyperlinkOnClick does not support link color var relationshipId = "rIdlink" + Guid.NewGuid().ToString();//create unique id slidePart.AddHyperlinkRelationship(new System.Uri(url, System.UriKind.Absolute), true, relationshipId);//assign hyperlink to the current slide we process var runProperties = new RunProperties( new LatinFont() { Typeface = "Bodoni MT Black"}, new HyperlinkOnClick() { Id = relationshipId }); //set basic styles and assign relationshipId runProperties.Bold = isBold; runProperties.Italic = isItalic; runProperties.FontSize = fontSize; runProperties.Dirty = false; var textBody = new Drawing.Text(); textBody.Text = text; //assign text var run = new Drawing.Run(); var newParagraph = new Paragraph(); run.Append(runProperties);//append styles run.Append(textBody);//append text newParagraph.Append(run);//append run to paragraph return newParagraph; }
The final replacement is being done in ReplaceText function. See in-line comments:
void ReplaceText(Paragraph paragraph, SlidePart currentSlide) { var parent = paragraph.Parent; //get parent element - to be used when removing placeholder var dataParam = new PowerPointParameter(); if (ContainsParam(paragraph, ref dataParam)) //check if paragraph is on our parameter list { //insert text list if (dataParam.Name.Contains("string[]")) //check if param is a list { var arrayText = dataParam.Text.Split(Environment.NewLine.ToCharArray()); //in our case we split it into lines if (arrayText is IEnumerable) //enumerate if we can { foreach (var itemData in arrayText) { //var newParagraph = CloneParaGraphWithStyles(paragraph, dataParam.Name, itemData);// create new param - preserve styles var newParagraph = CreateStyledParagraph(itemData.Trim(), System.Drawing.Color.Green, false, true, 2000); parent.InsertBefore(newParagraph, paragraph); //insert new element } } paragraph.Remove();//delete placeholder } else if (dataParam.Name.Contains("#link#")) //check if param is a link { var linkText = dataParam.Text.Split(';')[0].Trim(); var linkUrl = dataParam.Text.Split(';')[1].Trim(); var newParagraph = CreateStyledLinkParagraph(currentSlide, linkUrl, linkText, false, true, 1500); parent.InsertBefore(newParagraph, paragraph); //insert new element paragraph.Remove();//delete placeholder } else { //insert text line var param = CloneParaGraphWithStyles(paragraph, dataParam.Name, dataParam.Text); // create new param - preserve styles parent.InsertBefore(param, paragraph);//insert new element paragraph.Remove();//delete placeholder } } }
I have included fully working solution below so you can easily convert it to your needs. I hope this information was useful for you 🙂