6. Данные и переменные
Прежде чем переходить к непосредственно изучению МЭК-языков, необходимо познакомиться с общими элементами этих языков. Общие элементы служат единым фундаментом, позволяющим объединить многоязычные компоненты в одном проекте. В главе будут рассмотрены данные, с которыми способен работать стандартный ПЛК, форматы их представления и наиболее общие приемы и тонкости работы с ними.
Типы данных
Тип данных переменной определяет род информации, диапазон представления и множество допустимых операций. Языки МЭК используют идеологию строгой проверки типов данных. Это означает, что любую переменную можно использовать только после ее объявления. Присваивать значение одной переменной другой можно, только если они обе одного типа. Допускается также присваивание значения переменной совместимого типа, имеющей более широкое множество допустимых значений. В этом случае происходит неявное преобразование типа без потерь. Неявные преобразования типов данных с потерями запрещены. Так, например, логическую переменную, способную принимать только два значения (логические 0 и 1), можно присвоить переменной типа SINT (-128. +127), но не наоборот.
При трансляции программы все подобные попытки отслеживаются и считаются грубыми ошибками. Если же это действительно необходимо, то выполнить присваивание с потерями возможно, но только при помощи специальных операторов. Операторы преобразования в МЭК выполняют также и более сложные операции, например преобразование числа или календарной даты в текстовую строку, и наоборот.
Наибольшее разнообразие типов данных в стандарте предусмотрено для представления целых чисел. Смысл применения широкого спектра целочисленных переменных заключается в первую очередь в оптимизации кода программы. Скорость вычислений зависит от того, как микропроцессор оперирует с переменными данного типа. Так, вполне очевидно, что 16-разрядный процессор выполняет сложение двух 16-разрядных значений одной командой. Сложение же двух значений 32-разрядных переменных — это подпрограмма из нескольких команд.
Дополнительные задержки могут образовываться за счет мультиплексирования шины данных, связывающих процессор и память, особенностей микросхем памяти и т. д. В общем случае, меньшие по диапазону представляемых значений типы переменных требуют меньше памяти, меньше кода, и вычисления с их участием выполняются значительно быстрее.
Типы данных МЭК разделяются на две категории — элементарные и составные. Элементарные или базовые типы являются основой для построения составных типов. К составным типам относятся перечисления, массивы, структуры, массивы структур и т. д.
Элементарные типы данных
Целочисленные переменные отличаются различным диапазоном сохраняемых данных и, естественно, различными требованиями к памяти. Подробно данные характеристики представлены в следующей таблице.
ELMA/Тест для ELMA аналитика
Сколько стартовых и конечных событий должно быть на карте БП в ELMA? [ править ]
А) Одно начальное событие, одно конечное
Б) Любое количество начальных событий, одно конечное
В) Одно начальное событие, не менее одного конечных
Г) Любое количество начальных и конечных событий, это не регламентируется
Сколько переходов из блока «Пользовательская задача» может быть в системе ELMA? [ править ]
Б) Любое количество
В) Не менее одного, в зависимости от условий задания
Г) Всегда два перехода – один основной и резервный для обработки ошибки
Вам требуется проверку условий по каждому элементу некой коллекции в БП ELMA. Как верно это реализовать? [ править ]
А) Разместить блок сценария на графической схеме в нужном месте. В тексте сценария прописать цикл на языке JavaScript
Б) В графической схеме процесса разместить блок сценария, после него – исключающий ИЛИ-шлюз. Зациклить переходом к блоку сценария, выход из цикла – переход к следующему блоку (задаче)
В) Разместить блок сценария на графической схеме в нужном месте. В тексте сценария прописать цикл на языке C#
Г) В ELMA нет возможности реализовать исполнение поставленной задачи
После публикации бизнес-процесс будет [ править ]
А) Доступен для запуска для всех пользователей в любом случае ?-думаю, эта
Б) Будет доступен для запуска только для группы «Администраторы»
В) Будет доступен для группы пользователей и\или элемента оргструктуры, указанной в любой из зон ответственности
Г) Будет доступен для группы пользователей и\или элемента оргструктуры, указанной в зоне ответственности, в которой расположено стартовое событие
В Дизайнере ELMA отсутствует вкладка «Документооборот». В чем причина? [ править ]
А) Все верно, в дизайнере не предусмотрено такой вкладки
Б) Не активирован компонент BPM в системе
В) Не активирован компонент ECM системе
Г) В системе вся работа с документооборотом производится в web-части
Что такое IIS? [ править ]
А) Встроенная СУБД для ELMA
Б) Встроенный web-сервер ELMA
В) Web-сервер от Microsoft для работы web приложений в Windows среде
Г) Внешняя СУБД для ELMA
Какое значение примет переменная C при исполнения указанного ниже кода: [ править ]
public virtual void test (Context context) <
А) Будет выдана ошибка преобразования типа данных
Каким образом в ELMA реализовать параллельное исполнение нескольких задач в разных зонах ответственности? [ править ]
А) Использовать неисключающий ИЛИ шлюз
Б) Использовать И шлюз
В) Использовать элементы UML для распараллеливания
Г) Параллельно можно исполнять задачи только в одной зоне ответственности, используется механизм «Кто первый»
Какого типа зоны ответственности НЕ существует? [ править ]
Б) Системная
Что необходимо сделать, чтобы процесс запускался автоматически в указанное время? [ править ]
А) Настроить стартовое событие: изменить триггер на таймер и указать время запуска.
Б) В разделе «Админстрирование»-«Система»-«Планировщик» добавить задание
В) В системе нельзя запускать процессы по расписанию
Г) Сделать первую задачу процесса периодической
Выберите верное утверждение: Контекстная переменная процесса [ править ]
А) Объявляется в тексте первого сценария
Б) Всегда имеет тип «Объект»
В) Может быть простой — состоящей из одной компоненты, или составной — в виде набора полей или блока данных
Г) Никогда не может быть null вне зависимости от установленных настроек, для того чтобы избежать ошибок при выполнении кода сценариев.
Импорт и экспорт конфигурации или ее части можно осуществить [ править ]
А) Через xml-файл, генерируемый в веб-части системы
Б) Путем сохранения резервной копии БД MS SQL и ее загрузки в системе-приемнике
В) В дизайнере ELMA путем создания файла конфигурации BPMApp или в разделе Экспорт \ Импорт + — видимо, неверно
Г) Скопировав с заменой файл configuration.config, изменив строку подключения к БД
Чтобы запустить отладку процесса, необходимо: [ править ]
А) В web-части нажать на кнопку «Запустить отладку» на панели инструментов в карточке процесса
Б) При запуске процесса установить переключатель «Режим отладки» в положение «включено»
В) В дизайнере в разделе «Сценарии» нажать кнопку «Эмуляция»
Г) В дизайнере необходимо нажать на кнопку «Запустить отладку» на панели инструментов в карточке процесса
В каком типе ЗО не указывается исполнитель? [ править ]
А) Бизнес-роль
Какие элементы системы можно импортировать/экспортировать? [ править ]
А) Типы документов, бизнес-процессы, отчеты, оргструктура, объекты, пользовательские расширения, портлеты, страницы
Б) Оргструктура, отчеты, типы документов, объекты, бизнес-процессы
В) Оргструктура, объекты, бизнес-процессы, типы документов, портлеты, отчеты
Г) Оргструктура, объекты, бизнес-процессы, портлеты, отчеты
Как правильно вставить переменную в шаблон документа в ELMA? [ править ]
Укажите неверное утверждение: [ править ]
А) Запуск БП в ELMA из внешних систем невозможен
Б) Запуск БП из внешних систем возможен через GET и POST запрос
В) Запуск БП из внешних систем возможен через web-сервис
Г) Для запуска БП из внешней системы любым способом используется его токен
Какое действие выполняется в следующих строках кода: [ править ]
var ddlSettings = context.GetSettingsFor(m => m.Spisok) .As<DropDownListSettings>(); ddlSettings.Items.Add(new DropDownItem(«string»)); ddlSettings.Save();
А) Это неверный код, лямбда-выражение записано с ошибкой.
Б) Переменная типа «Строка» разбивается на несколько элементов выпадающего списка
В) В переменную типа «Выпадающий список» добавляется элемент
Г) Ничего не выполняется, кроме сохранения переменной типа «Выпадающий список» с элементами типа string
Какого типа может быть переменная elma
Прежде чем переходить к непосредственно изучению МЭК-языков, необходимо познакомиться с общими элементами этих языков. Общие элементы служат единым фундаментом, позволяющим объединить многоязычные компоненты в одном проекте. В главе будут рассмотрены данные, с которыми способен работать стандартный ПЛК, форматы их представления и наиболее общие приемы и тонкости работы с ними.
Типы данных
Тип данных переменной определяет род информации, диапазон представления и множество допустимых операций. Языки МЭК используют идеологию строгой проверки типов данных. Это означает, что любую переменную можно использовать только после ее объявления. Присваивать значение одной переменной другой можно, только если они обе одного типа. Допускается также присваивание значения переменной совместимого типа, имеющей более широкое множество допустимых значений. В этом случае происходит неявное преобразование типа без потерь. Неявные преобразования типов данных с потерями запрещены. Так, например, логическую переменную, способную принимать только два значения (логические 0 и 1), можно присвоить переменной типа SINT (-128. +127), но не наоборот.
При трансляции программы все подобные попытки отслеживаются и считаются грубыми ошибками. Если же это действительно необходимо, то выполнить присваивание с потерями возможно, но только при помощи специальных операторов. Операторы преобразования в МЭК выполняют также и более сложные операции, например преобразование числа или календарной даты в текстовую строку, и наоборот.
Наибольшее разнообразие типов данных в стандарте предусмотрено для представления целых чисел. Смысл применения широкого спектра целочисленных переменных заключается в первую очередь в оптимизации кода программы. Скорость вычислений зависит от того, как микропроцессор оперирует с переменными данного типа. Так, вполне очевидно, что 16-разрядный процессор выполняет сложение двух 16-разрядных значений одной командой. Сложение же двух значений 32-разрядных переменных — это подпрограмма из нескольких команд.
Дополнительные задержки могут образовываться за счет мультиплексирования шины данных, связывающих процессор и память, особенностей микросхем памяти и т. д. В общем случае, меньшие по диапазону представляемых значений типы переменных требуют меньше памяти, меньше кода, и вычисления с их участием выполняются значительно быстрее.
Типы данных МЭК разделяются на две категории — элементарные и составные. Элементарные или базовые типы являются основой для построения составных типов. К составным типам относятся перечисления, массивы, структуры, массивы структур и т. д.
Элементарные типы данных
Целочисленные переменные отличаются различным диапазоном сохраняемых данных и, естественно, различными требованиями к памяти. Подробно данные характеристики представлены в следующей таблице.
Name already in use
Результат работы программиста — программный код, текст. Код состоит из инструкций компьютеру, что, как и в какой последовательности выполнить. Все эти инструкции следуют определенной цели, которую видит программист. Начальные, промежуточные и конечные данные каждого действия или комплекса действий сохраняют в переменных, у которых есть определенный тип данных. Для того, чтобы понимать весь этот процесс, мы наше знакомство с программированием начнем с нескольких терминов:
Переменная — данные, которые хранятся в оперативной памяти и имеют имя и тип. Проще ассоциировать с подписанным контейнером, в котором что-то лежит.
Тип данных — характеристика набора данных, которая определяет возможные значения этого набора, ряд допустимых операций, которые можно предпринимать с этими данными, и способ хранения этих данных в памяти.
Пример из реальной жизни:
Коробки с фруктами, на которых написано «Фрукты». Они занимают определенное место, у нее есть название и все примерно ориентируются, что можно сделать с содержимым этой коробки. Коробки с фруктами содержат фрукты. Их можно открыть, фрукт можно съесть, можно разрезать, можно почистить, можно приготовить салат и так далее. Ящик с надписью «Посуда» при переезде. Ясно, что внутри хрупкое и бьющееся, ясно, как это транспортировать и когда распаковывать.
В программировании типов данных много, и в различных языках они различаются. Тем не менее, рассмотрим их общие виды и характеристики. Разобравшись с этим, мы сможем классифицировать любой незнакомый нам тип данных.
Примитивами называют типы данных, которые состоят из одного элемента. Синонимы к этому определению — скалярные.
Структурными можно назвать типы данных, которые состоят из элементов других типов данных. Название — синоним: нескалярные, аггрегатные.
Говоря проще, примитивы — простейшие типы данных, которые неделимы, тогда как структурные состоят из набора структурных или примитивных типов.
Скалярные типы данных или примитивы.
Во многих, если не во всех языках программирования высокого уровня встречаются следующие примитивы:
- Булевы или логические данные. Переменная этого типа может иметь только два значения — Правда и Ложь (True, False). Часто эти параметры интерпретируются соответственно как 1 и 0. Используется повсеместно для получения ответов на различные вопросы и дальнейшего выбора варианта действий.
- Целые числа. Переменные такого типа содержат целое число. В зависимости от языка программирования и выбранного подтипа целочисленных данных различаются диапазоном значений и воможностью работы с отрицательными числами.
- Числа с плавающей точкой или вещественные числа. Сюда входят как целые числа, у которых дробная часть есть, но считается пустой, так и дробные. В программном виде чаще всего такие числа записываются как x = a * 10^b , т.е. через дробное десятичное число a, умноженное на 10 в степени b. В математике это выглядит как 1.2*10^3 , в программировании степень числа 10 пишется через экспоненту, т.е. 1.2e3 . Например, расстояние от Земли до Солнца составляет 1.496 · 10^11 , или 1.496e11.
- Комплексные числа — числа вида x + iy , где i — корень из минус единицы. Необходимо для ряда математических действий и изысканий, обычному программисту может быть нужно довольно редко.
- Отсутствие значения и типа — особый тип данных, который означает ничего, пустое место. Отличается от нуля, пустой строки или пустого массива. В разных языках называется по-разному, например null, none, nan.
- Строки — Строки принято относить к примитивам, хотя они и состоят из символов.
Структурные типы данных.
Структурные типы данных, которые можно встретить в различных языках:
- Массивы
- Кортежи
- Словари
- Множества
- Функциональные типы данных
- Записи
Эти типы данных мы расмотрим позже более подробно.
Так же типы данных могут быть изменяемыми или мутабельными, и неизменяемыми (иммутабельными). Знакомясь с новыми типами данных конкретного языка разумно было бы выяснять, можно ли его менять, или он иммутабелен, т.е. значение его останется тем же, каким было создано, и можно либо работать с тем значением, что есть, либо создавать новое значение для него.
Те же строки, к примеру, могут быть неизменяемыми. Это значит, что в переменную можно записать строку, но изменить ее после этого будет невозможно. Однако, будет возможность записать в эту переменную другую строку, в том числе и измененную исходную строку.
Переменная типа bool может содержать только два значения: True или False, при чем это не строки, не числа, а именно понятия ложь и истина.
Для работы с булевыми переменными существует булева алгебра.
![]()
Булева алгебра (логические операторы)
Существуют следующие логические операторы:
- and — И
- or — ИЛИ
- xor — Исключающее ИЛИ (подключается отдельно)
- not — НЕ
not означает НЕ, и, будучи поставленным перед типом bool, меняет его значение на обратное, т.е. not True становится False , not False становится True
Далее приведена таблица, демонстрирующая работу операторов:
| Операторы | 0 to 0 | 0 to 1 | 1 to 0 | 1 to 1 |
|---|---|---|---|---|
| and или && | 0 | 0 | 0 | 1 |
| or | 0 | 1 | 1 | 1 |
| xor | 0 | 1 | 1 | 0 |
Оператор условия «если» (if)
Во многих, если не во всех языках программирования существуют условия вида если — иначе, если — иначе. Код выглядит примерно следующим образом:
Операция mod — операция взятия остатка от деления.
Есть различные варианты использования оператора если : просто если , с использованием иначе и с любым количеством иначе, если между если и иначе, если .
Во многих языках программирования (С++, Java, PHP. ) существуют тернарный оператор, т.е. специальный оператор условия, который возвращает один из двух результатов, в зависимости от того, выполняется его условие или нет. Выглядит он так:
Тернарные операторы часто применяются, когда варианта всего два, так как такая запись короче аналогичного действия с если . Однако, к сожалению, можно встретить связку нескольких если и тернарных операторов, которую совершенно невозможно прочесть. Другими словами, это не необходимая вещь в языке и она может стать причиной нечитаемого текста.
Множество или сет (set) по сути — «контейнер», содержащий не повторяющиеся, уникальные элементы в случайном порядке. В этом определении упомянуты две основные особенности сетов — уникальность и отсутствие сортировки.
Уникальность — сет содержит только уникальные элементы, если добавлять в него дубликаты — они не добавляются, если перевести какую-то переменную с неуникальными данными в сет — дублирующие элементы будут удалены.
Отсутствие сортировки — элементы в сете находятся в неком хаотичном порядке.
Множества поддерживают перебор всех элементов (итерацию), добавление и удаление элементов, но в силу отсутствия сортировки не поддерживают индексацию и срезы.
Множества поддерживают операции вычитания, объединения, пересечения:
Можно добавить элемент в множество и удалить из множества элемент. В качестве параметра выступает сам элемент, поскольку индексов в множестве нет.

