Давайте якісно проаналізуємо попередню статтю (“Створення простого довідника”). В цій статті ми вирішили питання ведення реєстру комп'ютерів. Але чи повністю? Зрозуміло, що ПК має набагато більше характеристик, ніж ми передбачили. Це і список комплектуючих, і підключені до нього периферійні пристрої. Комплектуючі теж відрізняються своїми параметрами.
Очевидно, ці всі дані потрібно реєструвати в системі.
Для того, щоби доповнити наш довідник, нам необхідно створити список цих комплектуючих. По суті, він вже існує в довіднику номенклатури. Проте до вже існуючих даних потрібно додати технічні характеристики кожного комплектуючого. Для цього, нам потрібно створити такий довідник аналітики, який би містив список комплектуючих (взятих з довідника номенклатури) розбитих на групи і технічні характеристики, записаних окремим списком.
Для реалізації цього ми створимо новий тип довідника аналітики.
Створений на основі цього типу довідник аналітика буде містити список комплектуючих в одній таблиці, а їхніх характеристик – в іншій. Відображати на екрані ми будемо за допомогою двох списків. В одному комплектуючі, а в другому характеристики, при чому при переміщенні по списку комплектуючих їхні характеристики будуть змінюватись автоматично.
Почнемо...
Трошки теорії про створення типів довідників аналітики.Типи довідників аналітики зберігаються в папціScripts/Cls. Для кожного типу створюється окрема папка. Її назва і буде позначенням нового типу. В цій папці можуть бути наступні файли:
-
class.xml – тут описуються змінні довідника аналітики;
-
dpmapping.xml – тут ці змінні прив’язуються до полів таблиці;
-
form.xml – описується форма для додавання даних в довідник;
-
*.js – оброблювач подій на формі;
-
list.xml – описуються відображення списку;
-
list.js – описуються оброблювач подій списку (не обов’язкове);
Якщо довідник з рядками, то в цю ж папку треба помістити файл *.xml з описом цього Grid`а і окрему папку, в якій будуть міститись файли для оброблення даних в цьому списку:
-
class.xml – тут описуються змінні довідника аналітики;
-
dpmapping.xml – тут ці змінні прив’язуються до полів таблиці;
-
form.xml – описується форма для додавання даних в довідник;
-
*.js – оброблювач подій на формі;
Все просто і зрозуміло. Достатньо уважно описати змінні і поля, створити довідник аналітики потрібного (створеного) типу і сміливо користуватись.
Створення таблиць. Як створювати таблиці в існуючій базі даних ми знаємо. Тому тут я просто наведу назви таблиць і списки полів.
Нам потрібна одна таблиця, де ми опишемо код, назву і серійний номер деталі. Назвемо її CL_KOMPL. Поля, що входять:FKOD, FNAME, FSERNOM.
В другій нам потрібно лише два поля (потім зрозуміємо чому так). Цю таблицю назвемо CL_KOMPL_ROW. Поля, що входять: FPARNAME, FPARZNACH.
Таблиці створено і до цього більше не будемо звертатись. Просто навожу в лістингу 1 текст файлу для їх створення.
Лістинг 1
<?xml version="1.0" encoding="UTF-8"?>
<STRU>
<TABLES>
<table attr="" dospath="cdbf" path="cl_mdb" pattern="CL_KOMPL" sys="com" table="CL_KOMPL"></table>
<table attr="" dospath="cdbf" path="cl_mdb" pattern="CL_KOMPL_ROW" sys="com" table="CL_KOMPL_ROW"></table>
</TABLES>
<PATTERNS>
<CL_KOMPL>
<PARENTS>
<PARENT pattern="FWIDPARENT"/>
</PARENTS>
<FIELDS>
<FWID_CL attr=" " type="long"/>
<FKOD attr=" " type="text"/>
<FNAME attr=" " type="text"/>
<FSERNOM attr=" " type="text"/>
<FREM attr=" " type="longtext"/>
</FIELDS>
</CL_KOMPL>
<CL_KOMPL_ROW>
<PARENTS>
<PARENT pattern="FWIDPARENT"/>
</PARENTS>
<FIELDS>
<FWID_CL attr=" " type="long"/>
<FPARNAME attr=" " type="long"/>
<FPARZNACH attr=" " type="text"/>
</FIELDS>
</CL_KOMPL_ROW>
</PATTERNS>
</STRU>
Для створення нового типу довідника виконаємо наступні дії:
-
В Scripts/Cls створимо папку з іменем довідника (наприклад, clkompl);
-
Створимо всі необхідні файли в цій папці.
Описання типу довідника (class.xml). Отже, поля таблиць створені, можна описувати клас довідника. Нагадую, що в класі ми описуємо змінні довідника. Імена цим змінним ми будемо давати такі, як і імена полів, замінюючи першу літеру F на H.
Лістинг 2
<?xml version="1.0" encoding="UTF-8"?>
<DpCL type="clkompl" name="Комплектуючі|Комплектующие" sys="COM">
<Parents>
<parent classid="cls.CL1"/>
</Parents>
<Header>
<var name="HKOD" datatype="text"/>
<var name="HNAME" datatype="text"/>
<var name="HSERNOM" datatype="text"/>
<var name="HREM" datatype="text"/>
</Header>
<rows>
<row id="KLROWS" classid="KLROWS"/>
</rows>
</DpCL>
В лістингу 2 не складно розібратись самостійно. Тут описано текст файлу class.xml. Все ж дам деякі пояснення.
<Header> - описує основні змінні довідника. Тут вказується і тип цієї змінної.
<rows> - прив'язує до основного класу рядки. Classid - ідентифікатор класу рядків. Папку з такою ж назвою потрібно створити в папці Scripts/Cls/Назва довідника.
Зв'язок змінних з полями таблиці (dpmapping.xml). Тепер “прив'яжемо” змінні довідника до полів таблиці. В системі “Дебет Плюс V12” це здійснюеться за допомогою файлу dpmapping.xml, який описано в лістингу 3.
Лістинг 3
<?xml version="1.0" encoding="UTF-8"?>
<DpCL type="clkompl">
<Header>
<Tables>
<table name="CL" />
<table name="CLRELCLCL" ID="FWID_CL" />
<table name="CL_KOMPL" ID="FWID_CL" />
</Tables>
<Fields>
<field name="FWID" table="CL" var="ID" />
<field name="FTXT" table="CL" var="HTXT" />
<field name="FTXTS" table="CL" var="HTXTS" />
<field name="FCOD" table="CLRELCLCL" var="HCOD" />
<field name="FCL" table="CLRELCLCL" var="HCL" />
<field name="FWID_CL" table="CLRELCLCL" var="ID" />
<field name="FWID" table="CL_KOMPL" var="ID" />
<field name="FKOD" table="CL_KOMPL" var="HKOD" />
<field name="FNAME" table="CL_KOMPL" var="HNAME" />
<field name="FSERNOM" table="CL_KOMPL" var="HSERNOM" />
<field name="FREM" table="CL_KOMPL" var="HREM" />
</Fields>
</Header>
<Rows>
<Tables>
<table name="CL_KOMPL_ROW" reffield="FWID_CL"/>
</Tables>
</Rows>
</DpCL>
Тут name –ім'я поля, table –ім'я таблиці, в якій це поле знаходиться,var – ім'я змінної. Якщо все зрозуміло – йдемо далі.
Тепер потрібно описати grid.
Файл list.xml. Як описувати відображення таблиці на екрані ми вже знаємо. Тому просто навожу лістинг цього файлу.
Лістинг 4
<?xml version="1.0" encoding="UTF-8"?>
<list>
<grid>
<field field="kompl.FKOD" text="Код|Код" width="20" />
<field field="kompl.FNAME" text="Назва|Название" width="40" />
<field field="kompl.FSERNOM" text="Серійний номер|Серийный номер" width="20" />
<field field="kompl.FREM" text="Примітка|Примечание" width="70" />
</grid>
</list>
В цьому коді kompl.FKOD означає <псевдонім таблиці>.<назва поля>. Така комбінація утворилась в результаті використання функції tie. Ця функція приєднує до основної таблиці іншу по вибраних полях. Її використано в файлі list.js.
Файл list.js.
Лістинг 5
function clAfterLoad()
{
this.addTies = clAddTies;
}
function clAddTies()
{
this.extTie("CL",Fcl);
this.extTieEx("ext0","fwid","CL","0");
this.subTie("CL_KOMPL", "kompl", "FWID_CL", "Fwid");
}
Функція є clAfterLoad()обов’язковою. В ній описуються методи і властивості таблиці, яка відображається на гріді.
Я спробую пояснити тільки останній рядок функції clAddTies(). Тут:
-
"CL_KOMPL" – ім'я таблиці, що приєднується.
-
"kompl" – псевдонім цієї таблиці.
-
"FWID_CL", "Fwid" – поля таблиць, за якими ці таблиці об'єднуються.
Все доволі просто. Якщо ви створили і цей файл, то можемо йти далі.
Тепер потрібно створити форму для заповнення таблиці. Знову ж таки ми це вже з вами робили. Я зупинюсь тільки на використанні гріда.
Файл form.js і form.xml.
Лістинг 6
<?xml version="1.0" encoding="utf-8"?>
<Form>
<Controls col="3">
<Label text="№" width="80" gridwidth="1"/>
<TextField ID="FKOD" width="80" gridwidth="2"/>
<Label text="Назва:|Название:" gridwidth="1"/>
<TextField ID="FNAME" width="450" gridwidth="2"/>
<Label text="Серійний номер:|Серийный номер:" gridwidth="1"/>
<TextField ID="FSERNOM" width="450" gridwidth="2"/>
<Label text="Примітка:|Примечание:" gridwidth="1"/>
<TextField ID="FREM" width="450" gridwidth="2"/>
<grid ID="grid" width="700" height="250" gridwidth="3" align="fill" valign1="fill"/>
</Controls>
<script languige="JavaScript" src="form.js"/>
</Form>
Лістинг 7
include("objects//DpCl.js");
include("gridedit.js");
var sDir = rootDirectory() + "cls/clkompl/";
var sTmpTbl = "TMP_KOMPL_ROW";
var sRowTbl = "CL_KOMPL_ROW";
var sRowClass = "KLROWS";
var objCl = extPar.dpObj;
var ctrlLinker;
var gridTbl;
var oGridEdit;
function onLoad()
{
this.onEscape = exit;
Caption(ru("Комплектующие", "Комплектуючі") +": "+ modeName(this.sMode));
ctrlLinker = new DpCtrlLinker(objCl);
FKOD.setMask("######");
FKOD.setFocus();
ctrlLinker.addLink("HKOD", FKOD);
ctrlLinker.addLink("HNAME", FNAME);
ctrlLinker.addLink("HSERNOM", FSERNOM);
ctrlLinker.addLink("HREM", FREM);
ctrlLinker.toControls();
loadGrid(this.sMode);
}
function loadGrid(sMode)
{
DropTable(sTmpTbl);
var sSQL = "SELECT * "
+ " INTO " + sTmpTbl
+ " FROM ^"+ sRowTbl;
var sWhere = " WHERE 1<>1 ";
if (sMode != "ADD")
sWhere = " WHERE FWID_CL="+ sqlTo(objCl.getID());
sSQL += sWhere;
ExecuteSQL(sSQL);
gridTbl = OpenTable("m", "SELECT * FROM "+ sTmpTbl);
clTie(gridTbl,"kk","="+250+",FPARNAME");
//browse(gridTbl);
grid.setXMLDir(sDir);
grid.setXMLFile("l_kompllist.xml");
grid.setTable(gridTbl);
grid.build();
grid.setData(sRowClass);
this.gridMenuInit = gridMenuInit;
this.gridMenuRum = gridMenuRum;
grid.loadMenuHandler(this,"gridMenuInit");
grid.selectMenuHandler(this,"gridMenuRum");
oGridEdit = new DpGridEdit(grid);
oGridEdit.canEdit = canEditRecord;
oGridEdit.saveRecord = saveRecord;
}
function saveRecord()
{
var rowID = parseInt(grid.getTable().getValue("fwid"));
var oRow = objCl.getRow(sRowClass, rowID);
if (oRow == null)
{
oRow = objCl.createRow(sRowClass);
oRow.setID(rowID);
objCl.appendRow(sRowClass, oRow);
}
with (oRow)
{
setVar("RPARNAME", gridTbl.getValue("FPARNAME"));
setVar("RPARZNACH", gridTbl.getValue("FPARZNACH"));
}
return true;
}
function canEditRecord()
{
return true;
}
function gridMenuInit(grid)
{
grid.AddMenuItem("ADD","Додати|Добавить");
if (!grid.getTable().isEmpty())
{
grid.AddMenuItem("EDIT","Редагувати|Редактировать");
grid.AddMenuItem("COPY","Копіювати|Копировать");
grid.AddMenuItem("DEL","Видалити|Удалить");
}
}
function gridMenuRum(sID, grid)
{
var tbl = grid.getTable();
var tName = tbl.getTableName();
var rowID = tbl.getValue("FWID");
switch(sID)
{
case "DEL":
var nGridPos = grid.getRowSelected();
ExecuteSQL("delete From "+ tName
+" where Fwid="+ sqlTo(rowID));
objCl.deleteRow(sRowClass, rowID);
tbl.requery();
tbl.setAbsolute(nGridPos-1);
grid.refresh();
break;
case "ADD": case "EDIT": case "COPY":
var oRow;
if(sID == "ADD")
oRow = objCl.createRow(sRowClass);
else if(sID == "EDIT")
oRow = objCl.getRow(sRowClass, rowID);
else if(sID == "COPY")
oRow = objCl.copyRow(sRowClass, rowID);
if(!oRow)
break;
if (!rowEdit(sID, oRow))
break;
tbl.requery();
grid.refresh();
break;
}
return true;
}
function onSave()
{
ctrlLinker.toVars();
storeToDb(sRowTbl, sTmpTbl);
exit();
}
function rowEdit(sMode, oRow)
{
var par = new Object();
par.dpObj = oRow;
par.mode = sMode;
par.tblName = sTmpTbl;
par.dpObj.hasExt = hasExt;
par.formFile = "cls/"+ objCl.sClassId +"/KLROWS/form.xml";
showWindow(par.formFile, "XMLDLG", par);
if(par.escape)
return false;
var id = oRow.getID();
if(inList(sMode, "ADD", "COPY"))
objCl.appendRow(sRowClass, oRow);
obj2DB(id, oRow.jObj, null, sTmpTbl);
return true;
}
function hasExt()
{
return false;
}
function storeToDb(sTbl, tmpTbl)
{
var sFld = GetPatternIntersection (sTbl, sTbl);
ExecuteSQL("DELETE FROM ^"+ sTbl +" WHERE FWID_CL="+ sqlTo(objCl.getID()));
ExecuteSQL("UPDATE "+ tmpTbl +" SET Fwid_cl="+ sqlTo(objCl.getID()));
ExecuteSQL("INSERT INTO ^"+ sTbl +" ("+ sFld +")"
+" SELECT "+ sFld +" FROM "+ tmpTbl);
}
function exit()
{
gridTbl.close();
DropTable(sTmpTbl);
}
include("sys/DpBaseDlg.js");
Грід завантажується на форму та ініціалізується функцією loadGrid. Поля на формі прив'язуються до змінних класу з допомогою об'єкту ctrlLinker. Це дає можливість зручного збереження даних та завантаження даних на форму. Все інше – це оброблення даних. Шукайте описання об'єктів і функцій в файлах бізнес-логіки системи “Дебет Плюс V12”.
Один момент. Описання гріду, який знаходиться на формі знаходиться в файлі l_kompllist.xml. Ось його літинг.
Лістинг 8
<?xml version="1.0" encoding="UTF-8"?>
<grid>
<field field="=tcl('CL','TXT',250,FPARNAME)" text="Параметр|Параметр" width="20" />
<field field="FPARZNACH" text="Значення|Значение" width="30" />
</grid>
Для успішного виконання коду потрібно створити довідник аналітики №250 “Характеристики комплектуючих”.
<Тепер створимо клас для додавання рядків. Оскільки ми повністю розробили один клас , то нема проблеми розібратись як зробити інший.
В папці Scripts/Cls/Назва довідника стпоримо папку KLROWS. В ній чотири файли. Навожу без коментарів.
class.xml
<?xml version="1.0" encoding="utf-8"?>
<DpCl type="KLROWS">
<Header>
<var name="RWID_CL" datatype="long"/>
<var name="RPARNAME" datatype="text"/>
<var name="RPARZNACH" datatype="text"/>
</Header>
</DpCl>
dpmapping.xml
<?xml version="1.0" encoding="utf-8"?>
<DpCl type="KLROWS">
<Header>
<Tables>
<table name="CL_KOPML_ROWS"/>
</Tables>
<Fields>
<field name="FWID_CL" table="CL_KOMPL_ROWS" var="RWID_CL"/>
<field name="FPARNAME" table="CL_KOPML_ROWS" var="RPARNAME"/>
<field name="FPARZNACH" table="CL_KOPML_ROWS" var="RPARZNACH"/>
</Fields>
</Header>
</DpCl>
form.xml
<?xml version="1.0" encoding="utf-8" ?>
<Form>
<Controls col="4" >
<ComboBox ID="FPARNAME">
<option selected="true" value="-">---</option>
</ComboBox>
<Label text="Значення|Значение"/>
<TextField ID="FPARZNACH" width="130" colspan="2"/>
</Controls>
<script languige="JavaScript" src="form.js"/>
</Form>
form.js
include("Objects/DpVal.js");
include("Objects/DpBank.js");
var obj = extPar.dpObj;
var oVal;
var ctrlLinker;
function onLoad()
{
Caption(ru("Комплектующие", "Комплектуючі")
+ ": " + modeName(extPar.mode));
//Блок для заповнення списку ComboBox з довідника аналітики № 250
var tt = OpenTable("Select a.FCOD,b.FWID,b.FTXT, a.FWID_CL From ^CL b, ^CLRELCLCL a WHERE b.FWID=a.FWID_CL and a.FCL=250 ORDER BY b.FTXT");
for(tt.MoveFirst();!tt.IsEOF();tt.MoveNext())
{
var sVal = tt.getValue("FCOD");
var sTxt = tt.getValue("FTXT");
FPARNAME.addItem(sVal,sTxt);
}
FPARNAME.selectedIndex = obj.getVar("RPARNAME");
//showObject(obj);
//Кінець блоку
ctrlLinker = new DpCtrlLinker(obj);
ctrlLinker.addLink("RPARNAME", FPARNAME);
ctrlLinker.addLink("RPARZNACH", FPARZNACH);
ctrlLinker.updateData(false);
}
function onSave()
{
ctrlLinker.updateData(true);
}
function hasExt()
{
// return false;
}
include("sys\\DpBaseDlg.js");
Тепер додамо довідник аналітики створеного типу і от, що в нас вийшло: