Change Connection String via code [closed] - vba

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have 9 sheets that connect to different tables in teradata, each time i have to enter my user name and password to refresh and get new set of data. could someone please advice how do i write a VBA code that could change the connection string for each connection and refresh the data table.I am a begginner in VBA and have no clue in codding in VBA
Thanks
Syam

Here is what I do: I put the following in cells A2:B5
Data Source:
Database:
I put the SQL in cell D2. I use Row 1 for telling me how long the query takes. Then, I add a button anywhere on the page. Then I call the code below. It looks complicated, but the core of the functionality is all in Get_Data_Teradata.
The Get_SQL Function simply reads down column D until it finds a blank row and then returns a big block of text for the SQL. You could replace this with a hardcoded SQL statement.
Pop_Col_Heads puts the column headings from the result in Row 1. Note, that I have discovered a Bug in Excel 2010 on Win 7 where I can only populate columns once or twice per Excel session. If I quit and load Excel again, it works another once or twice.
Copy_Data_From_RDBMS places the ADODB RecordSet into a range in the active sheet. I had to do some tweaks to handle inserts and updates because they don't return any rows.
Sub Get_Data_Teradata()
'Supports Multi Query
Dim cn As ADODB.Connection
Dim sConnect As String
Set cn = New ADODB.Connection
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim cmdSQLData As ADODB.Command
Set cmdSQLData = New ADODB.Command
Dim sQueries() As String
sConnect = "Persist Security Info=True; Session Mode=ANSI; " & _
"Data Source=" & ActiveSheet.Range("B2").Value & ";" & _
"Database=" & ActiveSheet.Range("B3").Value & ";" & _
"User ID=" & ActiveSheet.Range("B4").Value & ";" & _
"Password=" & ActiveSheet.Range("B5").Value & ";"
sQueries = Get_SQL(ActiveSheet.Range("D2:D9999"))
nRow = 1 'initialize to start at the top of the page
For i = 0 To UBound(sQueries) - 1
cn.Open sConnect
Set cmdSQLData.ActiveConnection = cn
cmdSQLData.CommandText = sQueries(i) 'TELL VBA TO LOAD THE QUERY INTO TERADATA
cmdSQLData.CommandType = adCmdText
cmdSQLData.CommandTimeout = 0
Set rs = cmdSQLData.Execute()
Call Pop_Col_Heads(rs, nRow)
nRow = Copy_Data_From_RDBMS(rs, nRow)
cn.Close
Next i
End Sub
Dim a As Long
Dim i As Long
Dim nIndex As Long
Dim sSQL() As String
Function Get_SQL(oRange As Object) As String()
'First figure out how many rows the SQL statement is
a = 0
For Each cCell In oRange
a = a + 1
If cCell.Value = "" Then
a = a - 1
Exit For
End If
Next cCell
'Num rows = a now
'Step through and parse into array
i = 0
nIndex = 0
ReDim Preserve sSQL(1)
For Each cCell In oRange
i = i + 1
If i > a Then
Exit For
ElseIf cCell.Value = "<Multi>" Then
nIndex = nIndex + 1
ReDim Preserve sSQL(nIndex + 1)
Else
sSQL(nIndex) = sSQL(nIndex) & To_Text(cCell.Value) & " "
End If
Next cCell
Get_SQL = sSQL
End Function
Sub Pop_Col_Heads(rs As Object, nRow As Long)
Dim rHeads As Range
Dim fFields As Field
Dim nCol As Integer
nCol = 0
If nRow = 1 Then
ActiveSheet.Range("E1:ZZ1").ClearContents
End If
Set rHeads = ActiveSheet.Range("E1").Offset(nRow - 1, 0)
Do While nCol < rs.Fields.Count
sTemp = rs.Fields(nCol).Name
rHeads.Cells(nRow, nCol + 1).Value = rs.Fields(nCol).Name
ActiveSheet.Calculate
rHeads.Cells(nRow, nCol + 1).Value = sTemp
nCol = nCol + 1
rHeads.WrapText = True
rHeads.VerticalAlignment = xlVAlignTop
Loop
End Sub
Function Copy_Data_From_RDBMS(rs As Object, nRow As Long) As Long
'Supports Multi Query
If nRow = 1 Then
x = Get_Last_Row_Find(ActiveSheet.Range("E1:ZZ64000"))
ActiveSheet.Range("E2:ZZ" & x).ClearContents
End If
On Error Resume Next
rs.MoveFirst
On Error GoTo 0
If Not rs.EOF Then
ActiveSheet.Range("E2").Offset(nRow - 1, 0).CopyFromRecordset rs
x = Get_Last_Row_Find(ActiveSheet.Range("E1:ZZ64000"))
Copy_Data_From_RDBMS = x + 1
ActiveSheet.Range("E2:ZZ" & x).Offset(nRow - 1, 0).WrapText = False
Else 'no results (e.g. insert)
ActiveSheet.Range("E2").Offset(nRow - 1, 0).Value = "<no data returned>"
End If
rs.Close
Set rs = Nothing
End Function