Множества принято визуализировать при помощи диаграмм Эйлера-Венна. В том числе и булеву алгебру удобно и просто понять на примере таких диаграмм:
AND, и в том и в том случае истина: 
OR, или в том или в том случае истина: 
XOR, истина или в том, или в другом случае, но не в обоих случаях сразу. 
Практические задания на диаграммы Эйлера-Венна
1. Разместить в кругах:
- Числа целые
- Числа положительные
- Числа отрицательные
- Числа простые
2. Нарисовать круги для заварного кофе:
- эспрессо (30 мл кофе)
- американо (эспрессо + вода)
- каппучино (эспрессо + вспененное молоко)
- латте (эспрессо + вспененное молоко + молоко)
- доппио (два эспрессо)
3. Решить задачу: Все женщины — дочки, но не все женщины матери. Некоторые матери — бабушки. Нарисуйте внучек!
И напоследок немного поговорим о системах счисления, это нам неоднократно пригодится в понимании некоторых концепций программирования в будущем.
Для лучшего понимания программирования будет не лишним уметь читать числа разных систем счисления и переводить из одной в другую.
ELMA/Тест для ELMA аналитика
Сколько стартовых и конечных событий должно быть на карте БП в ELMA?
А) Одно начальное событие, одно конечное
Б) Любое количество начальных событий, одно конечное
В) Одно начальное событие, не менее одного конечных
Г) Любое количество начальных и конечных событий, это не регламентируется
Сколько переходов из блока «Пользовательская задача» может быть в системе ELMA?
Б) Любое количество
В) Не менее одного, в зависимости от условий задания
Г) Всегда два перехода – один основной и резервный для обработки ошибки
Вам требуется проверку условий по каждому элементу некой коллекции в БП ELMA. Как верно это реализовать?
А) Разместить блок сценария на графической схеме в нужном месте. В тексте сценария прописать цикл на языке JavaScript
Б) В графической схеме процесса разместить блок сценария, после него – исключающий ИЛИ-шлюз. Зациклить переходом к блоку сценария, выход из цикла – переход к следующему блоку (задаче)
В) Разместить блок сценария на графической схеме в нужном месте. В тексте сценария прописать цикл на языке C#
Г) В ELMA нет возможности реализовать исполнение поставленной задачи
После публикации бизнес-процесс будет
А) Доступен для запуска для всех пользователей в любом случае ?-думаю, эта
Б) Будет доступен для запуска только для группы «Администраторы»
В) Будет доступен для группы пользователей и\или элемента оргструктуры, указанной в любой из зон ответственности
Г) Будет доступен для группы пользователей и\или элемента оргструктуры, указанной в зоне ответственности, в которой расположено стартовое событие
В Дизайнере ELMA отсутствует вкладка «Документооборот». В чем причина?
А) Все верно, в дизайнере не предусмотрено такой вкладки
Б) Не активирован компонент BPM в системе
В) Не активирован компонент ECM системе
Г) В системе вся работа с документооборотом производится в web-части
Что такое IIS?
А) Встроенная СУБД для ELMA
Б) Встроенный web-сервер ELMA
В) Web-сервер от Microsoft для работы web приложений в Windows среде
Г) Внешняя СУБД для ELMA
Какое значение примет переменная C при исполнения указанного ниже кода:
public virtual void test (Context context) m.Spisok) .As (); ddlSettings.Items.Add(new DropDownItem(«string»)); ddlSettings.Save();
А) Это неверный код, лямбда-выражение записано с ошибкой.
Б) Переменная типа «Строка» разбивается на несколько элементов выпадающего списка
В) В переменную типа «Выпадающий список» добавляется элемент
Г) Ничего не выполняется, кроме сохранения переменной типа «Выпадающий список» с элементами типа string
Как я от elma ушел
Несколько значений для одного атрибута объединил в одно с помощью STUFF(. ). Результат запроса сохранил в формате csv с разделителем «;». Первой строкой в файле добавил обозначения атрибутов в easla.com. Загрузил файл в разделе «Импорт объектов». Потом указал кодировку файла и пользователя, от имени которого выполнить импорт. Запустил импорт. Процедура импорта не очень быстрая, на создание каждого объекта может уходить порядка одной секунды. Количество импортированных записей было примерно 500. Выглядело это примерно так:
Теперь контакты. Написал вот такой SQL запрос:
Все действия аналогичны предыдущему импорту. Особенность импорта контактов после контрагентов заключалась в том, что контакт обладает атрибутом «Контрагент», который ссылается на контрагента. Поэтому, в первую очередь были импортированы контрагенты, а за ними контакты. При импорте контактов в поле «Контрагент» easla.com находила и подставляла ссылки на контрагентов! Количество импортированных записей было примерно 1800.
После импорта контрагентов и контактов получилась структурированная база данных, в которой все контакты принадлежат определенным контрагентам. На импорт данных ушло примерно 2 часа. Причем половину времени потратил на разработку SQL запросов. В результате получил две готовые и взаимосвязанные таблицы.
Реестр контрагентов:

