OpenOffice.org宏学习笔记4
前面介绍了OpenOffice.Org SpreadSheet宏的IDE和UNO,现在可以开始编写代码了。这里主要介绍怎样使用宏操作工作表,我们将学会怎样:
- 打开和关闭文件
- 使用多个工作表
- 在工作表中操作数据
- 使用OOo的内置函数
- 使用单元格和区域
打开和关闭电子表格
在前面我们已经知道了怎样打开和关闭电子表格
- 使用starDeskTop对象访问电子表格
- 使用loadComponentFromURL函数载入电子表格
- 使用close方法关闭电子表格
- 使用fileExists函数判断文件是否存在
- 使用storeAsUrl方法保存电子表格。

接着我们开始操作电子表格的内容。
操作电子表格单元格
我们知道:
- 每个电子表格包括一个或多个工作表(一般默认是3个,最多可以到256个)
- 每个工作表由8192000个单元格组成(256列乘以32000行)— OpenOffice.org Calc 3.0已经增加到67108864个单元格(1024乘以65536行)
- 每个工作表可以通过一个序号(0到255)来指认
- 每个单元格可以通过getCellByPosition方法使用一个格子坐标来指认它的位置

下面这个代码在一个工作表的单元格中填充内容:
Sub singleFile Dim oDoc as Object Dim oSheet as Object Dim oCell as Object oDoc = starDeskTop.loadComponentFromUrl _ ("private:factory/scalc", "_blank",0,Array ()) oSheet = oDoc.sheets (0) oCell = oSheet.getCellByPosition (0,0) oCell.String = now 'This function returns the current date and time End Sub
这个宏打开一个空白电子表格,获得第一个工作表,然后获得最左上角的单元格,写入当前时间到该单元格。
内容可以以三种方式写入到单元格—公式、字符串、数值。这个很重要,参考下面的代码:
oCell = oSheet.getCellByPosition (0,1) oCell.Value = 20 oCell = oSheet.getCellByPosition (0,2) oCell.Value = 30 oCell = oSheet.getCellByPosition (1,1) oCell.String = "=A2+A3" oCell = oSheet.getCellByPosition (2,1) oCell.Formula = "=A2+A3" oCell = oSheet.getCellByPosition (3,1) oCell.Value = "=A2+A3"
尽管我们输入的信息差不多,但是结果却完全不同。

如果简单一些的话,上面的代码也可以写成:
oSheet.getCellByPosition (0,1).Value = 20 oSheet.getCellByPosition (0,2).Value = 30 oSheet.getCellByPosition (1,1).String = "=A2+A3" oSheet.getCellByPosition (2,1).Formula = "=A2+A3" oSheet.getCellByPosition (3,1).Value = "=A2+A3"
使用OOo内置函数
我们会经常在Calc中使用OOo的内置数学函数。在宏中我们也可以使用它们。例如,我们可以:
oCell1 = oSheet.getCellRangeByName ("A1") oCell2 = oSheet.getCellRangeByName ("B1") oCell1.value = 23.1 oCell2.value = SIN(oCell1.value)
也可以这样:
oCell2.formula = "=SIN(A1)"有什么区别呢?前面的代码将值-0.9放入B1单元格,而后面的代码则在B1单元格中放入一个公式。
然而,只有一部分函数可以这样使用。例如,下面的代码可以运行:
For r = 0 to 9 i = r + 1 oCell1 = oSheet.getCellByPosition (0,r) oCell1.Value = i oCell2 = oSheet.getCellByPosition (1,r) oCell2.Formula = "=ROMAN(A" + i + ")" Next r oLetters = Array("I","V","X","L","C","D","M") For r = 0 to ubound(oLetters) i = r + 1 oCell1 = oSheet.getCellByPosition (2,r) oCell1.String = oLetters(r) oCell2 = oSheet.getCellByPosition (3,r) oCell2.Formula = "=ARABIC(C" + i + ")" Next r
运行上面的代码,将在工作表中显示下面有趣的结果。

但是如果我们试下面的代码:
oCell2.value =ARABIC(oCell1.String)将会得到下面的错误提示:

