1

Background

Let's say I copy a range. In Excel, the copied range will be highlighted with a dashed border. Then I select another cell.
Now I will run a macro. In a message box, I want to see the address of the copied range.

Example:

  1. Copied Range("$A$1:$A$5") and selected the B1 cell. When I run the macro, the message box shows $A$1:$A$5.
  2. Copied Range("$C$5:$E$10") and selected the B1 cell. When I run the macro, the message box shows $C$5:$E$10.
sub GetCopiedAddress()

Dim CopiedRange as Range

'Set CopiedRange = Here Copied range will be mentioned.

MsgBox CopiedRange.Address 'Here Copied range will be shown

End sub
double-beep
  • 5,031
  • 17
  • 33
  • 41
  • 1
    `Set CopiedRange = Range("$A$1:$A$5")`... If you need it for the active sheet. If not, you should qualify it using the sheet you need. Then `CopiedRange .Copy range("C4")`. – FaneDuru Oct 26 '22 at 12:27
  • 1
    `Range("$A$1:$A$5")` this copied range is variable. And also Paste range is variable. I can copy any range from a sheet. Now how can set this copied range. – Mohashin Bipu Oct 26 '22 at 17:09
  • I cannot get you, sorry... – FaneDuru Oct 26 '22 at 17:47
  • Ok, I am trying again to explain. **Background:** Lets say I copy a range. In Excel, Copied Range will be highlighted with dashed border. Then I just select another cell. Now I will run a macro. In messageBox, I want to see the address of Copied range. **Example:** 1. Copied `Range("$A$1:$A$5")` and select `B1`Cell. When I will run the messageBox will show $A$1:$A$5. 2. Copied `Range("$C$5:$E$10")` and select `B1`Cell. When I will run the messageBox will show $C$5:$E$10. – Mohashin Bipu Oct 26 '22 at 18:20
  • 1
    Updated the main post for easy understanding. @FaneDuru – Mohashin Bipu Oct 26 '22 at 18:28
  • 1
    One approach if your copied range is contiguous - https://stackoverflow.com/a/13914224/478884 – Tim Williams Oct 26 '22 at 21:24
  • Also - https://www.mrexcel.com/board/threads/which-range-is-currently-being-cut-or-copied.1110148/ – Tim Williams Oct 26 '22 at 21:27
  • 1
    To get the copied range with [paste as Link](https://stackoverflow.com/questions/1108947/excel-vba-macro-check-content-of-clipboard-before-pasting/13914224#13914224) option is working... But this is slow when anyone select a column. I am looking for solution with windows API as i believe this process speed will be high. [Retrieve location of copied](https://stackoverflow.com/questions/23112161/retrieve-location-of-copied-cell-range-in-vba/23119068#23119068) or [Range is being Cut or Copied ?](https://www.mrexcel.com/board/threads/which-range-is-currently-being-cut-or-copied.1110148/) – Mohashin Bipu Oct 27 '22 at 09:04
  • This would be help if you can help me how I can get the address in message box mentioned in link- [Retrieve location of copied](https://stackoverflow.com/questions/23112161/retrieve-location-of-copied-cell-range-in-vba/23119068#23119068) or [Range is being Cut or Copied ?](https://www.mrexcel.com/board/threads/which-range-is-currently-being-cut-or-copied.1110148/) – Mohashin Bipu Oct 27 '22 at 09:10

1 Answers1

1

This method is by windows API. Paste as link method is very slow when you will copy a full column. This code works in 64bit. Didnot check in 32bit. Oddclock posted this amazing code.

    Private Declare PtrSafe Function CloseClipboard Lib "user32" () As Long
    Private Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongLong) As Long
    Private Declare PtrSafe Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As LongPtr
    Private Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Long) As Long
    Private Declare PtrSafe Function RegisterClipboardFormat Lib "user32.dll" Alias "RegisterClipboardFormatA" (ByVal lpString As String) As Long
    Private Declare PtrSafe Function GlobalLock Lib "kernel32.dll" (ByVal hMem As LongPtr) As LongPtr
    Private Declare PtrSafe Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As LongPtr) As Long
    Private Declare PtrSafe Function GlobalSize Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)

