How to apply margin in Presentation Document using OpenXml - c#

I wrote code to create Presentation Document using open-xml SDK. I follow this sample code. MSDD Sample Code. Now i need to apply margin before starting my text. I've tried below code but didn't get expected result.
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 A.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 A.Paragraph(new D.EndParagraphRunProperties() { Language = "en-US" }, new D.ParagraphProperties() { LeftMargin = 10 }),
//new A.Paragraph(new A.Run(new A.RunProperties() { Bold = true, Italic = true, Underline = D.TextUnderlineValues.Single }, new A.Text()
//{ Text = text })))))),
new A.Paragraph(textListWithStyle.ToArray()))))),
new ColorMapOverride(new D.MasterColorMapping()));
My generated PPT File looks like:
No left margin applied but in code i applied 10 left margin.

It seems not so easy to add an indented paragraph using Open XML SDK. With Aspose.Slides for .NET, this can be done like this:
// Create a new presentation.
using var presentation = new Presentation();
// Add a text box to the first slide.
var slide = presentation.Slides[0];
var rectangle = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 20, 20, 200, 150);
// Create a new paragraph.
var paragraph = new Paragraph();
paragraph.Text = "Some text.";
// Set left margin for the paragraph.
paragraph.ParagraphFormat.MarginLeft = 10;
// Add the paragraph to the text box.
rectangle.TextFrame.Paragraphs.Add(paragraph);
// Save the presentation to PPTX format.
presentation.Save("example.pptx", SaveFormat.Pptx);
This is a paid product, but you can get a temporary license to evaluate all features of this library. I work as a Support Developer at Aspose.

Related

System.NullReferenceException: 'Object reference not set to an instance of an object.' page was null

I'm traying to test this method that checks for specific tag footer to show.
here is the function:
public void CheckForOrderOfFooterTags(PdfDocument pdfDoc, out TagTreePointer autoP, out TagTreePointer posBackup, out TagTreeInfo p)
{
// the following logic takes care of changing the order of the footer tags
// so that footers appear in the proper order in the tag tree structure
autoP =pdfDoc.GetTagStructureContext().GetAutoTaggingPointer();
posBackup =new TagTreePointer(autoP);
PagesTag.TryGetValue(PageNumber, out p);
if (p?.TagTreePointer != null)
{
// Make sure that content that will be tagged is placed in tag structure specifically where we need it.
int indexInParentKidsList = p.TagTreePointer.GetIndexInParentKidsList();
autoP.MoveToPointer(p.TagTreePointer).MoveToParent();
// setting new index only works on taggable items
if (p.Tagged)
{
autoP.SetNextNewKidIndex(indexInParentKidsList + 1);
}
}
}
and this is the test:
public void Check_For_Specific_Tag_Footer_To_Show_Successfully_Called()
{
var ir = new TestIllustrationReport().Report;
var reportProperties = new TestDocument().ReportProperties;
var sec = new FooterSection(new ProductContent(ir));
sec.Build();
Dictionary<int, TagTreeInfo> dict = new Dictionary<int, TagTreeInfo>();
reportProperties.FooterTag=dict;
FooterEventHandler footerEvent = new FooterEventHandler(sec, reportProperties);
// Must have write permissions to the path folder
var path = System.IO.Path.GetTempPath();
var fileName = System.IO.Path.ChangeExtension("Test", ".pdf");
var com = System.IO.Path.Combine(path, fileName);
// pdf
PdfWriter writer = new PdfWriter(com);
PdfDocument pdf = new PdfDocument(writer);
Event headerEvent= new PdfDocumentEvent("pdf", pdf);
PdfDocumentEvent docEvent = (PdfDocumentEvent)headerEvent;
iText.Layout.Document document = new iText.Layout.Document(pdf);
pdf.GetCatalog().SetLang(new PdfString("en-US"));
// Header and Paragraph
Paragraph header = new Paragraph(TestData.Header)
.SetTextAlignment(TextAlignment.CENTER)
.SetFontSize(20);
document.Add(header);
pdf.SetTagged();
pdf.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true));
PdfDocumentInfo info = pdf.GetDocumentInfo();
info.SetTitle("Testing tags");
Paragraph p = new Paragraph();
p.Add("The quick brown ");
PdfPage page = docEvent.GetPage();
// Rectangle and canvas
Rectangle rectangle = new Rectangle(
pdf.GetDefaultPageSize().GetX() + document.GetLeftMargin(),
pdf.GetDefaultPageSize().GetTop() - 80,
page.GetPageSize().GetWidth() - document.GetLeftMargin() - document.GetRightMargin(),
50);
Div canvas = new Div().SetFixedPosition(pdf.GetPageNumber(page), rectangle.GetLeft(), rectangle.GetBottom(), rectangle.GetWidth());
Paragraph pFooter = new Paragraph(TestData.Paragraph);
pFooter.GetAccessibilityProperties().SetRole("H");
canvas.Add(pFooter);
document.Add(canvas);
// Don't close document itself! It would close the PdfDocument!
document.GetRenderer().Close();
var pPointer = new TagTreePointer(pdf);
var pInfo = new TagTreeInfo { Tagged = true };
// Act
footerEvent.CheckForOrderOfFooterTags(pdf, out pPointer, out pPointer, out pInfo);
document.Close();
// Assert
Assert.NotNull(pdf);
}
For this test, I needed to create the pdf, set and build the footer section. I added the header to the pdf and the "footer test", I also set the document to be tagged.
I don't know why I always get the page is null if I'm adding a header and a paragraph to it.

