【问题标题】:LlibreOffice macro fails to sort the filtered resultsLibreOffice 宏无法对过滤结果进行排序
【发布时间】:2019-04-05 20:08:56
【问题描述】:

这是一个 LibreOffice Calc 宏。目标是从一个工作表上的列中筛选唯一数据,将其粘贴到另一个工作表上,然后对粘贴的值进行排序。但是,输出列未排序。

对于工作表“final”和“lists”,数据从$final.$m2:$m100 读取,并在$lists.$C 列中结束,从$lists.$C2 开始。过滤工作正常,只抓取包含空单元格的唯一行(这是所需的)。

共有三个子/功能:

  • runit(用于测试)
  • filterDistinct(过滤数据,设置范围)
  • sortRange(对结果排序)

您发现代码有什么问题吗?

sub runit

    filterDistinct( "final", "$m2:$m100", "lists", "$C2", false, false)

end sub

Sub filterDistinct( _
    strSourceSheet As String, _
    strSourceRange As String, _
    strTargetSheet As String, _
    strTargetCell As String, _
    Optional bContainsHeader As Boolean, _
    Optional bCaseSensitive As Boolean _
)
    GlobalScope.BasicLibraries.loadLibrary("Tools")

    ' Uses a Filter to copy distinct rows from the 
    '   specified Source Range into a new Range that starts from the specified Target Cell.
    '
    ' <strSourceRange>    : specifies the Range to find distinct rows in, e.g. "A1:B99".
    ' <strTargetCell>     : specifies the Cell to put the first found distinct row in, e.g. "D1".
    ' <bContainsHeader>   : OPTIONAL - pass TRUE if the Source Range contains a Header.
    ' <bCaseSensitive>    : OPTIONAL - pass TRUE if case matters while searching for distinct rows.

    Dim oSheet As Object, oTargetSheet As Object, oSourceRange As Object, oTargetRange As Object, oFilter As Object

    oSheet = ThisComponent.getSheets().getByName(strSourceSheet)
    oSourceRange = oSheet.getCellRangebyName( strSourceRange )
    oTargetSheet = ThisComponent.getSheets().getByName(strTargetSheet)
    oTargetRange = oTargetSheet.getCellRangebyName( strTargetCell )
    oTargetSortRange = oTargetSheet.getCellRangebyName( "$C1:$C40000" )

    'msgbox oSheet.getName()
    'msgbox oSourceRange.AbsoluteName
    'msgbox oTargetSheet.getName()
    'msgbox oTargetRange.AbsoluteName
    'msgbox oTargetSortRange.AbsoluteName
    'sortRange( oTargetSortRange, 0, 1 )
    'exit sub

    oFilter = oSourceRange.createFilterDescriptor( True )
    oFilter.SkipDuplicates = True
    oFilter.CopyOutputData = True
    oFilter.OutputPosition = oTargetRange.CellAddress

    If Not IsMissing( bContainsHeader ) Then oFilter.ContainsHeader = bContainsHeader
    If Not IsMissing( bCaseSensitive ) Then oFilter.IsCaseSensitive = bCaseSensitive

    oSourceRange.filter( oFilter )

    sortRange( oTargetSortRange, 1, 1 ) 
End Sub


' sorts the cell range xRange by the iColumn (0 = first) column in IsAscending (=T/F) order: 
function sortRange( _
    xRange As Object, _
    iColumn As Integer, _
    IsAscending As Boolean _
)
    GlobalScope.BasicLibraries.loadLibrary("Tools")

    Dim oSortDesc(4) As New com.sun.star.beans.PropertyValue
    Dim aSortFields As Object
    ' Dim oField As New com.sun.star.sheet.TableFilterField2

    'oField.Field=0
    'oField.Operator=com.sun.star.sheet.FilterOperator2.NOT_EMPTY
    'oFilterDesc.setFilterFields2(Array(oField))

    ' define the fields to sort
    aSortFields = New com.sun.star.util.SortField
    aSortFields.Field = iColumn
    aSortFields.SortAscending = IsAscending

    ' define the sort descriptor
    oSortDesc(0) = new com.sun.star.beans.PropertyValue
    oSortDesc(0).Name = "SortFields"
    oSortDesc(0).Value = aSortFields

    oSortDesc(1) = new com.sun.star.beans.PropertyValue
    oSortDesc(1).Name = "ContainsHeader"
    oSortDesc(1).Value = true

    oSortDesc(2) = new com.sun.star.beans.PropertyValue
    oSortDesc(2).Name = "IsCaseSensitive"
    oSortDesc(2).Value = False

    oSortDesc(3) = new com.sun.star.beans.PropertyValue
    oSortDesc(3).Name = "ContainsHeader"
    oSortDesc(3).Value = True

    ' Select the range and sort it.
    ' ThisComponent.getCurrentController.select( xRange )

    msgbox xRange.AbsoluteName
    xRange.Sort( oSortDesc )    

    'dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

end function

【问题讨论】:

  • 体面的问题,尽管最好将问题缩小到更小的代码示例和更简单的示例表。
  • 理论上我是同意的,但是我不知道错误发生在哪里,并且厌倦了盲目地尝试调试它。

标签: macros libreoffice libreoffice-calc


【解决方案1】:

有几个小问题。

  • 该范围只有一列,因此iColumn 必须为 0 才能使用第一列也是唯一一列。
  • aSortFields 应该是一个数组。
  • sortRange 它被用作子程序,而不是函数。它可能仍然有效,但它不正确。

这是基于清单 6.28:Calc 文档中的降序排序的示例工作代码,来自Andrew's macro document

Sub doSort
    oSheet = ThisComponent.getSheets().getByIndex(0)
    oTargetSortRange = oSheet.getCellRangebyName( "$C1:$C40000" )
    sortRange( oTargetSortRange, 0, 1 ) 
End Sub

' sorts the cell range xRange by the iColumn (0 = first) column in IsAscending (=T/F) order: 
Sub sortRange( _
    xRange As Object, _
    iColumn As Integer, _
    IsAscending As Boolean _
)
    Dim oSortDesc(0) As New com.sun.star.beans.PropertyValue
    Dim aSortFields(0) As New com.sun.star.util.SortField

    aSortFields(0).Field = iColumn
    aSortFields(0).SortAscending = IsAscending

    oSortDesc(0).Name = "SortFields"
    oSortDesc(0).Value = aSortFields()

    xRange.Sort( oSortDesc )    
End Sub

【讨论】:

  • 好的,线索是数组建议,但不是你提到的地方。创建新PropertyValue 的行以某种方式扼杀了排序。删除这些类型的行有效:oSortDesc(0) = new com.sun.star.beans.PropertyValue 但是,我不知道为什么。那些行应该不会影响结果吧?
  • 不确定,但正如我所说,有很多事情对我来说不合适。要准确找出问题所在,有必要隔离一个问题。
猜你喜欢
  • 1970-01-01
  • 2020-11-02
  • 2018-03-13
  • 1970-01-01
  • 2015-05-04
  • 2020-02-10
  • 1970-01-01
  • 2020-01-27
  • 1970-01-01
相关资源
最近更新 更多