Вы подумаете, что это глупо, но это решит вашу проблему ...
Вам необходимо удалить запятую после вызова метода SaveAs
и перед Filename
именованный параметр.
Таким образом, самая последняя строка вашего кода должна выглядеть следующим образом:
analysisbook.SaveAs Filename:="analysis" & " " & Format(Now(), "dd_mm_yyyy_hh_mm_AMPM") & ".xlsx"
Запятую нужно использовать, только если вы предоставляете более одного именованного аргумента.Поскольку вы предоставляете только один (Filename
), запятую не нужно, и это приводит к тому, что вы получаете (несколько загадочный) «Именованный аргумент уже указан», ошибка времени компиляции.Excel считает, что вы пропустили , предоставив именованный аргумент в начале, до запятой.Уберите это, и он поймет, что вы хотели включить только один.
РЕДАКТИРОВАТЬ: Точное значение скобок в вызовах методов, и когда они требуются, эточто-то, что смущает даже давних пользователей VBA.Это относительно сложно, поэтому давайте посмотрим, насколько хорошо я могу объяснить это.(Те же правила также применяются к версиям Visual Basic до .NET, таким как VB 6.)
Простое правило заключается в том, что когда вы присваиваете результат функции переменной или другойобъект, вы всегда заключаете список аргументов в скобки. Итак, если бы у меня была функция с именем GetAge
, которая возвращала числовое значение, когда я указала имя и фамилию, я бы написала следующее:
Dim age As Integer
age = GetAge("John", "Smith")
В противном случае нет необходимости заключать аргументы в скобки. Это охватывает два возможных случая.Во-первых, когда вы вызываете подпрограмму («sub»), которая никогда не возвращает значение, и, во-вторых, если вы вызываете функцию (которая всегда возвращает значение), но не присваивает значение, возвращаетсялюбая переменная или объект.По сути, когда вы игнорируете значение, которое оно возвращает.Например:
''#Calling a subroutine
MsgBox "Hello World"
''#Calling the same function as above, but ignoring its return value
''# (this particular example is not very useful, but sometimes you'll do this)
GetAge "John", "Smith"
В качестве альтернативы вы можете выбрать как подпрограммы, так и функции, чье возвращаемое значение вы игнорируете , используя оператор Call
, который всегда требует переноса аргументов в скобках.,Лично я предпочитаю этот синтаксис, потому что он больше похож на другие языки, на которых я работаю, устраняет неоднозначность, когда требуются скобки, а когда нет, и делает вызовы внешних методов более явными в вашем коде.Для тех же двух примеров, которые приведены выше, код изменится на:
''#Calling a subroutine, but using the Call statement
Call MsgBox("Hello World")
''#Calling a function, but ignoring its return value
Call GetAge("John", "Smith")
И, наконец, на случай, если вы думаете, что получаете все это, есть еще одна возможность, которую вы должны понять.Если вы переносите аргументы в подпрограмму или функцию, возвращаемое значение которой вы игнорируете в скобках, и не используете оператор Call
, VBA будет интерпретировать аргументы как передаваемые значением (ByVal
) прив противном случае они обычно передаются по ссылка (ByRef
).Когда вы пишете вызов метода таким образом, компилятор автоматически переформатирует его для вас, демонстрируя разницу в том, как он интерпретируется:
''#The following line
MsgBox("Hello World")
''#will be re-formatted by the compiler to
MsgBox ("Hello World")
Обратите внимание на пространство, которое он добавил между именем метода иаргументы в скобках?Этот пробел указывает, что аргументы переданы ByVal
. сообщение в блоге Эрика Липперта по связанному вопросу, вероятно, объясняет эту проблему лучше, чем я.