UPDATE with ADO in Access VBA Array - vba

I have 31 text boxes that get populated with ADO from a Calendar Table as per below function:
Private Function FillDates()
Dim cnn As ADODB.Connection
Dim ssql As String
Dim rst As ADODB.Recordset
Set cnn = CurrentProject.Connection
Dim i As Integer
Dim Records As Integer
ssql = "SELECT RoomAvailabilityId, Availability FROM RoomAvailability WHERE Month(AvailabilityDate)=Month(Now()) AND RoomTypesId=1"
Set rst = New ADODB.Recordset
rst.CursorLocation = adUseClient
rst.Open ssql, cnn
Records = rst.RecordCount
For i = 1 To Records
Me("idtext" & i).Value = rst.Fields!RoomAvailabilityId
Me("Text" & i).Value = rst.Fields!Availability
rst.MoveNext
Next i
rst.Close
Set rst = Nothing
End Function
This is a simplified version of the actual code. The actual code hides the text boxes when a month is made up of 30 days or 29/28 days.
So I have 2 values now stored in my grid made up of the above text boxes.
I now want to update my table field called Availability (Number - Long Integer Datatype) with a button click and I am not able to touch base with this.
Could you please suggest how? This is my starting non working code:
Private Sub cmdUpdatetxt_Click()
Dim cn As ADODB.Connection '* Connection String
Dim oCm As ADODB.Command '* Command Object
Dim iRecAffected As Integer
Set cn = CurrentProject.Connection
Dim i As Integer
For i = 1 To 31
AvailableRooms = Me("txt" & i).Value
AvailableRoomsId = Me("idtext" & i).Value
Next i
Set oCm = New ADODB.Command
oCm.ActiveConnection = cn
oCm.CommandText = "Update RoomAvailability Set Availability ='" & AvailableRooms & "' WHERE RoomAvailabilityId = '" & AvailableRoomsId & "' AND Month(RoomAvailability.AvailabilityDate) = '" & cboMonthYear.Value & "' "
oCm.Execute iRecAffected
If iRecAffected = 0 Then
MsgBox "Nessun Utente Inserito"
End If
If cn.State <> adStateClosed Then
cn.Close
If Not oCm Is Nothing Then Set oCm = Nothing
If Not cn Is Nothing Then Set cn = Nothing
End If
End Sub
Thank you very much in advance

As per Nathan_Sav suggestion, this is the working code:
Private Sub cmdUpdatetxt_Click()
On Error GoTo ErrorTrap
Dim i As Integer
For i = 1 To 31
Dim cn As ADODB.Connection '* Connection String
Dim oCm As ADODB.Command '* Command Object
Dim iRecAffected As Integer
Set cn = CurrentProject.Connection
AvailableRooms = Me("txt" & i).Value
AvailableRoomsId = Me("idtext" & i).Value
Set oCm = New ADODB.Command
oCm.ActiveConnection = cn
oCm.CommandText = "Update RoomAvailability Set Availability =" & AvailableRooms & " WHERE RoomAvailabilityId = " & AvailableRoomsId & " AND Month(RoomAvailability.AvailabilityDate) = '" & cboMonthYear.Value & "' "
oCm.Execute iRecAffected
If iRecAffected = 0 Then
MsgBox "Nessun Utente Inserito"
End If
If cn.State <> adStateClosed Then
cn.Close
If Not oCm Is Nothing Then Set oCm = Nothing
If Not cn Is Nothing Then Set cn = Nothing
End If
Next i
Exit Sub
ErrorTrap:
MsgBox (Err.Description)
End Sub
Have a great day

Related

SQL Query Returns empty Recordset

