Румяна Цанкова Владимир Л. Станчев Работа с бази от данни в примери на access 2003 2007


Глава 17. Задача за “Специфициране на материали” с решение чрез VBA, ADO и SQL



страница17/20
Дата13.11.2018
Размер3.1 Mb.
#104752
ТипГлава
1   ...   12   13   14   15   16   17   18   19   20

Глава 17. Задача за “Специфициране на материали” с решение чрез VBA, ADO и SQL

    1. Обща постановка, проект на база от данни и идея за алгоритъм


Някои задачи изискват работа с позаписно процедурно програмиране. Такава например е задачата за Специфициране на материали, известна в литературата като Bill of materials. За да се определи например общото количество от всеки материал за производството на изделията, не е достатъчно само познаването на производствената програма. Ако това е една монтажна спецификация, необходимо е да се изпълни алгоритъм, който да определи общия брой от всеки детайл в едно изделие. И тъй като даден детайл може да участвува в много възли, които от своя страна да участвуват в други по-високо стоящи възли, налага се една рекурсивна обработка на отделните мрежово свързани записи. В този случай базата от данни се изгражда в Access, а съответното извеждане се прави с процедурен език, напр. VBA. За отразяването на йерархичните връзки се организира отделна таблица на структурата (Struktura) – фиг. 17.1.


Фиг. 17.1. Проект на таблица за структурата на монтажно изделие.


Както се вижда структурната схема е мрежова:



Конкретните данни за структурата на изделието са показани на фиг. 17.2.


Фиг. 17.2. Данни за таблица Struktura.
Тук под Продукт No (ProductNom ) се разбира съставен компонент – изделие или възел, който съдържа друг съставен или не компонент, носещ името Детайл No (DetailNom). В същност всеки ред на таблицата съдържа една йерархическа връзка – един компонент-родител съдържа друг компонент- наследник в някакво количество, различно от нула. Затова един и същ компонент може да се срещне и като Продукт No и като Детайл No – например виж компонент 70300. Също така един и същ Детайл No може да се срещне и в различни Продукт No – например виж компонент 070107. Това показва, че този компонент има повече от един родители и е носител на мрежова връзка. Главният ключ е съставен: Изделие (Izdelie), Продукт No (ProductNom ), Детайл No (DetailNom). Именно тези особености изискват използването на позаписно ориентиран програмен език. Свойството Унифициран (Unificiran) показва дали съответният наследник се взема като готов недекомпозиран продукт.

Проектът на таблицата за всички компоненти (детайли, възли и изделия) Komponenti и данните за тях са дадени съответно на фиг. 17.3. и фиг. 17.4. Главният ключ е Детайл No (DetailNom). Тук разходната норма (RazhodNorm) е в мярка kg. За да се спазят изискванията за цялостност (всеки Детайл No от таблица Struktura да е включен предварително в таблица Komponenti), тук като компоненти са включени и всички възли и изделия. Тяхната разходна норма е приета условно с нулева стойност, а за стандартните компоненти като гайки, винтове, болтове, шпилки и други подобни - единица. Полето за материал в таблицата Komponenti за възлите и изделията има същата стойност както полето за наименование, тъй като в този случай двете полета са с идентични стойности.




Фиг. 17.3. Проект за таблица Komponenti.



Фиг.17.4. Данни за таблица Komponenti

За да може да се създаде спецификация на материалите, е необходима и таблица за производствената програма - Programa. Проектът за нея е показан на фиг. 17.5, а конкретните данни – на фиг. 17.6. Ако искаме да се спазят изискванията за цялост (всеки Продукт No от таблица Struktura да е включен предварително в таблица Programa), тук като продукти трябва да се включат и всички възли. В този случай обаче тяхното количество условно трябва да се зададе с нулева стойност.

Като имаме пред вид броя на детайлите и продуктите, решаваме техните номенклатури да са изградени на фасетен принцип, кодът да е шестпозиционен, изграден по следната схема на кодиране:

ХХХ ХХХ


½ ½____________ типоразмер

½___________________ разновидност, габарит



