Unrecognized DB Format-Excel VBA to Access Database - vba

Im using a .accdb file and connecting with the following code, which has worked for me multiple times, so I don't know why its corrupting the file this time.
dbPath = ActiveWorkbook.Path & "\WaitAnalysisDB.accdb"
tblName = "Wait_Data_Table"
strcon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & dbPath & "';"
conn.Open strcon
Does the "Unrecognized Format" Access error only occur due to an error in the connection string, or could it be my SQL statement inserting records as well? Thanks
Here's my code, if anyone cares to look through it. In the for loops that build the SQL statemetn (rcdDetail variable), I have an if statement, which basically says if there is a blank in Column A, then use the row above it that isnt blank.
Dim conn As New ADODB.Connection, rs As New ADODB.Recordset, dbPath As String, tblName As String
Dim rngColHeads As Range, rngTblRcds As Range, colHead As String, rcdDetail As String
Dim ch As Integer, cl As Integer, notNull As Boolean, strcon As String, lr As Integer
Dim currentdate As String
Dim strdbcheck As String
'Code Checks if There Are Records for the Date in the DB
'If there is, then it skips the SQL code
currentdate = Date
dbPath = ActiveWorkbook.Path & "\WaitAnalysisDB.accdb"
tblName = "Wait_Data_Table"
strcon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & dbPath & "';"
conn.Open strcon
strdbcheck = "SELECT * FROM " & tblName
rs.Open strdbcheck, conn
rs.Filter = "Date= #" & currentdate & "#"
If Not rs.EOF Then
Set rs = Nothing
Set conn = Nothing
GoTo SkipExport
Else
Set rs = Nothing
Set conn = Nothing
GoTo Export
End If
Export:
'Set Up Connections
dbPath = ActiveWorkbook.Path & "\WaitAnalysisDB.accdb"
tblName = "Wait_Data_Table"
'Create Date Column
Worksheets("Wait Analysis DATA").Select
lr = Cells(Rows.Count, "K").End(xlUp).Row
currentdate = Date: Range("O1").Value = "Date": Range(Range("O2"), Range("O" & lr)).Value = currentdate
Set rngColHeads = ActiveSheet.Range(Range("a1"), Range("a1").End(xlToRight))
Set rngTblRcds = ActiveSheet.Range(Range("K2:k" & lr).Offset(0, -10), Range("K2:k" & lr).Offset(0, 4))
'SQL connection String
strcon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & dbPath & "';"
'Create String for Columns for SQL
colHead = "(["
For ch = 1 To rngColHeads.Count
colHead = colHead & rngColHeads.Columns(ch).Value
Select Case ch
Case Is = rngColHeads.Count
colHead = colHead & "])"
Case Else
colHead = colHead & "],["
End Select
Next ch
On Error GoTo EndUpdate
conn.Open strcon
conn.BeginTrans
Dim tempcl As Integer
For cl = 1 To rngTblRcds.Rows.Count
If Range("a2").Offset(cl - 1, 0) = "" Then
tempcl = cl - Range("a2").Offset(cl, 0).End(xlUp).Rows.Count
notNull = False
rcdDetail = "('"
For ch = 1 To rngColHeads.Count
Select Case rngTblRcds.Rows(tempcl).Columns(ch).Value
Case Is = Empty
Select Case ch
Case Is = rngColHeads.Count
rcdDetail = Left(rcdDetail, Len(rcdDetail) - 1) & "NULL)"
Case Else
rcdDetail = Left(rcdDetail, Len(rcdDetail) - 1) & "NULL,'"
End Select
Case Else
notNull = True
Select Case ch
Case "11":
rcdDetail = rcdDetail & rngTblRcds.Rows(cl).Columns(ch).Value & "','"
Case Is = rngColHeads.Count
rcdDetail = rcdDetail & rngTblRcds.Rows(tempcl).Columns(ch).Value & "')"
Case Else
rcdDetail = rcdDetail & rngTblRcds.Rows(tempcl).Columns(ch).Value & "','"
End Select
End Select
Next ch
tempcl = 0
GoTo skipads
End If
notNull = False
rcdDetail = "('"
For ch = 1 To rngColHeads.Count
Select Case rngTblRcds.Rows(cl).Columns(ch).Value
Case Is = Empty
Select Case ch
Case Is = rngColHeads.Count
rcdDetail = Left(rcdDetail, Len(rcdDetail) - 1) & "NULL)"
Case Else
rcdDetail = Left(rcdDetail, Len(rcdDetail) - 1) & "NULL,'"
End Select
Case Else
notNull = True
Select Case ch
Case Is = rngColHeads.Count
rcdDetail = rcdDetail & rngTblRcds.Rows(cl).Columns(ch).Value & "')"
Case Else
rcdDetail = rcdDetail & rngTblRcds.Rows(cl).Columns(ch).Value & "','"
End Select
End Select
Next ch
skipads:
Select Case notNull
Case Is = True
rs.Open "INSERT INTO " & tblName & colHead & " VALUES " & rcdDetail, conn
Case Is = False
'do not insert record
End Select
Next cl
EndUpdate:
If Err.Number <> 0 Then
On Error Resume Next
conn.RollbackTrans
MsgBox "There was an error. This will exit the macro.", vbCritical, "Error!"
End
Else
On Error Resume Next
conn.CommitTrans
End If
conn.Close
Set rs = Nothing
Set conn = Nothing
On Error GoTo 0
SkipExport:

Everything looks ok, here's what I'd try.
Manually type the path for dbPath, moreover the entire connection string. Perhaps path isn't being populated correctly.
Here's the connection string you can follow:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\myFolder\myAccessFile.accdb;Persist Security Info=False;
If that doesn't work, double check your table name is correctly named. If it checks out, try wrapping your table name in []. So:
tblName = "[Wait_Data_Table]"
These are common things that give me grief, perhaps one of these are happening to you as well.

Related

Can't union two tables even though ADODB confirms equal field counts

I'm not able to union two csvs even though ADODB confirms via .Fields.Count that they both have the same number of columns.
Here's the query that's failing:
select * from csv1.csv union select * from csv2.csv
with the error message:
The number of columns in the two selected tables or queries of a union query do not match
However, when I do select * from csv1.csv and select * from csv2.csv separately, ADODB confirms that .Fields.Count = 8 for both.
Possible key to the problem:
Do I need to create two separate connections? I'm only creating one connection (to the first csv) even though there are two csvs in the query.
I was trying to figure out how to do two separate connections for the same query and it seemed like people weren't finding that necessary - I couldn't find two connections mentioned in equivalent queries people were running against csvs.
Per #Parfait's request to see more of the code:
GetDataFromCSV
Public Function GetDataFromCSV(ByVal fileReport As Scripting.File, ByVal strQuery As String, ByVal arrSourceReports As Variant) As Boolean
Dim strRevisedQuery As String
strRevisedQuery = GetRevisedQueryWithFileAliasesReplacedWithTrueFileNames(strQuery, arrSourceReports)
Dim cnn As ADODB.Connection
Set cnn = OpenConnectionToCSV(fileReport)
If cnn Is Nothing Then
GetDataFromCSV = False
Exit Function
End If
GetDataFromCSV = QueryDataFromCSV(cnn, strRevisedQuery, fileReport.Name, fileReport.Name)
End Function
OpenConnectionToCSV
Private Function OpenConnectionToCSV(ByVal fileCSV As Scripting.File, Optional boolHeadersPresent As Boolean = True) As ADODB.Connection
Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection
cnn.ConnectionTimeout = 0
Dim strfileCSVParentFolderPath As String
strfileCSVParentFolderPath = fileCSV.ParentFolder
If Right(strfileCSVParentFolderPath, 1) <> Application.PathSeparator Then strfileCSVParentFolderPath = strfileCSVParentFolderPath & Application.PathSeparator
Dim strConn As String
If boolHeadersPresent = False Then
strConn = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & strfileCSVParentFolderPath & ";Extended Properties=""text;HDR=NO;FMT=Delimited"""
Else
strConn = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & strfileCSVParentFolderPath & ";Extended Properties=""text;HDR=YES;FMT=Delimited"""
End If
If strConn <> vbNullString Then
On Error GoTo ErrorHandler
Dim lngRetryCount As Long
lngRetryCount = 0
cnn.Open strConn
On Error GoTo 0
Set OpenConnectionToCSV = cnn
End If
Exit Function
ErrorHandler:
Select Case True
Case InStr(1, Err.Description, "Connect timeout occurred", vbTextCompare) > 0
If lngRetryCount < 30 Then
Application.Wait DateAdd("s", 1, Now)
lngRetryCount = lngRetryCount + 1
Resume
Else
MsgBox "Can't connect to " & fileCSV.Path & ". Reading this file will be skipped."
Exit Function
End If
Case Else
MsgBox "Getting data from " & fileCSV.Name & " has failed with the following error message: " & Err.Number & ": " & Err.Description
On Error GoTo 0
Resume
End Select
End Function
QueryDataFromCSV
Private Function QueryDataFromCSV(ByVal cnn As ADODB.Connection, ByVal strQuery As String, ByVal strCSVName As String, ByVal strFinalReportTitle As String) As Boolean
QueryDataFromCSV = True
Dim cmd As ADODB.Command
Set cmd = PrepareQueryCommand(cnn, strQuery)
CreateQueryDebugLog cmd.CommandText
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
rst.Open cmd
Dim Loop1 As Long
With rst
For Loop1 = 1 To .Fields.Count
If .Fields(Loop1 - 1).Name = "F" & Loop1 Then
If Loop1 < 4 Then
MsgBox "Can't retrieve data from " & strCSVName & " because it is formatted improperly."
Else
MsgBox "Can't retrieve data from " & strCSVName & " because it is delimited improperly. The file is most likely delimited with a comma even though it has addresses or other fields that contain commas. Ask Encounters IT to change this report's delimiter to another character, such as | (pipe), in the Tidal batch file."
End If
QueryDataFromCSV = False
Exit Function
End If
Next Loop1
End With
CopyThisCSVRecordsetToResultSheets rst, strFinalReportTitle
cnn.Close
Set rst = Nothing
Set cmd = Nothing
Set cnn = Nothing
End Function
The error is occurring at rst.Open cmd in the above function QueryDataFromCSV
Illustrating schema.ini creation for #Comintern:
GetRevisedQueryWithFileAliasesReplacedWithTrueFileNames
Private Function GetRevisedQueryWithFileAliasesReplacedWithTrueFileNames(ByVal strQuery As String, ByVal arrSourceReports As Variant) As String
Dim FSO As Scripting.FileSystemObject
Set FSO = New Scripting.FileSystemObject
Dim lngPosition As Long
lngPosition = 0
Do Until lngPosition > Len(strQuery)
Dim lngStartPosition As Long
lngStartPosition = InStr(lngPosition + 1, strQuery, "from", vbTextCompare) + 5
If lngStartPosition > lngPosition Then
Dim lngEndPosition As Long
lngEndPosition = InStr(lngStartPosition + 1, strQuery, " ", vbTextCompare)
If lngEndPosition = 0 Then lngEndPosition = Len(strQuery) + 1
Dim strSourceReportTitle As String
strSourceReportTitle = Mid(strQuery, lngStartPosition, lngEndPosition - lngStartPosition)
Dim Loop2 As Long
For Loop2 = LBound(arrSourceReports, 1) To UBound(arrSourceReports, 1)
If arrSourceReports(Loop2, 1) = strSourceReportTitle Then Exit For
Next Loop2
Dim fileSource As Scripting.File
Set fileSource = FSO.GetFile(arrSourceReports(Loop2, 3))
If arrSourceReports(Loop2, 2) = "TAB" Then arrSourceReports(Loop2, 2) = Chr(9)
CreateSchemaIni fileSource, arrSourceReports(Loop2, 2)
Dim strRevisedQuery As String
If strRevisedQuery = vbNullString Then
strRevisedQuery = Replace(strQuery, "from " & strSourceReportTitle, "from " & fileSource.Name)
Else
strRevisedQuery = Replace(strRevisedQuery, "from " & strSourceReportTitle, "from " & fileSource.Name)
End If
lngPosition = lngEndPosition
Else
lngPosition = Len(strQuery) + 1
End If
Loop
GetRevisedQueryWithFileAliasesReplacedWithTrueFileNames = strRevisedQuery
End Function
CreateSchemaIni
Private Sub CreateSchemaIni(ByVal fileReport As Scripting.File, ByVal strDelimiter As String)
Dim intSystemFileNumber As Integer
intSystemFileNumber = FreeFile()
On Error GoTo ErrorHandler
Open fileReport.ParentFolder.Path & Application.PathSeparator & "Schema.ini" For Output As #intSystemFileNumber
Print #intSystemFileNumber, "[" & fileReport.Name & "]"
Print #intSystemFileNumber, "Format=Delimited(" & strDelimiter & ")"
Close #intSystemFileNumber
Exit Sub
ErrorHandler:
Select Case True
Case InStr(1, Err.Description, "Path/File Access Error", vbTextCompare) > 0
Dim strStandardQueryDebugLogPath As String
strStandardQueryDebugLogPath = fileReport.ParentFolder.Path & Application.PathSeparator & "strQuery.txt"
MsgBox strStandardQueryDebugLogPath & " was inaccessible. Creating log in same folder where your copy of the Mass Queryer is saved instead."
Open Left(ThisWorkbook.Path, InStrRev(ThisWorkbook.Path, Application.PathSeparator, , vbTextCompare)) & "strQuery.txt" For Output As #intSystemFileNumber
Print #intSystemFileNumber, "[" & fileReport.Name & "]"
Print #intSystemFileNumber, "Format=Delimited(" & strDelimiter & ")"
Close #intSystemFileNumber
Exit Sub
Case Else
MsgBox "Creating a query debug log has failed with the following error message: " & Err.Number & ": " & Err.Description
On Error GoTo 0
Resume
End Select
End Sub
With #Comintern's help, I was able to see that I made a silly mistake having nothing to do with the question title in actuality. You can see above that my CreateSchemaIni method was creating and then overwriting the Schema.ini file for each csv I was querying rather than creating and then appending to it. By changing that method to use Open For Append instead of Open For Output, the problem was solved.

