SQL error: Re: Error 3704: Operation is not allowed when the object is closed

rpaulson

Well-known Member
Joined
Oct 4, 2007
Messages
1,376
Hello all SQL guru's

I have been using excel VBA for about a year now to retrieve data from out SQL server. I can write some basic SQL strings and select the data I want to return it to my sheet without any issues.

I am now trying to pass a much more complex SQL string that was written some years ago by someone who is no longer available to us. The SQL string work fine inside of SQL Server Management Studio.

When I try to run it in my VBA I get "Error 3704: Operation is not allowed when the object is closed" I did some research and added "SET NOCOUNT ON" to my SQL, but know help.

I am willing to share any information needed to get this working.

-Ross
 

Excel Facts

Format cells as currency
Select range and press Ctrl+Shift+4 to format cells as currency. (Shift 4 is the $ sign).
I think we'd need to see the code (with error line highlighted) and the SQL statement in question.
 
Upvote 0
Here is the VBA code
VBA Code:
Sub GetQueryResults(SQLString As String, Dump_Sheet As Worksheet) 'link to the database as ready only and rerung the dataset as RS
'https://www.wiseowl.co.uk/vba-macros/videos/vba-ado-net-recordsets/ado-execute-sql-query-file/
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    
    Set cn = New ADODB.Connection
    
    cn.ConnectionString = _
        "Provider=MSOLEDBSQL;" & _
        "Server=128.127.2.87;" & _
        "Database=PDI_Warehouse_2064_01;" & _
        "UID=user;" & _
        "PWD=password;" & _
        "Connection Timeout=100"

   If cn.State = adStateOpen Then cn.Close
    cn.Open
     
    Set rs = New ADODB.Recordset
    
    rs.ActiveConnection = cn
    rs.Source = SQLString
    rs.CursorType = adOpenForwardOnly
    rs.LockType = adLockReadOnly
    
    rs.Open
    
Dump_Sheet.Range("A2").CopyFromRecordset rs

rs.Close
cn.Close

here is the SQL String that i am sending. (I do NOT understand most of it. as its abouve my pay grade)
SQL:
  --Scripts for Gallons sold Every Hour
  --This is a demanding script that may take time if the date range is too wide 
  --Designed for optimization
  Use PDI_Warehouse_2064_01
 Go


