首页 > OpenOffice > OpenOffice.org宏学习笔记4

OpenOffice.org宏学习笔记4

2009年10月3日

前面介绍了OpenOffice.Org SpreadSheet宏的IDE和UNO,现在可以开始编写代码了。这里主要介绍怎样使用宏操作工作表,我们将学会怎样:

  • 打开和关闭文件
  • 使用多个工作表
  • 在工作表中操作数据
  • 使用OOo的内置函数
  • 使用单元格和区域

打开和关闭电子表格

在前面我们已经知道了怎样打开和关闭电子表格

  1. 使用starDeskTop对象访问电子表格
  2. 使用loadComponentFromURL函数载入电子表格
  3. 使用close方法关闭电子表格
  4. 使用fileExists函数判断文件是否存在
  5. 使用storeAsUrl方法保存电子表格。

oosmacro0401
接着我们开始操作电子表格的内容。

操作电子表格单元格

我们知道:

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

oosmacro0402

下面这个代码在一个工作表的单元格中填充内容:

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"

尽管我们输入的信息差不多,但是结果却完全不同。
oosmacro0403
如果简单一些的话,上面的代码也可以写成:

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

运行上面的代码,将在工作表中显示下面有趣的结果。
oosmacro0404
但是如果我们试下面的代码:

oCell2.value =ARABIC(oCell1.String)

将会得到下面的错误提示:
oosmacro0405

但这并不表示我们不能使用内置函数,只是需要使用另外一种方法(有些类似于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

运行结果如图:
oosmacro0406
上面的代码使用一个对象变量来表示不同的对象,这样需要再转换到另外一个对象之前保证完成自己的操作。我们会发现如果对每个电子表格使用不同的对象会更有效一些,这样我们可以控制所有的操作。

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 提供支持。

OpenOffice ,

  1. cake
    2010年4月25日20:24 | #1

    好极啦,学习啦。不过强烈建议,增加内部指针随时指向当前DOCUMENT,当前sheet,当前CELL(其光标位置)。这样我就会变得喜欢他,而放弃花钱的Excle

  2. dachai
    2010年7月20日20:57 | #2

    你好!
    想请教关于OpenOffice的宏问题
    现在对原有Ms ExcelVBA实现的工具进行向OpenOffice转换
    但发现有好多东西都有问题
    比如下面的这个Aplication的属性
    Aplication.MoveAfterReturnDirection
    Aplication这个OBJECT在OpenOffice内就不存在,OpenOffice内用的什么实现上面的属性的呢
    还有方法Workbook_Before()等,OpenOffice内用什么替换的呢
    原ExcelVBA中有个小按钮一点击可以察看相关的方法和属性什么的
    OpenOffice上我没有找到察看那些东西的地方 请高手指教一下

  3. Winland
    2010年7月20日23:25 | #3

    @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的事件响应也应该是一个高阶的应用,我也不太清楚,要先学习学习。

  4. dachai
    2010年7月21日08:46 | #4

    哦 好的 努力学习中
    谢谢回答

  5. dachai
    2010年7月21日09:24 | #5

    你好
    你那有openoffice的电子书吗
    你提到的这本书Learn OpenOffice.org Spreadsheet Macro Programming(PACKT 出版,作者为Dr. Mark Alexander Bain)
    我没有下载成功
    能提供一下吗

  6. winland
    2010年7月23日11:51 | #6

    @dachai
    已经发到你的163邮箱了。

  7. jobsen
    2010年8月19日22:04 | #7

    你好,我现在正在学习openoffice ,能发送一份你那本电子书到我邮箱吗?
    谢谢!

  8. winland
    2010年8月21日20:34 | #8

    @jobsen
    已经发到你的邮箱。

  9. cora-cora
    2010年9月23日09:42 | #9

    你好!
    我现在也在学习openoffice的宏。
    看了你的教程后,感觉讲得很好。
    为了便于随时查阅,
    不知道能不能发一份你说的电子教程到我邮箱马?
    非常感谢!

  10. winland
    2010年9月23日20:20 | #10

    @cora-cora
    已经发到你的邮箱。

  11. shan
    2010年11月8日13:54 | #11

    你好!我也想要那份关于openoffice宏的电子教程。

  12. winland
    2010年11月8日18:53 | #12

    @shan
    你好,已经发到你的邮箱。

  13. niejieqiang
    2010年11月12日10:47 | #13

    @winland
    能给我也发一份吗,niejieqiang@gmail.com 谢谢啦。

  14. winland
    2010年11月12日18:40 | #14

    @niejieqiang
    已经发到你的邮箱

  15. pikerlee
    2011年3月14日16:09 | #15

    你好 能帮忙发一份吗 alpser25@163.com 谢谢

  16. Winland
    2011年3月15日19:17 | #16

    @pikerlee
    已经发到你的邮箱。

  17. juaner
    2011年5月17日22:12 | #17

    你好 能给我发一份么 juaner215123@163.com 谢谢
    最近想用openoffice的运行vba的宏来画图,发现好多都不支持

  18. Winland
    2011年5月22日18:40 | #18

    @juaner
    已经把链接发给了你。

  1. 目前还没有任何 trackbacks 和 pingbacks.

使用腾讯微博登陆

使用新浪微博登陆