'reads excel copy-paste range from the clipboard and returns range object or nothing if not found
'_2022_03_19
Function fGetClipboardRange() As Range  'get excel copy or cut range from clipboard
Dim strClipboard As String  'raw clipboard data
Dim arrClipboard() As String    'parse into an array
    Set fGetClipboardRange = Nothing    'default is nothing
    
    strClipboard = fGetClipboardData("link")    'get the link data string
    If strClipboard = "" Then Exit Function 'done if it's empty
    arrClipboard = Split(strClipboard, Chr(0))  'else parse at null characters
    If arrClipboard(0) <> "Excel" Then Exit Function    'excel should be first
    strClipboard = "'" & arrClipboard(1) & "'!" & arrClipboard(2)   'parse the range from the others
    strClipboard = Application.ConvertFormula(strClipboard, xlR1C1, xlA1)   'convert to a1 style
    Set fGetClipboardRange = Range(strClipboard)    'range needs a1 style

End Function
'read clipboard for specified format into string or null string
'_2022_03_19
Function fGetClipboardData(strFormatId As String) As String 'read clipboard into string
Dim arrData() As Byte   'clipboard reads into this array
Dim hMem As LongPtr 'memory handle
Dim lngPointer As LongPtr   'memory pointer
Dim lngSize As Long 'size on clipboard
Dim lngFormatId As Long 'id number, for format name
    fGetClipboardData = ""  'default

    lngFormatId = fGetClipboardFormat(strFormatId)  'get format
    If lngFormatId <= 0 Then Exit Function  'zero if format not found

    CloseClipboard  'in case clipboard is open
    If CBool(OpenClipboard(0)) Then 'open clipboard
        hMem = GetClipboardData(lngFormatId)    'get memory handle
        If hMem > 0 Then    'if there's a handle
            lngSize = CLng(GlobalSize(hMem))    'get memory size
            If lngSize > 0 Then 'if we know the size
                lngPointer = GlobalLock(hMem)   'get memory pointer
                If lngPointer > 0 Then  'make sure we have the pointer
                    ReDim arrData(0 To lngSize - 1) 'size array
                    CopyMemory arrData(0), ByVal lngPointer, lngSize    'data from pointer to array
                    fGetClipboardData = StrConv(arrData, vbUnicode) 'convert array to string
                End If
                GlobalUnlock hMem   'unlock memory
            End If
        End If
    End If
    CloseClipboard  'don't leave the clipboard open
    
End Function

'return verified format number for format number, format number from format name or 0 for not found
'_2022_03_19
Function fGetClipboardFormat(strFormatId As String) As Long 'verify, or get format number from format name
Dim lngFormatId As Long 'format id number
    fGetClipboardFormat = 0 'default false

    If IsNumeric(strFormatId) Then  'for format number
        lngFormatId = CLng(strFormatId) 'use number for built in format
        CloseClipboard  'in case clipboard is already open
        If CBool(OpenClipboard(0)) = False Then 'done if can't open clipboard
        ElseIf CBool(IsClipboardFormatAvailable(lngFormatId)) = True Then   'true if format number found
            fGetClipboardFormat = lngFormatId   'return format number
        End If
        CloseClipboard  'don't leave the clipboard open
    Else
        lngFormatId = RegisterClipboardFormat(strFormatId & Chr(0)) 'else get number from format name
        If (lngFormatId > &HC000) Then fGetClipboardFormat = lngFormatId   'if valid return format number
    End If

End Function

Sub test()
If Application.CutCopyMode Then CopyRefEditTB.Value = fGetClipboardRange.Address
End Sub
Zohir Emon
  • 104
  • 8
  • In the fGetClipboardRange() function, make sure to add a line to replace F with R in arrClipboard(2) if Office is in Spanish. God damn it. – Ivan Feb 09 '23 at 11:53
  • @Ivan can you please explain this is details? – Zohir Emon Feb 10 '23 at 12:27
  • Simply that. If your Office suite is in Spanish, arrClipboard(2) will be something like F1C1 instead of R1C1. That's because "Row" is "Fila" in Spanish. Application.ConvertFormula expects R1C1 independently of your language. Just add arrClipboard(2) = Replace(arrClipboard(2),"F","R") before calling Application.ConvertFormula and your good. – Ivan Feb 11 '23 at 13:24