Передача файла с помощью mstsc в командной строке

Select query и dataset: пользовательские фильтры

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

sq_

. В нашем случае это

sq_myworkspace

. По умолчанию будет создан фильтр по ID, который сразу можно использовать в коде.

Применяется обычный фильтр с помощью функции ApplyDatasetFilter:

ApplyDatasetFilter(Dataset, 'ID',  id, true);

Создадим простой фильтр по полю «Зарплата»:

1) создаем параметр, который будет передаваться в фильтр (SalarySum);2) в блок WHERE добавляем «Фильтр сравнения», указываем название такое же, как и у параметра (SalarySum). Выбираем поле (tbl_myworkspace.Salary) для сравнения с параметром, который мы будем передавать из функции ApplyDatasetFilter.

Теперь можем применить его в коде и найти всех сотрудников с зарплатой 30000.

var ds = Services.GetNewItemByUSI('ds_myworkspace');	
ApplyDatasetFilter(ds, 'SalarySum',  30000,  true);
ds.Open();
Log.Write(2, ds.ValAsStr('Name')); 
ds.Close();


Можно также применять несколько фильтров. Например, найти всех директоров с зарплатой больше 30000 и т.д.

Terminal server client [tsclient]

This is the best terminal client I have used so far. Compared to others I have tested (gnome-rdp,KRDC,Remmina,Vinagre) it provides functionality that others do not have, like:
-mapping of local drives,
-storing passwords(gnome-rdp claims to have it but is not working),
-storing separate settings for each connection,
-one click connection from tsclient icon on task bar,
-auto adjusting window size to remote screen resolution,
-thin window borders,
-and many others.
[OT] I can honestly say IMHO this is quite old client but still the best one to choose. Recently Ubuntu removed tsclient from it’s repositories, which was big mistake, because they didn’t provided anythig which is at least as good as tsclient. They claimed tsclient is old and nobody is working on it anymore. So what? When was the last time somebody worked on ‘ls’ or ‘cd’ command? Will they remove those also? 😉

Выпадающие списки

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

Предположим, мы уже создали справочник со списком должностей MyWorkspaceAppointments. Создаем поле AppointmentID в таблице tbl_myworkspace, где будет храниться ID должности. Добавляем его в sq_myworkspace, и также нам надо будет делать выборку поля «Название должности», которое будет отображаться в выпадающем списке.

Теперь добавляем поле «Поле справочника» в датасет. Выбираем колонку AppointmentID, в источнике данных справочника выбираем датасет справочника должностей, а в поле «Колонка для отображения» выбираем поле AppointmentName, выбранное нами ранее. Внизу ставим галочку «Отображать как выпадающий список в карточках». На окно добавляем элемент LookupDataControl и выбираем в DataFieldName. Все, можно проверять.

:/>  Инструкции по настройке Windows для подключения к интернету - Домашний билайн - Инструкции к устройствам - билайн Москва

Собственно, это и есть самые основы на которых построена система Terrasoft (по моему личному мнению).

Добавление данных

Попробуем создать раздел с информацией о сотрудниках. Добавим несколько новых полей:

Сначала необходимо создать все эти поля в таблице

tbl_myworkspace

. Ни каких сложностей возникнуть не должно. После сохранения поля обновятся в БД которую вы используете (у меня Microsoft SQL). Здесь же мы можем добавить индексы по полям или связи при необходимости.

Теперь надо обновить запрос sq_myworkspace, который отвечает за выборку данных из этой таблицы.

Добавляем необходимые поля и сохраняем. При желании можно просмотреть SQL, запрос нажав ctrl P.

В конце добавляем все эти поля в датасет ds_myworkspace, чтобы можно было работать с данными через специальный объект.

Тоже самое можно проделать гораздо проще, надо найти справочник нашего раздела (myworkspace) и изменить структуру полей:

Инструменты -> Справочники 


Теперь, когда мы добавили необходимые поля, можно отобразить их на форме добавления/редактирования данных

wnd_myworkspaceEdit

Из множества доступных элементов, выбираем TextDataControl. В свойствах необходимо указать следующие параметры:

Для зарплаты выбираем

IntegerDataControl

и проделываем все то же самое. Теперь мы можем открыть Terrasoft Client и добавить запись, используя окно редактирования данных раздела. Запись без проблем добавляется, но в гриде не отображаются наши пользовательские поля. Почему? Да потому что мы не добавили их в этот самый грид. Поэтому открываем

