Любой класс, который наследуется публично, полиморфно или нет, должен иметь виртуальный деструктор. Иными словами, если на него может указывать указатель на базовый класс, его базовый класс должен иметь виртуальный деструктор.
Если виртуальный, вызывается деструктор производного класса, то конструктор базового класса. Если не виртуально, вызывается только деструктор базового класса.
Я начал получать эту ошибку при обновлении с 2003 по 2010 год, но макрос все еще работал в 2003 году.
Таблицы были там, но я заметил, что иногда копирование не работает. Поскольку это никогда не случалось в режиме отладки, я добавил 5 секунд ожидания перед копированием.
Это делает макрос медленнее, но по крайней мере он работает.
Я не подтвердил это как окончательное решение, но зависание, кажется, при копировании. Скопированные данные никогда не попадают в буфер обмена, поэтому код не работает при попытке вставить. Очистка буфера обмена любых ранее скопированных данных перед началом следующей команды копирования помогла. Я все еще использую время ожидания, показанное выше, но, похоже, я могу уйти с более коротким временем ожидания, используя следующую функцию для очистки буфера обмена:
Application.CutCopyMode = False
Это код, который я использую:
Private Declare Function apiOpenClipboard Lib "user32" Alias "OpenClipboard" (ByVal hWnd As Long) As Long
Private Declare Function apiEmptyClipboard Lib "user32" Alias "EmptyClipboard" () As Long
Private Declare Function apiCloseClipboard Lib "user32" Alias "CloseClipboard" () As Long
Private Declare Function CountClipboardFormats Lib "user32" () As Long
Function ClipboardEmpty() As Boolean
ClipboardEmpty = (CountClipboardFormats() = 0)
End Function
Sub EmptyClipboard()
If apiOpenClipboard(0&) <> 0 Then
Call apiEmptyClipboard
Call apiCloseClipboard
End If
End Sub
функция ClipboardEmpty
является тестом. например if clipboardempty then
Суб EmptyClipboard
просто очистит буфер обмена
Я все еще тестирую свое решение, но оно отличается от сделанных предложений и до сих пор безупречно работает. Просто другой подход:
Я добавляю метку и окружаю мою попытку скопировать с помощью обработчика ошибок ...
Pg1CopyAttempt:
DoEvents
shSomeSheet.Range("A1:G30").Copy
On Error GoTo Pg1PasteFail
WordApp.Selection.PasteExcelTable False, False, False
On Error goto 0 'disable the error handler
Я вызываю метку «Pg1CopyAttempt», потому что знаю, что Excel, без моего собственного недостатка, может не копировать его в буфер обмена. Если Excel меня подведет, я не буду знать, пока не попытаюсь вставить. Когда я пытаюсь, я попадаю в обработчик ошибок (Pg1PasteFail), когда метод пасты терпит неудачу. Это сидит в нижней части моей подпрограммы (после прямого выхода или процедуры выхода).
Pg1PasteFail:
If Err.Number = 4605 Then ' clipboard is empty or not valid.
DoEvents
Resume Pg1CopyAttempt
End If
Было бы лучше протестировать пустой буфер обмена программно, чем полагаться на обработчик ошибок, но Идея здесь заключается в том, чтобы заставить цикл, чтобы он продолжал копировать, пока не будет успешным. Более простой цикл с программным тестированием буфера обмена может использовать функцию ClipboardEmpty от Sean (см. Выше). DoEvents все еще эксплуатируется, но даже с DoEvents подпрограммы могут выйти из строя, и им просто поручено продолжать попытки.