DECLARE @EntStartDate AS DATETIME,  @EntEndDate AS DATETIME
  DECLARE @SiteID as Varchar(15)
  DECLARE @ShowValuesWithNoSales  as BIT


  --Set the Date range needed.
  SET @EntStartDate = '03/11/2023'
  SET @EntEndDate  = '03/11/2023'
  --SET @SiteID   = '6' 
  SET @SiteID   = '79'  
   --Enter the specific site ID between the single quote  or 'ALL' to return all sites.
   --e.g SET @SiteID = '6'   for Site_ID 6
  

  -- Set this Option to 0 if do not want to show any hours that have no Fuel Gallon Sales. 
  -- Set this Option to 1 If show all hours of the day. 
  SET @ShowValuesWithNoSales = 0  
      

  -- Get MB Headers
  -------------------------------------------------------------------------
  --Get all MarketBasket_Header_Key involved
  IF OBJECT_ID(N'tempdb..#MBHeaderKeys', N'U') IS NOT NULL DROP TABLE #MBHeaderKeys
  CREATE TABLE #MBHeaderKeys
  (
   MarketBasket_Header_Key decimal(15,0),
   calendar_key   decimal(10,0),
   organization_key  int, 
   timeofday_key   int
  )
  CREATE INDEX MBX1 ON #MBHeaderKeys(MarketBasket_Header_Key)

  --Get only outside sales MBH.Inside_Sales_Flag = 0
  INSERT INTO #MBHeaderKeys



  SELECT MBH.MarketBasket_Header_Key, MBH.calendar_key, MBH.organization_key,  MBH.timeofday_key
  FROM MarketBasket_Header MBH (NoLock)
  INNER JOIN organization_view O (NoLock)
   ON O.organization_key = MBH.organization_key 
   AND  ( (@SiteID = 'All') OR (@SiteID <> 'All' AND O.Site_ID = @SiteID) )
  WHERE EXISTS ( SELECT 1 FROM Calendar C (NoLock) 
      WHERE C.calendar_key = MBH.calendar_key 
      AND C.Day_Date BETWEEN @EntStartDate 
      AND @EntEndDate 
      AND MBH.Inside_Sales_Flag = 0
      AND MBH.Total_Quantity <> 0 )
  ORDER BY MBH.calendar_key, organization_key, MarketBasket_Header_Key


  --SELECT * FROM #MBHeaderKeys
  
  IF OBJECT_ID(N'tempdb..#Temp_Hourly_Items', N'U') IS NOT NULL DROP TABLE #Temp_Hourly_Items 
   CREATE TABLE #Temp_Hourly_Items
    (
   calendar_Key      int,    
   organization_key     int,   
   timeofday_key                       int,
   timeofday_hour      INT, 
   Product_Key       int,
   Item_Desc       Varchar(50),  
   Item_Type       int,  
   Quantity_Sold      decimal(18, 2),
   Extended_Retail      decimal(18, 2)
    )
  CREATE INDEX MBX1 ON #Temp_Hourly_Items (organization_key, calendar_Key)

  --Limit sales to only fuel
  INSERT INTO #Temp_Hourly_Items
  SELECT 
    MLI.calendar_key,
    MLI.organization_key,
    MLI.TimeOfDay_Key,
    T.timeofday_hour,
    MLI.Product_Key,
    P.Item_Desc,
    MLI.Item_Type,
    MLI.Quantity_Sold,
    MLI.Extended_Retail
  FROM MarketBasket_Line_Items MLI (NoLock)
  INNER JOIN FuelProduct P (NoLock)
   ON P.Product_Key = MLI.Product_Key
  INNER JOIN timeofday T (NoLock)
   ON T.timeofday_key = MLI.TimeOfDay_Key
  WHERE EXISTS ( SELECT 1 FROM #MBHeaderKeys MBH 
      WHERE MBH.MarketBasket_Header_Key = MLI.MarketBasket_Header_Key 
      AND MBH.Organization_Key = MLI.Organization_Key 
      AND MLI.Item_Type = 2) --fuel sales only
  ORDER BY MLI.calendar_key, MLI.organization_key

  SET NOCOUNT ON;
  set ANSI_WARNINGS OFF
  --Create a table with all the hours 
  IF OBJECT_ID(N'tempdb..#All_Hour_Items ', N'U') IS NOT NULL DROP TABLE #All_Hour_Items 
   CREATE TABLE #All_Hour_Items 
    (
   calendar_Key      int,    
   organization_key     int,
   Site_id        Varchar(50),
   Site_desc       Varchar(50),
   [Date]        Date,
   Day_Of_Week       Varchar(50),
   timeofday_hour      INT, 
   Item_Desc       Varchar(50),
   Product_Key       INT, 
   Gallons_Sold      decimal(18, 2),
   Fuel_Sales       decimal(18, 2),
   RowNum        int identity(1,1)
    )
  CREATE INDEX MBX1 ON #All_Hour_Items  (organization_key, calendar_Key, timeofday_hour)
  
  INSERT INTO #All_Hour_Items 
  SELECT distinct
    A.calendar_Key,
    A.organization_key,
    O.Site_id,
    O.Site_desc,
    [Date]   = CAST(C.Day_Date as Date),
    Day_Of_Week,
    TOD.timeofday_hour ,
    Grade   = A.Item_Desc,
    A.Product_Key,
    Gallons_Sold = NULL,
    Fuel_Sales  = NULL
  FROM #Temp_Hourly_Items A
  INNER JOIN organization_view O (NoLock)
   ON O.organization_key = A.organization_key
  INNER JOIN Calendar C (NoLock)
   ON C.calendar_key = A.calendar_key
  CROSS JOIN (SELECT DISTINCT timeofday_hour FROM timeofday) tod
  ORDER BY O.Site_id,  A.calendar_Key, TOD.timeofday_hour , A.Product_Key


  
  --Update #All_Hour_Items  with gallon sales
  UPDATE #All_Hour_Items SET Gallons_Sold = B.Gallons_Sold, Fuel_Sales = B.Fuel_Sales
  FROM #All_Hour_Items A
  INNER JOIN ( SELECT DISTINCT
        A.organization_key,
        A.calendar_Key,
        timeofday_hour,
        Item_Desc,
        Gallons_Sold = SUM(Quantity_Sold),
        Fuel_Sales  = SUM(Extended_Retail)
      FROM #Temp_Hourly_Items A
      INNER JOIN organization_view O (NoLock)
       ON O.organization_key = A.organization_key
      INNER JOIN Calendar C (NoLock)
       ON C.calendar_key = A.calendar_key
      GROUP BY A.organization_key, A.calendar_Key, A.timeofday_hour, A.Item_Desc
     ) B
   ON A.calendar_Key =B.calendar_Key
   AND A.organization_key = B.organization_key
   AND A.timeofday_hour = B.timeofday_hour
   AND A.Item_Desc = B.Item_Desc

  IF @ShowValuesWithNoSales <> 1
  BEGIN
   DELETE FROM #All_Hour_Items WHERE (Gallons_Sold IS NULL AND Fuel_Sales IS NULL)
  END


 --Output what you want
 SELECT Site_id
   ,Site_desc
   ,[Date]
   ,Day_Of_Week
   ,Hour_Of_Day  = timeofday_hour + 1
   ,Fuel_Grade   = Item_Desc
   ,Gallons_Sold
   ,Fuel_Sales
 FROM #All_Hour_Items ORDER BY RowNum
 
 --Delete all created Temp Tables created
