пользовательская функция Calc и пустая ячейка

Автор Yakov, 19 июля 2010, 20:03

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

Yakov

Вопрос из рассылки oo-discuss@openoffice.ru:
Есть задача, которая может быть решена пользовательской функцией на
Basic в OOo Calc. По смыслу задачи на вход могут подаваться и пустые
значения (логика их обработки описывается в функции). Однако, если в
качестве аргумента (параметра) пользовательской функции Basic передаётся
пустая ячейка, то OOo Calc подставляет значение 0 (ноль, типа Double).

В приложенном примере ячейка A3 пустая, а B3 в результате выполнения
функции, приведенной ниже, содержит "Double : 0."

Вот тестовая функция, демонстрирующая такое поведение Calc:
Function MyTest(Optional a as Variant) as String
If Not IsMissing(a) Then
MyTest = TypeName(a) & " : " & a
Else
MyTest = "Нет значения"
End If
End Function

Поиск у Питоньяка и в Google, а также вопрос на форуме i-rs.ru разумного
результата не дали. Есть у коллег какие-то решения? Обрабатывать ноль,
как пропущенное значение по условиям задачи нельзя: ноль является в
части случаев вполне допустимым входным параметром.

Кстати, обратите внимание, как обрабатывается дата; она тоже в функции
преобразуется к Double.

prof-alex


«Студентов, ранее изучавших Бейсик, практически невозможно обучить хорошему программированию. Как потенциальные программисты они подверглись необратимой умственной деградации» Э. Дейкстра

prof-alex

Похоже нужно обращаться к ячейкам из макроса напрямую, тогда можно анализировать три параметра value, string и formula. Оттуда видно пустая ячейка или там нулевое значение.

'Author: Sasa Kelecevic
'email: scat@teol.net
Sub ExampleGetValue
  Dim oDoc As Object, oSheet As Object, oCell As Object
  oDoc=ThisComponent
  oSheet=oDoc.Sheets.getByName("Sheet1")
  oCell=oSheet.getCellByposition(0,0) 'A1
  Rem содержимое ячейки может иметь один из следующих трех типов:
  Print oCell.getValue()
  'Print oCell.getString()
  'Print oCell.getFormula()
End Sub

«Студентов, ранее изучавших Бейсик, практически невозможно обучить хорошему программированию. Как потенциальные программисты они подверглись необратимой умственной деградации» Э. Дейкстра

Yakov

Цитата: prof-alex от 19 июля 2010, 20:54
Пример где?
Вот
http://lists.openoffice.ru/pipermail/oo-discuss/2010-July/022863.html
Почему-то с архива списка рассылки в виде bin скачивается,
прикрепляю файл


[вложение удалено Администратором]

dr.Faust

Цитата: prof-alex от 19 июля 2010, 20:28Похоже нужно обращаться к ячейкам из макроса напрямую, тогда можно анализировать три параметра value, string и formula. Оттуда видно пустая ячейка или там нулевое значение.
Да - только так.
Это уже изъезженная тема.
Однако тут возникают некоторые проблемы с пересчётом функции:
Мы можем отдать функции ячейку (пусть Б) содержащую адрес ячейки (пусть А), которую необходимо отслеживать, но тогда при изменении значения в ячейке А, функция не будет пересчитана, что печально...
Решаются они так:
Пусть ваша функция принимает 2 параметра - один ячейка Б (в ней адрес ячейки которую необходимо проверить на содержимое или формат (у меня был именно формат)), второй - ячейка А (отслеживаемый диапазон) второй параметр (полученный из ячейки А) можно негде в функции и не использовать - он нужен только для того, чтобы функция была пересчитана при изменении ячейки А.
Хотя это немного и коряво, зато работает.

Надеюсь я понятно изложил.
Свобода информации - свобода личности!

Рыбка Рио

#5
Можно так (только функцию нужно писать не MyTest(xx), а MyTest(cell("COORD",xx))

REM  *****  BASIC  *****

Function MyTest(Optional sa as String) as String
Dim fa As Object, a As Object, ars(1) As String
sa=Join(Split(sa,"$"),"")
ars()=Split(sa,":")
Sheet=ThisComponent.Sheets(asc(ars(0))-65)
cell=Sheet.getCellRangeByName(ars(1))
fa = CreateUnoService( "com.sun.star.sheet.FunctionAccess" )
ae = fa.callFunction("CELL", Array("TYPE", cell.DataArray))
If ae<>"b" Then MyTest = ae & " :   " & cell.Value else MyTest=""
End Function


[вложение удалено Администратором]
ubuntu 12.04 + LibO3.6.0

Рыбка Рио

Точнее, последнюю строчку лучше так записать:
If ae="l" Then
   MyTest = ae & " :   " & cell.String
elseif ae="v" then
   MyTest = ae & " :   " & cell.Value
else
   MyTest=""
Endif
ubuntu 12.04 + LibO3.6.0

smaharbA

Можно и только с range, но функция сложнее и вычисления медленнее

function myfunc(rangeStr,range)
doc = ThisComponent
sheet=doc.getcurrentcontroller.getActiveSheet
reg=sheet.getCellRangeByName(rangeStr)
dim s
s=""
rows=reg.getRows()
cols=reg.getColumns()
for i=0 to rows.count - 1
for n=0 to cols.count - 1
s=s & reg.getCellByPosition(n,i).String & chr(10)
next
next
myfunc=s
end function

=MYFUNC("A2";A2)
=MYFUNC("A2:C2";A2:C2)
Я конечно далек от мысли... (с)