Setting Columns Width in Excel with C# VSTO - c#

I'm using C# for a VSTO Excel Add In.
Currently I'm setting the columns to be auto fitted with:
newWorkSheet.Columns.AutoFit();
How can I set the Column width to have some additional padding?
In psuedocode it would be:
Column.Width = columnCurrentWidth + 10
For a certain column, make it a bit wider than the auto fit width
I've figure out how to get the width of a column but not set it
int width = ((Excel.Range)newWorkSheet.Cells[rowCount, 2]).Width;

You have to set ColumnWidth and RowHeight of Range.
This should work:
int width = ((Excel.Range)newWorkSheet.Cells[rowCount, 2]).Width;
((Excel.Range)newWorkSheet.Cells[rowCount, 2]).ColumnWidth = width + 10;

Related

C# MS Word Interoperability - how to stretch-fill last column in table

I am using Microsoft.Office.Interop.Word in a WinForms application written in c# to create a word document programmatically. I need to create a table with the first two columns having a predefined fixed width and the third (last) column stretched to fill the remaining width of the useable page (if I do not specify any widths, by default, the table would stretch itself to fill the useable width of the page and all 3 columns would be resized equally, which is not what I need).
I can preset the size of the first two columns like this:
myTable.Columns[1].Width = 130;
myTable.Columns[2].Width = 70;
That part is straight forward and works ok. But I couldn't work out how to adjust the third column to stretch-fill the rest of the page width. Here's my last attempt which resulted in the third column extending way beyond the edge of the page:
myTable.Columns[3].Width = wordApp.UsableWidth - myTable.Columns[1].Width - myTable.Columns[2].Width;
I also tried not specifying a value for the width of the 3rd column hoping that it would take up the rest of the width of the table by default - but instead, the 3rd column was adjusted to some seemingly arbitrary value (with the content of cells on this column wrapped to fit) and the overall width of the table shrank to fit all 3 columns which was less than the useable width of the page.
I tried playing with different values for the following table attributes without success:
myTable.AllowAutoFit = true;
myTable.PreferredWidth = wordApp.UsableWidth;
If anyone could help, that would be greatly appreciated. Thank you.
I included the relevant block of code if this helps in anyway:
Microsoft.Office.Interop.Word.Table myTable = wordDoc.Tables.Add(paraTitle.Range, 2, 3, ref missing, ref missing);
myTable.Borders.Enable = 1;
myTable.AllowAutoFit = true;
myTable.PreferredWidth = wordApp.UsableWidth;
//myTable.PreferredWidthType = WdPreferredWidthType.wdPreferredWidthAuto;
myTable.Columns[1].Width = 130;
myTable.Columns[2].Width = 70;
myTable.Columns[3].Width = wordApp.UsableWidth - myTable.Columns[1].Width - myTable.Columns[2].Width;
myTable.Rows[1].Cells[1].Range.Text = "Items returned by:";
myTable.Rows[1].Cells[1].Range.Bold = 1;
myTable.Rows[1].Cells[2].Range.Text = "Name";
myTable.Rows[1].Cells[2].Range.Bold = 1;
myTable.Rows[1].Cells[3].Range.Text = "(person's name and initials...)";
myTable.Rows[1].Cells[3].Range.Bold = 0;
myTable.Rows[2].Cells[2].Range.Text = "Date / Time";
myTable.Rows[2].Cells[2].Range.Bold = 1;
myTable.Rows[2].Cells[3].Range.Text = "(timestamp...)";
myTable.Rows[2].Cells[3].Range.Bold = 0;
UsableWidth refers to the Window width of the Word Application, not the document page width.
Instead use:
doc.PageSetup.PageWidth - (doc.PageSetup.LeftMargin + doc.PageSetup.RightMargin);

Adjust the column width only when its content cant fit in

I have form with DataGridView on it that displays data. Everything looks fine except when one of the columns content is wider then the column width. So I searched and found a line of code that I added to my Adjust_the DGV_width method so that columns width is adjusted
foreach (DataGridViewColumn col in zGrid1.Columns)
{
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
It works nicely but it is ugly and I would prefer to keep the columns width as is except when there is content that cant fit in.
How can I programmaticaly find out what is the width of the content that cant fit columns width?
Here is how it looks now, but I prefer when there is more space in columns.
This can be easily achieved by checking the column width after setting it to autosize.
Example:
int myDefaultWidth = 100;
myDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
foreach ( DataGridViewColumn column in myDataGridView.Columns )
{
if ( column.Width < myDefaultWidth)
{
column.Width = myDefaultWidth;
}
}

Autofit Row Height of Merged Cell in EPPlus

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.

MS Chart draw barchart

I need to draw a histogram, and columns with minimum and maximum values ​​should have other colors that are different from other columns and have different widths!
Now I have done this in two sets, but it's the wrong outcome.
Below is my code:
chart1.Series[0].Color = Color.Blue;
int y;
for (y = 0; y < lbls.Length; y++)
{
chart1.Series[0].Points.AddY(costs[y]);
chart1.ChartAreas[0].AxisX.CustomLabels.Add(new CustomLabel(y, y + 2, lbls[y], 0, LabelMarkStyle.LineSideMark));
}
chart1.Series[1].Color = Color.Red;
chart1.Series[1].Points.AddY(1500);
chart1.ChartAreas[1].AxisX.CustomLabels.Add(new CustomLabel(y+4, y + 6, "lol", 0, LabelMarkStyle.LineSideMark));
its give me:
Not too sure how to change specific column width but and to change a specific i points color do the below.
'Loop through series to find min and max and then color label
Chart1.Series[0].Points[i].Color = Color.Red
P.S.
I'm not sure if you can change just one columns width. I sometimes use Chart1.Series[0]("PixelPointWidth") = some integer to change the width of column series but looking at the msdn page it seems it can only be applied to the series and not individual datapoints.
PixelPointWidth # MSDN
You could just create a new series and add it to the chartarea with just the max and min values and then do Chart1.Series[1]("PixelPointWidth") = some integer to make them wider than the first series

DataGridView header alignment slightly to left even after setting it to MiddleCenter

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.

Categories

Resources