Basic: Optional параметры обрабатываются по разному

Автор eeigor, 29 апреля 2021, 05:56

0 Пользователи и 1 гость просматривают эту тему.

eeigor

Сделайте 2 одинаковых вызова PassParamsByType (с листа и из модуля) и сравните результат. Ну, Double – понятно, а остальное? Особенно, 0 вместо пустой строки (вызов из ячейки) и разные значения логической переменной.

1. Присвойте ячейке
A1: =PASSPARAMSBYTYPE(1;;;;;)

2. Выполните Test_PassParamsByTypeFromModule

Function PassParamsByType(pRequired _
, Optional pVariant, Optional pLong&, Optional pDouble#, Optional pString$, Optional pBoolean As Boolean)

  If IsMissing(pBoolean) Then
     pBoolean = True
  End If
  MsgBox "Parameters Passed" _
   & Chr(10) & "TypeName(pRequired):=" & TypeName(pRequired) _
   & Chr(10) & "pVariant:=" & pVariant _
   & Chr(10) & "pLong:=" & pLong _
   & Chr(10) & "pDouble:=" & pDouble _
   & Chr(10) & "pString:=" & pString _
   & Chr(10) & "pBoolean:=" & pBoolean _
   , , "macro:PassParamsByType"
End Function

Sub Test_PassParamsByTypeFromModule
  Call PassParamsByType(1 _
   , , , , ,)
End Sub


Баг

По уму, нужна заплатка – процедура, обрабатывающая необязательные параметры одинаково в любом случае. Сегодня надо использовать тип Variant и присваивать переданный параметр внутренней переменной... с некоторой избыточностью кода
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

sokol92

Я бы не торопился с этим примером.
Запустите его в Excel. Во-первых, синтаксис VBA не разрешает такого. Если мы запишем вызов функции как:

Call PassParamsByType(1, , , , , True)

то получим сообщение "Type mismatch", что, с моей точки зрения, справедливо.
Вызов параметров по ссылке означает, что Вы передаете параметры того же типа, что в прототипе функции (процедуры).

Другое дело, что у Basic в каких-то случаях "едет крыша" при пропуске необязательных параметров (две и более запятых подряд при вызове).

Пока накапливаю материал.
Владимир.

eeigor

Вот я пытаюсь разобраться и систематизировать. Давайте накапливать вместе.
Пусть это будет особенностью языка. Нужна только ясность. А то у меня одна и та же UDF привела к противоположным значениям опциональной логической переменной. Причём при отсутствии необязательного логического параметра он имеет сначала значение ошибки (Error 448), а после вызова функции IsMissing() ему автоматически присваивается значение False, и он перестаёт быть отсутствующим (Bug?), а значит не происходит вход в тело блока If и не удаётся присвоить отсутствующему параметру значение True. Нонсенс.

Ещё раз скажу: с переменной типа Variant и использованием второй внутренней переменной проблем, вроде, меньше. Только я так не делал в VBA.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

sokol92

В сопоставлениях с VBA нужно быть крайне осторожным. Смотрите (Basic, VBA):

Sub Mysub(Optional ByVal opt As Boolean)
  MsgBox IsMissing(opt)
End Sub

Sub TestSub()
  Mysub
End Sub


В VBA результат при вызове TestSub будет False, поскольку IsMissing имеет смысл только для переменных типа Variant.
В Basic результат будет True. Фактически вместо аргумента будет передано ошибочное значение. Я рекомендую всегда в начале любого макроса обрабатывать отсуствующие параметры явно:

If IsMissing(opt) Then opt=False

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