Av rating:
Total votes: 40
Total comments: 19


Phil Factor
Writing to Word from SQL Server
06 March 2007

Having helped Robyn with her Excel Workbench, I couldn't get out of my head the idea of achieving the same effect with MS Word. After all, from the data viewpoint, MS Word documents are just a series of paragraphs and tables aren't they? Surely, it should be easy to read and write data between SQL Server and Word.

Robyn backed away nervously at this point, to leave me full rein. There are reams of advice on why it was a very bad idea to do such a thing as read data from Word documents into SQL, and plenty of indignation at the idea of writing to Word. I always smell humbug when I hear this sort of talk. If Microsoft fail to do something properly with a product, one gets quasi-religious pronouncements from everywhere that it is not appropriate to use the product in this way, or it traduces one's architectural design, or it should be done in C #.

Nevertheless, I quickly realized that there were plenty of obstacles in my way. For a start, I was puzzled by the lack of ODBC drivers for Word. You'd have thought that all one has to do is to indicate which table in the document you want to populate, and send it the result of the SQL. You'd be able to read the document attributes as if it was a built-in table and the contents of the paragraphs as if it were another.

The next indication I had that something was really amiss was when I started trying a few simple automation tasks with Word, using OLE Automation in TSQL. Whenever a mistake happened, a warning sound came through the speakers of the server, scaring the life out of a dozing DBA. It looked as if Word was never intended for such connectivity. This was strange, as Excel is so well-mannered in this respect, a tame creature that handles errors obligingly and does exactly what is said in the documentation. I was not emotionally prepared for recalcitrance on the scale I was confronted with.

Some perfectly reasonable OLE methods, taken from fully operational VBA examples, never worked. I waded through reams of example scripts, noting with some alarm the trepidation expressed by the authors of scripts on Technet ('Two tables in a document via automation? Dear me', and 'we employed a stunt double to do the testing'). I could find almost no successful attempts at OLE automation via TSQL. I just had to design around them. I came close to throwing in the towel, but my stubborn streak took over. Dammit, I was going to succeed.

And here, at last, are two stored procedures, too long to show in the body of this article, but attached nevertheless:

  • SpWord_Document_content – extracts the text from an MS Word file into a table of paragraphs, along with the name of the style of the original paragraph
  • spExportToWord – creates a new Word file, and writes results from the SQL expression to a table in Word, with a heading if required.

If you want to follow along and test them out, download them now from the CODE DOWNLOAD link above, or from the direct text file links below.

Reading from Word paragraphs to SQL Server

This SpWord_Document_content T-SQL stored procedure is easy to use. It is a pretty straightforward automation of Word, though I've seen no stored procedure like it anywhere. Remember that you will need to have MS Word installed on the server you are executing the stored procedure from.

drop table #MyContent
Create table #MyContent (
   Paragraph_ID int,
   Style varchar(20),
   Content Varchar(8000))
Insert into #myContent
   Exec spWord_Document_content @documentFile ='c:\FooBar.doc'

In case you are wondering whether it reads any tables and other content that happens to be in the way; it doesn't. It only reads the words of the paragraphs. The difficulties involved in providing a generic Word reader multiply at the point when one considers tables, and it is far easier to automate the saving of the file as text, and then pulling into SQL Server via the automation of Windows.FileSystemObject.

Exporting from SQL Server to Word

The spExportToWord T-SQL stored procedure creates a new Word file, and writes results to a Word table in that file. This allows you to autoformat the results in any of the standard ways that Word allows.

I decided to use ADODB, mainly in order to get the field-names of any result. However, the other advantage was that I could use it to connect to servers anywhere (I administer database-driven websites) without permanent links.

NOTE:
I also had the ambitious idea of allowing you to write several tables, using multiple recordsets from the one query. Sorry. Next time maybe

All you need to run this is to have Word installed on your server, and have configured SQL Server to allow OLE Automation. If you have a trusted connection, and the query is in your current database, then the syntax is simple:

Execute spExportToword @QueryText='MyQuery',
   @documentFile='C:\foobar.doc',@Tableformat='Colourful 1'

Or, if you have SQL Server security then you need to specify the password:

Execute spExportToword @QueryText='MyQuery',
   @SourceUID ='
MyUserID', @SourcePWD='MyPassword'
  
@documentFile='C:\foobar.doc',
  
@Tableformat='Colourful 1'

If you don't like the 'professional' auto format that I chose by default ('colourful 1' is just one of the many built-in auto formats you can see in Word), then try this:

create table sample(
   [ ] varchar(80),
   [Software Sales] varchar(80),
   [Hardware Sales] varchar(80),
   [Consultancy] varchar(80),
   [Total] varchar(80))
insert into sample
   select 'First Quarter','£1940','£567','£765','£3272'
