I have created a web part with a button that once clicked generates a word document containing the list item values of particular list. I want to be able to change the margins for the document (top, bottom margins), but I am unsure as to how to proceed. Can anyone shed some light on how to achieve this?
So far the code I have is a as follows:
void GenerateBadges_Click(object sender, EventArgs e)
{
string Title = null;
string jobTitle = null;
WordprocessingDocument document = WordprocessingDocument.Create(#"C:\sample-
badges.docx", WordprocessingDocumentType.Document);
MainDocumentPart mainDocumenPart = document.AddMainDocumentPart();
mainDocumenPart.Document = new Document();
Body documentBody = new Body();
mainDocumenPart.Document.Append(documentBody);
SPWeb web = SPContext.Current.Web;
SPList list = web.Lists["SampleList"];
SPListItemCollection collListItems = list.Items;
//getting the internal name for the Title and JobTitle fields of the list
string jobTitleField = collListItems.Fields["JobTitle"].InternalName;
string titleField = collListItems.Fields["Title"].InternalName;
//adding a table to the document
//creating a properties object to add border to the table (wNo border will be required)
Table table = new Table();
TableProperties tblProps = new TableProperties();
TableBorders tblBorders = new TableBorders();
tblBorders.TopBorder = new TopBorder();
tblBorders.TopBorder.Val = new EnumValue<BorderValues>(BorderValues.Single);
tblBorders.BottomBorder = new BottomBorder();
tblBorders.BottomBorder.Val = new EnumValue<BorderValues>(BorderValues.Single);
tblBorders.RightBorder = new RightBorder();
tblBorders.RightBorder.Val = new EnumValue<BorderValues>(BorderValues.Single);
tblBorders.LeftBorder = new LeftBorder();
tblBorders.LeftBorder.Val = new EnumValue<BorderValues>(BorderValues.Single);
tblBorders.InsideHorizontalBorder = new InsideHorizontalBorder();
tblBorders.InsideHorizontalBorder.Val = BorderValues.Single;
tblBorders.InsideVerticalBorder = new InsideVerticalBorder();
tblBorders.InsideVerticalBorder.Val = BorderValues.Single;
tblProps.Append(tblBorders);
table.Append(tblProps);
int x = collListItems.Count;
//creatin the table rows/cells
for (int i = 0; (i * 2) < x; i++)
{
TableRow row = new TableRow();
// get the indexes for left and right cells as pairs (i.e. 0 + 1, 2 + 3, 4 + 5 etc)
int leftIndexer = i * 2;
int rightIndexer = (i * 2) + 1;
if (leftIndexer == x)
{
break;
}
//getting the values from the list for the left table cell
Title = collListItems[leftIndexer][titleField].ToString();
jobTitle = collListItems[leftIndexer][jobTitleField].ToString();
// attach content to row as cell
row.Append(new TableCell(new Paragraph(new Run(new Text(Title)))));
// get right cell contents, if there is a value for this index
if (rightIndexer < x)
{
//getting the values from the list for the right cell
Title = collListItems[rightIndexer][titleField].ToString();
jobTitle = collListItems[rightIndexer][jobTitleField].ToString();
// attach to table row as right cell
row.Append(new TableCell(new Paragraph(new Run(new Text(Title)))));
}
// attach row to table
table.Append(row);
}
//add the table to the document - table needs to be wired into the for each loop above
documentBody.Append(table);
//Saving/Disposing of the created word Document
document.MainDocumentPart.Document.Save();
document.Dispose();
The key part to be able to change the page margins is to firs t create a "PageMagrin" object and then a "SectionProperties" object. Lastly we need to append the page margin object in to the section properties object. Lastly append the section properties object to a body object.
Additionally it is very useful to create a word document, then save it as .xml. Then open it in notepad, notepad++ or even visual studio 2010. This displays all of th elements that make up the word document with this you are then able to determine which parts or elements of the document you need to modify.
Below is the actual code used:
//setting the page margins go here
PageMargin pageMargins = new PageMargin();
pageMargins.Left = 600;
pageMargins.Right = 600;
pageMargins.Bottom = 500;
pageMargins.Top = 500;
//pageMargins.Header = 1500; //not needed for now
//pageMargins.Footer = 1500; //not needed for now
//Important needed to access properties (sections) to set values for all elements.
SectionProperties sectionProps = new SectionProperties();
sectionProps.Append(pageMargins);
documentBody.Append(sectionProps);
Hope this helps others, I had a tough time figuring this out
It is a bit hard to tell what exactly you want to do - the following links contain details and source code for page margins, headers, footers etc.:
http://msdn.microsoft.com/en-us/library/ee355228%28office.12%29.aspx
http://sharepointweblog.blogspot.com/2009/08/wordprocessingml-insert-page-number-in.html
IF the above is not what you asked please provide more details on what you achieve...
Related
Background
I am currently using Kendo-UI as my front-end library and I was using the saveAs method to generate reports based on the DOM that was being rendered, but ran into some serious performance issues (especially in IE). So I decided that I would handle the PDF generation on the server-side using Migradoc.
What I'm Trying To Do
Right now I have a listview (see demo) that essentially represents an image gallery. What I'm having a difficult time with is trying to figure out how to have the image/text go from left-to-right.
What I've Done
Here is my current code:
// Title
var title = section.AddParagraph("Photos");
title.Format.SpaceAfter = Unit.FromPoint(9);
title.Format.SpaceBefore = Unit.FromPoint(9);
title.Format.Font.Bold = true;
title.Format.Font.Color = new Color(33, 37, 41);
title.Format.Font.Name = "Segoe UI";
title.Format.Font.Size = Unit.FromPoint(11);
title.Format.Borders.Bottom = new Border()
{
Color = new Color(222, 226, 230),
Style = BorderStyle.Single
};
// listview
foreach (var photo in _photos)
{
var photoDocument = _documentService.Get(photo.DocumentId);
var textFrame = section.AddTextFrame();
textFrame.AddImage("base64:" + Convert.ToBase64String(photoDocument.ThumbnailBinaryData));
paragraph = textFrame.AddParagraph(photo.Filename);
paragraph.Format.Alignment = ParagraphAlignment.Center;
if (photo.CreatedOn != null)
{
var dateValue = (DateTimeOffset) photo.CreatedOn;
paragraph.AddLineBreak();
paragraph.AddText(dateValue.ToString("yyyy-MM-dd"));
}
}
The issue with this approach is that Migradoc is placing the photos vertically and the text basically on top of each other (see image below).
Question
How can I make it so that the images go from left-to-right until there is no longer any room in which case it starts to wrap on the next line?
Update
I'm able to get the photos to line up left-to-right, but without any text using:
var paragraph = section.AddParagraph();
foreach (var photo in _photos)
{
var photoDocument = _documentService.Get(photo.DocumentId);
paragraph.AddImage("base64:" + Convert.ToBase64String(photoDocument.ThumbnailBinaryData));
}
However, I still haven't figured out how to set the text below the image and have the images appear on the same line.
Update #2
After spending a long time thinking about this, ultimately what I did was create a table, calculate the maximum number of columns that can fit on the page, and then dynamically add columns as I go. I'm not sure if this is the right solution or not, but it works for me:
if (_photos.Any())
{
var columnWidth = Unit.FromInch(1.75);
var maximumColumns = (int)Math.Floor((11.5 - pageSetup.LeftMargin.Inch - pageSetup.RightMargin.Inch) / columnWidth.Inch); // 11.5 (page width) - 0.25 (left margin) - 0.25 (right margin) divided by columnWidth
var table = section.AddTable();
table.Style = "Table";
if (maximumColumns > photos.Count())
{
columnWidth = Unit.FromInch(Math.Floor((11.5 - pageSetup.LeftMargin.Inch - pageSetup.RightMargin.Inch) / photos.Count()));
maximumColumns = photos.Count();
}
Enumerable.Range(1, maximumColumns).ForEach(i => table.AddColumn(columnWidth));
var row = table.AddRow();
var columnIndex = 0;
foreach (var photo in _photos)
{
if (columnIndex == maximumColumns - 1)
{
row = table.AddRow();
columnIndex = 0;
}
else
{
columnIndex++;
}
var photoDocument = _documentService.Get(photo.DocumentId);
var photoParagraph = row.Cells[columnIndex].AddParagraph();
photoParagraph.AddImage("base64:" + Convert.ToBase64String(photoDocument.ThumbnailBinaryData));
photoParagraph.AddLineBreak();
photoParagraph.AddText(photo.Filename);
photoParagraph.Format.Alignment = ParagraphAlignment.Center;
if (photo.CreatedOn != null)
{
var dateValue = (DateTimeOffset)photo.CreatedOn;
photoParagraph.AddLineBreak();
photoParagraph.AddText(dateValue.ToString("yyyy-MM-dd"));
}
}
}
I have a Windows form on which I put a flow layout panel. I also have a class that reads a local database and returns the corresponding values. Depending on the user input via a button(s) the panel gets filled with other buttons. The amount of these buttons depends on the values in the local database. The buttons are displayed correctly and with the correct information, but the order in which they are displayed is alphabetical even though the data-table, from the database class, is ordered in the correct way (via the numerical value of the "ID" column from the database).
I have also added a data-grid view to check and there the items are displayed in the correct way. I have tried to add a for-each loop but that just seems to randomize the order of the buttons.
Does anybody know how I can get the buttons to be displayed in the correct way, so that the button with the lowest "ID" value gets displayed first.
Here is the code for displaying the buttons:
//set the datagridview with the correct values/names. Order works perfectly
dataGridView_AttackName.DataSource = db.attackIDName(attackCategory, taughtOn);
DataTable dt = db.attackIDName(attackCategory, taughtOn);
//sort datable again because doesnt work from db class
dt.DefaultView.Sort = "ID";
dt.DefaultView.ToTable();
int horizontal = 0;
int vertical = 0;
Button[] buttonArray = new Button[dt.Rows.Count];
for (int items = 0; items < buttonArray.Length; items++)
{
buttonArray[items] = new Button();
buttonArray[items].Size = new Size(150, 50);
buttonArray[items].Location = new Point(horizontal, vertical);
buttonArray[items].Name = string.Format("Button_{0}", dt.Rows[items]["ID"].ToString());
buttonArray[items].Text = dt.Rows[items]["Name"].ToString();
buttonArray[items].Click += btn_msg;
if ((items + 1) < buttonArray.Length)
{
vertical += 50;
}
flowLayoutPanel_AttackName.Controls.Add(buttonArray[items]);
}
//get the correct ID value from the button name and try to order it that way
foreach (Button b in flowLayoutPanel_AttackName.Controls)
{
string name = b.Name;
string subname = name.Substring(name.IndexOf("_") + 1);
int i = Convert.ToInt32(subname);
flowLayoutPanel_AttackName.Controls.SetChildIndex(b, i);
}
I have searched around on this site but couldn't find anything that worked.
You've correctly sorted the DefaultView by the ID, but then haven't used the results!
You need to replace, for example, dt.Rows[items]["Name"]with dt.DefaultView[items].Row["Name"]. You then don't need the statement dt.DefaultView.ToTable().
Full code is below:
dt.DefaultView.Sort = "ID";
int horizontal = 0;
int vertical = 0;
Button[] buttonArray = new Button[dt.Rows.Count];
for (int items = 0; items < buttonArray.Length; items++)
{
buttonArray[items] = new Button();
buttonArray[items].Size = new Size(150, 50);
buttonArray[items].Location = new Point(horizontal, vertical);
buttonArray[items].Name = string.Format("Button_{0}", dt.DefaultView[items].Row["ID"].ToString());
buttonArray[items].Text = dt.DefaultView[items].Row["Name"].ToString();
buttonArray[items].Click += btn_msg;
if ((items + 1) < buttonArray.Length)
{
vertical += 50;
}
flowLayoutPanel_AttackName.Controls.Add(buttonArray[items]);
}
I am attempting to dynamically create a bar chart in C# based on the following datatable (which will change, hence the need for dynamic creation).
Here's the datatables that I'm reading from currently:
(people of the future: these images contained work stuff and I don't want to get fired, so I've removed them =O )
The top table is where I add the series (s24, s26, s27) data. The second table is where I slim it down and add the "Total" series.
So here are the columns that I'm trying to chart from:
Config - this is where I want to get my individual series: ie: s24, s26, s27, etc.
HRC_Count - this is the actual value I'm trying to graph
HRC_Description and HRC - these are labels for the Y axis
Total_HRC_Count - this is for my "Total" series (black bar on chart)
//get distinct Configs (to be added as Series in chart)
//this creates a dataview to parse for the series in the chart
DataView view = new DataView(dt);
DataTable distinctValues = new DataTable();
distinctValues = view.ToTable(true, "Config");
DataView dv = new DataView(distinctValues);
dv.Sort = "Config ASC";
DataTable dt_temp = new DataTable();
dt_temp = dv.ToTable();
distinctValues = dt_temp;
GraphDataNew(distinctValues);
then I call GraphDataNew and parse the dataview for the series:
private void GraphDataNew(DataTable dt_distinct)
{
chart_new.Series.Clear();
foreach (DataRow row in dt_distinct.Rows)
{
string s = row["Config"].ToString();
chart_new.Series.Add(s);
chart_new.Series[s].ChartType = SeriesChartType.Bar;
chart_new.Series[s].IsValueShownAsLabel = true;
chart_new.Series[s].Sort(PointSortOrder.Ascending, "X");
chart_new.Series[s].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
chart_new.Series[s].YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Double;
}
So now I have my Series (Configs) set up, now I add actual data:
DataView dv = new DataView(dt);
dv.Sort = "HRC_Description ASC, Config ASC"; // sort by description first, then config second
string HRC_Description = "";
string Config = "";
double HRC_Count = 0;
DataTable dt_temp = new DataTable();
dt_temp = dv.ToTable();
// add actual data
//loop through dt_temp and add datapoints and custom labels to chart
for (int x = 0; x < dt_temp.Rows.Count; x++)
{
HRC_Description = (dt_temp.Rows[x]["HRC_Description"].ToString().Trim());
Config = dt_temp.Rows[x]["Config"].ToString().Trim();
HRC_Count = Double.Parse(dt_temp.Rows[x]["HRC_Count"].ToString().Trim());
chart_new.Series[Config].Points.AddXY(HRC_Description, HRC_Count);
int y = chart_new.Series[Config].Points.Count;
chart_new.Series[Config].Points[y - 1].AxisLabel = HRC_Description;
}
Then I add the "Total" series bar:
if (1==1) // fake condition for this question
{
chart_new.Series.Add("Total");
chart_new.Series["Total"].ChartType = SeriesChartType.Bar;
chart_new.Series["Total"].Color = Color.Black;
chart_new.Series["Total"].IsValueShownAsLabel = true;
chart_new.Series["Total"].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
chart_new.Series["Total"].YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Double;
DataView view1 = new DataView(dt_temp);
DataTable distinctValues1 = view1.ToTable(true, "HRC_Description", "Total_HRC_Count");
dt_temp = distinctValues1;
double Total_HRC_Count = 0;
for (int x = 0; x < dt_temp.Rows.Count; x++)
{
HRC_Description = (dt_temp.Rows[x]["HRC_Description"].ToString().Trim());
Total_HRC_Count = Double.Parse(dt_temp.Rows[x]["Total_HRC_Count"].ToString().Trim());
chart_new.Series["Total"].Points.AddXY(HRC_Description, Total_HRC_Count);
}
}
This is what the chart looks like:
[![Example Chart][2]][2]
However, as you can see in the attached chart, my data is all off. There are 10 of the HRC_Description, but only 9 show up, and one is repeated. On top of that, it seems that whenever I have more than 2 series, the data gets mixed up. Does anyone have any tips on what I can do to fix this? It's driving me crazy! Thanks!!
I can't fully analyze your data but I can give you a hint, which should help in solving your problem:
I see that you add the datapoints with strings as the x-values.
This is ok (sort of; well, no, not really) but the x-values of the datapoints that actually are addded really are not strings but double and they all contain 0.
The strings only go into the labels, not the x-values! (So the values are lost)
But to be grouped together the points in your various series need some criterion and as the x-values won't work (even though they do look as if they did) the position of the points is used instead. Which dervies from the positions, i.e. from the order and number of points you add.
So only those bars will be grouped together which are added to the same position and since there are no real positions the order in which they are added is all that counts.
So you need to make sure to always use the same order and to never leave a spot empty when you add your points. If a values is missing in a series you need to add an empty dummy points (set its DataPoint.IsEmpty=true)
Easy to get wrong..!
You can check if this is the cause by checking the number of datapoints in each series. If they are not all the same this is the problem..
Here is an example: Note how the second, yellow and the 3rd, red series both are missing values but how only the yellow one is off; note the last point especially!
private void button17_Click(object sender, EventArgs e)
{
chart3.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
chart3.Series.Clear();
Series s1 = chart3.Series.Add("S1");
Series s2 = chart3.Series.Add("S2");
Series s3 = chart3.Series.Add("S3");
Random R = new Random(42);
s1.ChartType = SeriesChartType.Bar;
s2.ChartType = SeriesChartType.Bar;
s3.ChartType = SeriesChartType.Bar;
for (int i = 0; i < 10; i++)
{
// this series is complete..:
s1.Points.AddXY(i + "", R.Next(100));
int r = R.Next(5);
// this series misses some points..:
if (r==0) s2.Points.AddXY(i + "", R.Next(100));
// this series inserts empty points and so misses no points.:
if (r == 0) s3.Points.AddXY(i + "", R.Next(100));
else { int p = s3.Points.AddXY(i + "", R.Next(100)); s3.Points[p].IsEmpty = true; }
}
// now add a value at "10" for all series..;
s1.Points.AddXY("10", 100);
s2.Points.AddXY("10", 100);
s3.Points.AddXY("10", 100);
}
I am dynamically creating several HtmlTableRows and adding cells to them, like so:
HtmlTable dynamicTable = new HtmlTable();
. . .
// Create row 6
var row6 = new HtmlTableRow();
var cellLitCtrl_6 = new HtmlTableCell();
var cellTxtbx_6 = new HtmlTableCell();
row6.Cells.Add(cellLitCtrl_6);
row6.Cells.Add(cellTxtbx_6);
var mailStopStr = new Label
{
CssClass = "dplatypus-webform-field-label",
Text = "Mail Stop:"
};
cellLitCtrl_6.Controls.Add(mailStopStr);
boxMailStop = new TextBox
{
CssClass = "dplatypus-webform-field-input"
};
cellTxtbx_6.Controls.Add(boxMailStop);
dynamicTable.Rows.Add(row6);
// Create row 7
var row7 = new HtmlTableRow();
var cellCkbx_7 = new HtmlTableCell();
var cellLitCtrl_7 = new HtmlTableCell();
var cellTxtbx_7 = new HtmlTableCell();
row7.Cells.Add(cellCkbx_7);
row7.Cells.Add(cellLitCtrl_7);
row7.Cells.Add(cellTxtbx_7);
CheckBox ckbxEmployeeQ = new CheckBox
{
CssClass = "dplatypus-webform-field-input",
ID = "ckbxEmp",
};
ckbxEmployeeQ.Text = "Employee?";
cellCkbx_7.Controls.Add(ckbxEmployeeQ);
var SSNOrITINStr = new Label
{
CssClass = "dplatypus-webform-field-label",
Text = "ITIN:",
ID = "lblSSNOrITIN"
};
cellLitCtrl_7.Controls.Add(SSNOrITINStr);
boxSSNOrITIN = new TextBox
{
CssClass = "dplatypus-webform-field-input",
ID = "txtbxSSNOrITIN",
Width = 80,
MaxLength = 12
};
cellTxtbx_7.Controls.Add(boxSSNOrITIN);
dynamicTable.Rows.Add(row7);
This code produces what you see here:
But I want the textbox (the yellow one) to be snug up against its label ("SSN" in the screamshot, but it can also be "ITIN" depending on the state of the "Employee?" checkbox).
So what we have here is an HtmlTableRow with two elements (the "Mail Stop:" label and its "associated" Textbox) and another HtmlTableRow with three elements (the checkbox, label, and textbox).
The second HtmlTableRow is obviously taking its layout cue from the one above (aligning cells to to the same X coordinate value), but why? And how can I circumvent that? I want the second row to look like this:
|_| Employee? SSN |___________|
...not like this:
|_| Employee? SSN |___________|
How can I "snug up" the label ("SSN") and the following Textbox?
I tried putting the label and textbox in the same HtmlTableCell, but it blew up at runtime when I tried to add two Controls to a single HtmlTableCell.
For the most part, it's nice that the supposedly "independent" HtmlTableRows horizontally line up with each other, but I don't know why/how they do that, nor how to bypass that usually-desirable feature.
HtmlTableCell seems to have a ColSpan property. You may try setting that on the other rows to format it the way you would like:
https://msdn.microsoft.com/en-us/library/system.web.ui.htmlcontrols.htmltablecell.colspan(v=vs.110).aspx
This is not really an answer to my specific question (I didn't find a way to do that), but this is the solution I ended up with: adding these controls to the page not as part of a table, but "standalone":
// These elements were not aligning right as row 7 of the section 1 table, so I am just adding them one by one
CheckBox ckbxEmployeeQ = new CheckBox
{
CssClass = "dplatypus-webform-field-input",
ID = "ckbxEmp",
};
ckbxEmployeeQ.Text = "Employee?";
this.Controls.Add(ckbxEmployeeQ);
AddVerticalSpace();
var SSNOrITINStr = new Label
{
CssClass = "dplatypus-webform-field-label",
Text = "ITIN:",
ID = "lblSSNOrITIN"
};
SSNOrITINStr.Style.Add("padding", "2px");
this.Controls.Add(SSNOrITINStr);
boxSSNOrITIN = new TextBox
{
CssClass = "dplatypus-webform-field-input",
ID = "txtbxSSNOrITIN",
Width = 80,
MaxLength = 12
};
this.Controls.Add(boxSSNOrITIN);
AddVerticalSpace();
I have a large form I'm transforming into a PDF. The first 1/6th of it looks like this:
http://i.imgur.com/y4pO8Th.png
The number of entered fields however, varies from 1 to 20 per section, and I need to be able to make this document break pages intelligently. My plan was to originally draw the tables piece by piece and just manage the Y-coordinate by grabbing the number of rows in all previous tables. This worked, but falls apart when I get to a page break, and I start needing some semi-complicated logic to make it work, and it's the kind of logic that gets messier and messier with each additional table added.
My second plan was to reproduce the table structure of the HTML document in the PDF, which I manage to do successfully...
private void DrawPDF()
{
Document tDoc = new Document();
MigraDoc.DocumentObjectModel.Style style = tDoc.Styles["Normal"];
style.Font.Name = tPdfFont;
style.Font.Size = 10;
Section tSec = tDoc.AddSection();
MigraDoc.DocumentObjectModel.Tables.Table masterTable = new MigraDoc.DocumentObjectModel.Tables.Table();
masterTable = tSec.AddTable();
masterTable.Borders.Visible = false;
Column leftColumn = masterTable.AddColumn("365pt");
Column spacer = masterTable.AddColumn("10pt");
Column rightColumn = masterTable.AddColumn("365pt");
Row tFS = masterTable.AddRow();
Cell tCell = tFS.Cells[0];
//
// Farm Assets Column
//
{
MigraDoc.DocumentObjectModel.Tables.Table tAssetsTable = new MigraDoc.DocumentObjectModel.Tables.Table();
tAssetsTable.Borders.Visible = false;
Column tColumn = tAssetsTable.AddColumn("365pt");
tCell.Elements.Add(tAssetsTable);
//
// Current Farm Assets
//
for (int i = 0; i < 10; i++) // Drawn 10 times to force it to draw over the 1st page.
{
Section thisSection = tDoc.AddSection();
Row tAssetsRow = tAssetsTable.AddRow();
Cell tAssetsCell = tAssetsRow.Cells[0];
MigraDoc.DocumentObjectModel.Tables.Table table = new MigraDoc.DocumentObjectModel.Tables.Table();
table = thisSection.AddTable();
table.Borders.Width = 0.2;
table.Rows.LeftIndent = 0;
Column columnData = table.AddColumn("295pt");
columnData.Borders.Left.Visible = false;
Column columnValue = table.AddColumn("70pt");
Row rowA = table.AddRow();
rowA.Shading.Color = Color.FromRgbColor((byte)255, Color.Parse("0xa2a2d2"));
rowA.Cells[0].AddParagraph("CURRENT FARM ASSETS");
rowA.Cells[1].AddParagraph("$ Value");
rowA.Cells[1].Format.Alignment = ParagraphAlignment.Right;
Row row1 = table.AddRow();
row1.Borders.Bottom.Visible = false;
row1.Cells[0].AddParagraph("Cash: Savings: ($" + MP.FormFinancialStatement.CurrentStaticAssets.Savings + ") Checking: ($" + MP.FormFinancialStatement.CurrentStaticAssets.Checking + ")");
row1.Cells[1].AddParagraph(MP.FormFinancialStatement.CurrentStaticAssets.CashTotal);
row1.Cells[1].Format.Alignment = ParagraphAlignment.Right;
Row row2 = table.AddRow();
row2.Borders.Bottom.Visible = false;
row2.Cells[0].AddParagraph("Invest: Time Cret $" + MP.FormFinancialStatement.CurrentStaticAssets.TimeCret + " Other: $" + MP.FormFinancialStatement.CurrentStaticAssets.OtherInvestments + "");
row2.Cells[1].AddParagraph(MP.FormFinancialStatement.CurrentStaticAssets.InvestTotal);
row2.Cells[1].Format.Alignment = ParagraphAlignment.Right;
Row row3 = table.AddRow();
row3.Borders.Bottom.Visible = false;
row3.Cells[0].AddParagraph("Replacement Account");
row3.Cells[1].AddParagraph(MP.FormFinancialStatement.CurrentStaticAssets.ReplacementAccount);
row3.Cells[1].Format.Alignment = ParagraphAlignment.Right;
Row row4 = table.AddRow();
row4.Cells[0].AddParagraph("Accouts and Notes Recievable");
row4.Cells[1].AddParagraph(MP.FormFinancialStatement.CurrentStaticAssets.AccountsNotesReceivable);
row4.Cells[1].Format.Alignment = ParagraphAlignment.Right;
MigraDoc.DocumentObjectModel.Tables.Table clone = (MigraDoc.DocumentObjectModel.Tables.Table)table.Clone();
tAssetsCell.Elements.Add(clone);
}
}
MigraDoc.Rendering.DocumentRenderer docRenderer = new DocumentRenderer(tDoc);
docRenderer.PrepareDocument();
docRenderer.RenderObject(gfx, 30, 85, "740pt", masterTable);
}
But alas, this does not actually break pages correctly. I tried sectioning off each individual table, hoping that'd do page break magic, but it does not.
How can I structure this to allow for good page breaks?
You can use the KeepWith property of the table rows to keep blocks together on one page. Only use this for chunks that will surely fit on one page.
See also:
https://stackoverflow.com/a/6831048/1015447
https://stackoverflow.com/a/1327228/1015447