如何计算OpenOffice / LibreOffice BASIC中的重复条目?

时间:2016-10-26 15:03:03

标签: libreoffice-basic openoffice-basic

我在LibreOffice的多个工作表中有大量数据 - ADDRESS列和DATA列 - 我想计算每个地址发生的次数,放进入NUM_ADDR列。 E.g:

ADDR             | DATA             | NUM_ADDR
00000000bbfe22d0 | 876d4eb163886d4e | 1
00000000b9dfffd0 | 4661bada6d4661ba | 1
00000000b9dfc3d0 | 5d4b40b4705d4b40 | 1
00000000b9def7d0 | 8f8570a5808f8570 | 1
00000000b9de17d0 | 63876d4eb163886d | 1
00000000b9dddfd0 | 6d4eb163886d4eb1 | 3
00000000b9dddfd0 | 705d4b40b4705d4b | 
00000000b9dddfd0 | b4705d4b40b4705d | 
00000000b7df83d0 | 40b4705d4b40b470 | 1
00000000b7d607d0 | 705d4b40b4705d4b | 1
...

当手动操作时,我在每个地址上使用COUNTIF函数,但我发现宏可以节省时间。鉴于前一个函数已经确定了RowCounter中存储的数据的长度(行数),这是我到目前为止的一个片段:

Dim CountedAddr(RowCounter, RowCounter) as String
Dim CountedAddrPtr as Integer
Dim CurrentCell as Object
Dim i as Integer

CountedAddrPtr = 0

' Populate CountedAddr array
For i = 1 to RowCounter-1
  CurrentCell = CurrentSheet.getCellByPosition(0, i)
  If Not CurrentCell.String In CountedAddr(?) Then
    CurrentSheet.getCellByPosition(2, i).Value = 1 ' for debugging
    CountedAddr(CountedAddrPtr, 0) = CurrentCell.String
    CountedAddrPtr = CountedAddrPtr + 1
  Else
    CurrentSheet.getCellByPosition(2, i).Value = 0 ' for debugging
  EndIf
Next

' For each unique address, count number of occurances
For i = 0 to UBound(CountedAddr())
  For j = 1 to RowCounter-1
    If CurrentSheet.getCellByPosition(0, j).String = CountedAddr(i, 0) Then
      CountedAddr(i, 1) = CountedAddr(i, 1)+1
    EndIf
  Next
Next

' Another function to populate NUM_ADDR from CountedAddr array...

所以我的第一个问题是:我们如何确定一个元素(当前单元格中的地址)是否在CountedAddr数组中(参见上面的(?))?第二,是否有更有效的方法来实现第二块代码?不幸的是,排序是不可能的,因为地址和数据的年表形成了某种时间基础。第三,整个shebang是一种愚蠢的方式来解决这个问题吗?

非常感谢软件任务中的硬件问题!

1 个答案:

答案 0 :(得分:0)

字典类型的对象(例如VB6 Collection)可以有效地查找项目,因为它直接找到密钥而不是循环遍历长数组。我们下面的countedAddrs集合将存储每个地址的计数。

Sub CountAddrs
    Dim countedAddrs As New Collection
    Dim oCurrentSheet As Object
    Dim oCurrentCell As Object
    Dim currentAddr As String
    Dim i As Integer
    Dim newCount As Integer
    Dim rowCounter As Integer
    Const ADDR_COL = 0
    Const COUNT_COL = 2

    oCurrentSheet = ThisComponent.CurrentController.ActiveSheet
    rowCounter = 11
    ' Populate countedAddrs array.
    For i = 1 to rowCounter - 1
      oCurrentCell = oCurrentSheet.getCellByPosition(ADDR_COL, i)
      currentAddr = oCurrentCell.String
      If Contains(countedAddrs, currentAddr) Then
        ' Increment the count.
        newCount = countedAddrs.Item(currentAddr) + 1
        countedAddrs.Remove(currentAddr) 
        countedAddrs.Add(newCount, currentAddr)
        oCurrentSheet.getCellByPosition(COUNT_COL, i).Value = newCount ' for debugging
      Else
        countedAddrs.Add(1, currentAddr)
        oCurrentSheet.getCellByPosition(COUNT_COL, i).Value = 1 ' for debugging
      EndIf
    Next
End Sub

此代码需要以下辅助函数。在大多数语言中,字典对象都内置了此功能,但Basic非常简单。

' Returns True if the collection contains the key, otherwise False.
Function Contains(coll As Collection, key As Variant)
    On Error Goto ErrorHandler
    coll.Item(key)
    Contains = True
    Exit Function
ErrorHandler:
    Contains = False
End Function