VCS_Table.bas 21 KB

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