Different styling in a line in wordprocessing with opxnxml in c# - c#

I have used codes below to apply two different character style to the two runs of one paragraph:
Paragraph heading = new Paragraph();
ParagraphProperties heading_pPr = new ParagraphProperties();
heading.Append(heading_pPr);
Run Run1 = new Run() { RsidRunProperties = "009531B2" };
Text Text_Run1 = new Text("THIS IS TEST RUN 1");
Run1.Append(Text_Run1);
RunProperties rpr_Run1 = new RunProperties();
rpr_Run1.RunStyle = new RunStyle() { Val = "CharacterStyle1" };
Run Run2 = new Run();
RunProperties rpr_Run2 = new RunProperties();
rpr_Run2.RunStyle = new RunStyle() { Val = "CharacterStyle2" };
Text text_Run2 = new Text("THIS IS TEST RUN 2");
Run2.Append(text_Run2);
heading.Append(Run1);
heading.Append(Run2);
body.Append(heading);
But after running the code, In the word file these runs gets the Normal style.
I can apply paragraph style to the paragraph but i can't apply character style to run,Where is wrong in my code?
In Conclusion:
How can i apply character style to a run and how to have a paragraph with different styling Run?

You need to specify the formatting for the paragraph in its properties section otherwise it's going to fallback to the document's default which in this case is Normal. This might also happen if your custom styles are not saved to the styles part of the document.
Change your code to:
Paragraph heading = new Paragraph();
ParagraphProperties heading_pPr = new ParagraphProperties();
heading.Append(heading_pPr);
ParagraphMarkRunProperties headingParagraphMarkRunProperties = new ParagraphMarkRunProperties();
RunStyle runStyle1 = new RunStyle(){ Val = "CharacterStyle1" };
headingParagraphMarkRunProperties.Append(runStyle1);
heading_pPr.Append(headingParagraphMarkRunProperties);
This will enable your paragraph to adopt your custom formatting. You still need to apply individual styles to the run elements to change it's formatting as you correctly did in your rest of the code.

Related

GemBox C# - position qr code in top right corner

I am creating a PDF-file with GemBox in my .net project and I am wondering how to position the qr code in the top right corner.
With the code below, I am replacing variables in my word file and with the addition of the qr code section, the qr code is created on a separate page instead on the same page.
So my question is, how to place the qr code on the same page and how to position it in the top right corner.
I hope someone can help :)
var qrCodeValue = JsonConvert.SerializeObject(new
{
FirstName = data.firstName,
LastName = data.lastName,
CreationDate = data.documentCreationDate
});
var qrCodeField = new Field(document, FieldType.DisplayBarcode, $"{qrCodeValue} QR");
document.Sections.Add(new Section(document, new Paragraph(document, qrCodeField)));
document.Content.Replace("%FirstName%", data.firstName);
document.Content.Replace("%LastName%", data.lastName);
You need to add the QR code to an existing section.
Also, to position it in the top right corner you could insert the right aligned Paragraph at the beginning or in the document's header or insert a floating TextBox.
Here are the examples for all three suggested approaches.
Insert into the body of an existing section
var qrCodeField = new Field(document, FieldType.DisplayBarcode, $"{qrCodeValue} QR");
var qrCodeParagraph = new Paragraph(document, qrCodeField);
qrCodeParagraph.ParagraphFormat.Alignment = HorizontalAlignment.Right;
document.Sections[0].Blocks.Insert(0, qrCodeParagraph);
Insert into the header of an existing section
var qrCodeField = new Field(document, FieldType.DisplayBarcode, $"{qrCodeValue} QR");
var qrCodeParagraph = new Paragraph(document, qrCodeField);
qrCodeParagraph.ParagraphFormat.Alignment = HorizontalAlignment.Right;
var headersFooters = document.Sections[0].HeadersFooters;
if (headersFooters[HeaderFooterType.HeaderFirst] == null)
headersFooters.Add(new HeaderFooter(document, HeaderFooterType.HeaderFirst));
headersFooters[HeaderFooterType.HeaderFirst].Blocks.Insert(0, qrCodeParagraph);
Insert with a floating textbox
var qrCodeField = new Field(document, FieldType.DisplayBarcode, $"{qrCodeValue} QR");
var qrCodeParagraph = new Paragraph(document, qrCodeField);
var qrTextBox = new TextBox(document,
new FloatingLayout(
new HorizontalPosition(-50, LengthUnit.Point, HorizontalPositionAnchor.RightMargin),
new VerticalPosition(50, LengthUnit.Point, VerticalPositionAnchor.TopMargin),
new Size(100, 100)),
qrCodeParagraph);
qrTextBox.Outline.Fill.SetEmpty();
var paragraph = (Paragraph)document.Sections[0]
.GetChildElements(false, ElementType.Paragraph)
.First();
paragraph.Inlines.Add(qrTextBox);

