nwein
Posts: 577
Joined: 2011-03-28
|
I was wondering if there's an easy way to retrieve back the Point (x,y) of the top left cell of a selected range.
I'm talking about the absolute screen coordinates, not the column/row, i.e. it should return a Point object (or two ints specifying the x and y coordinates), not a range or anything like that.
I've found some funky VBA code that can do it somehow, but it's not pretty.
It most likely requires some pinvokes (user32 and gdi32) which I'm fine with, though I thought I'd ask here first before going to the dark side :) |
|
nwein
Posts: 577
Joined: 2011-03-28
|
Well, I figured I might as well share with you my current solution (which works pretty darn well).
As before, if there's an easier way to do it I'd be happy to hear about it.
(this code all goes into the ADXAddinModule class, i.e. COM Addin):
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
private const int LOGPIXELSX = 88;
private const int LOGPIXELSY = 90;
private System.Drawing.Point GetCellPosition(Range range)
{
Worksheet ws = range.Worksheet;
IntPtr hdc = GetDC((IntPtr)0);
long px = GetDeviceCaps(hdc, LOGPIXELSX);
long py = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC((IntPtr) 0, hdc);
double zoom = ExcelApp.ActiveWindow .Zoom;
var pointsPerInch = ExcelApp.Application.InchesToPoints(1); // usually 72
var zoomRatio = zoom/100;
var x = ExcelApp.ActiveWindow .PointsToScreenPixelsX(0);
// Coordinates of current column
x = Convert.ToInt32(x + range.Left * zoomRatio * px / pointsPerInch);
// Coordinates of next column
//x = Convert.ToInt32(x + (((Range)(ws.Columns)[range.Column]).Width + range.Left) * zoomRatio * px / pointsPerInch);
var y = ExcelApp.ActiveWindow .PointsToScreenPixelsY(0);
y = Convert.ToInt32(y + range.Top * zoomRatio * py / pointsPerInch);
Marshal.ReleaseComObject(ws);
Marshal.ReleaseComObject(range);
return new System.Drawing.Point(x, y);
}
|
|
Eugene Astafiev
Guest
|
Hi Nir,
Thank you for sharing your solution (the code) to other forum readers!
As you may see there is no trivial way for implementing the required functionality. I.e. the Excel Object Model doesn't provide any property or method for this. That is why you chose the right way and use some WinAPI functions. |
|