I have a wide merged cell showing the title of the sheet. I also have a colored Textbox that I would like to position immediately to the right of the text in the merged cell.
The width of the title is variable so I have used a very wide merged cell.
sheet.Range["A2"].Value = title;
//Red Square
sheet.Shapes.Item("redSquare").Left += 0; // Position sheet.Range["A2"].TextWidth ???
Is there a property I can access on Range that will give me the actual text width in pixels of the text in merged cell?
As far as I know, there isn't anything in Interop that will tell you the width of text in pixels, but you can do it with the following. It seems to return a value reasonably similar to the column widths that Excel sets based on the same fonts.
Excel.Range xlRange = sheet.get_Range("A2");
Excel.Font xlFont = xlRange.Font;
string fontName = xlFont.Name;
double fontSize = xlFont.Size;
Font font = new Font(fontName, (float)fontSize);
float width = Graphics.FromImage(new Bitmap(1, 1)).MeasureString(title, font).Width;
You might need to add a few pixels here and there to make sure your textbox clears the end of the text, but I think it's about as accurate as you're going to get.
Related
I added a new chart control (System.Windows.Forms.DataVisualiation.Charting) with ChartType Bar.
As requirement the label text must be white and into the bar value. Therefore I set the BarLabelStyle=Right in the CustomProperties of the DataPoint objects and the LabelForeColor to White.
See the below images.
The label in the 2nd gray bar is correctly shown.
The first bar instead is too small and the white text is shown out on the right side but is not visible.
However, when the bar is too short, the label text is positioned outside the bar and the text cannot be seen using white color.
Is there a way to check when the label text is drawn outside the bar value so that I can change the color (e.g. black)?
Thanks.
Unfortunately MCChart has almost no capacities wrt to dynamic expressions.
To work around you can either..:
Code the ForeColor depending on the y-value your DataPoints has. Either right when you add them or in a function that loops over all points, whenever you call it.. - Depending on the Font, the axis range and the label text this could be some threshold number you have to determine.
Example:
int p = yourSeries.Points.AddXY(...);
yourSeries.Points[p].LabelForeColor = yourSeries.Points[p].YValues[0] < threshold ?
Color.Black : Color.White;
Or you can cheat a little ;-)
You can set the LabelBackColor to have the same color as the Series, i.e. the bar itself. Here is is how to do that:
To access the Series.Color we have to call:
chart.ApplyPaletteColors();
Now we can set
yourSeries.LabelForeColor = Color.White;
yourSeries.LabelBackColor = yourSeries.Color;
Example:
Update:
Since you can't use the cheat you will have to set the colors.
The challenge is to know just how much space each label's text needs compared to how much space the bars have. The former can be measured (TextRenderer.MeasureString()) and the latter can be extracted from the y-axis (Axis.ValueToPixelPosition()).
Here is a function to do that; it is a little more complicated than I had hoped for, mostly because it tries to be generic..
void LabelColors(Chart chart, ChartArea ca, Series s)
{
if (chart.Series.Count <= 0 || chart.Series[0].Points.Count <= 0) return;
Axis ay = ca.AxisY;
// get the maximum & minimum values
double maxyv = ay.Maximum;
if (maxyv == double.NaN) maxyv = s.Points.Max(v => v.YValues[0]);
double minyv = s.Points.Min(v => v.YValues[0]);
// get the pixel positions of the minimum
int y0x = (int)ay.ValueToPixelPosition(0);
for (int i = 0; i < s.Points.Count; i++)
{
DataPoint dp = s.Points[i];
// pixel position of the bar right
int vx = (int)ay.ValueToPixelPosition(dp.YValues[0]);
// now we knowe the bar's width
int barWidth = vx - y0x;
// find out what the label text actauly is
string t = dp.LabelFormat != "" ?
String.Format(dp.LabelFormat, dp.YValues[0]) : dp.YValues[0].ToString();
string text = dp.Label != "" ? dp.Label : t;
// measure the (formatted) text
SizeF rect = TextRenderer.MeasureText(text, dp.Font);
Console.WriteLine(text);
dp.LabelForeColor = barWidth < rect.Width ? Color.Black : Color.White;
}
}
I may have overcomplicated the way to get at the text that should show; you certainly can decide if you can simplify for your case.
Note: You must call this function..
whenever your data may have changed
only after the axes of the chart have finished their layout (!)
The former point is obvious, the latter isn't. It means that you can't call the function right after adding your points! Instead you must do it at some later place or else the axis function needed to get the bar size will not work.
MSDN says it can only happen in a PaintXXX event; I found that all mouse events also work and then some..
To be save I'll put it in the PostPaint event:
private void chart_PostPaint(object sender, ChartPaintEventArgs e)
{
LabelColors(chart, chart.ChartAreas[0], chart.Series[0]);
}
I have some text in a pdf that has been OCR'ed.
The OCR returns the bounding boxes of the words to me.
I'm able to draw the bounding boxes (wordRect) on the pdf and everything seems correct.
But when i tell my fontsize to be the height of these bounding boxes,
it all goes wrong. The text appears way smaller than it should be and doesn't match the height.
There's some conversion i am missing. How can i make sure the text is as high as the bounding boxes?
pdftron.PDF.Font font = pdftron.PDF.Font.Create(convertedPdf.GetSDFDoc(), pdftron.PDF.Font.StandardType1Font.e_helvetica);
for (int j = 0; j < ocrStream.pr_WoordList.Count; j++)
{
wordRect = (Rectangle) ocrStream.pr_Rectangles[j];
Element textBegin = elementBuilder.CreateTextBegin();
gStateTextRun = textBegin.GetGState();
gStateTextRun.SetTextRenderMode(GState.TextRenderingMode.e_stroke_text);
elementWriter.WriteElement(textBegin);
fontSize = wordRect.Height;
double descent;
if (hasColorImg)
{
descent = (-1 * font.GetDescent() / 1000d) * fontSize;
textRun = elementBuilder.CreateTextRun((string)ocrStream.pr_WoordList[j], font, fontSize);
//translate the word to its correct position on the pdf
//the bottom line of the wordrectangle is the baseline for the font, that's why we need the descender
textRun.SetTextMatrix(1, 0, 0, 1, wordRect.Left, wordRect.Bottom + descent );
How can i make sure the text is as high as the bounding boxes?
The font_size is just a scaling factor, which in most cases does map to 1/72 inch (pt), but not always.
The transformations are:
GlyphSpace -> TextSpace -> UserSpace (where UserSpace is essentially the page space, and is 1/72 inch)
The glyphs in the font are defined in GlyphSpace, and there is a font matrix that maps to TextSpace. Typically, 1000 units maps to 1 unit in test space, but not always.
Then the text matrix (element.SetTextMatrix), the font size (variable in question here) and some additional parameters, transform TextSpace coordinates to UserSpace.
In the end though, the exact height, depends on the glyph also.
This forum post shows how to go from the glyph data, to UserSpace. See ProcessElements
https://groups.google.com/d/msg/pdfnet-sdk/eOATUHGFyqU/6tsUF0BHukkJ
I am trying to recreate a table like this:
I am using the DocX library to manipulate Word files, but I'm having trouble getting the widths right. Trying to set the widths of cells only seems to work when it's not set to the window autofit mode, and it only seems to resize when the specified width is greater than half of the table width, or rather, I can make a cell bigger than half the width but not smaller.
What would be the simplest way to reproduce the intended table?
I found the answer to this myself. In order to properly set the width, you have to loop through each cell in a column and set every width. This will not work with any autofit options selected.
Try this :
Table table = doc.AddTable(2, 2);
table.SetColumnWidth(0, 500);
//first is column index, the second is column width
Bit of an old post to tag to, but after having the same issue it would appear that none of the widths on either the cells or columns actually work, so as a dirty workaround, you can loop through each column and cell adding text to each of the cells, make the text white and finally use the autofit option to autofit to contents eg.
Table t2 = doc.AddTable(2, 8);
for (int i = 0; i < t2.RowCount; i ++)
{
for(int x = 0; x < t2.ColumnCount; x++)
{
t2.Rows[i].Cells[x].Paragraphs.First().Append("12").Color(Color.White);
}
}
t2.AutoFit = AutoFit.Contents;
doc.InsertTable(t2);
This is the way:
Table t = doc.AddTable(1, 5);
t.SetWidthsPercentage(new[] { 20f, 20f, 40f, 10f, 10f }, 500);
The float array sets width percentage for each of the columns, second parameter is the total width of the table.
I'm having a bit of trouble on solving this. Is there a way to set the width of a specific cell from a worksheet using epplus? Because when i use, for example:
ws.Column(1).Width = 40;
the whole column gets affected.
Thanks in advance!
As I know, there is no way to change the width of a specific cell. All cells in one column have same width. You can change the width of a cell by merging it with its neighbour. I have an example:
sheet.Cells["A1"].Value = "This is a cell";
sheet.Cells["A1:A2"].Merge = true;
Then you can set width by using
sheet.Column(1).Width = 40;
or
sheet.Cells["A1:A2"].AutoFitColumns();
Hi you can try like this
using (ExcelPackage pck = new ExcelPackage())
{
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("1232");
ws.Cells["A1"].AutoFitColumns();
//ws.Cells[""].AutoFitColumns(20);//overloaded
//ws.Cells[""].AutoFitColumns(20,40);//overloaded min and max lengths
}
Hi i am using EPPlus to populate a spreadsheet with data, so far so good text wise but i am having issues when trying to add a picture??
I can add a picture but its from the top left cell and its not contained with in a cell.
Please could someone show me how i can place a picture into a cell and fill the cell?
Bitmap image = new Bitmap(tempFolderPathAlt + "ExtractedFiles/" + ArrayNode[i].TagValue);
ExcelPicture picture = null;
var rowIndex = xlWorkSeet1[k].Dimension.Start.Row;
var columnIndex = xlWorkSeet1[k].Dimension.Start.Column;
picture = xlWorkSeet1[k].Drawings.AddPicture(System.Guid.NewGuid().ToString() + rowIndex.ToString() + columnIndex.ToString(), image);
picture.From.Column = columnIndex;
picture.From.Row = rowIndex;
I believe there is no way to add a picture into a cell.
The work around for this is to resize the cell to be the same size as your image and place it over the cell.