VCS_Table.bas 21 KB

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