Make date variable in a oracle query using VBA - sql

first I'm sorry for the poor english but I'll try my best.
I have an oracle query running in a VBA macro and I need to set the date in the sql select as a variable that relates to a sheet cell, I already managed to make the sql consult work.
I would really appreciate some help with this, I'm really stuck, down goes the working code.
Private Sub cmdConexaoBD_Click()
Dim sql As String
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim i As Integer
'define a conexão com o banco de dados
Set cn = New ADODB.Connection
cn.CursorLocation = adUseClient
cn.Open "Driver={Microsoft ODBC for Oracle}; " & _
"CONNECTSTRING=database;uid=username;pwd=password;"
Set rs = New ADODB.Recordset
sql = "SELECT NUMOS,MIN(DTINICIOOS),MAX(DTFIMOS),MAX(DTFIMOS)-MIN(DTINICIOOS) FROM PCMOVENDPEND WHERE DATA >= TRUNC(SYSDATE) GROUP BY NUMOS"
rs.Open sql, cn
Range("A1").Value = "OS"
Range("B1").Value = "DT"
Range("C1").Value = "DT"
Range("D1").Value = "TEMPO"
i = 1
If Not rs.EOF Then
Do While Not rs.EOF
Range("A" & i + 1).Value = rs(0)
Range("B" & i + 1).Value = rs(1)
Range("C" & i + 1).Value = rs(2)
Range("D" & i + 1).Value = rs(3)
rs.MoveNext
i = i + 1
Loop
End If
cn.Close
End Sub
Where is written WHERE DATA >= TRUNC(SYSDATE) "DATA" actually is date (it's in portuguese), I want to set the date as a variable referring to a sheet cell, so I can change it in the spreadsheet and import the data of such date without changing the code.
I hope that I made myself clear, Thanks!

For example:
Dim dt
dt = format(Range("F1").Value,"mm/dd/yyyy") 'your date is in F1
sql = " SELECT NUMOS,MIN(DTINICIOOS),MAX(DTFIMOS),MAX(DTFIMOS)-MIN(DTINICIOOS) " & _
" FROM PCMOVENDPEND " & _
" WHERE DATA >= to_date('" & dt & "','mm/dd/yyyy') GROUP BY NUMOS "

It's better to use bind variables, so you need something like this:
Set dbADOCommand = New ADODB.Command
Set dbADOParameter = New ADODB.Parameter
sql = "SELECT NUMOS,MIN(DTINICIOOS),MAX(DTFIMOS),MAX(DTFIMOS)-MIN(DTINICIOOS) FROM PCMOVENDPEND WHERE DATA >= :bindDate GROUP BY NUMOS"
dbADOCommand.CommandText = sql
dbADOCommand.CommandType = adCmdText
dbADOCommand.NamedParameters = true
dbADOCommand.Prepared = true
Set dbADOParameter = dbADOCommand.CreateParameter("bindDate", _
ADODB.DataTypeEnum.adDBDate, _
ADODB.adParamInput, _
8, _
"2020-01-01")
dbADOCommand.Parameters.Append dbADOParameter
Set dbADORecordSet = New ADODB.Recordset
Set dbADORecordSet = dbADOCommand.Execute

Related

sql scripts in vba

I am having trouble running my sql code in a for loop. The code works for simple pasting the the sql code in one sheet but not when i put it in a loop. Does anyone have some experience in positing sql scripts in a for loop.
I need it to loop over my three sheets and paste the sql code in each sheet.
Sub rapport()
Dim ws_count As Integer
Dim i As Integer
Dim fundowner(3) As String
fundowner(1) = "110"
fundowner(2) = "120"
fundowner(3) = "130"
'fundowner(4) = "110"
'fundowner(5) = "110"
' Set variables
Dim con As ADODB.Connection
Dim rs_set As ADODB.Recordset
Dim sql As String
'Set Connection
Set rs_set = New ADODB.Recordset
Set con = New ADODB.Connection
con.ConnectionString = NPARRP_CONN_STRING
con.CursorLocation = adUseClient
con.Open
'Sheets("Ark1").Select
'Range("A9:I1000").ClearContents
'sql = Sheets("Ark1").Cells(1, 1).Value
sql = "Select port.FUND_OWNER, sum(fig.ASSETS)" & _
"from SCDDEX.NP_DM_FUND_FIGURES_V fig" & _
"inner join SCDDEX.NP_DM_FUND_PORTFOLIO_DEX port on fig.POR=PORT.POR" & _
"where port.FUND_OWNER in('130')" & _
"and DATE_FOR_FIGURES='2019-11-04'" & _
" group by port.FUND_OWNER"
ws_count = ActiveWorkbook.Worksheets.Count
For i = 1 To ws_count
If ActiveWorkbook.Worksheets(i).Cells(1, 1) = fundowner(i) Then
ActiveWorkbook.Worksheets(i).Cells(3, 1) = sql
Debug.Print sql
rs_set.Open sql, con
ActiveWorkbook.Worksheets(i).Cells(9.1).CopyFromRecordset rs_set
Else
MsgBox "Error"
End If
Next i
End Sub
You could change the Source string for the SQL connection on every iteration to output the recordset according to your fundownder value.
Keep in mind that by this approach, fundowner has be dimensioned according to the number of sheets in the workbook.
Also you will have to Close the recordset each time.
Sub rapport()
Dim ws_count As Integer
Dim i As Integer
Dim fundowner(1 To 3) As String
fundowner(1) = "110"
fundowner(2) = "120"
fundowner(3) = "130"
' Set variables
Dim con As ADODB.Connection
Dim rs_set As ADODB.Recordset
Dim sql As String
'Set Connection
Set rs_set = New ADODB.Recordset
Set con = New ADODB.Connection
con.ConnectionString = NPARRP_CONN_STRING
con.CursorLocation = adUseClient
con.Open
ws_count = ActiveWorkbook.Worksheets.Count
For i = 1 To ws_count
If ActiveWorkbook.Worksheets(i).Cells(1, 1) = fundowner(i) Then
ActiveWorkbook.Worksheets(i).Cells(3, 1) = sql
sql = "Select port.FUND_OWNER, sum(fig.ASSETS) " & _
"from SCDDEX.NP_DM_FUND_FIGURES_V fig " & _
"inner join SCDDEX.NP_DM_FUND_PORTFOLIO_DEX port on fig.POR=PORT.POR " & _
"where port.FUND_OWNER ='" & fundowner(i) & "') " & _
"and DATE_FOR_FIGURES='2019-11-04' " & _
"group by port.FUND_OWNER"
Debug.Print sql
rs_set.Open sql, con
ActiveWorkbook.Worksheets(i).Cells(9.1).CopyFromRecordset rs_set
rs_set.Close
Else
MsgBox "Error"
End If
Next i
End Sub

Excel vba - ADO inner join on data tables

I have two data tables in excel that I wish to join into a single set in my vba code. I have identified the ADO connector as the best way to do this, however using the query below, I get the following error
"Run time error -2147217904
No value given for one or more required parameters"
SELECT components.[name], InputData.Datatype
FROM [Rules$A5:F30] components
INNER JOIN [Rules$O5:R17] InputData ON components.[name] = InputData.[name]
WHERE components.RowId = 0 GROUP BY components.[name], InputData.Datatype
EDIT: The full code:
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim dataRows As Integer
strFile = ThisWorkbook.FullName
strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFile _
& ";Extended Properties=""Excel 12.0;HDR=Yes;IMEX=1"";"
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open strCon
strsql = "SELECT components.[name], InputData.Datatype " _
+ " FROM [" + GetTableAddress("componentTable") _
+ "] components INNER JOIN [" + GetTableAddress("DataLocations") + "] InputData" _
+ " ON components.[name] = InputData.[name] " _
+ " WHERE components.RowId = " + CStr(RowId) + " GROUP BY components.[name], InputData.Datatype"
rs.Open strsql, cn
If Not rs.EOF Then
dataRows = rs.GetRows
and the GetTableAddress function
Private Function GetTableAddress(tableName)
Dim oSh As Worksheet
Dim oLo As ListObject
For Each oSh In ThisWorkbook.Worksheets
For Each oLo In oSh.ListObjects
If oLo.Name = tableName Then
GetTableAddress = Replace(oSh.ListObjects(tableName).Range.AddressLocal, "$", "")
GetTableAddress = oSh.Name + "$" + GetTableAddress
End If
Next
Next
End Function
If both data sets are in Excel, you should use vLookup to create the final table. It'll be easier for you and the benefit is that you can use syntax that you're already familiar with.
vLookup is essentially a table join. You can even use it with Application.WorksheetFunctions if you wish to do it that way.
Also, RecordSet.GetRows can return an array. You should probably use CInt(rs.GetString) if you're not expecting more than one value to be returned.

VBA code to loop and update MS access database column from Excel

Background:
I have an excel spreadsheet that retrieves data from an MS Access database. That code works fine. It retrieves records that have the "comments" field as blank. Users update the comments field in Excel and click a button.
The Ask: Once the button is clicked, the VBA code must loop through all retrieved records in my excel sheet and those records that are marked "completed" in excel must update the same comment in the "comments field" in my database.
I have looked at this article and Gord Thompson posted some code that could work for my situation; except that i dont know how to tailor that code to work for me :(
Link--
VBA code to update / create new record from Excel to Access
**Snapshot of the structure of my database and excel at this ** link
excel:
database:
Will this code work
Sub Update()
Dim cn As ADODB.Connection, rs As ADODB.Recordset
Dim xComments As String
Dim xType As String
Dim xIBES_Ticker As String
Dim xEditor As String
Dim xPRD_Year As String
Dim xPRD_Month As String
Dim xEvent_Date As String
Dim xReporting As String
Dim xNotes As String
' connect to the Access database
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0; " & _
"Data Source=C:\Database1.mdb;"
' open a recordset
Set rs = New ADODB.Recordset
rs.Open "tablename", cn, adOpenKeyset, adLockOptimistic, adCmdTable
Range("A2").Activate ' row 1 contains column headings
Do While Not IsEmpty(ActiveCell)
'filter all columns and update all records back instead of looking for those marked with "complete"
'guessing this will be easier to do
rs.Filter = "Type='" & xType & "' AND IBES_Ticker='" & xIBES_Ticker & "' AND Editor='" & xEditor & "' AND PRD_Year='" & xPRD_Year & "' AND PRD_Month='" & xPRD_Month & "' AND Event_Date='" & xEvent_Date & "' AND Reporting='" & xReporting & "' AND Notes='" & xNotes & "' AND Comments='" & xComments & "' "
If rs.EOF Then
Debug.Print "No existing records found..."
rs.Filter = ""
Else
Debug.Print "Existing records found..."
End If
rs("Type").Value = xType
rs("IBES_Ticker").Value = xIBES_Ticker
rs("Editor").Value = xEditor
rs("PRD_Year").Value = xPRD_Year
rs("PRD_Month").Value = xPRD_Month
rs("Event_Date").Value = xEvent_Date
rs("Reporting").Value = xReporting
rs("Notes").Value = xNotes
rs("Comments").Value = xComments
rs.Update
Debug.Print "...record update complete."
ActiveCell.Offset(1, 0).Activate ' next cell down
Loop
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
I am not sure what bit of the adaptation you are struggling with. The following might help:
Sub update()
Dim r as Range
Set r = [J2] ' shorthand for Range("J2")
While r.offset(0, -3).Value > 0
If r.Value = "Complete" Then
' take this record and put it in the DB
End If
Set r = r.offset(1,0) ' go to the next row
Wend
End Sub
Is that the bit you had difficulty with? If it is something else, please leave a comment.
UPDATE I don't have Access, so it is a little bit hard to give more guidance. However, I found the following code snippet for updating a record in Access (see http://msdn.microsoft.com/en-us/library/office/ff845201(v=office.15).aspx )
UPDATE tblCustomers
SET Email = 'None'
WHERE [Last Name] = 'Smith'
I think we can use that with the above and do something like this:
Sub update()
Dim cn As ADODB.Connection, rs As ADODB.Recordset
' connect to the Access database
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0; " & _
"Data Source=C:\Database1.mdb;"
' open a recordset
Set rs = New ADODB.Recordset
rs.Open "tablename", cn, adOpenKeyset, adLockOptimistic, adCmdTable
Dim r as Range
Set r = [J2] ' shorthand for Range("J2")
While r.offset(0, -3).Value > 0
If r.Value = "Complete" Then
ticker = r.offset(0, -7)
notes = r.offset(0, -1)
' create the query string - something like this?
qString = "UPDATE table name SET Notes='" & notes & "' WHERE IBES_Ticker='" & ticker
' now put it in the database:
cn.Execute qString, dbFailOnError
End If
set r = r.offset(1,0) ' go to the next row
Wend
' now close your connections properly…
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub

Operation must use an Updateable Query / SQL - VBA

I am trying to create a very dynamic macro that will update different tables in a Database, depending on what the user chooses. Each table has of course distinct titles and information. I'm having a problem with the update (when the user adds new records to an old Table). This is part of the code, the problem is when it gets to the ".update", I get the "Operation must use an Updateable Query" error.
Dim DBCnn As ADODB.Connection
Dim RecSet As ADODB.Recordset
Dim sQRY As String
Dim FilePath, Titulo, Tabla As String
Dim LastRow, LastColumn, TotalRecords, Id As Long
Set DBCnn = New ADODB.Connection
Set RecSet = New ADODB.Recordset
DBCnn.Mode = adModeReadWrite
DBCnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & "Data Source=" & FilePath & ";"
sQRY = "SELECT * FROM Customers" & Tabla ' & " WHERE PopID = " & lngid
RecSet.CursorLocation = adUseClient
RecSet.Open _
Source:=sQRY, _
ActiveConnection:=DBCnn, _
CursorType:=adOpenDynaset, _
LockType:=adLockOptimistic
Do While Range("A" & LastRow).Value <> ""
' repeat until first empty cell in column A
With RecSet
.AddNew
.Fields("Id") = Range("A" & LastRow).Value
.Fields("Name") = Range("B" & LastRow).Text
.Fields("Age") = Range("C" & LastRow).Value
.Update '(Here's my error)
End With
LastRow = LastRow + 1
Loop
Discard this line:
RecSet.CursorLocation = adUseClient
Or try it like this instead:
RecSet.CursorLocation = adUseServer
See the Remarks section at CursorLocation Property (ADO) on MSDN:
"If the CursorLocation property is set to adUseClient, the recordset will be accessible as read-only, and recordset updates to the host are not possible."
You're concatenating a string here - "SELECT * FROM Customers" & Tabla , but I don't see where Tabla is being provided.
Have you tried running the query directly in Access?
Also, have you tried changing cursortype yet?
http://www.w3schools.com/ado/prop_rs_cursortype.asp

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