Я использовал этот код для копирования по ряду диапазонов и диаграмм. Однако по мере того, как мой код вырос, он, похоже, падает, после поиска в Google этой проблемы я думаю, что это вызвано неправильным копированием диаграммы / диапазона в / из кеша буфера обмена. Есть ли способ избежать этой ошибки?
Error - " Run-time error '-2147188160 (80048248)': Shapes.PasteSpecial :Invalid request. Clipboard is empty or contains data which may not be pasted here"
Public Sub CopyPasteHeadcountTopGraph()
If PPT Is Nothing Then Exit Sub
If PPT_pres Is Nothing Then Exit Sub
Dim rng As Range
Dim mySlide As Object
Dim myShape As Object
Dim cht As Chart
Set mySlide = PPT_pres.Slides(6)
With mySlide
.Select
Set cht = ThisWorkbook.Worksheets("Headcount").ChartObjects("HcChart").Chart
cht.CopyPicture Appearance:=xlScreen, Format:=xlPicture, Size:=xlScreen
.Shapes.Paste.Select 'ERROR HERE
'''''''''''''''''''''''''''''''''
'Paste as Chart and break link. '
'''''''''''''''''''''''''''''''''
'cht.ChartArea.Copy
'.Shapes.Paste.Select
'With .Shapes("HcChart")
'.LinkFormat.BreakLink
'End With
PPT_pres.Windows(1).Selection.ShapeRange.Left = 35
PPT_pres.Windows(1).Selection.ShapeRange.Top = 110
PPT_pres.Windows(1).Selection.ShapeRange.Width = 655
PPT_pres.Windows(1).Selection.ShapeRange.Height = 300
End With
'Clear The Clipboard
Application.CutCopyMode = False
Application.Wait (Now + TimeValue("00:00:01"))
End Sub
Часто VBA начинает работать с объектами, когда эти объекты еще не готовы к работе. Даже копирование объекта может не быть завершено (т. Е. Весь объект не полностью зафиксирован в буфере обмена), когда VBA пытается вставить.
Я обнаружил, что помещения определенных операций в отдельную процедуру может быть достаточно, чтобы VBA дождался завершения одного фонового процесса, прежде чем запускать следующий.
Например, в приведенном ниже коде я убрал вставку из основной процедуры. Это заставляет VBA ждать завершения копирования перед вставкой, а также до завершения вставки перед размещением вставленной диаграммы.
Фактически, у меня часто есть три отдельные функции, которые вызываются основной подпрограммой: копирование диаграммы, вставка диаграммы и позиционирование диаграммы.
Public Sub CopyPasteHeadcountTopGraph()
If PPT Is Nothing Then Exit Sub
If PPT_pres Is Nothing Then Exit Sub
Dim rng As Range
Dim mySlide As Object
Dim myShape As Object
Dim cht As Chart
Set mySlide = PPT_pres.Slides(6)
With mySlide
.Select
Set cht = ThisWorkbook.Worksheets("Headcount").ChartObjects("HcChart").Chart
cht.CopyPicture Appearance:=xlScreen, Format:=xlPicture, Size:=xlScreen
'''''''''''''''''''''''''''''''''''
'' .Shapes.Paste.Select 'ERROR HERE
'''''''''''''''''''''''''''''''''''
PasteChartIntoSlide mySlide
PPT_pres.Windows(1).Selection.ShapeRange.Left = 35
PPT_pres.Windows(1).Selection.ShapeRange.Top = 110
PPT_pres.Windows(1).Selection.ShapeRange.Width = 655
PPT_pres.Windows(1).Selection.ShapeRange.Height = 300
End With
'Clear The Clipboard
Application.CutCopyMode = False
Application.Wait (Now + TimeValue("00:00:01"))
End Sub
Function PasteChartIntoSlide(theSlide As Object) As Object
theSlide.Shapes.Paste.Select
End Function
Спасибо тебе за это. Я потратил несколько часов, потому что не знал об этом поведении VBA. Это даже не упоминается в документации ...
@jonPeltier. У меня тоже были те же проблемы: много копий диаграмм нужно было вставить как изображения в другую таблицу. Я также не вижу задокументированной проблемы с ошибкой, но также отмечаю, что предложение «подпрограмма» для завершения необходимой обработки не имеет документированного объяснения. Мой вопрос1: Почему подпрограмма вызывает необходимую обработку? (Этот эффект где-нибудь задокументирован?) Вопрос 2: Если это помогает, почему TisButaScratch и JonPeltier вообще включают .waits?
Проблема не задокументирована Microsoft; он носит спорадический характер, и вы увидите вопросы по этому поводу на онлайн-форумах. Объяснение «подпрограммы» таково: я обнаружил, что идентификация операций, которые требуют времени и могут привести к рассинхронизации VBA, и разбиение их на другие процедуры, похоже, помогает с этими проблемами. Я не знаю, почему это работает, но я предполагаю, что это может быть связано с тем, что границы вызываемых процедур заставляют VBA завершать работу с объектами перед входом в эти процедуры или выходом из них. Во всяком случае, для меня это имеет смысл.
Я стараюсь избегать использования Application.Wait
(хотя я вижу, что оставил его в образце кода в своем ответе, который был взят из образца кода в вопросе). DoEvents
и вызов других процедур поддерживают работу VBA, тогда как .Wait
фактически останавливает VBA. Мне кажется, что остановка VBA помешала бы ему догнать себя.
Мне пришлось использовать этот код для решения этой проблемы. Вызова функции или DoEvents было недостаточно:
...
ActiveChart.ChartArea.Copy
aplicacion = RUTA & "\freemem.vbe"
lngErr = ShellExecute(0, "OPEN", aplicacion, "", "", 0)
Call pegadatos(PPSlide)
...
где функция shellexecute объявлена ранее как
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
freemem.vbe - это текстовый файл с единственной строкой: Mystring=(80000000)
. После создания файла .txt необходимо изменить расширение на .vbe.
И пегадато:
Sub pegadatos(TheSlide As Object)
TheSlide.Shapes.Paste.Select
End Sub
Эта ошибка также может быть связана с ошибкой Excel, которая, по-видимому, не позволяет вам копировать диаграммы, метки данных которых связаны с несмежным диапазоном ячеек, так что вы получаете ошибку «Буфер обмена пуст ...» при последующей попытке вставить. Эта ошибка была воспроизведена в Excel 2013 и новее и дополнительно описана по адресу:
Спасибо, Джон, отличное объяснение, и это действительно улучшило мой код, я был вынужден использовать Sleep 50 в каждой функции, но изначально он ждал целую секунду, поэтому резко увеличил скорость кода!