Проблема с абсолютными координатами станицы.

Автор Kadet, 16 февраля 2022, 18:48

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

eeigor

Цитата: mikekaganski от 18 февраля 2022, 21:14Я представил в ответе #30 незаданное состояние аргумента как своего рода третье состояние
Да, я перечитал. Можно и так. Информации набирается много...
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

eeigor

Обращение через IsMissing сбрасывает состояние ошибки. Надо проверять код ошибки до этого.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

Kadet

Цитата: mikekaganski от 18 февраля 2022, 21:14Нет. Здесь только 2: 1 (True) и 0 (False). Поэтому число 2 (в примере) и не может быть присвоено типу Boolean.
Кстати, а как же результат ChekBox? Разве он не Boolean? А ведь он имеет три состояния.

Кстати, как-то проводил эксперименты с этим типом (Boolean). Присваивал ему разные значения. Точно не помню (а специально перепроверять не охота), но... все значения, кроме 0, переменная типа Boolean воспринимает как True. Конечно, могу ошибаться.

Kadet

#48
Цитата: eeigor от 18 февраля 2022, 21:43Обращение через IsMissing сбрасывает состояние ошибки. Надо проверять код ошибки до этого.
Согласен. Но это же дополнительный наворот. Нельзя ли вообще обойти без впадения в состояние ошибки, как было ранее.
Вот я о чём.

Допустим, как в примере выше - нужно проверить тип переменной, допустим - цифра или строка. Для этого по логике нужен всего один If ... ElseIf...
А в случае с IsMissing - бедьте любезны - многоярусная проверка, сначала проверка на IsMissing, а уж потом на строка/число. И даже в один If IsMissing(Var1) AND IsNumber(Var1) Then ... их не засунуть. Ошибку бьёт. Только - многоярусная проверка. Иначе никак.

Это печально.

Kadet

#49
И вообще, сама по-себе эта странная ошибка вгоняет меня в ступор. Зачем она? Для каких целей?
Почему на мой простой вопрос: не цифра ли это (If IsNumber(Var1) Then..), нельзя просто ответить - нет, не цифра, даже если эта переменная находится в состоянии неопределённости, как в случае с ориенталами. (Не объект ли, не строка ли). Зачем же вгонять при этом в ошибку?
Наверное, конечно, это не спроста, где-нибудь в высших сферах. Но мне, как обывателю, это не понятно и кажется избыточными сложностями.

eeigor

#50
Цитата: Kadet от 18 февраля 2022, 21:56Кстати, а как же результат ChekBox? Разве он не Boolean? А ведь он имеет три состояния.
1) Нет. Делайте так в коде, если надо присвоить результат состояния чекбокса чему-либо:
= CBool(chkSomething.State)

2) А вот так я присваиваю чекбоксу на листе его же значение по событию (щелчок пользователя):
chkSomething.State = Abs(oEvent.Source.chkSomething)  'Source = ThisComponent
Это для чекбокса, не связанного с ячейкой (там всё просто).
Если я не забыл чего. У чекбокса, вроде, 3 состояния, но это не -1, 0, 1, как следовало бы ожидать, а 0, 1, 2.

В первом случае надо преобразовать ту же двойку в 1 (True). Во втором: преобразовывает -1 в 1.
Я понимаю, о чём Вы говорите: сам помучился.

В Excel тройственное состояния (triple state) - это: -1, 0, Null

Цитата: Kadet от 18 февраля 2022, 21:56...переменная типа Boolean воспринимает как True.
Так и есть.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

mikekaganski

#51
Цитата: Kadet от 18 февраля 2022, 22:19
И вообще, сама по-себе эта странная ошибка вгоняет меня в ступор. Зачем она? Для каких целей?
Почему на мой простой вопрос: не цифра ли это (If IsNumber(Var1) Then..), нельзя просто ответить - нет, не цифра, даже если эта переменная находится в состоянии неопределённости, как в случае с ориенталами. (Не объект ли, не строка ли). Зачем же вгонять при этом в ошибку?

А вот это совсем другой вопрос. Is*-функции совсем не обязаны ошибаться на missing optional. Но кто Вам сказал, что IsNumeric ошибается на этом? Он прекрасно возвращает False при передаче в него missing optional, включая фиксированные типы. Так что пафос вопроса не вполне ясен. В какой версии ошибка? Или всё это даже без проверки работоспособности?

Или речь о какой-то своей IsNumber, которая совсем не IsNumeric?

Цитата: Kadet от 18 февраля 2022, 14:48
Sub WriteTable(oSheet AS Object, oRow%, oCol%,_
Optional Var0 As Variant, Optional Var1 As Variant, Optional Var2 As Variant, Optional Var3 As Variant,_
...
Optional Var28 As Variant, Optional Var29 As Variant, Optional Var30 As Variant, Optional Var31 As Variant)

