Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?

Официальный форум Simple-Scada.

Просмотр сообщений

В этом разделе можно просмотреть все сообщения, сделанные этим пользователем.


Сообщения - OlegM

Страницы: [1]
1
Если сделать через конкатенацию, то все выполняется без ошибок.
Код: (delphi)
    // Выполняется без ошибок.
    GetVariableByName('Ch'+ IntToStr(ChamberNo) +'_PrgName'  ).Value :=           tblPrograms.GetCell(Ord( colPrgName      ), SelRow).Text;
    GetVariableByName('Ch'+ IntToStr(ChamberNo) +'_BoardWood').Value :=           tblPrograms.GetCell(Ord( colPrgBoardWood ), SelRow).Text;
    GetVariableByName('Ch'+ IntToStr(ChamberNo) +'_BoardThk' ).Value := StrToInt( tblPrograms.GetCell(Ord( colPrgBoardThk  ), SelRow).Text );

2
Переделал на функцию без Variant: вместо %s функция подставляет только строки из массива.
Проблема осталась. По прежнему выбивает эту ошибку 'Ошибка в скрипте Utils в строке 262. Обращение к несуществующему объекту (017C0647 . Read of address 00000028)'.
Код: (delphi)
// === FormatStr ===============================================================================
// =============================================================================================
// Функция подставляет в строку вместо '%s' строки из массива.

function FormatStr(const S: string; const Args: array of string): string;
var
  I, ArgIndex: Integer;
  NextChar: Char;
begin
  Result := '';
  ArgIndex := 0;
  I := 1;

  while I <= Length(S) do
  begin
    if (S[I] = '%') and (I < Length(S)) then
    begin
      NextChar := S[I + 1];

      if NextChar = '%' then
      begin
        Result := Result + '%';
        Inc(I, 2);
      end
      else if NextChar = 's' then
      begin
        if ArgIndex < Length(Args) then
        begin
          Result := Result + Args[ArgIndex];
          Inc(ArgIndex);
        end
        else
          Result := Result + '<missing>';
        Inc(I, 2);
      end
      else
      begin
        // неизвестная последовательность — оставляем просто '%'
        Result := Result + '%';
        Inc(I);
      end;
    end
    else
    begin
      Result := Result + S[I];
      Inc(I);
    end;
  end;
end;

3
Добрый день.

Помогите, пожалуйста, разобраться со скриптом.
Реализовал свою простенькую функцию FormatStr.
Не всегда, но достаточно часто вижу в логах сервера, вот такую ошибку на этот скрипт: 'Ошибка в скрипте Utils в строке 192. Обращение к несуществующему объекту (017C0647 . Read of address 00000028)'.
Utils -- это мой глобальный модуль, а строка 192 -- это завершающий мою функцию `end;` .

Вот сама функция:
Код: (delphi)
// === Format String ===============================================================================
// =================================================================================================
// Подставляет в строку вместо %s элементы из массива.
// Может принимать элементы для подстановки разных типов (Variant).
// Каждый элемент для подстановки рассматривается внутри функции как тип Variant,
//   который затем приводится к строке через VarToStrDef().
// Экранирование процента делается так: '%%' -> '%'.


// Стандартная делфишная функция Format() не поддерживается.


// Пример:
// FormatStr('Процент: %s%%, значение: %s.', [85, 'Ok']);
// => 'Процент: 85%, значение: Ok.'


function FormatStr(const AString: string; const Args: array of Variant): string;
var
  I, ArgIndex: Integer;
  NextSeq: string;
  V: Variant;
begin
  Result := '';
  ArgIndex := 0;
  I := 1;


  while I <= Length(AString) do
  begin
    if (AString[I] = '%') and (I < Length(AString)) then
    begin
      NextSeq := Copy(AString, I, 2); // например: '%s', '%%', '%x'


      if NextSeq = '%%' then
      begin
        Result := Result + '%';
        Inc(I, 2);
      end
      else if NextSeq = '%s' then
      begin
        if (Length(Args) > 0) and (ArgIndex <= High(Args)) then
        begin
          V := Args[ArgIndex];
          Result := Result + VarToStrDef(V, '<unsupported>');
          Inc(ArgIndex);
        end
        else
          Result := Result + '<missing>';
        Inc(I, 2);
      end
      else // неизвестная последовательность -- оставляем просто '%'
      begin
        Result := Result + '%';
        Inc(I);
      end;
    end
    else
    begin
      Result := Result + AString[I];
      Inc(I);
    end;
  end;
end;
PS: Странно, что эта функция не поддерживается из коробки. Очень удобно ей пользоваться, например, при формировании sql-запросов с несколькими подстановками.

Вот код вызова, он иногода выполняется без ошибок, а иногда с этой ошибкой по памяти.
Но! Если перед этим кодом добавить строку для записи в виртуальную переменную любого значения, то всегда работает без ошибок.
Код: (delphi)
    Test.Value := 'Ok'; // С этой строкой FormatStr всегда работает без ошибок.
    GetVariableByName(FormatStr('Ch%s_PrgName',   [ChamberNo])).Value :=           tblPrograms.GetCell(Ord( colPrgName      ), SelRow).Text;
    GetVariableByName(FormatStr('Ch%s_BoardWood', [ChamberNo])).Value :=           tblPrograms.GetCell(Ord( colPrgBoardWood ), SelRow).Text;
    GetVariableByName(FormatStr('Ch%s_BoardThk',  [ChamberNo])).Value := StrToInt( tblPrograms.GetCell(Ord( colPrgBoardThk  ), SelRow).Text );