Фиг. 17.5. Проект на таблица Programa.

Фиг. 17.6. Данни за таблица Programa.
Концептуалният модел на базата от данни е даден на фиг. 17.7.
Фиг. 17.7. Концептуален модел на база от данни за специфициране на материали

17.2. Решение чрез ACCESS с VBA, ADO и SQL

Решението на задачата на основата на базата от данни с таблици и входни данни представени в глава 17.1. може да се постигне чрез ACCESS при използване на Visual Basic for Application (VBA), ActiveX Data Objects (ADO)


и Structured Query Language (SQL). Последователността на конкретното решение има следните осем стъпки:
17.2.1. Актуализация на входните данни в таблици: Struktura, Komponenti и Programa

Актуализацията, ако е необходима, може да се направи с директно внасяне на данни в таблиците.



17.2.2. Проектиране на формуляр ObKol за поддръжка на таблица Struktura и добавяне към този формуляр на бутон за стартиране на всички обработки и изчисления в последователността на решението.
Проектирането на формуляра се постига по примера даден в глава 12. Кодът “2” в поле Unificiran означава, че детайлът е унифициран (структурата на такъв детайл вече е записана в таблица Struktura). Затова унифицираните детайли в таблицата се записват съкратено (без да се записва тяхната структура, ако имат такава).

Фиг. 17.8. Формуляр за поддръжка на данните в таблица Struktura и бутон за пускане в действие на изчисляването на разхода на материали.
В режим Design (за формуляра) бутонът „Изчисляване на разход на материали” (с име на контрола Command10), трябва чрез контекстното меню Properties / Event / On Click (събитие - щракване с мишката) да бъде свързан с процедура за обработка на събитие - Event Procedure. Тази процедура в конкретното решение се нарича Command10_Click.
17.2.3. Проектиране на работна таблица ObshtoKolich за запазване на междинните резултати при изчислителната работа в решението.

Фиг. 17.9. Работната таблица ObshtoKolich в режим на проектиране.


Работната таблица е подобна на таблица Struktura и съдържа няколко допълнителни полета. Проектирането е показано на фиг. 17.9.

17.2.4. Решение на задачата чрез програмен код написан на Visual Basic for Application (с ADO и SQL).
Програмният код - Form ObKol Code e свързан с формата – ObKol и се състои от четири части.


  • Първата част на кода е записана в областта на декларациите – General Declarations. Декларирани са масив и променливи, две от които се свързани с възможността да се осигури достъп до таблиците на базата от данни чрез активния обект - ADODB. Обектите от тип ActiveX Data Objects (ADO) дават възможност (през OLE DB доставчик) да се отвори клиентско приложение за достъп и манипулация в базата данни, намираща се на сървър. В тази част се съдържа следният код:

Option Compare Database

Dim mas(1000, 9)

Dim TableIn, TableOut As String

Dim conn As ADODB.Connection

Dim rst As ADODB.Recordset

Dim SQL_x As String




  • Втората част на кода е подпрограма - Command10_Click

записана в областта Form Click и се изпълнява при възникване на събитието On Click (щракване с мишката при натискане на бутона във формата). Тази подпрограма задава имена на входната и изходната – резултатната таблици и извиква (Call) за изпълнение подпрограмата - CreateTab. В тази част се съдържа следният код:
'Ïðè íàòèñêàíå íà áóòîí

Private Sub Command10_Click()

TableIn = "Struktura"

TableOut = "ObshtoKolich"

Call CreateTab

End Sub


  • Третата част на кода е подпрограма - CreateTab, записана в областта General CreateTab Тя се изпълнява след извикване от подпрограма Command10_Click. В CreateTab са реализирани основните стъпки на решението. Използвани са обекти на ADO и заявки на SQL. Действието на частите на тази подпрограма е коментирано в нейния код:


Private Sub CreateTab()

‘ Контролиране на възникването на грешки при изпълнение

On Error GoTo Err_CreateTab

'Код на декларациите

Dim Izdelie, ProduktNom, DetailNom, Unificiran As String

Dim Kolichestvo, Rod As Integer