I'm trying to learn how to connect to a SQL Server DB from Excel DB. I've tried to reduce the code to dead simple to begin with. I've looked at several answers to related questions, however, I cannot figure out why this doesn't work. It executes all the way through. (The code shown here is somewhat anonymized.)
The query finds the database, because if the table name is invalid it throws an error. However it always returns record count = -1. I can eyeball the table in MSSMS and it has data. Same result for other tables in the DB.
Public Sub ADOtest1()
Dim Conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim strConnString As String
strConnString = "Provider='SQLOLEDB'" & ";" & _
"Data Source='XXX-XPS\SQLEXPRESS'" & ";" & _
"Initial Catalog='XXXXX'" & ";" & _
"Integrated Security='SSPI'"
Set Conn = New ADODB.Connection
Conn.Open strConnString
' the query finds the DB, because if the table name is incorrect, it throws an error
strSQLString = "SELECT * from t300_XXXX"
Set rs = Conn.Execute(strSQLString)
wrkRecordCount = rs.RecordCount
'--- just some test breakpoints
If wrkRecordCount = -1 Then
a = "" '--- code keeps arriving here
Else
a = ""
End If
rs.Close
Conn.Close
End Sub
Answer from Srinika below worked:
Set rs = Conn.Execute(strSQLString)
rs.Close
rs.CursorLocation = adUseClient
rs.Open
I'll post two examples, so please refer.
First Example
Sub ExampleSQL()
Dim cnn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim strSQL As String
Set cnn = New ADODB.Connection
'Set the provider property to the OLE DB Provider for ODBC.
'cnn.Provider = "MSDASQL"
'cnn.Provider = "Microsoft.ACE.OLEDB.12.0"
'cnn.Provider = "MSOLAP"
'cnn.Provider = "SQLOLEDB.1"
' Open a connection using an ODBC DSN.
cnn.ConnectionString = "driver={SQL Server};" & _
"server=severname;uid=sa;pwd=password;database=test"
Set rs = New ADODB.Recordset
strSQL = "SELECT * FROM [your Table] "
rs.Open strSQL, cnn.ConnectionString, adOpenForwardOnly, adLockReadOnly, adCmdText
cnn.Open
If cnn.State = adStateOpen Then
Else
MsgBox "Sever is not connected!! "
Exit Sub
End If
If Not rs.EOF Then
With Ws
.Range("a4").CurrentRegion.ClearContents
For i = 0 To rs.Fields.Count - 1
.Cells(4, i + 1).Value = rs.Fields(i).Name
Next
.Range("a5").CopyFromRecordset rs
.Columns.AutoFit
End With
Else
MsgBox "No Data!!", vbCritical
End If
rs.Close
Set rs = Nothing
cnn.Close
Set cnn = Nothing
End Sub
Second Example
Sub getDataFromServer()
Dim con As New ADODB.Connection
Dim cmd As New ADODB.Command
Dim rs As New ADODB.Recordset
Dim i As Integer
con.ConnectionString = "Provider=SQLOLEDB.1;" _
& "Server=(local);" _
& "Database=TEST;" _
& "Integrated Security=SSPI;" _
& "DataTypeCompatibility=80;"
con.Open
Set cmd.ActiveConnection = con
cmd.CommandText = "SELECT * FROM [your Table]"
Set rs = cmd.Execute
Range("A1").CopyFromRecordset rs
con.Close
Set con = Nothing
End Sub

Send a recordset to another macro

I have a macro for updating an SQL table in an Excel Add-in.
In order to use the same macro from multiple files I want to be able to create the recordset outside of the connection and then send it as a parameter to the update macro. Is this possible?
I have tried looking at the solutions found for in memory recordsets but these seemes to focus more on creating the columns rather than column-value pairs.
Sub test()
Dim ws As Worksheet
Dim serverName As String
Dim dataBase As String
Dim forecastDate As Date
Dim projectNum As Long
Dim SqlStr As String
Dim rst As New ADODB.Recordset
Set ws = ActiveSheet
serverName = "Servername"
dataBase = "database"
forecastDate = ws.Cells(2, "B").Value
projectNum = ws.Cells(3, "B").Value
SqlStr = "SELECT * From forecast WHERE forecastDate='" & forecastDate & "' AND projectNum = '" & projectNum & "';"
Set rst = New ADODB.Recordset
rst!forecastDate = forecastDate
rst!projectNum = projectNum
rst!Data = Cells(4, "B").Value
Application.Run "updateMacro", serverName, dataBase, SqlStr, rst
rst.Close
End Sub
'Part of the updateMacro:
Set conn = New ADODB.Connection
cs = "DRIVER=SQL Server;DATABASE=" & dataBase & ";SERVER=" & serverName & ";Trusted_connection=yes;"
conn.Open cs
'Set rst = New ADODB.Recordset
rst.Open SqlStr, conn, adOpenDynamic, adLockOptimistic 'adLockPessimistic
If rst.EOF Then
rst.AddNew
End If
'get the recordset from caller macro and update
rst.Update
rst.Close
Set rst = Nothing
conn.Close
Set conn = Nothing
I would like to create the recordset outside of the updateMacro and use it in that macro or create some sort of column-value pairs that could be copied to the recordset in the updateMacro.
You can declare the recordset as global or also pass the recordset between functions/subs. Please see code below for an example:
Option Explicit
'Global Recordset to be sued by other functions
Private rsMain As ADODB.Recordset
Public Function ImportData(ByVal fyYear As String) As Long
Dim sConnString As String, sqlYears As String
Dim conn As ADODB.Connection
Dim tCount As Long
sConnString = "Provider=SQLOLEDB;Data Source=server2;" & "Initial Catalog=FPSA;" & "Integrated Security=SSPI;"
sqlYears = "select ltrim(rtrim(FinYearDesc)) as FinYearDesc, Month, AccountType, ltrim(rtrim(AccountName))as AccountName, " & _
"ActualValue, BudgetValue from [GL_AccountMovements] where FinYearDesc >= '" & fyYear & "'"
Set conn = New ADODB.Connection
Set rsMain = New ADODB.Recordset
rsMain.CursorLocation = adUseClient
rsMain.Open sqlYears, conn, _
ADODB.adOpenForwardOnly, _
ADODB.adLockBatchOptimistic
Set rsMain.ActiveConnection = Nothing
conn.Close
If Not rsMain.EOF Then
tCount = rsMain.RecordCount
End If
ImportData = tCount
End Function
'An example of using Global Recordset
Function GetAccountsByYearMonth(ByVal strYTDLastYear as String) As Double
Dim lastYearYTDAct As Double
rsMain.Filter = strYTDLastYear
Do While Not rsMain.EOF
lastYearYTDAct = lastYearYTDAct + rsMain.Fields("ActualValue")
rsMain.MoveNext
Loop
GetAccountsByYearMonth = lastYearYTDAct
End Function
Thanks