insert into sample
select 'Second Quarter','£15960','£3685','£34000','£53645'
insert into sample
select 'Third Quarter','£39480','£5000','£23000','£67480'
insert into sample
select 'Fourth Quarter','£23960','£3549','£3470','£30979'
insert into sample
select 'Total','£81340','£12801','£61235','£155376'
execute spExportToword @QueryText='Select * from sample',
   @documentFile='C:\report.doc',@Tableformat='Grid 6'

This should result in the following table:

Software Sales

Hardware Sales

Consultancy

Total

First Quarter

£1940

£567

£765

£3272

Second Quarter

£15960

£3685

£34000

£53645

Third Quarter

£39480

£5000

£23000

£67480

Fourth Quarter

£23960

£3549

£3470

£30979

Total

£81340

£12801

£61235

£155376

You can also provide a heading to the table to explain what the data is about.

execute spExportToword @QueryText='Select * from sample',
   @documentFile='C:\report.doc',@Tableformat='Grid 6',
  
@tableHeading='2006 Earnings. The Kamakaze Laxative Company'

If you have a slightly more complex access requirement then you can specify the server, database, userid and password

spExportToword 
@Sourceserver='MyServer',
@SourceDatabase='MyDatabase',
@SourceUID='MyUserID',
@SourcePWD='MyPassword',
@QueryText='Select * from MyTable',
   @documentFile='C:\MyDocument.doc'

You can, of course, get serious about your connection string to get a report from a server managing a distant ecommerce site.

spExportToword @QueryText='spWho',
   @documentFile='C:\remotestuff.doc',
  
@ConnectionString='Driver={SQL Server};
                      Server=xxx.xxx.xxx.xxx;
                      Address=xxx.xxx.xxx.xxx,1433;
                      Network=DBMSSOCN;
                      Database=myDatabaseName;
                      Uid=myUsername;
                      Pwd=myPassword'

Or, if you wish, you can connect to any ODBC source you can think of! The secret is in the connection string.

A few words of caution

Something like this, which is perfectly serviceable for small-scale applications, may not necessarily scale-up – please bear that in mind if you are considering putting this sort of code into a production server.

Whereas Excel is relatively well-behaved, MS Word is notorious for hitting a bug, forgetting that it is being automated as a background task without a user-interface, and popping up a system modal dialog box.

Also, bear in mind that OLE Automation has to be done by a process with extensive login roles. You can't give these sorts of roles to the ordinary user. It is much better to queue up jobs like this and have a scheduled process on SQL Server Agent to execute them, using a login with the correct roles.

Summary

There is much more that can be done, of course. It would not be a big problem to read from Word tables, and I'd have done it for you if I'd been able to think of a useful application. It would also be reasonably easy to write out a mixture of tables and paragraphs into a word file too. It all depends on the requirements of your application. Hopefully, armed with the code I include, it may give you the impetus to try things out.

However get in plenty of sandwiches and Jack Daniels before doing so, as this sort of task is not for the faint-hearted.



This article has been viewed 15311 times.
Phil Factor

Author profile: Phil Factor

Phil Factor (real name withheld to protect the guilty), aka Database Mole, has 25 years of experience with database-intensive applications. Despite having once been shouted at by a furious Bill Gates at an exhibition in the early 1980s, he has remained resolutely anonymous throughout his career. See also :

Search for other articles by Phil Factor

Rate this article:   Avg rating: from a total of 40 votes.


Poor

OK

Good

Great

Must read
 
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: WordML?
Posted by: Anonymous (not signed in)
Posted on: Tuesday, March 06, 2007 at 9:52 PM
Message: You could remove the need for Word (Office) on the server (always a good idea!), by using the Office Open XML standard.

Subject: Problem could be occurred if non-sysadmin members run these sp's
Posted by: Anonymous (not signed in)
Posted on: Wednesday, March 07, 2007 at 12:03 AM
Message: These T-SQL stored procedures are typically designed for members of sysadmin. Lower members cannot run these sp.

Subject: Error whilst Opening the file,
Posted by: Anonymous (not signed in)
Posted on: Friday, March 09, 2007 at 5:18 PM
Message: I am receiving an "Error whilst Opening the file," message when running spWord_Document_content.

After some investigation, I was able to determine that this error was a Microsoft Word - Command Failed. While searching for information on the subject, I read of several users receiving the same message (0x800A1066) when executing Documents.Open().

If anyone has any thoughts/ideas, I would appreciate the input. This stored procedure could open up a lot of doors for our organization, if only I could get it to run property.

System Configuration:
Operating System - Windows Server 2003
SQL Server Version - 2005

