Типовые варианты использования функций ISBL

10 7

Это третья статья из цикла, посвященного основам работы на ISBL. Ранее уже рассказывалось, что представляет собой ISBL и основы его синтаксиса. В этой статье будет рассмотрено несколько примеров использования функций ISBL.

Работа с функциями ISBL

Функция – это имя для некоторой последовательности операторов, используемое в текстах вычислений при вызове этих операторов.

Работа с функциями производится через компоненту Функции ISBL в Утилитах разработчика. Стандартная версия системы уже содержит ряд полезных функций, позволяющих без труда создать собственный код. Посмотреть список доступных для использования функций можно, открыв эту компоненту в системе. Для удобной навигации функции разбиты на группы.

Открыв карточку функции, можно просмотреть список передаваемых параметров. В таблице указаны их типы и значения по умолчанию. Если значение по умолчанию указано, параметр считается необязательным, иначе – обязательным.

Для большинства функций код открыт для разработчика. Для того, чтобы просмотреть или отредактировать код, необходимо нажать на кнопку Текст в карточке функции.  

Назначение каждой из функций можно посмотреть в справке, которая также доступна по кнопке Справка в карточке.

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

В рассмотренной выше функции единственный обязательный параметр, поэтому ее вызов будет осуществляться при помощи следующего кода:

AbsValue = Abs(Value)

В более сложной функции InputDialog() 8 параметров, все необязательные. Опустили 2, 5, 6, 7 и 8. Чтобы не нарушить порядок следования, необходимо между первым и третьим параметрами поставить две точки с запятой. После четвертого все параметры берем по умолчанию, поэтому точки с запятой в конце списка параметров можно не ставить.

Кроме использования уже готовых функций, ISBL дает возможность разрабатывать собственные прикладные функции. Для этого необходимо создать новую запись в компоненте Функции ISBL, задать имя функции, определить список ее параметров и написать текст.

Для обращения к параметрам в тексте функции необходимо использовать переменные, совпадающие с идентификаторами этих параметров. Изменение параметров внутри функции не приведет к их изменению в головной программе, так как параметры в функцию передаются по значению, а не по ссылке.

Для того чтобы функция вернула результат, необходимо использовать переменную, которая совпадает с именем функции, или зарезервированные переменные Result и Результат.

Работа с числами, строками, датами

Функции работы с числами, строками и датами можно найти в соответствующих группах.

Функций работы с числами достаточно много. Среди них функции нахождения модуля, округления, нахождения минимума и максимума двух чисел, функции проверки, является ли переменная числом или целым числом, функция вывода числа прописью и другие.

Рассмотрим пример, иллюстрирующий работу с несколькими функциями:

  // Ввести 2 числа
  InputData = InputDialog('Первое число|Второе число';;
                          'Число:0|Число:0'; 'Введите 2 числа')
  // Считать их
  a = SubString(InputData; '|'; 1)
  b = SubString(InputData; '|'; 2)

  // Проверить, являются ли они целыми числами
  if IsInteger(a) and IsInteger(b)
    // Первое умножить на разницу между первым и вторым и взять по модулю
    Result1 = abs(a * (a - b))
    // Второе разделить на 2, округлить до целых и взять по модулю
    Result2 = abs(Round(a / 2; 0))
    // Вывести максимальный из результатов прописью
    Result = AmountInWords(max(Result1; Result2))
  endif

Функций работы со строками тоже достаточно много. Среди них функции сложения и форматирования строк, функции работы с подстроками, функции поиска и замены и многие другие.

Рассмотрим пример, охватывающий сразу несколько функций работы со строками:

  // Задать строку
  StartString = '    Это СлоЖНо ЧiТаЕмаЯ сТРокА с веДущiМi ПроБеЛаМi i ЛаТiнiцей'
  // Удалить ведущие пробелы
  String = Trim(StartString)
  // Заменить латинскую "i" на русскую "и"
  String = Replace(String; 'i'; 'и')
  // Перевести в нижний регистр
  String = LowerCase(String)
  // Узнать длину строки...
  LengthString = Length(String)
  // ... и количество слов как количество подстрок разделенных пробелами
  CountWords = SubStringCount(String; ' ')
  // Сформировать выходное сообщение при помощи функции, подставляющей в шаблон значения из массива
  Message = Format('Исходная строка: %1:s%0:sПолученная строка: %2:s%0:s' &
                   'Длина строки: %3:s%0:sСлов: %4:s';
                   ArrayOf(CR; StartString; String; LengthString; CountWords))
  // Вывести полученный результат
  ShowMessage(Message)