Missing value in expression

I am receiving a general ODBC error when executing the code below. I also receive a pop-up box before the error to Enter Parameter Value for parameter1. I do not know what range is incorrectly referenced in my code.
Sub CIABIConnect()
Dim sConn As String
Dim sSql As String
Dim oQt As QueryTable
Dim part As String
Dim fromDate As String
Dim toDate As String
Dim reportSelect As String
Dim thisBook As Workbook
Dim inSheet As Worksheet
Dim outSheet As Worksheet
Dim connName As String
Dim todateString As String
Dim fromdateString As String
Dim locString As String
Dim lastRow As Integer
Set thisBook = ActiveWorkbook
Set inSheet = thisBook.Worksheets("Direct Query")
Set outSheet = thisBook.Worksheets("Direct Data")
inSheet.Select
inSheet.Range("B6").Activate
lastRow = inSheet.UsedRange.Rows.Count
fromDate = Format(inSheet.Cells(2, 2).Value, "yyyymmdd")
toDate = Format(inSheet.Cells(3, 2).Value, "yyyymmdd")
fromdateString = " '" & fromDate & "' "
todateString = " '" & toDate & "' "
connName = inSheet.Cells(11, 2).Value
Call deleteConnections
outSheet.Cells.Clear
outSheet.Select
sConn = "ODBC;DSN=" & connName
sConn = sConn & ";DBQ=" & connName
sConn = sConn & ";"
For i = 2 To lastRow
Select Case i
Case 37: sSql = sSql & inSheet.Cells(i, 4).Value & fromdateString
Case 38: sSql = sSql & inSheet.Cells(i, 4).Value & todateString
Case Else: sSql = sSql & inSheet.Cells(i, 4).Value
End Select
Next i
Set oQt = ActiveSheet.QueryTables.Add( _
Connection:=sConn, _
Destination:=outSheet.Range("a1"), _
Sql:=sSql)
oQt.refresh
CrwOut.Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Columns.AutoFit
End Sub
Sub deleteConnections()
For Each conn In ThisWorkbook.Connections
conn.Delete
Next conn
End Sub
SQL:
SELECT
'Direct from APIA' as source_nm
,itm.merch_cat_desc
,case
when data.purchase_type='EDGE' then 'Edge'
when data.purchase_type='TRADITIONAL' then 'Traditional'
else '?'
end "EDGE/NON-EDGE"
,sum(data.item_qty) as Net_Quantity
,sum(data.bams_price) as Net_Cost
,sum(data.revenue) as Net_Revenue
,sum(DATA.IT_DISC_AMT * SIGN (DATA.ITEM_QTY)) as Net_Discount
,sum( case
when data.item_qty > 0 then data.revenue
else 0
end
) as Gross_Revenue
,sum(
case
when data.item_qty > 0 then data.item_qty
else 0
end
) as Gross_Quantity
FROM DATA
--
JOIN INV.INV_STORE_EXTRACT STORE ON STORE.STORE_ID = DATA.STORE
--
JOIN INV.INV_CODA_CHANNEL CODA ON CODA.CODA_DEPT = STORE.CODA_DEPT
--
JOIN INV.ITEM_LIST_DRM ITM ON ITM.ITEM_CD = DATA.ITEM_CODE
--
LEFT OUTER JOIN INV.PROGRAM_DRM PRGRM
ON ITM.EQP_ITEM_PROGRAM_RPTKEY = PRGRM.PROGRAM_RPTKEY
--
WHERE
data.ord_comp_date between
**20170426
and
20170427**
--data.acct_prd='201708'
and data.trade_in_ind = 'N'
and CODA.CHANNEL_CATEGORY='DIRECT'
and PRGRM.program_cd in ('APO','CPO','IOT','NEW','USED','VIR')
and ITM.EQP_CLASS_DESC='Wireless Devices'
group by
itm.merch_cat_desc
,case
when data.purchase_type='EDGE' then 'Edge'
when data.purchase_type='TRADITIONAL' then 'Traditional'
else '?'
end

