Kadet
|
Вчера поставил обновление LO 7.2.4.1 После этого часть формул, создаваемых макросом в листе calc, стали выдавать ошибку. Причём как-то странно - в одних случаях формула продолжает работать с других нет. Вот такую формулу создаёт макрос (oVK = 5 (intager)): oSheet.getCellByPosition(14, oRow).setFormula("=C701*" & oVK/100) Она перестала работать. Нашёл такой выход, как всегда обходной: oSheet.getCellByPosition(14, oRow).setFormula("=C701*" & oVK & "/100") Эта формула прекращает работать в тех случаях если используется формат ячейки C701 с разделителями разрядов тысяч и если это значение больше тысячи (т.е. появляется пробел между тысячами и пр.). Пока число меньше тысячи формула работает. Появляется пробел разделителя - появляется ошибка "=#ИМЯ". Регресс, однако.
|
|
|
Записан
|
|
|
|
mikekaganski
|
Это не регресс, а прогресс. Конкретно - это исправление бага 97983, где раньше простое приведение числа к строке не использовало параметры локали. Раньше было так: dim s as string dim d as double d = 1.5 s = d ' s = "1.5" независимо от текущей локали!!! d = s ' d = 1.5 в локали en-US, и d = 1 в локали ru-RU, потому что в последней превращение строки в число правильно использовало локаль!
Теперь: dim s as string dim d as double d = 1.5 s = d ' s = "1.5" в локали en-US, и s = "1,5" в локали ru-RU d = s ' d = 1.5
При этом, как и раньше, локаль-независимые преобразования строк в числа и обратно должны производиться с помощью функциq Val/ Str. См. руководство по Basic. А setFormula как раз и устанавливает локаль-независимую формулу, и поэтому все числовые литералы там должны использовать точку. oSheet.getCellByPosition(14, oRow).setFormula("=C701*" & Str(oVK/100))
|
|
|
Записан
|
|
|
|
Kadet
|
Интересненький "прогресс". То, что были проблемы с локалями это факт. Из-за неё мне часто приходится в своих макросах испрользовать подмены типа var = replace(var1,",",".") Если это исправлено, то это прекрасно. Однако, странное дело таки с этим "прогрессом". Простая матемематическая формула - oVK/100, перестала работать. Причём действительно в совокупности с разделителями тысяч. Засомневался в своей версии про разделители, ведь исправление "oVK/100" на "oVK & "/100"" дало положительный результат, а оно меняет разделители дробной части, а не тысячные. В общем, попробовал проверить так: Dim dVK# dVK = oVK/100 oSheet.getCellByPosition(14, oRow).setFormula("=C701*" & dVK) Не алё. Результат - ошибка. Если после формирования страницы calc вручную обновить ссылку на ячейку C701, при первичном варианте формулы (т.е. - ""=C701*" & oVK/100"), то ошибка уходит. Вариант с "Str(oVK/100)" работает. Однако, странное "улучшение", с усложнением. Нужно ещё проверять не испортились ли формулы в других местах программы. Пока выявил в одном месте, но из же гораздо больше.
|
|
« Последнее редактирование: 8 Декабрь 2021, 12:57 от Kadet »
|
Записан
|
|
|
|
mikekaganski
|
В общем, попробовал проверить так: Ну ок, я понял, что не было смысла приводить правильный вариант строки Basic и объяснять, раз это всё игнорируется. То, что были проблемы с локалями это факт. Но то, что Вы привели как "проблемы с локалями", является просто неумением работать с ними.
|
|
« Последнее редактирование: 8 Декабрь 2021, 13:01 от mikekaganski »
|
Записан
|
|
|
|
Kadet
|
"Правильный вариант", насколько я понимаю, был проверен и подтверждён, и даже отзыв об этом описан. Не так? Просто ДО появления "правильного" варианта были проведены тесты других вариантов. Что и описано. Однако, что скрывается за: является просто неумением работать с ними ? Когда я беру данные из ячейки calc, где по локали дробное число представляется через запятую, и пытаюсь его засунуть в БД, у которой по умолчанию и неизменно разделитель дробной части является точка и ничто другое, в итоге получаю ошибку, пока не проведу replace переменной с переводом её в Str. В чём "неумение"?
|
|
« Последнее редактирование: 8 Декабрь 2021, 13:17 от Kadet »
|
Записан
|
|
|
|
mikekaganski
|
Я уже описал: для локаль-зависимых преобразований используются одни методы, для независимых - другие. Даже ссылку дал на документацию. Использование replace для этого неправильно.
|
|
|
Записан
|
|
|
|
Kadet
|
Да даже любое математическое получение дробного числа типа doeble в макросе, допустим как результат математической функции, тоже приходится прогонять через replace чтобы подать его в SQL запрос.
|
|
|
Записан
|
|
|
|
Kadet
|
...зависимых преобразований... ...независимых... Для меня это абракадабра. Не понимаю о чём речь. Со ссылкой и без неё - не понимаю. Тем более в английской версии.
|
|
« Последнее редактирование: 8 Декабрь 2021, 13:24 от Kadet »
|
Записан
|
|
|
|
Kadet
|
Чего уж тут понимать? Раньше функция Str в принципе не работала. Поэтому всеми силами старался её избегать или обходить с финдиперсами. Много крови попила. Зато простая банальная "неправильная" математика внутри формулы, как -то (""=C701*" & oVK/100") - работала и кушать не просила.
А теперь... всё наоборот. Теперь, однако, без Str уже не обойтись.
|
|
« Последнее редактирование: 8 Декабрь 2021, 13:49 от Kadet »
|
Записан
|
|
|
|
mikekaganski
|
Когда Вы работаете с числами и строками, первое, что необходимо понять - это что число может быть представлено разными строками, а разные строки, представляющие одно и то же число, могут быть по-разному восприняты в разных случаях. Это связано с богатой историей человечества, письменности, математической записи и других увлекательных вещей. В принципе это всё зависит от локали (то есть от соглашений по представлению данных, принятых в данной местности или в данной ситуации).
Понимание этого приводит нас к понятию текущей локали. Обычно это то, что представляется "обычным/нормальным" простому пользователю Вашей программы: например, использование запятой для разделения дробной части в России. В Basic стандартные преобразования все задуманы использующими именно текущую локаль - то есть все стандартные преобразования должны в России считать дроби отделяющимися запятой.
Однако при программировании имеется множество вещей, которые не должны зависеть от локали. Например, если Вы формируете формулы и будете их писать для Вашей русской локали, с использованием русских названий функций и т.п., то программа не будет работать в других локалях. Поэтому программист должен думать о том, в каком месте программы у него данные в текущей локали, а в каком - должны быть независимы от текущей локали. Это основы, без этого понимания всегда возникают проблемы.
В ЛО был баг, что стандартное преобразование числа в текст всегда использовало "стандартную" локаль en-US, а стандартное преобразование текста в число - текущую локаль. Это было несоответствие документации и дизайну. Это и было исправлено. А для приобразования любого числа в стандартный вид (независимо от локали в строку с использованием точки для разделения целой и дробной частей) - всегда были функции Str и Val. Надо преобразовать строку, введённую пользователем, в число - используем стандартное преобразование (просто присваиваем строку числовой переменной). Надо взять число из базы данных, где числа в стандартной форме - используем Val(s). Надо число показать пользователю - используем стандартное преобразование (например, просто передаём число в MsgBox), что даст привычный для пользователя вид. Надо число засунуть в формулу Calc, где используется стандартный вид - используем Str(n).
Ну и всегда для преобразований с использованием локали (то есть вместо стандартных преобразований) можно было использовать функции CStr/CInt/CDbl/...
То, что Вы полагались на нестандартное, ошибочное поведение в одних местах, и страдали от того же самого в других - это и был баг, который полностью рушил логику преобразований. Исправление ничего не усложнило. Если бы Вы использовали Str/Val/CStr/CDbl... везде, где данные преобразуются между типами (число-строка), Вы даже не заметили бы ничего.
А использовать replace для того, что Вы делаете - нельзя, потому, например, что в некоторых локалях запятая - это разделитель тысяч.
|
|
« Последнее редактирование: 8 Декабрь 2021, 14:06 от mikekaganski »
|
Записан
|
|
|
|
mikekaganski
|
Раньше функция Str в принципе не работала Это когда она не работала?
|
|
|
Записан
|
|
|
|
Kadet
|
Это когда она не работала? Это когда при d=1,5 она делалось d = 1. А зачастую просто давала ошибку. Приходилось от неё избавляться. И началось это не так давно. В общем пришлось выискивать и проверять все входы этой функции. В общем, с какого-то времени я стал избегать и даже побаиваться этой Str. А теперь - всё наоборот. Спасибо за лекцию, но всё это понятно и известно. Мне в принципе не понятно какие математические функции могут быть независимы от локали. Разве что 1+1. Мне больше не понятно почему перестала работать вариация "на свободную тему" - "=C701*" & oVK/100. По сути я передаю ячейке строку "=C701* плюс числовое дробное значение - (допустим = 0,05), как результат вычисления - oVK/100. И я не заморачивался с переводом в Str и с локалями. И транслятор Bacic сам всё это переводил в удобный для себя формат... и это работало. И теперь, почему-то, транслятору нужно "чётко говорить" - "переведи в Str", хотя раньше это было излишним.
|
|
« Последнее редактирование: 8 Декабрь 2021, 14:53 от Kadet »
|
Записан
|
|
|
|
mikekaganski
|
Ох.
Вы не понимаете, чем число 0,1 отличается от строки "0,1"?
|
|
|
Записан
|
|
|
|
Kadet
|
Если мне не изменяет память, то любое число типа double, при переводе через Str выбивало ошибку. Точно не помню с когда это началось. Возможно с выходом 7-ки, но не буду утверждать. Почему помню и говорю об этом? Потому что во многих своих SQL-запросах для занесения данных типа double в базу мне постоянно приходилось использовать подобный конструкт: Replace(Str(oSheet.getCellByPosition(14, oRow).getValue()), ",", ".") И таких "приколов" было просто тьма. А потом, в каокй-то момент всё пришлось переписывать и убирать все упоминания Str, ибо при каждом её упоминании неизменно давало ошибку.
|
|
|
Записан
|
|
|
|
Kadet
|
Вы не понимаете, чем число 0,1 отличается от строки "0,1"? Понимаю. Только не понимаю почему раньше транслятор сам переводил число, результат вычисления oVK/100 (т.е. число 0,05), в строку, переводя это в удобный для себя формат (по сути в 0.05 - с точкой), а теперь перестал. И теперь ему для этого потребовались конкретные указания программиста - "Str(oVK/100)"
|
|
« Последнее редактирование: 8 Декабрь 2021, 15:10 от Kadet »
|
Записан
|
|
|
|
|