I pull data from an Oracle database using VBscript and place the recordset result into a csv file. Here is my code,
Set con = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
Set ssfile = CreateObject("Scripting.FileSystemObject").CreateTextFile("C:\Users\jasons\Documents\Closing_stock\scripts\SuperSession.csv")
con.Open "Provider=OraOLEDB.Oracle;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=athena)(PORT=1521)))(CONNECT_DATA=(SID=jasdnf)));User Id=xxxx;Password=xxxx"
rs.Open "select * from mytable", con, 1, 3
ssfile.WriteLine "ITEM, ALTITEM"
rs.MoveFirst
Do
ssfile.WriteLine rs("item") & "," & rs("altitem")
rs.MoveNext
Loop Until rs.EOF
rs.Close
con.Close
Set con = Nothing
The code works fine. The problem I have is that there is about 4 million records and it takes the code long to loop through each record and paste it into the csv file. Is there a similar function in VBscript as in Excel-VBA such as CopyFromRecordset, where the whole recordset can be dumped into a sheet. So I would like to dump the recordset result into the csv file without having to loop through each record. How can I do this?
You could try using GetString(), which returns all (or optionally, a subset) of your recordset as a string where you can specify the delimiters etc:
Set con = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
Set ssfile = CreateObject("Scripting.FileSystemObject").CreateTextFile("C:\Users\jasons\Documents\Closing_stock\scripts\SuperSession.csv")
con.Open "Provider=OraOLEDB.Oracle;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=athena)(PORT=1521)))(CONNECT_DATA=(SID=jasdnf)));User Id=xxxx;Password=xxxx"
rs.Open "select * from mytable", con, 1, 3
ssfile.WriteLine "ITEM, ALTITEM"
rs.MoveFirst
ssfile.writeline rs.GetString(2, , ",")
rs.Close
con.Close
Set con = Nothing
Not sure if you need to supply a rowdelimiter or not, you may need to experiment - eg try rs.GetString(2, , ",", vbNewLine)
Related
I have a Query Where I Need to Add Query Statement and fetch that Details to the Excel Sheet
Table name is : Student_Details
ID|Name|Course|
1 |vik |MBA |
2 |sik |CA |
3 |mil |CP |
4 |hil |MP |
query : Select * from Student_Details;
How Do I implement in Below Query
Sub Ora_Connection()
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Dim query As String
Set con = New ADODB.Connection
Set rs = New ADODB.Recordset
'--- Replace below highlighted names with the corresponding values
strCon = "Driver={Microsoft ODBC for Oracle}; " & _
"CONNECTSTRING=(DESCRIPTION=" & _
"(ADDRESS=(PROTOCOL=TCP)" & _
"(HOST=ora130b-example.intra)(PORT=1534))" & _
"(CONNECT_DATA=(SERVICE_NAME=JFG))); uid=jfg_o; pwd=ure;"
'--- Open the above connection string.
con.Open (strCon)
'--- Now connection is open and you can use queries to execute them.
'--- It will be open till you close the connection
con.Close
End Sub
This should make it work Taken from Link
Steps:
Set the results and Execute the Query
Print those result in a loop.
con.Open (strCon)
query = "Select * from Student_Details"
Set rs = con.Execute(query)
Do While Not rs.EOF
For i = 0 To rs.Fields.Count - 1
Debug.Print rs.Fields(i).Name, rs.Fields(i).Value
Next
rs.MoveNext
Loop
rs.Close
con.Close
To directly copy data to Activesheet Use:
ActiveSheet.Range("A1").CopyFromRecordset rs
I have the following code that looks up an ID in a data table and returns the corresponding value from other columns. Below is the code to return a single column value and post it to the TextBox/ComboBox on my form. However, I am looking to create this as a loop to post to all the 20-30 fields I have rather than repeating the code for each field.
col_no = 3 to 29
Note that my TextBox/ComboBox have varying names e.g. customer, site etc.
id_1 = OrderDisplay.id
col_no = 3
sales_order = WorksheetFunction.VLookup(id_1, Worksheets("Data").Range("A:AB"), col_no, False)
OrderDisplay.sales_order = sales_order
How can I achieve that?
Consider querying your worksheet data as a database as it seems to be tabular structure where you pass in as a parameter the specific id. In fact, this may set you up to upsize your worksheet to actual database like MS Access (Excel's sibling), SQLite, etc. where you can swap out the ADO connection string and then sheet name in SQL for database table!
Below assumes all your userform controls have the same exact name as table fields (first columns of worksheet).
Dim conn As Object, rst As Object, cmd As Object
Dim strSQL As String, id1 As Long
Set conn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;" _
& "Data Source='C:\Path\To\Workbook.xlsm';" _
& "Extended Properties=""Excel 12.0;HDR=YES;"";"
' OPEN CONNECTION
conn.Open strConnection
' WORKBOOK QUERY
strSQL = "SELECT t.* " _
& " FROM [SheetName$] AS t" _
& " WHERE t.id = ?"
id_1 = OrderDisplay.id
' BUILD PARAMETERED QUERY
Set cmd = CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandText = strSQL
.CommandType = adCmdText
.Parameters.Append .CreateParameter("idparam", adInteger, adParamInput, , id1)
End With
' CREATE RECORDSET
Set rst = cmd.Execute
' LOOP THROUGH RECORDSET AND FILL IN CONTROL VALUES
rst.MoveFirst
Do While Not rst.EOF
For i = 1 To rst.Fields.Count - 1
Me.Controls(rst.Fields(i).Name).Value = rst.Fields(i)
Next i
rst.MoveNext
Loop
rst.Close: conn.Close
Set conn = Nothing: Set rst = Nothing: Set cmd = Nothing
I want to analyse my DB and get the results for each table into an MS Excel worksheet by executing "sp_MSforeachtable 'EXECUTE sp_spaceused [?];';" from an ADODB Command or Recordset and then use CopyFromRecordset to output the results into Excel.
Here is the code I am using:
Sub analyseHermesDB()
Dim oConn As Object, oRec As Object, oField As Object, iIndx As Integer
' sp_MSforeachtable 'EXECUTE sp_spaceused [?];';
Set oConn = CreateObject("ADODB.Connection")
Set oRec = CreateObject("ADODB.Recordset")
oConn.Open "FILE NAME=" & ThisWorkbook.Path & "\conn.udl"
With oRec
.activeconnection = oConn
.Source = "sp_MSforeachtable 'EXECUTE sp_spaceused [?];';"
.cursorlocation = 3
.Open
For iIndx = 0 To .fields.Count - 1
ActiveCell.Offset(0, iIndx).Value = .fields(iIndx).Name
Next
Do Until .EOF
ActiveCell.Offset(.absoluteposition, 0).CopyFromRecordset oRec
.movenext
Loop
ActiveCell.Offset(0, 1).Value = .RecordCount
.Close
End With
End Sub
The problem is this: When I execute "sp_MSforeachtable 'EXECUTE sp_spaceused [?];';" in SQL Server 2008 Management Studio I get one resultset for each table.
I am only getting one recordset back from the call using ADO
What am I doing wrong? Should I be trying to get an array of recordsets, or execute sp_MSforeachtable to get the list of tables then execute EXECUTE sp_spaceused [?];' for each one?
sp_MSforeachtable returns multiple result sets and you need to consume them this way
However, you can achieve what you want with some simple SQL instead
sp_spaceused uses similar SQL internally anyway...
Feel free to tweak, this is an exact copy/paste of a script I use
SELECT
o.name,
SUM(ps.reserved_page_count)/128.0 AS ReservedMB,
SUM(ps.used_page_count)/128.0 AS UsedMB
FROM
sys.objects o
JOIN
sys.dm_db_partition_stats ps ON o.object_id = ps.object_id
WHERE
OBJECTPROPERTYEX(o.object_id, 'IsMSShipped') = 0
GROUP BY
o.name
ORDER BY
SUM(ps.reserved_page_count) DESC
I am only getting one recordset back from the call using ADO
That's not true, you're only evaluating one recordset. Use NextRecordset to get the next recordset.
From Visual Basic Concepts:
Running a Stored Procedure That Returns Multiple Resultsets
Private Sub MultipleRSButton_Click()
Dim rs As New ADODB.Recordset
sql = "Select * from Authors Where year_born is not null; " _
& "Select * from Authors where year_born is null"
rs.Open sql, cn
Do
i = MsgBox("Ready for results?", vbYesNoCancel)
If i = vbYes Then
ADOGrid1.ShowData rs
Set rs = rs.NextRecordset
End If
Loop Until rs.State = adStateClosed
End Sub
Note Set rs = rs.NextRecordset.
But for all intents and purposes, gbn's answer is probably better; it doesn't rely on an undocumented stored procedure.
i want to allow the user to upload xls file with 9 columns and unlimited number of rows.
i will run over everyline and insert the data to the db
how do i read the xls file?
You can read the XLS by opening an ADO recordset which pulls in the spreadsheet's data.
This example reads data from a spreadsheet named Billing Summary which includes column names in the first row..
Public Sub ReadSpreadsheet()
Const cstrFolder As String = "C:\Access\webforums"
Const cstrFile As String = "ExampleFinance.xls"
Dim strConnect As String
Dim strSql As String
Dim cn As Object
Dim rs As Object
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
strConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
cstrFolder & Chr(92) & cstrFile & _
";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
cn.Open strConnect
strSql = "SELECT * FROM [Billing Summary$] WHERE SomeField Is Not Null;"
rs.Open strSql, cn
Do While Not rs.EOF
'* do something with each row of data *'
'Debug.Print rs!SomeField '
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
If that particular connection string doesn't work for you, look at other examples of Excel connection strings at Connection strings for Excel
Edit: That example works in Access. But you said ASP. I think it will work there, too, if you drop the data types from the variable and constant declarations: Dim strSql instead of Dim strSql As String
Example of using an SQL statement to update Access from Excel.
Set cn = CreateObject("ADODB.Connection")
scn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\docs\dbto.mdb"
cn.Open scn
sSQL = "SELECT * INTO NewTable FROM "
sSQL = sSQL & "[Excel 8.0;HDR=YES;IMEX=2;DATABASE=C:\Docs\From.xls].[Sheet1$]"
cn.Execute sSQL, recs
MsgBox recs
In C#, I had to load an excel spreadsheet to a DataSet - this got me there...
Code Project Example
I used Option 1 - the Preferred method! Hope this helps...
Mike
Using a VBA script in Excel, I'm trying to insert a new row into a table and then get back the identity value of that row. If I run:
INSERT INTO DataSheet(databaseUserID, currentTimestamp)
VALUES (1, CURRENT_TIMESTAMP);
SELECT SCOPE_IDENTITY()
in Management Studio, the row is inserted and it gives me the returned identity value as expected. However, when I run the exact same query through a ADODB recordset in VBA, I'm having trouble. The row is indeed inserted, but I can't access the identity value. The recordset lists 0 fields and has actually been closed as well. I've tried with and without the semicolon, and I also tried running the query as a single transaction as well. Same deal, no dice. Any idea what is going on?
Here's my VBA:
Dim rs As ADODB.Recordset
Dim cn As Connection
Dim SQLStr As String
Dim serverName As String
Dim databaseName As String
serverName = "MSSQLServer"
databaseName = "QA"
cxnStr = "Driver={SQL Server};Server=" & serverName & ";Database=" & databaseName & ";"
SQLStr = "INSERT INTO DataSheet(databaseUserID, currentTimestamp)
VALUES (1, CURRENT_TIMESTAMP); SELECT SCOPE_IDENTITY()"
Set cn = New ADODB.Connection
cn.Open cxnStr
Set rs = New ADODB.Recordset
rs.Open SQLStr, cn, adOpenKeyset, adLockOptimistic
MsgBox (rs.Fields(0).Value)
And the message box fails to display because the rs.Fields(0).Value returns NULL. I added a watch to rs, and, like I said, shows 0 fields after the query and also appears to be closed (state = 0).
When you run a batch of commands using ADODB, I believe it runs each one seperately. To force the next command to run, you have to use the following:
Set rs = rs.NextRecordset()
Changing the end of your routine to the following should do the trick:
Set rs = New ADODB.Recordset
rs.Open SQLStr, cn, adOpenKeyset, adLockOptimistic
Set rs = rs.NextRecordset
MsgBox (rs.Fields(0).Value)
You are executing two statements so you will get two results back. the recordset object can only hold one result at a time - to get the other result you need to use the NextRecordset method.
Set rs = rs.NextRecordset
In your rs.Open Try this
rs.Open SQLStr, cn, adCmdText
See what happens when you remove the adOpenKeySet and adLockOptimistic values leave them at their defaults.