Мой первый вопрос на эту тему был закрыт из-за недостаточной конкретики, поэтому я попытаюсь рассказать вам, что я пробовал до сих пор, но это не сработало. Я пытаюсь перенести книги Excel 2010 на свой новый компьютер Mac mini Big Sur с помощью Office 365. Это мой первый Mac, поэтому я очень плохо знаком с операционной системой и отличиями от мира Microsoft. Кроме того, я впервые использую Office 365. Я надеюсь, что вы будете достаточно любезны, чтобы помочь мне. В своих макросах VBA я запускаю скрипты Python для сбора данных с веб-страниц. Обычно скрипт Python создает файл .csv, который затем открываю в макросе VBA для чтения и заполнения необходимых ячеек в рабочей книге. Это код, который я использую в версии для ПК для вызова скрипта Python:
Kill strFileOfData
Set objWsh = VBA.CreateObject("WScript.shell")
strPython = """C:\Users\Phil\AppData\Local\Programs\Python\Python37-32\python.exe"""
strPyScript = """C:\Users\Phil\Documents\PyScripts\GetMarketsStks1-0.py"""
objWsh.Run strPython & strPyScript
Err = 0
Do Until Dir(StrFileOfData) <> 0
Application.Wait (Now() + TimeValue("0:00:01"))
Loop
Это может быть не самое лучшее, но оно надежно работает на ПК. Сначала я удаляю файл данных, запускаю скрипт Python, жду, пока файл данных будет создан, затем продолжаю. Я установил последнюю версию Python на Mac и переписал скрипт Python, чтобы получить больше данных, и запустил скрипт Python в Терминале, чтобы убедиться, что он выполняется правильно. Он работал нормально и правильно создал файл .csv. Затем я изменил код в макросе VBA, чтобы учесть различные файловые структуры. Это новый код:
Kill strFileOfData
Set objWsh = VBA.CreateObject("WScript.shell")
strPython = """/Library/Frameworks/Python.framework/Python"""
strPyScript = """/Users/minime/MyDocuments/Finance/GetHistory1-0.py"""
objWsh.Run strPython & strPyScript
Err = 0
Do Until Dir(StrFileOfData) <> 0
Application.Wait (Now() + TimeValue("0:00:01"))
Loop
Когда я запускаю это на Mac, я получаю:
Ошибка выполнения «429»: компонент ActiveX не может создать объект
Подозревая, что это разница в способах создания и использования оболочек, я начал исследовать, как вызывать Python из Excel на Mac. После значительных тупиков я нашел этот поток 4 года назад: Как запустить внешний процесс Python из Excel 365 VBA в OSX?
Я пытался просто идти вперед и следовать инструкциям. Я немного узнал об AppleScript, добавил папку: ~/Library/Application Scripts/com.microsoft.Excel/, создал AppleScript с именем PythonCommand.scpt и поместил его в эту папку. Поскольку я не смог найти путь в примере, я заменил его тем, что я считал правильным путем, предполагая, что это произошло из-за разницы в MacOS с 4-летней давности. Мой AppleScript выглядит так:
on PythonCommand(pythonScript)
do shell script "/Library/Frameworks/Python.framework/Python" & pythonScript
end PythonCommand
Затем я добавил этот код в макрос VBA:
strPyScript = """/Users/minime/MyDocuments/Finance/GetHistory1-0.py"""
Dim result As String
result = AppleScriptTask("PythonCommand.scpt", "PythonCommand", strPyScript)
Когда я запустил макрос VBA. Я получил это сообщение:
Ошибка выполнения «13»: несоответствие типов
Я попробовал еще раз с одинарными кавычками вместо тройных и получил тот же результат. Я пытался работать в обратном порядке, чтобы убедиться, что части работают. Я снова без проблем запустил скрипт Python из окна терминала, поэтому следующим шагом, который я попробовал, был запуск AppleScript из IDLE. Я набрал это:
AppleScriptTask("PythonCommand.scpt", "PythonCommand","/Users/minime/MyDocuments/Finance/GetHistory1-0.py")
и получил такой результат:
Трассировка (последний последний вызов): файл ‹pyshell#0›, строка 1, в AppleScriptTask(PythonCommand.scpt, PythonCommand,/Users/minime/My Documents/Finance/GetHistory1-0.py) NameError: name 'AppleScriptTask' is не определено
После дополнительных исследований я попробовал этот AppleScript в редакторе:
do shell script "/Library/Frameworks/Python.framework/Versions/3.9/Python /Users/minime/MyDocuments/Finance/GetHistory1-0.py"
Я получил этот результат:
ошибка sh: /Library/Frameworks/Python.framework/Versions/3.9/Python: невозможно выполнить двоичный файл номер 126
Далее я попробовал это:
do shell script "Python /Users/minime/MyDocuments/Finance/GetHistory1-0.py"
и получил это:
error "Traceback (most recent call last):
File \"/Users/philipackermann/MyDocuments/Finance/GetHistory1-0.py\", line 2, in <module>
from urllib.request import urlopen
ImportError: No module named request" number 1
Это действительно может быть некоторый прогресс! Этот оператор импорта является первой строкой кода в моем скрипте Python, но я понятия не имею, почему он зашел дальше, чем предыдущая попытка, и почему он работает иначе, чем выполнение скрипта Python в Терминале. Но я только что заметил, что в терминале я ввожу Python3, поэтому я попробовал это:
do shell script "Python3 /Users/minime/MyDocuments/Finance/GetHistory1-0.py"
и получил всплывающее окно с ошибкой сценария: и это:
Прочитав больше о терминале, я понял, что на Mac есть скрытые файлы, поэтому я попробовал этот AppleScript:
do shell script "/usr/local/bin/Python3 /Users/minime/MyDocuments/Finance/GetHistory1-0.py"
И это сработало!! CSV-файл успешно создан. Итак, теперь мне нужно выяснить, как вызвать это из Excel. Я нашел статью здесь:
https://stackoverflow.com/questions/38723420/how-to-simply-run-an-applescript-task-from-mac-excel-2016
Это действительно работает. Я преобразовал AppleScript в приложение (просто изменил расширение с scpt на app) и переместил его в папку «Приложения», а затем поместил этот код в макрос VBA:
ThisWorkbook.FollowHyperlink Address:="/Applications/RunGetHistory.app", NewWindow:=True
Это сработало! Конечно, он не передает никаких аргументов и не получает никаких результатов. Одна проблема, однако, как и в моей предыдущей версии для ПК, код не ждет завершения приложения, поэтому мне нужен способ проверить, будет ли это сделано, и поскольку я изменил скрипт Python, чтобы открыть файл в начале и написать строки для него при очистке веб-страниц файл создается сразу, поэтому этого кода, который я использовал в версии для ПК, недостаточно:
Do Until Dir(strFileNmHistory) <> ""
Application.Wait (Now() + TimeValue("0:00:01"))
Loop
Я полагаю, я мог бы добавить отдельный файл, написанный в конце скрипта Python, просто чтобы сказать, что это сделано, но это довольно хромой хак. Так что технически, я думаю, я мог бы сказать, что решил эту проблему и МОЖЕТ запустить скрипт Python из Excel, но я должен верить, что есть лучший способ, и я уверен, что в этом сообществе есть люди намного умнее меня, которые могут сделать это лучше. Кто-нибудь смог заставить работать решение 4-летней давности? Это может решить проблемы с аргументами, результатами и ожиданием завершения скрипта Python. Любые предложения, которые вы можете сделать, будут наиболее полезными. Я тщательно исследовал эту проблему, и в некоторых ответах говорилось, что песочница не позволяет Excel запускать Python, но если мы сможем запустить приложение, которое запускает скрипт Python, я думаю, это обойдется. Если вы можете прокомментировать конкретные ошибки, с которыми я столкнулся выше, я попробую разные подходы и отчитаюсь. Пожалуйста помоги. Фил