http://www.cnblogs.com/aiya/articles/268974.html
1. 概述
OpenOffice.org 2.0于近日已经发布了,这是一个里程碑式的新版本,包括了很多的新的特征和功能。在2000年的时候,Sun公司将其开发的StarOffice的源代码交给了OpenOffice.org来维护,标志着StarOffice实现了开源,OpenOffice.org正式诞生了。OpenOffice.org的诞生虽然没有给MS Office的市场带来什么特别大的影响,但是其对于开发人员的意义却是相当的巨大,因为开发者通过OpenOffice.org可以学习和了解很多有用的技术,这些技术包括编程技巧、组件技术、文档格式。在OpenOffice.org提供的技术中,其使用的组件技术显得很独特,而且与MS Office使用的COM组件技术有过之而无不及。
在OpenOffice.org 2.0版本之前,开发者可以使用C++、Java、Python和OLE自动化等语言和技术来开发关于OpenOffice.org的应用。随着CLR和.Net框架技术的出现和普及,OpenOffice.org开发组亦开始计划对CLR和.Net框架提供支持,并在2.0版本内提供了测试的库和一些实例程序。本文就是在此基础上向大家介绍一些关于OpenOffice.org的组件技术、开发技术的相关知识。
2. OpenOffice.org的可编程架构
2.1. 使用UNO进行编程
UNO(Universal Network Objects)是OpenOffice.org的核心组件技术。开发者通过UNO技术可以跨过编程语言、组件技术、系统平台和网络平台来使用各种各样的组件。目前,UNO技术可以用于Linux、Solaris、Windows、PowerPC、FreeBSD以及Mac OS X,其他平台的移植工作目前也正在进行中。UNO支持的编程语言包括Java、C++、Python和OpenOffice.org Basic(OpenOffice.org实现的类似于VBA的宏语言),另外通过微软的COM技术,UNO可以在其他很多的支持COM的语言中使用。
UNO技术的目标是提供一种网络对象的环境,而这个环境并不依赖于特定的编程语言和平台。UNO通过以下几个基础架构技术来实现这样的目标:
l UNO对象由类似CORBAIDL和MIDL的UNOIDL(UNO Interface Definition Language)来定义。由UNOIDL定义独立于编程语言的对象头文件以及库文件可以用于生成目标语言的实现。经过编译和打包的UNO对象可被称作为组件,这些组件必须提供由UNO上下文环境支持的各种接口。
l 在目标环境中,UNO使用工厂模式来实现对象的实例化,这些组件工厂被称作服务管理器(Service Manager)。服务管理器维护着包括注册对象信息的数据库,这些已经注册的对象由其名称标识并且可以根据其名称来重新建立对象实例。服务管理器在Linux平台上向操作系统提出建立由C++编写的对象的实例的请求,或者可以通过调用Java虚拟机来实例化某个对象。这些过程对于开发者来说都是透明的,而且并不依赖于实现组件的编程语言。而这一过程中,对象之间的通讯都是通过UNOIDL定义的接口来进行的。
l UNO使用桥接技术在进程之间、在使用不同语言编写的组件之间来实现方法的调用和返回值的接受。远程桥接技术使用支持套接字和管道的URP(UNO Remote Protocol)来进行通讯。桥接的两端必须都是UNO上下文环境,因此特定语言实现的UNO运行时必须连接到由其他编程语言实现的UNO运行进程。这些运行时不同的编程语言有不同的版本。
l 在UNO运行时环境中,大部分对象可以进行相互通讯。
关于UNO技术更多的内容请参见《OpenOffice.org开发者指南》中关于UNO组件技术的部分。
2.2. 创建到OpenOffice.org的连接
UNO中使用服务管理器来实现任务,服务管理器可以视为提供服务创建活动的工厂模式的实现。服务则可以视为由UNO对象提供的某种功能,例如,以下是几类典型的服务:
l com.sun.star.frame.Desktop主要负责维护已经打开的各种文档,其职责包括打开文档、获取已经打开的文档以及访问所有已经打开的文档。
l com.sun.star.configuration.ConfigurationProvider负责访问OpenOffice.org的配置。
l com.sun.star.sdb.DatabaseContext负责管理在OpenOffice.org中注册的数据库信息。
l com.sun.star.system.SystemSellExecute负责执行平台命令以及使用指定的外部应用程序打开某种类型的文档。
l com.sun.star.text.GlobalSettings负责管理文本文档全局设置、打印机设置等等。
图1 服务和服务管理器的关系
图1很好地概括了服务和服务管理器之间的关系,服务管理器有很多服务构成,也就是服务管理器通过其拥有的各种对象来提供各种服务,也正是通过服务,应用程序才能够访问由众多对象组件提供的各种功能,这些概念将在实际的编程中得到进一步的加强。在下面的例子中,我们也可以看到,连接OpenOffice.org实际上就是为了获得关于服务管理器的引用,应用程序拥有了服务管理器之后,便可以获得服务管理器提供的各项服务。下面就让我们结合连接OpenOffice.org的示例代码来进一步了解服务管理器、服务以及对象之间的关系。
在各个示例程序中,一般都需要引用以下的几个库:
接着就让我们看看怎样连接到OpenOffice.org来获取服务管理器的引用,示例代码如下:
代码片断2展示了怎样通过工具类连接到OpenOffice.org后获取组件上下文,进而获得服务管理器,其中m_xContext变量是XComponentContext类型的,该类型封装了组件上下文的基础功能,其核心功能便是提供服务管理器的引用。XMultiServiceFactory接口便是提供服务管理器功能的接口了,我们在下面的实例中将利用它来体验OpenOffice.org的各种可编程的特性。
3. OpenOffice.org中的电子表格
3.1. 电子表格的对象模型
使用MS Office的对象模型进行编程的朋友对电子表格的内部模型应该是相当的熟悉,OpenOffice.org电子表格的对象模型虽然与MS Office的不太一样,但是在大多数方面还是非常的相似的,因此那些熟悉Excel内部模型的朋友熟悉OpenOffice.org的模型时肯定不是特别的困难。下面我们就使用《OpenOffice.org开发者指南》中提供的模型图片来看看电子表格的对象模型。
如图2中所示,图形上部的服务管理器提供了电子表格文档模型来提供与模型相关的各种服务,这再一次应证了上文中述及的服务管理器的基本模型。电子表格文档模型提供了各种服务,包括工作簿容器服务、内部服务管理器、绘制页管理服务、上下文属性服务以及关于样式设置的服务。电子表格文档的核心服务是工作簿容器服务,这项服务提供了工作簿、工作表管理的各项功能。每个工作簿中可以包含多个工作表,并且可以往工作簿中添加工作表,当然也可以进行其他类似的删除、命名等操作。其他类型的服务在这里也不在赘述,请读者参阅《OpenOffice.org开发者指南》。在下面几小节中我将使用示例代码来详述这些对象、模型以及它们之间的关系,相信随着读者的深入阅读对这些模型以及关系会有全面而深刻的认识。
图2 电子表格内部模型
3.2. 添加新的工作薄
在添加新的工作簿之前,我们自然需要拥有电子表格文档的引用,而这是通过对XComponentLoader接口的相关方法调用而达到的,看代码片断3:
代码片断3中的mxMSFactory变量是XMultipeServiceFactory类型的,它可以通过对代码片断2中的ConnectTo方法的调用来获取。代码中使用了XMultipeServiceFactory接口类型的createInstance方法来根据对象类型字符串创建了对Desktop的引用,如上文中述及的Desktop对象负责管理OpenOffice.org文档的打开、关闭等操作,负责管理各种已经打开的文档。获得了Desktop对象的引用之后,我们便可以通过调用loadComponentFromURL方法来新建空白的电子文档,并且把电子文档接口的引用返回给方法的调用者。
3.3. 添加新的工作表
添加完新的工作簿并且获得了工作簿的引用后,我们就可以使用工作簿对象拥有的方法来完成新的工作表的添加,示例代码如下:
代码片断4中的变量mxDocument是XSpreadsheetDocumnet类型的。代码中首先调用XSpreadsheetDocumnet接口提供的getSheets方法来获取当前工作簿拥有的工作表集合,然后调用工作表集合提供的insertNewByName方法根据aName和nIndex参数来向工作簿中插入新的工作表,并且将新的工作表的引用作为方法的返回值返回给调用者。
3.4. 获取单元格
开发者拥有工作表的引用之后,便可以进行工作表的各种操作了。工作表中的单元格是由XCell和XCellRange来表示的,前者表示单个单元格,而后者表示一系列的单元格,XCellRange本身就包含了多个XCell。XSpreadsheet接口本身就支持XSheetCellRange接口,而XSheetCellRange接口拥有getCellByPosition、getCellRangeByPosition、getCellByName和getCellRangeByName等方法来获取XCell和XCellRange,关于这些方法的应用在3.5小节中的代码中会涉及到。需要说明的是ByPosition之类的方法是使用电子表格的行列绝对地址进行访问的,而ByName之类的方法是使用电子表格的命名地址进行访问的,典型的命名地址如“A1:E5”是指工作表内自A1单元格起至E5单元格止的矩形区域内的所有单元格。
3.5. 设置单元格格式
OpenOffice.org电子表格中的单元格格式设置与MS Office相比采用了不同的方法,OpenOffice.org采用的方法是将一揽子属性置于一个属性集合中,然后将该属性集合添加到单元格的属性集合中,看下面的代码:
4. 结语
OpenOffice.org无论如何也算大型软件了,这一篇文章也不足以描绘其全貌,不过能够通过它来向大家介绍OpenOffice.org的各项功能也是不错的。多多的研究,多多的写东西和大家分享技术的快乐!
2 {
3 XPropertySet xPropSet = null ;
4 XCellRange xCellRange = null ;
5 // 设置单元格的边界
6 xCellRange = xSheet.getCellRangeByName( aRange );
7 xPropSet = (XPropertySet) xCellRange;
8 BorderLine aLine = new BorderLine();
9 aLine.Color = 0x99CCFF ;
10 aLine.InnerLineWidth = aLine.LineDistance = 0 ;
11 aLine.OuterLineWidth = 100 ;
12 TableBorder aBorder = new TableBorder();
13 aBorder.TopLine = aBorder.BottomLine = aLine;
14 aBorder.LeftLine = aBorder.RightLine = aLine;
15 aBorder.IsTopLineValid = aBorder.IsBottomLineValid = true ;
16 aBorder.IsLeftLineValid = aBorder.IsRightLineValid = true ;
17 xPropSet.setPropertyValue( " TableBorder " , new Any( typeof (TableBorder), aBorder ) );
18 }
代码片断5
2 {
3 XSpreadsheets xSheets = mxDocument.getSheets();
4 xSheets.insertNewByName( aName, nIndex );
5 XSpreadsheet xSheet = (XSpreadsheet) xSheets.getByName( aName ).Value;
6 return xSheet;
7 }
代码片断4
2 {
3 X ComponentLoader aLoader = (XComponentLoader)
4 mxMSFactory.createInstance( " com.sun.star.frame.Desktop " );
5 XComponent xComponent = aLoader.loadComponentFromURL(
6 " private:factory/scalc " , " _blank " , 0 ,
7 new unoidl.com.sun.star.beans.PropertyValue[ 0 ] );
8 return (XSpreadsheetDocument) xComponent;
9 }
10
代码片断3
2 {
3 m_xContext = uno.util.Bootstrap.bootstrap ();
4 return (XMultiServiceFactory) m_xContext.getServiceManager();
5 }
6
代码片断2

2

3

4

5

代码片断1