I have a macro in Excel connecting to MS SQL, checking some counts and writing in my Excel sheet. It was working properly but it is not working now. I have an error code like this:
Run-time error -2147217871 Query Timeout Expired
My time out value is 960 but it showing me this problem.
How can I solve this problem?
I am sharing code with you:
Sub GetDataFromADO()
'Declare variables'
Set objMyConn = New ADODB.Connection
Set objMyCmd = New ADODB.Command
Set objMyRecordset = New ADODB.Recordset
'Open Connection'
objMyConn.ConnectionString = "Provider=SQLOLEDB;Data Source=<server>;User ID=<id>;Password=<pass>;"
'For Timeout'
Application.ODBCTimeout = 960
objMyConn.Open
'Set and Excecute SQL Command'
Set objMyCmd.ActiveConnection = objMyConn
'Set Recordset'
Set objMyRecordset.ActiveConnection = objMyConn
currentDate = Worksheets("RUN").Range("A1").Value
'-----------------------------------------------------------------------------------
cnt = 0
currentSheet = "LegalInsCrawling" 'Seq
cell = Worksheets(currentSheet).Range("A1").Value
Do
cnt = cnt + 1
cell = Worksheets(currentSheet).Range("A1").Offset(cnt).Value
Loop Until cell = "" Or cell = CDate(currentDate)
Worksheets(currentSheet).Range("A1").Offset(cnt).Value = currentDate
objMyCmd.CommandText = "<mssql query>"
objMyCmd.Execute
'Open Recordset'
objMyRecordset.Open objMyCmd
Worksheets(currentSheet).Range("B1").Offset(cnt).CopyFromRecordset (objMyRecordset)
objMyRecordset.Close
'------
cnt = 0
currentSheet = "LegalInsCrawling" 'HomePageCrawlingCount
cell = Worksheets(currentSheet).Range("A1").Value
Do
cnt = cnt + 1
cell = Worksheets(currentSheet).Range("A1").Offset(cnt).Value
Loop Until cell = "" Or cell = CDate(currentDate)
Worksheets(currentSheet).Range("A1").Offset(cnt).Value = currentDate
objMyCmd.CommandText = "<mssql query>"
objMyCmd.Execute
'Open Recordset'
objMyRecordset.Open objMyCmd
Worksheets(currentSheet).Range("D1").Offset(cnt).CopyFromRecordset (objMyRecordset)
objMyRecordset.Close
Related
I have multiple Excel 2016 and Excel 365 files, all with different queries and connections, pointing to a SQL database.
The database exists on multiple servers - for testing etc.
I would like to be able to connect the spreadsheets to each of the different servers e.g. TESTA1 PRODA01 without having to update each individual Excel workbook.
Is this possible using Excel and without having to change network settings like DNS.
Thanks in advance :)
A few years ago I put together some VBA code to list all connections in Excel and update all these same connections.
Public Sub UpdateConnectionStrings()
FromString = Worksheets("AccessLinks").Range("A1").Value
ToString = Worksheets("AccessLinks").Range("A2").Value
i = 1
Dim conn As Variant
Dim connectString As String
For Each conn In ActiveWorkbook.Connections
connectString = conn.ODBCConnection.Connection
Worksheets("AccessLinks").Range("D" & i).Value = connectString
connectString = Replace(connectString, FromString, ToString)
connectString = Replace(connectString, FromString, ToString)
Worksheets("AccessLinks").Range("E" & i).Value = connectString
conn.ODBCConnection.Connection = connectString
i = i + 1
FindPathBegin = InStr(1, conn.ODBCConnection.Connection, "DBQ=") + 4
FindPathEnd = InStr(1, conn.ODBCConnection.Connection, "Database1.accdb")
FindFullPath = Mid(conn.ODBCConnection.Connection, FindPathBegin, FindPathEnd - FindPathBegin)
Next conn
MsgBox ("Done!!")
End Sub
''''''''''''''''''''''''''''''
Sub DataExtractFromSQL_Server()
' Create a connection object.
Dim cnPubs As ADODB.Connection
Set cnPubs = New ADODB.Connection
' Provide the connection string.
Dim strConn As String
'Connect to the Pubs database on the local server.
strConn = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=DATABASE_NAME;Data Source=SERVER_NAME"
'Now open the connection.
' Create a recordset object.
Dim rsPubs As ADODB.Recordset
Set rsPubs = New ADODB.Recordset
Worksheets(1).Cells.Clear
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Worksheets("Data Validation")
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
cnt = ActiveWorkbook.Connections.Count
For j = cnt To 1 Step -1
cnPubs.Open strConn
Set conn = ActiveWorkbook.Connections.Item(j)
' conn is the name of the connection string; not the connection string
Sql = "SELECT * FROM [TABLE_PREFIX_NAME].[dbo].[" & conn & "]"
With rsPubs
.ActiveConnection = cnPubs
.Open Sql
For i = 1 To .Fields.Count
Worksheets(1).Cells(LastRow, 1) = conn
Worksheets(1).Cells(LastRow, 2) = .Fields(i - 1).Name
Select Case DataType
Case .Fields(i - 1).Type = "200"
Worksheets(1).Cells(LastRow, 3) = "VARCHAR"
Case .Fields(i - 1).Type = "131"
Worksheets(1).Cells(LastRow, 3) = "DECIMAL"
Case .Fields(i - 1).Type = "135"
Worksheets(1).Cells(LastRow, 3) = "DATE"
Case Else
Worksheets(1).Cells(LastRow, 3) = "INT"
End Select
LastRow = LastRow + 1
Next i
End With
cnPubs.Close
Next j
Set rsPubs = Nothing
Set cnPubs = Nothing
End Sub
Executing a macro from VBScript gives error :
Method CopyFromRecordset of object 'Range' failed
But It works fine, when I execute same from Excel workbook.
I tried executing from Excel workbook and it worked fine.
Here Is My VBA Code:
Set conn = New ADODB.Connection
conn.connectionString = "PROVIDER=SQLOLEDB;DATA SOURCE=localhost\SQLEXPRESS;INITIAL CATALOG=DEVDB; INTEGRATED SECURITY=sspi;"
Set rs = New ADODB.Recordset
str = "exec SP_Getcustomers #RequestID=" & requestID
rs.Open str, conn, adOpenStatic, adLockReadOnly
If Not IsEmptyRecordset(rs) Then
rs.MoveFirst
'Populate the first row of the sheet with recordset’s field names
i = 0
For Each fld In rs.Fields
ActiveWorkbook.Worksheets("Customer Table").Cells(1, i + 1).Value = rs.Fields.Item(i).Name
i = i + 1
Next fld
'Populate the sheet with the data from the recordset
ActiveWorkbook.Worksheets("Customer Table").Range("A2").CopyFromRecordset rs
End If
VB Script Code:
Dim path, macroname
path = ""
path = Wscript.Arguments.Item(2)
macroname = ""
macroname = Wscript.Arguments.Item(3)
Set objExcel = CreateObject("Excel.Application")
objExcel.Application.Run "'" & path & "'!" & macroname, WScript.Arguments.Item(0)
objExcel.Visible = False
objExcel.DisplayAlerts = False
objExcel.Application.Quit
Set objExcel = Nothing
I am having trouble when getting data from SQL Server. Here is the code.
Private Sub Form_Load()
Dim blsCritical As Boolean
'----------------------------------------------
ListBox.AddItem "Initializing..."
'----------------------------------------------
Me.Repaint
'----------------------------------------------
ListBox.AddItem "Welcome"
'----------------------------------------------
Me.Repaint
'----------------------------------------------
ListBox.AddItem "Examining your access rights..."
Call ConnectSQLServer
'----------------------------------------------
Me.Repaint
ListBox.AddItem strSQL
'----------------------------------------------
ListBox.AddItem "Opening database connection..."
'----------------------------------------------
Me.Repaint
End Sub
Sub ConnectSQLServer()
Dim cmd As ADODB.Command
Dim conn As ADODB.Connection
Dim strConn As String
Dim par As ADODB.Parameter
Set objMyConn = New ADODB.Connection
Set objMyRecordset = New ADODB.Recordset
Dim strSQL As String
objMyConn.ConnectionString = "DRIVER=SQL Server;SERVER=CHU-AS-0004;DATABASE=RTC_LaplaceD_DEV;Trusted_Connection=Yes;"
objMyConn.Open
strSQL = "SELECT [currentVersion], [standardVersion] FROM [dbo].[Version]"
If currentVersion = "" Then
MsgBox ("No currentVersion value")
ElseIf Not IsNull(currentVersion) Then
If currentVersion < standardVersion Then
MsgBox ("Upgrade is needed")
ElseIf currentVersion = standardVersion Then
MsgBox ("PASS")
Else
End If
Else
End If
Set objMyRecordset.ActiveConnection = objMyConn
objMyRecordset.Open strSQL
End Sub
I have data in SQL Server:
but I cannot get data from SQL Server. When I execute it, 'No CurrentVersion value' message pops up. I don't see any mistakes in my code. Could you help me to solve this problem?(It would be great if you can share your fixed code...)
Just whipped this up for you to show you where you went wrong... untested...
strSQL = "SELECT [currentVersion], [standardVersion] FROM [dbo].[Version]"
Set objMyRecordset.ActiveConnection = objMyConn
objMyRecordset.Open strSQL
while objMyRecordset.EOF = false
currentVersion = objMyRecordset!currentVersion
objMyRecordset.MoveNext
wend
If currentVersion = "" Then
MsgBox ("No currentVersion value")
ElseIf Not IsNull(currentVersion) Then
If currentVersion < standardVersion Then
MsgBox ("Upgrade is needed")
ElseIf currentVersion = standardVersion Then
MsgBox ("PASS")
Else
End If
Else
End If
Something like this should do the job.
Sub GetDataFromADO()
'Declare variables'
Set objMyconn = New ADODB.Connection
Set objMyCmd = New ADODB.Command
Set objMyRecordset = New ADODB.Recordset
Dim rc As Long
'Open Connection'
objMyconn.ConnectionString = "Provider=SQLOLEDB;Data Source=SAXAM\SQLEXPRESS;Initial Catalog=AdventureWorks2012; Integrated Security=SSPI;"
objMyconn.Open
'Set and Excecute SQL Command'
Set objMyCmd.ActiveConnection = objMyconn
objMyCmd.CommandText = "select * from [Person].[BusinessEntity] "
objMyCmd.CommandType = adCmdText
objMyCmd.Execute
'Open Recordset'
Set objMyRecordset.ActiveConnection = objMyconn
objMyRecordset.Open objMyCmd
'Copy Data to Excel'
'ActiveSheet.Range("A1").CopyFromRecordset (objMyRecordset)
Application.ActiveCell.CopyFromRecordset (objMyRecordset)
rc = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
ActiveSheet.Cells(rc + 1, 1).Select
'Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Value
objMyconn.Close
End Sub
Here's one more idea. Let's say you had a bunch of Select statements in a bunch of cells from A1, down to whatever, you can add sheets dynamically, and import some sample data on to each sheet, to get a sense of the data structures of multiple tables.
Assuming the following in A1:A3.
SELECT TOP 1000 * FROM [YOUR_DB].[dbo].[YOUR_TABLE1]
SELECT TOP 1000 * FROM [YOUR_DB].[dbo].[YOUR_TABLE2]
SELECT TOP 1000 * FROM [YOUR_DB].[dbo].[YOUR_TABLE3]
Run the script below.
Sub Download_From_Multiple_Tables()
'Initializes variables
Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
Dim ConnectionString As String
Dim StrQuery As String
Dim rCell As Range
Dim rRng As Range
Dim sht As Worksheet
Dim LastRow As Long
Set cnn = New ADODB.Connection
'For a trusted Connection, where your user ID has permissions on the SQL Server:
cnn.Open ConnectionString:="Provider=SQLOLEDB.1;" & _
"Data Source=" & "YOUR_SERVER_NAME" & ";Initial Catalog=" & "YOUR_DB_NAME" & _
";TRUSTED_CONNECTION=YES"
'Opens connection to the database
'Timeout error in seconds for executing the entire query; this will run for 15 minutes before VBA timesout, but your database might timeout before this value
cnn.CommandTimeout = 900
Set sht = ThisWorkbook.Worksheets("Sheet1")
'Ctrl + Shift + End
LRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
Set rRng = Sheet1.Range("A1:A" & LRow)
i = 2
For Each rCell In rRng.Cells
LPosition = InStrRev(rCell.Value, "[dbo]") + 5
' Name the newly added worksheet, based on the cell value
Name = Mid(rCell.Value, LPosition + 1, 99)
' Remove [] characters, as these are not permitted in tab names
Name = Replace(Name, "[", "")
Name = Replace(Name, "]", "")
SheetName = Left(Name, 31)
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = SheetName
Worksheets(SheetName).Activate
StrQuery = rCell.Value
'Performs the actual query
rst.Open StrQuery, cnn
'Dumps all the results from the StrQuery into cell A2 of the first sheet in the active workbook
' Dump field names to the worksheet
For intFieldIndex = 0 To rst.Fields.Count - 1
ActiveSheet.Cells(1, intFieldIndex + 1).Value = rst.Fields(intFieldIndex).Name
Next intFieldIndex
' Dump the records to the worksheet
ActiveSheet.Cells(2, 1).CopyFromRecordset rst
' Sheets(i).Range("A1").CopyFromRecordset rst
i = i + 1
rst.Close
Next rCell
End Sub
I have to write a program for my company's accountant, and I have a problem in returning articles' families in an array, all of the families I want to have have an Accounting code who begins with "707". Here's my code in VBScript :
Set objConnection = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\BASES\Base.mdb;Persist Security Info=False"
rs.CursorLocation = adUseClient
FamilleQuery = "Select Code from FamilleArticle Where CptVenteFrance Like '707%'"
rs.Open FamilleQuery, objConnection, adOpenStatic, adLockOptimistic
'rs.MoveFirst
'Do
'ListeFamille(rs.AbsolutePosition) = rs("Code")
'rs.MoveNext
'Loop until rs.EOF
'ListeFamilleString = rs.GetString(AdClipString, -1,"/","/"," ")
'ListeFamille = split(ListeFamilleString,"/")
'Set ListeFamille = rs.GetRows
'for i=0 to ubound(rs)
'ListeFamille(i) = rs.Fields("Code").Value(i)
'next
rs.Close
objConnection.Close
As comments you have all of my attempts to return the resultat of the recordset in an array and no one didn't work.
Can someone say where I'm wrong please ?
Give this a try
Option Explicit
'ADO Constants
Const adCmdText = 1
Const adParamInput = 1
Const adVarWChar = 202
'Would usually be passed in from somewhere
Dim value: value = "707%"
Dim cmd, rs, data
Dim conn: conn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\BASES\Base.mdb;Persist Security Info=False"
Dim sql: sql = "Select Code from FamilleArticle Where CptVenteFrance Like ?"
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandType = adCmdText
.CommandText = sql
Call .Parameters.Append(.CreateParameter("#value", adVarWChar, adParamInput, 50))
Set rs = .Execute(, Array(value))
If Not rs.EOF Then data = rs.GetRows()
Call rs.Close()
Set rs = Nothing
End With
Set cmd = Nothing
Dim row, rows
If IsArray(data) Then
'Test data (2d Array, 0 = column, 1 = row)
Call WScript.Echo(data(0, 0))
'Retrieving all rows
rows = UBound(data, 2)
For row = 0 To rows
'First column from each row.
Call WScript.Echo(data(0, row))
Next
Else
'No records returned
End If
Useful Links
Using Stored Procedure in Classical ASP .. execute and get results (talk about returning data as an Array you can traverse)
You don't need the Set in vbScript to set the array to the recordSet's rows. You only use a Set where setting an object reference, which isn't the case here.
ListeFamille = rs.GetRows will set ListeFamille to a 2 dimensional array with the results of the recordset in it.
Here's an excerpt from one of my own function libraries:
oConnection.open sConnectionString
oRecordSet.open sSql, oConnection
If oRecordSet.RecordCount = 0 Then
DataArray = ""
Else
oRecordSet.MoveFirst
DataArray = oRecordSet.GetRows
End If
Need some SQL advice please
I am using a program called WinCC, in which I am using Vb script language with SQL.
I have a SQL table in which there are 3 columns, TagName, Value and Date
I need to display the Value for each TagName for each day in the chosen month.
The below SQL query give me same value for each day in the month. When I have different values for each day in the month.
Tags(0) = "Tag1"
Tags(1) = "Tag2"
TempTags(0) = "Temp1"
TempTags(1) = "Temp2"
ConnectionString = "Provider=SQL Native Client;Server=WIN81 \WINCC;Database=Teams;Trusted_Connection=yes"
Set Connection = CreateObject("ADODB.Connection")
Set rs = CreateObject ("ADODB.Recordset")
Connection.ConnectionString = ConnectionString
Connection.Open
For i = 0 To 2
SQLStr = "select Value FROM atrperformancestats WHERE TagName = '"+Tags(i)+"'And Month(Date)='"+date+"'"
rs = Connection.Execute(SQLStr)
HMIRuntime.Tags(TempTags(i)).Write rs("Value")
Next
I have tried changing my SQL query to get the value for each day in the user selected month but I am failing miserably...please help
Thank you so much
If the query returns multiple rows, you need a While loop to process the result set. Below is a parameterized example that assumes date is an integer representing the month.
Const adVarChar = 200
Const adInteger = 3
Const adParamInput = 1
Const adCmdText = 1
Tags(0) = "Tag1"
Tags(1) = "Tag2"
TempTags(0) = "Temp1"
TempTags(1) = "Temp2"
ConnectionString = "Provider=SQL Native Client;Server=WIN81 \WINCC;Database=Teams;Trusted_Connection=yes"
Set Connection = CreateObject("ADODB.Connection")
Set Command = CreateObject("ADODB.Command")
Connection.ConnectionString = ConnectionString
Connection.Open
Command.ActiveConnection = Connection
Command.CommandType = adCmdText
Command.CommandText = "SELECT Value FROM atrperformancestats WHERE TagName = ? And Month(Date) = ?;"
Set parmTagName = command.CreateParameter("TagName", adVarchar, adParamInput, 100)
Command.Parameters.Append(parmTagName)
Set parmDate = command.CreateParameter("Date", adInteger, adParamInput)
command.Parameters.Append(parmDate)
For i = 0 To 1
parmTagName.Value = Tags(i)
parmDate.Value = date
Set rs = Command.Execute()
While rs.EOF = False
HMIRuntime.Tags(TempTags(i)).Write rs("Value").Value
rs.MoveNext
WEnd
rs.Close
Next
In WinCC , a SCADA program which is not very code savy I eventually found a way...
j = 0
SQLStr = "Select Value FROM table1 WHERE Name = '" + Names(i) + "' And Month(Date) = '" + MonthSelect + "' order by date asc"
rs.Open SQLStr, Connection
Do Until j = 31
HMIRuntime.Tags(arrayInt(i)).Write rs("Value")
rs.MoveNext
i = i +1
j = j +1
Loop
And it works !!!
Thanks for all the help , your recommendation of a loop got me thinking