I have in document placeholder with some text. This text consists from several strings, splitted by "<line>". How can I replace this text witha scoupe of paragraphs, each containing only one string?
I've found a solution. It was only necessary to break the string and for each string create a paragraph with formatting, otherwise the elements are created as OpenXmlUnknownElement.
XDocument customXml = GenerateXmlForReport(report);
String customXmlId = AddCustomXml(document, customXml);
DataBind(document, customXml, customXmlId);
document.MainDocumentPart.Document.Body.GetFirstChild<SdtBlock>().RemoveAllChildren();
string[] lines = Regex.Split(report.ReportTextBody, "</line>");
foreach (var line in lines)
{
Paragraph p = new Paragraph();
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId() { Val = "BodyText" };
ParagraphMarkRunProperties paragraphMarkRunProperties1 = new ParagraphMarkRunProperties();
RunFonts runFonts1 = new RunFonts() { Ascii = "Arial", HighAnsi = "Arial" };
paragraphMarkRunProperties1.Append(runFonts1);
paragraphProperties1.Append(paragraphStyleId1);
paragraphProperties1.Append(paragraphMarkRunProperties1);
RunProperties runProperties1 = new RunProperties();
RunStyle runStyle1 = new RunStyle() { Val = "PlaceholderText" };
runProperties1.Append(runStyle1);
Run run = new Run();
Text txt = new Text(line);
run.Append(txt);
p.Append(run);
document.MainDocumentPart.Document.Body.GetFirstChild<SdtBlock>().Append(p);
}
Related
I am using GemBox.Document library in my ASP.Net Page. I have a paragraph which contains line breaks and I also need to set the paragraph to bold.
I my below code the variable str contains line break characters.
TRY 1
Line breaks work well in the below code
var p3 = new Paragraph(wDoc, str);
How to set BOLD to this paragraph
TRY 2
Bold work well in the below code
var p3 = new Paragraph(wDoc,
new Run(wDoc, str) { CharacterFormat = { Bold = true } }
);
This doesn't allow line breaks
Please help for a solution
Probably the easiest way to do this is something like this:
var paragraph = new Paragraph(wDoc);
paragraph.Content.LoadText(str, new CharacterFormat() { Bold = true });
Or this:
var paragraph = new Paragraph(wDoc);
paragraph.CharacterFormatForParagraphMark.Bold = true;
paragraph.Content.LoadText(str);
But just in case you're interested, the thing to note here is that line breaks are represented with SpecialCharacter objects, not with Run objects.
So the following would be the "manual" way in which you would need to handle those breaks yourself, you would need to add the correct elements to the Paragraph.Inlines collection:
string str = "Sample 1\nSample 2\nSample 3";
string[] strLines = str.Split('\n');
var paragraph = new Paragraph(wDoc);
for (int i = 0; i < strLines.Length; i++)
{
paragraph.Inlines.Add(
new Run(wDoc, strLines[i]) { CharacterFormat = { Bold = true } });
if (i != strLines.Length - 1)
paragraph.Inlines.Add(
new SpecialCharacter(wDoc, SpecialCharacterType.LineBreak));
}
That is the same as if you were using this Paragraph constructor:
var paragraph = new Paragraph(wDoc,
new Run(wDoc, "Sample 1") { CharacterFormat = { Bold = true } },
new SpecialCharacter(wDoc, SpecialCharacterType.LineBreak),
new Run(wDoc, "Sample 2") { CharacterFormat = { Bold = true } },
new SpecialCharacter(wDoc, SpecialCharacterType.LineBreak),
new Run(wDoc, "Sample 3") { CharacterFormat = { Bold = true } });
I'm generating a word docx file from a html string and using various articles I've found how to add simple headers and footers to that document.
What I now need to do is generate the header from a html string too but I'm struggling to find an example of how this is done.
The author of this question:
Export docx/doc First Header and Footer as docx File Using openXML
says he has done it but unfortunately he hasn't posted an example.
My code below successfully adds a header but as you can see from the code it will only add the html as text in the header, whereas I want to pass in a html string and that to appear in the header as formatted html.
Has anyone done this?
static void AddHeaderPart(MainDocumentPart mainPart, string headerHtml, Encoding encoding)
{
if (mainPart == null || string.IsNullOrEmpty(headerHtml))
{return;}
// Create a new header part.
HeaderPart headerPart = mainPart.AddNewPart<HeaderPart>();
// Get Id of the headerPart.
string rId = mainPart.GetIdOfPart(headerPart);
// Call GenerateHeaderPartContent
GenerateHeaderPartContent(mainPart, headerPart, headerHtml, encoding);
// Get SectionProperties and Replace HeaderReference with new Id.
IEnumerable<SectionProperties> sectPrs = mainPart.Document.Body.Elements<SectionProperties>();
foreach (var sectPr in sectPrs)
{
// Delete existing references to headers.
sectPr.RemoveAllChildren<HeaderReference>();
// Create the new header reference node.
sectPr.PrependChild<HeaderReference>(new HeaderReference() { Id = rId, Type = HeaderFooterValues.Default });
}
}
static void GenerateHeaderPartContent(MainDocumentPart mainPart, HeaderPart headerPart, string headerHtml, Encoding encoding)
{
Header header1 = new Header() { MCAttributes = new MarkupCompatibilityAttributes() { Ignorable = "w14 wp14" } };
header1.AddNamespaceDeclaration("wpc", "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas");
header1.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
header1.AddNamespaceDeclaration("o", "urn:schemas-microsoft-com:office:office");
header1.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
header1.AddNamespaceDeclaration("m", "http://schemas.openxmlformats.org/officeDocument/2006/math");
header1.AddNamespaceDeclaration("v", "urn:schemas-microsoft-com:vml");
header1.AddNamespaceDeclaration("wp14", "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing");
header1.AddNamespaceDeclaration("wp", "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing");
header1.AddNamespaceDeclaration("w10", "urn:schemas-microsoft-com:office:word");
header1.AddNamespaceDeclaration("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
header1.AddNamespaceDeclaration("w14", "http://schemas.microsoft.com/office/word/2010/wordml");
header1.AddNamespaceDeclaration("wpg", "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup");
header1.AddNamespaceDeclaration("wpi", "http://schemas.microsoft.com/office/word/2010/wordprocessingInk");
header1.AddNamespaceDeclaration("wne", "http://schemas.microsoft.com/office/word/2006/wordml");
header1.AddNamespaceDeclaration("wps", "http://schemas.microsoft.com/office/word/2010/wordprocessingShape");
Paragraph paragraph1 = new Paragraph();
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId() { Val = "Header" };
paragraphProperties1.Append(paragraphStyleId1);
//This adds the headerHtml as text - how to add it as html?
Run run1 = new Run();
Text text1 = new Text();
text1.Text = headerHtml;
run1.Append(text1);
paragraph1.Append(paragraphProperties1);
paragraph1.Append(run1);
header1.Append(paragraph1);
headerPart.Header = header1;
}
So the code below uses an altChunk to add html into the header. It's not perfect as I get validation errors when I use the OpenXmlValidator to validate the generated document although the doc still opens ok in word but I'm posting it here as an answer as it does do what I asked above & it might help others:
static void GenerateHeaderPartContent(MainDocumentPart mainPart, HeaderPart headerPart, string headerHtml)
{
Header header1 = new Header() { MCAttributes = new MarkupCompatibilityAttributes() { Ignorable = "w14 wp14" } };
header1.AddNamespaceDeclaration("wpc", "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas");
header1.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
header1.AddNamespaceDeclaration("o", "urn:schemas-microsoft-com:office:office");
header1.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
header1.AddNamespaceDeclaration("m", "http://schemas.openxmlformats.org/officeDocument/2006/math");
header1.AddNamespaceDeclaration("v", "urn:schemas-microsoft-com:vml");
header1.AddNamespaceDeclaration("wp14", "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing");
header1.AddNamespaceDeclaration("wp", "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing");
header1.AddNamespaceDeclaration("w10", "urn:schemas-microsoft-com:office:word");
header1.AddNamespaceDeclaration("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
header1.AddNamespaceDeclaration("w14", "http://schemas.microsoft.com/office/word/2010/wordml");
header1.AddNamespaceDeclaration("wpg", "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup");
header1.AddNamespaceDeclaration("wpi", "http://schemas.microsoft.com/office/word/2010/wordprocessingInk");
header1.AddNamespaceDeclaration("wne", "http://schemas.microsoft.com/office/word/2006/wordml");
header1.AddNamespaceDeclaration("wps", "http://schemas.microsoft.com/office/word/2010/wordprocessingShape");
Paragraph paragraph1 = new Paragraph();
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId() { Val = "Header" };
paragraphProperties1.Append(paragraphStyleId1);
paragraph1.Append(paragraphProperties1);
string altChunkId = "AltChunkId1";
AlternativeFormatImportPart chunk = headerPart.AddAlternativeFormatImportPart(
AlternativeFormatImportPartType.Html, altChunkId);
// Note that headerHtml should be full html, not just a snippet
// eg. <html><h1>My Header</h1></html> is OK
// <h1>My Header</h1> is not OK
MemoryStream ms = new MemoryStream(new UTF8Encoding(true).GetPreamble().Concat(Encoding.UTF8.GetBytes(headerHtml)).ToArray());
chunk.FeedData(ms);
AltChunk altChunk = new AltChunk();
altChunk.Id = altChunkId;
Run run1 = new Run();
RunProperties runProps = new RunProperties();
NoProof noProof1 = new NoProof();
runProps.Append(noProof1);
run1.Append(runProps);
run1.Append(altChunk);
paragraph1.Append(run1);
header1.Append(paragraph1);
headerPart.Header = header1;
}
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 })));
I'm using the openxml sdk 2.0 for generating some word files. My problem now is that for german vowel mutations (äöÄÖÜ) the font isn't applied.
Here's an example:
Tried it with some other fonts but even with them it's not working, the font is always set to "Calibri".
Anyone knows some hints to get the style appended to these special german characters?
Thanks in advice.
.
This is my Method to create the character styles:
public static void CreateAndAddCharacterStyle(StyleDefinitionsPart styleDefinitionsPart,
string styleid, string stylename, string aliases = "")
{
Styles styles = styleDefinitionsPart.Styles;
DocumentFormat.OpenXml.Wordprocessing.Style style = new DocumentFormat.OpenXml.Wordprocessing.Style()
{
Type = StyleValues.Character,
StyleId = styleid,
CustomStyle = true
};
Aliases aliases1 = new Aliases() { Val = aliases };
StyleName styleName1 = new StyleName() { Val = stylename };
LinkedStyle linkedStyle1 = new LinkedStyle() { Val = styleid + "Para" };
if (aliases != "")
style.Append(aliases1);
style.Append(styleName1);
style.Append(linkedStyle1);
StyleRunProperties styleRunProperties1 = new StyleRunProperties();
if (styleid == "textfett")
{
RunFonts font1 = new RunFonts() { Ascii = "Gotham Narrow Medium" };
styleRunProperties1.Append(font1);
}
else
{
RunFonts font1 = new RunFonts() { Ascii = "Gotham Narrow Light" };
styleRunProperties1.Append(font1);
}
style.Append(styleRunProperties1);
styles.Append(style);
}
and my code for writing text:
List<Run> runs = new List<Run>();
Run r = new Run(new Text(node.Attributes["titel"].InnerText) { Space = SpaceProcessingModeValues.Preserve });
r.RunProperties = new RunProperties();
r.RunProperties.RunStyle = new RunStyle();
r.RunProperties.RunStyle.Val = "textfett";
runs.Add(r);
r = new Run(new Break());
runs.Add(r);
foreach (System.Xml.XmlNode node2 in node.ChildNodes)
{
if (node2.Name == "info")
{
r = new Run(new Text(node2.Attributes["name"].InnerText + ":") { Space = SpaceProcessingModeValues.Preserve });
r.RunProperties = new RunProperties();
r.RunProperties.RunStyle = new RunStyle();
r.RunProperties.RunStyle.Val = "textfett";
runs.Add(r);
r = new Run(new Text(" " + node2.InnerText + " ") { Space = SpaceProcessingModeValues.Preserve });
r.RunProperties = new RunProperties();
r.RunProperties.RunStyle = new RunStyle();
r.RunProperties.RunStyle.Val = "textnormal";
runs.Add(r);
}
if (node2.Name == "ende")
{
//r = new Run(new Break());
//runs.Add(r);
r = new Run(new Text(node2.InnerText) { Space = SpaceProcessingModeValues.Preserve });
r.RunProperties = new RunProperties();
r.RunProperties.RunStyle = new RunStyle();
r.RunProperties.RunStyle.Val = "textnormal";
runs.Add(r);
}
}
Paragraph p = new Paragraph();
foreach (Run run in runs)
{
p.AppendChild<Run>(run);
}
doc.MainDocumentPart.Document.Body.AppendChild(p);
I had the same problem with French accented chars.
You need to set these properties for the font to be applied to accented characters. For instance :
RunFonts font = new RunFonts();
font.Ascii = font.HighAnsi = font.ComplexScript = #"Calibri";
So for modify your code as the following :
RunFonts font1 = new RunFonts() {
Ascii = "Gotham Narrow Medium",
HighAnsi = "Gotham Narrow Medium",
ComplexScript = "Gotham Narrow Medium" };
How can I change the font family of the document via OpenXml ?
I tried some ways but, when I open the document, it's always in Calibri
Follow my code, and what I tried.
The Header Builder I think is useless to post
private static void BuildDocument(string fileName, List<string> lista, string tipo)
{
using (var w = WordprocessingDocument.Create(fileName, WordprocessingDocumentType.Document))
{
var mp = w.AddMainDocumentPart();
var d = new DocumentFormat.OpenXml.Wordprocessing.Document();
var b = new Body();
var p = new DocumentFormat.OpenXml.Wordprocessing.Paragraph();
var r = new Run();
// Get and format the text.
for (int i = 0; i < lista.Count; i++)
{
Text t = new Text();
t.Text = lista[i];
if (t.Text == " ")
{
r.Append(new CarriageReturn());
}
else
{
r.Append(t);
r.Append(new CarriageReturn());
}
}
// What I tried
var rPr = new RunProperties(new RunFonts() { Ascii = "Arial" });
lista.Clear();
p.Append(r);
b.Append(p);
var hp = mp.AddNewPart<HeaderPart>();
string headerRelationshipID = mp.GetIdOfPart(hp);
var sectPr = new SectionProperties();
var headerReference = new HeaderReference();
headerReference.Id = headerRelationshipID;
headerReference.Type = HeaderFooterValues.Default;
sectPr.Append(headerReference);
b.Append(sectPr);
d.Append(b);
// Customize the header.
if (tipo == "alugar")
{
hp.Header = BuildHeader(hp, "Anúncio Aluguel de Imóvel");
}
else if (tipo == "vender")
{
hp.Header = BuildHeader(hp, "Anúncio Venda de Imóvel");
}
else
{
hp.Header = BuildHeader(hp, "Aluguel/Venda de Imóvel");
}
hp.Header.Save();
mp.Document = d;
mp.Document.Save();
w.Close();
}
}
In order to style your text with a specific font follow the steps listed below:
Create an instance of the RunProperties class.
Create an instance of the RunFont class. Set the Ascii property to the desired font familiy.
Specify the size of your font (half-point font size) using the FontSize class.
Prepend the RunProperties instance to your run containing the text to style.
Here is a small code example illustrating the steps described above:
private static void BuildDocument(string fileName, List<string> text)
{
using (var wordDoc = WordprocessingDocument.Create(fileName, WordprocessingDocumentType.Document))
{
var mainPart = wordDoc.AddMainDocumentPart();
mainPart.Document = new Document();
var run = new Run();
foreach (string currText in text)
{
run.AppendChild(new Text(currText));
run.AppendChild(new CarriageReturn());
}
var paragraph = new Paragraph(run);
var body = new Body(paragraph);
mainPart.Document.Append(body);
var runProp = new RunProperties();
var runFont = new RunFonts { Ascii = "Arial" };
// 48 half-point font size
var size = new FontSize { Val = new StringValue("48") };
runProp.Append(runFont);
runProp.Append(size);
run.PrependChild(runProp);
mainPart.Document.Save();
wordDoc.Close();
}
}
Hope, this helps.
If you are using Stylesheet just add an instance of FontName property at appropriate font index during Fonts initilaization.
private Stylesheet GenerateStylesheet()
{
Stylesheet styleSheet = null;
Fonts fonts = new Fonts(
new Font( // Index 0 - default
new FontSize() { Val = 8 },
new FontName() { Val = "Arial"} //i.e. or any other font name as string
);
Fills fills = new Fills( new Fill(new PatternFill() { PatternType = PatternValues.None }));
Borders borders = new Borders( new Border() );
CellFormats cellFormats = new CellFormats( new CellFormat () );
styleSheet = new Stylesheet(fonts, fills, borders, cellFormats);
return styleSheet;
}
Then use it in Workbook style part as below.
WorkbookStylesPart stylePart = workbookPart.AddNewPart<WorkbookStylesPart>();
stylePart.Stylesheet = GenerateStylesheet();
stylePart.Stylesheet.Save();