1

I have a problem with Excel VBA recordset, it runs all other queries but this one particular query which runs in SQL Server does not open with the Recordset. Here is the code chunk:

SQL2 = "DECLARE @val VARCHAR (2000) " & vbCrLf & "DECLARE @cert VARCHAR(2000) " & vbCrLf & _
    "DECLARE @inv VARCHAR(2000) " & vbCrLf & "DECLARE @loc INT " & vbCrLf & _
    "DECLARE @res TABLE(val VARCHAR(100)) " & vbCrLf & _
    "DECLARE @Delimiter VARCHAR(2) " & vbCrLf & "SET @val = '' " & vbCrLf & _
    "SET @Delimiter = ',' " & vbCrLf & "SELECT @cert = " & vbCrLf & "CASE WHEN @cert = '' " & vbCrLf & _
    "THEN CertInvsRec " & vbCrLf & "ELSE @cert + coalesce(',' + CertInvsRec, '') " & vbCrLf & _
    "End " & vbCrLf & "FROM  ProjValuations WHERE (Proj = 'TPL-15-020') " & vbCrLf & _
    "SELECT @inv = " & vbCrLf & "CASE WHEN @inv = '' " & vbCrLf & "THEN InvsAmountRec " & vbCrLf & _
    "ELSE @inv + coalesce(',' + InvsAmountRec, '') " & vbCrLf & "End " & vbCrLf & _
    "FROM  ProjValuations WHERE (Proj = 'TPL-15-020') " & vbCrLf & "SET @val = CONCAT(@inv, ',', @cert) " & vbCrLf & _
    "IF NOT  @val = ',' " & vbCrLf & "DECLARE @Index SMALLINT, @Start SMALLINT, @DelSize SMALLINT " & vbCrLf & _
    "SET @DelSize = LEN(@Delimiter) " & vbCrLf & "WHILE LEN(@val) > 0 " & vbCrLf & "BEGIN " & vbCrLf & _
    "SET @Index = CHARINDEX(@Delimiter, @val) " & vbCrLf & "IF @Index = 0 " & vbCrLf & "BEGIN " & vbCrLf & _
    "INSERT INTO @res(val) VALUES(LTRIM(RTRIM(@val))) " & vbCrLf & "BREAK " & vbCrLf & _
    "End " & vbCrLf & "Else " & vbCrLf & "BEGIN " & vbCrLf & _
    "INSERT INTO @res (val) VALUES (LTRIM(RTRIM(SUBSTRING(@val, 1,@Index - 1)))) " & vbCrLf & _
    "SET @Start = @Index + @DelSize " & vbCrLf & _
    "SET @val = SUBSTRING(@val, @Start , LEN(@val) - @Start + 1) " & vbCrLf & "End " & vbCrLf & _
    "End " & vbCrLf & vbCrLf & "SELECT " & vbCrLf & "( " & vbCrLf & _
    "SELECT sum(InvTotExcl) FROM invnum WHERE autoindex in ( " & vbCrLf & _
    "SELECT iInvoiceID FROM _bvSalesOrdersFull WHERE (ProjectCode LIKE '%020%') AND " & vbCrLf & _
    "(StatusDescription = 'CERTIFICATE') and iInvoiceID not in (SELECT * FROM @res)) " & vbCrLf & _
    ") " & vbCrLf & " AS certAmnt, " & vbCrLf & "( " & vbCrLf & _
    "SELECT SUM(InvTotExcl) FROM _bvSalesOrdersFull WHERE (ProjectCode = 'TPL-15-020') AND " & vbCrLf & _
    "(StatusDescription = 'STANDARD') and iInvoiceID not in (SELECT * FROM @res) " & vbCrLf & ") AS invAmnt" 
If rsAmnts.State = adStateOpen Then rsAmnts.Close 
rsAmnts.Open SQL2, CN, adOpenStatic, adLockReadOnly

Any help would be highly appreciated, thanks in advance.

If it helps, If I use direct SELECT queries like e.g. SELECT * FROM things it runs, could be because of the variable declarations, so maybe should I move the query to a procedure?

10
  • 1
    sql server? oracle? please tag the question with the db flavor you are using. Commented Jan 5, 2017 at 11:06
  • 2
    If you do debug.print SQL2 in the immediate window and then run the query in SQL does it run ok? Commented Jan 5, 2017 at 11:09
  • what is the error number you have? if there is no runtime error then the problem is inside the SQL which is rather ok but not valid for your database/table Commented Jan 5, 2017 at 11:21
  • @shahkalpesh its sql server Commented Jan 5, 2017 at 11:37
  • @GaryEvans yes it runs okay, just in the code is where it doesn't run Commented Jan 5, 2017 at 11:38

4 Answers 4

1

So a solution I found that worked is by creating a procedure out of the SQL Query