Related

SQL Query with n number of WHERE-arguments in VBA

I’m using ADO to run SQL query in VBA. I’ve done this quite a lot, and everything works properly.
However, I’m advancing to a more sophisticated query, where I need to input an unknown number of conditional strings. In short:
SELECT * FROM database.dbo.table
WHERE Col1 IN (‘val1’, ‘val2’, ..., ‘valn’)
I have a set of data on my worksheet, which changes every time. The data are of the same string format each time, but number of cells with values varies. I want to execute above query, using my n number of variables in the WHERE-statement.
Example of query with 5 variables from worksheet:
SELECT * FROM database.dbo.table
WHERE Col1 IN (‘000165234’, ‘000165238’, ‘000165231’, ‘000165232’, ‘000165239’)
Any pointers to the right direction are greatly appreciated.
My biggest issue is how to handle the unknown number of variables.
Constraints: will always be at least 1 cell with value, and never more than 60.
Notes: Data is also stored in an array, and does not necessarily needs to be printed on the worksheet.
Updated code
Sub TEST()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
Dim fRow As Long
Dim sRow As Integer
Dim col As Integer
Dim arr() As Variant
Dim coll As New Collection
col = 3
sRow = 6
With ws1
fRow = .Cells(.Rows.Count, col).End(xlUp).Row
End With
With ws2
fRow2 = .Cells(.Rows.Count, 12).End(xlUp).Row
End With
For i = sRow To fRow
With ws1
ele1= .Cells(i, 2).Value
ele2= "000" & .Cells(i, 4).Value
If ele1<> "" Then
coll.Add Array(ele2)
End If
End With
Next
On Error GoTo gotcha
ReDim arr(1 To coll.Count, 1 To 2)
For i = 1 To coll.Count
arr(i, 1) = coll(i)(0)
Next
gotcha:
Debug.Print Err.number
If Err.number = 9 Then
MsgBox "Error"
Exit Sub
End If
ws2.Range("L29:M" & fRow2).ClearContents
ws2.Range("L29").Resize(UBound(arr, 1), UBound(arr, 2)).Value = arr
Set conn = CreateObject("ADODB.Connection")
Dim fRow3 As Long
With ws2
fRow3 = .Cells(.Rows.Count, 13).End(xlUp).Row
End With
Dim CONNECTION As String
Dim QUERY As String
Dim WHERE As String
'Set connection and SELECT query
CONNECTION = "Provider=*.1;Persist Security Info=True;User ID=*; Password=*; Data Source=*;Initial Catalog=*"
selectpart = "SELECT *FROM database.dbo.table "
'### The error occurs here ###
conditionpart = "WHERE [COL1] IN ('" & Join(arr, "','") & "')"
GetBreakerQuantitiesQuery = selectpart & vbNewLine & conditionpart
QUERY = GetBreakerQuantitiesQuery
conn.Open CONNECTION
Set rs = CreateObject("ADODB.Recordset")
rs.ActiveConnection = conn
rs.Open QUERY
ws.Range("T6").CopyFromRecordset rs
ws.Range("T6:AL6").Copy
ws.Range("N7").PasteSpecial xlPasteValues, xlPasteSpecialOperationNone, True, True
ws.Range("T6:AL6").ClearContents
ws.Range("L6").Select
rs.Close
conn.Close
Set conn = Nothing
Set rs = Nothing
End Sub
Dim sql as string, arr
arr = Array("000165231", "000165232", "000165239")
sql = "SELECT * FROM database.dbo.table WHERE Col1 IN ('" & Join(arr, "','") & "')"
'use sql variable for your query
Use a 1-d array:
For i = sRow To fRow
With ws1
If Len(.Cells(i, 2).Value) > 0 Then
coll.Add "000" & .Cells(i, 4).Value
End If
End With
Next
On Error GoTo gotcha '??
ReDim arr(0 To coll.Count-1)
For i = 1 To coll.Count
arr(i - 1) = coll(i)
Next
'....
ws2.Range("L29").Resize(UBound(arr) + 1, 1).Value = Application.Transpose(arr)

