使用Open XML SDK 2.0生成Office文档

IT168.com
【IT168 技术文档】我们会利用OpenXML SDK 2.0写程序生成一个Word文档。在这个文档中有一个表含有产品信息。每个产品的名称,类别,价钱和图像都显示在一个表格里。而这些信息又是从后台数据库里提取出来的。下面是几个步骤:
• 添加引用到OpenXML SDK
• 生成一个Word文档
• 定义一个表(Table)和它的列
• 给这个表加一行台头
• 将每个产品信息生成一行添加到表单里
• 将表加入到文档中
备注:在这个程序中我们只更改Program.cs里的程序代码。
1. 在解决方案资源管理器中, 右击 项目CreateDocFromDatabase 然后选中添加引用。
2. 在添加引用对话框中,选择.Net tab,向下滚动,选中DocumentFormat.OpenXml,, 点击确定按钮。
3. 用同样步骤添加对System.Drawing 和 WindowsBase的引用.
备注:如果有多个WindowsBase,选中路径是c:\Program Files\Reference Assemblies\Microsoft \Framework\v3.0\WindowsBase.dll
4. 删除在上一步加入在Main(){ }的程序:在解决方案资源管理器中,右击Program.cs 打开程序编辑页面。删除Main() { }中的所有程序。你的程序应该看上去像是这样:
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CreateDocFromDatabase
{
class Program
{
static void Main(string[] args)
{
}
}
}
5. 将下面的代码段加入到最后一个Using 语句后面;为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | UsingStatement
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
Using DocumentFormat.OpenXml;
Using DocumentFormat.OpenXml.Packaging;
Using DocumentFormat.OpenXml.Wordprocessing;
Using wp = DocumentFormat.OpenXml.Drawing.Wordprocessing;
Using a = DocumentFormat.OpenXml.Drawing;
Using pic = DocumentFormat.OpenXml.Drawing.Pictures;
Using System.IO;
Using System.Drawing;
Your code should look like the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using wp = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using a = DocumentFormat.OpenXml.Drawing;
using pic = DocumentFormat.OpenXml.Drawing.Pictures;
using System.IO;
using System.Drawing;
namespace CreateDocFromDatabase
{
class Program
{
static void Main(string[] args)
{
}
}
}wordend相关阅读:
- 微软Office XML文档标准投票失利 明年再战
- 处理OpenOffice.org基于XML的文档格式
- 支持XML!微软Office Mobile升级
6. 将下面的程序加入到method:static void Main(string[] args)中;为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | OpenDocument
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
// Name the word document
string docName = @"CreateDocFromDatabase.docx";
// Reuse style info from template
File.Copy(@"Template.docx", docName, true);
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(docName, true))
{
}
备注:这一步,我们拷贝一个空文档到debug路径下,给其一个名字,并且用SDK打开文档
7. 将下面的程序加入到method Main() 中的using (WordprocessingDocument myDoc = WordprocessingDocument.Open(docName, true)) {}中;为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | CreateTable
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
// Grab main document part
MainDocumentPart mainPart = myDoc.MainDocumentPart;
Document doc = mainPart.Document;
// Connect to databse
AdventureWorksDataContext db = new AdventureWorksDataContext();
// Create table and add properties
Table table = new Table();
// Header strings for table
string[] headerContent = new[] { "Name", "Subcategory", "Price", "Image" };
// Create row
TableRow header = CreateRow(headerContent, null);
table.AppendChild(header);
备注:这一步,我们生成一个LINQ to SQL类的instance – AdventureWorksDataContext。我们有生成一个Table object。
8. 将以下程序直接加到上一段程序后面;为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | QueryDB
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
var productQuery = from p in db.Product group p by p.ProductID;
int i = 1;
foreach (var product in productQuery)
{
foreach (var item in product)
{
// insert your next code snippet here
}
}
备注:在这一步,我们从AdventureWorks2008 LINQ to SQL类连到AdventureWorks2008数据库,并从中读取数据出来。
9. 将以下程序直接加到上一段程序的inner foreach loop里;为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | ProcessProduct
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
string price = "$";
if (item.ListPrice != 0)
{
// Get data from query
price += Math.Round(item.ListPrice, 2);
string imgId = "rIdImg" + i;
i++;
string[] content = new[] { item.Name,
item.ProductSubcategoryID == null ? null : item.ProductSubcategory.Name,
price };
// Insert the next code snippet here
}
备注:在这一步中,每个产品的价格被四舍五入到小数点后两位。每个产品的Image 都生成一个id。我们也生成一个字串列string array来存储每个产品的名称(name),副类(Subcategory)和价格(price)。
10. 将以下程序直接加到上一段程序的后面,但是要在‘if’语句里面; 为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | ProcessProductImage
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
// Add a new image for every image in DB
ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Gif, imgId);
// Stream image into image part
imagePart.FeedData( new MemoryStream( item.ProductProductPhoto.First().ProductPhoto.LargePhoto.ToArray()));
// Calculate image size for xml
Bitmap bitmap = new Bitmap( new MemoryStream( item.ProductProductPhoto.First().ProductPhoto.LargePhoto.ToArray()));
int widthInEmu, heightInEmu;
CalculateEmus(bitmap, out widthInEmu, out heightInEmu);
// Create a new drawing object based on xml
Drawing d = GenerateDrawing(imgId, item.ProductProductPhoto.First().ProductPhoto.LargePhotoFileName, widthInEmu, heightInEmu);
备注:在这一步中,我们生成了一个ImagePart 的instance,它的类是Gif。它的内容是从数据库中取来的。我们也生成了一个Bitmap对象。同样它里面的数据也是通过计算图形文档的高和宽而得来的。然后我们生成一个Drawing对象,并设置它指向刚才生成的ImagePart的instance。
11. 将以下程序直接加到上一段程序的后面,但是要在‘if’语句里面; 为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | AddRow
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
// Add row
TableRow tr = CreateRow(content, d);
table.AppendChild(tr);
备注:在这一步中,我们生成一个TableRow对象,并把它加到最后我们要生成的文档中。到此,我们已经完成了处理每一个TableRow的步骤。
wordend相关阅读:- 微软Office XML文档标准投票失利 明年再战
- 处理OpenOffice.org基于XML的文档格式
- 支持XML!微软Office Mobile升级
12. 将以下程序加到foreach语句的后面(最外面的那个foreach语句),但是要在using语句的里面; 为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | AddRow.
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
// Append table and save
doc.Body.AppendChild(table);
// Save changes
// this step is not necessary as doc has been configured to automatically save changes
doc.Save();
备注:在这一步中,我们只是把生成的table加到文档中并保存文档。至此我们完成了所有需要加在Main()里的语句。
13. 将以下程序加到method:static void Main(string[] args)的后面,在class Program 的closing bracket (}) 里面;为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | CreateRow.
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
private static TableRow CreateRow(string[] cellText, Drawing d)
{
// create a table row and insert content
TableRow tr = new TableRow();
// Add text
foreach (string s in cellText)
{
TableCell tc = new TableCell();
Paragraph p = new Paragraph();
Run r = new Run();
Text t = new Text();
t.Text = s;
r.AppendChild(t);
p.AppendChild(r);
tc.AppendChild(p);
tr.AppendChild(tc);
}
// Add image
if (d != null)
{
TableCell tcDrawing = new TableCell();
Paragraph pDrawing = new Paragraph();
Run rDrawing = new Run();
rDrawing.AppendChild(d);
pDrawing.AppendChild(rDrawing);
tcDrawing.AppendChild(pDrawing);
tr.AppendChild(tcDrawing);
}
return tr;
}
备注:这是一个辅助Method。我们生成每一个TableRow的内容,分别用TableCell来存放产品的名称,类别,价钱和图像(Name, Subcategory Name, Price and Drawing)。每个TableCell有是用Paragraph和Run组成的。一个Run是OpenXML中最基本的单位。
14. 将以下程序直接加到上一段程序的后面,也是要在class Program 的closing bracket (}) 里面;为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | GenerateDrawing.
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
public static Drawing GenerateDrawing(string relId, string imageName, int width, int height)
{
Drawing element =
new Drawing(
new wp.Inline(
new wp.Extent() { Cx = width, Cy = height },
new wp.EffectExtent() {
LeftEdge = 19050L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L },
new wp.DocProperties() { Id = (UInt32Value)1U, Name = imageName, Description = imageName },
new wp.NonVisualGraphicFrameDrawingProperties(
new a.GraphicFrameLocks() { NoChangeAspect = true }),
new a.Graphic(
new a.GraphicData(
new pic.Picture(
new pic.NonVisualPictureProperties(
new pic.NonVisualDrawingProperties() { Id = (UInt32Value)0U, Name = imageName },
new pic.NonVisualPictureDrawingProperties()),
new pic.BlipFill(
new a.Blip() { Embed = relId, CompressionState = a.BlipCompressionValues.Print },
new a.Stretch(
new a.FillRectangle())),
new pic.ShapeProperties(
new a.Transform2D(
new a.Offset() { X = 0L, Y = 0L },
new a.Extents() { Cx = width, Cy = height }),
new a.PresetGeometry(
new a.AdjustValueList()
) { Preset = a.ShapeTypeValues.Rectangle }))
) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" })
) { DistanceFromTop = (UInt32Value)0U, DistanceFromBottom = (UInt32Value)0U, DistanceFromLeft = (UInt32Value)0U, DistanceFromRight = (UInt32Value)0U });
return element;
}
备注:这也是一个辅助Method。在这段程序中我们根据OpenXML文档规范生成一个Drawing对象。这个Drawing对象会被包含在我们上面生成的TableRow中的最后一个TableCell里面。
wordend相关阅读:- 微软Office XML文档标准投票失利 明年再战
- 处理OpenOffice.org基于XML的文档格式
- 支持XML!微软Office Mobile升级
15. 将以下程序直接加到上一段程序的后面,也是要在class Program 的closing bracket (}) 里面;为避免手工输入这些语句,可以通过插入代码段 | My Code Snippets | CalculateEmus.
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
private static void CalculateEmus(Bitmap bitmap, out int widthInEmu, out int heightInEmu)
{
float verticalResolution = bitmap.VerticalResolution;
float horizontalResolution = bitmap.HorizontalResolution;
int width = bitmap.Size.Width;
int height = bitmap.Size.Height;
float widthInInches = (float)width / horizontalResolution;
float heightInInches = (float)height / verticalResolution;
widthInEmu = (int)(widthInInches * 914400);
heightInEmu = (int)(heightInInches * 914400);
}
备注:这个辅助程序将产品图像的高和宽转换成用emu作为单位的值。EMU是English metric Unit的缩写,被用于OpenXML的文档规范。至此所有程序代码已经添加完毕。
16. 将每个Method的代码隐藏起来,你的程序代码编辑窗口应该看上去像这样:
17. 现在编辑解决方案:在解决方案资源管理器中,右击项目CreateDocFromDatabase ,选中菜单选项生成。编辑应该通过无误。
18. 现在在运行程序之前我们要准备必须的文档:将文档Template.docx 从路径 c:\HOL\OFCHOL245\Resources\拷贝到c:\HOL\OFCHOL245\CreateDocFromDatabase\bin\Debug。可以通过以下几步完成:
·在Windows的任务栏(taskbar)中点击资源管理器图标打开资源管理器(从左边数第三个图标)
·在资源管理器中,在上方的路径中填入c:\HOL\OFCHOL245\Resources
·右击文档Template.docx,在菜单中选中复制。
·回到Visual Studio 2008,在解决方案资源管理器中,点击显示所有文件图标
·在解决方案资源管理器中,展开CreateDocFromDatabase | bin | Debug;右击Debug,在菜单中选择粘贴将Template.docx粘贴在bin\debug路径里。
- 微软Office XML文档标准投票失利 明年再战
- 处理OpenOffice.org基于XML的文档格式
- 支持XML!微软Office Mobile升级