I have written a method to insert a table in a word document using Open XML. The method accepts a generic list and a few parameters to control number of columns, column headings etc.
That all works fine.
However when populating the cells in the table I want to pull out the values for each row and place them in their corresponding columns. Given the names of the properties are going to change depending on the contents of the generic list, I am not sure how to accomplish this.
Anyone that can point me in the right direction it would be appreciated.
void InsertTable<T>(List<T> tableData, int[] tableHeadingCount, string[] columnHeadings, string locationInDocument)
{
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(_newDocument, true))
{
var docPart = myDoc.MainDocumentPart;
var doc = docPart.Document;
var table = new Table();
var tableBorderTop = new TopBorder();
var tableBorderBottom = new BottomBorder();
var tableBorderLeft = new LeftBorder();
var tableBorderRight = new RightBorder();
var tableBorderHorizontal = new InsideHorizontalBorder();
var tableBorderVertical = new InsideVerticalBorder();
var tableProperties = new TableProperties();
var borders = new TableBorders();
// Set Border Styles for Table
tableBorderTop.Val = BorderValues.Single;
tableBorderTop.Size = 6;
tableBorderBottom.Val = BorderValues.Single;
tableBorderBottom.Size = 6;
tableBorderLeft.Val = BorderValues.Single;
tableBorderLeft.Size = 6;
tableBorderRight.Val = BorderValues.Single;
tableBorderRight.Size = 6;
tableBorderHorizontal.Val = BorderValues.Single;
tableBorderHorizontal.Size = 6;
tableBorderVertical.Val = BorderValues.Single;
tableBorderVertical.Size = 6;
// Assign Border Styles to Table Borders
borders.TopBorder = tableBorderTop;
borders.BottomBorder = tableBorderBottom;
borders.LeftBorder = tableBorderLeft;
borders.RightBorder = tableBorderRight;
borders.InsideHorizontalBorder = tableBorderHorizontal;
borders.InsideVerticalBorder = tableBorderVertical;
// Append Border Styles to Table Properties
tableProperties.Append(borders);
// Assign Table Properties to Table
table.Append(tableProperties);
var tableRowHeader = new TableRow();
tableRowHeader.Append(new TableRowHeight() { Val = 2000 });
for (int i = 0; i < tableHeadingCount.Length; i++)
{
var tableCellHeader = new TableCell();
//Assign Font Properties to Run
var runPropHeader = new RunProperties();
runPropHeader.Append(new Bold());
runPropHeader.Append(new Color() { Val = "000000" });
//Create New Run
var runHeader = new Run();
//Assign Font Properties to Run
runHeader.Append(runPropHeader);
var columnHeader = new Text();
//Assign the Pay Rule Name to the Run
columnHeader = new Text(columnHeadings[i]);
runHeader.Append(columnHeader);
//Create Properties for Paragraph
var justificationHeader = new Justification();
justificationHeader.Val = JustificationValues.Left;
var paraPropsHeader = new ParagraphProperties(justificationHeader);
SpacingBetweenLines spacing = new SpacingBetweenLines() { Line = "240", LineRule = LineSpacingRuleValues.Auto, Before = "0", After = "0" };
paraPropsHeader.Append(spacing);
var paragraphHeader = new Paragraph();
paragraphHeader.Append(paraPropsHeader);
paragraphHeader.Append(runHeader);
tableCellHeader.Append(paragraphHeader);
var tableCellPropertiesHeader = new TableCellProperties();
var tableCellWidthHeader = new TableCellWidth();
tableCellPropertiesHeader.Append(new Shading() { Val = ShadingPatternValues.Clear, Color = "auto", Fill = "#C0C0C0" });
var textDirectionHeader = new TextDirection();
textDirectionHeader.Val = TextDirectionValues.BottomToTopLeftToRight;
tableCellPropertiesHeader.Append(textDirectionHeader);
tableCellWidthHeader.Type = TableWidthUnitValues.Dxa;
tableCellWidthHeader.Width = "2000";
tableCellPropertiesHeader.Append(tableCellWidthHeader);
tableCellHeader.Append(tableCellPropertiesHeader);
tableRowHeader.Append(tableCellHeader);
}
tableRowHeader.AppendChild(new TableHeader());
table.Append(tableRowHeader);
//Create New Row in Table for Each Record
foreach (var record in tableData)
{
var tableRow = new TableRow();
for (int i = 0; i < tableHeadingCount.Length; i++)
{
//**** This is where I dynamically want to iterate through selected properties and output the value ****
var propertyText = "Test";
var tableCell = new TableCell();
//Assign Font Properties to Run
var runProp = new RunProperties();
runProp.Append(new Bold());
runProp.Append(new Color() { Val = "000000" });
//Create New Run
var run = new Run();
//Assign Font Properties to Run
run.Append(runProp);
//Assign the text to the Run
var text = new Text(propertyText);
run.Append(text);
//Create Properties for Paragraph
var justification = new Justification();
justification.Val = JustificationValues.Left;
var paraProps = new ParagraphProperties(justification);
var paragraph = new Paragraph();
paragraph.Append(paraProps);
paragraph.Append(run);
tableCell.Append(paragraph);
var tableCellProperties = new TableCellProperties();
var tableCellWidth = new TableCellWidth();
tableCellWidth.Type = TableWidthUnitValues.Dxa;
tableCellWidth.Width = "2000";
tableCellProperties.Append(tableCellWidth);
tableCell.Append(tableCellProperties);
tableRow.Append(tableCell);
}
table.Append(tableRow);
}
var res = from bm in docPart.Document.Body.Descendants<BookmarkStart>()
where bm.Name == locationInDocument
select bm;
var bookmark = res.SingleOrDefault();
var parent = bookmark.Parent; // bookmark's parent element
Paragraph newParagraph = new Paragraph();
parent.InsertAfterSelf(newParagraph);
if (bookmark != null)
{
newParagraph.InsertBeforeSelf(table);
}
}
}
I resolved this issue by tackling the problem another way. Essentially rather than passing a List to the Insert Table Method. I decided to Pass a Multi-Dimensional Array with all the data need for the table including the table headings. This essentially meant that the Insert Table method would be more generic and any customization i.e. Generating Data, Specifying Column Headings etc would be done in the Method calling Insert Table.
Related
I am just using OpenXML for manipulating docx document. I have templates that has notation like
{{userFirstName}}
{{tableOfUsers}}
{{signatureImage}} etc
I need to replace those text with table, image etc. How to do that in Openxml ?
I'm using C# .Net core 3.1 with OpenXML 2.5
My code was like this, but the table still not inserted into the right place:
var fileName = Path.Combine(_hostingEnv.WebRootPath, "test/test.docx");
var fileNameResult = Path.Combine(_hostingEnv.WebRootPath, "test/result.docx");
byte[] byteArray = System.IO.File.ReadAllBytes(fileName);
using (MemoryStream stream = new MemoryStream())
{
stream.Write(byteArray, 0, (int)byteArray.Length);
using (WordprocessingDocument wd = WordprocessingDocument.Open(stream, true))
{
Table table = new Table();
// Create a TableProperties object and specify its border information.
TableProperties tblProp = new TableProperties(
new TableBorders(
new TopBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
},
new BottomBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
},
new LeftBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
},
new RightBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
},
new InsideHorizontalBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
},
new InsideVerticalBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
}
)
);
// Append the TableProperties object to the empty table.
table.AppendChild<TableProperties>(tblProp);
// Create a row.
TableRow tr = new TableRow();
// Create a cell.
TableCell tc1 = new TableCell();
// Specify the width property of the table cell.
tc1.Append(new TableCellProperties(
new TableCellWidth() { Type = TableWidthUnitValues.Dxa, Width = "2400" }));
// Specify the table cell content.
tc1.Append(new Paragraph(new Run(new Text("some text"))));
// Append the table cell to the table row.
tr.Append(tc1);
// Create a second table cell by copying the OuterXml value of the first table cell.
TableCell tc2 = new TableCell(tc1.OuterXml);
// Append the table cell to the table row.
tr.Append(tc2);
// Append the table row to the table.
table.Append(tr);
var tblStr = table.ToString();
//wd.MainDocumentPart.Document.Body.Append(table);
Text tablePl = wd.MainDocumentPart.Document.Body.Descendants<Text>().Where(x => x.Text == "{{tableOfUsers}}").First();
if(tablePl != null)
{
var parent = tablePl.Parent;
tablePl.Parent.InsertAfter<Table>(table, tablePl);
tablePl.Remove();
}
string docText = null;
using (StreamReader sr = new StreamReader(wd.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
Regex regexText = new Regex("{{name}}");
docText = regexText.Replace(docText, "Claire " + DateTime.Now.ToString());
// Regex regextable = new Regex("{{tableOfUsers}}");
// docText = regextable.Replace(docText, tblStr);
using (StreamWriter sw = new StreamWriter(wd.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
}
await System.IO.File.WriteAllBytesAsync(fileNameResult, stream.ToArray());
}
_fileRepo.SetPath("test");
string fileName2 = "result.docx";
var data = await _fileRepo.DownloadFile(fileName2);
return File(data, "application/octet-stram", "filename.docx");
}
My docx file looks like
Hello {{name}}
Here is the list of users : {{tableOfUsers}}
Sincerely,
{{signatureImage}}
Use the code below to insert a table:
............
string tablePlaceholder = "{{tableOfUsers}}";
Text tablePl = wd.MainDocumentPart.Document.Body
.Descendants<Text>()
.Where(x => x.Text.Contains(tablePlaceholder))
.First();
if (tablePl != null)
{
//Insert the table after the paragraph.
var parent = tablePl.Parent.Parent.Parent;
parent.InsertAfter(table, tablePl.Parent.Parent);
tablePl.Text = tablePl.Text.Replace(tablePlaceholder, "");
wd.MainDocumentPart.Document.Save();
}
string docText = wd.MainDocumentPart.Document.Body.OuterXml;
Regex regexText = new Regex("{{name}}");
docText = regexText.Replace(docText, "Claire " + DateTime.Now.ToString());
wd.MainDocumentPart.Document.Body = new Body(docText);
wd.MainDocumentPart.Document.Save();
.............
You are looking for {{table}} in your code, but the notation in your template is {{tableOfUsers}}.
I have used these links and got a working code where I can use a template report(containing placeolders) and generate new PPTX report with data I get from database. I have 4 more placeholders where I need to populate 4 different data tables. Currently I am using that template to create new slide and replacing placeholder for text but for tables I couldn't figure out. I am able to generate the table using below code but not in placeholder's location. Table always appear in center of screen.
Links used: https://blogs.msdn.microsoft.com/brian_jones/2008/11/18/creating-a-presentation-report-based-on-data/
https://code.msdn.microsoft.com/office/How-to-add-a-table-with-03578dde
Call this from some button click event:
using (PresentationDocument presentationDocument = PresentationDocument.Open(slideName, true))
{
//Get the first slide from presentation
SlidePart intitalSlide = presentationDocument.PresentationPart.SlideParts.First();
AddNewSlide(presentationDocument, intitalSlide, 1045);
}
private void AddNewSlide(PresentationDocument presentationDocument, SlidePart _slideTemplate, int projectID)
{
PresentationPart parent = presentationDocument.PresentationPart;
System.Data.DataTable dt = GetValueForPPTReport(projectID);
var newSlidePart = parent.AddNewPart<SlidePart>("newSlide1");
//copy the contents of the template slide to the new slide and attach the appropriate layout
newSlidePart.FeedData(_slideTemplate.GetStream(FileMode.Open));
newSlidePart.AddPart(_slideTemplate.SlideLayoutPart, _slideTemplate.GetIdOfPart(_slideTemplate.SlideLayoutPart));
//Alter the placeholder text in new slide
SetPlaceholder(newSlidePart, "txtProjectIDName", dt.Rows[0]["projName"].ToString());
SetPlaceholder(newSlidePart, "txtProjType", dt.Rows[0]["proj_type"].ToString());
SetPlaceholder(newSlidePart, "txtProbSt", dt.Rows[0]["proj_problem_state"].ToString());
SetPlaceholder(newSlidePart, "txtGoal", dt.Rows[0]["proj_goal_obj"].ToString());
SetPlaceholder(newSlidePart, "txtInScope", dt.Rows[0]["proj_in_scope"].ToString());
SetPlaceholder(newSlidePart, "txtOutOfScope", dt.Rows[0]["proj_out_scope"].ToString());
SetPlaceholder(newSlidePart, "txtCustomer", dt.Rows[0]["proj_who_customer"].ToString());
SetPlaceholder(newSlidePart, "txtCTQ", dt.Rows[0]["proj_critical_to_qlty"].ToString());
SetPlaceholder(newSlidePart, "txtDefect", dt.Rows[0]["proj_what_defect"].ToString());
SetPlaceholder(newSlidePart, "txtDate", System.DateTime.Now.ToString("MM/dd/yyyy HH:mm"));
//Add Tables here
//tblXBenefit
System.Data.DataTable dtXb = GetValueForPPTReportBenefit(1045);
string placeholder = "tblXBenefit";
List<D.Text> textListExif1 = newSlidePart.Slide.Descendants<D.Text>().Where(t => t.Text.Equals(placeholder)).ToList();
if (textListExif1.Count == 1)
{
}
List<OpenXmlElement> elements = new List<OpenXmlElement>();
elements.Add(new P.NonVisualGraphicFrameProperties
(new P.NonVisualDrawingProperties() { Id = 1, Name = "xyz" }, new P.NonVisualGraphicFrameDrawingProperties(), new ApplicationNonVisualDrawingProperties()));
// Declare and instantiate the graphic Frame of the new slide
P.GraphicFrame graphicFrame = newSlidePart.Slide.CommonSlideData.ShapeTree.AppendChild(new P.GraphicFrame());
// Specify the required Frame properties of the graphicFrame
ApplicationNonVisualDrawingPropertiesExtension applicationNonVisualDrawingPropertiesExtension = new ApplicationNonVisualDrawingPropertiesExtension() { Uri = "{D42A27DB-BD31-4B8C-83A1-F6EECF244321}" };
P14.ModificationId modificationId1 = new P14.ModificationId() { Val = 3229994563U };
modificationId1.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");
applicationNonVisualDrawingPropertiesExtension.Append(modificationId1);
graphicFrame.NonVisualGraphicFrameProperties = new P.NonVisualGraphicFrameProperties
(new D.NonVisualDrawingProperties() { Id = 5, Name = "table 1" },
new D.NonVisualGraphicFrameDrawingProperties(new D.GraphicFrameLocks() { NoGrouping = true }),
new ApplicationNonVisualDrawingProperties(new ApplicationNonVisualDrawingPropertiesExtensionList(applicationNonVisualDrawingPropertiesExtension)));
graphicFrame.Transform = new Transform(new D.Offset() { X = 1650609L, Y = 4343400L }, new D.Extents() { Cx = 6096000L, Cy = 741680L });
// Specify the Griaphic of the graphic Frame
graphicFrame.Graphic = new D.Graphic(new D.GraphicData(GenerateTable()) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/table" });
//save the changes to the slide
newSlidePart.Slide.Save();
//need to assign an id to the new slide and add it to the slideIdList
//first figure out the largest existing id
DocumentFormat.OpenXml.Presentation.SlideIdList slideIdList = parent.Presentation.SlideIdList;
uint maxSlideId = 1;
foreach (DocumentFormat.OpenXml.Presentation.SlideId slideId in slideIdList.ChildElements)
{
if (slideId.Id > maxSlideId) maxSlideId = slideId.Id;
}
//assign an id and add the new slide at the end of the list
DocumentFormat.OpenXml.Presentation.SlideId newSlideId = new DocumentFormat.OpenXml.Presentation.SlideId { Id = ++maxSlideId, RelationshipId = parent.GetIdOfPart(newSlidePart) };
slideIdList.Append(newSlideId);
//Delete first template slide
SlideId tempSlideId = slideIdList.ChildElements[0] as SlideId;
slideIdList.RemoveChild(tempSlideId);
}
private void SetPlaceholder(SlidePart slidePart, string placeholder, string value)
{
List<D.Text> textListExif1 = slidePart.Slide.Descendants<D.Text>().Where(t => t.Text.Equals(placeholder)).ToList();
foreach (D.Text text in textListExif1)
{
text.Text = value;
}
}
#region tables
/// <summary>
/// Generate Table as below order:
/// a:tbl(Table) ->a:tr(TableRow)->a:tc(TableCell)
/// We can return TableCell object with CreateTextCell method
/// and Append the TableCell object to TableRow
/// </summary>
/// <returns>Table Object</returns>
private static D.Table GenerateTable()
{
string[,] tableSources = new string[,] { { "name", "age" }, { "Tom", "25" } };
// Declare and instantiate table
D.Table table = new D.Table();
// Specify the required table properties for the 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);
// Declare and instantiate tablegrid and colums
D.TableGrid tableGrid1 = new D.TableGrid();
D.GridColumn gridColumn1 = new D.GridColumn() { Width = 3048000L };
D.GridColumn gridColumn2 = new D.GridColumn() { Width = 3048000L };
tableGrid1.Append(gridColumn1);
tableGrid1.Append(gridColumn2);
table.Append(tableProperties);
table.Append(tableGrid1);
for (int row = 0; row < tableSources.GetLength(0); row++)
{
// Instantiate the table row
D.TableRow tableRow = new D.TableRow() { Height = 370840L };
for (int column = 0; column < tableSources.GetLength(1); column++)
{
tableRow.Append(CreateTextCell(tableSources.GetValue(row, column).ToString()));
}
table.Append(tableRow);
}
return table;
}
/// <summary>
/// Create table cell with the below order:
/// a:tc(TableCell)->a:txbody(TextBody)->a:p(Paragraph)->a:r(Run)->a:t(Text)
/// </summary>
/// <param name="text">Inserted Text in Cell</param>
/// <returns>Return TableCell object</returns>
private static D.TableCell CreateTextCell(string text)
{
if (string.IsNullOrEmpty(text))
{
text = string.Empty;
}
// Declare and instantiate the table cell
// Create table cell with the below order:
// a:tc(TableCell)->a:txbody(TextBody)->a:p(Paragraph)->a:r(Run)->a:t(Text)
D.TableCell tableCell = new D.TableCell();
// Declare and instantiate the text body
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;
}
#endregion
Okay, I can place the table at any location I want to by changing values in this.. for X and Y.. not sure what Cx and Cy values does. So that works
graphicFrame.Transform = new Transform(new D.Offset() { X = 1650609L, Y = 4343400L }, new D.Extents() { Cx = 6096000L, Cy = 741680L });
But now the new issue is I am unable to reduce the font and table row height.
I tried changing this values but nothing works. Will post here when I find out.
D.TableRow tableRow = new D.TableRow() { Height = 370840L };
I had to to make this change in createTextCell method: added FontSize=800
D.RunProperties runProperties = new D.RunProperties() { Language = "en-US", Dirty = false, FontSize=800 };
Below is the code I'm working with to pass multiple line items to create sales order through GP Web service. I can pass single Line Item without any problem , but when I pass multiple Items it is only taking the last one. The array has around 5 Item ID and I'm passing fixed Quantity as 15, Need to make both dynamic. But for the testing purpose I'm trying like this. I know the problem with the creation/initialization of some web service objects. As novice to the entire set of things I couldn't find the exact problem.
C# Code
CompanyKey companyKey;
Context context;
SalesOrder salesOrder;
SalesDocumentTypeKey salesOrderType;
CustomerKey customerKey;
BatchKey batchKey;
// SalesOrderLine salesOrderLine;
ItemKey orderedItem;
Quantity orderedAmount;
Policy salesOrderCreatePolicy;
DynamicsGPClient wsDynamicsGP = new DynamicsGPClient();
wsDynamicsGP.ClientCredentials.Windows.ClientCredential.UserName = "Admin";
wsDynamicsGP.ClientCredentials.Windows.ClientCredential.Password = "pass";
wsDynamicsGP.ClientCredentials.Windows.ClientCredential.Domain = "Gp";
System.ServiceModel.WSHttpBinding binding;
binding = new System.ServiceModel.WSHttpBinding(System.ServiceModel.SecurityMode.None);
context = new Context();
companyKey = new CompanyKey();
companyKey.Id = (1);
context.OrganizationKey = (OrganizationKey)companyKey;
salesOrder = new SalesOrder();
salesOrderType = new SalesDocumentTypeKey();
salesOrderType.Type = SalesDocumentType.Order;
salesOrder.DocumentTypeKey = salesOrderType;
customerKey = new CustomerKey();
customerKey.Id = "121001";
salesOrder.CustomerKey = customerKey;
batchKey = new BatchKey();
batchKey.Id = "RMS";
salesOrder.BatchKey = batchKey;
// SalesOrderLine[] orders = new SalesOrderLine[6];
SalesOrderLine[] lines = { };
for (int i = 1; i < 5; i++)
{
SalesOrderLine salesOrderLine = new SalesOrderLine();
orderedItem = new ItemKey();
orderedItem.Id = Arr[i].ToString();
salesOrderLine.ItemKey = orderedItem;
orderedAmount = new Quantity();
orderedAmount.Value = 15;
salesOrderLine.Quantity = orderedAmount;
lines = new SalesOrderLine[] { salesOrderLine };
MessageBox.Show(lines.Count().ToString());
}
salesOrder.Lines = lines;
//salesOrder.Lines = orders;
salesOrderCreatePolicy = wsDynamicsGP.GetPolicyByOperation("CreateSalesOrder", context);
wsDynamicsGP.CreateSalesOrder(salesOrder, context, salesOrderCreatePolicy);
if (wsDynamicsGP.State != CommunicationState.Faulted)
{
wsDynamicsGP.Close();
}
MessageBox.Show("Success");
lines = new SalesOrderLine[] { salesOrderLine }; will recreate the lines array object each time meaning you loose any previously added objects. Effectively only the final object in the loop is actually added.
Try using a List<T> like so:
SalesOrderLine[] lines = { }; Becomes List<SalesOrderLine> lines = new List<SalesOrderLine>();
lines = new SalesOrderLine[] { salesOrderLine }; Becomes: lines.Add(salesOrderLine);
If its important you end up with an array as the input:
salesOrder.Lines = lines; Becomes: salesOrder.Lines = lines.ToArray();
Trying to style a table using a predefined style but nothing is working. I've tried with a a newly created document and one created from a saved template. Using the SDK Productivity tool I can see the style is there in the template but it's not being applied. I've tried appended the style or setting it directly and neither seem to work.
public static void CreateWordprocessingDocument(string fileName) {
string[,] data = {
{"Texas", "TX"},
{"California", "CA"},
{"New York", "NY"},
{"Massachusetts", "MA"}
};
using (var wordDocument = WordprocessingDocument.Open(fileName, true)) {
// We need to change the file type from template to document.
wordDocument.ChangeDocumentType(WordprocessingDocumentType.Document);
var body = wordDocument.GetDocument().Body;
Table table = new Table();
TableProperties props = new TableProperties();
TableStyle tableStyle = new TableStyle { Val = "Light Shading Accent 1" };
props.TableStyle = tableStyle;
//props.Append(tableStyle);
table.AppendChild(props);
for (var i = 0; i <= data.GetUpperBound(0); i++) {
var tr = new TableRow();
for (var j = 0; j <= data.GetUpperBound(1); j++) {
var tc = new TableCell();
tc.Append(new Paragraph(new Run(new Text(data[i, j]))));
tc.Append(new TableCellProperties(new TableCellWidth { Type = TableWidthUnitValues.Auto }));
tr.Append(tc);
}
table.Append(tr);
}
body.Append(table);
wordDocument.GetDocument().Save();
}
}
Finally figured it out. I was using the style name and not the style id. So the line where the style is declared should look like:
TableStyle tableStyle = new TableStyle { Val = "LightShading-Accent1" };
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();