wnd_myworkspaceGridArea

, находим элемент grdData -> gdvData, щелкаем правой кнопкой мыши, выбираем пункт «Определить колонки» и добавляем наши поля. После чего они станут видны в гриде в клиенте (возможно вам понадобится добавить их, нажав плюсик в правом верхнем углу грида, там вы можете добавлять или наоборот прятать необходимые колонки).

Передача файла с помощью mstsc в командной строке

Вы сказали “jump box”, поэтому я предполагаю, что вам нужно подключиться к серверу jump, а затем начать сеанс rdp.

Как вы копируете файлы после входа на удаленный сервер? Перетаскивание (копирование / вставка) через проводник? Если это так, это может быть ужасно медленно через сервер перехода. Лучше всего использовать утилиту копирования командной строки и сопоставления tsclient.

robocopy tsclientCsomefolder C:temp *.exe или что-то еще. К сожалению, все это основано на установлении удаленного сначала сеанс рабочего стола, поэтому я не знаю, как инициировать копию с вашей локальной рабочей станции на удаленный хост с помощью сервера перехода.

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

:/>  Кракозябры в Windows 10

Работа с набором данных dataset


Как я уже говорил, работа с БД происходит через набор данных dataset. Получить текущий dataset для окна, в котором мы работаем, можно через DataLink:

var Dataset = dlData.Dataset;

Получить любой другой набор данных можно также по его названию:

var TestDataset = Services.GetNewItemByUSI('ds_Test');

Добавление записи в коде

TestDataset.Append();
TestDataset.Values('Name') = 'Василий Иванов';
TestDataset.Values('Salary') = 30000;
TestDataset.Post();

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

Редактирование записиДля редактирования конкретной записи применяем фильтр (далее фильтры будут более подробно рассмотрены) к набору данных:

ApplyDatasetFilter(TestDataset, 'ID', '{e2ad6e6f-481a-40d0-abb6-50e4b19a43d6}', true);
TestDataset.Open(); // открываем набор
if(!TestDataset.IsEmptyPage) {
    TestDataset.Edit();
    TestDataset.Values('Salary') = 35000; // изменяем нужные поля
    TestDataset.Post(); // сохраняем	
}
TestDataset.Close(); // закрываем по завершении работы

Если необходимо отредактировать более одной записи:

TestDataset.Open();
while (!TestDataset.IsEOF) {  
    TestDataset.Edit();              
    TestDataset.Values('Salary') = 40000;  
    TestDataset.Post();  
    TestDataset.GotoNext(); // переходим к следующей записи
}             
TestDataset.Close();  

Удаление

// не забывайте применять соответствующие фильтры, чтобы не удалить все записи
TestDataset.Open();
while(!TestDataset.IsEOF) {
    TestDataset.Delete();
    TestDataset.Open();
}
TestDataset.Close();


Посчитать количество записей в наборе можно с помощью свойства RecordsCount.

var Records = TestDataset.RecordsCount;

События dataset

Также хочется отметить наиболее используемые события dataset:

OnDatasetAfterOpen — возникает после открытия набора данных;OnDatasetAfterPositionChange — возникает после перехода на другую запись (бывает полезно при отслеживании смены выделенной записи в гриде);OnDatasetAfterPost — возникает после добавления/изменения записи (бывает полезно, когда надо изменить связанные данные в другой таблице);

OnDatasetBeforePost — возникает перед добавлением/изменением записи (бывает полезно для пользовательской проверки данных, перед сохранением). Также в событие передается параметр DoPost, если по какой-то причине нужно отменить добавление (например, данные не прошли пользовательскую проверку) просто делаем:

DoPost.Value = false;

OnDatasetDataChange

— возникает при изменении данных датасета. Например нужна какая-то логика при изменении поля должность из нашего выпадающего списка.

function dlDataOnDatasetDataChange(DataField) {
	var FieldName = DataField.Name;
	switch(FieldName) {
        case 'EditionID':   
            // организуем необходимую логики при каждом изменении поля
        break;		
    }
}

OnDatasetBeforeDelete

— возникает перед удалением записи (например можно повесить пользовательскую проверку данных, и при необходимости отменить удалить используя параметр DoDelete).

