Excel VBA - Executing a job within SQL Server via a macro - sql-server

I have a job stored on a database, scheduled to run every day. But its sometimes necessary to want to execute this job at any given time to view up to date data (I'm using SQL Server Management Studio 2008).
The job itself simply takes data from a view which contains live data and puts it into a table which will then be used as a data source for an excel file. Executing the job drops and re-creates the table with fresh data.
In excel (2010), i wish to have a 'button' which which pressed will execute the job and then hitting refresh on the data tab in excel will then update the data on the sheet with the fresh data.
My question is: How do i execute this job from an excel macro?

Private Sub CmdRunJob_Click()
Dim con As Object
Set con = CreateObject("ADODB.Connection")
con.Open = "DRIVER={SQL Server};SERVER=YourServer;" & _
"USER=YourUser;PASSWORD=YourPassword;"
con.Execute "exec msdb.dbo.sp_start_job 'YourJob'"
End Sub

You create a SP that moves data from view to table.
Then modify the Job that it executes that SP by schedule.
Then in Excel Macro you can just use that SP to update the data.
Or see example how to run the Job from VBScript

You can use SQLDMO.SQLServer to execute your job.

Related

Return Select Queries Using ADO and Provider = SQLOLEDB

My ultimate goal is to run sql queries against sql-server and capture the returned data in a spreadsheet. The following code roughly reflects my current set-up and it works. The design allows me to read sql codes from text files and submit it to a sql-server. "Sub ExecuteCRUD" submits a first sql script to prepare data and dumps the result into a temp table. "Function loadRecordset" submits a relatively simple select query and captures the returned data in a recordset, which I then use to populate a spreadsheet.
There are a couple "variables" in my setup that could potentially be relevant for discussion.
My 4 set of Sql Codes
The ConnectionString (Part of my vba code)
The rest of my vba codes
a. Dbo.ConnectionString = "Provider=MSDASQL;DRIVER=SQL
Server;SERVER=myserver;UID=id;PWD=password;DATABASE=database;"
b. Dbo.ConnectionString = "Provider=SQLOLEDB;Data
Source=myserver;Initial Catalog=database;User
ID=id;Password=password;"
Initially, all I changed was the connection string. The immediate result was connection string version a works perfectly. Using b version, my setup would fail without any errors from sql-server.
Using Connection string version b, "Sub ExecuteCRUD" (data preparation step) would still work smoothly. I can verify that the temp table is created in tempdb as a result of my first sql script.
"Function loadRecordset" would run through the lines without any errors up to and including "rs.open". (I checked for errors, none whatsoever from the ado connection).
Only subsequent codes, when using the recordset to copy out the data would get an error: "Operation is not allowed when the object is closed."
Through some testing, I narrowed down the issue to the sql codes, sort of.
I have to reiterate here. My initial set of sql codes worked completely fine when using the ODBC provider. Things only went sideways using the OLEDB provider.
Using the OLEDB provider, the "offending" sql code was Use databaseABC. Furthermore, using ado, my setup submits 4 sets of sql codes to the sql server. The first set of sql codes prepares data (creating tables, inserting data, creating index, using while loops to populate data, using recursive ctes, etc). In this first set of sql codes, Use databaseABC was also included, and it would execute successfully. The other 3 set of sql codes submitted were only select queries aimed at obtaining data. When Use databaseABC was included in the select query sql codes, the operation failed without any errors. After I took out the Use databaseABC, everything would run correctly in the OLEDB provider world.
Use databaseABC is not a necessary part of the select queries. Using it saves me the trouble of specifying database names all the time in the join clauses.
At this point, my curiosity is two fold
why Use databaseABC causes failures, specifically only when using OLEDB provider, more specifically only when running select queries.
When the failure occurred, should sql-server or the driver generate any errors? What would be the proper way of checking and verifying that?
Private Dbo As New ADODB.Connection
Private rs As ADODB.Recordset
Public Sub ConnectServer()
If Dbo.State = adStateClosed Then
Dbo.ConnectionString = "Provider=SQLOLEDB;Data Source=*server*;" _
& "Initial Catalog=*database*;User ID=*id*;Password=*pwd*;"
Dbo.Open
End If
End Sub
Public Sub ExecuteCRUD(ByVal Sql As String)
On Error GoTo PANIC
Dbo.Execute Sql
Exit Sub
PANIC:
Debug.Print Err.Descript
Stop
End Sub
Public Function loadRecordset(ByVal Sql As String) As Long
On Error GoTo PANIC
Set rs = New ADODB.Recordset
With rs
.CursorLocation = adUseClient
.CursorType = adOpenStatic
.LockType = adLockReadOnly
.Source = Sql
Set .ActiveConnection = Dbo
End With
rs.Open
loadRecordset = rs.RecordCount
Exit Function
PANIC:
Debug.Print Err.Description
loadRecordset = 0
Stop
End Function

Refresh data in Excel connection by just appending new data to the tables instead of retrieving everything from the sql server

Needed to refresh data connection (SQL server connection consisting of multiple tables) in my excel worksheet on a regular basis. However, when I perform a "Refresh All" excel basically retrieves all data from the SQl server from scratch and hence takes a long time to retrieve data. I was hoping to speed this by pulling in only the required data and then appending this to my tables in my connection. Is there a way to do this using VBA?
I have an Excel sheet with a connection to a SQL server from which I bring in multiple tables to build dynamic reports. While refreshing the data to bring in new rows to all different tables, excel takes a really long time to bring in the data as it retrieves all rows from the sql server from scratch. I was hoping I could just bring in the new data and then feed it into the tables in my data connection and refresh the data this way using a VBA script. I did come across code to get the required data from the SQL server but didn't find a way to then feed this data back into the tables and refresh the tables this way instead of using the "refresh all" option and avoid having to wait a long time.
Dim sConnString As String
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
sConnString = "Provider=SQLOLEDB.1;Initial Catalog=WELLTHY_ALL;" & _
"User ID=username;Password=password;Data Source=NEWINSTANCE;"
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
conn.Open sConnString
query = "SELECT * FROM table where date >" & " '2019-05-03'"
Set rs = conn.Execute(query)
I want to then append this data that I got above in rs into the table bought into excel via the connection and avoid the time-consuming refresh all method

Transfer table from Ms-Access to SQL Server

I don't have much experience with SQL Server, I use it currently to run some simple queries, and I link to SQL tables from Access where I have all my heavy queries. My goal is to run all of my queries in Access daily and then at the end write the finished tables up to SQL where my Access front end will read them (versus keeping them in my Access backend).
I've tried messing around with the code below to try and figure out how to do this, but I'm stuck at the driver and I can't find any references on how to do this with just a single table. Let's call it "PO_STATUS_TBL"
Public Sub ADOtest()
Dim ADOConn As New ADODB.Connection
Dim ADOCom As New ADODB.Command
On Error Resume Next
ADOConn.ConnectionString = "Driver =(SQL Server);DRIVER=SQL Server;SERVER=BUSINESS_BWP;Trusted_Connection=Yes"
ADOConn.Open
Debug.Print ADOConn.State
Dim db As Database
Set db = CurrentDb
'db.Execute "INSERT INTO [ODBC;DRIVER=SQL Server;ENCSQL28\BUSINESS_BWP;DATABASE=CurrentDb].SFTransfersDB ( ID, TO ) SELECT ID,TO FROM SFTransfersDB"
End Sub
I went through this process lately.
For migration you can use this tool by Microsoft. With this tool you can either migrate a table or a query to MS-SQL - or even both. Even with relations.
Simple export with this wizard and add your one table through ODBC Connector in Access. Important is to have the correct ODBC Driver.
If you are interested I resolved this issue with Parfait's advise. By using a simple INSERT statement.
INSERT INTO Dbo_PO_STATUS_ALL_TBL Select * FROM PO_STATUS_ALL_TBL

Error 3035 when querying linked table in Access

I get error 3035: 'System Resource Exceeded' when executing the following sub:
Private Sub delete_result_staging()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb
Set qdf = db.QueryDefs("qryWQPassthrough")
qdf.Connect = Me.con_str.Value
qdf.ReturnsRecords = False
qdf.SQL = "TRUNCATE TABLE tblWQResultStaging;"
qdf.Execute
Set qdf = Nothing
Set db = Nothing
End Sub
I am using MS Access 2013 and SQL Server 2012.
This code has worked previously; it stopped working when I refactored another sub per How to increase performance for bulk INSERTs to ODBC linked tables in Access?. I have changed the MaxLocksPerFile to 1,000,000 in the registry per other suggestions on the internet. I restarted Access and my computer, and I still get the error every time the sub fires. In the SQL Server Profiler I see no activity on the server when the code is executed. Forms and reports that point to linked tables on the same server but are connected via the GUI, rather than through VBA, still work as expected.
I figured out the issue was that I was reusing a single passthrough query multiple times in VBA. It didn't like the SQL statement that was in the query from the last time I used it in code, so it threw the error. Looks like I need to either be more careful with my earlier VBA code that uses that query, or use separate queries for every VBA sub, or both.

Crystal Report Datasource remap

I am working with Crystal Reports and MS SQL Server.
I need to remap the crystal report to point to a different database on the same SQL Server. Is there an automated way of doing this, or do I have to remap for every single report? I am currently doing this by adding a new data connection, and then updating the stored procedure with the specified paramether to change database(catalog). Also, after remaping, the .asp that displays the report crashes like this:
Active Server Pages, ASP 0115 (0x80004005)
A trappable error (E06D7363) occurred in an external object. The script cannot continue running.
The code is:
Set mainReportTableCollection = Session("oRpt").Database.Tables
For Each mnTable in mainReportTableCollection
With mnTable.ConnectionProperties
.Item("user ID") = "<some_login_name>"
.Item("Password") = "<some_password>"
.Item("DSN") = "<some_DSN>"
.Item("Database") ="<some_Database>"
End With
Next
It runs, however, if i comment out the last two assignations.
Thanks in advance.
Yours trully, Silviu.
You'll find hereafter the procedure I use (I simplified it on the fly, suppressing our own objects and global variables). This procedure allows to redirect a report from an original connection used at development time to the active SQL server. It is written in VB and uses 2 main objects:
The original report object opened through an instance of crystal report
An ADODB connection being the active connection (called P_currentConnection) to the current SQL server
This function (could be also a sub) is called before viewing/printing the report object in the application. It can be used when distributing reports among replicated databases where users, depending on their location, connect to different servers/databases.
Public Function connectReportToDatabase( _
P_report As CRAXDRT.Report)
Dim table As CRAXDRT.DatabaseTable, _
For Each table In P_report.Database.tables
If table.DllName <> "crdb_ado.dll" Then
table.DllName = "crdb_ado.dll"
End If
table.ConnectionProperties.DeleteAll
table.ConnectionProperties.Add "Provider", P_currentConnection.Provider
table.ConnectionProperties.Add "Data source", P_currentConnection.Properties("Data source").Value
table.ConnectionProperties.Add "Database", P_currentConnection.DefaultDatabase
table.ConnectionProperties.Add "Integrated security", P_currentConnection.Properties("Integrated security").Value
table.ConnectionProperties.Add "Persist Security Info", P_currentConnection.Properties("Persist Security Info").Value
table.ConnectionProperties.Add "Initial Catalog", P_currentConnection.Properties("Initial Catalog").Value
table.SetTableLocation table.location, "", P_currentConnection.ConnectionString
table.TestConnectivity
Next table
It can be called with a procedure such as:
Dim crystal As CRAXDRT.Application, _
m_report as CRAXDRT.report
Set crystal = New CRAXDRT.Application
Set m_rapport = crystal.OpenReport(nameOfTheReport & ".rpt")
connectreportToDatabase(m_report)
In case your report includes subreports, You might also have to redirect them to the active connection. In this case, you'll have to browse all objects in your report, check the ones that are of the report type and redirect them to the new connection. I am sure you'll have fun adding the corresponding extra lines to this original procedure.
You can get any of the info from the current report connection info. So if your not changing servers, then set the crystalServer variable to the reports current server.
'SET REPORT CONNECTION INFO
For i = 0 To rsource.ReportDocument.DataSourceConnections.Count - 1
rsource.ReportDocument.DataSourceConnections(i).SetConnection(crystalServer, crystalDB, crystalUser, crystalPassword)
Next
For i = 0 To rsource.ReportDocument.Subreports.Count - 1
For x = 0 To rsource.ReportDocument.Subreports(i).DataSourceConnections.Count - 1
rsource.ReportDocument.OpenSubreport(rsource.ReportDocument.Subreports(i).Name).DataSourceConnections(x).SetConnection(crystalServer, crystalDB, crystalUser, crystalPassword)
Next
Next

Resources