Реестр контактов:

На очереди стоял импорт договоров. Выгрузил их с помощью вот такого SQL запроса:
Все действия также аналогичны предыдущему импорту. И точно также, как с контактами, все договоры обладая атрибутом «Контрагент» при импорте связались с соответствующими контрагентами. Количество импортированных записей было немногим больше 200.

Вот теперь, когда все контрагенты, контакты и договоры, на которые ссылаются входящие и исходящие документы находились в easla.com, можно было приступить к импорту переписки.
Количество входящих и исходящих писем было большим — примерно 5400 и 5300 соответственно.
Интересно то, что входящие и исходящие письма ссылаются друг на друга, т.е. исходящее может быть отправлено в ответ на входящее и информации об этом сохраняется в соответствующем атрибуте исходящего документа. Входящий документ может быть получен в ответ на исходящий и информация об этом хранится в соответствующем атрибуте входящего документа. Таким образом, при импорте одного из типов объектов обеспечить формирование всех связей невозможно. Первыми были импортированы входящие документы, но перед этим, тип атрибута хранящего ссылку на исходящий документ был изменен с «Объект» на «Строка». Это позволило сохранить в атрибуте описание исходящего документа, которого пока нет в базе данных и использовать его позже, после импорта исходящих документов. В конечном счете, для выгрузки входящих документов получился вот такой SQL запрос:
Загрузил csv файл, загрузил все файлы входящих. Процедура оказалась долгой, т.к. общий объем файлов был несколько гигабайт. Хорошо, что импорт данных по 1000 записей, т.к. без накладок не обошлось. Обязательно в каждой тысяче всплывало по 10-15 ошибок. Выявить ошибки удалось перед процедурой импорта, с помощью предварительного просмотра. Очень удобно. В общем, каждая тысяча требовала предварительной подготовки.
Таким же образом импортировал все исходящие документы.
После этого, в объектах была написана процедура преобразования имен файлов. Она удаляла id, а data, переносила в revdata файла в easla.com. Таким образом, файлы приложений получили исходные имена filename.ext.
Специально для входящих писем была написана процедура, которая заменяла описания ссылок на исходящие документы на их идентификаторы.
Проверив работу этих процедур запустил пакетное обновление объектов. Медленно, но верно easla.com обновила все объекты! После этого, изменил тип атрибута ссылающегося на исходящий документ во входящем документе со «Строка» на «Объект», чтобы идентификаторы объекта стали объектами.
Таким образом, easla.com переименовала файлы и организовала перекрестные ссылки между входящими и исходящими документами!
В целом, процедура экспорта и импорта заняла примерно 3 рабочих дня. Загрузку файлов на easla.com осуществлял по вечерам, когда канал Интернет был свободен. Импорт данных по 1000 был удобен еще и потому, что старые письма можно было импортировать сразу, не беспокоясь о целостности данных. И только перед «боевым» запуском загрузил и импортировал остатки – последние пару сотен писем.
Миграцию осуществил в конце 2014 года, а запустил в эксплуатацию все описанные бизнес-процессы 12 января 2015 года.
Прошло уже больше года. Общий объем писем превысил 20 тысяч. Количество задач перевалило за 10 тысяч. Вот свежие данные из главного меню: 
ELMA — передать значение переменной JS в контекстную
![]()
Вы уж определитесь: использовать jquery или же нативный js.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.3.13.43310
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.