2012-02-12 75 views
2

如何查找某個單元格的像素絕對座標?Excel加載項:單元格絕對位置

我開發的Office 2010插件(Ribbon UI的),我在功能區中添加一個新的按鈕到一個新的菜單,按下按鈕時,我想獲得該單元的屏幕位置。問題是,

Globals.ThisWorkbook.Application.ActiveCell . Top/Left 

只給相對於A1角落的電子表格的位置,而我想相對於屏幕的0,0位置。

我發現這一點:How to get screen X and Y of an Excel 2003 cell in C#但它是Office 2003和我不完全理解的答案。

我使用C#進行開發,但VB也會這樣做。

謝謝!

+0

僅供參考,您鏈接到不會幫助,因爲它是確定的高度的代碼XL 2003和更早的工具欄在屏幕的頂部。 – 2012-02-12 14:12:50

+0

這是有點我的觀點,並沒有把我自己完全愚弄,我沒有到處看。 – cdavid 2012-02-13 00:02:08

+0

@cdavid有點晚了,但看看這對你沒有問題:http://stackoverflow.com/a/29354020/904156 – Loathing 2015-03-30 23:26:12

回答

3

我找到了this post,其中包含下面使用的API調用。我還被提醒說,你可以通過Application.Commandbars(「Ribbon」)獲得Ribbon的高度。所以,在VBA你會這樣做:

編輯:在迴應公式欄和標題高度問題我添加了一個函數,隱藏它們,獲取ActiveWindow.Height,然後顯示它們並獲取新的ActiveWindow.Height和數字區別。該函數現在在下面的行中被調用,在轉換之前將高度加在一起。我認爲它可行,但我沒有做很多測試。

Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long 
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long 
Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long 
Private Const LOGPIXELSX As Long = 88 
Private Const LOGPIXELSY As Long = 90 

Sub CellTopLeftPixels(rng As Excel.Range) 
Dim RibbonHeight As Long 
Dim TotalTop As Long 
Dim TotalLeft As Long 

RibbonHeight = Application.CommandBars("Ribbon").Height 
TotalTop = (RibbonHeight + GetFormulaBarAndHeadingsHeight + rng.Top) * PixelsPerPointY 
TotalLeft = rng.Left * PixelsPerPointX 
Debug.Print "Top: "; TotalTop; " Left: "; TotalLeft 
End Sub 

Function GetFormulaBarAndHeadingsHeight() 
Dim ActiveWindowHeightWhenHidden As Long 
Dim ActiveWindowHeightWhenShown As Long 

Application.DisplayFormulaBar = False 
ActiveWindow.DisplayHeadings = False 
ActiveWindowHeightWhenHidden = ActiveWindow.Height 
Application.DisplayFormulaBar = True 
ActiveWindow.DisplayHeadings = True 
ActiveWindowHeightWhenShown = ActiveWindow.Height 
GetFormulaBarAndHeadingsHeight = ActiveWindowHeightWhenHidden - ActiveWindowHeightWhenShown 
End Function 

Function PixelsPerPointX() As Double 
Dim hdc As Long 
Dim PixPerInchX As Long 

hdc = GetDC(0) 
PixPerInchX = GetDeviceCaps(hdc, LOGPIXELSX) 
PixelsPerPointX = PixPerInchX/72 
ReleaseDC 0, hdc 
End Function 

Function PixelsPerPointY() As Double 
Dim hdc As Long 
Dim PixPerInchY As Long 

hdc = GetDC(0) 
PixPerInchY = GetDeviceCaps(hdc, LOGPIXELSY) 
PixelsPerPointY = PixPerInchY/72 
ReleaseDC 0, hdc 
End Function 

的72的上方是每英寸的點。

這樣稱呼它:

Sub test() 
CellTopLeftPixels ActiveCell 
End Sub 
+0

謝謝! @Doug代碼很好,但它仍然有一些問題,據我發現 - 它沒有考慮到Excel在屏幕上的位置,以及公式欄的大小和大小標題(A,B,C ... 1,2,3)。對於應用程序,我發現'appTop = Globals.ThisWorkbook.Application.Top',但我仍在考慮如何獲取配方欄大小和標題大小(如果有的話)。非常感謝幫助。 – cdavid 2012-02-13 01:00:30

+0

我修改了(破解)代碼來解決這個問題。不知道這是否是最好的方法。查看修改。 – 2012-02-13 03:06:59

+0

與配方欄非常好的主意。不幸的是,同樣的事情不會與標題一起工作。而且你也不能使用'UsableHeight' /'UsableWidth'。我會將您的答覆標記爲答案並嘗試自己。如果你對更多的細節感興趣,我也發佈了同樣的問題[這裏](http://social.msdn.microsoft.com/Forums/en-US/exceldev/thread/50dae716-598c-4b16-bd57- 4e09b859c83e) – cdavid 2012-02-14 03:20:33

4

我發現這沒有任何一種兩輪牛車的工作:

Point GetScreenPositionFromCell(Excel.Range cell, Excel.Application excel) 
    { 
     var wnd = excel.ActiveWindow; 
     if (wnd != null) 
     { 
      var result = new Point 
      { 
       X = wnd.PointsToScreenPixelsX((int)cell.Left), 
       Y = wnd.PointsToScreenPixelsY((int)cell.Top) 
      }; 

      //cleanup 
      Marshal.ReleaseComObject(wnd); 
      wnd = null; 

      return result; 
     } 

     throw new Exception("Error retrieving active Excel-window."); 
    } 
+0

已經接受了安瑟 – tod 2015-02-17 09:16:53