Using VBA to query a VIEW from SQL Server

I am trying to create a VBA script that will pull the results from a View (SELECT * FROM view_name) from the RecordSet.Source property, but when attempted, my CloseConnection error handler keeps getting caught. I can get results from a table using a simple query like SELECT * FROM tbl_name with no issues.
Below is the code I am using. Note: my Const variable has the Provider and Database information removed.
I guess it really comes down to is it even possible to get results from a View like I would from a table?
Option Explicit
Const ConStrMSSQL As String = _
"Provider=provider_name;Database=database_name;Trusted_Connection=yes;"
Sub test()
Dim formConnect As ADODB.connection
Dim formData As ADODB.recordSet
Dim formField As ADODB.Field
Set formConnect = New ADODB.connection
Set formData = New ADODB.recordSet
formConnect.ConnectionString = ConStrMSSQL
formConnect.Open
On Error GoTo CloseConnection
With formData
.ActiveConnection = formConnect
.Source = "SELECT * FROM v_data_extract_658"
.LockType = adLockReadOnly
.CursorType = adOpenForwardOnly
.Open
End With
On Error GoTo CloseRecordset
Sheets("test").Range("A1").Select
For Each formField In formData.Fields
ActiveCell.Value = formField.Name
ActiveCell.Offset(0, 1).Select
Next formField
Sheets("test").Range("A2").CopyFromRecordset formData
On Error GoTo 0
CloseRecordset:
formData.Close
CloseConnection:
formConnect.Close
End Sub
This is the error message:
run-time error 2147467259 (80004005): unknown token received from SQL Server
I think the big issue here is that you haven't defined a Command Object.
I somewhat put this together "freehand" and for certain, didn't test it but it should get you to where you need to go.
Sub test()
On Error GoTo ErrorHandle:
Dim formConnect As ADODB.Connection
Set formConnect = New ADODB.Connection
formConnect.ConnectionString = ConStrMSSQL
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
formConnect.Open
With cmd
.ActiveConnection = formConnect
.CommandType = adCmdText
.CommandText = "SELECT * FROM v_data_extract_658"
.CommandTimeout = 30
End With
Dim formData As ADODB.Recordset
Set formData = New ADODB.Recordset
formData.Open cmd, , adOpenStatic, adLockReadOnly
Sheets("test").Range("A1").Select
Dim formField As ADODB.Field
For Each formField In formData.Fields
ActiveCell.value = formField.Name
ActiveCell.Offset(0, 1).Select
Next formField
Range("A2").CopyFromRecordset formData
On Error GoTo 0
Cleanup:
If Not formData Is Nothing Then
If formData.State <> adStateClosed Then formData.Close
Set formData = Nothing
End If
If Not formConnect Is Nothing Then
If formConnect.State <> adStateClosed Then formConnect.Close
Set formConnect = Nothing
End If
Set cmd = Nothing
Exit Sub
ErrorHandle:
MsgBox Err.Description
'Do whatever else is needed to respond to errors.
Resume Cleanup
End Sub
Using Excel & VBA to fetch dta from SLQ Server is quite easy (not always, but these days).
Sub ADOExcelSQLServer()
' Carl SQL Server Connection
'
' FOR THIS CODE TO WORK
' In VBE you need to go Tools References and check Microsoft Active X Data Objects 2.x library
'
Dim Cn As ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim User_ID As String
Dim Password As String
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Server_Name = "EXCEL-PC\SQLEXPRESS" ' Enter your server name here
Database_Name = "NORTHWND" ' Enter your database name here
User_ID = "" ' enter your user ID here
Password = "" ' Enter your password here
SQLStr = "SELECT * FROM [Customers]" ' Enter your SQL here
Set Cn = New ADODB.Connection
Cn.Open "Driver={SQL Server};Server=" & Server_Name & ";Database=" & Database_Name & _
";Uid=" & User_ID & ";Pwd=" & Password & ";"
rs.Open SQLStr, Cn, adOpenStatic
' Dump to spreadsheet
For iCols = 0 To rs.Fields.Count - 1
Worksheets("Sheet1").Cells(1, iCols + 1).Value = rs.Fields(iCols).Name
Next
With Worksheets("sheet1").Range("a2:z500") ' Enter your sheet name and range here
'.ClearContents
.CopyFromRecordset rs
End With
' Tidy up
rs.Close
Set rs = Nothing
Cn.Close
Set Cn = Nothing
End Sub
As an aside, you can try this as well (please change to suit your specific setup/configuration)...
Sub Working2()
Dim con As Connection
Dim rst As Recordset
Dim strConn As String
Set con = New Connection
strConn = "EXCEL-PC\SQLEXPRESS;Database=Northwind;Trusted_Connection=True"
con.Open strConn
'Put a country name in Cell E1
Set rst = con.Execute("Exec dbo.MyOrders '" & ActiveSheet.Range("E1").Text & "'" & ActiveSheet.Range("E2").Text & "'")
'The total count of records is returned to Cell A5
ActiveSheet.Range("A5").CopyFromRecordset rst
rst.Close
con.Close
End Sub
Please see the link below for more details.
https://www.excel-sql-server.com/excel-sql-server-import-export-using-vba.htm#Excel%20Data%20Export%20to%20SQL%20Server%20Test%20Code