My font size set using openXML for a Powerpoint paragraph is not being used

I'm trying to set a font size for a paragraph in a PowerPoint slide. In my code when I print out the font size it displays as 9 but when I open up my PowerPoint it is set to 12.
Notes:
I don't have admin rights on my pc so I can't install tools to help reverse-engineer something as I've read in a few posts.
_bulletParagraphOuterXML is a string I grabbed from a premade paragraph after hours of hunting how to set bullets via code. Still don't know how and learning how is another post for the future. Even if it says Arial in this string the bullet point text is in Times New Roman.
In the code it prints a font size of 9 but in the PowerPoint it shows up with a font size of 12.
Bellow is code I've extracted from the class I use to modify and update my PowerPoint Document.
using System;
using System.Collections.Generic;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using D = DocumentFormat.OpenXml.Drawing;
using P = DocumentFormat.OpenXml.Presentation;
static string _bulletParagraphOuterXML = "<a:pPr marL=\"285750\" indent=\"-285750\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\"><a:buFont typeface=\"Arial\" panose=\"020B0604020202020204\" pitchFamily=\"34\" charset=\"0\" /><a:buChar char=\"•\" /></a:pPr>";
public static void ReplaceShapeBulletsText(this SlidePart slidePart, string ShapeName, List<string> newTexts)
{
P.Shape shape = slidePart.GetShapeByName(ShapeName);
D.Paragraph paragraph = shape.TextBody.Elements<D.Paragraph>().FirstOrDefault();
shape.TextBody.RemoveAllChildren<D.Paragraph>();
foreach (string text in newTexts)
{
shape.AddBulletParagraph(text);
}
}
public static void AddBulletParagraph(this P.Shape shape, string NewText)
{
D.Paragraph p = new D.Paragraph();
P.TextBody docBody = shape.TextBody;
p.ParagraphProperties = new D.ParagraphProperties(_bulletParagraphOuterXML);
D.Run run = new D.Run(new D.Text(NewText));
D.RunProperties runProp = new D.RunProperties() { Language = "en-US", FontSize = 9, Dirty = false };
run.AppendChild(runProp);
Console.WriteLine("--------------------------------------------------------------");
Console.WriteLine(runProp.FontSize.ToString());
Console.WriteLine("--------------------------------------------------------------");
p.Append(run);
docBody.Append(p);
}
Order of appending matters in openXML. After being able to get both the text with the incorrect font size and the text with the correct font size to appear in the same shape I noticed only one difference.
The order in which a:rPr and a:t appear. a:rPr needs to precede a:t
Knowing this one fact should also help me solve lots of other issues I've been having.
Correct Font Size
<a:p>
<a:pPr marL="171450" indent="-171450">
<a:buFont typeface="Arial" charset="0" pitchFamily="34" panose="020B0604020202020204"/>
<a:buChar char="•"/>
</a:pPr>
<a:r>
<a:rPr lang="en-US" sz="900"/>
<a:t>Random Text</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0" sz="900"/>
</a:p>
Incorrect Font Size
<a:p>
<a:pPr xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" marL="285750" indent="-285750">
<a:buFont typeface="Arial" charset="0" pitchFamily="34" panose="020B0604020202020204"/>
<a:buChar char="•"/>
</a:pPr>
<a:r>
<a:t>Other Random Text</a:t>
<a:rPr lang="en-US" dirty="0" sz="900"/>
</a:r>
<a:endParaRPr lang="en-US" dirty="0" sz="900"/>
</a:p>
To relate it back to my code.
This code block:
p.ParagraphProperties = new D.ParagraphProperties(_bulletParagraphOuterXML);
D.Run run = new D.Run(new D.Text(NewText));
D.RunProperties runProp = new D.RunProperties() { Language = "en-US", FontSize = 9, Dirty = false };
run.AppendChild(runProp);
was updated to
p.ParagraphProperties = new D.ParagraphProperties(_bulletParagraphOuterXML);
D.Run run = new D.Run();
D.RunProperties runProp = new D.RunProperties() { Language = "en-US", FontSize = 900, Dirty = false };
run.AppendChild(runProp);
D.Text newText = new D.Text(NewText);
run.AppendChild(newText);

Add date on Presentations (Open XML SDK) on C#

My reference is Presentations (Open XML SDK)
With the code-behind below I add the date on existing PowerPoint.
This code working and in the first slide the date is added, but it's possible customize the point on the page where to insert this date? The font and size ?
This is current output:
Thank you in advance for help.
string fileName = #"C:\\inetpub\\wwwroot\\aspnet\\Template\\01_FOCUS.pptx";
using (PresentationDocument oPDoc = PresentationDocument.Open(fileName, true))
{
PresentationPart oPPart = oPDoc.PresentationPart;
SlideIdList slideIdList = oPPart.Presentation.SlideIdList;
SlidePart sp = slideIdList.ChildElements
.Cast<SlideId>()
.Select(x => oPPart.GetPartById(x.RelationshipId))
.Cast<SlidePart>().First();
AddDateToSlidePart(sp);
}
public static void AddDateToSlidePart(SlidePart slidePart1)
{
Slide slide1 = slidePart1.Slide;
CommonSlideData commonSlideData1 = slide1.GetFirstChild<CommonSlideData>();
ShapeTree shapeTree1 = commonSlideData1.GetFirstChild<ShapeTree>();
DocumentFormat.OpenXml.Presentation.Shape shape1 =
new DocumentFormat.OpenXml.Presentation.Shape();
DocumentFormat.OpenXml.Presentation.NonVisualShapeProperties nonVisualShapeProperties1 =
new DocumentFormat.OpenXml.Presentation.NonVisualShapeProperties();
DocumentFormat.OpenXml.Presentation.NonVisualDrawingProperties nonVisualDrawingProperties1 =
new DocumentFormat.OpenXml.Presentation.NonVisualDrawingProperties() { Id = (UInt32Value)4U, Name = "Date Placeholder 3" };
DocumentFormat.OpenXml.Presentation.NonVisualShapeDrawingProperties nonVisualShapeDrawingProperties1 =
new DocumentFormat.OpenXml.Presentation.NonVisualShapeDrawingProperties();
DocumentFormat.OpenXml.Drawing.ShapeLocks shapeLocks1 =
new DocumentFormat.OpenXml.Drawing.ShapeLocks() { NoGrouping = true };
nonVisualShapeDrawingProperties1.Append(shapeLocks1);
ApplicationNonVisualDrawingProperties applicationNonVisualDrawingProperties1 =
new ApplicationNonVisualDrawingProperties();
PlaceholderShape placeholderShape1 =
new PlaceholderShape() { Type = PlaceholderValues.DateAndTime, Size = PlaceholderSizeValues.Half, Index = (UInt32Value)10U };
applicationNonVisualDrawingProperties1.Append(placeholderShape1);
nonVisualShapeProperties1.Append(nonVisualDrawingProperties1);
nonVisualShapeProperties1.Append(nonVisualShapeDrawingProperties1);
nonVisualShapeProperties1.Append(applicationNonVisualDrawingProperties1);
DocumentFormat.OpenXml.Presentation.ShapeProperties shapeProperties1 =
new DocumentFormat.OpenXml.Presentation.ShapeProperties();
DocumentFormat.OpenXml.Presentation.TextBody textBody1 =
new DocumentFormat.OpenXml.Presentation.TextBody();
DocumentFormat.OpenXml.Drawing.BodyProperties bodyProperties1 =
new DocumentFormat.OpenXml.Drawing.BodyProperties();
DocumentFormat.OpenXml.Drawing.ListStyle listStyle1 =
new DocumentFormat.OpenXml.Drawing.ListStyle();
DocumentFormat.OpenXml.Drawing.Paragraph paragraph1 =
new DocumentFormat.OpenXml.Drawing.Paragraph();
DocumentFormat.OpenXml.Drawing.Field field1 =
new DocumentFormat.OpenXml.Drawing.Field() { Id = "{528B97E8-8E4B-4D32-BA17-4F287283DFD6}", Type = "datetime1" };
DocumentFormat.OpenXml.Drawing.RunProperties runProperties1 =
new DocumentFormat.OpenXml.Drawing.RunProperties() { Language = "it-IT" };
DocumentFormat.OpenXml.Drawing.Text text1 =
new DocumentFormat.OpenXml.Drawing.Text();
text1.Text = DateTime.Now.ToString("dd/mm/yyyy");
field1.Append(runProperties1);
field1.Append(text1);
DocumentFormat.OpenXml.Drawing.EndParagraphRunProperties endParagraphRunProperties1 =
new DocumentFormat.OpenXml.Drawing.EndParagraphRunProperties() { Language = "it-IT" };
paragraph1.Append(field1);
paragraph1.Append(endParagraphRunProperties1);
textBody1.Append(bodyProperties1);
textBody1.Append(listStyle1);
textBody1.Append(paragraph1);
shape1.Append(nonVisualShapeProperties1);
shape1.Append(shapeProperties1);
shape1.Append(textBody1);
shapeTree1.Append(shape1);
}
The OpenXML SDK Productivity tool (downloadable from the Microsoft site) is your friend here. When I need to do something like this, I:
Create the document I want
Open it in the appropriate tool (PowerPoint in this case).
Make a tiny change (to "dirty" the document and make PowerPoint believe it needs to be changed).
Save the result
Make the changes to the document that I want to see, and save the result with a new name
Open the OpenXML Productivity Tool and click the "Compare Files" tool.
The reason I force a save (in steps 3/4) is so that PowerPoint can add all of it's PowerPoint-ness to the document I created. The second save (step 5) will necessarily have all of that, so I want the two documents as close as possible - with only the "changes to the document that I want to see" being the difference between the two documents.
At this point, you should see a path to a solution to your problem. That tool is indispensable when working with OOXML.