If IsNumeric(Var0) Then
If Var0 <> 0 Then oSheet.getCellByPosition(oCol+0, oRow).setValue(Var0)
Else
If Var0 <> "" Then oSheet.getCellByPosition(oCol+0, oRow).setString(Var0)
End If

...
End Sub

...
Раньше представленный выше вариант прекрасно работал, т.е. проверял неопределённую переменную на нумерик или нет и делал своё дело.

Ещё раз посмотрим сюда.

If IsNumeric(Var0) Then
If Var0 <> 0 Then oSheet.getCellByPosition(oCol+0, oRow).setValue(Var0)
Else
If Var0 <> "" Then oSheet.getCellByPosition(oCol+0, oRow).setString(Var0)
End If


Проблема не в IsNumeric, который честно отрабатывает на незаданном аргументе, а в ветви Else, которая обращается к значению незаданной переменной в операторе сравнения <>.

Причём в данном конкретном случае код неверен в любом диалекте Basic, в т.ч. в VBA. Вы всё пытаетесь доказать, что код осмысленный с человеческой точки зрения, но это не так. Определение Optional ("опциональный", которое Вы настойчиво обзываете "ориенталом" - при чём тут восток?) концептуально не позволяет так работать.
С уважением,
Михаил Каганский

Kadet

Цитата: mikekaganski от 19 февраля 2022, 09:58Но кто Вам сказал, что IsNumeric ошибается на этом?
Мне никто не говорил. Я проверял это на "собственной шкуре". Не однократно тестировал и искал выход из подобной фигни. Проверял подобные переменные на все Is*.
Проверю ещё раз, но ранее эта ситуация безвыходности меня сильно бесила.

Kadet

Цитата: mikekaganski от 19 февраля 2022, 09:58Проблема не в IsNumeric, который честно отрабатывает на незаданном аргументе, а в ветви Else, которая обращается к значению незаданной переменной в операторе сравнения <>.
С этим согласен. Else написано не корректно.
Но выбивало ошибку именно на строке If IsNumeric(Var0) Then, а не на Else. С объяснением - "переменная должна быть задана".
Проверю ещё раз, но... если память не изменяет было именно так. Поэтому везде пришлось ставить IsMissing

eeigor

#54
Памятка по ссылке от Михаила (в моём переводе) решила мои проблемы с опциональными переменными. Всё понятно, хотя и многообразно. Если надо использовать значения по умолчанию, то для этого есть функция CompatibilityMode() для включения режима Compatible на время выполнения кода процедуры. Есть особенности вызова UDF из ячеек листа (пропущенный аргумент не будет считаться отсутствующим, если дальше через точку с запятой есть что-то ещё (другой параметр).
A1: =UDF(arg1;;arg3)
В Basic при таком вызове arg2 (по порядку) is missing, а на листе Calc – нет. Если Вы ещё окончательно не запутались  :)

Edit: Для режима VBASupport лучше использовать отдельный модуль из иной "парадигмы" использования опциональных аргументов. Иногда использую, когда надо работать с диапазонами Excel на листе Calc.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

Kadet

#55
Проверил. Действительно. Все Is* с неопределившимися переменными после Optional отпрабатывают без ошибок.
Sub Main
Test()
End Sub

'*******************************
Sub Test(Optional Var1)
Dim sStr$
ON LOCAL ERROR GOTO Error1:
sStr = "IsMissing"
If IsMissing(Var1) Then GoTo Jamp::
sStr = "IsArray"
If NOT IsArray(Var1) Then GoTo Jamp::
sStr = "IsDate"
If NOT IsDate(Var1) Then GoTo Jamp::
sStr = "IsEmpty"
If NOT IsEmpty(Var1) Then GoTo Jamp::
sStr = "IsNull"
If NOT IsNull(Var1) Then GoTo Jamp::
sStr = "IsNumeric"
If NOT IsNumeric(Var1) Then GoTo Jamp::
sStr = "IsObject"
If NOT IsObject(Var1) Then GoTo Jamp::
sStr = "IsUnoStruct"
If NOT IsUnoStruct(Var1) Then GoTo Jamp::
sStr = "TypeLen"
' If TypeLen(Var1) Then GoTo Jamp::
sStr = "TypeName"
' If TypeName(Var1) Then GoTo Jamp::
sStr = "VarType"
' If VarType(Var1) Then GoTo Jamp::

GoTo Jamp:
Error1:
ON LOCAL ERROR GOTO 0
MsgBox "Ошика на проверка - " & sStr
GoTo Jamp1:
Jamp:
MsgBox "Без ошибок на - " & sStr
Jamp1:
End Sub

Приношу свои извинения за дезинформацию.

