I am struggling to implement what seems should be something straight forward, but having not much luck. I need a MigraDoc table to render with just the Table border, excluding all cells in between:
I have followed the remarks on this post:
How do you add a border around a table in MigraDoc?
Useful information but I havent been able to implement a full fix from it?
I have the following code run just before the table is added to the section:
table.Borders.Visible = true;
for (int i = 0; i < table.Rows.Count - 2; i++)
{
table.Rows[i].Borders.Bottom.Visible = false;
}
Which at first seemed like it did the job... until I come across a table that follows onto the next page... The bottom row border is obviously only rendered for the very bottom row and does not account for PageBreaks mid-table.
Surely there must be a better way of doing this?
EDIT: I appreciate this is somewhat of an old question, but just incase anyone ends up here looking for an answer...
Try using the SetEdge option. There's two ways you could do it, depending on whether you know how many table rows or columns you're going to have (static content), or you don't know yet (dynamic content).
Option 1: Static table content
Set your table up first, so all the columns, cells and rows exist, then add an edge border to your table with
table.SetEdge(a, b, x, y, Edge.Box, BorderStyle.Single, 1, Colors.Black);
The first four numbers a, b, x, y indicate which of the table cells you want to add a borders to, the first two numbers are the top left column then row (in your case to border the whole table, this should be 0, 0) and the second two numbers are the bottom right corner column then row (as per your example this is 3, 4, assuming the heading is a heading row).
After Edge.Box, the options are border style, border width, border color.
You can then add any extra individual borders per cell or row after as normal, so to add a border at the bottom of your header row as per your example...
headerRow.Borders.Bottom.Width = 0.2;
headerRow.Borders.Bottom.Color = Colors.Black;
Option 2: Dynamic table content
If you don't know how many rows or columns are in your table becuase the content is dynamic, the first four numbers in SetEdge could be set with this.table.Columns.Countand this.table.Rows.Count - for example :
table.SetEdge(0, 0, this.table.Columns.Count, this.table.Rows.Count, Edge.Box, BorderStyle.Single, 1, Colors.Black);
References
For more info, see this post:
https://forum.pdfsharp.net/viewtopic.php?f=2&t=3598
And it's also here in the MigraDoc Example (search for SetEdge):
http://pdfsharp.net/wiki/HelloMigraDoc-sample.ashx
Related
I need to divide two cells in adjacent columns into X equal cells horizontally. I am given a DocumentBuilder, pointing to the cell. I decided that I can insert a separate table into the cell:
var table = builder.StartTable();
builder.InsertCell();
table.AutoFit(AutoFitBehavior.AutoFitToWindow);
builder.Write("1");
builder.EndRow();
builder.InsertCell();
builder.Write("2");
builder.EndRow();
builder.EndTable();
But still, there is a margin on the sides of the inner table:
(ignore the left cell being splitted by horizontal thick line)
I googled that table.AutoFit(AutoFitBehavior.AutoFitToWindow); should solve the problem, but it doesn't. What am I supposed to do, to get desired output:
I managed to split the cell vertically, by setting all other cells in a row cell.CellFormat.VerticalMerge = CellMerge.First, then adding X - 1 rows, in which cells are cell.CellFormat.VerticalMerge = CellMerge.Previous, except cells in columns to de divided.
I have a DataGridView control, and the number of columns changes depending on the input from the user every 10 minutes.
What needs to be achieved is:
The DataGridView needs to show all columns without a horizontal scrollbar unless it affects the readability of any cell contents. If it starts hiding a cell content, a horizontal scrollbar needs to appear.
Regardless of how many columns are currently shown, and regardless of whether the horizontal scrollbar is shown or not, the right-hand side of the DataGridView's data must be filled so there is no unused space.
Regardless of the length of the cell contents, all of the column widths need to be the same. (A cell can have an integer from 10 up to 9999)
All of these 3 requirements need to be satisfied at the same time, but if I try to meet one requirement, the other(s) falls apart. I know for sure that there are always at least 16 columns no matter what. It is really up to the user if there will be more columns or not.
Can someone tell me what is wrong with the following?
int countVisible = 0; //Count the number of columns displayed
foreach(DataGridViewColumn col in myDGV.Columns)
if(col.Visible) countVisible++;
//By default, use Fill mode
DataGridViewAutoSizeColumnMode mode = DataGridViewAutoSizeColumnMode.Fill;
//I am trying to show up to 20 columns without a scrollbar
//A horizontal scrollbar required for more than 20 columns
//If there are more than 20 columns, use DisplayedCells mode
if(countVisible > 20)
mode = DataGridViewAutoSizeColumnMode.DisplayedCells;
//Apply the mode to all columns
for(int i = 0; i < myDGV.Columns.Count; i++)
myDGV.Columns[i].AutoSizeMode = mode;
This code works if the number of columns is less than a certain value, but in the case of greater than the certain value, it shrinks the width of columns that only have 2-digit numbers in all rows, and it violates the requirement #3. By shrinking some column widths, it creates extra space on the right-hand side, and it violates the requirement #2.
I am so lost and stuck. Can someone please help? Any advice will be greatly appreciated.
The requirements appear to be somewhat obscure to me. One issue would be requirement 3…
”3. Regardless of the length of the cell contents, all of the column widths need to be the same. (A cell can have an integer from 10 up to 9999)” …
If ALL columns have to be the same width and at least ONE (1) cell has a value of “9999” then ALL the columns will be this width regardless of how many digits it has.
It does appear a requirement is to have all the data display in a cell, in addition… have all the columns the same width. This will require going through each cell and find the cell with the largest width to display all its data and make ALL columns this width to keep with the previous requirement.
The point being, that requiring all the columns to be the same size AND make sure ALL the contents of every cell is displayed leaves little to question… Each column will have to be the width of the largest value. Any other situation will break one of the requirements.
Assuming the above is correct, the other requirement
”2. Regardless of how many columns are currently shown, and regardless of whether the horizontal scrollbar is shown or not, the right-hand side of the DataGridView's data must be filled so there is no unused space.” …
I am confident YOU will have to control this. Unfortunately, the grids column “Fill” property will gladly cram a hundred columns into a small space. This suggest that you will have to get the grids displayed width, count how many columns there are, find the width for the columns and check to see if it fits in the grids display.
This implies a MINIMUM value for a columns width. If each columns width is set to a minimum value AND the total width from all columns is greater than the grids width, then obviously you are going to need a horizontal scroll bar.
Given this, to find the total width of all the columns is easy enough. If this value is greater than the grids width, then the horizontal scroll bar will appear automatically, nothing else needs to be done unless you want to avoid the possible splitting of a column which would most likely involve resizing the grid. If the total width of the columns is less than the grids width… then simply set the columns to fill. Below is an example.
A global variable minWidth is used to ensure all columns are at least this value. This is a value you could get some other way; in this case, its purpose is to set a columns minimum width.
First, a check is made to see if the width is less than the minimum and if so set it to the minimum. Next, set each columns width to the given value. Finally check to see if the total width of all columns is greater than the grids width. If the columns will not fit in the grids width then simply set the grid to DisplayedCells and the horizontal scroll bar will pop up. .If the columns do fit, then simply set the grids AutoColumnSizeMode to Fill. Hope this helps.
int minWidth = 40;
private int YourMethodToGetColumnWidth() {
return myDGV.Width / myDGV.Columns.Count;
}
private void SetColumnWidths() {
int columnWidth = YourMethodToGetColumnWidth();
if (columnWidth < minWidth)
columnWidth = minWidth;
foreach (DataGridViewColumn col in myDGV.Columns)
col.Width = columnWidth;
int allColumnsWidth = columnWidth * myDGV.Columns.Count;
if (allColumnsWidth > myDGV.Width) {
myDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;
}
else {
myDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
}
}
I read your interesting question yesterday. Thinking about it, in my opinion the best solution is to get rid of AutoSizeMode at all and create a variable ColMinWidth for a minimum width of a column. Then get DataGridView.Width and divide it by the number of required columns (with a little tweak, perhaps 2px less). If the calculated width of the column is greater then ColMinWidth, then this will be a width of the column, otherwise use ColMinWidth.
Finally set that width to all columns.
I think that this is minimal solution and unlike AutoSize with hidden catches, reliable.
I have created one report which hides some of the columns of table at end when some criteria don't match. For example, there are total 7 columns and I am hiding 2 columns when criteria don't match. This leads to so much empty space at right side as table don't centre automatically.
I have tried VerticalAlign = Middle but it is not working.
Finally after all efforts I didn't find exact solution but found one alternative.
I have applied Anchoring = Left, Right on table and that helps me to make my table looks better.
What it actually does is, it keeps width as it was specified and based on no. of columns, columns width either shrink or grows.
Using Microsoft Interop for word, after adding a table to the document, how can the column width be set for all columns so that it fits the largest item there? For example, if the column header is only two letters, and each cell underneath is only one digit, the column should only be about a centimeter wide.
If you only have one table in your document, you would use something like this (where oDoc is your active document.)
oDoc.Tables(0).AllowAutoFit = True;
oDoc.Tables(0).AutoFitBehavior(Word.WdAutoFitBehavior.wdAutoFitContent);
If you have more than one table, you'd want to choose the index of the one you wish to update or loop through them.
In the Word object model AutoFit is what the feature is called that allows (or doesn't allow) table columns to resize to fit the content, the width of the window/page or prevents them from resizing automatically.
To force the table columns to resize to fit their content:
tbl.AutoFitBehavior(Word.WdAutoFitBehavior.wdAutoFitContent);
To change the width of a single column to fit to the content:
tbl.Columns[index].AutoFit();
This can also be done for all columns:
tlb.Columns.AutoFit();
I'm adding an image to a Word document using OpenXml.
I am able to tell the size of the image being added, and I can resize it if I want to. But what I really want is to only resize it if it's wider than the current column. (In my case, there is only one column but perhaps that could change.)
Is there any way to know how wide the current column is and, therefore, be able to ensure that the image fits within the column? As it is, large images are extending off the page.
I've updated my answer, because it was an answer for a case when table columns are involved, but the word column in the question mean a column or text rather than a column in a table.
In the document, You should be able to get the following values:
// ...
var sectionProperties = body.GetFirstChild<SectionProperties>();
// pageSize contains Width and Height properties
var pageSize = sectionProperties.GetFirstChild<PageSize>();
// this contains information about surrounding margins
var pageMargin = sectionProperties.GetFirstChild<PageMargin>();
// this contains information about spacing between neighbouring columns of text
// this can be useful if You use page layout with multiple text columns
var columns = sectionProperties.GetFirstChild<Columns>();
var spaceBetweenColumns = columns.Space.Value;
var columnsCount = columns.ColumnCount.Value;
I haven't tested this, but I suppose You may be able to calculate the actual width of a text column using those values.