VCS_Table.bas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. Option Compare Database
  2. Option Private Module
  3. Option Explicit
  4. ' --------------------------------
  5. ' Structures
  6. ' --------------------------------
  7. ' Structure to keep track of "on Update" and "on Delete" clauses
  8. ' Access does not in all cases execute such queries
  9. Private Type structEnforce
  10. foreignTable As String
  11. foreignFields() As String
  12. table As String
  13. refFields() As String
  14. isUpdate As Boolean
  15. End Type
  16. ' keeping "on Update" relations to be complemented after table creation
  17. Private k() As structEnforce
  18. Public Sub ExportLinkedTable(ByVal tbl_name As String, ByVal obj_path As String)
  19. On Error GoTo Err_LinkedTable
  20. Dim tempFilePath As String
  21. tempFilePath = VCS_File.TempFile()
  22. Dim FSO As Object
  23. Dim OutFile As Object
  24. Set FSO = CreateObject("Scripting.FileSystemObject")
  25. ' open file for writing with Create=True, Unicode=True (USC-2 Little Endian format)
  26. VCS_Dir.MkDirIfNotExist obj_path
  27. Set OutFile = FSO.CreateTextFile(tempFilePath, overwrite:=True, unicode:=True)
  28. OutFile.Write CurrentDb.TableDefs(tbl_name).name
  29. OutFile.Write vbCrLf
  30. If InStr(1, CurrentDb.TableDefs(tbl_name).connect, "DATABASE=" & CurrentProject.path) Then
  31. 'change to relatave path
  32. Dim connect() As String
  33. connect = Split(CurrentDb.TableDefs(tbl_name).connect, CurrentProject.path)
  34. OutFile.Write connect(0) & "." & connect(1)
  35. Else
  36. OutFile.Write CurrentDb.TableDefs(tbl_name).connect
  37. End If
  38. OutFile.Write vbCrLf
  39. OutFile.Write CurrentDb.TableDefs(tbl_name).SourceTableName
  40. OutFile.Write vbCrLf
  41. Dim db As DAO.Database
  42. Set db = CurrentDb
  43. Dim td As DAO.TableDef
  44. Set td = db.TableDefs(tbl_name)
  45. Dim idx As DAO.index
  46. For Each idx In td.Indexes
  47. If idx.Primary Then
  48. OutFile.Write Right$(idx.Fields, Len(idx.Fields) - 1)
  49. OutFile.Write vbCrLf
  50. End If
  51. Next
  52. Err_LinkedTable_Fin:
  53. On Error Resume Next
  54. OutFile.Close
  55. 'save files as .odbc
  56. Dim path As String
  57. path = obj_path & VCS_IE_Functions.to_filename(tbl_name) & ".LNKD"
  58. VCS_File.ConvertUcs2Utf8 tempFilePath, path
  59. logger "ExportLinkedTable", "DEBUG", "LinkedTable " & tbl_name & " exported to " & path
  60. Exit Sub
  61. Err_LinkedTable:
  62. OutFile.Close
  63. logger "ImportLinkedTable", "CRITICAL", "ERROR: IMPORT LINKED TABLE: " & err.Description
  64. Call err.Raise(60000, "Critical error", "Critical error occured, see the log file for more informations")
  65. Resume Err_LinkedTable_Fin
  66. End Sub
  67. ' This requires Microsoft ADO Ext. 2.x for DLL and Security
  68. ' See reference: https://social.msdn.microsoft.com/Forums/office/en-US/883087ba-2c25-4571-bd3c-706061466a11/how-can-i-programmatically-access-scale-property-of-a-decimal-data-type-field?forum=accessdev
  69. Private Function formatDecimal(ByVal tableName As String, ByVal fieldName As String) As String
  70. Dim cnn As ADODB.Connection
  71. Dim cat As ADOX.Catalog
  72. Dim col As ADOX.Column
  73. Set cnn = New ADODB.Connection
  74. Set cat = New ADOX.Catalog
  75. Set cnn = CurrentProject.Connection
  76. Set cat.ActiveConnection = cnn
  77. Set col = cat.Tables(tableName).Columns(fieldName)
  78. formatDecimal = "(" & col.Precision & ", " & col.NumericScale & ")"
  79. Set col = Nothing
  80. Set cat = Nothing
  81. Set cnn = Nothing
  82. End Function
  83. ' Save a Table Definition as SQL statement
  84. Public Sub ExportTableDef(ByRef db As DAO.Database, ByRef td As DAO.TableDef, ByVal directory As String)
  85. Dim tableName, filename As String
  86. tableName = td.name
  87. filename = directory & to_filename(tableName) & ".sql"
  88. Dim sql As String
  89. Dim fieldAttributeSql As String
  90. Dim idx As DAO.index
  91. Dim fi As DAO.Field
  92. Dim FSO As Object
  93. Dim OutFile As Object
  94. Dim ff As Object
  95. 'Debug.Print tableName
  96. Set FSO = CreateObject("Scripting.FileSystemObject")
  97. Set OutFile = FSO.CreateTextFile(filename, overwrite:=True, unicode:=False)
  98. sql = "CREATE TABLE " & strName(tableName) & " (" & vbCrLf
  99. For Each fi In td.Fields
  100. sql = sql & " " & strName(fi.name) & " "
  101. If (fi.Attributes And dbAutoIncrField) Then
  102. sql = sql & "AUTOINCREMENT"
  103. Else
  104. sql = sql & strType(fi.Type) & " "
  105. End If
  106. Select Case fi.Type
  107. Case dbText, dbVarBinary
  108. sql = sql & "(" & fi.Size & ")"
  109. Case dbDecimal
  110. sql = sql & formatDecimal(tableName, fi.name)
  111. Case Else
  112. End Select
  113. For Each idx In td.Indexes
  114. fieldAttributeSql = vbNullString
  115. If idx.Fields.count = 1 And idx.Fields(0).name = fi.name Then
  116. If idx.Primary Then fieldAttributeSql = fieldAttributeSql & " PRIMARY KEY "
  117. If idx.Unique Then fieldAttributeSql = fieldAttributeSql & " UNIQUE "
  118. If idx.Required Then fieldAttributeSql = fieldAttributeSql & " NOT NULL "
  119. If idx.Foreign Then
  120. Set ff = idx.Fields
  121. fieldAttributeSql = fieldAttributeSql & formatReferences(db, ff, tableName)
  122. End If
  123. If Len(fieldAttributeSql) > 0 Then fieldAttributeSql = " CONSTRAINT " & strName(idx.name) & fieldAttributeSql
  124. End If
  125. sql = sql & fieldAttributeSql
  126. Next
  127. sql = sql & "," & vbCrLf
  128. Next
  129. sql = Left$(sql, Len(sql) - 3) ' strip off last comma and crlf
  130. Dim constraintSql As String
  131. For Each idx In td.Indexes
  132. If idx.Fields.count > 1 Then
  133. If Len(constraintSql) = 0 Then constraintSql = constraintSql & " CONSTRAINT "
  134. If idx.Primary Then constraintSql = constraintSql & formatConstraint("PRIMARY KEY", idx)
  135. If Not idx.Foreign Then
  136. If Len(constraintSql) > 0 Then
  137. sql = sql & "," & vbCrLf & " " & constraintSql
  138. sql = sql & formatReferences(db, idx.Fields, tableName)
  139. End If
  140. End If
  141. End If
  142. Next
  143. sql = sql & vbCrLf & ")"
  144. 'Debug.Print sql
  145. OutFile.WriteLine sql
  146. OutFile.Close
  147. 'exort Data Macros
  148. VCS_DataMacro.ExportDataMacros tableName, directory
  149. logger "ExportTableDef", "DEBUG", "TblDef '" & tableName & "' exported to " & filename
  150. End Sub
  151. Private Function formatReferences(db As DAO.Database, ff As Object, _
  152. ByVal tableName As String) As String
  153. Dim rel As DAO.Relation
  154. Dim sql As String
  155. Dim f As DAO.Field
  156. For Each rel In db.Relations
  157. If (rel.foreignTable = tableName) Then
  158. If FieldsIdentical(ff, rel.Fields) Then
  159. sql = " REFERENCES "
  160. sql = sql & strName(rel.table) & " ("
  161. For Each f In rel.Fields
  162. sql = sql & strName(f.name) & ","
  163. Next
  164. sql = Left$(sql, Len(sql) - 1) & ")"
  165. If rel.Attributes And dbRelationUpdateCascade Then
  166. sql = sql + " ON UPDATE CASCADE "
  167. End If
  168. If rel.Attributes And dbRelationDeleteCascade Then
  169. sql = sql + " ON DELETE CASCADE "
  170. End If
  171. Exit For
  172. End If
  173. End If
  174. Next
  175. formatReferences = sql
  176. End Function
  177. Private Function formatConstraint(ByVal keyw As String, ByVal idx As DAO.index) As String
  178. Dim sql As String
  179. Dim fi As DAO.Field
  180. sql = strName(idx.name) & " " & keyw & " ("
  181. For Each fi In idx.Fields
  182. sql = sql & strName(fi.name) & ", "
  183. Next
  184. sql = Left$(sql, Len(sql) - 2) & ")" 'strip off last comma and close brackets
  185. 'return value
  186. formatConstraint = sql
  187. End Function
  188. Private Function strName(ByVal S As String) As String
  189. strName = "[" & S & "]"
  190. End Function
  191. Private Function strType(ByVal i As Integer) As String
  192. Select Case i
  193. Case dbLongBinary
  194. strType = "LONGBINARY"
  195. Case dbBinary
  196. strType = "BINARY"
  197. Case dbBoolean
  198. strType = "BIT"
  199. Case dbAutoIncrField
  200. strType = "COUNTER"
  201. Case dbCurrency
  202. strType = "CURRENCY"
  203. Case dbDate, dbTime
  204. strType = "DATETIME"
  205. Case dbGUID
  206. strType = "GUID"
  207. Case dbMemo
  208. strType = "LONGTEXT"
  209. Case dbDouble
  210. strType = "DOUBLE"
  211. Case dbSingle
  212. strType = "SINGLE"
  213. Case dbByte
  214. strType = "BYTE"
  215. Case dbInteger
  216. strType = "SHORT"
  217. Case dbLong
  218. strType = "LONG"
  219. Case dbNumeric
  220. strType = "NUMERIC"
  221. Case dbText
  222. strType = "VARCHAR"
  223. Case dbDecimal
  224. strType = "DECIMAL"
  225. Case Else
  226. strType = "VARCHAR"
  227. End Select
  228. End Function
  229. Private Function FieldsIdentical(ff As Object, gg As Object) As Boolean
  230. Dim f As DAO.Field
  231. If ff.count <> gg.count Then
  232. FieldsIdentical = False
  233. Exit Function
  234. End If
  235. For Each f In ff
  236. If Not FieldInFields(f, gg) Then
  237. FieldsIdentical = False
  238. Exit Function
  239. End If
  240. Next
  241. FieldsIdentical = True
  242. End Function
  243. Private Function FieldInFields(fi As DAO.Field, ff As DAO.Fields) As Boolean
  244. Dim f As DAO.Field
  245. For Each f In ff
  246. If f.name = fi.name Then
  247. FieldInFields = True
  248. Exit Function
  249. End If
  250. Next
  251. FieldInFields = False
  252. End Function
  253. ' Determine if a table or exists.
  254. ' based on sample code of support.microsoftcom
  255. ' ARGUMENTS:
  256. ' TName: The name of a table or query.
  257. '
  258. ' RETURNS: True (it exists) or False (it does not exist).
  259. Private Function TableExists(ByVal TName As String) As Boolean
  260. Dim db As DAO.Database
  261. Dim Found As Boolean
  262. Dim test As String
  263. Const NAME_NOT_IN_COLLECTION As Integer = 3265
  264. ' Assume the table or query does not exist.
  265. Found = False
  266. Set db = CurrentDb()
  267. ' Trap for any errors.
  268. On Error Resume Next
  269. ' See if the name is in the Tables collection.
  270. test = db.TableDefs(TName).name
  271. If err.Number <> NAME_NOT_IN_COLLECTION Then Found = True
  272. ' Reset the error variable.
  273. err = 0
  274. TableExists = Found
  275. End Function
  276. ' Build SQL to export `tbl_name` sorted by each field from first to last
  277. Private Function TableExportSql(ByVal tbl_name As String) As String
  278. Dim rs As Object ' DAO.Recordset
  279. Dim fieldObj As Object ' DAO.Field
  280. Dim sb() As String, count As Integer
  281. Set rs = CurrentDb.OpenRecordset(tbl_name)
  282. sb = VCS_String.Sb_Init()
  283. VCS_String.Sb_Append sb, "SELECT "
  284. count = 0
  285. For Each fieldObj In rs.Fields
  286. If count > 0 Then VCS_String.Sb_Append sb, ", "
  287. VCS_String.Sb_Append sb, "[" & fieldObj.name & "]"
  288. count = count + 1
  289. Next
  290. VCS_String.Sb_Append sb, " FROM [" & tbl_name & "] ORDER BY "
  291. count = 0
  292. For Each fieldObj In rs.Fields
  293. DoEvents
  294. If fieldObj.Type <> 109 And _
  295. fieldObj.Type <> 101 And _
  296. fieldObj.Type <> 11 Then 'ignore muliple choices fields, ole, and attached fields
  297. If count > 0 Then VCS_String.Sb_Append sb, ", "
  298. VCS_String.Sb_Append sb, "[" & fieldObj.name & "]"
  299. count = count + 1
  300. End If
  301. Next
  302. TableExportSql = VCS_String.Sb_Get(sb)
  303. End Function
  304. ' Export the lookup table `tblName` to `source\tables`.
  305. Public Sub ExportTableData(ByVal tbl_name As String, ByVal obj_path As String)
  306. On Error GoTo err
  307. Dim FSO As Object
  308. Dim OutFile As Object
  309. Dim rs As DAO.Recordset ' DAO.Recordset
  310. Dim fieldObj As Object ' DAO.Field
  311. Dim c As Long, value As Variant
  312. ' Checks first
  313. If Not TableExists(tbl_name) Then
  314. logger "ExportTableData", "ERROR", "Table " & tbl_name & " missing"
  315. Exit Sub
  316. End If
  317. Set rs = CurrentDb.OpenRecordset(TableExportSql(tbl_name))
  318. If rs.RecordCount = 0 Then
  319. 'why is this an error? Debug.Print "Error: Table " & tbl_name & " empty"
  320. rs.Close
  321. Exit Sub
  322. End If
  323. Set FSO = CreateObject("Scripting.FileSystemObject")
  324. ' open file for writing with Create=True, Unicode=True (USC-2 Little Endian format)
  325. VCS_Dir.MkDirIfNotExist obj_path
  326. Dim tempFileName As String
  327. tempFileName = VCS_File.TempFile()
  328. Set OutFile = FSO.CreateTextFile(tempFileName, overwrite:=True, unicode:=True)
  329. c = 0
  330. For Each fieldObj In rs.Fields
  331. If c <> 0 Then OutFile.Write vbTab
  332. c = c + 1
  333. OutFile.Write fieldObj.name
  334. Next
  335. OutFile.Write vbCrLf
  336. rs.MoveFirst
  337. Do Until rs.EOF
  338. c = 0
  339. For Each fieldObj In rs.Fields
  340. DoEvents
  341. If c <> 0 Then OutFile.Write vbTab
  342. c = c + 1
  343. value = rs(fieldObj.name)
  344. If IsNull(value) Then
  345. value = vbNullString
  346. Else
  347. On Error GoTo errData
  348. value = Replace(value, "\", "\\")
  349. value = Replace(value, vbCrLf, "\n")
  350. value = Replace(value, vbCr, "\n")
  351. value = Replace(value, vbLf, "\n")
  352. value = Replace(value, vbTab, "\t")
  353. On Error GoTo err
  354. End If
  355. OutFile.Write value
  356. Next
  357. OutFile.Write vbCrLf
  358. next_field:
  359. rs.MoveNext
  360. Loop
  361. rs.Close
  362. OutFile.Close
  363. Dim path As String
  364. path = obj_path & VCS_IE_Functions.to_filename(tbl_name) & ".txt"
  365. VCS_File.ConvertUcs2Utf8 tempFileName, path
  366. logger "ExportTableData", "DEBUG", "Data from '" & tbl_name & "' exported to " & path
  367. FSO.DeleteFile tempFileName
  368. Exit Sub
  369. err:
  370. logger "ExportTableData", "ERROR", err.Description
  371. Exit Sub
  372. errData:
  373. logger "ExportTableData", "ERROR", "[" & fieldObj.name & "] field > Uneadable data"
  374. Resume next_field
  375. End Sub
  376. ' Kill Table if Exists
  377. Private Sub KillTable(ByVal tblName As String, db As Object)
  378. If TableExists(tblName) Then
  379. 'Db.Execute "DROP TABLE [" & tblName & "]"
  380. run_sql "DROP TABLE [" & tblName & "]"
  381. End If
  382. End Sub
  383. Public Sub ImportLinkedTable(ByVal tblName As String, ByRef obj_path As String)
  384. Dim db As DAO.Database
  385. Dim FSO As Object
  386. Dim InFile As Object
  387. Set db = CurrentDb
  388. Set FSO = CreateObject("Scripting.FileSystemObject")
  389. Dim tempFilePath As String
  390. tempFilePath = VCS_File.TempFile()
  391. ConvertUtf8Ucs2 obj_path & tblName & ".LNKD", tempFilePath
  392. ' open file for reading with Create=False, Unicode=True (USC-2 Little Endian format)
  393. Set InFile = FSO.OpenTextFile(tempFilePath, iomode:=ForReading, Create:=False, Format:=TristateTrue)
  394. On Error GoTo err_notable:
  395. DoCmd.DeleteObject acTable, tblName
  396. GoTo err_notable_fin
  397. err_notable:
  398. err.Clear
  399. Resume err_notable_fin
  400. err_notable_fin:
  401. On Error GoTo Err_CreateLinkedTable:
  402. Dim td As DAO.TableDef
  403. Set td = db.CreateTableDef(InFile.readline())
  404. Dim connect As String
  405. connect = InFile.readline()
  406. If InStr(1, connect, "DATABASE=.\") Then 'replace relative path with literal path
  407. connect = Replace(connect, "DATABASE=.\", "DATABASE=" & CurrentProject.path & "\")
  408. End If
  409. td.connect = connect
  410. td.SourceTableName = InFile.readline()
  411. db.TableDefs.Append td
  412. GoTo Err_CreateLinkedTable_Fin
  413. Err_CreateLinkedTable:
  414. logger "ImportLinkedTable", "CRITICAL", "ERROR: IMPORT LINKED TABLE: " & err.Description
  415. Call err.Raise(60000, "Critical error", "Critical error occured, see the log file for more informations")
  416. Resume Err_CreateLinkedTable_Fin
  417. Err_CreateLinkedTable_Fin:
  418. 'this will throw errors if a primary key already exists or the table is linked to an access database table
  419. 'will also error out if no pk is present
  420. On Error GoTo Err_LinkPK_Fin:
  421. Dim Fields As String
  422. Fields = InFile.readline()
  423. Dim Field As Variant
  424. Dim sql As String
  425. sql = "CREATE INDEX __uniqueindex ON " & td.name & " ("
  426. For Each Field In Split(Fields, ";+")
  427. sql = sql & "[" & Field & "]" & ","
  428. Next
  429. 'remove extraneous comma
  430. sql = Left$(sql, Len(sql) - 1)
  431. sql = sql & ") WITH PRIMARY"
  432. 'CurrentDb.Execute sql
  433. run_sql sql
  434. logger "ImportLinkedTable", "DEBUG", "LinkedTable " & tblName & " improted from " & obj_path & tblName & ".LNKD"
  435. Err_LinkPK_Fin:
  436. On Error Resume Next
  437. InFile.Close
  438. End Sub
  439. ' Import Table Definition
  440. Public Sub ImportTableDef(ByVal tblName As String, ByVal directory As String)
  441. Dim filepath As String
  442. filepath = directory & to_filename(tblName) & ".sql"
  443. Dim db As Object ' DAO.Database
  444. Dim FSO As Object
  445. Dim InFile As Object
  446. Dim buf As String
  447. Dim p As Integer
  448. Dim p1 As Integer
  449. Dim strMsg As String
  450. Dim S As Variant
  451. Dim N As Integer
  452. Dim i As Integer
  453. Dim j As Integer
  454. Dim tempFileName As String
  455. tempFileName = VCS_File.TempFile()
  456. N = -1
  457. Set FSO = CreateObject("Scripting.FileSystemObject")
  458. VCS_File.ConvertUtf8Ucs2 filepath, tempFileName
  459. ' open file for reading with Create=False, Unicode=True (USC-2 Little Endian format)
  460. 'Set InFile = fso.OpenTextFile(tempFileName, iomode:=ForReading, create:=False, Format:=TristateTrue)
  461. Set db = CurrentDb
  462. KillTable tblName, db
  463. buf = ReadFile(filepath, "x-ansi")
  464. ' The following block is needed because "on update" actions may cause problems
  465. For Each S In Split("UPDATE|DELETE", "|")
  466. p = InStr(buf, "ON " & S & " CASCADE")
  467. Do While p > 0
  468. N = N + 1
  469. ReDim Preserve k(N)
  470. k(N).table = tblName
  471. k(N).isUpdate = (S = "UPDATE")
  472. buf = Left$(buf, p - 1) & Mid$(buf, p + 18)
  473. p = InStrRev(buf, "REFERENCES", p)
  474. p1 = InStr(p, buf, "(")
  475. k(N).foreignFields = Split(VCS_String.SubString(p1, buf, "(", ")"), ",")
  476. k(N).foreignTable = Trim$(Mid$(buf, p + 10, p1 - p - 10))
  477. p = InStrRev(buf, "CONSTRAINT", p1)
  478. p1 = InStrRev(buf, "FOREIGN KEY", p1)
  479. If (p1 > 0) And (p > 0) And (p1 > p) Then
  480. ' multifield index
  481. k(N).refFields = Split(VCS_String.SubString(p1, buf, "(", ")"), ",")
  482. ElseIf p1 = 0 Then
  483. ' single field
  484. End If
  485. p = InStr(p, "ON " & S & " CASCADE", buf)
  486. Loop
  487. Next
  488. On Error Resume Next
  489. For i = 0 To N
  490. strMsg = k(i).table & " to " & k(i).foreignTable
  491. strMsg = strMsg & "( "
  492. For j = 0 To UBound(k(i).refFields)
  493. strMsg = strMsg & k(i).refFields(j) & ", "
  494. Next j
  495. strMsg = Left$(strMsg, Len(strMsg) - 2) & ") to ("
  496. For j = 0 To UBound(k(i).foreignFields)
  497. strMsg = strMsg & k(i).foreignFields(j) & ", "
  498. Next j
  499. strMsg = Left$(strMsg, Len(strMsg) - 2) & ") Check "
  500. If k(i).isUpdate Then
  501. strMsg = strMsg & " on update cascade " & vbCrLf
  502. Else
  503. strMsg = strMsg & " on delete cascade " & vbCrLf
  504. End If
  505. Next
  506. On Error GoTo 0
  507. 'Db.Execute buf
  508. run_sql buf
  509. If Len(strMsg) > 0 Then
  510. OA_MsgBox strMsg, vbOKOnly, "Correct manually"
  511. logger "ImportTableDef", "ERROR", strMsg & " - Correct manually"
  512. Else
  513. logger "ImportTableData", "DEBUG", "TableDef '" & tblName & "' imported from " & filepath
  514. End If
  515. End Sub
  516. ' Import the lookup table `tblName` from `source\tables`.
  517. Public Sub ImportTableData(ByVal tblName As String, ByVal obj_path As String)
  518. 'On Error GoTo err
  519. Dim db As Object ' DAO.Database
  520. Dim rs As Object ' DAO.Recordset
  521. Dim fieldObj As Object ' DAO.Field
  522. Dim FSO As Object
  523. Dim InFile As Object
  524. Dim c As Long, buf As String, Values() As String, value As Variant
  525. Dim path As String
  526. Set FSO = CreateObject("Scripting.FileSystemObject")
  527. Dim tempFileName As String
  528. tempFileName = VCS_File.TempFile()
  529. path = obj_path & tblName & ".txt"
  530. VCS_File.ConvertUtf8Ucs2 path, tempFileName
  531. ' open file for reading with Create=False, Unicode=True (USC-2 Little Endian format)
  532. Set InFile = FSO.OpenTextFile(tempFileName, iomode:=ForReading, Create:=False, Format:=TristateTrue)
  533. Set db = CurrentDb
  534. 'Db.Execute "DELETE FROM [" & tblName & "]"
  535. run_sql "DELETE FROM [" & tblName & "]"
  536. Set rs = db.OpenRecordset(tblName)
  537. buf = InFile.readline()
  538. Do Until InFile.AtEndOfStream
  539. buf = InFile.readline()
  540. If Len(Trim$(buf)) > 0 Then
  541. Values = Split(buf, vbTab)
  542. c = 0
  543. rs.AddNew
  544. For Each fieldObj In rs.Fields
  545. On Error GoTo errField
  546. DoEvents
  547. value = Values(c)
  548. If Len(value) = 0 Then
  549. value = Null
  550. Else
  551. value = Replace(value, "\t", vbTab)
  552. value = Replace(value, "\n", vbCrLf)
  553. value = Replace(value, "\\", "\")
  554. End If
  555. '** correct a bug due to internationalization
  556. If fieldObj.Type = dbBoolean Then value = CBool(value)
  557. '**
  558. rs(fieldObj.name) = value
  559. On Error GoTo err
  560. c = c + 1
  561. Next
  562. rs.update
  563. End If
  564. Loop
  565. rs.Close
  566. InFile.Close
  567. logger "ImportTableData", "DEBUG", "Table data '" & tblName & "' imported from " & path
  568. FSO.DeleteFile tempFileName
  569. Exit Sub
  570. err:
  571. logger "ImportTableData", "ERROR", "Table data '" & tblName & "' : Unable to import"
  572. Exit Sub
  573. errField:
  574. logger "ImportTableData", "ERROR", fieldObj.name & " > this field can not be updated"
  575. End Sub