Но почему же тогда я везде, где есть опционалы вставлял IsMissing-и?! Напрягался, вставлял, трудился... Не спроста же. Не помню уже.
Но, с чем-то в этом плане были немыслимые мучения, когда я пытался проверять тип каких-то переменных... Выдумывал методы обхода подобных ситуаций.
Может с чем-то путаю. Или тот баг уже исправили. Не знаю. Теперь все Is* работают нормально.

Kadet

#56
Цитата: eeigor от 19 февраля 2022, 12:38Если Вы ещё окончательно не запутались
Уже... уже... и безвозвратно.

Понял так, что при использовании оптионалов в Basic обязательно в процедуре нужно использовать:
- либо CompatibilityMode();
- либо IsMissing(var);
- либо ***(Optional VAR as Boolean = False).
По другому никак.

Вот так я всё это понял.

Kadet

Кстати, а как же там дела с нашим масштабированием (основная тема темы)?
Смотрю в багзиле не проявляется интерес в этому вопросу. Арман Ле Гранд (автор сего непорядка)  :'(сидит в своём Турине, и не обращает на это никакого внимания.
Жаль. Значит придётся обходиться без выпендрёжей.

sokol92

На неподготовленного читателя темы эти "ужасы"  могут произвести сильное воздействие.

Если Вы создаете программный комплекс, то нужно для себя определить дисциплину программирования и ее придерживаться.
Никому не навязывая свою точку зрения (что для меня нетипично  :)), сформулирую некие предложения.

1. Об использовании или неиспользовании Option Compatible и Option VBASupport 1.

Всегда используем один из этих двух режимов, если только у нас нет ностальгии по cтарым версиям OO.

Используем Option VBASupport 1, если:
a. У нас есть унаследованный код из VBA (который приемлемо для нас работает в Basic) или мы создаем код, который предназначен как для Basic, так и для VBA.
b. Мы используем конструкции, который работают c  Option VBASupport 1 и не работают c Option Compatible. К ним относится ряд полезных функций (InStrRev и др.), которые дискриминированы по непонятным причинам, объект VBA Err, позволяющий более комфортно работать с обработкой ошибок, ...

В остальных случаях используем Option Compatible.

2. Использование конструкции Byval.

Всегда используем эту конструкцию для неизменяемых (входных) параметров.
Лучше вообще отказаться от изменяемых в ходе макроса параметров  для функций, которые могут вызываться "извне" (аналогичную рекомендацию дают разработчики Python). Функция может возвращать не одно, а массив значений, и это будет работать при вызове этой функции из других языков программирования.
Можно использовать ByRef для "локальных" ("Private") функций.

3. Обработка Optional параметров (Optional Compatible).
Можно в самом начале макроса для каждого такого параметра применить функцию IsMissing и, возможно, присвоить опущенному параметру некоторое значение.

4. Определение подтипа параметра типа Variant.
Ни в коем случае не используем IsNumeric и IsDate. Эти функции возвращают результат, зависящий от локали. К вашим услугам проверенные бойцы VarType и TypeName, а также IsObject, IsArray. Проанализируйте пример:

Option Compatible
Sub Mysub(Optional ByVal arg)
  Msgbox IsNumeric(arg) & Chr(10) & VarType(arg) & " " & TypeName(arg)
End Sub

Sub Test
  Mysub "1.2"
  Mysub "1,2"
  Mysub
End Sub


Владимир.

mikekaganski

#59
Цитата: eeigor от 19 февраля 2022, 12:38Есть особенности вызова UDF из ячеек листа (пропущенный аргумент не будет считаться отсутствующим, если дальше через точку с запятой есть что-то ещё (другой параметр).
A1: =UDF(arg1;;arg3)
В Basic при таком вызове arg2 (по порядку) is missing, а на листе Calc – нет. Если Вы ещё окончательно не запутались

Вот как раз упоминание синтаксиса формул Calc здесь совершенно неуместно и ведёт только к путанице. Когда Вы используете UDF в формуле, Вы работаете с Calc, и ЯП, на котором реализована UDF, не имеет никакого значения. Точно с тем же успехом можно начать сравнивать синтаксис формул Calc и C++, на котором написаны все встроенные функции. А в кальке единственный синтаксис незадания опционального аргумента - это в конце, без соответствующего разделителя. Как только разделитель появился - это не пропущенный, а заданный аргумент (если значение в таком случае не задано явно, оно равно нулю).

Такие сравнения подобны недавнему "багу" 147366, где пользователь перепутал функцию Log из Basic и LOG из Calc. Они не имеют друг к другу никакого отношения.

Как пример опущенного опционального аргумента:

=INDIRECT("A1")

А здесь он задан (и поэтому будет ошибка, поскольку значение по умолчанию 1, а здесь задан ноль, и значит, требуется ссылка R1C1):

=INDIRECT("A1";)
С уважением,
Михаил Каганский