December 26, 2008 at 1:14 pm
Hi Guys
Hope you all had a very nice christmas.
I am working on a project at the mo that will query my database and put the results in to a spreadsheet and email them out. I have set this up on a local instance and i can run the whole process from the same machine with no problems.
I am however encountering problems when i try and run the same code on from my local machine on a remote instance. It seems that there may be a security issue when creating the worksheet on the remote machine.
I believe that it is a security issue but i cannot figure out what to change.
Any pointers would be appreciated.
Thanks
Steve
December 26, 2008 at 1:42 pm
The server you are working on, whether local or remote, must be logged in as a user that can "see" the spreadsheet using a UNC instead of a mapped drive.
--Jeff Moden
Change is inevitable... Change for the better is not.
December 26, 2008 at 3:29 pm
Thanks for the reply.
I have changed the path from 'C:\severname\test\ExcelExport.xls' to '\\Servername\Test\ExcelExport.xls' and still the same issue. I can access that from both the server and the local machine.
The user that i am logged into the instance as has the sysadmin fixed role. Does it need anything else?
December 26, 2008 at 5:20 pm
Not the login you're using... the login the SQL SERVER is using when it starts up on the network...
--Jeff Moden
Change is inevitable... Change for the better is not.
December 26, 2008 at 5:35 pm
sperry (12/26/2008)
Thanks for the reply.I have changed the path from 'C:\severname\test\ExcelExport.xls' to '\\Servername\Test\ExcelExport.xls' and still the same issue. I can access that from both the server and the local machine.
The user that i am logged into the instance as has the sysadmin fixed role. Does it need anything else?
what Jeff was saying is that when you use something that goes outside of a database...OLE, xp_cmdshell, whatever, the user you logged in with is not used....the user that is used to run the service is used instead:
THAT IS account is used...so if it doesn't have access to a folder the Administrator created locally, or does not login to the network, and this cannot go to a \\UNC\share, you will get a failure with your OLE.
I don't know about others, but I usually create a local or domain Admin named SQLAdmin, with a password that does not expire, and use that to run the service...that way I'm sure it has access we are talking about.
Lowell
December 26, 2008 at 5:47 pm
Thanks for the backup Lowell... I was thinking that I need to include a graphic and a better explanation... you saved me some work. Thanks, ol' friend.
--Jeff Moden
Change is inevitable... Change for the better is not.
December 27, 2008 at 10:41 am
Thanks again guys. I have already found an article pointing to the user rights. I have added the SQL service user into the security group for that server with full control. Still no luck.
The code that i am using is below (it is stolen from the simple talk workbench)
alter PROCEDURE [dbo].[usp_spDMOExportToExcel] (
@SourceServer VARCHAR(30),
@SourceUID VARCHAR(30)=NULL,
@SourcePWD VARCHAR(30)=NULL,
@QueryText VARCHAR(200),
@filename VARCHAR(100),
@WorksheetName VARCHAR(100)='Worksheet1',
@RangeName VARCHAR(80)='MyRangeName'
)
AS
DECLARE @objServer INT,
@objQueryResults INT,
@objCurrentResultSet INT,
@objExcel INT,
@objWorkBooks INT,
@objWorkBook INT,
@objWorkSheet INT,
@objRange INT,
@hr INT,
@Columns INT,
@Rows INT,
@Output INT,
@currentColumn INT,
@currentRow INT,
@ResultSetRow INT,
@off_Column INT,
@off_Row INT,
@command VARCHAR(255),
@ColumnName VARCHAR(255),
@value VARCHAR(255),
@strErrorMessage VARCHAR(255),
@objErrorObject INT,
@Alphabet VARCHAR(27)
SELECT @Alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
IF @QueryText IS NULL
BEGIN
RAISERROR ('A query string is required for spDMOExportToExcel',16,1)
RETURN 1
END
-- Sets the server to the local server
IF @SourceServer IS NULL SELECT @SourceServer = @@servername
SET NOCOUNT ON
SELECT @strErrorMessage = 'instantiating the DMO',
@objErrorObject=@objServer
EXEC @hr= sp_OACreate 'SQLDMO.SQLServer', @objServer OUT
IF @SourcePWD IS NULL OR @SourceUID IS NULL
BEGIN
--use a trusted connection
IF @hr=0 SELECT @strErrorMessage=
'Setting login to windows authentication on '
+@SourceServer, @objErrorObject=@objServer
IF @hr=0 EXEC @hr=sp_OASetProperty @objServer, 'LoginSecure', 1
IF @hr=0 SELECT @strErrorMessage=
'logging in to the requested server using windows authentication on '
+@SourceServer
IF @SourceUID IS NULL AND @hr=0 EXEC @hr=sp_OAMethod @objServer,
'Connect', NULL, @SourceServer
IF @SourceUID IS NOT NULL AND @hr=0
EXEC @hr=sp_OAMethod
@objServer, 'Connect', NULL, @SourceServer ,@SourceUID
END
ELSE
BEGIN
IF @hr=0
SELECT @strErrorMessage = 'Connecting to '''+@SourceServer+
''' with user ID '''+@SourceUID+'''',
@objErrorObject=@objServer
IF @hr=0
EXEC @hr=sp_OAMethod @objServer, 'Connect', NULL,
@SourceServer, @SourceUID, @SourcePWD
END
--now we execute the query
IF @hr=0 SELECT @strErrorMessage='executing the query "'
+@querytext+'", on '+@SourceServer,
@objErrorObject=@objServer,
@command = 'ExecuteWithResults("' + @QueryText + '")'
IF @hr=0
EXEC @hr=sp_OAMethod @objServer, @command, @objQueryResults OUT
IF @hr=0
SELECT @strErrorMessage='getting the first result set for "'
+@querytext+'", on '+@SourceServer,
@objErrorObject=@objQueryResults
IF @hr=0 EXEC @hr=sp_OAMethod
@objQueryResults, 'CurrentResultSet', @objCurrentResultSet OUT
IF @hr=0
SELECT @strErrorMessage='getting the rows and columns "'
+@querytext+'", on '+@SourceServer
IF @hr=0
EXEC @hr=sp_OAMethod @objQueryResults, 'Columns', @Columns OUT
IF @hr=0
EXEC @hr=sp_OAMethod @objQueryResults, 'Rows', @Rows OUT
--so now we have the queryresults. We start up Excel
IF @hr=0
SELECT @strErrorMessage='Creating the Excel Application, on '
+@SourceServer, @objErrorObject=@objExcel
IF @hr=0
EXEC @hr=sp_OACreate 'Excel.Application', @objExcel OUT
IF @hr=0 SELECT @strErrorMessage='Getting the WorkBooks object '
IF @hr=0
EXEC @hr=sp_OAGetProperty @objExcel, 'WorkBooks',
@objWorkBooks OUT
--create a workbook
IF @hr=0
SELECT @strErrorMessage='Adding a workbook ',
@objErrorObject=@objWorkBooks
IF @hr=0
EXEC @hr=sp_OAGetProperty @objWorkBooks, 'Add', @objWorkBook OUT
--and a worksheet
IF @hr=0
SELECT @strErrorMessage='Adding a worksheet ',
@objErrorObject=@objWorkBook
IF @hr=0
EXEC @hr=sp_OAGetProperty @objWorkBook, 'worksheets.Add',
@objWorkSheet OUT
IF @hr=0
SELECT @strErrorMessage='Naming a worksheet as "'
+@WorksheetName+'"', @objErrorObject=@objWorkBook
IF @hr=0
EXEC @hr=sp_OASetProperty @objWorkSheet, 'name', @WorksheetName
SELECT @currentRow = 1
--so let's write out the column headings
SELECT @currentColumn = 1
WHILE (@currentColumn <= @Columns AND @hr=0)
BEGIN
IF @hr=0
SELECT @strErrorMessage='getting column heading '
+LTRIM(STR(@currentcolumn)) ,
@objErrorObject=@objQueryResults,
@Command='ColumnName('
+CONVERT(VARCHAR(3),@currentColumn)+')'
IF @hr=0 EXEC @hr=sp_OAGetProperty @objQueryResults,
@command, @ColumnName OUT
IF @hr=0
SELECT @strErrorMessage='assigning the column heading '+
+ LTRIM(STR(@currentColumn))
+ ' from the query string',
@objErrorObject=@objExcel,
@command='Cells('+LTRIM(STR(@currentRow)) +', '
+ LTRIM(STR(@CurrentColumn))+').value'
IF @hr=0
EXEC @hr=sp_OASetProperty @objExcel, @command, @ColumnName
SELECT @currentColumn = @currentColumn + 1
END
--format the headings in Bold nicely
IF @hr=0
SELECT @strErrorMessage='formatting the column headings in bold ',
@objErrorObject=@objWorkSheet,
@command='Range("A1:'
+SUBSTRING(@alphabet,@currentColumn/26,1)
+SUBSTRING(@alphabet,@currentColumn % 26,1)
+'1'+'").font.bold'
IF @hr=0 EXEC @hr=sp_OASetProperty @objWorkSheet, @command, 1
--now we write out the data
SELECT @currentRow = 2
WHILE (@currentRow <= @Rows+1 AND @hr=0)
BEGIN
SELECT @currentColumn = 1
WHILE (@currentColumn <= @Columns AND @hr=0)
BEGIN
IF @hr=0
SELECT
@strErrorMessage=
'getting the value from the query string'
+ LTRIM(STR(@currentRow)) +','
+ LTRIM(STR(@currentRow))+')',
@objErrorObject=@objQueryResults,
@ResultSetRow=@CurrentRow-1
IF @hr=0
EXEC @hr=sp_OAMethod @objQueryResults, 'GetColumnString',
@value OUT, @ResultSetRow, @currentColumn
IF @hr=0
SELECT @strErrorMessage=
'assigning the value from the query string'
+ LTRIM(STR(@CurrentRow-1)) +', '
+ LTRIM(STR(@currentcolumn))+')' ,
@objErrorObject=@objExcel,
@command='Cells('+STR(@currentRow) +', '
+ STR(@CurrentColumn)+').value'
IF @hr=0
EXEC @hr=sp_OASetProperty @objExcel, @command, @value
SELECT @currentColumn = @currentColumn + 1
END
SELECT @currentRow = @currentRow + 1
END
--define the name range
--Cells(1, 1).Resize(10, 5).Name = "TheData"
IF @hr=0 SELECT @strErrorMessage='assigning a name to a range '
+ LTRIM(STR(@CurrentRow-1)) +', '
+ LTRIM(STR(@currentcolumn-1))+')' ,
@objErrorObject=@objExcel,
@command='Cells(1, 1).Resize('+STR(@currentRow-1) +', '
+ STR(@CurrentColumn-1)+').Name'
IF @hr=0 EXEC @hr=sp_OASetProperty @objExcel, @command, @RangeName
--Now autofilt the columns we've written to
--IF @hr=0 SELECT @strErrorMessage='Auto-fit the columns ',
-- @objErrorObject=@objWorkSheet,
-- @command='Columns("A:'
-- +SUBSTRING(@alphabet,(@Columns / 26),1)
-- +SUBSTRING(@alphabet,(@Columns % 26),1)+
-- '").autofit'
--
--
--IF @hr=0 --insert into @bucket(bucket)
-- EXEC @hr=sp_OAMethod @objWorkSheet, @command, @output out
execute @hr = sp_OAMethod @objWorkSheet, 'Columns.AutoFit'
IF @hr=0 SELECT @command ='del "' + @filename + '"'
IF @hr=0 EXECUTE master..xp_cmdshell @Command, no_output
IF @hr=0
SELECT @strErrorMessage='Saving the workbook as "'+@filename+'"',
@objErrorObject=@objRange,
@command = 'SaveAs("' + @filename + '")'
IF @hr=0 EXEC @hr=sp_OAMethod @objWorkBook, @command
IF @hr=0 SELECT @strErrorMessage='closing Excel ',
@objErrorObject=@objExcel
EXEC @hr=sp_OAMethod @objWorkBook, 'Close'
EXEC sp_OAMethod @objExcel, 'Close'
IF @hr<>0
BEGIN
DECLARE
@Source VARCHAR(255),
@Description VARCHAR(255),
@Helpfile VARCHAR(255),
@HelpID INT
EXECUTE sp_OAGetErrorInfo @objErrorObject,
@source output,@Description output,
@Helpfile output,@HelpID output
SELECT @hr, @source, @Description,@Helpfile,@HelpID output
SELECT @strErrorMessage='Error whilst '
+COALESCE(@strErrorMessage,'doing something')
+', '+COALESCE(@Description,'')
RAISERROR (@strErrorMessage,16,1)
END
EXEC sp_OADestroy @objServer
EXEC sp_OADestroy @objQueryResults
EXEC sp_OADestroy @objCurrentResultSet
EXEC sp_OADestroy @objExcel
EXEC sp_OADestroy @objWorkBooks
EXEC sp_OADestroy @objWorkBook
EXEC sp_OADestroy @objRange
RETURN @hr
When i call this from another stored proc i get this error message.
Msg 50000, Level 16, State 1, Procedure usp_spDMOExportToExcel, Line 250
Error whilst Creating the Excel Application, on C6SERVER13, sp_OAMethod usage: ObjPointer int IN, MethodName varchar IN [, @returnval OUT [, additional IN, OUT, or BOTH params]]
Msg 22051, Level 16, State 1, Line 0
The error handeling being returned by the stored proc leads me to believe that that it is an issue creating the worksheet. Any pointers would be great, i have been going over this for days now.
Thanks
December 27, 2008 at 11:03 am
I believe that I'd post that exact same thing on Simple Talk and let Phil and Robyn have a crack at it... they're the ones that wrote the method to begin with... they should be able to troubleshoot it for you in a jiffy.
--Jeff Moden
Change is inevitable... Change for the better is not.
December 27, 2008 at 12:36 pm
I will do that. Thanks again.
January 7, 2009 at 4:14 am
Hi again.
I didnt manage to get a response from anyone at simple talk. I have narrowed the problem down to security rights.
The account that we use as the service account is in the power user domain group. When i run it i get an error telling me that the excel file could not be created.
If i add that user into the administrators domain group it works.
I have tested this on a number of machines and get the same results on all of them.
i do not want to give this account full administrator rights. Does anyone have any idea which rights i would need to give this ser to allow it to create the file?
Thanks
January 7, 2009 at 5:06 am
sperry (1/7/2009)
Hi again.I didnt manage to get a response from anyone at simple talk. I have narrowed the problem down to security rights.
The account that we use as the service account is in the power user domain group. When i run it i get an error telling me that the excel file could not be created.
If i add that user into the administrators domain group it works.
I have tested this on a number of machines and get the same results on all of them.
i do not want to give this account full administrator rights. Does anyone have any idea which rights i would need to give this ser to allow it to create the file?
Thanks
Hmmmm.... you could make sure that the server itself is logged in as such a user, create a "job" on SQL Server having it log it as that user, and then have the sproc run that job effectively forming a "proxy". That means the ultimate user would have the rights to run the "job" but not the code... that would keep the user from having the rights you want to keep away while still letting them do this one very very specific thing.
--Jeff Moden
Change is inevitable... Change for the better is not.
January 7, 2009 at 6:36 am
No dice.
I have the service account set as the domain user with limited rights. I then set up a job that calls the procedure in question and set the Run As User as the domain administrator (An account that i know works).
Was this correct?
January 7, 2009 at 6:57 am
So as Administrator, it can access the folder with Read/Write permissions, but as it's normal domain rights it can't...I think it goes back to Security permissions on the Folder.
If the folder was created by an administrator login, that user probably can't access it...just check the specific folder(right click...security...note the groups with permission)
if your power user login CREATES the folder, I think your issue goes away.
via TSQL, since it would use your power user rights, make a new directory,so you know that user is the owner/creator
try exec xp_cmdshell 'mkdir C:\ExcelTest'
then use that new folder for the testing of creating the Exceldocument.
I think since the pwer user created it instead of administrator, your issue might go away.
sperry (1/7/2009)
Hi again.I didnt manage to get a response from anyone at simple talk. I have narrowed the problem down to security rights.
The account that we use as the service account is in the power user domain group. When i run it i get an error telling me that the excel file could not be created.
If i add that user into the administrators domain group it works.
I have tested this on a number of machines and get the same results on all of them.
i do not want to give this account full administrator rights. Does anyone have any idea which rights i would need to give this ser to allow it to create the file?
Thanks
Lowell
January 7, 2009 at 7:16 am
Still the same error i am afraid.
The folder was created fine and the service account user was down as the owner.
The original folder that i was using had full control assigned to everybody.
It works for local users, local admins and domain admins but nothing else.
Thanks for the suggestion.
January 7, 2009 at 9:07 am
I have a question about methodology. Why not, instead of OLE automation, use SSIS? It's designed to do this kind of thing. It has no problem whatsoever with creating and e-mailing spreadsheets from SQL data. I've done that dozens of times.
- Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
Property of The Thread
"Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon
Viewing 15 posts - 1 through 15 (of 16 total)
You must be logged in to reply to this topic. Login to reply