Получение региональных настроек

Опубликовано в AmiSharp

При использовании AmiSharp (или иного механизма получения таблиц QUIK) приходится преобразовывать строковые представления чисел в сами числа. Процедура кажется тривиальной, однако встроенная функция StrToNum() Амиброкера не знает ничего о региональных настройках и, соответственно, оказывается бесполезной.

Например, если в таблице терминала QUIK фигурирует цена фьючерса на индекс РТС в виде 158 450, то упомянутая функция преобразует эту строку в число 158. Первый же найденный пробел введет ее в заблуждение. Также в качестве разделителя целой и дробной частей StrToNum ожидает увидеть точку, хотя Windows для наших мест по умолчанию устанавливает запятую. При этом мы из языка AFL не имеем возможности заранее знать, каким образом терминал QUIK будет форматировать числа в своих таблицах при включённом флаге форматирования - вид строк, представляющих числа будет зависеть от региональных настроек операционной системы. Значит, нужно делать универсальный механизм - перед преобразованием в число необходимо строку, содержащую это число, привести в надлежащий вид:

  • удалить разделители триад
  • заменить разделитель целой и дробной частей на точку

А для этого нужно знать, какие разделители установлены в настройках операционной системы. Как получить из AFL региональные настройки?

Я делаю это так:

function RegionalSettings()
{   local WSHShell;     if (StaticVarGetText("RegionalSettings~Locale") == "")
    { WSHShell = CreateObject("WScript.Shell");       pushdef(`GetRegistryKey', `StaticVarSetText("RegionalSettings~`$1'",WSHShell.RegRead("HKEY_CURRENT_USER\\Control Panel\\International\\`$1'"))')
      GetRegistryKey(Locale);
      GetRegistryKey(sList);               dnl рaздeлитeль элeмeнтoв cпиcкa
      GetRegistryKey(sDecimal);         dnl рaздeлитeль цeлoй и дpoбнoй чacти
      GetRegistryKey(sThousand);      dnl рaздeлитeль гpупп paзpядoв
      popdef(`GetRegistryKey')
    }
}

Функция читает 4 региональных параметра, используя Windows Script и помещает их в глобальные переменные. В тексте используются команды препроцессора M4.

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

function NormalizeNumber(NumString)
{ RegionalSettings();
  NumString = StrReplace(NumString,StaticVarGetText("RegionalSetings~sThousand"),"");
  NumString = StrReplace(NumString,StaticVarGetText("RegionalSetings~sDecimal"),".");
  return NumString;
}

Конечно, возможны и экзотические случаи, когда рукам пользователя покоя нет. Он может поменять способ представления отрицательных чисел и подобные настройки. Можно и такие варианты отследить и исправить, но я этого не делаю: всему есть разумный предел.



Таким образом, для получения ячейки данных в виде числа при помощи AmiSharp я использую следующие 2 макроса:

define(`Get_Cell_Number',`StrToNum(NormalizeNumber(m4_amisharp.GetCell(`$1',`$2',`$3')))')
define(`Get_Cell_Name_Number',`StrToNum(NormalizeNumber(m4_amisharp.GetCellName(`$1',`$2',`$3')))')