Trying to make code more efficient and stable

I have a program, that works, I just feel that it is running slower than it should and I feel that it is a bit more unstable than it should be. I am looking for tips on writing "better" code and making my program more stable.
I am looking to better this part of my code for now:
Private Sub Worksheet_Activate()
Application.ScreenUpdating = False
'Removes shapes already there that will be updated by the getWeather function
For Each delShape In Shapes
If delShape.Type = msoAutoShape Then delShape.Delete
Next delShape
'Calls a function to get weather data from a web service
Call getWeather("", "Area1")
Call getWeather("", "Area2")
Call getWeather("", "Area3")
'Starting to implement the first connection to a SQL Access database.
Dim cn As Object
Dim rs As Object
'Set cn and sqlConnect as ADODB-objects. Set rs as recordset
Set cn = CreateObject("ADODB.Connection")
Set sqlConnect = New ADODB.Connection
Set rs = CreateObject("ADODB.RecordSet")
'Set sqlConnect as connection string
sqlConnect.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\databases\database.accdb;Persist Security Info=False;"
'Open connection string via connection object
cn.Open sqlConnect
'Set rs.Activeconnection to cn
rs.ActiveConnection = cn
'Get a username from the application to be used further down
Brukernavn = Application.userName
'This part of the code re-arranges the date format from american to european
StartDate = Date
EndDate = Date - 7
midStartDate = Split(StartDate, ".")
midEndDate = Split(EndDate, ".")
StartDate2 = "" & midStartDate(1) & "/" & midStartDate(0) & "/" & midStartDate(2) & ""
EndDate2 = "" & midEndDate(1) & "/" & midEndDate(0) & "/" & midEndDate(2) & ""
'SQL statement to get data from the access database
rs.Open "SELECT [RefNr], [Registrert Av],[Nettstasjon], [Meldt Dato] , [Bestilling], [Sekundærstasjon], [Avgang], [Hovedkomponent], [HovedÅrsak], [Status Bestilling] FROM [tblDatabase]" & _
"WHERE [Registrert Av] = '" & Brukernavn & "' AND [Loggtype] <> 'Beskjed' AND [Meldt Dato] BETWEEN #" & StartDate2 & "# AND # " & EndDate2 & "#" & _
"ORDER BY [Meldt Dato] DESC;", _
cn, adOpenStatic
'Start to insert data from access database into a list
Dim i As Integer
Dim u As Integer
If Not rs.EOF Then
rs.MoveFirst
End If
i = 0
With lst_SisteFeil
.Clear
Do
If Not rs.EOF Then
.AddItem
If Not IsNull(rs!refnr) Then
.List(i, 0) = rs![refnr]
End If
If IsDate(rs![Meldt Dato]) Then
.List(i, 1) = Format(rs![Meldt Dato], "dd/mm/yy")
End If
.List(i, 4) = rs![nettstasjon]
If Not IsNull(rs![Sekundærstasjon]) Then
.List(i, 2) = rs![Sekundærstasjon]
End If
If Not IsNull(rs![Avgang]) Then
.List(i, 3) = rs![Avgang]
End If
If Not IsNull(rs![Hovedkomponent]) Then
.List(i, 5) = rs![Hovedkomponent]
End If
If Not IsNull(rs![HovedÅrsak]) Then
.List(i, 6) = rs![HovedÅrsak]
End If
If Not IsNull(rs![Status Bestilling]) Then
.List(i, 7) = rs![Status Bestilling]
End If
If Not IsNull(rs![bestilling]) Then
.List(i, 8) = rs![bestilling]
End If
i = i + 1
rs.MoveNext
Else
GoTo endOfFile
End If
Loop Until rs.EOF
End With
endOfFile:
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
'Starts to connect to SQL access database again to get different set of data. This must be possible to make more efficient?
Dim cn2 As Object
Dim rs2 As Object
'Set cn and sqlConnect as ADODB-objects. Set rs as recordset
Set cn2 = CreateObject("ADODB.Connection")
Set sqlConnect2 = New ADODB.Connection
Set rs2 = CreateObject("ADODB.RecordSet")
'Set sqlConnect as connection string
sqlConnect2.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\databases\database.accdb;Persist Security Info=False;"
'Open connection string via connection object
cn2.Open sqlConnect
'Set rs.Activeconnection to cn
rs2.ActiveConnection = cn2
'Second SQL statement
rs2.Open "SELECT [RefNr], [Registrert Av],[Nettstasjon], [Meldt Dato] , [Bestilling], [Sekundærstasjon], [Avgang], [Hovedkomponent], [HovedÅrsak], [Status Bestilling] FROM [tblDatabase]" & _
"WHERE [Registrert Av] <> '" & Brukernavn & "' AND [Meldt Dato] BETWEEN #" & StartDate2 & "# AND # " & EndDate2 & "#" & _
"ORDER BY [Meldt Dato] DESC;", _
cn2, adOpenStatic
'Inserting into second list
If Not rs2.EOF Then
rs2.MoveFirst
End If
u = 0
With lst_AlleFeil
.Clear
Do
If Not rs2.EOF Then
.AddItem
If Not IsNull(rs2!refnr) Then
.List(u, 0) = rs2![refnr]
End If
If IsDate(rs2![Meldt Dato]) Then
.List(u, 1) = Format(rs2![Meldt Dato], "dd/mm/yy")
End If
.List(u, 4) = rs2![nettstasjon]
If Not IsNull(rs2![Sekundærstasjon]) Then
.List(u, 2) = rs2![Sekundærstasjon]
End If
If Not IsNull(rs2![Avgang]) Then
.List(u, 3) = rs2![Avgang]
End If
If Not IsNull(rs2![Hovedkomponent]) Then
.List(u, 5) = rs2![Hovedkomponent]
End If
If Not IsNull(rs2![HovedÅrsak]) Then
.List(u, 6) = rs2![HovedÅrsak]
End If
If Not IsNull(rs2![Status Bestilling]) Then
.List(u, 7) = rs2![Status Bestilling]
End If
If Not IsNull(rs2![bestilling]) Then
.List(u, 8) = rs2![bestilling]
End If
u = u + 1
rs2.MoveNext
Else
GoTo endOfFile2
End If
Loop Until rs2.EOF
End With
endOfFile2:
rs2.Close
cn2.Close
Set rs2 = Nothing
Set cn2 = Nothing
'Starting to connect to the database for the third time
Dim cn3 As Object
Dim rs3 As Object
'Set cn and sqlConnect as ADODB-objects. Set rs as recordset
Set cn3 = CreateObject("ADODB.Connection")
Set sqlConnect3 = New ADODB.Connection
Set rs3 = CreateObject("ADODB.RecordSet")
'Set sqlConnect as connection string
sqlConnect3.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\databases\database.accdb;Persist Security Info=False;"
'Open connection string via connection object
cn3.Open sqlConnect
'Set rs.Activeconnection to cn
rs3.ActiveConnection = cn3
'third sql statement
rs3.Open "SELECT [RefNr], [Registrert Av],[Nettstasjon], [Meldt Dato], [Sekundærstasjon], [Avgang], [Beskrivelse], [Til Dato] FROM [tblDatabase]" & _
"WHERE [Loggtype] = 'Beskjed' AND [Meldt Dato] >= DateAdd('d',-30,Date())" & _
"ORDER BY [Meldt Dato] DESC;", _
cn3, adOpenStatic
'Inserting data in to third list
If Not rs3.EOF Then
rs3.MoveFirst
End If
j = 0
With lst_beskjeder
.Clear
Do
If Not rs3.EOF Then
.AddItem
If Not IsNull(rs3!refnr) Then
.List(j, 0) = rs3![refnr]
End If
If IsDate(rs3![Meldt Dato]) Then
.List(j, 1) = Format(rs3![Meldt Dato], "dd/mm/yy")
End If
.List(j, 4) = rs3![nettstasjon]
If Not IsNull(rs3![Sekundærstasjon]) Then
.List(j, 2) = rs3![Sekundærstasjon]
End If
If Not IsNull(rs3![Avgang]) Then
.List(j, 3) = rs3![Avgang]
End If
If Not IsNull(rs3![beskrivelse]) Then
.List(j, 5) = rs3![beskrivelse]
End If
j = j + 1
rs3.MoveNext
Else
GoTo endOfFile3
End If
Loop Until rs3.EOF
End With
endOfFile3:
rs3.Close
cn3.Close
Set rs3 = Nothing
Set cn3 = Nothing
End Sub
Here is the function I have used to get weather data.
Public Sub getWeather(APIurl As String, sted As String)
Dim i As Integer
i = 0
Dim omraade As String
omraade = ""
omraade = sted
If sted = "Area1" Then
i = 4
ElseIf sted = "Area2" Then
i = 6
ElseIf sted = "Area3" Then
i = 8
End If
Dim WS As Worksheet: Set WS = ActiveSheet
Dim delShape As Shape
Dim city As String
Dim Req As New XMLHTTP
Req.Open "GET", "" & APIurl & "", False
Req.Send
Dim Resp As New DOMDocument
Resp.LoadXML Req.responseText
Dim Weather As IXMLDOMNode
Dim wShape As Shape
Dim thisCell As Range
For Each Weather In Resp.getElementsByTagName("current_condition")
Set thisCell = WS.Range(Cells(2, i), Cells(2, i))
Set wShape = WS.Shapes.AddShape(msoShapeRectangle, thisCell.Left, thisCell.Top, thisCell.Width, thisCell.Height)
wShape.Fill.UserPicture Weather.ChildNodes(4).Text 'img
Cells(3, i).Value = "" & Weather.ChildNodes(7).Text * 0.28 & " m/s" 'windspeedkmph
Cells(4, i).Value = Weather.ChildNodes(9).Text 'Direction
Cells(5, i).Value = Weather.ChildNodes(1).Text & " C" 'observation time
Next Weather
End Sub
Feel free to point out any poor coding and tips on how to improve it. I am currently using the Worksheet Activate sub to activate changes in the tables and get new data, but I suspect that is not the best solution. I am just not sure how else to do it seeing as I want it to be as "automatic" as possible, and use as few buttons to refresh as I can.
Thank you for all the help.
-Thomas
Some tips, but none will affect performance, only help make your code more succinct.
1.
rs.Open "SELECT ..."
If Not rs.EOF Then
rs.MoveFirst
End If
.MoveFirst is unnecessary. After opening a recordset, you are always on the first record, if there are records.
When building complex SQL in VBA, have a look at How to debug dynamic SQL in VBA.
2.
Don't do a Do ... Until loop for recordsets:
Do
If Not rs.EOF Then
' do stuff for each record
' ...
rs.MoveNext
Else
GoTo endOfFile
End If
Loop Until rs.EOF
endOfFile:
rs.Close
Instead use Do While Not rs.EOF :
Do While Not rs.EOF
' do stuff for each record
' ...
rs.MoveNext
Loop
rs.Close
For an empty rs, the loop will not be entered. You don't need the If/Else and the Goto.