Получили следующий результат: 

Работа с датами на ISBL осуществляется через функции соответствующей группы. Среди них функции получения времени и даты, функции сравнения дат, получения их разности в заданных единицах, представления дат в заданном формате и другие.

Рассмотрим пример: узнать, сколько дней осталось до нового года:

  // Получить текущую дату
  Today = Today()
  // Узать какой год будет следующим
  NextYear = FormatDate('Y'; Today) + 1
  // Получить первый день нового года
  NextYearFirstDay = '01.01.' & NextYear
  // Получить количество дней до нового года
  Result = DateDiff('D'; Today; NextYearFirstDay)

Работа с объектами, списками значений произвольного типа, списками строк

Основными единицами ISBL являются объекты системы. Объектами системы являются все справочники, сценарии, отчеты, документы, задачи и др. Работа с ними происходит через специальную объектную модель. Для их получения используются системный функции, имеющие формат наименования Create<тип>.

Рассмотрим пример работы с функцией CreateList(), которая создает объект типа IList. Он хранит пары «Имя» - «Значение». Имя строкового типа, значение – произвольного. Обратиться к имени можно по индексу, к значению – по имени или индексу. Элементы нумеруются с нуля.

Пусть нужно получить наименование текущего месяца:

  // Создать список значений
  MonthList = CreateList()
  // Заполнить
  MonthList.Add('01'; 'январь')
  MonthList.Add('02'; 'февраль')
  MonthList.Add('03'; 'март')
  MonthList.Add('04'; 'апрель')
  MonthList.Add('05'; 'май')
  MonthList.Add('06'; 'июнь')
  MonthList.Add('07'; 'июль')
  MonthList.Add('08'; 'август')
  MonthList.Add('09'; 'сентябрь')
  MonthList.Add('10'; 'октябрь')
  MonthList.Add('11'; 'ноябрь')
  MonthList.Add('12'; 'декабрь')
  // Получить номер текущего месяца
  MonthID = FormatDate('M'; Today())
  // Получить его наименование из списка
  MonthName = MonthList.ValueByName(MonthID)
  // Вывестирезультат
  ShowMessage(Format('Сейчас %s!'; MonthName))

Для работы со списком строк можно воспользоваться типом IStringList. Создать его можно при помощи функции CreateStringList(). Обращение к элементам – по индексу.

Подробнее об объектах системы и работе с ними можно узнать из руководства разработчика.

Организация диалога с пользователем

Организация диалога с пользователем ведется через функции группы «Ввод/вывод».

Например, следующий код позволяет вывести на экран простое сообщение:

  // Вывести 'Hello world!' на ISBL
  ShowMessage('Hello world!')

Если необходимо предложить пользователю право выбора или вывести больше информации, необходимо воспользоваться функциями вывода расширенных сообщений.

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

Код в данном случае будет иметь вид:

  if MessageBoxEx('Внимание!';
                  'Продолжить сохранение?';
                  'Документ с таким именем уже существует.';
                  'Да|Нет';;
                  'Старая версия документа будет потеряна.') == 'Да'
    Document.Save()
  endif

Если же необходимо запросить у пользователя какую-то информацию, для этого тоже есть специально разработанные функции ввода. Подробнее о них можно узнать из статьи Варианты запроса данных в DIRECTUM.

Работа с константами информационной системы

Константы информационной системы представляют собой именованные условно постоянные величины. Работа с константами может производиться в компоненте Константы в Утилитах разработчика или через специальные функции, объединенные в группу «Работа с константами».

В качестве типового примера можно рассмотреть сценарий, устанавливающий значения констант:

  
  // Считать установки из констант
  Director =   GetConstant('РукОрг')
  Accountant = GetConstant('ГлавБухг')
  DayStart =   GetConstant('НачалоРД')
  DayEnd =     GetConstant('КонецРД')  

  // Вывести диалоговое окно с настройками
  Settings = InputDialog(
    'Руководитель организации|Главный бухгалтер|Начало рабочего дня|Конец рабочего дня';
    Format('%s|%s|%s|%s'; ArrayOf(Director; Accountant; DayStart; DayEnd));
    'Аналитика:РАБ|Аналитика:РАБ|Число:0|Число:0'; 'Установки системы')

  // Считать значения из диалогового окна
  Director =   SubString(Settings; '|'; 1)
  Accountant = SubString(Settings; '|'; 2)
  DayStart =   SubString(Settings; '|'; 3)
  DayEnd =     SubString(Settings; '|'; 4) 

  // Записать новые значения констант
  SetConstant('РукОрг';   Director)
  SetConstant('ГлавБухг'; Accountant)
  SetConstant('НачалоРД'; DayStart)
  SetConstant('КонецРД';  DayEnd)

В ходе работы сценария пользователь увидит на экране окно, предлагающее ввести значения констант. Руководитель организации и Главный бухгалтер будут выбираться из справочника Работники, а Начало рабочего дня и Конец рабочего дня необходимо ввести вручную:

В результате работы сценария, введенные значения будут записаны в качестве значений соответствующих констант.

Аналогичный результат даст использование функции ShowConstantsInputDialog():

  
ShowConstantsInputDialog(
    'РукОрг|ГлавБухг|НачалоРД|КонецРД';
    'Руководитель организации|Главный бухгалтер|Начало рабочего дня|Конец рабочего дня';
    'Аналитика:РАБ|Аналитика:РАБ|Число:0|Число:0'; 'Установки системы')

Естественно, в статье рассмотрены не все возможности работы с функциями ISBL. Для более подробного ознакомления необходимо пройти обучение по Курсу 234. Модификация системы DIRECTUM с помощью IS-Builder

Андрей Подкин
Если значение по умолчанию указано, параметр считается необязательным, иначе – обязательным.
Тут есть один подвох: IS-Builder никак не проверяет, что обязательные параметры не передаются. Если они не указаны, в функцию передается специальное значение, которое (если я ничего не путаю) на ISBL даже проверить нельзя.
 
Для большинства функций код открыт для разработчика.
Точнее для всех прикладных.
 
Функций работы со строками тоже достаточно много.
Со строками самое главное помнить, что работа с большим объемом данных крайне неэффективна. Например, если попытаться написать свой аналог функции SQL только на строках (без списков и прочей оптимизации), то время выполнения будет расти по экспоненте (от объема данных).
 
  Message = Format('Исходная строка: %1:s%0:sПолученная строка: %2:s%0:s' &                    'Длина строки: %3:s%0:sСлов: %4:s';                    ArrayOf(CR; StartString; String; LengthString; CountWords))
Если кому-то из читателей от такой строки формата становится страшно так же, как мне, то добро пожаловать сюда.
А если интересуют сложные операции по поиску и замене данных в строках, то рекомендую обратить внимание на регулярные выражения.
Андрей Куров

IS-Builder никак не проверяет, что обязательные параметры не передаются.

И слава богу, откровенно говоря. Если параметр нужен обязательно, его на наличие значения можно проверить и в самой функции.
 
которое (если я ничего не путаю) на ISBL даже проверить нельзя.
Гмм. А что вы подразумеваете под "проверить нельзя"? Пишу в функции Test строку:
showmessage(IfThen(param=='';'true';'false'))
где param - это единственный параметр функции.
В сценарии вызываю sin_test() - выводит true вне зависимости от типа параметра.
Андрей Подкин
Гмм. А что вы подразумеваете под "проверить нельзя"? Пишу в функции Test строку: showmessage(IfThen(param=='';'true';'false'))
где param - это единственный параметр функции.
В сценарии вызываю sin_test() - выводит true вне зависимости от типа параметра.
А теперь попробуйте отличить передачу пустой строки от неуказания параметра wink
Андрей Куров
А теперь попробуйте отличить передачу пустой строки от неуказания параметра
А есть принципиальная практическая разница между пустой строкой и неуказанным значением? smiley
Андрей Подкин
А теперь попробуйте отличить передачу пустой строки от неуказания параметра А есть принципиальная практическая разница между пустой строкой и неуказанным значением?
Если не уточнять конкретную задачу - конечно есть. Пустая строка - это значение, поставленное программистом целенаправленно (пример: передаем ее в качестве разделителя подстрок). Неуказанное значение - это значит программист забыл указать.
 
Если, кстати, отвлечься от задания именно строк, то, скажем, проверка интерфейса на == "" для меня выглядит довольно дико.
Антон ИСУПОВ

 

Обратиться к значению можно по индексу, к значению – по имени или индексу.

Предложение следует читать:
"Обратиться к имени можно по индексу, к значению - по имени или индексу"
 
... при помощи следующего кода можно отследить, произошло ли исключение при сохранении документа и вывести корректное сообщение об ошибке ...

это никак не соотносится с самим примером, в котором выполняется абстрактный SQL-запрос. Если цикл статей ориентирован на начинающих разработчиков, то не следует вводить их в заблуждение на этапе подачи материала.
 

Ксения Иванова

2 Антон: спасибо за замечания, все исправила.

Авторизуйтесь, чтобы написать комментарий