Opening a table in Microsoft Access with VBA in Excel

I'm trying to load a table from Microsoft Access and paste it into Excel cells with VBA.
My path is correctly finding my .accdb file and does error until the first Cells(row x).Value = statement.
The "OpenRecordset" method not referencing a table, makes me feel like I shouldn't be passing in the name of the table- or using a different method altogether.
I get an error: "Run-time error '3265' Application-defined or object-defined error
Here is my code below:
Sub ImportAccessButton()
Dim row As Integer
Dim dbPassengerCarMileage As Database
Dim rstPassengerCarMileage As Recordset
row = 3
Set dbPassengerCarMileage = OpenDatabase(ThisWorkbook.Path & "\Cars.accdb")
Set rstPassengerCarMileage = dbPassengerCarMileage.OpenRecordset("Amber")
If Not rstPassengerCarMileage.BOF Then
Do Until rstPassengerCarMileage.EOF
Cells(row, 1).Value = rstPassengerCarMileage!MAKE
Cells(row, 2).Value = rstPassengerCarMileage!Model
Cells(row, 3).Value = rstPassengerCarMileage!VOL
Cells(row, 4).Value = rstPassengerCarMileage!HP
Cells(row, 5).Value = rstPassengerCarMileage!MPG
Cells(row, 6).Value = rstPassengerCarMileage!SP
Cells(row, 7).Value = rstPassengerCarMileage!WT
row = row + 1
rstPassengerCarMileage.MoveNext
Loop
End If
'Close database and Cleanup objects
rstPassengerCarMileage.Close
dbPassengerCarMileage.Close
Set rstPassengerCarMileage = Nothing
Set dbPassengerCarMileage = Nothing
End Sub
It uses ADODB. The CopyFromRecordset command speeds up.
Sub ImportAccessButton()
Dim Rs As Object
Dim strConn As String
Dim i As Integer
Dim Ws As Worksheet
Dim strSQL As String
set Ws = ActiveSheet
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & ThisWorkbook.Path & "\Cars.accdb" & ";"
strSQL = "SELECT * FROM Amber"
Set Rs = CreateObject("ADODB.Recordset")
Rs.Open strSQL, strConn
If Not Rs.EOF Then
With Ws
.Range("a2").CurrentRegion.ClearContents
For i = 0 To Rs.Fields.Count - 1
.Cells(2, i + 1).Value = Rs.Fields(i).Name
Next
.Range("a" & 3).CopyFromRecordset Rs
End With
End If
Rs.Close
Set Rs = Nothing
End Sub

how to display the rows and columns values in VBA for select query