3146 ODBC Call Failed - Access 2010

Please reference code below...
Private Sub Save_Click()
On Error GoTo err_I9_menu
Dim dba As Database
Dim dba2 As Database
Dim rst As Recordset
Dim rst1 As Recordset
Dim rst2 As Recordset
Dim rst3 As Recordset
Dim SQL As String
Dim dateandtime As String
Dim FileSuffix As String
Dim folder As String
Dim strpathname As String
Dim X As Integer
X = InStrRev(Me!ListContents, "\")
Call myprocess(True)
folder = DLookup("[Folder]", "Locaton", "[LOC_ID] = '" & Forms!frmUtility![Site].Value & "'")
strpathname = "\\Reman\PlantReports\" & folder & "\HR\Paperless\"
dateandtime = getdatetime()
If Nz(ListContents, "") <> "" Then
Set dba = CurrentDb
FileSuffix = Mid(Me!ListContents, InStrRev(Me!ListContents, "."), 4)
SQL = "SELECT Extension FROM tbl_Forms WHERE Type = 'I-9'"
SQL = SQL & " AND Action = 'Submit'"
Set rst1 = dba.OpenRecordset(SQL, dbOpenDynaset, dbSeeChanges)
If Not rst1.EOF Then
newname = Me!DivisionNumber & "-" & Right(Me!SSN, 4) & "-" & LastName & dateandtime & rst1.Fields("Extension") & FileSuffix
Else
newname = Me!DivisionNumber & "-" & Right(Me!SSN, 4) & "-" & LastName & dateandtime & FileSuffix
End If
Set moveit = CreateObject("Scripting.FileSystemObject")
copyto = strpathname & newname
moveit.MoveFile Me.ListContents, copyto
Set rst = Nothing
Set dba = Nothing
End If
If Nz(ListContentsHQ, "") <> "" Then
Set dba2 = CurrentDb
FileSuffix = Mid(Me.ListContentsHQ, InStrRev(Me.ListContentsHQ, "."), 4)
SQL = "SELECT Extension FROM tbl_Forms WHERE Type = 'HealthQuestionnaire'"
SQL = SQL & " AND Action = 'Submit'"
Set rst3 = dba2.OpenRecordset(SQL, dbOpenDynaset, dbSeeChanges)
If Not rst3.EOF Then
newname = Me!DivisionNumber & "-" & Right(Me!SSN, 4) & "-" & LastName & dateandtime & rst3.Fields("Extension") & FileSuffix
Else
newname = Me!DivisionNumber & "-" & Right(Me!SSN, 4) & "-" & LastName & dateandtime & FileSuffix
End If
Set moveit = CreateObject("Scripting.FileSystemObject")
copyto = strpathname & newname
moveit.MoveFile Me.ListContentsHQ, copyto
Set rst2 = Nothing
Set dba2 = Nothing
End If
Set dba = CurrentDb
Set rst = dba.OpenRecordset("dbo_tbl_EmploymentLog", dbOpenDynaset, dbSeeChanges)
rst.AddNew
rst.Fields("TransactionDate") = Date
rst.Fields("EmployeeName") = Me.LastName
rst.Fields("EmployeeSSN") = Me.SSN
rst.Fields("EmployeeDOB") = Me.EmployeeDOB
rst.Fields("I9Pathname") = strpathname
rst.Fields("I9FileSent") = newname
rst.Fields("Site") = DLookup("Folder", "Locaton", "Loc_ID='" & Forms!frmUtility!Site & "'")
rst.Fields("UserID") = Forms!frmUtility!user_id
rst.Fields("HqPathname") = strpathname
rst.Fields("HqFileSent") = newname2
rst.Update
Set dba = Nothing
Set rst = Nothing
exit_I9_menu:
Call myprocess(False)
DivisionNumber = ""
LastName = ""
SSN = ""
ListContents = ""
ListContentsHQ = ""
Exit Sub
err_I9_menu:
Call myprocess(False)
MsgBox Err.Number & " " & Err.Description
'MsgBox "The program has encountered an error and the data was NOT saved."
Exit Sub
End Sub
I keep getting an ODBC call error. The permissions are all correct and the previous piece of code worked where there were separate tables for the I9 and Hq logs. The routine is called when someone submits a set of files with specific information.
Just a guess here, but I'm thinking you've got a typo that's resulting in assigning a Null to a required field.
Change "Locaton":
rst.Fields("Site") = DLookup("Folder", "Locaton", "Loc_ID='" & Forms!frmUtility!Site & "'")
To "Location":
rst.Fields("Site") = DLookup("Folder", "Location", "Loc_ID='" & Forms!frmUtility!Site & "'")
Some general advice for troubleshooting 3146 ODBC Errors: DAO has an Errors collection which usually contains more specific information for ODBC errors. The following is a quick and dirty way to see what's in there. I have a more refined version of this in a standard error handling module that I include in all of my programs:
Dim i As Long
For i = 0 To Errors.Count - 1
Debug.Print Errors(i).Number, Errors(i).Description
Next i
I solved this by recreating the table in SQL instead of up-sizing it out of Access.
My 3146 error was caused by the lack of primary key on my sql server table. It was resolved by defining a primary key and then refreshing the connection through Linked Table Manager.

How to run a SQL Query from Excel in VBA on changing a Dropdown

I'm trying to create a dropdown that upon changing the selection from the list of options will run a query that will insert the query results into the page. Here's what I have thus far:
Sub DropDown1_Change()
Dim dbConnect As String
Dim leagueCode As String
Dim leagueList As Range
Dim leagueVal As String
Dim TeamData As String
Set leagueList = Worksheets("Menu Choices").Range("A5:A10")
Set leagueVal = Worksheets("Menu Choices").Cell("B1").Value
leagueCode = Application.WorksheetFunction.Index(leagueList, leagueVal)
TeamData = "SELECT DISTINCT(Teams.teamID), name FROM Teams WHERE lgID = '" & leagueCode & "' & ORDER BY name ASC"
With Worksheets("Menu Choices").QueryTables.Add(Connection:=dbConnect, Destination:=Worksheets("Menu Choices").Range("D5"))
.CommandText = TeamData
.Name = "Team List Query"
.Refresh BackgroundQuery:=False
End With
End Sub
Anywho have any suggestions to get it working? Thanks in advance!
I was able to resolve the issue using similar code to the following:
Sub createTeamList()
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim SQL As String
Dim inc As Integer
Dim topCell As Range
Dim leagueID As String
Dim leagueList As Range
Dim leagueChoice As Range
Set leagueList = Worksheets("Menu Choices").Range("A4:A9")
Set leagueChoice = Worksheets("Menu Choices").Range("B1")
leagueID = Application.WorksheetFunction.Index(leagueList, leagueChoice)
Set topCell = Worksheets("Menu Choices").Range("D4")
With topCell
Range(.Offset(1, 0), .Offset(0, 1).End(xlDown)).ClearContents
End With
With cn
.ConnectionString = "Data Source=" & ThisWorkbook.Path & "\lahman_57.mdb"
.Provider = "Microsoft Jet 4.0 OLE DB Provider"
.Open
End With
inc = 0
SQL = "SELECT teamID, name " _
& "FROM Teams " _
& "WHERE lgID = '" & leagueID & "' " _
& "GROUP BY teamID, name " _
& "ORDER BY name "
rs.Open SQL, cn
With rs
Do Until .EOF
topCell.Offset(inc, 0) = .Fields("teamID")
topCell.Offset(inc, 1) = .Fields("name")
inc = inc + 1
.MoveNext
Loop
End With
rs.Close
cn.Close
End Sub