Subject: Re: Error whilst Opening the file
Posted by: Phil Factor (view profile)
Posted on: Sunday, March 11, 2007 at 3:42 PM
Message: I reckon that the user account that SQL Server service is using doesn't have rights to create the file in whichever directory it is being created in. Have a look in the Services applet and look at the properties of the SQL Server Service. that will tell you the account that SQL Server is using. Does it have access rights to Word, and to the various directories that Word is using? You'd think Word would come back with a sensible message wouldn't you? I hope that works, since it works fine on my test systems.

Subject: Way to reinforce the stereotype!!
Posted by: Anonymous (not signed in)
Posted on: Monday, March 12, 2007 at 5:53 PM
Message: "Whenever a mistake happened, a warning sound came through the speakers of the server, scaring the life out of a dozing DBA."

Thanks for this.. it makes me so happy that you just reinforced that DBA's do nothing..

-jfc-

Subject: Re: Error whilst Opening the file
Posted by: Anonymous (not signed in)
Posted on: Friday, March 16, 2007 at 1:24 PM
Message: The SQL Server service is running as NETWORK SERVICE on the machine. I added appropriate rights to get a spell checking tutorial to work that I found elsewhere on the web. The sproc still refuses to read the word document from C:\test\test.doc which I gave NETWORK SERVICE full access to.

Any other ideas? I'm stumped...

Subject: various
Posted by: Anonymous (not signed in)
Posted on: Tuesday, March 27, 2007 at 6:25 AM
Message: Can I send reports to word?

Subject: Re: Various
Posted by: Phil Factor (view profile)
Posted on: Tuesday, March 27, 2007 at 8:13 AM
Message: Yes, indeed you can with the stored procedure that I supply with this article. The result is converted into a Word table.

Subject: Re: Way to reinforce the stereotype!!
Posted by: Anonymous (not signed in)
Posted on: Wednesday, April 04, 2007 at 3:57 AM
Message: Only the best DBAs have time to do nothing. Most are too busy running around fighting fires and never quite getting to grips with what it is they should be doing ;-)

Subject: FeedBack
Posted by: Anonymous (not signed in)
Posted on: Wednesday, April 11, 2007 at 7:10 AM
Message: Yes, indeed you can with the stored procedure that I supply with this article. The result is converted into a Word table.

Subject: What about the reverse?
Posted by: Anonymous (not signed in)
Posted on: Friday, May 25, 2007 at 7:37 AM
Message: This may be a simple question, but how to do you access a SQL Server stored procedure from MS Word?

Subject: re: What about the reverse?
Posted by: Phil Factor (view profile)
Posted on: Saturday, May 26, 2007 at 10:49 AM
Message:

You can use Word for all sorts of simple chores such as printing reports by using Word Macros. Word uses VBA and has 'native' support for ODBC so it shouldn't be too tricky to use. Click on (Tools)..(Macro)..(Visual Basic Editor) in Word, and then look up 'OpenDataSource Method' in Visual Basic Help. If you can use VB then it will be a doddle to run up routines for getting reports or doing mail-merge!

A useful article to get you started would be How to automate Word with Visual Basic to create a Mail Merge.

A fascinating technique is described in How to automate Word to perform a client-side Mail Merge using XML from SQL Server

Word should be part of the armoury of every DBA, it is extraordinarily handy for those odd ad-hoc jobs. For ninety percent of the time, it is better to use VBA in Word to pull the data from SQL Server rather than using the 'Push' techniques I describe in this article!


Subject: fields in ms word to ms sql 2000
Posted by: Anonymous (not signed in)
Posted on: Tuesday, July 24, 2007 at 5:15 PM
Message: hi,

haven't tried this as yet but I sure hope it works as I've been searching for somthing like this for ages, I need to get the contents of application forms-into our db from a ms word document

Subject: About the WordML comment
Posted by: SAinCA (view profile)
Posted on: Tuesday, August 21, 2007 at 7:48 PM
Message: The prospect of having to install a licensed copy of Word on our DATABASE Server thrills me to the core (not!). The first post under this very helpful article (the code for which works on my local box perfectly, thanks) cites using WordML as a way of obviating the Word install. 'twould be useful if more detail could be posted on that as XML works fine even in SS2000. Anyone know anything more than "You could remove the need..."?

Subject: About the WordML comment
Posted by: SAinCA (view profile)
Posted on: Wednesday, August 22, 2007 at 11:22 AM
Message: The prospect of having to install a licensed copy of Word on our DATABASE Server thrills me to the core (not!). The first post under this very helpful article (the code for which works on my local box perfectly, thanks) cites using WordML as a way of obviating the Word install. 'twould be useful if more detail could be posted on that as XML works fine even in SS2000. Anyone know anything more than "You could remove the need..."?