My actual code is the following:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Call extract
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
End SubSub extract()
Dim cn As Object
Dim uid1, pass1, srvrnm --pass parm
Set cn = CreateObject("ADODB.Connection")
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
Dim cmdSQLData As Object
Set cmdSQLData = CreateObject("ADODB.Command")
uid1 = "SSSS" --user-id
pass1 = "JJJJ" --pass words
srvrnm = "JJJJSDS" --server name
On Error GoTo err1
cn.Open "Driver=Teradata; DBCName="& srvrnm& ";uid="& uid1& ";AUTHENTICATION=ldap;pwd="& pass1& "; Trusted_Connection=True"
Set cmdSQLData.ActiveConnection = cn
On Error Resume Next
query1 = "select tablename,databasename as xx from DBC.TABLES sample 2;"
cmdSQLData.CommandText = query1
cmdSQLData.CommandTimeout = 0
Set rs = cmdSQLData.Execute()
Sheet1.Cells(2, 1) = rs.Fields(0).Value
Set rs = Nothing
err1:
End Sub
My question is how to get database table result in excel rows and column with as many rows as in table and consequent number of columns
You need to loop through your recordset and display the data. So where you have this:
Set rs = cmdSQLData.Execute()
Sheet1.Cells(2, 1) = rs.Fields(0).Value
Set rs = Nothing
You need something like this:
Dim r as Integer 'Row
Dim c as Integer 'Column
For c = 0 To rs.Fields.Count - 1
'This will start on Row 1, Column A (due to + 1) and place all the field headers
Sheet1.Cells(1, c + 1).Value = rs.Fields(c).Name
Next c
r = 3 'We'll start on Row 3
Do While Not rs.EOF
For c = 0 to rs.Fields.Count - 1
'c + 1 means we're starting on Column 1 (A)
'If we wanted to start in Column d, we would use c + 4
Sheet1.Cells(r, c + 1).Value = rs.Fields(c)
Next
r = r +1
rs.MoveNext
Loop
Regarding the comments: To add the field headers, you create an initial loop and simply do not move to the next record. See the modified code above.
The fastest way to copy the entire recordset to an excel sheet should be:
Sheet1.Cells(2, 1).CopyFromRecordset rs

SQL query results into separate columns on Excel worksheet