Dim Programa As Integer

Dim ObshtoKolichestvo As Double

Set conn = CurrentProject.Connection

' open client-side recordset

Set rst = New ADODB.Recordset

rst.CursorLocation = adUseClient


'Èçïúëíåíèå íà SQL çàÿâêà çà èçòðèâàíe íà записите â òàáëèöà ObshtoKolich
SQL_x = "delete from " & TableOut

rst.Open SQL_x, conn, adOpenStatic, adLockReadOnly


'Èçïúëíåíèå íà SQL çàÿâêà çà ïðåõâúðëÿíå íà äàííè

‘от òàáëèöà Struktura â òàáëèöà ObshtoKolich


SQL_x = "INSERT INTO " & TableOut & "(Izdelie, ProduktNom,DetailNom,Unificiran,Kolichestvo) " _

& " SELECT Izdelie,ProduktNom,DetailNom,Unificiran,Kolichestvo from " & TableIn

rst.Open SQL_x, conn, adOpenStatic, adLockReadOnly

DoCmd.Close acTable, TableOut, acSaveYes


'Èçïúëíåíèå íà SQL çà ñîðòèðàíå íà òàáëèöà ObshtoKolich

SQL_x = TableOut

rst.Open SQL_x, conn, adOpenKeyset, adLockOptimistic, adCmdTable

' sort the recordset ascending

rst.Sort = "Izdelie ASC, DetailNom ASC, ProduktNom ASC "

' Çàòâàðÿíå íà îòâîðåíèòå äî ìîìåíòà òàáëèöè è çàÿâêè

DoCmd.Close acTable, TableOut, acSaveYes

DoCmd.Close acQuery, "ObshtoKolichQuery", acSaveYes

DoCmd.Close acQuery, "RazhodMateriasliQuery", acSaveYes

' Èçïúëíåíèå íà ïðîöåäóðà çà áðîåíå íà çàïèñèòå â TableOut

Call CountRecords(CountRec)

' Ïðî÷èòàíå íà äàííèòå îò TableOut è çàïèñване â масив MAS ===========

kursor2 = 1 '

Set conn = CurrentProject.Connection

Set rst = New ADODB.Recordset

SQL_x = TableOut

rst.Open SQL_x, conn, adOpenStatic, adLockReadOnly

RowKursor = 0

rst.MoveFirst

Do Until rst.EOF

RowKursor = RowKursor + 1

mas(RowKursor, 1) = rst!Izdelie

mas(RowKursor, 2) = rst!ProduktNom

mas(RowKursor, 3) = rst!DetailNom

mas(RowKursor, 4) = rst!Unificiran

mas(RowKursor, 5) = rst!Kolichestvo

mas(RowKursor, 6) = rst!Kolichestvo

mas(RowKursor, 7) = ""

mas(RowKursor, 8) = ""

mas(RowKursor, 9) = 0

rst.MoveNext

Loop


RowKursor = RowKursor + 1

mas(RowKursor, 1) = 9999

rst.Close 'end read ot TableOut =====================

CountRec = RowKursor

' Ïîïúëâàíå ñ äàííè íà ïîëåòî Rod за определяне на номера на предходния детайл в структурата.

‘<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

kursor2 = 0

Do While mas(kursor2, 1) <> 9999

kursor2 = kursor2 + 1

Izdelie2 = mas(kursor2, 1)

ProduktNom2 = mas(kursor2, 2)

DetailNom2 = úmas(kursor2, 3)

kursor3 = 1

Do While mas(kursor3, 1) <> 9999

izdelie3 = mas(kursor3, 1)

ProduktNom3 = mas(kursor3, 2)

DetailNom3 = mas(kursor3, 3)

If ProduktNom3 = DetailNom2 And izdelie3 = Izdelie2 Then

mas(kursor3, 9) = kursor2 ' Rod

End If


kursor3 = kursor3 + 1

Loop


loop1: Loop ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

' Ïîêàçâàíå - ðàçãúâàíå íà ñòðóêòóðàòà íà óíèôèöèðàíèòå äåòàéëè