How to apply a character style to a run in a wordprocessing document?

When I create a paragraph style with openxml sdk 2 in c# and apply it to a paragraph every thing will be correct and it will run without any problem.
But with the codes below, when I create a character style and apply it to a run it make no change to the runs of document:
Codes below will create and save the style to style part of document:
StyleDefinitionsPart stylePart = mainPart.AddNewPart<StyleDefinitionsPart>();
Style style = new Style()
{
Type = StyleValues.Character,
CustomStyle = true,
StyleId = "CharacterStyle1"
};
LinkedStyle linkedStyle1 = new LinkedStyle() { Val = "LinkedStyle" };
style.Append(linkedStyle1);
style.Append(new Name() { Val = "CharacterStyle1" });
StyleRunProperties styleRunProperties1 = new StyleRunProperties();
Color color = new Color() { Val = "FF0000" };
RunFonts font1 = new RunFonts() { ComplexScript = "Tahoma" };
styleRunProperties1.Append(color);
styleRunProperties1.Append(font1);
styleRunProperties1.Append(new Bold());
styleRunProperties1.Append(new FontSize() { Val = "48" });
style.Append(styleRunProperties1);
stylePart.Styles = new Styles();
stylePart.Styles.Append(style);
And below codes are something I wrote to apply the style to a run:
Paragraph heading = new Paragraph();
ParagraphProperties headingPPr = new ParagraphProperties();
heading.Append(headingPPr);
Run run1 = new Run();
Text textRun1 = new Text("THIS IS TEST RUN 1");
run1.Append(textRun1);
RunProperties rprRun1 = new RunProperties {RunStyle = new RunStyle() {Val = "CharacterStyle1"}};
heading.Append(run1);
body.Append(heading);
And these are the output code of document.xml:
<?xml version="1.0" encoding="utf-8"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:pPr />
<w:r w:rsidRPr="009531B2">
<w:t>THIS IS TEST RUN 1</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
The style didn't applied to my run!
And at the end, this is the screen-shot of the style gallery when I open the outputted document, this picture show that the style has been added successfully to the document but it didn't apply to run:
How can I apply a character style to a run?
Based on the ECMA specification for OpenXML, in order to style any runs in the paragraph you have to apply style to the paragraph mark as well :
17.3.1.29 rPr (Run Properties for the Paragraph Mark)
This element specifies the set of run properties applied to the glyph used to
represent the physical location of the paragraph mark for this
paragraph. This paragraph mark, being a physical character in the
document, can be formatted, and therefore shall be capable of
representing this formatting like any other character in the
document. If this element is not present, the paragraph mark is
unformatted, as with any other run of text.
So to fix this in your code.. try this..
Paragraph heading = new Paragraph();
ParagraphProperties headingPPr = new ParagraphProperties();
heading.Append(headingPPr);
ParagraphMarkRunProperties headingParagraphMarkRunProperties = new ParagraphMarkRunProperties();
RunStyle runStyle1 = new RunStyle(){ Val = "CharacterStyle1" };
headingParagraphMarkRunProperties.Append(runStyle1);
headingPPr.Append(headingParagraphMarkRunProperties);
Run run1 = new Run();
Text textRun1 = new Text("THIS IS TEST RUN 1");
run1.Append(textRun1);
RunProperties rprRun1 = new RunProperties {RunStyle = new RunStyle() {Val = "CharacterStyle1"}};
run1.Append(rprRun1);
heading.Append(run2);
body.Append(heading);
Update:
Based on your open xml snippet in the comment, you forgot to include
RunProperties rprRun1 = new RunProperties {RunStyle = new RunStyle() {Val = "CharacterStyle1"}};
run1.Append(rprRun1); //Adding run properties to the run
in your code. It is also required to apply properties to the run seperately in order to get the formatting applied to the run element as run has its own properties section:
Just as a paragraph can have properties, so too can a run. All of the
elements inside an r element have their properties controlled by a
corresponding optional rPr run properties element (§17.7.9.1;
§17.3.2.27), which shall be the first child of the r element. In
turn, the rPr element is a container for a set of property elements
that are applied to the rest of the children of the r element. [Note:
The elements inside the rPr container element allow the consumer to
control whether the content in the following run content is bold,
underlined, or visible, for example. end note]
Hope this helps.

