AutoFitColumns() with EPPlus slightly short - c#

I generate an Excel sheet with EPPlus and at the end, call AutoFitColumns() on my range:
sheet.DefaultColWidth = 10;
sheet.Cells[1,1,myRow,myCol].AutoFitColumns();
It works fine, except all the columns that are adjusted end up slightly short of the actual column width. Microsoft Excel adjusts the width properly when I double click on the column header, but with EPPlus, the last character will often by half-hidden.
The size difference between EPPlus and Excel's auto-adjust seems to vary based on the width of the contents, but it is not linear, so I assume EPPlus does not calculate the content width accurately based on the font.
Is there a way to fix this problem, other than arbitrarily increasing column width after auto-adjusting?

I conclude that this is a bug with EPPlus. Setting column width via the default parameter is also inaccurate (the resulting width is lower). I have not tested manually setting column width.
As a workaround, I have calculated the difference between each column's width as set with EPPlus and Excel, and have determined that for my application, it differs by up to 6-7%. So, after calling AutoFitColumns(), I do the following:
for(int i = 1; i < myRow; i++
sheet.Column(i).Width *= 1.06;

Related

How to set the max height for datagridview row while using autoresize?

I want to resize the row height of DataGridView based upon height of individual cells in a row.
For which I am using
dt_grid.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
but I also want to limit it to a maximum size beyond which it shouldn't increase the row height.
I believe it is not supported by DataGridView. You can either set AutoSizeRowsMode as you did, or have the content in one line and truncatenated at the end of column(s) width.
However, there's a workaround you can use to achive a very similar effect you're asking for. Let's say you have a Description column, which causes you a trouble. Then, if you set the column to AllCells, you can truncatenate it in the source, i.e. in SQL this way:
SELECT ID, CASE
WHEN LEN(Description) > 150 -- check length
THEN CONCAT(SUBSTRING(Description,1,150),'...') -- truncatenate, if needed
ELSE Description -- else keep it as is
END
FROM MyTable;
You won't get the long text precisely finishing to a pixel, but it will be totally fine and not intereferring with user experience.

How to set data to resize depending on columns and vise versa inside datagridview using C#?

I have one problem. When ever I try to print my datagridview it always splits in half, so what I wanna do is to find a way to set length of column name adapt to data inside the column or to set that data adapts to column name. Its not the best explanation but take a look at the pictures:
This is what I have now:
This is what I want:
So basically I want the name of the column and data inside the rows to be visible but to take as minimum space as they can, depending on what length is bigger, If column name is bigger, adapt to that, if data length is bigger, adapt to that. Any solution for my problem?
Set the following property:
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
See here the documentation for DataGridViewAutoSizeColumnsMode member AllCells:
The column widths adjust to fit the contents of all cells in the
columns, including header cells.

Get height of row where the cells have WrapText set

I am trying to compute the height of the row I'm inserting into my excel sheet. The row's cells are formatted with WrapText=true, so the height of the row is not fixed.
Accessing row.Height will return null.
I was thinking of using something similar to Graphics.MeasureString where I also specify the width constraint in order to retrieve the height.
Didn't find any relevant info online. Any help would be appreciated.
See my post here using Graphics.MeasureString. It works very well.
Autofit Row Height of Merged Cell in EPPlus

EPPlus - AutoFitColumns() method fails when a column has merged cells

I was wondering if anyone has come up with a workaround to this problem. I've noticed that the AutoFitColumns() method is failing on columns with merged cells. I've included a basic code example below:
var cellRange = worksheet.Cells[1, column, 2, column];
cells.Merge = true;
cells.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
cells.Value = "Some Text Goes Here";
worksheet.Cells.AutoFitColumns();
The resulting worksheet will have the cells in rows 1 and 2 merged (correctly) for the column in the column variable, but that particular cell is disregarded by the AutoFitColumns() method.
Any help would be appreciated.
Basically...
AutoFitColumns is documented to ignore merged cells. It isn't failing, at least in the sense of being defective.
AutoFit within Excel ignores merged cells, too.
Apparently up through Excel 2007, you cannot use the AutoFit feature for rows or columns that contain merged cells at all.
I've only tested with Excel 2013, which seems to behave differently:
Auto-fitting a row ignores all row-merged cells in that row.
Auto-fitting a column ignores all column-merged cells in that column.
In other words, you can use AutoFit in rows and columns with merged cells, it'll just ignore any cells that have been merged along the same dimension you're auto-fitting.
Desired effect of AutoFit w/r/t merged cells? (+ workarounds)
Finally, I'm not sure whether I see how it makes sense to auto-fit with respect to a merged cell. For example, suppose you have a merged cell at A1:B1 with content that fills a default two-column width.
If you auto-fit on column A, what is supposed to happen? Is column A supposed to become wide enough to fit all of A1:B1, sort of like treating the merged cell as if it's content existed only in A1, the top-left original cell? That might be reasonable, insofar as I can't immediately see whether strange behaviors might be implied in some circumstances.
If something like that is desired, I'd insert the content, auto-fit, and only then merge.
But what if you want to auto-fit on column B, in a situation like this:
Here, you might want column B to get wide enough so that all of the content in A1:B1 shows. (The content is just the text "well hello world".)
There's no one-liner for this, I'm afraid. Here's one way to do it, though:
Insert the content in the as-yet-unmerged top-left cell.
Save the current width of this cell's column.
Auto-fit the column.
Save the new column width.
Reset the column width to what you saved in step 2.
Merge the cells you want to merge.
Total up the widths of all your merged columns but the last one.
Subtract this total from the width you saved in step 4.
Set the last merged column's width to the result of step 8.
More generally, you can split up the total auto-fitted width from step 4 among the merged columns in any way you see fit.
To do all this, you'll want to use ExcelColumn.AutoFit and ExcelColumn.Width (and ExcelWorksheet.Column to grab the ExcelColumn objects).
But most simply...
If your content is static (or at least dynamic but not too variable in length), you can simply set reasonable fixed width(s) for the column(s) in question, distributed however you'd like.

Read width value in runtime

When I read the width value of my GridColumn I get the default value set in xaml (640 pixels). But the column is much wider than that in runtime because it stretches according to the width of the browser. In runtime I want to scale some of my controls to match that but when I read the value of my column it still gives me the default value 640. Until I actually resize the column with a gridsplitter the correct value get through. Anyone know how I can get the REAL width of the column during runtime without me having to resize it first?
Double a = this.Column1.Width.Value; // Gives me the default value of 640 while the column is much wider than that.
Try
Double a = this.Column1.ActualWidth.Value;

Categories