I would like to enlarge a cell to a certain height by using paragraphs. i have tried working with height, but it always gives me the same height back, no matter how many paragraphs i insert. is there a way to determine the exact size?
var cell = table.Cell(1, 1);
var limitHeight = 6f;
while (cell.Height <= limitHeight)
{
cell.Range.Text += "\r";
}
Related
I'm using EPPlus and C# and trying to autosize/autofit the height of a row to accommodate the height needed to show all of the contents of a merged cell with text wrapping. However no matter what I try the text always truncates. Since I'm repeating this process with various text sizes on various worksheets, I don't want to hard code the row height (except to enforce a minimum height for the row). If possible I'd like to do this within EPPlus/C#.
With the cells A2:E2 merged and WrapText = true:
Cell with Text Truncated
Here's what it should look like with desired Cell Height
Here's my relevant and short C# code
Int32 intToCol;
intToCol = 5;
eppWorksheet.Cells[2, 1, 2, intToCol].Merge = true;
eppWorksheet.Cells[2, 1].Style.WrapText = true;
//Check if at the minimum height. If not, resize the row
if (eppWorksheet.Row(2).Height < 35.25)
{
eppWorksheet.Row(2).Height = 35.25;
}
I've looked at Autofit rows in EPPlus and it didn't seem to directly answer my question unless I'm reading it wrong.
Here is the solution in a reusable method. Pass in the text value, font used for the cell, summed width of the columns merged, and receive back the row height. Set the row height with the result.
Use of Method
eppWorksheet.Row(2).Height = MeasureTextHeight(cell.Value, cell.Style.Font, [enter the SUM of column widths A-E]);
Reuseable Method
public double MeasureTextHeight(string text, ExcelFont font, double width)
{
if (text.IsNullOrEmpty()) return 0.0;
var bitmap = _bitmap ?? (_bitmap = new Bitmap(1, 1));
var graphics = _graphics ?? (_graphics = Graphics.FromImage(bitmap));
var pixelWidth = Convert.ToInt32(width * 7); //7 pixels per excel column width
var fontSize = font.Size * 1.01f;
var drawingFont = new Font(font.Name, fontSize);
var size = graphics.MeasureString(text, drawingFont, pixelWidth, new StringFormat { FormatFlags = StringFormatFlags.MeasureTrailingSpaces });
//72 DPI and 96 points per inch. Excel height in points with max of 409 per Excel requirements.
return Math.Min(Convert.ToDouble(size.Height) * 72 / 96, 409);
}
I have used a workaround for this and I a had print area A:Q.
I copied merged cells value to column z.
set width of column z to merge cells width.
Then set auto row height true in format.
Hide the z column.
Set print area A:Q
Cons:
There are duplicate data. But we are okay since report is printing and not print z column.
Pros:
Row height works correctly not like calculation method.
Had to tweak the code a little bit by removing the multiplication factor at the return line. May be because i am using this code to get the width of the column.
ws1.Column(colIndx).Width * 7
The multiplication factor is the number of columns been merged.
How to set up paragraph width in MigraDoc? All what I imagine is create table and set the column width and then paragraph populate all width. But I need something like next:
var paragraph016 = section.AddParagraph();
paragraph016.Format.Borders.Bottom.Visible = true;
paragraph016.Format.WidowControl = true;
//here must be define paragraph width
Or maybe anybody know how can I draw line on the page, where I can setup width and position of my line?
I use paragraph width as a part of my 'add a horizontal rule' helper method. Using left and right indent works great:
public static void AddHorizontalRule(Section section, double percentWidth, Color? color = null)
{
double percent = (percentWidth < 0.0 || percentWidth > 1.0) ? 1.0 : percentWidth;
Color hrColor = color ?? new Color(96, 96, 96); // Lt Grey default
Unit contentWidth = section.PageSetup.PageWidth - section.PageSetup.LeftMargin - section.PageSetup.RightMargin;
Unit indentSize = (contentWidth - (percent * contentWidth)) / 2.0;
Paragraph paragraph = section.AddParagraph();
paragraph.Format.LeftIndent = indentSize;
paragraph.Format.RightIndent = indentSize;
paragraph.Format.Borders.Top.Visible = true;
paragraph.Format.Borders.Left.Visible = false;
paragraph.Format.Borders.Right.Visible = false;
paragraph.Format.Borders.Bottom.Visible = false;
paragraph.Format.Borders.Top.Color = hrColor;
}
Note that because a section's PageSetup values are 0 and therefore use the default document settings, that to use the client area width as shown above, you need to explicitly set these values in the section.PageSetup before calling this method. I do it this way so that I don't have to pass around the document nor depend on document.LastSection being the section that I am working on. I just pass in a Section object and have at it.
Enjoy!
Brian
You can set the width indirectly by specifying left and right indent. I don't know if this leads to the desired line, but it's worth a try.
A table will work.
An image would also work - best with a vector image (could be PDF), but a raster image with a single pixel in the desired color should also work.
I am new to iTextSharp, and want to convert my DataGridView to a PdfPtable.
When i write the table to PDF, it shows up nicely, except when the amount of columns is relatively large. Then it accomodates by making the column width smaller.
Instead, I would like to start on a new page, with more of the table shown, with headers.
Below is my code for the table:
PdfPTable table = new PdfPTable( view.Columns.Count );
float[] widths = new float[view.Columns.Count];
for ( int i = 0; i < view.Columns.Count; i++ ) {
widths[i] = view.Columns[i].Width;
}
table.SetWidths( widths );
table.HorizontalAlignment = 1; //Center
PdfPCell cell = null;
//Headers
foreach ( DataGridViewColumn c in view.Columns ) {
cell = new PdfPCell( new Phrase( new Chunk( c.HeaderText, _standardFont ) ) );
cell.HorizontalAlignment = PdfPCell.ALIGN_CENTER;
cell.VerticalAlignment = PdfPCell.ALIGN_CENTER;
table.AddCell( cell );
}
//Rest of table
for ( int i = 1; i < view.Rows.Count; i++ ) {
for ( int j = 0; j < view.Columns.Count; j++ ) {
bool hasValue = view.Rows[i].Cells[j].Value == null ? false : true;
if ( hasValue ) {
cell = new PdfPCell( new Phrase( view.Rows[i].Cells[j].Value.ToString(), _standardFont ) );
} else {
cell = new PdfPCell( new Phrase( "", _standardFont ) );
}
cell.HorizontalAlignment = PdfPCell.ALIGN_CENTER;
cell.VerticalAlignment = PdfPCell.ALIGN_CENTER;
table.AddCell( cell );
}
}
One solution would be to somehow know how many columns could be printed fullsize on a page, and then add a new page, with more of the grid displayed there, but i am unsure how to detect a new page. The problem here is that there seems to be no way of changing the number of columns of a PdfPtable, so I have to be able to calculate the effect in width when adding columns beforehand.
EDIT: I want to split the pages vertically
The problem you're facing, is the fact that PDF isn't HTML. A page in a PDF has a fixed size. You don't have a scrollbar, and the content doesn't change when you resize the viewer window.
I'm going to answer using JAVA examples from Chapter 4 of my book. If you need the C# version of these examples, you'll need this URL: http://tinyurl.com/itextsharpIIA2C04
First this: whether or not a table looks nice is something a machine can't judge. It's something only a human can do.
Seems like you want to control the width of the columns. The example ColumnWidths gives you some examples on how to do that. In your case, you should use a solution that involves using absolute values for the width of the table. You'll recognize these solutions because they all have this line in common:
table.setLockedWidth(true);
Using an absolute width is mandatory if you want to calculate the height of each row or of the complete table. A Frequently Asked Question is "I've created a table and when I ask for its total width, it returns zero." It can be answered by a counter-question: "How can iText calculate the height of a table, if you didn't define the width first?" This is a rhetorical question: it's impossible to calculate the height before the width has been defined. That's shown in the TableHeight example.
Once you've defined the widths of the table (and its columns), you can calculate the height, and you're ready to position the table at absolute positions. The Zhang example shows how it's done. In this example, a table with 4 columns is created. The first two colums are drawn using this commando:
table.writeSelectedRows(0, 2, 0, -1, 236, 806, canvas);
Where the first 0 defines the first column that needs to be drawn, and the 2 defines the first column that isn't drawn. The remaining columns are drawn on the next page, using this commando:
table.writeSelectedRows(2, -1, 0, -1, 36, 806, canvas);
Where 2 defines the first column that needs to be drawn, and -1 indicates that all remaining columns should be drawn.
In this case, 0 and -1 are used for the rows. If your table contains more rows than fit on one page, you'll have to do the math to make sure you don't have any rows that "fall off the page."
Note that the 36 and 806 represent an X and a Y coordinate. As your taking control over the layout, you're responsible to calculate those coordinates.
I'm setting the following properties for a DataGridView in my C# project ...
sampleDataGridView.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
sampleDataGridView.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
But I notice that the heading's (i.e. text in header cell is offset slightly to the left, for some reason .. The data rows alignment in perfectly in center though ...
What can be causing this ?
It is because there is a sorting glyph (little arrow) for which the DataGridView reserves some space to show the sort order. If you want to disable the sorting glyph, set the SortMode on your column to NotSortable, and your text should then be centered.
Old topic,
i had this problem, and i found out that the problem was that i had the grid datasource-linked to my stuff, and when the columns where created they put the ALLOW SORT ON by default, which created the arrow down button to sort, and the text gets pushed to the left.
small fix to this is:
private void MyDataGridView_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
e.Column.SortMode = DataGridViewColumnSortMode.NotSortable;
}
I had the same problem as you and it seems it's a framework issue: MS Connect
Figure out the glyph width without refection and supress when out of line:
In the following code I turn on and off sorting while autoadjusting column width to the column header text width. The difference in width between sorting on/off will reveal the width used by the column sort glyph.
As column looses the glyph when column width is set less than autoadjusted width I supress it by inserting symetric left and right column padings.
I also use a dictionary to store ColumnWidth events by datagridview instance to turn width events on and off while seting the width.
I call this crazy code both to autoadjust initial column widths and to manage the column header padings when user drags column widths.
void AdaptColumnHeaderText(DataGridViewColumn column, bool autoSize=false)
{
//Supress column width events
if (dataGridViewColumnWidthEventHandlers.ContainsKey(column.DataGridView))
{
dataGridView1.ColumnWidthChanged -= dataGridViewColumnWidthEventHandlers[column.DataGridView];
}
//Save initial column with as preferred
var w_preferred = column.Width;
if (
column.SortMode.Equals(DataGridViewColumnSortMode.Automatic) &&
column.HeaderCell.Style.Alignment.Equals(DataGridViewContentAlignment.MiddleCenter))
{
//remove all header padding
column.HeaderCell.Style.Padding = new Padding(0, 0, 0, 0);
//Fit column width to header text with AND sort glyph
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
//save column width sort enabled
var w_sort = column.Width;
//Fit column width to header text with NO sort glyph
column.SortMode = DataGridViewColumnSortMode.NotSortable;
//save column width when sort disable
var w_nosort = column.Width;
//Calculate width consumed by sort glyph
var w_glyph = w_sort - w_nosort;
//Nominal column width if glyph width applied left and right of header text
var w_nominal = w_glyph + w_nosort + w_glyph;
//Disable column width autosize
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
//Enable column autosorting
column.SortMode = DataGridViewColumnSortMode.Automatic;
//If autosize option - ignore preferred width and set to nominal
if (autoSize)
{
w_preferred = w_nominal;
}
//Pad depending on final column width
if (w_preferred >= w_nominal)
{
//Preferred width greater than nominal - pad left of text to balance width used by glyph
column.HeaderCell.Style.Padding = new Padding(w_glyph, 0, 0, 0);
}
else
{
//Two symetric glyphs will not fit - pad left and right to supress glyph
w_glyph = (w_preferred - w_nosort) / 2;
column.HeaderCell.Style.Padding = new Padding(w_glyph, 0, w_glyph, 0);
}
column.Width = w_preferred;
Console.WriteLine("name:{0}, glyph:{1}, w_preferred:{2}", column.Name, w_glyph, w_preferred);
}
//re-enable column width events
if (dataGridViewColumnWidthEventHandlers.ContainsKey(column.DataGridView))
{
dataGridView1.ColumnWidthChanged += dataGridViewColumnWidthEventHandlers[column.DataGridView];
}
}
You can add two spaces at the beginning of the column name to compensate the space reseved for the glyph.
This question already has answers here:
How to set line spacing Graphics.DrawString
(2 answers)
Closed 5 years ago.
I know how to create an image from text in C# and how to specify a certain font size for the text. But, I want to be able to have a few lines of text where the text is one font size - but the line spacing is a smaller font size - and be able to create an image from this in C#.
For example, I have three lines of text. The font size for each text line is 24 (not sure what the unit is - pixels? point?). But, I want the line spacing between each text line to only be 8.
Does anyone know how this can be accomplished?
Try to draw each line separately and define its vertical position as vertical position of the previous line plus your desired spacing.
var left = 0;
var top = 0;
var myFontSize = 12;
var mySpacing = 8;
var myFont = new Font("MyFontFamily", myFontSize);
var myBrush = Brushes.Black;
var myLines = new List<string>{
// your strings here
};
for(var i = 0; i < myLines.Count; i++)
{
var lineText = myLines[i];
// this line is needed to get line size in pixels, regardless in which units font size is specified
// also different fonts can have different image sizes for the same font size
var lineImageSize = graphics.MeasureString(lineText, myFont);
graphics.DrawString(myLines[i], myFont, myBrush, left, top + (i * (lineImageSize.Height + mySpacing)));
}