kursor2 = 0

Do While mas(kursor2, 1) <> 9999

kursor2 = kursor2 + 1

If IsNull(mas(kursor2, 4)) Then GoTo loopa

If mas(kursor2, 4) <> "2" Then GoTo loopa

Izdelie2 = mas(kursor2, 1)

ProduktNom2 = mas(kursor2, 2)

DetailNom2 = mas(kursor2, 3)

Unificiran2 = mas(kursor2, 4)

Kolichestvo2 = mas(kursor2, 5)

Rod2 = mas(kursor2, 9)

kursor3 = 1

Do While mas(kursor3, 1) <> 9999

izdelie3 = mas(kursor3, 1)

ProduktNom3 = mas(kursor3, 2)

DetailNom3 = mas(kursor3, 3)

Unificiran3 = mas(kursor3, 4)

Kolichestvo3 = mas(kursor3, 5)

rod3 = mas(kursor3, 9)

If ProduktNom3 = DetailNom2 And Unificiran3 = "1" Then

mas(CountRec, 1) = Izdelie2

mas(CountRec, 2) = ProduktNom3

mas(CountRec, 3) = DetailNom3

mas(CountRec, 4) = "2" 'Unificiran

mas(CountRec, 5) = Kolichestvo3

mas(CountRec, 6) = Kolichestvo3

mas(CountRec, 9) = kursor2 'Rod

mas(CountRec + 1, 1) = 9999

CountRec = CountRec + 1

End If

kursor3 = kursor3 + 1



Loop 'za tarsene v cialata tablica na ProduktNom

'(ot Izdelie2) raven na DetailNom2

loopa: Loop ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

‘Изчисляване на количеството

MultiKolichestvo: kursor3 = 0

Do While mas(kursor3, 1) <> 9999

kursor3 = kursor3 + 1

rod3 = mas(kursor3, 9)

If rod3 = 0 Then GoTo loop3

kursor4 = kursor3

Do While mas(kursor4, 1) <> 9999

KursorRod = mas(kursor4, 9)

If KursorRod = 0 Then Exit Do

mas(kursor3, 6) = mas(kursor3, 6) * mas(KursorRod, 5)

kursor4 = mas(kursor4, 9)

Loop

loop3: Loop ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>



'Çàïèñ íà ðåçóëòàòите îò MAS â TableOut <<<<<<<<<<<<<<<<<

SQL_x = "delete from " & TableOut

rst.Open SQL_x, conn, adOpenStatic, adLockReadOnly

DoCmd.Close acTable, TableOut, acSaveYes

SQL_x = TableOut

rst.Open SQL_x, conn, adOpenKeyset, adLockOptimistic, adCmdTable

RowKursor = 1

Do

If mas(RowKursor, 1) = 9999 Then Exit Do



rst.AddNew

rst!Izdelie = mas(RowKursor, 1)

If IsEmpty(mas(RowKursor, 2)) Then Exit Do

rst!ProduktNom = mas(RowKursor, 2)

rst!DetailNom = mas(RowKursor, 3)

rst!Unificiran = mas(RowKursor, 4)

rst!Kolichestvo = mas(RowKursor, 5)

rst!ObshtoKolichestvo = mas(RowKursor, 6)

'rst!Programa = mas(RowKursor, 7)

rst!Sleda = RowKursor

rst!Rod = mas(RowKursor, 9)

rst.Update

RowKursor = RowKursor + 1

Loop '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

DoCmd.Close acTable, TableOut, acSaveYes

DoCmd.SetWarnings False


' Çàÿâêà (активна) çà âúâåæäàíå â òàáëèöà ObshtoKolich

' íà êîëè÷eñòâî îò òàáëèöà Programa

DoCmd.OpenQuery "ProgramaUpdateQuery", , acEdit

' Îòâàðÿíå íà òàáëèöà TableOut

DoCmd.OpenTable TableOut

' Çàÿâêà çà èç÷èñëÿâàíå íà ObshtoKolich

DoCmd.OpenQuery "ObshtoKolichQuery", , acEdit