4
Добрый день.
Добавьте, пожалуйста, свойство "Скрыть стрелку выпадающего списка" в редакторе для Списка (TM_Combobox).

Будет очень полезно для случаев, когда нужно только выводить информацию для оператора.
Стрелка занимает место, и как бы указывает на то, что можно выбирать, хотя это не предусмотрено изначально.
Да, можно использовать текст, но здесь (в Списке) есть целое меню для создания позиций прямо в редакторе + не нужны скрипты.

Добавьте, пожалуйста, больше иконок для кнопок.
Не хватает базовых для элементарных операций: для копирования, редактирования, поиска, сортировки и т.п.
Эти иконки часто нужны, например, при работе с таблицами рецептов.
Ещё хотелось бы, чтобы добавили возможность использовать иконки кнопок в качестве изображений в элементе TM_Image

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

5
Ваши вопросы / Re: Опять массивы
« : 13 Марта 2025, 14:01:41 »
Спасибо, теперь понятно. :)

6
Ваши вопросы / Re: Опять массивы
« : 12 Марта 2025, 15:47:54 »
Добрый день.
Пытаюсь получить длину массива (тип: универсальный скрипт), но получаю вот такую ошибку
Код
Test | Incompatible types в строке: 5, позиция: 34
Код: (delphi)
var
  anArrayLength: Integer;
  anArray: array [0..10] of Integer;
begin
  anArrayLength := Length(anArray);
end.
Помогите разобраться, пожалуйста!

Кажется, я понял, что функция Length(arr) не поддерживается, и вместо нее нужно использовать High(arr), но как тогда быть с примерами скриптов выше, где эта самая функция Length() используется?

7
Тогда возникает вопрос: как закрыть все окна и/или формы на экране через скрипт, у которого тип "Заполнена форма" ?

8
Нашел ту строчку из-за которой возникает такое странное поведение формы:
Код: (delphi)
CloseAllWindows(GetClientName);
Эта инструкция идет последней в моем скрипте по нажатию на кнопку Добавить.

Получается так: форма закрывается автоматически если у кнопки указано действие "Отправить форму", и если в скрипте для отправки формы добавить закрытие всех окон, то это окно закроется (при первой отправке формы) и уже больше не откроется.

Вот скрипт (тип: заполнена форма) на кнопку Добавить целиком:
Код: (delphi)
var
  aProgramName, aQuery, aWoodType: string;
begin
  if FormData.Window <> wndAddProgram then
    Exit;

  aProgramName := FormData[fldProgramName_wndAddProgram].AsStr;
  aWoodType := FormData[cmbWoodType_wndAddProgram].AsStr; // из комбо-бокса в FormData забирается свойство ItemIndex

  if aProgramName.Trim = '' then
    begin
      FormData.SetError('Введите название программы сушки.');
      Exit;
    end;

  aQuery := ''+
  '  INSERT INTO programs (name, wood_type_id)'+
  '  VALUES ('+
       QuotedStr(aProgramName) +','+
  '    (SELECT id FROM wood_types WHERE enum_value = '+ QuotedStr(aWoodType) +')'+
  '  );';
  RunSQL(aQuery, nil, CREATE_PROGRAM);

  //HideStagesParamsTables;

  // если есть эта инструкция, то после закрытия и отправки формы, эта форма уже больше не откроется!
  CloseAllWindows(GetClientName);
end.

9
Добрый день.
После последнего обновления я открыл и пересохранил свой проект.
Затем переделал обычное окно на форму ввода (оно у меня для добавления рецепта).
Форма ввода открывается только один раз - после закрытия она уже не открывается.

Нашел решение - если в новой версии создать новую форму и скопировать туда элементы из старого окна, то все работает - форма открывается и закрывается сколько угодно раз.
PS: Возможно кто-то столкнется или уже столкнулся с таким поведением и не знает что делать.

10
Поддерживаю. Тоже так делаю - использую свойство Hint.

11
Допустимый диапазон определяется не типом данных, а шкалой и сдвигом запятой/визуальной шкалой. Практически во всех известных нам проектах, весь диапазон типа данных не используется...
Вы отвечаете про ситуацию, которая наоборот от описанной мной: диапазон типа данных включает в себя диапазон шкалы (т.е., используя шкалу мы сужаем перечень возможных значений, который нам предоставляет тип данных). Это хорошо, это есть в вашей документации.
Я же спрашиваю про ситуацию, когда диапазон, предоставляемый типом данных меньше (является лишь частью) диапазона шкалы: шкала включает в себя диапазон типа данных.

Как получается так, что я могу задать в поле для типа данных Byte число, которое выходит за его диапазон?
Тип данных отвечает за размер выделяемой под переменную памяти и максимальное число, которое может попасть в Byte -- это 255.
Я же могу, изменив шкалу, задать, например, 65500 для переменной типа Byte.

Такое странное поведение я заметил для внутренних переменных.
Спасибо  :)

12
Добрый день.
1. Создал внутреннюю переменную Byte [0…255].
2. Выбрал для нее шкалу с диапазоном [0…65535]. Теперь диапазон шкалы больше чем диапазон типа данных.
3. Привязывал эту переменную к полю ввода.

Почему я могу ввести в поле ввода любое число из диапазона шкалы от 0 до 65535 (например 65000),
когда указанный тип данных Byte может принимать лишь значение 255 ?

Страницы: [1]