IF OBJECT_ID(N'tempdb..#MBHeaderKeys', N'U') IS NOT NULL DROP TABLE #MBHeaderKeys
IF OBJECT_ID(N'tempdb..#Temp_Hourly_Items', N'U') IS NOT NULL DROP TABLE #Temp_Hourly_Items 
IF OBJECT_ID(N'tempdb..#All_Hour_Items ', N'U') IS NOT NULL DROP TABLE #All_Hour_Items

thanks for Looking
-Ross
 
Upvote 0
The SET NOCOUNT ON line needs to be at the beginning.
 
Upvote 0
If you comment out those last three DROP TABLE lines, does it then work?
 
Upvote 0
Hate to be the bearer of bad news.

Remove last 3 DROP TABLE lines and still error.
 
Upvote 0
Just to check - it's the same error? Can you post the full revised SQL just so I can check it?
 
Upvote 0
SET NOCOUNT ON;
--Scripts for Gallons sold Every Hour
--This is a demanding script that may take time if the date range is too wide
--Designed for optimization
Use PDI_Warehouse_2064_01
--Go

DECLARE @EntStartDate AS DATETIME, @EntEndDate AS DATETIME
DECLARE @SiteID as Varchar(15)
DECLARE @ShowValuesWithNoSales as BIT




--Set the Date range needed.
SET @EntStartDate = '03/11/2023'
SET @EntEndDate = '03/11/2023'
--SET @SiteID = '6'
SET @SiteID = '79'
--Enter the specific site ID between the single quote or 'ALL' to return all sites.
--e.g SET @SiteID = '6' for Site_ID 6


-- Set this Option to 0 if do not want to show any hours that have no Fuel Gallon Sales.
-- Set this Option to 1 If show all hours of the day.
SET @ShowValuesWithNoSales = 0


-- Get MB Headers
-------------------------------------------------------------------------
--Get all MarketBasket_Header_Key involved
IF OBJECT_ID(N'tempdb..#MBHeaderKeys', N'U') IS NOT NULL DROP TABLE #MBHeaderKeys
CREATE TABLE #MBHeaderKeys
(
MarketBasket_Header_Key decimal(15,0),
calendar_key decimal(10,0),
organization_key int,
timeofday_key int
)
CREATE INDEX MBX1 ON #MBHeaderKeys(MarketBasket_Header_Key)

--Get only outside sales MBH.Inside_Sales_Flag = 0
INSERT INTO #MBHeaderKeys
SELECT MBH.MarketBasket_Header_Key, MBH.calendar_key, MBH.organization_key, MBH.timeofday_key
FROM MarketBasket_Header MBH (NoLock)
INNER JOIN organization_view O (NoLock)
ON o_Organization_key = MBH.organization_key
AND ( (@SiteID = 'All') OR (@SiteID <> 'All' AND O.Site_ID = @SiteID) )
WHERE EXISTS ( SELECT 1 FROM Calendar C (NoLock)
WHERE C.calendar_key = MBH.calendar_key
AND C.Day_Date BETWEEN @EntStartDate
AND @EntEndDate
AND MBH.Inside_Sales_Flag = 0
AND MBH.Total_Quantity <> 0 )
ORDER BY MBH.calendar_key, organization_key, MarketBasket_Header_Key

--SELECT * FROM #MBHeaderKeys

IF OBJECT_ID(N'tempdb..#Temp_Hourly_Items', N'U') IS NOT NULL DROP TABLE #Temp_Hourly_Items
CREATE TABLE #Temp_Hourly_Items
(
calendar_Key int,
organization_key int,
timeofday_key int,
timeofday_hour INT,
Product_Key int,
Item_Desc Varchar(50),
Item_Type int,
Quantity_Sold decimal(18, 2),
Extended_Retail decimal(18, 2)
)
CREATE INDEX MBX1 ON #Temp_Hourly_Items (organization_key, calendar_Key)

