Gruß Gott :-)
I wonder if the phenomena discussed here could be explained slightly differently:
It seems to me that the data object and the Windows Clipboard are somehow linked quite closely, but in a way that maybe, either, no one knows anymore exactly, or, those that do are not telling as it is propriety information . In addition possibly there are some rules , coding, or similar that govern how the data object and Windows Clipboard copes with the spaghetti of different Clipboards ( Office, Windows, Excel etc… ) and different versions of copied data therein. I doubt anyone in the meantime is capable of unravelling that spaghetti to make any clear sense of it.
Part of the monster that is “clipboards” is a true OLE object , the Data object. We have access to that.
Our Data object is perhaps more of a hooked Events thing which monitors the Windows Clipboard. We can set things that may then be used. We can influence with the Data object the behaviour of the clipboards
My experimenting suggest to me that there is some registers not directly accessible to us, and which we can influence and which is somehow strongly related to what is in the Window Clipboard. I think we are only privy to some of its behaviour.
I am thinking that .GetText() returns the last thing added in to a register.
Some examples to help shed some explanation to the strange behaviour:
Sub Copying()
This routine initially fills Office, Windows, and Excel Clipboards via an Excel range copy
.PutInClipboard and .GetText() would fail initially as the registers are not filled to which they refer.
.GetFromClipboard somehow now adds something to a register in the data object; I think that is getting data from the Windows Clipboard.
I clear the Office and Excel Clipboard to demonstrate they are not used further in the code. However I note that I must do the .GetFromClipboard before clearing those: clearing in this case either of the Office or Excel clipboard seams to make the Windows clipboard empty. I am not sure exactly why this should be the case, other than the spaghetti of dependencies in the clipboards somehow coming into play at this initial point ### I do not think that is generally true that we can empty the Windows clipboard by emptying the Office or Excel Clipboards
.GetText() now gives me the value from the copied cell. But I believe this is telling me what I last added to a register in the data object.
Now I use .SetText , and I believe I am adding something again to a register in the data object.
.GetText() now gives me the text that I added, “New Text”
I am proposing that at this point, in this particular code, I still have the value from the cell as coming from a clipboard and this is in a main register. I am not too sure where/ how the “New Text” is at this point. ( There are cases I have seen where this “New Text” would replace the text in the windows clipboard by a .PutInClipboard. This does not happen in this routine, strangely)
If I attempt a paste at this point, it would error. I think this is reasonable: At this point I think I have no data in the Windows Clipboard. ### In this particular example the windows clipboard has been emptied by the code lines emptying the Office or Excel clipboard: This is not usually the case ###
.PutInClipboard code line does now not error.
Nor does the paste a few lines down.
What one might not have expected is that the value pasted is not the “New Text”, but in fact, the original text from the cell
( And note also that this time we could clear the Office and Excel clipboards – with or without these lines the result is the same - Code line ActiveSheet.Paste Destination:=ActiveSheet.Range("C1") is apparently using the Windows Clipboard )
Option Explicit ' https://stackoverflow.com/questions/25091571/strange-behavior-from-vba-dataobject-gettext-returns-what-is-currently-on-the-c
' YOU NEED routine, ClearOffPainBouton() - get here, or just comment out Call s to it : --- https://pastebin.com/5bhqBAVx , http://www.eileenslounge.com/viewtopic.php?f=30&t=31849&start=20#p246838 http://www.excelfox.com/forum/showthread.php/2056-Appendix-Thread-(-Codes-for-other-Threads-HTML-Tables-etc-)?p=11019&viewfull=1#post11019 --- it will be best to copy entire coding here to a seperate code module
Sub Copying()
Range("C1").Clear
Dim DtaObj As Object ' Late Binding equivalent' If you declare a variable as Object, you might be late binding it. http://excelmatters.com/2013/09/23/vba-references-and-early-binding-vs-late-binding/ ... if you can .... http://www.eileenslounge.com/viewtopic.php?f=30&t=31547&start=40#p246602
Set DtaObj = GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}") ' http://excelmatters.com/2013/10/04/late-bound-msforms-dataobject/
Let Range("A1").Value = "CellA1": Range("A1").Copy ' This probably fills the Excel Clipboard, the Window Clipboard and the Office Clipboard
' DtaObj.PutInClipboard ' ' This will fail, DtaObj clear
' MsgBox Prompt:="DtaObj.GetText(1) is " & DtaObj.GetText() ' This will fail, DtaObj clear
DtaObj.GetFromClipboard '
Let Application.CutCopyMode = False ' This clears the Excel Clipboard
Call ClearOffPainBouton ' This clears the Office Clipboard
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText() ' --- "DtaObj.GetText() is CellA1"
DtaObj.SetText Text:="New Text" '
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText() ' --- "DtaObj.GetText() is New Text"
' ActiveSheet.Paste Destination:=ActiveSheet.Range("C1") ' This would error here
DtaObj.PutInClipboard
Let Application.CutCopyMode = False ' This clears the Excel Clipboard
Call ClearOffPainBouton ' This clears the Office Clipboard
ActiveSheet.Paste Destination:=ActiveSheet.Range("C1") ' --- "CellA1" is pasted in cell C1
End Sub
Sub Copying2()
This takes the last Sub further .. here an short walk through the coding
' New bit below
In the next 6 lines I have a feeling that the .PutInClipboard and the .GetFromClipboard are not doing much , if anything at all. Possibly the Excel knows that I have not changed any data, so it ignores attempts to do things that usually would be applied to some new data.
' Manual copy
You are prompted to copy anything. You should do this
Immediately after, .GetText() has not changed, but you get now pasted out the value that you copied. This suggest once again that code line ActiveSheet.Paste Destination:=ActiveSheet.Range("C1") is apparently using the Windows Clipboard
After using .GetFromClipboard , you will now find that .GetText() returns the value that you copied
Attempt to use .SetText to add to windows Clipboard
We Set the Text (do a .SetText) and do a .PutInClipboard. But as we have seen, this does not change the clipboard on this case, and the last thing we manually copied is still there to be pasted out
I try .Clear
The next two lines would error. This makes sense: I have emptied the registers. The third line erroring is less obvious. It suggests that .Clear clears the Windows Clipboard. I am not sure if that would always be the case.
The final code lines are successful in adding, via .SetText , something to the windows clipboard. My explanation is that as all registers are empty, the value given via .SetText is the only thing there, it is added to an empty thing so that is what is in there and available to be Put in the Clipboard.
In this case, now, a second attempt in adding via SetText is also successful. Why it should be in this case is slightly puzzling.
Sub Copying2()
Range("C1").Clear
Dim DtaObj As Object '
Set DtaObj = GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
Let Range("A1").Value = "cellA1": Range("A1").Copy ' This fills the Excel Clipboard, the Window Clipboard and the Office Clipboard
' DtaObj.PutInClipboard '
' MsgBox Prompt:="DtaObj.GetText(1) is " & DtaObj.GetText()
DtaObj.GetFromClipboard
Let Application.CutCopyMode = False ' This clears the Excel Clipboard
Call ClearOffPainBouton ' This clears the Office Clipboard
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText()
DtaObj.SetText Text:="New Text"
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText()
' ActiveSheet.Paste Destination:=ActiveSheet.Range("C1") ' This would error here
DtaObj.PutInClipboard
Let Application.CutCopyMode = False ' This clears the Excel Clipboard
Call ClearOffPainBouton ' This clears the Office Clipboard
ActiveSheet.Paste Destination:=ActiveSheet.Range("C1")
' New bit below - first 6 lines are not doing much if at all
Range("C1").Clear
DtaObj.PutInClipboard
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText()
DtaObj.GetFromClipboard
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText()
ActiveSheet.Paste Destination:=ActiveSheet.Range("C1")
' Below we manually copy
MsgBox prompt:="Please copy anything from anywhere , before hitting OK "
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText() ' has not changed
Range("C1").Clear
ActiveSheet.Paste Destination:=ActiveSheet.Range("C1") ' pastes what you copied
DtaObj.GetFromClipboard
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText() ' now shows what you copied
' Attempt to use SetText to add to windows Clipboard
DtaObj.SetText Text:="New Text To Paste"
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText() ' reflects the added text, "New Text To Paste"
DtaObj.PutInClipboard ' This either does nothing or once again puts what you copied there - as it already is, then Excel may know you already did this so does nothing
ActiveSheet.Paste Destination:=ActiveSheet.Range("C1") ' pastes what you copied
DtaObj.Clear
' MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText()' This would error - the registers are empty
' DtaObj.PutInClipboard ' This would also error - there is nothing in the registers to fill the clipboard with
' ActiveSheet.Paste Destination:=ActiveSheet.Range("C1") ' pastes what you copied
DtaObj.SetText Text:="New Text To Paste"
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText() ' reflects the added text, "New Text To Paste"
DtaObj.PutInClipboard
ActiveSheet.Paste Destination:=ActiveSheet.Range("C1") ' pastes "New Text To Paste"
DtaObj.SetText Text:="second Text To Paste"
MsgBox prompt:="DtaObj.GetText() is " & DtaObj.GetText() ' reflects the added text, "New Text To Paste"
DtaObj.PutInClipboard
ActiveSheet.Paste Destination:=ActiveSheet.Range("C1") ' pastes "New Text To Paste"
End Sub
_.__________________________________________
Coming back to the original question .. to explain the strange behaviour … just my take…
_ …... Q: Is this behaviour expected or is it a bug?
_ ....A
I think I expect it if my assessment of the situation above is correct: Doing a manual copy, or a copy via coding, makes an entry in a register in the data object. This is what .GetText() appears to get – the last thing entered, be it via a copy or by a .SetText. The .SetText won’t have any effect on a .PutInClipboard unless the register is empty. I guess the reason why it is done like this is somehow related to how you can use the format thing to effectively have multi text.
What is required to empty these registers is not clear always, that is to say , it is not clear if .Clear always is necerssary.
Clearly, the clipboard remains a mystery to everyone I think.
@ Tim Williams.
Sub Tester()
I think the results from your Sub Tester() are constant with my take on the situation: If you have nothing in the windows clipboard , you will need your code lines of d2.PutInClipboard and d.GetFromClipboard to get d.GetText to not error the first time. This will have a similar effect to doing d.SetText in terms of initialising a register, that is somehow related to d.
( If you have something in the Windows clipboard, then you do not need d2.PutInClipboard to prevent d.GetText from erroring , but it will return you what is in the windows clipboard. )
You do not ever need the second and third d2.PutInClipboard as they never have any effect on your coding: As long as you have your first d2.PutInClipboard, then you will get your shown results. My take on that is that .GetText is indicating the last thing it knows about that was added. You will find however, that if you copy something to the windows clipboard and delete all your 3 d2.PutInClipboard lines, then d.GetText will always tell you what is in the window clipboard. Somehow in this case it has lost its awareness of what d2 is doing. To confirm this you can try copying something to the Windows Clipboard, then run Sub Testies3() , which has the first d2.PutInClipboard removed, but the second and third included. Your routine will in this case tell you all the time what is in the windows clipboard, at least if you copy from Word… . ( …. if you copy something from inside Excel…. Then the first time you run that last routine, Sub Testies3() , you will get some interesting results. Something is managing to make d aware of what d2 is doing, the first time you run the code after copying something from Excel. It also happens like that if you copy something out of a text datei, or a browser, but not if you copy from Word )
If you try to understand fully what is going on in the spaghetti of interdependencies in the Clipboards then you will go mad…
Sub Tester()
Dim d As New DataObject, d2 As New DataObject
d2.SetText "first": d2.PutInClipboard
d.GetFromClipboard
Debug.Print d.GetText '--> "first"
d2.SetText "second": 'd2.PutInClipboard
Debug.Print d.GetText '--> "second"
d2.SetText "third" 'd2.PutInClipboard
Debug.Print d.GetText '--> "third"
End Sub
Sub Testes2() 'COPY SOMETING before running this
Dim d As New DataObject, d2 As New DataObject
d2.SetText "first": 'd2.PutInClipboard
d.GetFromClipboard
Debug.Print d.GetText '--> "What you copied"
d2.SetText "second": 'd2.PutInClipboard
Debug.Print d.GetText '--> "What you copied"
d2.SetText "third" 'd2.PutInClipboard
Debug.Print d.GetText '--> "What you copied"
End Sub
Sub Testies3() 'COPY SOMETING before running this
Dim d As New DataObject, d2 As New DataObject
d2.SetText "first": 'd2.PutInClipboard
d.GetFromClipboard
Debug.Print d.GetText '--> "What you copied"
d2.SetText "second": d2.PutInClipboard
Debug.Print d.GetText '--> "What you copied"
d2.SetText "third": d2.PutInClipboard
Debug.Print d.GetText '--> "What you copied"
End Sub