Access VBA - data provider or other service returned an e_fail status

could you please help me understand what-s wrong with the below code:
Private Function FillCalendar()
Dim cnn As ADODB.Connection
Dim ssql As String
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
Set cnn = CurrentProject.Connection
Dim i As Integer
Dim Records As Integer
ssql = "SELECT Format(Availability.AvailabilityDate,'mmm dd ddd') AS MyDate FROM Availability WHERE HotelId=3 AND Month( Availability.AvailabilityDate)=Month(Now()) GROUP BY Availability.AvailabilityDate"
rst.CursorLocation = adUseClient
rst.Open ssql, cnn
Records = rst.RecordCount
For i = 1 To Records
Me("Text" & i).Visible = True
Me("Text" & i).Value = rst.Fields!MyDate
If InStr(Me("Text" & i).Value, "sat") Or InStr(Me("Text" & i).Value, "sun") Then
Me("Text" & i).BackColor = RGB(179, 45, 0)
Else
Me("Text" & i).BackColor = RGB(0, 114, 188)
End If
rst.MoveNext
Next i
rst.Close
Set rst = Nothing
End Function
The code stucks at Records = rst.RecordCount and cannot figure out why.
My table called Availability is really simple:
AvailabilityId Autonumber Long Integer (Primary Key)
RoomTypeId Number (Foreign Key)
HotelId Number (Foreign Key)
AvailabilityDate Date/Time (Format: ShortDate)
AvailableRooms Number (Long Integer - Default Value: 0)
Thanks a lot in advance
at the end I managed to solve the issue by changing a bit my sql statement and my code:
Private Function FillDates()
Dim cnn As ADODB.Connection
Dim ssql As String
Dim rst As ADODB.Recordset
Set cnn = CurrentProject.Connection
Dim i As Integer
Dim Records As Integer
ssql = "SELECT AvailabilityDate FROM Availability WHERE Month(AvailabilityDate)=Month(Now()) GROUP BY AvailabilityDate"
Set rst = New ADODB.Recordset
rst.CursorLocation = adUseClient
rst.Open ssql, cnn
Records = rst.RecordCount
For i = 1 To Records
Me("Text" & i).Value = rst.Fields!AvailabilityDate
Me("Text" & i).Value = Format(Me("Text" & i), "mmm dd ddd")
If InStr(Me("Text" & i).Value, "sab") Or InStr(Me("Text" & i).Value, "dom") Then
Me("Text" & i).BackColor = RGB(179, 45, 0)
Else
Me("Text" & i).BackColor = RGB(0, 114, 188)
End If
rst.MoveNext
Next i
rst.Close
Set rst = Nothing
End Function
Thanks for your help
Could be that your Query ran through the table and found no matching results.
Try this to check if any records were found:
if rst.EOF = false Then
Records = rst.RecordCount
else
Debug.Print "No records returned :/"
End if

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