Working with Word for WPF > Advanced Level Working > Inserting Table |
Table is used in word documents to present data in a well formatted form with the help of rows and columns.
Note that two classes named WordUtils and DataAccess are used in the code given below. These classes are available in the product sample located at the following location on your system:
Documents\ComponentOne Samples\WPF\WordCreator
You can use these classes in your application from the mentioned location.
Word for WPF enables you to add structure to a word document using the following code:
' get the data Dim ds = DataAccess.GetDataSet() ' calculate page rect (discounting margins) Dim rcPage As Rect = WordUtils.PageRectangle(word) Dim rc As Rect = rcPage ' add title Dim titleFont As New Font("Tahoma", 24, RtfFontStyle.Bold) rc = WordUtils.RenderParagraph(word, word.Info.Title, titleFont, rcPage, rc, False) ' render some tables RenderTable(word, rc, rcPage, ds.Tables("Customers"), New String() {"CompanyName", "ContactName", "Country", "Address", "Phone"})
// get the data var ds = DataAccess.GetDataSet(); // calculate page rect (discounting margins) Rect rcPage = WordUtils.PageRectangle(word); Rect rc = rcPage; // add title Font titleFont = new Font("Tahoma", 24, RtfFontStyle.Bold); rc = WordUtils.RenderParagraph(word, word.Info.Title, titleFont, rcPage, rc, false); // render some tables RenderTable(word, rc, rcPage, ds.Tables["Customers"], new string[] { "CompanyName", "ContactName", "Country", "Address", "Phone" });
The following code can be used to select the font for the content of the table and build the table:
' select fonts Dim hdrFont As New Font("Tahoma", 10, RtfFontStyle.Bold) Dim txtFont As New Font("Tahoma", 8) ' build table 'word.AddBookmark(table.TableName, 0, rc.Y); rc = WordUtils.RenderParagraph(word, "NorthWind " + table.TableName, hdrFont, rcPage, rc, False) ' build table rc = RenderTableHeader(word, hdrFont, rc, fields) For Each dr As DataRow In table.Rows rc = RenderTableRow(word, txtFont, hdrFont, rcPage, rc, fields, _ dr) Next ' done Return rc
// select fonts Font hdrFont = new Font("Tahoma", 10, RtfFontStyle.Bold); Font txtFont = new Font("Tahoma", 8); // build table //word.AddBookmark(table.TableName, 0, rc.Y); rc = WordUtils.RenderParagraph(word, "NorthWind " + table.TableName, hdrFont, rcPage, rc, false); // build table rc = RenderTableHeader(word, hdrFont, rc, fields); foreach (DataRow dr in table.Rows) { rc = RenderTableRow(word, txtFont, hdrFont, rcPage, rc, fields, dr); } // done return rc;
After building the table, you need to cell height and width of the table headers and rows, and then render them using the following code:
Private Shared Function RenderTableHeader(word As C1WordDocument, font As Font, rc As Rect, fields As String()) As Rect ' calculate cell width (same for all columns) Dim rcCell As Rect = rc rcCell.Width = rc.Width / fields.Length rcCell.Height = 0 ' calculate cell height (max of all columns) For Each field As String In fields Dim height = word.MeasureString(field, font, rcCell.Width).Height rcCell.Height = Math.Max(rcCell.Height, height) Next rcCell.Height += 6 ' add 6 point margin ' render header cells Dim fmt = New StringFormat() fmt.LineAlignment = VerticalAlignment.Center For Each field As String In fields word.FillRectangle(Colors.Black, rcCell) word.DrawString(field, font, Colors.White, rcCell, fmt) rcCell = WordUtils.Offset(rcCell, rcCell.Width, 0) Next ' update rectangle and return it Return WordUtils.Offset(rc, 0, rcCell.Height) End Function Private Shared Function RenderTableRow(word As C1WordDocument, font As Font, hdrFont As Font, rcPage As Rect, rc As Rect, fields As String(), _ dr As DataRow) As Rect ' calculate cell width (same for all columns) Dim rcCell As Rect = rc rcCell.Width = rc.Width / fields.Length rcCell.Height = 0 ' calculate cell height (max of all columns) rcCell = WordUtils.Inflate(rcCell, -4, 0) For Each field As String In fields Dim text As String = dr(field).ToString() Dim height = word.MeasureString(text, font, rcCell.Width).Height rcCell.Height = Math.Max(rcCell.Height, height) Next rcCell = WordUtils.Inflate(rcCell, 4, 0) ' add 4 point margin rcCell.Height += 2 ' break page if we have to If rcCell.Bottom > rcPage.Bottom Then word.PageBreak() rc = RenderTableHeader(word, hdrFont, rcPage, fields) rcCell.Y = rc.Y End If ' center vertically just to show how Dim fmt As New StringFormat() fmt.LineAlignment = VerticalAlignment.Center ' render data cells For Each field As String In fields ' get content Dim text As String = dr(field).ToString() ' set horizontal alignment Dim d As Double fmt.Alignment = If((Double.TryParse(text, NumberStyles.Any, CultureInfo.CurrentCulture, d)), HorizontalAlignment.Right, HorizontalAlignment.Left) ' render cell word.DrawRectangle(Colors.LightGray, rcCell) rcCell = WordUtils.Inflate(rcCell, -4, 0) word.DrawString(text, font, Colors.Black, rcCell, fmt) rcCell = WordUtils.Inflate(rcCell, 4, 0) rcCell = WordUtils.Offset(rcCell, rcCell.Width, 0) Next ' update rectangle and return it Return WordUtils.Offset(rc, 0, rcCell.Height) End Function
static Rect RenderTableHeader(C1WordDocument word, Font font, Rect rc, string[] fields) { // calculate cell width (same for all columns) Rect rcCell = rc; rcCell.Width = rc.Width / fields.Length; rcCell.Height = 0; // calculate cell height (max of all columns) foreach (string field in fields) { var height = word.MeasureString(field, font, rcCell.Width).Height; rcCell.Height = Math.Max(rcCell.Height, height); } rcCell.Height += 6; // add 6 point margin // render header cells var fmt = new StringFormat(); fmt.LineAlignment = VerticalAlignment.Center; foreach (string field in fields) { word.FillRectangle(Colors.Black, rcCell); word.DrawString(field, font, Colors.White, rcCell, fmt); rcCell = WordUtils.Offset(rcCell, rcCell.Width, 0); } // update rectangle and return it return WordUtils.Offset(rc, 0, rcCell.Height); } static Rect RenderTableRow(C1WordDocument word, Font font, Font hdrFont, Rect rcPage, Rect rc, string[] fields, DataRow dr) { // calculate cell width (same for all columns) Rect rcCell = rc; rcCell.Width = rc.Width / fields.Length; rcCell.Height = 0; // calculate cell height (max of all columns) rcCell = WordUtils.Inflate(rcCell, -4, 0); foreach (string field in fields) { string text = dr[field].ToString(); var height = word.MeasureString(text, font, rcCell.Width).Height; rcCell.Height = Math.Max(rcCell.Height, height); } rcCell = WordUtils.Inflate(rcCell, 4, 0); // add 4 point margin rcCell.Height += 2; // break page if we have to if (rcCell.Bottom > rcPage.Bottom) { word.PageBreak(); rc = RenderTableHeader(word, hdrFont, rcPage, fields); rcCell.Y = rc.Y; } // center vertically just to show how StringFormat fmt = new StringFormat(); fmt.LineAlignment = VerticalAlignment.Center; // render data cells foreach (string field in fields) { // get content string text = dr[field].ToString(); // set horizontal alignment double d; fmt.Alignment = (double.TryParse(text, NumberStyles.Any, CultureInfo.CurrentCulture, out d)) ? HorizontalAlignment.Right : HorizontalAlignment.Left; // render cell word.DrawRectangle(Colors.LightGray, rcCell); rcCell = WordUtils.Inflate(rcCell, -4, 0); word.DrawString(text, font, Colors.Black, rcCell, fmt); rcCell = WordUtils.Inflate(rcCell, 4, 0); rcCell = WordUtils.Offset(rcCell, rcCell.Width, 0); } // update rectangle and return it return WordUtils.Offset(rc, 0, rcCell.Height); }
The above code creates a table from the information taken from the Nwind database with proper indentation and alignment in a word document.
The output of the above code will look similar to the image given below: