<?xml version="1.0"?>
<snippet language="OOBasic" application="Calc">

<keywords>
	<keyword>sort</keyword>
	<keyword>sorting</keyword>
</keywords>

<authors>
	<author id="swubuntu" initial="true" email="[EMAIL PROTECTED]">Stefan Weigel</author>
</authors>

<question heading="Improve sorting capabilities">

</question>

<answer>
<p>This macro provides an improved sorting function for the user.</p>
<p></p>
<p>It enables to sort using as many sort criteria as desired. (Calc normally allows max. 3 criteria.)</p>
<p></p>
<p>The sort criteria to be used is determined by the currently active cell. (Calc normally uses the first column.)</p>
<p></p>
<p>The macro recognizes if there are column headers (Calc normally does not recognize column header when using the sort icons from the toolbar)</p>
<p></p>
<p>The macro overcomes issue #7277 and issue #20491. For background info and long description see http://www.stefan-weigel.de/?ID=83. For German text see http://www.stefan-weigel.de/?ID=81</p>
<listing>REM  *****  BASIC  *****

option explicit

sub SWsortUp()
	thisComponent.lockcontrollers
	SWSort true
	thisComponent.unlockcontrollers
end sub

sub SWsortDown()
	thisComponent.lockcontrollers
	SWSort false
	thisComponent.unlockcontrollers
end sub

sub SWsort(blnUpDown)

	Dim oSheet						&apos; Betroffenes Tabellenblatt
	Dim oListe as Object 			&apos; Zu sortierender Bereich
	Dim intListeStartSpalte			&apos; 
	Dim intListeEndSpalte			&apos; 
	Dim lngListeStartZeile			&apos; 
	Dim lngListeEndZeile			&apos;
	Dim intListeAnzSpalten			&apos;
	Dim lngListeAnzZeilen			&apos; 
	Dim intKritSpalte as Integer 	&apos; Nummer der Spalte, nach der sortiert werden soll
	Dim blnUeberschriften			&apos; Hat die Liste &#220;berschriften?
	Dim i as Integer				&apos; Laufvariable Integer
	Dim oRange as Object			&apos; Hilfsvariable f&#252;r Zellbereich
	Dim aSortFields(1) as New [EMAIL PROTECTED] com.sun.star.table.TableSortField}
    Dim aSortDesc(1) as New [EMAIL PROTECTED] com.sun.star.beans.PropertyValue}
	
	
	&apos;Betroffenes Tabellenblatt
	oSheet = ThisComponent.CurrentController.ActiveSheet

	&apos; Was der User markiert hat
	oListe = thisComponent.CurrentSelection

	&apos; Es d&#252;rfen nicht mehrere Bereiche markiert sein
	if oListe.supportsService(&quot;[EMAIL PROTECTED] com.sun.star.sheet.SheetCellRanges}&quot;) then
		msgbox &quot;Sortieren in mehreren Bereichen nicht m&#246;glich!&quot;,,&quot;&#169; Ingenieurb&#252;ro Weigel&quot;
		exit sub
	end if
	
	&apos;Feststellen der Spalte der aktiven Zelle
	oRange = thisComponent.createInstance(&quot;[EMAIL PROTECTED] com.sun.star.sheet.SheetCellRanges}&quot;)
	ThisComponent.CurrentController.Select(oRange)
	intKritSpalte = ThisComponent.CurrentSelection.getCellAddress.Column
	ThisComponent.CurrentController.Select(oListe)
	
	&apos;Markieren des Listenbereichs, wenn genau eine einzelne Zelle markiert ist
	&apos;(Trick: verwende die Erkennung die Calc beim Sortieren durchf&#252;hrt)
	SelectCurrentRange
	
	&apos;Zeilen und Spalten des zu sortierenden Bereichs
	intListeStartSpalte = ThisComponent.CurrentSelection.getRangeAddress.StartColumn
	intListeEndSpalte = ThisComponent.CurrentSelection.getRangeAddress.EndColumn
	intListeAnzSpalten = intListeEndSpalte - intListeStartSpalte
	lngListeStartZeile = ThisComponent.CurrentSelection.getRangeAddress.StartRow
	lngListeEndZeile = ThisComponent.CurrentSelection.getRangeAddress.EndRow
	lngListeAnzZeilen = lngListeEndZeile - lngListeStartZeile + 1
	
	&apos;Nummer der Sortierspalte innerhalb des zu sortierenden Bereichs
	intKritSpalte = intKritSpalte - intListeStartSpalte
	
	if lngListeAnzZeilen = 1 then exit sub
	
	&apos;&#220;berschriften?
	blnUeberschriften = false
	&apos;Die erste Zeile wird als &#220;berschrift interpretiert, wenn die Zellen der ersten und zweiten Zeile unterschiedlich Datentypen enthalten
	for i=intListeStartSpalte to intListeEndSpalte
		if oSheet.getCellByPosition(i,lngListeStartZeile).FormulaResultType &lt;&gt; oSheet.getCellByPosition(i,lngListeStartZeile+1).FormulaResultType and _
									oSheet.getCellByPosition(i,lngListeStartZeile).FormulaResultType &lt;&gt; 0 and _
									oSheet.getCellByPosition(i,lngListeStartZeile+1).FormulaResultType &lt;&gt; 0 then
		blnUeberschriften = true
		exit for
		end if
	next i
	if blnUeberschriften = false then
	    &apos;Die erste Zeile wird auch dann als &#220;berschrift interpretiert,
	    &apos;wenn die Zellen der ersten und zweiten Zeile zwar gleiche Datentypen enthalten, aber unterschiedliche Formatvorlagen verwenden 
		for i=intListeStartSpalte to intListeEndSpalte
			if oSheet.getCellByPosition(i,lngListeStartZeile).CellStyle &lt;&gt; oSheet.getCellByPosition(i,lngListeStartZeile+1).CellStyle then
			blnUeberschriften = true
			exit for
			end if
		next i
	end if
		
	If blnUeberschriften and lngListeAnzZeilen &gt; 1 then
		lngListeStartZeile = lngListeStartZeile + 1
		lngListeAnzZeilen = lngListeAnzZeilen -1
	end if
	
	if lngListeAnzZeilen = 1 then exit sub
	
	&apos;Hilfsspalte einf&#252;gen
	oSheet.Columns.insertByIndex(intListeEndSpalte+1,1)
	
	&apos;bisherige Ordnung in Hilfsspalte durchnummerieren
	&apos;for i=lngListeStartZeile to lngListeEndZeile
	&apos;	oSheet.getCellByPosition(intListeEndSpalte+1,i).value=i
	&apos;next i
	&apos;Auf Anregung von Andreas Saeger ([EMAIL PROTECTED]) auf users@de.openoffice.org geht das Nummerieren so schneller:
    dim dA(), rA()
	with oSheet.getCellRangeByPosition(intListeEndSpalte+1,lngListeStartZeile,intListeEndSpalte+1,lngListeEndZeile)
    	dA() = .getDataArray()
    	for i = lBound(dA()) to uBound(dA())
        	rA() = dA(i)
       	    rA(0) = i
    	next
    	.setDataArray(dA())
	End With 			
	
	oListe =oSheet.getCellRangeByPosition(intListeStartSpalte,lngListeStartZeile,intListeEndSpalte+1,lngListeEndZeile)

	&apos;Sortieren
    aSortFields(0).Field = intKritSpalte		&apos;Spalte, in der der User die aktive Zelle gesetzt hatte
    aSortFields(0).IsAscending = blnUpDown
    aSortFields(0).IsCaseSensitive = false
    aSortFields(1).Field = intListeEndSpalte+1  &apos;Hilfspalte mit bisheriger Ordnung
    aSortFields(1).IsAscending = true
    aSortFields(1).IsCaseSensitive = false
    aSortDesc(0).Name  = &quot;SortFields&quot;
    aSortDesc(0).Value = aSortFields()
    aSortDesc(1).Name  = &quot;ContainsHeader&quot;
    aSortDesc(1).Value = false
    oListe.sort(aSortDesc())
	
	&apos;Hilfsspalte entfernen
	oSheet.Columns.removeByIndex(intListeEndSpalte+1,1)	

	oListe =oSheet.getCellRangeByPosition(intListeStartSpalte,lngListeStartZeile,intListeEndSpalte,lngListeEndZeile)
	ThisComponent.CurrentController.Select(oListe)
	
end sub


sub SelectCurrentRange
	dim oDisp as object
	dim oDoc as object
	dim Array()
	oDoc   = ThisComponent.CurrentController.Frame
	oDisp = createUnoService(&quot;[EMAIL PROTECTED] com.sun.star.frame.DispatchHelper}&quot;)
	oDisp.executeDispatch(oDoc, &quot;.uno:SortAscending&quot;, &quot;&quot;, 0, Array())
	oDisp.executeDispatch(ThisComponent.CurrentController.Frame,&quot;.uno:Undo&quot;, &quot;&quot;,0, Array())
End Sub

</listing>
</answer>

<versions>
	<version number="2.0.x" status="tested"/>
</versions>

<operating-systems>
<operating-system name="All"/>
</operating-systems>

<changelog>
</changelog>

</snippet>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to