R
RB Smissaert
Have worked this out a bit further, but not been able yet
to make it work with GROUP BY constructions. Could it work with
that? The problem might be that I still don't understand what exactly
is going on at:
" IN """"
Sub Test()
Dim strMDBPath As String
Dim strUN As String
Dim strPW As String
Dim strDSN As String
Dim strDBPath As String
Dim lOLDMETADATA As Long
Dim strSQL As String
Dim strTable As String
Dim arrTypes As Variant
strMDBPath = "C:\test.mdb"
strUN = "sysdba"
strPW = "torexkey"
strDSN = "System 6000"
strDBPath = "C:\Torex\Synergy\Meddata\S6000\db\s6.gdb"
lOLDMETADATA = 1
strTable = "TestTable"
'strSQL = "SELECT E.READ_CODE, E.TERM_TEXT " & _
"FROM ENTRY E INNER JOIN PATIENT P ON " & _
"(E.PATIENT_ID = P.PATIENT_ID) " & _
"WHERE E.READ_CODE = 'G2...' AND " & _
"NOT P.MAIN_REG_TYPE = 1"
'--------------------------------------
'this one doesn't work, will get:
'ODBC - call failed. (Error 3146)
'--------------------------------------
strSQL = "SELECT E.READ_CODE, COUNT(E.ENTRY_ID) FROM " & _
"ENTRY E WHERE E.READ_CODE LIKE 'G%' " & _
"GROUP BY E.READ_CODE " & _
"ORDER BY 2 DESC"
'arrTypes = Array("CHAR", "CHAR")
arrTypes = Array("CHAR", "LONG")
IB2Access strMDBPath, _
strUN, _
strPW, _
strDSN, _
strDBPath, _
lOLDMETADATA, _
strSQL, _
strTable, _
arrTypes
End Sub
Sub IB2Access(strMDBPath As String, _
strUN As String, _
strPW As String, _
strDSN As String, _
strDBPath As String, _
lOLDMETADATA As Long, _
strSQL As String, _
strTable As String, _
arrTypes As Variant)
Dim db As DAO.Database
Dim strConnect As String
Dim arr
Dim strSelectFrom As String
Dim lFieldCount As Long
'could start at GROUP BY or ORDER BY
'if there is no WHERE clause
'that is if this could work
'-----------------------------------
Dim strWhere As String
Dim arrFields
Dim strFieldDefs As String
arr = SplitSQLOnWhere(strSQL)
strSelectFrom = arr(1)
strWhere = arr(2)
arrFields = GetSelectFields(strSelectFrom)
lFieldCount = CountChar(",", strSelectFrom) + 1
On Error Resume Next
Kill strMDBPath
On Error GoTo 0
strConnect = "ODBC;" & _
"DSN=" & strDSN & ";" & _
"UID=" & strUN & ";" & _
"PWD=" & strPW & ";" & _
"DB=" & strDBPath & ";" & _
"OLDMETADATA=" & lOLDMETADATA & ";"
Set db = DBEngine.CreateDatabase(strMDBPath, dbLangGeneral)
With db
strFieldDefs = MakeFieldDefs(arrFields, arrTypes, lFieldCount, True)
.Execute "CREATE TABLE " & _
strTable & _
strFieldDefs, _
dbFailOnError
'not figured out yet what exactly is happening here:
' " IN """"
'---------------------------------------------------
strFieldDefs = MakeFieldDefs(arrFields, arrTypes, lFieldCount, False)
.Execute "INSERT INTO " & _
strTable & _
strFieldDefs & _
strSelectFrom & _
" IN """" [" & strConnect & "] " & _
strWhere, _
dbFailOnError
.Close
End With
Set db = Nothing
End Sub
Function SplitSQLOnWhere(strSQL As String) As String()
'splits SQL on first WHERE clause
'not suitable for sub-queries with multiple WHERE
'may need a different split here for GROUP BY etc.
'-------------------------------------------------
Dim lWherePos As Long
Dim arr(1 To 2) As String
lWherePos = InStr(1, UCase(strSQL), "WHERE", vbBinaryCompare)
If lWherePos = 0 Then
arr(1) = Trim(strSQL)
SplitSQLOnWhere = arr
Exit Function
End If
arr(1) = Trim(Left$(strSQL, lWherePos - 1))
arr(2) = Trim(Mid$(strSQL, lWherePos))
SplitSQLOnWhere = arr
End Function
Function GetSelectFields(strSelectFrom As String) As Variant
Dim arr
Dim strSelect As String
Dim strTemp As String
Dim lStart As Long
Dim lEnd As Long
Dim i As Long
lStart = InStr(6, strSelectFrom, " ", vbBinaryCompare) + 1
lEnd = InStr(lStart, UCase(strSelectFrom), " FROM", vbBinaryCompare)
strSelect = Replace(Trim(Mid$(strSelectFrom, _
lStart, _
lEnd - lStart)), _
" ", _
"", _
1, _
-1, _
vbBinaryCompare)
'£ is one of the very few non-letter chars allowed as Access fields
'other one is under-score
'take out brackets for if we have for example COUNT(E.ENTRY_ID)
'------------------------------------------------------------------
If InStr(1, strSelect, ",", vbBinaryCompare) = 0 Then
strTemp = Replace(strSelect, "(", "_", 1, -1, vbBinaryCompare)
strTemp = Replace(strTemp, ")", "", 1, -1, vbBinaryCompare)
GetSelectFields = Replace(strTemp, ".", "_", 1, -1, vbBinaryCompare)
Else
arr = Split(strSelect, ",")
For i = 0 To UBound(arr)
strTemp = Replace(arr(i), "(", "_", 1, -1, vbBinaryCompare)
strTemp = Replace(strTemp, ")", "", 1, -1, vbBinaryCompare)
arr(i) = Replace(strTemp, ".", "_", 1, -1, vbBinaryCompare)
Next
GetSelectFields = arr
End If
End Function
Function MakeFieldDefs(arrFields As Variant, _
arrTypes As Variant, _
lFieldCount As Long, _
bAddTypes As Boolean) As String
Dim i As Long
Dim strTemp As String
If bAddTypes Then
If lFieldCount = 1 Then
MakeFieldDefs = "(" & arrFields & " " & arrTypes & ")"
Else
strTemp = "(" & arrFields(0) & " " & arrTypes(0) & ", "
For i = 1 To UBound(arrFields)
If i = UBound(arrFields) Then
strTemp = strTemp & arrFields(i) & " " & arrTypes(i) & ")"
Else
strTemp = strTemp & arrFields(i) & " " & arrTypes(i) & ", "
End If
Next
End If
Else
If lFieldCount = 1 Then
MakeFieldDefs = " (" & arrFields & ") "
Else
strTemp = "(" & arrFields(0) & ", "
For i = 1 To UBound(arrFields)
If i = UBound(arrFields) Then
strTemp = strTemp & arrFields(i) & ") "
Else
strTemp = strTemp & arrFields(i) & ", "
End If
Next
End If
End If
MakeFieldDefs = strTemp
End Function
Function CountChar(strChar As String, _
strString As String) As Long
Dim i As Long
Dim n As Long
Dim btArray() As Byte
Dim btAscChar As Byte
If InStr(1, strString, strChar, vbBinaryCompare) = 0 Or _
Len(strString) = 0 Then
CountChar = 0
Exit Function
End If
btAscChar = Asc(strChar)
btArray = strString
For i = 0 To UBound(btArray) - 1 Step 2
If btArray(i) = btAscChar Then
n = n + 1
End If
Next
CountChar = n
End Function
RBS
to make it work with GROUP BY constructions. Could it work with
that? The problem might be that I still don't understand what exactly
is going on at:
" IN """"
Sub Test()
Dim strMDBPath As String
Dim strUN As String
Dim strPW As String
Dim strDSN As String
Dim strDBPath As String
Dim lOLDMETADATA As Long
Dim strSQL As String
Dim strTable As String
Dim arrTypes As Variant
strMDBPath = "C:\test.mdb"
strUN = "sysdba"
strPW = "torexkey"
strDSN = "System 6000"
strDBPath = "C:\Torex\Synergy\Meddata\S6000\db\s6.gdb"
lOLDMETADATA = 1
strTable = "TestTable"
'strSQL = "SELECT E.READ_CODE, E.TERM_TEXT " & _
"FROM ENTRY E INNER JOIN PATIENT P ON " & _
"(E.PATIENT_ID = P.PATIENT_ID) " & _
"WHERE E.READ_CODE = 'G2...' AND " & _
"NOT P.MAIN_REG_TYPE = 1"
'--------------------------------------
'this one doesn't work, will get:
'ODBC - call failed. (Error 3146)
'--------------------------------------
strSQL = "SELECT E.READ_CODE, COUNT(E.ENTRY_ID) FROM " & _
"ENTRY E WHERE E.READ_CODE LIKE 'G%' " & _
"GROUP BY E.READ_CODE " & _
"ORDER BY 2 DESC"
'arrTypes = Array("CHAR", "CHAR")
arrTypes = Array("CHAR", "LONG")
IB2Access strMDBPath, _
strUN, _
strPW, _
strDSN, _
strDBPath, _
lOLDMETADATA, _
strSQL, _
strTable, _
arrTypes
End Sub
Sub IB2Access(strMDBPath As String, _
strUN As String, _
strPW As String, _
strDSN As String, _
strDBPath As String, _
lOLDMETADATA As Long, _
strSQL As String, _
strTable As String, _
arrTypes As Variant)
Dim db As DAO.Database
Dim strConnect As String
Dim arr
Dim strSelectFrom As String
Dim lFieldCount As Long
'could start at GROUP BY or ORDER BY
'if there is no WHERE clause
'that is if this could work
'-----------------------------------
Dim strWhere As String
Dim arrFields
Dim strFieldDefs As String
arr = SplitSQLOnWhere(strSQL)
strSelectFrom = arr(1)
strWhere = arr(2)
arrFields = GetSelectFields(strSelectFrom)
lFieldCount = CountChar(",", strSelectFrom) + 1
On Error Resume Next
Kill strMDBPath
On Error GoTo 0
strConnect = "ODBC;" & _
"DSN=" & strDSN & ";" & _
"UID=" & strUN & ";" & _
"PWD=" & strPW & ";" & _
"DB=" & strDBPath & ";" & _
"OLDMETADATA=" & lOLDMETADATA & ";"
Set db = DBEngine.CreateDatabase(strMDBPath, dbLangGeneral)
With db
strFieldDefs = MakeFieldDefs(arrFields, arrTypes, lFieldCount, True)
.Execute "CREATE TABLE " & _
strTable & _
strFieldDefs, _
dbFailOnError
'not figured out yet what exactly is happening here:
' " IN """"
'---------------------------------------------------
strFieldDefs = MakeFieldDefs(arrFields, arrTypes, lFieldCount, False)
.Execute "INSERT INTO " & _
strTable & _
strFieldDefs & _
strSelectFrom & _
" IN """" [" & strConnect & "] " & _
strWhere, _
dbFailOnError
.Close
End With
Set db = Nothing
End Sub
Function SplitSQLOnWhere(strSQL As String) As String()
'splits SQL on first WHERE clause
'not suitable for sub-queries with multiple WHERE
'may need a different split here for GROUP BY etc.
'-------------------------------------------------
Dim lWherePos As Long
Dim arr(1 To 2) As String
lWherePos = InStr(1, UCase(strSQL), "WHERE", vbBinaryCompare)
If lWherePos = 0 Then
arr(1) = Trim(strSQL)
SplitSQLOnWhere = arr
Exit Function
End If
arr(1) = Trim(Left$(strSQL, lWherePos - 1))
arr(2) = Trim(Mid$(strSQL, lWherePos))
SplitSQLOnWhere = arr
End Function
Function GetSelectFields(strSelectFrom As String) As Variant
Dim arr
Dim strSelect As String
Dim strTemp As String
Dim lStart As Long
Dim lEnd As Long
Dim i As Long
lStart = InStr(6, strSelectFrom, " ", vbBinaryCompare) + 1
lEnd = InStr(lStart, UCase(strSelectFrom), " FROM", vbBinaryCompare)
strSelect = Replace(Trim(Mid$(strSelectFrom, _
lStart, _
lEnd - lStart)), _
" ", _
"", _
1, _
-1, _
vbBinaryCompare)
'£ is one of the very few non-letter chars allowed as Access fields
'other one is under-score
'take out brackets for if we have for example COUNT(E.ENTRY_ID)
'------------------------------------------------------------------
If InStr(1, strSelect, ",", vbBinaryCompare) = 0 Then
strTemp = Replace(strSelect, "(", "_", 1, -1, vbBinaryCompare)
strTemp = Replace(strTemp, ")", "", 1, -1, vbBinaryCompare)
GetSelectFields = Replace(strTemp, ".", "_", 1, -1, vbBinaryCompare)
Else
arr = Split(strSelect, ",")
For i = 0 To UBound(arr)
strTemp = Replace(arr(i), "(", "_", 1, -1, vbBinaryCompare)
strTemp = Replace(strTemp, ")", "", 1, -1, vbBinaryCompare)
arr(i) = Replace(strTemp, ".", "_", 1, -1, vbBinaryCompare)
Next
GetSelectFields = arr
End If
End Function
Function MakeFieldDefs(arrFields As Variant, _
arrTypes As Variant, _
lFieldCount As Long, _
bAddTypes As Boolean) As String
Dim i As Long
Dim strTemp As String
If bAddTypes Then
If lFieldCount = 1 Then
MakeFieldDefs = "(" & arrFields & " " & arrTypes & ")"
Else
strTemp = "(" & arrFields(0) & " " & arrTypes(0) & ", "
For i = 1 To UBound(arrFields)
If i = UBound(arrFields) Then
strTemp = strTemp & arrFields(i) & " " & arrTypes(i) & ")"
Else
strTemp = strTemp & arrFields(i) & " " & arrTypes(i) & ", "
End If
Next
End If
Else
If lFieldCount = 1 Then
MakeFieldDefs = " (" & arrFields & ") "
Else
strTemp = "(" & arrFields(0) & ", "
For i = 1 To UBound(arrFields)
If i = UBound(arrFields) Then
strTemp = strTemp & arrFields(i) & ") "
Else
strTemp = strTemp & arrFields(i) & ", "
End If
Next
End If
End If
MakeFieldDefs = strTemp
End Function
Function CountChar(strChar As String, _
strString As String) As Long
Dim i As Long
Dim n As Long
Dim btArray() As Byte
Dim btAscChar As Byte
If InStr(1, strString, strChar, vbBinaryCompare) = 0 Or _
Len(strString) = 0 Then
CountChar = 0
Exit Function
End If
btAscChar = Asc(strChar)
btArray = strString
For i = 0 To UBound(btArray) - 1 Step 2
If btArray(i) = btAscChar Then
n = n + 1
End If
Next
CountChar = n
End Function
RBS