Previously I was able to run some VBA that ran several SQL queries and put the results in separate columns in a single Excel worksheet. There was a reference set to Microsoft ActiveX Data Objects 2.8 Library (Tools, References in the VBE).
Although the code was working fine, recently I get an error message as follows -
Run-time error '-2147217913 (80040e07)'
Data type mismatch in criteria expression
Here is the code (the error appears in "rs.Open sql, cn, adOpenStatic" which is less than helpful). Please note that the same error appears in all VBA/SQL code I try to run, not just the code below.
Private Sub GetUniqueClassesListWithConditions()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim strWkbPath As String
Dim sql As String
Dim buf As Variant
Dim i As Long
Dim j As Long
Dim iTimes As Integer
Dim iQuestion As Integer
Dim iCondition As Integer
Dim iLimit As Integer
Dim sCondition As String
Dim iColumn As Integer
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
.EnableEvents = False
End With
strWkbPath = ThisWorkbook.FullName
Worksheets.Add After:=Sheets(Sheets.Count)
For iQuestion = 1 To 14
For iTimes = 1 To 5
Select Case iTimes
Case 1
iLimit = 7
sCondition = "Day"
Case 2
iLimit = 6
sCondition = "Time"
Case 3
iLimit = 16
sCondition = "Faculty"
Case 4
iLimit = 13
sCondition = "Department"
Case 5
iLimit = 6
sCondition = "Student Numbers"
End Select
For iCondition = 1 To iLimit
sql = "SELECT DISTINCT([Data$].Class) FROM [Data$] WHERE [Data$].Q" & iQuestion & " <> '-' AND [Data$]." & sCondition & " = " & iCondition
j = 0
Set cn = New ADODB.Connection
cn.Provider = "Microsoft.ACE.OLEDB.12.0"
cn.Properties("Extended Properties") = "Excel 12.0;HDR=YES;IMEX=1"
cn.Open strWkbPath
Set rs = New ADODB.Recordset
rs.Open sql, cn, adOpenStatic
ReDim buf(0 To rs.Fields.Count - 1, 0)
For i = 0 To rs.Fields.Count - 1
buf(i, 0) = rs(i).Name
Next i
Do Until rs.EOF
j = j + 1
ReDim Preserve buf(0 To rs.Fields.Count - 1, 0 To j)
For i = 0 To rs.Fields.Count - 1
buf(i, j) = rs(i).Value
Next i
rs.MoveNext
Loop
rs.Close
cn.Close
Set cn = Nothing
Set rs = Nothing
iColumn = iColumn + 1
With ActiveSheet
.Cells(1, iColumn).Value = "Q" & iQuestion & ", " & sCondition & "=" & iCondition
.Cells(2, iColumn).Resize(UBound(buf, 2) + 1, UBound(buf, 1) + 1).Value = TransposeArray(buf)
End With
Next iCondition
iColumn = iColumn + 2
Next iTimes
Next iQuestion
With ActiveSheet
.Rows(1).Font.Bold = True
.Rows(2).EntireRow.Delete
.UsedRange.Columns.EntireColumn.AutoFit
On Error Resume Next
.Name = "Unique Classes List (Condtions)"
On Error GoTo 0
End With
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End With
End Sub
Private Function TransposeArray(buf)
Dim tmp()
Dim i As Long
Dim j As Long
ReDim tmp(UBound(buf, 2), UBound(buf, 1))
For i = LBound(buf, 1) To UBound(buf, 1)
For j = LBound(buf, 2) To UBound(buf, 2)
tmp(j, i) = buf(i, j)
Next j
Next i
TransposeArray = tmp
End Function
If somebody can help me get the code running and/or tell me what the problem is, I'd be very grateful.
Also, I'd like to do the same thing in Access. If I can export all of the results to an Excel file, even as different sheets in a workbook, it's easy for me to run some other code to combine the data into another worksheet. (I'm new to Access and know how to run SQL, but have no idea how to automate it, including putting the results in different "columns" and exporting it)
Should mention my SQL "skills" are basic and I'm learning from w3schools as I go along (hope I'm not offending anybody here.
Thanks for your help in advance.

Building DataGridView Display in Code (VB 2010 NET)

I'm extracting information from an Excel Spreadsheet and trying to build the DataGridView in code. I found this information very helpful. In debug, everything appears to be right. I have the right number of columns and rows properly formatted but nothing displays on the DataGridView. Why? This is really frustrating.
Dim dTable as New DataTable
For Each currcol As Excel.Range In inputRange.Columns
dTable.Columns.Add(currcol.Value2, GetType(String))
Next
inputRange = objXLWs.Range("A" & HeaderRow + 1 & ":" & EndingColumn & EndingRow)
Dim i as Integer
For Each row As Excel.Range In inputRange.Rows
Dim dataRow As DataRow = dTable.NewRow()
i=0
For Each incell As Excel.Range In row.Columns
dataRow(i) = incell.Value2
i += 1
Next
dTable.Rows.Add(dataRow)
Next
bs4DataPreview.DataSource = dTable ' Set up BindingSource
dgv4PreviewData.AutoGenerateColumns = False
dgv4PreviewData.DataSource = bs4DataPreview
dgv4PreviewData.Show()
dgv4PreviewData.Refresh()
Edited source code to reflect use of DataTable. Still getting nothing on DataGridView.
It has been a long time since this question was originally posed. I continued working on the problem and finally came up with a solution that is working. It required building more intelligence into the DataTable.
Dim inputRange As Excel.Range
Dim i As Integer
BuildPreview = False
EndingColumn = ColumnIndexToColumnLetter(EndingColumnNo)
EndingRow = objXLWs.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell).Row
inputRange = objXLWs.Range("A" & HeaderRow & ":" & EndingColumn & HeaderRow)
i = 1
For Each currcol As Excel.Range In inputRange.Columns
Dim column As New DataColumn
column.DataType = GetType(String)
column.ColumnName = "Column" & i.ToString
column.Caption = NS(currcol.Value2)
dTable.Columns.Add(column)
i += 1
Next
inputRange = objXLWs.Range("A" & HeaderRow + 1 & ":" & EndingColumn & Math.Min(EndingRow, HeaderRow + previewRows))
For Each row As Excel.Range In inputRange.Rows
Dim dataRow As DataRow = dTable.NewRow()
i = 1
For Each incell As Excel.Range In row.Columns
dataRow("Column" & i.ToString) = NS(incell.Value2)
i += 1
Next
dTable.Rows.Add(dataRow)
Next
I hope this proves to be helpful for someone else.