--Limit sales to only fuel
INSERT INTO #Temp_Hourly_Items
SELECT
MLI.calendar_key,
MLI.organization_key,
MLI.TimeOfDay_Key,
T.timeofday_hour,
MLI.Product_Key,
P.Item_Desc,
MLI.Item_Type,
MLI.Quantity_Sold,
MLI.Extended_Retail
FROM MarketBasket_Line_Items MLI (NoLock)
INNER JOIN FuelProduct P (NoLock)
ON P.Product_Key = MLI.Product_Key
INNER JOIN timeofday T (NoLock)
ON T.timeofday_key = MLI.TimeOfDay_Key
WHERE EXISTS ( SELECT 1 FROM #MBHeaderKeys MBH
WHERE MBH.MarketBasket_Header_Key = MLI.MarketBasket_Header_Key
AND MBH.Organization_Key = MLI.Organization_Key
AND MLI.Item_Type = 2) --fuel sales only
ORDER BY MLI.calendar_key, MLI.organization_key


--Create a table with all the hours
IF OBJECT_ID(N'tempdb..#All_Hour_Items ', N'U') IS NOT NULL DROP TABLE #All_Hour_Items
CREATE TABLE #All_Hour_Items
(
calendar_Key int,
organization_key int,
Site_id Varchar(50),
Site_desc Varchar(50),
[Date] Date,
Day_Of_Week Varchar(50),
timeofday_hour INT,
Item_Desc Varchar(50),
Product_Key INT,
Gallons_Sold decimal(18, 2),
Fuel_Sales decimal(18, 2),
RowNum int identity(1,1)
)
CREATE INDEX MBX1 ON #All_Hour_Items (organization_key, calendar_Key, timeofday_hour)

INSERT INTO #All_Hour_Items
SELECT distinct
A.calendar_Key,
A.organization_key,
O.Site_id,
O.Site_desc,
[Date] = CAST(C.Day_Date as Date),
Day_Of_Week,
TOD.timeofday_hour ,
Grade = A.Item_Desc,
A.Product_Key,
Gallons_Sold = NULL,
Fuel_Sales = NULL
FROM #Temp_Hourly_Items A
INNER JOIN organization_view O (NoLock)
ON o_Organization_key = A.organization_key
INNER JOIN Calendar C (NoLock)
ON C.calendar_key = A.calendar_key
CROSS JOIN (SELECT DISTINCT timeofday_hour FROM timeofday) tod
ORDER BY O.Site_id, A.calendar_Key, TOD.timeofday_hour , A.Product_Key



--Update #All_Hour_Items with gallon sales
UPDATE #All_Hour_Items SET Gallons_Sold = B.Gallons_Sold, Fuel_Sales = B.Fuel_Sales
FROM #All_Hour_Items A
INNER JOIN ( SELECT DISTINCT
A.organization_key,
A.calendar_Key,
timeofday_hour,
Item_Desc,
Gallons_Sold = SUM(Quantity_Sold),
Fuel_Sales = SUM(Extended_Retail)
FROM #Temp_Hourly_Items A
INNER JOIN organization_view O (NoLock)
ON o_Organization_key = A.organization_key
INNER JOIN Calendar C (NoLock)
ON C.calendar_key = A.calendar_key
GROUP BY A.organization_key, A.calendar_Key, A.timeofday_hour, A.Item_Desc
) B
ON A.calendar_Key =B.calendar_Key
AND A.organization_key = B.organization_key
AND A.timeofday_hour = B.timeofday_hour
AND A.Item_Desc = B.Item_Desc

IF @ShowValuesWithNoSales <> 1
BEGIN
DELETE FROM #All_Hour_Items WHERE (Gallons_Sold IS NULL AND Fuel_Sales IS NULL)
END

--Output what you want
SELECT Site_id
,Site_desc
,[Date]
,Day_Of_Week
,Hour_Of_Day = timeofday_hour + 1
,Fuel_Grade = Item_Desc
,Gallons_Sold
,Fuel_Sales
FROM #All_Hour_Items ORDER BY RowNum
 
Upvote 0
not sure why, But i think I found it.

had to turn off the line below, and now it appears to work.

Use PDI_Warehouse_2064_01

thanks for you help.
 
Upvote 0

Forum statistics

Threads
1,214,918
Messages
6,122,255
Members
449,075
Latest member
staticfluids

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top