Выбрать дату в календареВыбрать дату в календаре

Страницы: 1
Интерактивный макрос виснет на Windows 7-10 в Excel 2007-2016, но НЕ виснет на Windows XP 32 bit Excel 2003
 
Спасибо, старался). Еще одна (неприятная) находка, не относящаяся к теме, но касающаяся производительности макросов (если для кого-то это действительно критично). В ходе парных тестов выяснилось, что активное "тиражирование" пользовательского класса (даже небольшого, на 20 переменных и почти без своего кода) способно очень сильно затормозить исполнение программы (до двух раз при числе копий в коллекции 600+) в сравнении с динамическим массивом из элементов пользовательского типа (несмотря на все необходимые действия по его обслуживанию: добавление и удаление элементов, устранение пробелов и перевыделение памяти).
Повторюсь, это может быть важно в случаях, когда в работе одновременно много копий пользовательского класса и есть требования к скорости исполнения макроса. В остальных же случаях ООП в VBA только помогает.
Изменено: левша - 16.10.2018 22:31:04
Интерактивный макрос виснет на Windows 7-10 в Excel 2007-2016, но НЕ виснет на Windows XP 32 bit Excel 2003
 
Спасибо за советы! Хоть и с большим запозданием, но отпишусь, что проблема была все-таки решена. Она была связана с тем, что в более поздних версиях Excel интерпретатор по-другому относится к инструкции Application.EnableEvents = False (при этом оператор DoEvents у меня был расположен однократно в главном цикле программы, и Excel 2003-2007 это нисколько не смущало), поэтому при малейшем "провисании" исполнения главного цикла программы система, насколько я понял, "насильно" отнимала у Excel управление и, тем самым, "завешивала" программу. Стоило расставить DoEvents во всех "трудоемких" и ожидающих пользовательского ввода кусках программы, и "болезнь отступила"... Еще один нюанс оказался связан, насколько я понял, с разделением потоков на ядра процессора в более поздних версиях Excel (2013-2016). Оказалось, что при этом игнорируется очередность исполнения таких вызовов, как Application.ScreenUpdating = True и вызовов форматирования ячеек листа (с точки зрения вычислений Excel это вполне допустимо, но вот графическое отображение от этого сильно пострадало, поэтому пришлось вводить спец. задержки для обновления экрана там, где оно de facto происходило раньше, чем предшествовавшая ему "отрисовка" листа).
Вобщем, вот такое вышло: https://youtu.be/6jyOJsJlLhI
Еще раз спасибо за помощь.
Интерактивный макрос виснет на Windows 7-10 в Excel 2007-2016, но НЕ виснет на Windows XP 32 bit Excel 2003
 
Спасибо, очень удобная тестовая программка. На 64 бит Win 8 и Excel 2016 GetAsyncKeyState работает, клавиши считывает, и кодировка клавиш совпадает с той таблицей, что у меня в программе. Но по ходу программы клавиатура на Excel 2016 висит (а в Excel 2007 нет). Очень странно.
Интерактивный макрос виснет на Windows 7-10 в Excel 2007-2016, но НЕ виснет на Windows XP 32 bit Excel 2003
 
Спасибо за советы. Пока что получилось добиться визуализации игрового экрана (он у меня на рабочем листе формируется), только полностью закомментировав все обращения к Application.ScreenUpdating (что конечно же сделало отображение совсем неприемлемым, но тут уж дело принципа). GetAsyncKeyState не работает, точнее - распознает только нажатие пробела. Курсор мышки ловится, музыка играет. Клавиши мыши, которые тоже читаются через GetAsyncKeyState, тоже не работают. Возможно, виртуальные коды клавиатуры GetAsyncKeyState в Windows 8.1 другие (хотя почему они тогда, хоть и не так стабильно, как в Windows XP SP3, работают на Windows 7 32 бит и 10 64 бит c Excel 2007? Если проблема не в ОС, а в версии Excel, то каким образом эта проблема влияет на работу внешней по отношению к Excel функции из Windows API?).
Изменено: левша - 14.08.2018 22:30:50
Интерактивный макрос виснет на Windows 7-10 в Excel 2007-2016, но НЕ виснет на Windows XP 32 bit Excel 2003
 
Спасибо большое за ответ и ссылку, кое-что отличалось, подправил, теперь заголовок выглядит так:

Код
#If VBA7 Then
    Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
    Declare PtrSafe Function Beep Lib "kernel32" (ByVal dwFreq As Long, ByVal dwDuration As Long) As Long
    Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Declare PtrSafe Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long
    Declare PtrSafe Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As LongPtr) As Long
#Else
    Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    Declare Function GetTickCount Lib "kernel32.dll" () As Long
    Declare Function Beep Lib "kernel32" (ByVal dwFreq As Long, ByVal dwDuration As Long) As Long
    Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Declare Function SetCursorPos Lib "user32" (ByVal x As Integer, ByVal y As Integer) As Long
    Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
#End If
Но на Windows 8.1 64-разрядной с Excel 2016 программа все равно не работает (хотя сначала все же реагирует на клавиатуру). Еще заметил, что попеременные  Application.ScreenUpdating = False/True, которые работают нормально в Excel 2003-2007 (в Excel 2010 не пробовал) тут приводят к тому, что экран в принципе перестает обновляться.
ПС. И я правильно понимаю, что функцией GetTickCount все еще можно пользоваться на 64-разрядных Windows (просто там есть еще GetTickCount64). Или нет? Быстрый тест показал, что зачение она возвращает вроде бы корректное.

Изменено: левша - 13.08.2018 23:29:05
Интерактивный макрос виснет на Windows 7-10 в Excel 2007-2016, но НЕ виснет на Windows XP 32 bit Excel 2003
 
Здравствуйте, такой непростой (для меня, как оказалось) вопрос. Есть большой (10к+ строк) интерактивный макрос (игра), использующий функции операционной системы для перехвата событий клавиатуры, мышки и проигрывания звуков (пищалкой и системной программой воспроизведения мультимедиа). Вот такой заголовок у моего макроса:
Код
#if VBA7 then
    Declare PtrSafe Function getTickCount Lib "kernel32" Alias "GetTickCount" () As Long
    Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    Declare PtrSafe Function beep Lib "kernel32" Alias "Beep" (ByVal dwFreq As LongPtr, ByVal dwDuration As LongPtr) As LongPtr
    Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Declare PtrSafe Function SetCursorPos Lib "user32" (ByVal x As Integer, ByVal y As Integer) As Long
    Private Declare PtrSafe Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
#Else
    Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    Declare Function getTickCount Lib "kernel32.dll" Alias "GetTickCount" () As Long
    Declare Function beep Lib "kernel32" Alias "Beep" (ByVal dwFreq As Long, ByVal dwDuration As Long) As Long
    Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Declare Function SetCursorPos Lib "user32" (ByVal x As Integer, ByVal y As Integer) As Long
    Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
#End If
Проблема заключается в том, что файл очень по-разному ведет себя на разных компах:
Win XP 32 и Excel 2003 (2 разных компа) - работает без проблем
Win XP 32 и Excel 2007 - работает практически без проблем
Win 7 32 и Excel 2007 - периодически зависает с надписью "программа не отвечает", но потом спустя какое-то время продолжает работать
Win 10 64 и Excel 2007 - периодически зависает с надписью "программа не отвечает"(предполагаю, что в ответ на использование клавиатуры, левая кнопка мыши и перемещение мышиного курсора иногда решают эту проблему, а иногда нет, и тогда Ctrl-Break уже не работает, хотя в коде я его не отключал).
Win 8.1 64 и Excel 2016 - виснет практически сразу (музыку играть начинает, но пишет "программа не отвечает" еще до нажатий на какие-либо клавиши и использование мыши. Что завешивает программу, мне непонятно), Ctrl-Break не работает

Поскольку программа отлично (соответственно скорости компьютера) чувствует себя на старых версиях Windows и Excel, и при этом подвисает или виснет на более мощных и современных машинах, для себя я сделал вывод, что проблема в неправильном объявлении внешних по отношению к коду функций (Уточню: в самом коде у меня новые 64-битные типы данных не используются, но, если я не ошибаюсь, это и не обязательно). Приведенный выше заголовок пытается решить эту проблему, но очевидно не решает ее. Лично для меня эта кросс-платформенная неразбериха внутри VBA поставила в тупик. Поэтому буду признателен за любую попытку помочь в решении проблемы.
 
Изменено: левша - 14.08.2018 23:34:31 (правка некорректного ввода )
Страницы: 1
Наверх