' Çàÿâêà çà èç÷èñëÿâàíå íà RazhodMateriali

DoCmd.OpenQuery "RazhodMaterialiQuery", , acEdit

DoCmd.SetWarnings True

Exit_CreateTab:

Exit Sub


Err_CreateTab:

MsgBox Err.Description, vbCritical, "ÑÌ"

Resume Exit_CreateTab

End Sub



  • Четвъртата част на кода е подпрограма - CountRecords, записана в областта General CountRecords Тя се изпълнява след извикване от подпрограма CreateTab. Чрез CountRecords се изброяват записите в TableOut. Действието на тази подпрограма е показано в нейния код:

'Подпрограма за иçáðîÿâàíå íà çàïèñèòå â TableOut

Private Sub CountRecords(RowKursor)

Set conn = CurrentProject.Connection

Set rst = New ADODB.Recordset

SQL_x = TableOut

rst.Open SQL_x, conn, adOpenKeyset, adLockOptimistic, adCmdTable

RowKursor = 0

Do Until rst.EOF

RowKursor = RowKursor + 1

rst.MoveNext

Loop


msg1 = "Count Records!: " & Str(RowKursor)

MsgBox msg1, vbÎÊ, "ÑÌ"

rst.Close

End Sub
17.2.5. Проектиране и действие на заявка - ProgramaUpdateQuery за въвеждане в таблица ObshtoKolich на количеството от таблица Programa


Заявката за промяна – ProgramaUpdateQuery на данни в таблица ObshtoKolich се изгражда по примера в глава 9.7. Въвежда се стойността на поле Kolichestvo в поле Programa. Проектирането е показано на фиг. 17.10.

Фиг. 17.10. Заявката ProgramaUpdateQuery в Design View.

Заявката ProgramaUpdateQuery се изпълнява след извикване в подпрограма CreateTab.
17.2.6. Показване на съдържанието на помощната таблица ObshtoKolich след действието на подпрограма CreateTab и заявката ProgramaUpdateQuery

Задействането на показването на таблица ObshtoKolich се прави от подпрограма CreateTab чрез команда: DoCmd.OpenTable TableOut




Фиг. 17.11. Таблица ObshtoKolich с резултати.
17.2.7. Проектиране и действие на заявка - ObshtoKolichQuery за изчисляване в таблица ObshtoKolich на общото количество и разхода на материали по детайли.
Заявката ObshtoKolichQuery за за изчисляване от таблица ObshtoKolich на общото количество и разхода на материали се изгражда по примера в глава 9. Проектирането е показано на фиг. 17.12.1 и фиг. 17.12.2. Заявката ProgramaUpdateQuery се изпълнява след извикване в подпрограма CreateTab.

Фиг. 17.12.1. Заявка ObshtoKolichQuery – Design View част 1.


Фиг. 17.12.2. Заявка ObshtoKolichQuery – Design View част 2.




Фиг. 17.13. Резултати в заявка ObshtoKolichQuery – Datasheet View.

17.2.8. Проектиране и действие на заявка - RazhodMaterialiQuery за сумиране по имена на материали на разхода на материали от заявка ObshtoKolichQuery
Заявката RazhodMaterialiQuery показва сумираните разходи, сортирани и групирани по име на материал. Тя е проектирана (фиг. 17.14.) по примера в глава 9. Заявката RazhodMaterialiQuery се изпълнява след извикване в подпрограма CreateTab чрез команда:

DoCmd.OpenQuery "RazhodMaterialiQuery", , acEdit


Заявката RazhodMaterialiQuery представя крайния резултат на решението на задачата (фиг. 17.15.).

Фиг. 17.14. Заявка RazhodMaterialiQuery – Design View.

Фиг. 17.15. Крайният резултат на решението в заявка RazhodMaterialiQuery – DatasheetView.


Част IV. SQL в ACCESS и Многопотребителски бази от данни


Приложение на SQL в ACCESS






Сподели с приятели:
1   ...   12   13   14   15   16   17   18   19   20




©obuch.info 2024
отнасят до администрацията

    Начална страница