How to set font size in empty cell of a Word table using the Open XML SDK?

I am creating a table in OpenXml with C# in a Word file. I used some code mentioned in this question to set the fontsize of the text in the cells. It works fine for the cells that contain text, but the empty cells seem to be given the normal style, and with that a bigger font size, which makes the row height bigger.
Here is my sample code with a single row with a single cell, where the font size should be 9:
TableRow tr = new TableRow();
TableCell tc = new TableCell();
Paragraph par = new Paragraph();
Run run = new Run();
Text txt = new Text("txt");
RunProperties runProps = new RunProperties();
FontSize fontSize = new Fontsize() { Val = "18" }; // font size 9
runProps.Append(fontSize);
run.Append(runProps);
run.Append(txt);
para.Append(run);
tc.Append(para);
tr.Append(tc);
Here is an example of the resulting table. As you can see the middle row is taller than the others. In the cells that say "txt" the font size is 9, but in the blank cell the font size is 11. The code above is used for all the cells, where the empty cell simply has the text "". When I looked at the file with the Open XML Tool, I can see that the RunProperties with value 18 is there for all the cells including the empty one.
How do I set the font size of a cell without displaying any text?
I confirm what you report. One way around it would be to substitute a space " " for the "empty" string, adding "space preserve" to the text run, of course.
Another possibility would be to create a character style and apply it to the table cells. This turned out to be trickier than it sounds as the style needs to be applied twice to cells that contain text: once to the ParagraphMarkRunProperties and once to the RunProperties. For empty cells the style need be applied only to the ParagraphMarkRunProperties.
Actually, on reflection, you can use the same approach for the font size...
I've included both approaches in the code below. The one for just the font size is commented out (four lines).
The sample code assumes that the third cell of the one-row, four column table, has no content. Run and Text information is added only when there is content.
private void btnCreateTable_Click(object sender, EventArgs e)
{
string filePath = #"C:\X\TestCreateTAble.docx";
using (WordprocessingDocument pkg = WordprocessingDocument.Open(filePath, true))
{
MainDocumentPart partDoc = pkg.MainDocumentPart;
Document doc = partDoc.Document;
StyleDefinitionsPart stylDefPart = partDoc.StyleDefinitionsPart;
Styles styls = stylDefPart.Styles;
Style styl = CreateTableCharacterStyle();
stylDefPart.Styles.AppendChild(styl);
Table t = new Table();
TableRow tr = new TableRow();
for (int i = 1; i <= 4; i++)
{
TableCell tc = new TableCell(new TableCellProperties(new TableCellWidth() { Type = TableWidthUnitValues.Dxa, Width = "500" }));
Paragraph para = new Paragraph();
ParagraphProperties paraProps = new ParagraphProperties();
ParagraphMarkRunProperties paraRunProps = new ParagraphMarkRunProperties();
RunStyle runStyl = new RunStyle() { Val = "Table9Point" };
paraRunProps.Append(runStyl);
// FontSize runFont = new FontSize() {Val = "18" };
// paraRunProps.Append(runFont);
paraProps.Append(paraRunProps);
para.Append(paraProps);
Run run = new Run();
Text txt = null;
if (i == 3)
{
}
else
{
txt = new Text("txt");
txt.Space = SpaceProcessingModeValues.Preserve;
RunProperties runProps = new RunProperties();
RunStyle inRunStyl = (RunStyle) runStyl.Clone();
runProps.Append(inRunStyl);
// FontSize inRunFont = (FontSize) runFont.Clone();
// runProps.Append(inRunFont);
run.Append(runProps);
run.Append(txt);
para.Append(run);
}
tc.Append(para);
tr.Append(tc);
}
t.Append(tr);
//Insert at end of document
SectionProperties sectProps = doc.Body.Elements<SectionProperties>().LastOrDefault();
doc.Body.InsertBefore(t, sectProps);
}
}
private Style CreateTableCharacterStyle()
{
Style styl = new Style()
{
CustomStyle = true,
StyleId = "Table9Point",
Type = StyleValues.Character,
};
StyleName stylName = new StyleName() { Val = "Table9Point" };
styl.AppendChild(stylName);
StyleRunProperties stylRunProps = new StyleRunProperties();
stylRunProps.FontSize = new FontSize() { Val = "18" };
styl.AppendChild(stylRunProps);
BasedOn basedOn1 = new BasedOn() { Val = "DefaultParagraphFont" };
styl.AppendChild(basedOn1);
return styl;
}
Just need to set the FontSize and FontSizeComplexScript for the ParagraphProperties and RunProperties, like this:
var cell = new TableCell(
new Paragraph(
new ParagraphProperties(
new SpacingBetweenLines { LineRule = LineSpacingRuleValues.Auto, Before = "0", After = "0" },
new RunProperties(
new FontSize { Val = "18" },
new FontSizeComplexScript { Val = "18" })),
new Run(
new RunProperties(
new FontSize { Val = "18" },
new FontSizeComplexScript { Val = "18" }),
new Text { Text = String.Empty, Space = SpaceProcessingModeValues.Preserve })));

