Подтвердить что ты не робот

Как мне сделать код VBA совместимым с 64-битной Windows?

У меня есть приложение VBA, разработанное в Excel 2007, и оно содержит следующий код для доступа к функции ShellExecute от Shell32.dll:

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

Я изначально сказал:

По-видимому, приложение не будет скомпилировать в 64-разрядной версии Windows (все еще используется 32-разрядный Office 2007). я предположим, что это связано с тем, что Declare требуется обновление.

Я читал, что Office 2010 представил новое время выполнения VBA (VB7), и что это имеет несколько новых ключевых слов, которые можно использовать в выражении Declare, чтобы разрешить для корректной работы на 64-битной Windows. VB7 также имеет новый предопределенный компилятор константы для поддержки условных компиляция, где либо старые, либо будет использована новая декларация, в зависимости от того, применяется ли приложение работает на 32 или 64-разрядной Windows.

Однако, поскольку я застрял с Office 2007 Мне нужно альтернативное решение. Какие у меня варианты? (Я бы действительно предпочитают не выпускать 2 отдельные версии моего приложения, если вообще возможно).

Однако, по словам Дэвида ниже, я ошибся в обстоятельствах, в которых мой оператор Declare не работает. Единственными обстоятельствами, при которых он не будет работать, является 64-разрядная версия Microsoft Office для 64-разрядной версии Windows. Таким образом, Office 2007 не является проблемой.

4b9b3361

Ответ 1

Я уже сталкивался с этой проблемой у людей, использующих мои собственные инструменты на новых 64-битных машинах с Office 2010.

все, что мне нужно было сделать, это изменить строки кода следующим образом:

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

К этому:

#If VBA7 Then
    Private Declare PtrSafe 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
#Else
    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
#End If

Вы, конечно же, захотите убедиться, что библиотека, которую вы используете, доступна на обеих машинах, но до сих пор ничто из того, что я использовал, было проблемой.

Обратите внимание, что в старом VB6 PtrSafe даже не является допустимой командой, поэтому он будет отображаться красным цветом, как если бы у вас была ошибка компиляции, но на самом деле она никогда не выдаст ошибку, потому что компилятор пропустит первая часть блока if.

code Appearance

Приложения, использующие вышеуказанный код, компилируются и выполняются отлично в Office 2003, 2007 и 2010 32 и 64 бит.

Ответ 2

Office 2007 - только 32-разрядный, так что там нет проблем. Ваши проблемы возникают только с битом Office 64, который имеет как 32, так и 64-разрядные версии.

Вы не можете надеяться на поддержку пользователей с 64-битным Office 2010, когда у вас только Office 2007. Решение должно быть обновлено.

Если у вас есть только Declare, это ShellExecute, тогда вам нечего делать, как только вы овладеете 64-битным Office, но не очень жизнеспособно поддерживать пользователей, когда вы не можете запускать программу, которую вы отправляете! Подумайте, что бы вы сделали, если сообщили об ошибке?

Ответ 3

я нашел этот код (обратите внимание, что некоторые Long изменены на LongPtr):

Declare PtrSafe Function ShellExecute Lib "shell32.dll" _
Alias "ShellExecuteA" (ByVal hwnd As LongPtr, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As _
String, ByVal nShowCmd As Long) As LongPtr

источник: http://www.cadsharp.com/docs/Win32API_PtrSafe.txt

Ответ 4

Собственно, правильным способом проверки для 32-битной или 64-битной платформы является использование константы Win64, которая определена во всех версиях VBA (16-разрядная, 32-разрядная и 64-разрядная версии).

#If Win64 Then 
' Win64=true, Win32=true, Win16= false 
#ElseIf Win32 Then 
' Win32=true, Win16=false 
#Else 
' Win16=true 
#End If

Источник: помощь VBA в константах компилятора

Ответ 5

Используйте PtrSafe и посмотрите, как это работает в Excel 2010.

Исправлена ​​опечатка из книги "Программирование питания Microsoft Excel 2010 с помощью VBA".

#If vba7 and win64 then
  declare ptrsafe function ....
#Else
  declare function ....
#End If

val (application.version) > 12.0 не будет работать, потому что Office 2010 имеет как 32, так и 64-разрядные версии

Ответ 6

Этот ответ скорее всего неверен в контексте. Я думал, что VBA теперь работает на CLR в наши дни, но это не так. В любом случае, этот ответ может быть полезен кому-то. Или нет.


Если вы запустите 32-битный режим Office 2010, то он будет таким же, как Office 2007. ( "Проблема" - это Office, работающий в 64-разрядном режиме). Это битту контекста исполнения (VBA/CLR), который здесь важен, и битность загруженного VBA/CLR зависит от битности хост-процесса.

Между 32/64-битными вызовами наиболее заметными ошибками являются long или int (постоянный размер в CLR) вместо IntPtr (динамический размер на основе битности) для "типов указателей",.

Функция ShellExecute имеет подпись:

HINSTANCE ShellExecute(
  __in_opt  HWND hwnd,
  __in_opt  LPCTSTR lpOperation,
  __in      LPCTSTR lpFile,
  __in_opt  LPCTSTR lpParameters,
  __in_opt  LPCTSTR lpDirectory,
  __in      INT nShowCmd
);

В этом случае важно HWND IntPtr (это связано с тем, что HWND - это "РУЧКА", которая void*/ "void pointer" ), а не long. См. pinvoke.net ShellExecute в качестве примера. (Хотя некоторые "решения" теневые на pinvoke.net, это хорошее место, чтобы выглядеть изначально).

Счастливое кодирование.


Что касается любого "нового синтаксиса", я понятия не имею.