/****** Object:  StoredProcedure [dbo].[valuationReports]    Script Date: 1/9/2017 17:24:26 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE PROCEDURE [dbo].[valuationReports] 
    @proj AS VARCHAR(200)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @val VARCHAR (2000)
    DECLARE @cert VARCHAR(2000)
    DECLARE @inv VARCHAR(2000)
    DECLARE @loc INT
    DECLARE @res TABLE(val VARCHAR(100))
    DECLARE @Delimiter VARCHAR(2)
    SET @val = ''
    SET @Delimiter = ','
    SELECT @cert = coalesce(',' + CertInvsRec, '')
        FROM  ProjValuations WHERE (Proj = @proj)
    SELECT @inv = coalesce(',' + InvsAmountRec, '')
        FROM  ProjValuations WHERE (Proj = @proj)
    SET @val = CONCAT(@inv, ',', @cert)
    --select @val as 'tst'
    IF NOT  @val = ','
    BEGIN
        DECLARE @Index SMALLINT, @Start SMALLINT, @DelSize SMALLINT
        SET @DelSize = LEN(@Delimiter)
        WHILE LEN(@val) > 0
        BEGIN
            SET @Index = CHARINDEX(@Delimiter, @val)
            IF @Index = 0
                BEGIN
                    INSERT INTO @res(val) VALUES(LTRIM(RTRIM(@val)))
                    BREAK
                END
            ELSE
                BEGIN
                    INSERT INTO @res (val) VALUES (LTRIM(RTRIM(SUBSTRING(@val, 1,@Index - 1))))
                    SET @Start = @Index + @DelSize
                    SET @val = SUBSTRING(@val, @Start , LEN(@val) - @Start + 1)
                END
        END
    END
    SET @cert = ''
    SET @inv = ''
    SELECT @cert = 
        CASE WHEN @cert = ''
        THEN cast(iInvoiceID as varchar)
        ELSE @cert + coalesce(',' + cast(iInvoiceID as varchar), '')
        END
        FROM _bvSalesOrdersFull WHERE (ProjectCode = @proj) AND 
        (StatusDescription = 'CERTIFICATE') AND iInvoiceID NOT IN (SELECT * FROM @res)
    SELECT @inv = 
        CASE WHEN @inv = ''
        THEN cast(iInvoiceID as varchar)
        ELSE @inv + coalesce(',' + cast(iInvoiceID as varchar), '')
        END
        FROM  _bvSalesOrdersFull WHERE (ProjectCode = @proj) AND 
        (StatusDescription = 'STANDARD') AND iInvoiceID NOT IN (SELECT * FROM @res)

    SELECT 
    (
        SELECT ISNULL(SUM(InvTotExcl), 0) FROM invnum WHERE autoindex in (
        SELECT iInvoiceID FROM _bvSalesOrdersFull WHERE (ProjectCode = @proj) AND 
        (StatusDescription = 'CERTIFICATE') AND iInvoiceID NOT IN (SELECT * FROM @res)
        )
    ) AS 'cert',
    (
        SELECT ISNULL(SUM(InvTotExcl), 0) FROM _bvSalesOrdersFull WHERE (ProjectCode = @proj) AND 
        (StatusDescription = 'STANDARD') AND iInvoiceID NOT IN (SELECT * FROM @res)
    ) AS 'inv',
    (
        SELECT ISNULL(@cert, '')
    ) AS 'certIn',
    (
        SELECT ISNULL(@inv, '')
    ) AS 'invIn'

END

GO

And the VBA code which I used is

'Declare variables
Dim CN As Connection
Dim cmd As Command, rsAmnts As Recordset

'Initialise the variables
Set CN = New Connection
Set cmd = New Command

'Open connection
CN.Open ("connection string")

'Call procedure assigning the variable
cmd.ActiveConnection = CN
cmd.CommandText = "valuationReports"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh

'The variable assigned a value
cmd(1) = "TP-15-0020"

'Set Recordset by executing the command i.e. procedure
Set rsAmnts = cmd.Execute

Hope this helps anyone out there

Sign up to request clarification or add additional context in comments.

Comments

0

Step 1: Open the immediate window, paste your code like this and press enter on every line:

enter image description here

Step 2: Write this and see what you get, when you press ENTER:

enter image description here

Step 3: Check the result carefully. Try to take it into the SQL Server and to see the error there.

11 Comments

Did exactly that but it runs perfectly in SQL Server, no errors. in VB.NET just like it does not execute the rsAmnts.Open SQL2, CN line because I checked and the recordset is still closed even after execution
still nothing, trying to shift it to a procedure right now
I shifted the whole query to a procedure and its working okay now, thanks for the help though
How did you shift a query to a procedure?
the adCmdStoredProc is to instruct the vba command that the query string is actually a stored procedure name, the command text is the name of the procedure
|
0

This may not be the direct answer but it won't fit in comments and may solve the issue.

You are using Connection.Open which according to this may not get you a recordset right away: -

Opens a connection to a data source.

And

When used on a client-side Connection object, the Open method doesn't actually establish a connection to the server until a Recordset is opened on the Connection object.

It could be a case of assigning it to a Recordset object exposes it as a recordset.

Whereas with Connection.Execute, according to this will return a recordset: -

Returns a Recordset Object (ADO) object reference.

And

Executes the specified query, SQL statement, stored procedure, or provider-specific text.

What I read from this is that Connection.Open will open a connection, this may not be the case of executing specific commands, but simply opening access to data. Connection.Execute explicitly mentions running queries and commands, so may accept your declarations as well as standard queries.

Quick example of execute: -

Public Sub Sample(ByVal SQL2 As String)
Dim DBConn  As ADODB.Connection
Dim RS      As ADODB.Recordset

Set DBConn = New ADODB.Connection
    DBConn.Open "Provider=SQLOLEDB;Server=[SERVER];Database=[DATABASE];User Id=[USER];Password=[PASSWORD;"
    Set RS = DBConn.Execute(SQL2)
        'RS is a recordset at this point
        RS.Close
    Set RS = Nothing
    DBConn.Close
Set DBConn = Nothing

End Sub

1 Comment

I shifted the whole query to a procedure and its working okay now, thanks for the help though
0

Make sure you check regional settings, this will affect how the data is entered into the DB

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.