Subject: Just out of curiosity . . .
Posted by: RDWilson2 (view profile)
Posted on: Thursday, October 04, 2007 at 11:03 AM
Message: I have a need to store paragraphs of text (in some cases "boiler plate"and in others selectable paragraphs for things like contracts) in a SQL Server database and then extract them, based on selection constraints, to produce a document. Of course, the preferred format that I have been given is a "Word document". Now I am wondering whether this techinique could/would work for pualling the such paragraph-oriented data into a Word doc as paragraphs rather than in the table format.

Subject: spExportToword
Posted by: Anonymous (not signed in)
Posted on: Wednesday, November 28, 2007 at 1:17 PM
Message: There is no SQL code about how to create spExportToword.

Subject: Write in Word Doc in Specfic Place
Posted by: Qasim Nadeem (not signed in)
Posted on: Tuesday, March 11, 2008 at 4:40 AM
Message: please help me if any one know how we can write in word document in specfic place through SQL server.
please replay me on this email qnadeem@abana.com.sa
Thanks in advance.

Subject: for 1 database
Posted by: irvin (view profile)
Posted on: Sunday, October 05, 2008 at 10:20 PM
Message: i already try this code and its working. the problem is, i only can generate 1 table. please tell me how to generate 1 database (with 7000 record).
i am using this script for 1 table :

declare @sql varchar(5000)

set @sql = '
SELECT
[Table Name] = OBJECT_NAME(c.object_id),
[Column Name] = c.name,
[Description] = ex.value
FROM
sys.columns c
LEFT OUTER JOIN
sys.extended_properties ex
ON
ex.major_id = c.object_id
AND ex.minor_id = c.column_id
AND ex.name = ''MS_Description''
WHERE
OBJECTPROPERTY(c.object_id, ''IsMsShipped'')=0
AND OBJECT_NAME(c.object_id) = ''mstusermgmt''
ORDER
BY OBJECT_NAME(c.object_id), c.column_id '

exec spExportToword
@Sourceserver='server',
@SourceDatabase='Data',
@SourceUID='sa',
@SourcePWD='adm',
@QueryText=@sql,
@documentFile='C:\cape deeeee.doc'

i am using this script for all table in database'data' [i am delete this statement : AND OBJECT_NAME(c.object_id) = ''mstusermgmt'']

declare @sql varchar(5000)

set @sql = '
SELECT
[Table Name] = OBJECT_NAME(c.object_id),
[Column Name] = c.name,
[Description] = ex.value
FROM
sys.columns c
LEFT OUTER JOIN
sys.extended_properties ex
ON
ex.major_id = c.object_id
AND ex.minor_id = c.column_id
AND ex.name = ''MS_Description''
WHERE
OBJECTPROPERTY(c.object_id, ''IsMsShipped'')=0

ORDER
BY OBJECT_NAME(c.object_id), c.column_id '

exec spExportToword
@Sourceserver='server',
@SourceDatabase='Data',
@SourceUID='sa',
@SourcePWD='adm',
@QueryText=@sql,
@documentFile='C:\cape deeeee.doc'

and i have this message error :
Msg 50000, Level 16, State 1, Procedure spExportToWord, Line 341
Error whilst Setting the data table cell with Cell(*,1).range.Text,

so, what should i do, please let me know.

thanks before
irvin



 









Phil Factor
To Boldly Ask IT for Development Work
 Phil has always been mystified by the way that, in Science-Fiction films, the crew of space-ships are able to... Read more...



 View the blog
Using the Filtering API with the SQL Comparison SDK
 Red Gate's SQL Comparison SDK provides a means to compare and synchronize database schemas and data... Read more...

SQL Toolbelt 2008: Predominantly an Engineering Task
 The conversion of the Red-Gate tools to be compatible with SQL Server 2008 might not seem, on first... Read more...

Audit Crosschecks
 In this short article, the second of a 2-part series, William suggests a solution, using SQL Data... Read more...

SQL Response: The dim sum interview
 Richard Morris met David and Nigel of the SQL Response team, in a dim sum Restaurant in Cambridge. They... Read more...

SQL Server 2008: Performance Data Collector
 With Performance Data Collector in SQL Server 2008, you can now store performance data from a number of... Read more...

Beginning SQL Server 2005 Reporting Services Part 1
 Steve Joubert begins an in-depth tour of SQL Server 2005 Reporting Services with a step-by-step guide... Read more...

Ten Common Database Design Mistakes
 Database design and implementation is the cornerstone of any data centric project (read 99.9% of... Read more...

Beginning SQL Server 2005 Reporting Services Part 2
 Continuing his in-depth tour of SQL Server 2005 Reporting Services, Steve Joubert demonstrates the most... Read more...

SQL Server Full Text Search Language Features
 SQL Full-text Search (SQL FTS) is an optional component of SQL Server 7 and later, which allows fast... Read more...

Executing SSIS Packages
 Nigel Rivett demonstrates how to execute all SSIS packages in a given folder using either an SSIS... Read more...

Over 150,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.

Join Simple Talk