Форум поддержки пользователей LibreOffice, Apache OpenOffice

Главная категория => Макросы => Тема начата: ost от 3 августа 2021, 16:10

Название: Странность с пропущенными параметрами.
Отправлено: ost от 3 августа 2021, 16:10
Доброго. Почему фактически пропущенный параметр таким не является?
При запуске test1 из файла по ссылке получаю сообщение. Почему так? На деле параметр "sArg1" пропущен.

https://yadi.sk/i/9OwKklryqrODGA
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 16:27
Optional может быть missing-объектом только если это Variant, у которого есть соответствующее состояние (по факту это значение - особого вида ошибка, что и можно проверить). Иначе - в случае явно заданных типов - переменная всегда имеет одно из допустимых значений для данного типа. По умолчанию пропущенное значение Optional-аргумента с фиксированным типом получает значение по умолчанию для данного типа (например, пустую строку для случая строкового аргумента).
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 16:37
Не соглашусь с Михаилом: описано абсолютно правильное поведение... но для VBA.

«например, пустую строку для случая строкового аргумента».
Увы, и со строковым нулем ("0") тоже приходится сравнивать, если использовать на листе.

Здесь, похоже, StarBasic "недоделан", работает непостоянно (до конца не исследовал, поднимал на англоязычном форуме – вопросы остались). К тому же, если пропущены аргументы в UDF на листе, то всё тоже неоднозначно... Другими словами, Optional – это тема отдельного «исследования», которую я начинал, но ещё не завершил...

Upd
Нужна тестовая книга с примерами, которая «разъяснит» все нюансы. Моя – в процессе... Если у кого есть, выкладывайте.