但这并不表示我们不能使用内置函数,只是需要使用另外一种方法(有些类似于Excel VBA中的Application.WorksheetFunction)。
oFunction = createUnoService("com.sun.star.sheet.FunctionAccess") oCell4.value = oFunction.callFunction("ARABIC", _ Array(oCell3.String))
注意传递给函数CallFunction的第二个参数是一个数组。
命名工作表和单元格
我们可以使用序号通过Sheets集合来访问工作表,但是在删除或添加工作表或者工作表的顺序改变后,使用现有的序号访问工作表时可能会发生错误。因此最好使用工作表名称来访问它们。
访问现有命名的工作表和单元格
使用序号访问:
oSheet = oDoc.sheets(0)
使用名称访问:
oSheet = oDoc.Sheets.getByName("PPI Accounts")访问到工作表后,也可以使用名称访问单元格。
使用位置访问:
oCell = oSheet.getCellByPosition(0,1)
使用名称访问:
oCell = oSheet.getCellRangeByName("Daily Total")创建新的命名工作表和单元格
命名一个已存在的单元格很简单:
oSheet.name = "PPI Client Details"创建一个新的单元格也差不多简单:
oSheet = oDoc.createInstance ( "com.sun.star.sheet.Spreadsheet" ) oDoc.Sheets.insertByName ( "PPI Daily Tasks", oSheet )
给一个单元格命名则稍微麻烦点:
Dim oCellAddress As new com.sun.star.table.CellAddress Dim oNamedRanges oNamedRanges = oDoc.NamedRanges oNamedRanges.addNewByName("Total", "$Sheet1.$A$8", oCellAddress, 0)
删除工作表
oDoc.Sheets.removeByName("Sheet3")使用多个工作表
使用多个工作表和一个工作表的复杂程度是差不多的。
Sub sequencialFiles Dim oDoc as Object Dim oDesk as Object Dim oSheet as Object Dim oCell as Object oDoc = starDeskTop.loadComponentFromUrl _ ("private:factory/scalc", "_blank",0,Array()) oSheet = thisComponent.sheets (0) oCell = oSheet.getCellByPosition (0,0) oCell.String = now oDoc = starDeskTop.loadComponentFromUrl _ ("private:factory/scalc", "_blank",0,Array()) oSheet = thisComponent.sheets (0) oCell = oSheet.getCellByPosition (0,0) oCell.String = now + 1 End Sub
运行结果如图:

上面的代码使用一个对象变量来表示不同的对象,这样需要再转换到另外一个对象之前保证完成自己的操作。我们会发现如果对每个电子表格使用不同的对象会更有效一些,这样我们可以控制所有的操作。
Sub multiSheets Dim oURL1 as String Dim oURL2 as String Dim oDoc1 as Object Dim oDoc2 as Object Dim oCell1 as Object Dim OCell2 as Object oURL1 = "private:factory/scalc" oURL2 = "private:factory/scalc" oDoc1 = starDeskTop.loadComponentFromURL (oURL1, "_blank", 0, _ Array() ) oDoc2 = starDeskTop.loadComponentFromURL (oURL2, "_blank", 0, _ Array() ) oCell1 = oDoc1.Sheets (0).getCellByPosition (0,0) oCell1.String = now oCell1 = oDoc1.Sheets (0).getCellByPosition (0,1) oCell1.Value = 37.5 oCell2 = oDoc2.Sheets (0).getCellByPosition (0,0) oCell2.String = now oCell2 = oDoc2.Sheets (0).getCellByPosition (0,1) oCell2.String = "Amount" oCell2 = oDoc2.Sheets (0).getCellByPosition (1,1) oCell2.String = "VAT" oCell2 = oDoc2.Sheets (0).getCellByPosition (2,1) oCell2.String = "Total" oCell2 = oDoc2.Sheets (0).getCellByPosition (0,2) oCell2.Value = oCell1.Value oCell2 = oDoc2.Sheets (0).getCellByPosition (1,2) oCell2.Value = oCell1.Value * 0.175 oCell2 = oDoc2.Sheets (0).getCellByPosition (2,2) oCell2.Value = oCell1.Value * 1.175 End Sub
使用区域
除了使用单元格之外,我们还需要使用区域。下面的代码将第2个工作表中区域A1:A100的内容负责到第一个工作表相同的区域中。
oRange1 = oDoc1.Sheets (1).getCellRangeByName ("A1:A100") oRange2 = oDoc2.Sheets (0).getCellRangeByName ("A1:A100") oRange2.setDataArray (oRange1.getDataArray ())
也可以使用单元格位置来表示区域。
oRange1 = oDoc1.Sheets (0).getCellRangeByPosition (0,0,0,100) oRange2 = oDoc2.Sheets (0).getCellRangeByPosition (0,0,0,100)
区域在使用某些函数时特别有用。
oCell1 = oSheet.getCellRangeByName ("A1") oCell2 = oSheet.getCellRangeByName ("A2") oCell3 = oSheet.getCellRangeByName ("A3") oCell4 = oSheet.getCellRangeByName ("B3") oCell1.Value = 36 oCell2.Value = 57 oCell3.Value = 42 oRange1 = oSheet.getCellRangeByName ("A1:A3") 'Remember to use callFunction oCell4.Value = _ oFunction.callFunction("STDEV", Array(oRange1.getDataArray ()))
No related posts.
以上关联文章由 Yet Another Related Posts Plugin 提供支持。
好极啦,学习啦。不过强烈建议,增加内部指针随时指向当前DOCUMENT,当前sheet,当前CELL(其光标位置)。这样我就会变得喜欢他,而放弃花钱的Excle
你好!
想请教关于OpenOffice的宏问题
现在对原有Ms ExcelVBA实现的工具进行向OpenOffice转换
但发现有好多东西都有问题
比如下面的这个Aplication的属性
Aplication.MoveAfterReturnDirection
Aplication这个OBJECT在OpenOffice内就不存在,OpenOffice内用的什么实现上面的属性的呢
还有方法Workbook_Before()等,OpenOffice内用什么替换的呢
原ExcelVBA中有个小按钮一点击可以察看相关的方法和属性什么的
OpenOffice上我没有找到察看那些东西的地方 请高手指教一下
@dachai
你好,我也在学习OpenOffice中,并不是很熟悉OpenOffice编程,所以算不上高手,甚至连入门都算不上。感觉OpenOffice编程的习惯还是和VBA相差太大,毕竟Excel VBA的资源很丰富,网络上基本上可以找到现成的答案。而OpenOffice本身的IDE功能已经帮助功能就不是很强大,并且网络上的资源极为缺乏。我们公司之前也打算转换现在的VBA,不知道现在进行得怎么样。
关于VBA中的Application.MoveAfterReturnDirection,这么简单的一个语句到OpenOffice中实现起来却极为麻烦(可能有其他的方法我不知道),涉及到
com.sun.star.beans.PropertyValue
com.sun.star.comp.configuration.ConfigurationProvider
“com.sun.star.configuration.ConfigurationUpdateAccess
一堆东西,而且貌似还要重启Calc。
VBA中的Application其实和com.sun.star是一样的。
Workbook的事件响应也应该是一个高阶的应用,我也不太清楚,要先学习学习。
哦 好的 努力学习中
谢谢回答
你好
你那有openoffice的电子书吗
你提到的这本书Learn OpenOffice.org Spreadsheet Macro Programming(PACKT 出版,作者为Dr. Mark Alexander Bain)
我没有下载成功
能提供一下吗
@dachai
已经发到你的163邮箱了。
你好,我现在正在学习openoffice ,能发送一份你那本电子书到我邮箱吗?
谢谢!
@jobsen
已经发到你的邮箱。
你好!
我现在也在学习openoffice的宏。
看了你的教程后,感觉讲得很好。
为了便于随时查阅,
不知道能不能发一份你说的电子教程到我邮箱马?
非常感谢!
@cora-cora
已经发到你的邮箱。
你好!我也想要那份关于openoffice宏的电子教程。
@shan
你好,已经发到你的邮箱。
@winland
能给我也发一份吗,niejieqiang@gmail.com 谢谢啦。
@niejieqiang
已经发到你的邮箱
你好 能帮忙发一份吗 alpser25@163.com 谢谢
@pikerlee
已经发到你的邮箱。
你好 能给我发一份么 juaner215123@163.com 谢谢
最近想用openoffice的运行vba的宏来画图,发现好多都不支持
@juaner
已经把链接发给了你。