VCS_Table.bas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  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(Db As DAO.Database, td As DAO.TableDef, ByVal tableName As String, _
  85. ByVal directory As String)
  86. Dim filename As String
  87. filename = directory & 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. End If
  381. End Sub
  382. Public Sub ImportLinkedTable(ByVal tblName As String, ByRef obj_path As String)
  383. Dim Db As DAO.Database
  384. Dim FSO As Object
  385. Dim InFile As Object
  386. Set Db = CurrentDb
  387. Set FSO = CreateObject("Scripting.FileSystemObject")
  388. Dim tempFilePath As String
  389. tempFilePath = VCS_File.TempFile()
  390. ConvertUtf8Ucs2 obj_path & tblName & ".LNKD", tempFilePath
  391. ' open file for reading with Create=False, Unicode=True (USC-2 Little Endian format)
  392. Set InFile = FSO.OpenTextFile(tempFilePath, iomode:=ForReading, create:=False, Format:=TristateTrue)
  393. On Error GoTo err_notable:
  394. DoCmd.DeleteObject acTable, tblName
  395. GoTo err_notable_fin
  396. err_notable:
  397. err.Clear
  398. Resume err_notable_fin
  399. err_notable_fin:
  400. On Error GoTo Err_CreateLinkedTable:
  401. Dim td As DAO.TableDef
  402. Set td = Db.CreateTableDef(InFile.readline())
  403. Dim connect As String
  404. connect = InFile.readline()
  405. If InStr(1, connect, "DATABASE=.\") Then 'replace relative path with literal path
  406. connect = Replace(connect, "DATABASE=.\", "DATABASE=" & CurrentProject.Path & "\")
  407. End If
  408. td.connect = connect
  409. td.SourceTableName = InFile.readline()
  410. Db.TableDefs.Append td
  411. GoTo Err_CreateLinkedTable_Fin
  412. Err_CreateLinkedTable:
  413. logger "ImportLinkedTable", "CRITICAL", "ERROR: IMPORT LINKED TABLE: " & err.Description
  414. Call err.Raise(60000, "Critical error", "Critical error occured, see the log file for more informations")
  415. Resume Err_CreateLinkedTable_Fin
  416. Err_CreateLinkedTable_Fin:
  417. 'this will throw errors if a primary key already exists or the table is linked to an access database table
  418. 'will also error out if no pk is present
  419. On Error GoTo Err_LinkPK_Fin:
  420. Dim Fields As String
  421. Fields = InFile.readline()
  422. Dim Field As Variant
  423. Dim sql As String
  424. sql = "CREATE INDEX __uniqueindex ON " & td.name & " ("
  425. For Each Field In Split(Fields, ";+")
  426. sql = sql & "[" & Field & "]" & ","
  427. Next
  428. 'remove extraneous comma
  429. sql = Left$(sql, Len(sql) - 1)
  430. sql = sql & ") WITH PRIMARY"
  431. CurrentDb.execute sql
  432. logger "ImportLinkedTable", "DEBUG", "LinkedTable " & tblName & " improted from " & obj_path & tblName & ".LNKD"
  433. Err_LinkPK_Fin:
  434. On Error Resume Next
  435. InFile.Close
  436. End Sub
  437. ' Import Table Definition
  438. Public Sub ImportTableDef(ByVal tblName As String, ByVal directory As String)
  439. Dim filepath As String
  440. filepath = directory & tblName & ".sql"
  441. Dim Db As Object ' DAO.Database
  442. Dim FSO As Object
  443. Dim InFile As Object
  444. Dim buf As String
  445. Dim p As Integer
  446. Dim p1 As Integer
  447. Dim strMsg As String
  448. Dim S As Variant
  449. Dim N As Integer
  450. Dim i As Integer
  451. Dim j As Integer
  452. Dim tempFileName As String
  453. tempFileName = VCS_File.TempFile()
  454. N = -1
  455. Set FSO = CreateObject("Scripting.FileSystemObject")
  456. VCS_File.ConvertUtf8Ucs2 filepath, tempFileName
  457. ' open file for reading with Create=False, Unicode=True (USC-2 Little Endian format)
  458. 'Set InFile = fso.OpenTextFile(tempFileName, iomode:=ForReading, create:=False, Format:=TristateTrue)
  459. Set Db = CurrentDb
  460. KillTable tblName, Db
  461. buf = ReadFile(filepath, "x-ansi")
  462. ' The following block is needed because "on update" actions may cause problems
  463. For Each S In Split("UPDATE|DELETE", "|")
  464. p = InStr(buf, "ON " & S & " CASCADE")
  465. Do While p > 0
  466. N = N + 1
  467. ReDim Preserve k(N)
  468. k(N).table = tblName
  469. k(N).isUpdate = (S = "UPDATE")
  470. buf = Left$(buf, p - 1) & Mid$(buf, p + 18)
  471. p = InStrRev(buf, "REFERENCES", p)
  472. p1 = InStr(p, buf, "(")
  473. k(N).foreignFields = Split(VCS_String.SubString(p1, buf, "(", ")"), ",")
  474. k(N).foreignTable = Trim$(Mid$(buf, p + 10, p1 - p - 10))
  475. p = InStrRev(buf, "CONSTRAINT", p1)
  476. p1 = InStrRev(buf, "FOREIGN KEY", p1)
  477. If (p1 > 0) And (p > 0) And (p1 > p) Then
  478. ' multifield index
  479. k(N).refFields = Split(VCS_String.SubString(p1, buf, "(", ")"), ",")
  480. ElseIf p1 = 0 Then
  481. ' single field
  482. End If
  483. p = InStr(p, "ON " & S & " CASCADE", buf)
  484. Loop
  485. Next
  486. On Error Resume Next
  487. For i = 0 To N
  488. strMsg = k(i).table & " to " & k(i).foreignTable
  489. strMsg = strMsg & "( "
  490. For j = 0 To UBound(k(i).refFields)
  491. strMsg = strMsg & k(i).refFields(j) & ", "
  492. Next j
  493. strMsg = Left$(strMsg, Len(strMsg) - 2) & ") to ("
  494. For j = 0 To UBound(k(i).foreignFields)
  495. strMsg = strMsg & k(i).foreignFields(j) & ", "
  496. Next j
  497. strMsg = Left$(strMsg, Len(strMsg) - 2) & ") Check "
  498. If k(i).isUpdate Then
  499. strMsg = strMsg & " on update cascade " & vbCrLf
  500. Else
  501. strMsg = strMsg & " on delete cascade " & vbCrLf
  502. End If
  503. Next
  504. On Error GoTo 0
  505. Db.execute buf
  506. 'InFile.Close
  507. If Len(strMsg) > 0 Then
  508. OA_MsgBox strMsg, vbOKOnly, "Correct manually"
  509. logger "ImportTableDef", "ERROR", strMsg & " - Correct manually"
  510. Else
  511. logger "ImportTableData", "DEBUG", "TableDef '" & tblName & "' imported from " & filepath
  512. End If
  513. End Sub
  514. ' Import the lookup table `tblName` from `source\tables`.
  515. Public Sub ImportTableData(ByVal tblName As String, ByVal obj_path As String)
  516. 'On Error GoTo err
  517. Dim Db As Object ' DAO.Database
  518. Dim rs As Object ' DAO.Recordset
  519. Dim fieldObj As Object ' DAO.Field
  520. Dim FSO As Object
  521. Dim InFile As Object
  522. Dim c As Long, buf As String, Values() As String, value As Variant
  523. Dim Path As String
  524. Set FSO = CreateObject("Scripting.FileSystemObject")
  525. Dim tempFileName As String
  526. tempFileName = VCS_File.TempFile()
  527. Path = obj_path & tblName & ".txt"
  528. VCS_File.ConvertUtf8Ucs2 Path, tempFileName
  529. ' open file for reading with Create=False, Unicode=True (USC-2 Little Endian format)
  530. Set InFile = FSO.OpenTextFile(tempFileName, iomode:=ForReading, create:=False, Format:=TristateTrue)
  531. Set Db = CurrentDb
  532. Db.execute "DELETE FROM [" & tblName & "]"
  533. Set rs = Db.OpenRecordset(tblName)
  534. buf = InFile.readline()
  535. Do Until InFile.AtEndOfStream
  536. buf = InFile.readline()
  537. If Len(Trim$(buf)) > 0 Then
  538. Values = Split(buf, vbTab)
  539. c = 0
  540. rs.AddNew
  541. For Each fieldObj In rs.Fields
  542. On Error GoTo errField
  543. DoEvents
  544. value = Values(c)
  545. If Len(value) = 0 Then
  546. value = Null
  547. Else
  548. value = Replace(value, "\t", vbTab)
  549. value = Replace(value, "\n", vbCrLf)
  550. value = Replace(value, "\\", "\")
  551. End If
  552. '** correct a bug due to internationalization
  553. If fieldObj.Type = dbBoolean Then value = CBool(value)
  554. '**
  555. rs(fieldObj.name) = value
  556. On Error GoTo err
  557. c = c + 1
  558. Next
  559. rs.update
  560. End If
  561. Loop
  562. rs.Close
  563. InFile.Close
  564. logger "ImportTableData", "DEBUG", "Table data '" & tblName & "' imported from " & Path
  565. FSO.DeleteFile tempFileName
  566. Exit Sub
  567. err:
  568. logger "ImportTableData", "ERROR", "Table data '" & tblName & "' : Unable to import"
  569. Exit Sub
  570. errField:
  571. logger "ImportTableData", "ERROR", fieldObj.name & " > this field can not be updated"
  572. End Sub