OpenXML preserving formats on break lines (problems)

I'm having serious problems with the breaks in a Word document generation.
this is my library funcion I'm using for send text in a BookMark:
public void sentText(string _BkMk, string _text, bool _break, RunProperties _rProp)
{
Text text = new Text(_text) { Space = SpaceProcessingModeValues.Preserve };
Run run = new Run(new RunProperties(_rProp));
run.Append(text);
Run run2 = new Run();
if (_break)
{
run2.Append(new Break());
//CarriageReturn cr = new CarriageReturn();
//run2.Append(cr);
}
foreach (BookmarkStart bookmarkStart in bookmarkMap.Values)
{
if (bookmarkStart.Name.Value == _BkMk)
{
bookmarkStart.InsertBeforeSelf(run);
if (_break)
{
bookmarkStart.InsertBeforeSelf(run2);
}
}
}
in the runProperties cames the font, size, etc...
The biggest problem is when I send diferent strings in the same Bookmark and I need to leave a line space. I send a empty string, or a space like " " and the result is a empty line, but with a diferent font (TimesNewRoman) and size (12). For me is really important to preserve the font size in this empty lines...
Some idea?
If I understand your question correctly and all you want is a blank line then all you have to do is insert a blank paragraph and it should follow the default font that you have setup. This will require you to split up your text across two different paragraphs with two different runs in order to work:
public void sentText(string _BkMk, string _text, bool _break, RunProperties _rProp)
{
Text text = new Text(_text) { Space = SpaceProcessingModeValues.Preserve };
Run run = new Run(new RunProperties(_rProp));
run.Append(text);
Paragraph paragraph1 = new Paragraph();
paragraph1.Append(run);
foreach (BookmarkStart bookmarkStart in bookmarkMap.Values)
{
if (bookmarkStart.Name.Value == _BkMk)
{
bookmarkStart.InsertBeforeSelf(paragraph1);
if (_break)
{
bookmarkStart.InsertBeforeSelf(paragraph1);
bookmarkStart.InsertBeforeSelf(new Paragraph());
}
}
}
}
I would also recommend using paragraphs instead of just runs since Word will create an empty paragraph when you hit the enter key.

Categories