ToyWorldDb.bas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. Attribute VB_Name = "ToyWorldDb"
  2. Option Explicit
  3. ' Òåìà "èãðóøêè": ñõåìà ÁÄ çàøèòà, äàííûå áåðóòñÿ èç ëèñòîâ êíèãè.
  4. ' Ëèñòû îïðåäåëÿþòñÿ ïî çàãîëîâêàì: òîâàðû / ïîëüçîâàòåëè / çàêàçû / ïóíêòû âûäà÷è.
  5. ' Ðåçóëüòàò -> generated.sql ðÿäîì ñ êíèãîé. Çàïóñê: Alt+F8 -> GenerateToyDb.
  6. Private buf As String
  7. Public Sub GenerateToyDb()
  8. buf = ""
  9. Emit SchemaSql()
  10. SeedSql
  11. Emit ViewsSql()
  12. WriteUtf8 ActiveWorkbook.Path & "\generated.sql", buf
  13. MsgBox "Ãîòîâî:" & vbCrLf & ActiveWorkbook.Path & "\generated.sql", vbInformation
  14. End Sub
  15. Private Sub Emit(ByVal s As String)
  16. buf = buf & s & vbCrLf
  17. End Sub
  18. Private Function SchemaSql() As String
  19. Dim s As String
  20. s = "IF DB_ID('ToyWorldDb') IS NULL CREATE DATABASE ToyWorldDb;" & vbCrLf & "GO" & vbCrLf
  21. s = s & "USE ToyWorldDb;" & vbCrLf & "GO" & vbCrLf
  22. s = s & "IF OBJECT_ID('dbo.OrderItem','U') IS NOT NULL DROP TABLE dbo.OrderItem;" & vbCrLf
  23. s = s & "IF OBJECT_ID('dbo.[Order]','U') IS NOT NULL DROP TABLE dbo.[Order];" & vbCrLf
  24. s = s & "IF OBJECT_ID('dbo.Product','U') IS NOT NULL DROP TABLE dbo.Product;" & vbCrLf
  25. s = s & "IF OBJECT_ID('dbo.[User]','U') IS NOT NULL DROP TABLE dbo.[User];" & vbCrLf
  26. s = s & "IF OBJECT_ID('dbo.PickupPoint','U') IS NOT NULL DROP TABLE dbo.PickupPoint;" & vbCrLf
  27. s = s & "IF OBJECT_ID('dbo.OrderStatus','U') IS NOT NULL DROP TABLE dbo.OrderStatus;" & vbCrLf
  28. s = s & "IF OBJECT_ID('dbo.Category','U') IS NOT NULL DROP TABLE dbo.Category;" & vbCrLf
  29. s = s & "IF OBJECT_ID('dbo.Manufacturer','U') IS NOT NULL DROP TABLE dbo.Manufacturer;" & vbCrLf
  30. s = s & "IF OBJECT_ID('dbo.Supplier','U') IS NOT NULL DROP TABLE dbo.Supplier;" & vbCrLf
  31. s = s & "IF OBJECT_ID('dbo.Unit','U') IS NOT NULL DROP TABLE dbo.Unit;" & vbCrLf
  32. s = s & "IF OBJECT_ID('dbo.Role','U') IS NOT NULL DROP TABLE dbo.Role;" & vbCrLf & "GO" & vbCrLf
  33. s = s & "CREATE TABLE dbo.Role (RoleId INT IDENTITY(1,1) CONSTRAINT PK_Role PRIMARY KEY, RoleName NVARCHAR(50) NOT NULL CONSTRAINT UQ_Role UNIQUE);" & vbCrLf
  34. s = s & "CREATE TABLE dbo.Unit (UnitId INT IDENTITY(1,1) CONSTRAINT PK_Unit PRIMARY KEY, UnitName NVARCHAR(20) NOT NULL CONSTRAINT UQ_Unit UNIQUE);" & vbCrLf
  35. s = s & "CREATE TABLE dbo.Supplier (SupplierId INT IDENTITY(1,1) CONSTRAINT PK_Supplier PRIMARY KEY, SupplierName NVARCHAR(100) NOT NULL CONSTRAINT UQ_Supplier UNIQUE);" & vbCrLf
  36. s = s & "CREATE TABLE dbo.Manufacturer (ManufacturerId INT IDENTITY(1,1) CONSTRAINT PK_Manufacturer PRIMARY KEY, ManufacturerName NVARCHAR(100) NOT NULL CONSTRAINT UQ_Manufacturer UNIQUE);" & vbCrLf
  37. s = s & "CREATE TABLE dbo.Category (CategoryId INT IDENTITY(1,1) CONSTRAINT PK_Category PRIMARY KEY, CategoryName NVARCHAR(100) NOT NULL CONSTRAINT UQ_Category UNIQUE);" & vbCrLf
  38. s = s & "CREATE TABLE dbo.OrderStatus (StatusId INT IDENTITY(1,1) CONSTRAINT PK_OrderStatus PRIMARY KEY, StatusName NVARCHAR(50) NOT NULL CONSTRAINT UQ_OrderStatus UNIQUE);" & vbCrLf & "GO" & vbCrLf
  39. s = s & "CREATE TABLE dbo.[User] (UserId INT IDENTITY(1,1) CONSTRAINT PK_User PRIMARY KEY, RoleId INT NOT NULL CONSTRAINT FK_User_Role REFERENCES dbo.Role(RoleId), FullName NVARCHAR(150) NOT NULL, Login NVARCHAR(100) NOT NULL CONSTRAINT UQ_User_Login UNIQUE, Password NVARCHAR(100) NOT NULL);" & vbCrLf
  40. s = s & "CREATE TABLE dbo.PickupPoint (PickupPointId INT NOT NULL CONSTRAINT PK_PickupPoint PRIMARY KEY, PostalCode NVARCHAR(10) NOT NULL, City NVARCHAR(80) NOT NULL, Street NVARCHAR(120) NOT NULL, House NVARCHAR(20) NOT NULL);" & vbCrLf
  41. s = s & "CREATE TABLE dbo.Product (ProductId INT IDENTITY(1,1) CONSTRAINT PK_Product PRIMARY KEY, Article NVARCHAR(10) NOT NULL CONSTRAINT UQ_Product_Article UNIQUE, Name NVARCHAR(255) NOT NULL, UnitId INT NOT NULL CONSTRAINT FK_Product_Unit REFERENCES dbo.Unit(UnitId), Price DECIMAL(10,2) NOT NULL CONSTRAINT CK_Price CHECK (Price>=0), SupplierId INT NOT NULL CONSTRAINT FK_Product_Supplier REFERENCES dbo.Supplier(SupplierId), ManufacturerId INT NOT NULL CONSTRAINT FK_Product_Manufacturer REFERENCES dbo.Manufacturer(ManufacturerId), CategoryId INT NOT NULL CONSTRAINT FK_Product_Category REFERENCES dbo.Category(CategoryId), Discount INT NOT NULL CONSTRAINT CK_Disc CHECK (Discount BETWEEN 0 AND 100), Stock INT NOT NULL CONSTRAINT CK_Stock CHECK (Stock>=0), Description NVARCHAR(MAX) NULL, Photo NVARCHAR(100) NULL);" & vbCrLf
  42. s = s & "CREATE TABLE dbo.[Order] (OrderId INT NOT NULL CONSTRAINT PK_Order PRIMARY KEY, OrderDate DATE NULL, DeliveryDate DATE NULL, PickupPointId INT NOT NULL CONSTRAINT FK_Order_Pickup REFERENCES dbo.PickupPoint(PickupPointId), ClientUserId INT NULL CONSTRAINT FK_Order_User REFERENCES dbo.[User](UserId), ReceiveCode INT NULL, StatusId INT NOT NULL CONSTRAINT FK_Order_Status REFERENCES dbo.OrderStatus(StatusId));" & vbCrLf
  43. s = s & "CREATE TABLE dbo.OrderItem (OrderItemId INT IDENTITY(1,1) CONSTRAINT PK_OrderItem PRIMARY KEY, OrderId INT NOT NULL CONSTRAINT FK_Item_Order REFERENCES dbo.[Order](OrderId) ON DELETE CASCADE, Article NVARCHAR(10) NOT NULL CONSTRAINT FK_Item_Product REFERENCES dbo.Product(Article), Quantity INT NOT NULL CONSTRAINT CK_Qty CHECK (Quantity>0), CONSTRAINT UQ_Item UNIQUE (OrderId, Article));" & vbCrLf & "GO" & vbCrLf
  44. SchemaSql = s
  45. End Function
  46. Private Function ViewsSql() As String
  47. Dim s As String
  48. s = "IF OBJECT_ID('dbo.vCatalog','V') IS NOT NULL DROP VIEW dbo.vCatalog;" & vbCrLf & "GO" & vbCrLf
  49. s = s & "CREATE VIEW dbo.vCatalog AS SELECT p.Article, p.Photo AS [Ôîòî], c.CategoryName AS [Êàòåãîðèÿ òîâàðà], p.Name AS [Íàèìåíîâàíèå òîâàðà], p.Description AS [Îïèñàíèå òîâàðà], m.ManufacturerName AS [Ïðîèçâîäèòåëü], s.SupplierName AS [Ïîñòàâùèê], p.Price AS [Öåíà], u.UnitName AS [Åäèíèöà èçìåðåíèÿ], p.Stock AS [Êîë-âî íà ñêëàäå], p.Discount AS [Äåéñòâóþùàÿ ñêèäêà] FROM dbo.Product p JOIN dbo.Category c ON p.CategoryId=c.CategoryId JOIN dbo.Manufacturer m ON p.ManufacturerId=m.ManufacturerId JOIN dbo.Supplier s ON p.SupplierId=s.SupplierId JOIN dbo.Unit u ON p.UnitId=u.UnitId;" & vbCrLf & "GO" & vbCrLf
  50. s = s & "IF OBJECT_ID('dbo.vOrders','V') IS NOT NULL DROP VIEW dbo.vOrders;" & vbCrLf & "GO" & vbCrLf
  51. s = s & "CREATE VIEW dbo.vOrders AS SELECT o.OrderId, STRING_AGG(oi.Article + N' x' + CAST(oi.Quantity AS nvarchar(10)), N', ') AS [Àðòèêóë çàêàçà], st.StatusName AS [Ñòàòóñ çàêàçà], (pp.PostalCode + ', ã. ' + pp.City + ', óë. ' + pp.Street + ', ä. ' + pp.House) AS [Àäðåñ ïóíêòà âûäà÷è], o.OrderDate AS [Äàòà çàêàçà], o.DeliveryDate AS [Äàòà äîñòàâêè] FROM dbo.[Order] o JOIN dbo.OrderStatus st ON o.StatusId=st.StatusId JOIN dbo.PickupPoint pp ON o.PickupPointId=pp.PickupPointId LEFT JOIN dbo.OrderItem oi ON oi.OrderId=o.OrderId GROUP BY o.OrderId, st.StatusName, pp.PostalCode, pp.City, pp.Street, pp.House, o.OrderDate, o.DeliveryDate;" & vbCrLf & "GO" & vbCrLf
  52. s = s & "IF OBJECT_ID('dbo.vw_UsersLogin','V') IS NOT NULL DROP VIEW dbo.vw_UsersLogin;" & vbCrLf & "GO" & vbCrLf
  53. s = s & "CREATE VIEW dbo.vw_UsersLogin AS SELECT u.UserId, u.FullName AS [ÔÈÎ], u.Login AS [Ëîãèí], u.Password AS [Ïàðîëü], r.RoleName AS [Ðîëü] FROM dbo.[User] u JOIN dbo.Role r ON u.RoleId=r.RoleId;" & vbCrLf & "GO" & vbCrLf
  54. ViewsSql = s
  55. End Function
  56. Private Sub SeedSql()
  57. Dim wsP As Worksheet, wsU As Worksheet, wsO As Worksheet, wsK As Worksheet, ws As Worksheet
  58. For Each ws In ActiveWorkbook.Worksheets
  59. If HasHeader(ws, "Àðòèêóë çàêàçà") Then
  60. Set wsO = ws
  61. ElseIf HasHeader(ws, "Ëîãèí") Then
  62. Set wsU = ws
  63. ElseIf HasHeader(ws, "Àðòèêóë") Then
  64. Set wsP = ws
  65. ElseIf Trim(CStr(ws.Cells(1, 1).Value)) <> "" Then
  66. Set wsK = ws
  67. End If
  68. Next ws
  69. ' ñïðàâî÷íèêè
  70. If Not wsU Is Nothing Then DictInsert wsU, "Ðîëü ñîòðóäíèêà", "dbo.Role", "RoleName"
  71. If Not wsP Is Nothing Then
  72. DictInsert wsP, "Åäèíèöà èçìåðåíèÿ", "dbo.Unit", "UnitName"
  73. DictInsert wsP, "Ïîñòàâùèê", "dbo.Supplier", "SupplierName"
  74. DictInsert wsP, "Ïðîèçâîäèòåëü", "dbo.Manufacturer", "ManufacturerName"
  75. DictInsert wsP, "Êàòåãîðèÿ òîâàðà", "dbo.Category", "CategoryName"
  76. End If
  77. If Not wsO Is Nothing Then DictInsert wsO, "Ñòàòóñ çàêàçà", "dbo.OrderStatus", "StatusName"
  78. Emit "GO"
  79. If Not wsU Is Nothing Then SeedUsers wsU
  80. If Not wsK Is Nothing Then SeedPickups wsK
  81. If Not wsP Is Nothing Then SeedProducts wsP
  82. If Not wsO Is Nothing Then SeedOrders wsO
  83. Emit "GO"
  84. End Sub
  85. Private Sub DictInsert(ws As Worksheet, header As String, tbl As String, col As String)
  86. Dim c As Long, r As Long, lastR As Long, v As String
  87. c = ColIdx(ws, header): If c = 0 Then Exit Sub
  88. lastR = LastRow(ws)
  89. Dim d As Object: Set d = CreateObject("Scripting.Dictionary")
  90. For r = 2 To lastR
  91. v = Trim(CStr(ws.Cells(r, c).Value))
  92. If Len(v) > 0 Then If Not d.Exists(v) Then d.Add v, 1
  93. Next r
  94. Dim k As Variant
  95. For Each k In d.Keys
  96. Emit "INSERT INTO " & tbl & "(" & col & ") VALUES (N'" & Esc(CStr(k)) & "');"
  97. Next k
  98. End Sub
  99. Private Sub SeedUsers(ws As Worksheet)
  100. Dim r As Long, lastR As Long
  101. Dim cR As Long, cF As Long, cL As Long, cP As Long
  102. cR = ColIdx(ws, "Ðîëü ñîòðóäíèêà"): cF = ColIdx(ws, "ÔÈÎ"): cL = ColIdx(ws, "Ëîãèí"): cP = ColIdx(ws, "Ïàðîëü")
  103. lastR = LastRow(ws)
  104. For r = 2 To lastR
  105. If Len(Trim(CStr(ws.Cells(r, cL).Value))) > 0 Then
  106. Emit "INSERT INTO dbo.[User](RoleId,FullName,Login,Password) VALUES (" & _
  107. "(SELECT RoleId FROM dbo.Role WHERE RoleName=N'" & Esc(CStr(ws.Cells(r, cR).Value)) & "')," & _
  108. "N'" & Esc(CStr(ws.Cells(r, cF).Value)) & "',N'" & Esc(CStr(ws.Cells(r, cL).Value)) & "',N'" & Esc(CStr(ws.Cells(r, cP).Value)) & "');"
  109. End If
  110. Next r
  111. End Sub
  112. Private Sub SeedPickups(ws As Worksheet)
  113. Dim r As Long, lastR As Long, id As Long, addr As String
  114. Dim p() As String, postal As String, city As String, street As String, house As String
  115. lastR = LastRow(ws)
  116. id = 0
  117. For r = 1 To lastR ' ó ïóíêòîâ âûäà÷è øàïêè íåò — áåð¸ì ñî ñòðîêè 1
  118. addr = Trim(CStr(ws.Cells(r, 1).Value))
  119. If Len(addr) > 0 Then
  120. id = id + 1
  121. p = Split(addr, ",")
  122. postal = "": city = "": street = "": house = ""
  123. If UBound(p) >= 0 Then postal = Trim(p(0))
  124. If UBound(p) >= 1 Then city = Trim(Replace(p(1), "ã.", ""))
  125. If UBound(p) >= 2 Then street = Trim(Replace(p(2), "óë.", ""))
  126. If UBound(p) >= 3 Then house = Trim(p(3))
  127. Emit "INSERT INTO dbo.PickupPoint(PickupPointId,PostalCode,City,Street,House) VALUES (" & _
  128. id & ",N'" & Esc(postal) & "',N'" & Esc(city) & "',N'" & Esc(street) & "',N'" & Esc(house) & "');"
  129. End If
  130. Next r
  131. End Sub
  132. Private Sub SeedProducts(ws As Worksheet)
  133. Dim r As Long, lastR As Long
  134. Dim cA, cN, cU, cPr, cS, cM, cC, cD, cQ, cDsc, cPh As Long
  135. cA = ColIdx(ws, "Àðòèêóë"): cN = ColIdx(ws, "Íàèìåíîâàíèå òîâàðà"): cU = ColIdx(ws, "Åäèíèöà èçìåðåíèÿ")
  136. cPr = ColIdx(ws, "Öåíà"): cS = ColIdx(ws, "Ïîñòàâùèê"): cM = ColIdx(ws, "Ïðîèçâîäèòåëü")
  137. cC = ColIdx(ws, "Êàòåãîðèÿ òîâàðà"): cD = ColIdx(ws, "Äåéñòâóþùàÿ ñêèäêà"): cQ = ColIdx(ws, "Êîë-âî íà ñêëàäå")
  138. cDsc = ColIdx(ws, "Îïèñàíèå òîâàðà"): cPh = ColIdx(ws, "Ôîòî")
  139. lastR = LastRow(ws)
  140. For r = 2 To lastR
  141. If Len(Trim(CStr(ws.Cells(r, cA).Value))) > 0 Then
  142. Emit "INSERT INTO dbo.Product(Article,Name,UnitId,Price,SupplierId,ManufacturerId,CategoryId,Discount,Stock,Description,Photo) VALUES (" & _
  143. "N'" & Esc(CStr(ws.Cells(r, cA).Value)) & "',N'" & Esc(CStr(ws.Cells(r, cN).Value)) & "'," & _
  144. "(SELECT UnitId FROM dbo.Unit WHERE UnitName=N'" & Esc(CStr(ws.Cells(r, cU).Value)) & "')," & Num(ws.Cells(r, cPr).Value) & "," & _
  145. "(SELECT SupplierId FROM dbo.Supplier WHERE SupplierName=N'" & Esc(CStr(ws.Cells(r, cS).Value)) & "')," & _
  146. "(SELECT ManufacturerId FROM dbo.Manufacturer WHERE ManufacturerName=N'" & Esc(CStr(ws.Cells(r, cM).Value)) & "')," & _
  147. "(SELECT CategoryId FROM dbo.Category WHERE CategoryName=N'" & Esc(CStr(ws.Cells(r, cC).Value)) & "')," & _
  148. Num(ws.Cells(r, cD).Value) & "," & Num(ws.Cells(r, cQ).Value) & ",N'" & Esc(CStr(ws.Cells(r, cDsc).Value)) & "',N'" & Esc(CStr(ws.Cells(r, cPh).Value)) & "');"
  149. End If
  150. Next r
  151. End Sub
  152. Private Sub SeedOrders(ws As Worksheet)
  153. Dim r As Long, lastR As Long
  154. Dim cNum, cArt, cOd, cDd, cPk, cFio, cCode, cSt As Long
  155. cNum = ColIdx(ws, "Íîìåð çàêàçà"): cArt = ColIdx(ws, "Àðòèêóë çàêàçà"): cOd = ColIdx(ws, "Äàòà çàêàçà")
  156. cDd = ColIdx(ws, "Äàòà äîñòàâêè"): cPk = ColIdx(ws, "Àäðåñ ïóíêòà âûäà÷è"): cFio = ColIdx(ws, "ÔÈÎ àâòîðèçèðîâàííîãî êëèåíòà")
  157. cCode = ColIdx(ws, "Êîä äëÿ ïîëó÷åíèÿ"): cSt = ColIdx(ws, "Ñòàòóñ çàêàçà")
  158. lastR = LastRow(ws)
  159. For r = 2 To lastR
  160. Dim ordId As String: ordId = Trim(CStr(ws.Cells(r, cNum).Value))
  161. If Len(ordId) > 0 Then
  162. Emit "INSERT INTO dbo.[Order](OrderId,OrderDate,DeliveryDate,PickupPointId,ClientUserId,ReceiveCode,StatusId) VALUES (" & _
  163. ordId & "," & DateVal(ws.Cells(r, cOd).Value) & "," & DateVal(ws.Cells(r, cDd).Value) & "," & Num(ws.Cells(r, cPk).Value) & "," & _
  164. "(SELECT TOP 1 u.UserId FROM dbo.[User] u JOIN dbo.Role rl ON u.RoleId=rl.RoleId WHERE u.FullName=N'" & Esc(CStr(ws.Cells(r, cFio).Value)) & "' ORDER BY CASE WHEN rl.RoleName=N'Àâòîðèçèðîâàííûé êëèåíò' THEN 0 ELSE 1 END, u.UserId)," & _
  165. Num(ws.Cells(r, cCode).Value) & ",(SELECT StatusId FROM dbo.OrderStatus WHERE StatusName=N'" & Esc(CStr(ws.Cells(r, cSt).Value)) & "'));"
  166. ' ïîçèöèè: "ART, qty, ART, qty"
  167. Dim p() As String, i As Long, art As String, qty As String
  168. p = Split(CStr(ws.Cells(r, cArt).Value), ",")
  169. For i = 0 To UBound(p) - 1 Step 2
  170. art = Trim(p(i)): qty = Trim(p(i + 1))
  171. If Len(art) > 0 And IsNumeric(qty) Then
  172. Emit "INSERT INTO dbo.OrderItem(OrderId,Article,Quantity) VALUES (" & ordId & ",N'" & Esc(art) & "'," & qty & ");"
  173. End If
  174. Next i
  175. End If
  176. Next r
  177. End Sub
  178. Private Function ColIdx(ws As Worksheet, header As String) As Long
  179. Dim c As Long, lc As Long
  180. lc = LastCol(ws)
  181. For c = 1 To lc
  182. If Trim(CStr(ws.Cells(1, c).Value)) = header Then ColIdx = c: Exit Function
  183. Next c
  184. ColIdx = 0
  185. End Function
  186. Private Function HasHeader(ws As Worksheet, header As String) As Boolean
  187. HasHeader = (ColIdx(ws, header) > 0)
  188. End Function
  189. Private Function LastCol(ws As Worksheet) As Long
  190. LastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
  191. End Function
  192. Private Function LastRow(ws As Worksheet) As Long
  193. LastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
  194. End Function
  195. Private Function Num(ByVal v As Variant) As String
  196. If Len(CStr(v)) = 0 Then Num = "0" Else Num = Replace(CStr(v), ",", ".")
  197. End Function
  198. Private Function DateVal(ByVal v As Variant) As String
  199. If VarType(v) = vbDate Then DateVal = "'" & Format$(v, "yyyy-mm-dd") & "'" Else DateVal = "NULL"
  200. End Function
  201. Private Function Esc(ByVal s As String) As String
  202. Esc = Replace(s, "'", "''")
  203. End Function
  204. Private Sub WriteUtf8(ByVal path As String, ByVal text As String)
  205. Dim st As Object
  206. Set st = CreateObject("ADODB.Stream")
  207. st.Type = 2
  208. st.Charset = "utf-8"
  209. st.Open
  210. st.WriteText text
  211. st.SaveToFile path, 2
  212. st.Close
  213. End Sub