I often had this problem too. But you cannot wait 3 seconds per picture , it's too long. I work on 1000 pictures, it's gonna take for ever.
The core of the problem is that Excel copies to windows clipboard first, which is slow.
If you try to paste before the clipboard has the Pic , its will error.
So, some small steps needed for mass copying:
- Clear clipbard (not always needed but it makes sure you are not working on older data)
- Copy Pic
- Test if Pic is in the Clipboard and wait until it is there (loop)
- Paste
Here is the code (for Excel 64 bits) :
Option Explicit
'Does the clipboard contain a bitmap/metafile?
Public Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Integer) As Long
'Open the clipboard to read
Private Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal Hwnd As LongPtr) As Long
'clear clipboard
Public Declare PtrSafe Function EmptyClipboard Lib "user32" () As Long
'Get a pointer to the bitmap/metafile
Private Declare PtrSafe Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As LongPtr 'wformat as long ?
'Close the clipboard
Private Declare PtrSafe Function CloseClipboard Lib "user32" () As Long
'for waiting
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub Clear_Clipboard()
OpenClipboard (0&)
EmptyClipboard
CloseClipboard
Application.CutCopyMode = False
End Sub
Sub PastePic(Pic As Shape)
Dim Rg As Range
Dim T#
Dim Ligne&: Ligne = 5
Dim Sh_Vendeur As Worksheet
Set Sh_Vendeur = ThisWorkbook.Sheets(1)
Clear_Clipboard
Pic.Copy
Set Rg = Sh_Vendeur.Cells(Ligne, 2)
'wait until the clipboard gets a pic, but not over 3 seconds (avoid infinite loop)
T = Timer
Do
Waiting (2)
Loop Until Is_Pic_in_Clipboard Or Timer - T > 0.3
'Rg.Select
'Rg.PasteSpecial
Sh_Vendeur.Paste Destination:=Rg 'paste to a range without select
End Sub
Sub Waiting(ByVal Mili_Seconds&)
Sleep Mili_Seconds
End Sub
Function Is_Pic_in_Clipboard() As Boolean
If IsClipboardFormatAvailable(2) <> 0 Or IsClipboardFormatAvailable(14) <> 0 Then Is_Pic_in_Clipboard = True '2-14 =bitmap et Picture JPEG
End Function