DoDelete.Value = false;

OnDatasetAfterDelete

— возникает после удаления записи (например можно проверить, обновить или удалить связанные данные с данной записью).

События окна, обращение к элементам


Иногда нужно прописать определенную логику при открытии окна, сделать это можно в событии

OnPrepare

По умолчанию у окна, в событии, будет прописана функция

wnd_BaseDBEditOnPrepare

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

wnd_MyWorkspaceDBEditOnPrepare

и дважды нажмем на нее. Откроется (или создастся новый) скрипт окна.

function wnd_MyWorkspaceDBEditOnPrepare(Window) {	
    scr_BaseDBEdit.wnd_BaseDBEditOnPrepare(Window); 
}


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

:/>  Синхронизация времени NTP.

Определяем события для поля Salary OnKeyDown и OnKeyUp, эти события буду срабатывать при вводе данных или при стирании. Напишем функцию, которая будет обновлять при каждом изменении поля Salary поле Tax (налог).

function edtSalaryOnKeyDown(Control, Key, Shift) {
	calculateTax();
}

function edtSalaryOnKeyUp(Control, Key, Shift) {
	calculateTax();
}

function calculateTax() {
	var Dataset = dlData.Dataset; // получаем набор данных для текущего окна
	edtTax.Value = dlData.Dataset.ValAsInt('Salary') * 0.13;
}

Все отлично работает. Однако при открытии окна поле «Налог» не будет заполнено. Это можно исправить с помощью события окна OnPrepare.

function wnd_MyWorkspaceDBEditOnPrepare(Window) {	
    scr_BaseDBEdit.wnd_BaseDBEditOnPrepare(Window); 
    calculateTax(); // просчитываем и заполняем поле налог
}


В процессе работы появились некоторые наработки, которые мне не раз пригодились.

Посмотреть

//изменение цвета и текста в ячейке у DataGrid
function grdDataOnGetRowDrawInfo(DataGrid, Color, TextColor, ImageName, Font) {
    if (/* условие */) {
        Color.Value= clRed; // цвет ячейки
        TextColor.Value = clYellow; // цвет текста
    }
}
//фильтрация значений выпадающего списка по определенном полю
function edtContactOnPrepareSelectWindow(LookupDataControl, SelectWindow) {
	ApplyDatasetFilter(LookupDataControl.DataField.LookupDataset, 'IsActive', true, true);
}

// сбрасывает выпадающий список, и при следующем обращении опять вызовет событие OnPrepareSelectWindow< (например если данные в списке зависят от другого поля, которое изменилось, и необходимо обновить фильтр) 
edtContact.UnprepareDropDownList();
// открытие любого окна 
var EditWindowUSI = 'wnd_OpportunityEdit';
var Attributes = GetNewDictionary();
Attributes.Add('RecordID', GUID_NULL);  // если не указываем RecordID то открывается окно для добавления данных, если указываем, то запись с ID = RecordID открывается для редактирование
var DefaultValues = GetNewDictionary();  // значения по умолчанию
DefaultValues.Add('CustomerID', AccountID); 
ShowEditWindowEx(EditWindowUSI, Attributes, DefaultValues);
// что-то вроде глобальной области видимости, можно таким образом передавать данные из одного окна в другое
Connector.Attributes('DatasetToSave') = object; 
// обращение к родительскому окну (также можно обратиться к элементам на этом окне)
var ParentWindow = Self.Attributes('NotifyObject').ParentContainer.ParentWindow.ComponentsByName('edtPriceListsEditionID');
// обращение к элементу родительского окна (текущее окно находится в контейнере)
var ParentWindow = Self.ParentContainer.ParentWindow.ComponentsByName('edtName’);
// обращение к одному гриду из другого через workspace
var grd = Self.ParentContainer.ParentWindow.ComponentsByName('wndGridData').Window.ComponentsByName('grdData');
// проверка, является ли данная запись новой, или она открыта на редактирование
Window.Attributes('IsNewRecordAppend')
// получить выделенные записи грида
var ArrayIDs = GetArrayByCollection(grdData.SelectedIDs);
// вывод каких либо данных в консоль
Log.Write(2, 'Text');
// например при отладке, удобно использовать исключение
try {
    // ваш код
} catch(e) {
    Log.Write(2, e.message);
}

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

Оставьте комментарий