https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=105086
Название: Re: Странность с пропущенными параметрами.
Отправлено: ost от 3 августа 2021, 16:40
Доходчиво. Спасибо. Нашел сейчас это сообщение и ссылку в нем. https://forumooo.ru/index.php/topic,8645.0/msg,58330.html
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 16:59
На сегодня самый безопасный, но «неэффективный» способ работы с необязательными аргументами в StarBasic – это инициализация соответствующей внутренней переменной в соответствии со значением переданного параметра. Так делают другие. Лично меня «напрягает» этот «двойной комплект» переменных в теле процедуры. В VBA всё и всегда в этом отношении работало безукоризненно, как Михаил и описал. Но то, что здесь это далеко не так, для меня очевидно: спотыкался неоднократно.
Название: Re: Странность с пропущенными параметрами.
Отправлено: sokol92 от 3 августа 2021, 17:04
Давайте продолжим дискуссию. TestSub (по ссылке из #4) по-прежнему (LO 7.1.5.2) выдает True. Если Mysub в TestSub вызвать с параметром, то выдается False.
Для удобства продублирую:

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

Sub TestSub
 Mysub
End Sub


На мой взгляд, возможность узнать, опущен ли параметр любого типа - это хорошо.
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 17:10
https://git.libreoffice.org/core/+/8e323fcacebad1afe9d867b846722a6b9bf20f78

Всё зависит от режима (их три).
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 17:12
Я тоже за продолжение дискуссии. Из-за этой «темы» многие мои «наработки» выглядят незавершёнными. Речь о UDF, работающих с родными диапазонами в коде и принимающих «неродные» Excel Range на листе при выборе их пользователем мышкой в ходе ввода параметра (Option Compatible).
При такой вариативности использования UDF с прочими строковыми, логическими необязательными параметрами возникают проблемы. С численными проблем меньше.

Строковый необязательный параметр, к примеру, надо проверить на IsMissing(), на <> "0", на <> "". В общем, невесело...

Прим. "0" – это видение пропущенного параметра при использовании на листе. Как пустые ячейки интерпретируются как ноль, так и пропущенный строковый параметр – "0" (ноль в кавычках).

Upd
Михаил, Вы удалили своё сообщение, но там были ссылки по теме, которые я не успел просмотреть (один, даа, три, четыре). Не могли бы опубликовать ссылки заново?
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 17:24
Цитата: ost от  3 августа 2021, 16:10
Доброго. Почему фактически пропущенный параметр таким не является?
При запуске test1 из файла по ссылке получаю сообщение. Почему так? На деле параметр "sArg1" пропущен.

Всё не так.

Во-первых, о дискуссии. Всё чётко описано по ссылке на исправление, приведённой в #6. Если до этого оно работало нестабильно, начиная с версии 7.0 должно работать, как указано там. Дискуссия окончена.

Теперь о файле из начального сообщения.
Там используется нативный режим (без Option Compatible или Option VBASupport). При этом доступны правильные Missing-переменные любого типа (вопреки тому, что я написал в #1; также они доступны при использовании Option Compatible - но там возможны и явно заданные значения по умолчанию). Однако у Вас используется синтаксис test2(sArg2:="Arg2"), которые не работает в нативном режиме - так что значение "Arg2" передаётся в первый по порядку аргумент. Баг в том, что мы должны по-хорошему выдать ошибку компиляции на := без поддержки расширений (не уверен, должно это быть Option Compatible или Option VBASupport).
Похоже, что баг всё-таки в обработке синтаксиса :=, который должен работать в нативном режиме: https://help.libreoffice.org/7.3/en-US/text/sbasic/shared/01020300.html?&DbPAR=BASIC&System=WIN
Название: Re: Странность с пропущенными параметрами.
Отправлено: sokol92 от 3 августа 2021, 17:28
Цитата: mikekaganski от  3 августа 2021, 17:10Всё зависит от режима (их три)
Режимы я смотрел (всегда работаю c Option Compatible). Если задан режим VBASupport 1, то, да, IsMissing (похоже) работает только для Variant.

Что касается разницы между поведением тестов в стартовом сообщении и #5, то, мне кажется, разница в том, что стартовом сообщении пропущен первый необязательный параметр из двух, а в #5 необязательный параметр один.
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 17:33
Да, три режима. Плюс использование на листе. Ведь если «пропустить» необязательные аргументы, поставив серию точек с запятой, будут ли они действительно пропущены? Или как-то интерпретироваться иначе? И теперь всё это в трёх режимах. Поэтому об «исследовании» этой темы я и говорил выше. В VBA этой проблемы нет, и режим только один!
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 17:38
"Использование на листе" (по-видимому, описывается "использование в качестве UDF") - совершенно не относится к работе Basic, и связано с работой Calc, у которого нет в принципе возможности пропустить необязательные параметры перед явно заданными - см., например, комментарий к STYLE (https://help.libreoffice.org/latest/en-US/text/scalc/01/04060109.html?DbPAR=CALC#bm_id3149425). Поэтому нет никакого "и теперь всё это в трёх режимах".
Название: Re: Странность с пропущенными параметрами.
Отправлено: sokol92 от 3 августа 2021, 17:39
Цитата: mikekaganski от  3 августа 2021, 17:24Похоже, что баг всё-таки в обработке синтаксиса

В стартовом сообщении если написать

test2(,"Arg2")

то, вроде, все нормально.

Мне кажется, я сталкивался с проблемами, когда указан необязательный параметр, перед которым есть пропущенный необязательный параметр. Постараюсь воспроизвести.
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 17:44
 Много всего... интересного. Эта «мутная» тема достойна прояснения и обобщения, ибо важна для работы с макросами.
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 17:49
Михаил, за ссылку спасибо. Один вопрос можно считать разъясненным.

In the LibreOffice Calc functions, parameters marked as "optional" can be left out only when no parameter follows. For example, in a function with four parameters, where the last two parameters are marked as "optional", you can leave out parameter 4 or parameters 3 and 4, but you cannot leave out parameter 3 alone.

Отсюда и появляются строковые нули "0", или же пользователь должен явно ввести "".

Upd
Кстати, как с эти в Excel, не могу сказать. Не помню. Нет компьютера под рукой.
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 18:01
@ost: tdf#143706 (https://bugs.documentfoundation.org/show_bug.cgi?id=143706)
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 18:08
Ещё раз перечитал ветку по ссылке в ответе #2.
Вопрос за вопросом на примере использования логической переменной.
И вот совет:
«Try to use two variables to handle the optional parameter».

О чём я и писал выше: двойной комплект переменных. Пытаюсь уйти от этого...
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 18:18
И причём тут тот бессмысленный совет?
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 18:25
А при том, что это и есть абсолютно работающий во всех режимах единственный (простой) вариант использования опциональных переменных в StarBasic – одна переменная для переданного параметра (сам параметр процедуры), а другая для использования в теле после анализа входного параметра*. По другому не так просто, со всеми особенностями. Во всяком случае совет дан старожилом форума.

А.Питоньяк тоже использует этот приём: passed – inner

Что и как для трёх режимов и отдельно на листе (UDF) нигде не описано: собираем по крохам.

Upd
* После анализа входного параметра (Variant) мы наконец-то можем присвоить значение внутренней переменной конкретизированного типа данных. Потому что "Optional bVariable As Boolean" – совсем не то, что вы можете ожидать и с чем можете столкнуться (по моей ссылке выше на англоязычный форум всё начинается с разбора этой ситуации).
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 18:48
Как этот метод отличается по результату от

Sub Foo(Optional Bar As Boolean)
 If IsMissing(Bar) Then Bar = True
End Sub


в любом режиме?
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 18:59
Ну, у меня было так, как описал:

«2. Function UDF(Optional bStatus As Boolean)
 If IsMissing(bStatus) Then: End If

And bStatus will automatically be set to False after calling the IsMissing function. Why?
 If IsMissing(bStatus) Then bStatus = True

Alas, the missing parameter after the call to the IsMissing function is set to False and is no longer considered missing and will not be assigned a new value of True. Is this a bug?»

Версии ПО разные, конечно, но исходя из того, что я описал, вторая часть условия (Then) никогда не будет выполнена, потому что обращение к отсутствующему параметру автоматически устанавливает его значение в FALSE, и TRUE уже не присвоить.
Название: Re: Странность с пропущенными параметрами.
Отправлено: sokol92 от 3 августа 2021, 19:08
Михаил, спасибо за описание бага.

Итак, уточним текущее состояние дел для макросов Basic.

1. В родном режиме (без Option Compatible, Option VBASupport)

  При пропуске необязательного (Optional) параметра любого типа функция IsMissing(arg) возвращает True, функция IsError(arg) возвращает True, при преобразовании параметра в строку выдается "Error 448". Естественно, дальнейшее использование такого параметра сопряжено с проблемами.
Присвоение необязательным параметрам значения по умолчанию режим не допускает.

2. Option Compatible
 
  При незадании значения по умолчанию - так же, как в предыдущем пункте. Если в шапке функции задан параметр по умолчанию, то IsMissing(arg) возвращает False (и, таким образом, нет возможности узнать, пропущен параметр при вызове функции или указан явно со значением по умолчанию).

3. Option VBASupport 1

  При пропуске необязательного параметра любого типа, кроме Variant, функция IsMissing(arg) выдает False, параметр инициализируется значением по умолчанию. Если значение по умолчанию не задано, то присваивается 0 для числовых типов, пустая строка для строк, false для логических и т.д.
  При пропуске необязательного параметра типа Variant, у которого не задано значение по умолчанию,  функция IsMissing(arg) возвращает True, функция IsError(arg) возвращает True, при преобразовании параметра в строку выдается "Error 448" (так же, как и в других режимах). Если параметр имеет значение по умолчанию, то IsMissing(arg) выдает False, параметр инициализируется значением по умолчанию.
  Поведение в этом режиме, на мой взгляд, соответствует VBA.

  Неожиданно обнаружил в этом режиме "баг" (?). Если значение параметра типа Variant по умолчанию 1 (или другое целое число), то аргумент преобразуется в строку и добавляется знак процента ("1%"). Сейчас отрапортую (tdf#143707 (https://bugs.documentfoundation.org/show_bug.cgi?id=143707)).


  Прикладываю "стенд" для дальнейших испытаний.

Option Explicit
Option Compatible

Sub Mysub(Optional ByVal arg1 As String, Optional ByVal arg2 As Long=0)
 Dim v As Long
 Msgbox "arg1: IsMissing " & IsMissing(arg1) & " IsError=" & IsError(arg1) & " " & arg1 & Chr(10) & _
        "arg2: IsMissing " & IsMissing(arg2) & " IsError=" & IsError(arg2) & " " & arg2
 v=arg1+1      
End Sub

Sub Test
 Mysub
 ' Mysub  ,2
End Sub  
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 19:14
Ошибка 448 «пролетает» незаметно и существенных проблем, однако, не создаёт.
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 19:16
Цитата: eeigor от  3 августа 2021, 18:59
Ну, у меня было так, как описал:

Так Вы не описали. Это просто набор букв. Что может значить, например, "And bStatus will automatically be set to False after calling the IsMissing function". Чему равен bStatus до вызова? Что вернёт сам вызов? Если IsMissing(bStatus) возвратит False, то неважно, будете Вы в ветви If True присваивать значение переменной bStatus или bInnerStatus - ни то, ни другое не выполнится. Если же возвращается True, то неважно, изменил вызов IsMissing значение bStatus или нет.

А может быть, тут вообще что-то другое имеется ввиду? Но это именно то, о чём пишу: ничего не описано.
Название: Re: Странность с пропущенными параметрами.
Отправлено: sokol92 от 3 августа 2021, 19:18
Цитата: eeigor от  3 августа 2021, 19:14Ошибка 448 «пролетает» незаметно и существенных проблем, однако, не создаёт.
Добавьте к этой переменной, например, 1.
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 19:23
Михаил, во всяком случае у меня до TRUE «дело» не доходит:

Sub Foo(Optional Bar As Boolean)
 If IsMissing(Bar) Then Bar = True
End Sub

PS. Я пишу со смартфона и излагаю настолько подробно, насколько возможно. А ссылку давал на целую ветку с примерами и и.п.

Upd
Но и уже очевидно, что мой «прогноз» на необходимость исследование «этой темы» имеет под собой «основания. Всё очень непросто
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 19:25
Цитата: sokol92 от  3 августа 2021, 19:08При пропуске необязательного (Optional) параметра любого типа функция IsMissing(arg) возвращает True, функция IsError(arg) возвращает True, при преобразовании параметра в строку выдается "Error 448". Естественно, дальнейшее использование такого параметра сопряжено с проблемами.

Обратите внимание на важный специальный случай использования такого значения:
Sub Foo(Optional Arg)
 If IsMissing(Arg) Then MsgBox "Missing!"
  ...
End Sub

Sub Bar(Optional Arg)
 Foo(Arg)
End Sub

...
Bar


Передача опционального аргумента в функцию, принимающую опциональный аргумент, сохраняет состояние IsMissing (естественно, поскольку это просто специальное значение-ошибка).
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 19:27
Цитата: eeigor от  3 августа 2021, 19:23Но и уже очевидно, что мой «прогноз» на необходимость исследование «этой темы» имеет под собой «основания. Всё очень непросто

Непросто здесь только одно: отсутствие внятного описания проблемы. У меня всё работает, и должно работать. А если не работает - это баг.
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 19:35
Ну, проблема в общем-то ясна. Вы слышите @economist'a? Правильно, нет. Потому как нет таких проблем в среде, которую он использует. Шучу.

Sub Foo(Optional Bar As Boolean)
 If IsMissing(Bar) Then Bar = True
End Sub

Ваш пример, Михаил. Однако у меня до TRUE дело не доходит.
Вторая часть условия (Then) никогда не будет выполнена, потому что обращение к отсутствующему параметру автоматически устанавливает его значение в FALSE, и TRUE уже не присвоить.

Upd. Да, в режиме совместности
Option Compatible
Название: Re: Странность с пропущенными параметрами.
Отправлено: sokol92 от 3 августа 2021, 19:42
Цитата: eeigor от  3 августа 2021, 19:35Однако у меня до TRUE дело не доходит
Что не так в ответе #21?
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 19:47
@dokol92, спасибо, я позже посмотрю и протестирую с компьютером (через неделю)
Название: Re: Странность с пропущенными параметрами.
Отправлено: mikekaganski от 3 августа 2021, 19:49
Цитата: eeigor от  3 августа 2021, 19:35
Sub Foo(Optional Bar As Boolean)
 If IsMissing(Bar) Then Bar = True
End Sub

Вторая часть условия (Then) никогда не будет выполнена, потому что обращение к отсутствующему параметру автоматически устанавливает его значение в FALSE, и TRUE уже не присвоить.

Тогда подумайте и скажите, пожалуйста, как может быть, что

ЦитироватьFunction UDF(Optional bPassedStatus As Boolean)

dim bInnerStatus as boolean

  If IsMissing(bPassedStatus) then bInnerStatus = True

  REM Use the bInnerStatus in the next parts of the function...

Цитата: eeigor от  3 августа 2021, 18:25это и есть абсолютно работающий во всех режимах единственный (простой) вариант использования опциональных переменных в StarBasic – одна переменная для переданного параметра (сам параметр процедуры), а другая для использования в теле после анализа входного параметра*. По другому не так просто, со всеми особенностями.

Ведь до присвоения всё равно не дойдёт.

Разве что это карго-культ по причине того, что
Цитата: eeigor от  3 августа 2021, 18:25Во всяком случае совет дан старожилом форума.
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 3 августа 2021, 20:17
Михаил, чтобы невероятное стало очевидным, есть ещё два режима. Вернусь к этой теме позже
Название: Re: Странность с пропущенными параметрами.
Отправлено: eeigor от 10 января 2022, 21:30
Цитата: mikekaganski от  3 августа 2021, 17:10
https://git.libreoffice.org/core/+/8e323fcacebad1afe9d867b846722a6b9bf20f78

Всё зависит от режима (их три).
Заметил, что в "родном" режиме (без всяких опций) необязательный параметр не инициализируется значением по умолчанию, это так, но вот если задан тип данных, то он сохраняется. Значит, задание типа данных для необязательных аргументов имеет смысл.

Sub Foo(Optional bStatus As Boolean, Optional nIndex%, Optional nValue&)
   If IsMissing(bStatus) Then bStatus = 2
   Print TypeName(bStatus); "="; bStatus  '<< displays: Boolean=True, not Integer=2

   If IsMissing(nIndex) Then nIndex = True
   Print TypeName(nIndex); "="; nIndex  '<< displays: Integer=-1, not Boolean=True

   If IsMissing(nValue) Then nValue = "string"
   Print TypeName(nValue); "="; nValue  '<< displays: Long=0, not String=string
End Sub

В VBA опциональные параметры, проверяемые функцией IsMissing(), должны иметь тип Variant. В StarBasic - любой.