How to dynamically add a page number in footer in Microsoft OXML c#

I'm creating a word document using OXML in Visual Studio. I don't know how long it is going to be and I need to add a simple page number in the footer of the document.
To generate headers and footers I used this:
https://msdn.microsoft.com/en-us/library/ee355228(v=office.12).aspx
As I understand, this presets the default headers/footers before I even write anything in the document. So I'm not quite sure if I can add page numbering to this? I'd really appreciate the help, because I've been stuck on this for a whole day...
You can add dynamic page numbers by adding a SimpleField with an Instruction of "PAGE". Word will automatically update any such field with the correct page number.
In order to code that you can adapt the GeneratePageFooterPart in the link you provided to include a SimpleField in the Run that gets added to the Footer:
private static Footer GeneratePageFooterPart(string FooterText)
{
var element =
new Footer(
new Paragraph(
new ParagraphProperties(
new ParagraphStyleId() { Val = "Footer" }),
new Run(
new Text(FooterText),
// *** Adaptation: This will output the page number dynamically ***
new SimpleField() { Instruction = "PAGE" })
));
return element;
}
Note that you can change the format of the page number by postfixing the PAGE text. From the Ecma Office Open XML Part 1 - Fundamentals And Markup Language Reference.pdf:
When the current page number is 19 and the following fields are updated:
PAGE
PAGE \* ArabicDash
PAGE \* ALPHABETIC
PAGE \* roman
the results are:
19
- 19 -
S
xix
So to get roman numerals for example you would need to change the SimpleField line of code above to:
new SimpleField() { Instruction = "PAGE \\* roman" })
or (if you prefer)
new SimpleField() { Instruction = #"PAGE \* roman" })
Try this:
private static void GenerateFooterPartContent(WordprocessingDocument package, string text = null)
{
FooterPart footerPart1 = package.MainDocumentPart.FooterParts.FirstOrDefault();
if (footerPart1 == null)
{
footerPart1 = package.MainDocumentPart.AddNewPart<FooterPart>();
}
var relationshipId = package.MainDocumentPart.GetIdOfPart(footerPart1);
// Get SectionProperties and set HeaderReference and FooterRefernce with new Id
SectionProperties sectionProperties1 = new SectionProperties();
FooterReference footerReference2 = new FooterReference() { Type = HeaderFooterValues.Default, Id = relationshipId };
sectionProperties1.Append(footerReference2);
package.MainDocumentPart.Document.Body.Append(sectionProperties1);
Footer footer1 = new Footer();
Paragraph paragraph2 = CreateParagraph(package, string.Empty, "Footer");
Run r = new Run(new SimpleField() { Instruction = "DATE" });
paragraph2.Append(r);
if (!string.IsNullOrWhiteSpace(text))
{
r = new Run();
PositionalTab positionalTab1 = new PositionalTab() { Alignment = AbsolutePositionTabAlignmentValues.Center,
RelativeTo = AbsolutePositionTabPositioningBaseValues.Margin,
Leader = AbsolutePositionTabLeaderCharValues.None };
r.Append(positionalTab1);
paragraph2.Append(r);
r = new Run(new Text(text) { Space = SpaceProcessingModeValues.Preserve });
paragraph2.Append(r);
}
r = new Run();
PositionalTab positionalTab2 = new PositionalTab() { Alignment = AbsolutePositionTabAlignmentValues.Right,
RelativeTo = AbsolutePositionTabPositioningBaseValues.Margin,
Leader = AbsolutePositionTabLeaderCharValues.None };
r.Append(positionalTab2);
paragraph2.Append(r);
r = new Run(new Text("Page: ") { Space = SpaceProcessingModeValues.Preserve },
// *** Adaptation: This will output the page number dynamically ***
new SimpleField() { Instruction = "PAGE" },
new Text(" of ") { Space = SpaceProcessingModeValues.Preserve },
// *** Adaptation: This will output the number of pages dynamically ***
new SimpleField() { Instruction = "NUMPAGES" });
paragraph2.Append(r);
footer1.Append(paragraph2);
footerPart1.Footer = footer1;
}
Refer to the following link for more instructions.

Apply style on Content Control in a Word Document using OpenXML

I'm trying to generate Word documents using OpenXML SDK and Word Document Generator. I need to apply my custom style on ContentControls (Repeating Section).
For Recursive Placeholders, I use
foreach (var item in list)
{
var datacontext = new OpenXmlElementDataContext()
{
Element = openXmlElementDataContext.Element,
DataContext = item.Value
};
var clonedElement = CloneElementAndSetContentInPlaceholders(datacontext);
SetContentOfContentControl(clonedElement, item.Value);
}
openXmlElementDataContext.Element.Remove();
I need to apply my style on this element. How to I can do ?
I try to see generated code with "Open XML SDK 2.5 Productivity Tool for Microsoft Office" to inspire me:
var moduleDatacontext = new OpenXmlElementDataContext()
{
Element = openXmlElementDataContext.Element,
DataContext = module.Valeur
};
var moduleClonedElement = CloneElementAndSetContentInPlaceholders(moduleDatacontext);
var sdtProperties1 = new SdtProperties();
var styleId1 = new StyleId() { Val = "FormationTitre2" };
ParagraphMarkRunProperties paragraphMarkRunProperties1 = new ParagraphMarkRunProperties();
RunFonts runFonts1 = new RunFonts() { ComplexScriptTheme = ThemeFontValues.MinorHighAnsi };
paragraphMarkRunProperties1.Append(runFonts1);
sdtProperties1.Append(styleId1);
sdtProperties1.Append(paragraphMarkRunProperties1);
Run run1 = new Run() { RsidRunProperties = "00C463E5" };
RunProperties runProperties1 = new RunProperties();
RunFonts runFonts2 = new RunFonts() { ComplexScriptTheme = ThemeFontValues.MinorHighAnsi };
runProperties1.Append(runFonts2);
run1.Append(runProperties1);
moduleClonedElement.Append(sdtProperties1);
moduleClonedElement.Append(run1);
When I open the generated document, I have this error :
We're sorry. We can't open "...docx" because we found a problem with its contents.
I validate the document and I can see 15 errors:
Full Size
I've found the solution. I search first paragraph and apply my custom style on it.
// clone element
var clonedElement = CloneElementAndSetContentInPlaceholders(datacontext);
// search the first created paragraph on my clonedElement
Paragraph p = clonedElement.Descendants<Paragraph>().FirstOrDefault();
if (p != null)
p.PrependChild<ParagraphProperties>(new ParagraphProperties());
// get the paragraph properties
ParagraphProperties pPr = p.Elements<ParagraphProperties>().First();
// apply style
pPr.ParagraphStyleId = new ParagraphStyleId { Val = "FormationTitre2" };
// set content of content control
SetContentOfContentControl(clonedElement, item.Value);

Changing Bullet Styles with Word 2007 Automation in C#

I am trying to change the style of my bullets in a word document (Word 2007).... I currently place a bullet and it comes out as a circle. I want it to be a square... here's my code for applying bullets...
public void ToggleBullets(bool bulletsOn)
{
Microsoft.Office.Interop.Word.Application wd;
Object _oMissing = Type.Missing;
Object _numberType = WdNumberType.wdNumberListNum;
if (bulletsOn)
{
wd.Selection.Range.ListFormat.ApplyBulletDefault(ref _oMissing);
}
else
{
wd.Selection.Range.ListFormat.RemoveNumbers(ref _numberType);
}
}
any ideas? Let me know if you need more details
I use the Open XML SDK 2.0 Productivity Tool for Microsoft Office:
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=c6e744e5-36e9-45f5-8d8c-331df206e0d0&displaylang=en
When I want to to do these kinds of things. Just launch the Productivity tool, load up the .docx that has what you want and then let the tool generate the code for you.
I just whipped up an example and this was the code it generated:
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
....
public Paragraph GenerateParagraph()
{
Paragraph paragraph1 = new Paragraph(){ RsidParagraphAddition = "00EA7FFB", RsidParagraphProperties = "00EA7FFB", RsidRunAdditionDefault = "00EA7FFB" };
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId(){ Val = "ListParagraph" };
NumberingProperties numberingProperties1 = new NumberingProperties();
NumberingLevelReference numberingLevelReference1 = new NumberingLevelReference(){ Val = 0 };
NumberingId numberingId1 = new NumberingId(){ Val = 2 };
numberingProperties1.Append(numberingLevelReference1);
numberingProperties1.Append(numberingId1);
paragraphProperties1.Append(paragraphStyleId1);
paragraphProperties1.Append(numberingProperties1);
Run run1 = new Run();
Text text1 = new Text(){ Space = SpaceProcessingModeValues.Preserve };
text1.Text = "Item ";
run1.Append(text1);
paragraph1.Append(paragraphProperties1);
paragraph1.Append(run1);
return paragraph1;
}
This is using the OpenXml headers, and not Word specifically

Categories

Resources