BITTE helfen Sie uns HEUTE mit einer SPENDE
Helfen Sie das LibreOffice Forum zu erhalten!

❤️ DANKE >><< DANKE ❤️

> KEINE WERBUNG FÜR REGISTRIERTE BENUTZER!<
Ihre Spende wird für die Deckung der laufenden Kosten sowie den Erhalt und Ausbau 🌱 des LibreOffice Forums verwendet.
🤗 Als Dankeschön werden Sie im Forum als LO-SUPPORTER gekennzeichnet. 🤗

[Gelöst] Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortcut?

CALC ist die Tabellenkalkulation, die Sie immer wollten.
Frank_M
Beiträge: 12
Registriert: Di 23. Jun 2015, 13:56

[Gelöst] Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortcut?

Beitrag von Frank_M » Di 23. Jun 2015, 14:41

Hi LO-Community :)

ich habe häufig Tabellen mit "eingeschaltetem Autofilter", d.h. im Tabellenkopf kann ich in einer eine Spalte ein Extra-Menü anklicken und dort auswählen, ob sich nach dieser Spalte sortieren oder Zeilen nach Inhalten filtern möchte. Sehr praktisch und schon lange Stand der Technik.

Oft habe ich die Situation, dass ich gerade einen Wert (z.B. "Mayer KG" in der Spalte "Firma") in der Zelle habe und dann alle Zeilen der "Mayer KG" in der Tabelle sehen möchte. Der Weg dahin erscheint mir etwas umständlich: Ich muss zum Kopf der Tabelle, dort auf das Kontext-Menü klicken, dann dort die "Mayer KG" auswählen und dort auf das Icon "alle anderen Zeilen ausblenden" klicken.

Ich frage mich, ob ich den Inhalt der aktuellen Zelle nicht einfacher als Filter nutzen kann, Möglicher Use Case mit Beispiel "Mayer KG":
  • Situation: Benutzer hat Autofilter aktiviert und Cursor befindet sich in der Tabelle.
  • Aufgabe: Inhalt der aktiven Zelle soll Filterkriterium werden.
  • Aktion: "Benutzer öffnet Kontext-Menü der Zelle und wählt dort den Eintrag "Tabelle nach 'Mayer KG' filtern" aus.
  • Ergebnis: Tabelle zeigt nur noch Elemente an, die dem Filterkriterium "Mayer KG" in der aktuellen Spalte entsprechen.
Noch praktischer wäre hier natürlich, das auf einen Shortcut zu legen.

Wenn es das nicht gibt, kann man das mit einem Makro "nachrüsten"?

Ich habe mit dem LO-Basic leider null Erfahrung. Vielleicht eine gute Idee, sich hieran mal zu probieren. Kann mir jemand beim Einstieg helfen? Habe früher das eine oder andere für meine Arbeit gescriptet (Shell, Perl, PHP, ..) aber eben nie im Office-Bereich.

Vielen Dank,

Frank
Zuletzt geändert von Frank_M am Fr 26. Jun 2015, 17:24, insgesamt 1-mal geändert.

swolf
Beiträge: 1143
Registriert: Di 14. Feb 2012, 16:56

Re: Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortc

Beitrag von swolf » Di 23. Jun 2015, 17:27

habe mit dem LO-Basic leider null Erfahrung ...Kann mir jemand beim Einstieg helfen?
in der richtigen Rubrik vielleicht
http://www.libreoffice-forum.de/viewforum.php?f=12

Hier http://de.openoffice.info/viewforum.php ... e776bfbd41
findest du im allerersten Beitrag "Informationen zur StarBasic Programmierung"

clag
Beiträge: 10
Registriert: Di 16. Jun 2015, 04:17

Re: Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortc

Beitrag von clag » Mi 24. Jun 2015, 07:10

Moin Frank_m

habe mal ein Beispiel erstellt, wie man deinen Wunsch erfüllen kann,
allerdings habe ich das Ereignis Doppelklick in der Tabelle als Trigger verwendet.
Ein Doppelklick in eine der Datenbereichszellen filtert den Bereich mit dem Zellstring
ein Doppelklick in den Spaltenkopf hebt den Filter wieder auf.
Das funktioniert erheblich schneller als das aufrufen vom Kontextmenü.
ClickFilter.ods
(13.28 KiB) 310-mal heruntergeladen
viel Spaß

LG
clag

Frank_M
Beiträge: 12
Registriert: Di 23. Jun 2015, 13:56

Re: Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortc

Beitrag von Frank_M » Mi 24. Jun 2015, 19:35

Großartig, vielen Dank!! :-)

Nach etwas Reindenken ist es ja ganz einfach zu verstehen und nachzutipseln, wenn man eine schöne Vorlage hat :D Ich habe es mal etwas gebastelt und das Ergebnis auf einen Shortcut (Ctrl-A) gelegt - funktioniert bei einer Tabelle schon sehr schön *freu*

Am Schluss musste ich nochmal den Autofilter setzen, weil die Anwendung des Makros ihn abgeschaltet hatte. Vermutlich geht das auch eleganter - genau wie das Setzen des Cursors in die Kopfteile des Datenbereiches, so dass man einfach nur nochmal Ctrl-A tippen muss, um wieder die ganze Liste zu sehen.

Noch zwei Fragen zur Verschönerung - also nice to have:

1. Wenn ich Filtere, dann wird kein sauberer refresh der Tabelle gemacht: Man sieht, dass die gefilterten Daten schon an den Anfang der tabelle geschrieben wurden, aber die alten Daten stehen quasi noch als Geister-Daten in der Tabelle, die erst beim unter Scrollen verschwinden. Ich hatte im Netz gesucht und die Methode refresh() gefunden, wende sie aber offenbar falsch an. Weiß jemand wie man so einen Refresh macht (keine Rekalkulation, F9, die verändert nichts). Kommt mir ein bisschen wie ein Grafik-Fehler vor, könnte also auch am System liegen (LO 4.2.8.2, Ubuntu 14.04).

2. Die Datenbereiche sind bei mir nicht überall gleich benannt, im Beispiel unten heißt es z.B. FullDataSet. Gibt es eine Methode, mit der man den Namen des Bereiches bekommt, in dem eine Zelle (ggf.) liegt? Dann ließe sich noch etwas flexibler scripten ..

Also Suchmethode(Zelle) -> Datenbereichsname -> Grenzen des Bereiches, gegen die geprüft werden muss.

Auf jeden Fall schon mal vielen Dank!

Frank

Code: Alles auswählen

sub FilterShortcut

Dim oDoc    as Object
Dim oSheet  as Object
Dim oCell   as Object
Dim oRange  as Object
Dim oView   as Object
Dim oHeadCell  as Object

Dim Row     as Integer
Dim Column  as Integer
Dim Content as String

oDoc   = ThisComponent
oSheet = oDoc.getCurrentController.getActiveSheet
oCell  = oDoc.getCurrentSelection
oRange = oSheet.getCellRangeByName("FullDataSet")

Row     = oCell.CellAddress.Row
Column  = oCell.CellAddress.Column
Content = oCell.string

if Column < oRange.RangeAddress.StartColumn or _
    Column > oRange.RangeAddress.EndColumn  or _
    Row < oRange.RangeAddress.StartRow      or _
    Row > oRange.RangeAddress.EndRow        then exit Sub

if Row = oRange.RangeAddress.StartRow then
    oFilterDesc = oSheet.createFilterDescriptor(True)
    oSheet.filter(oFilterDesc)
  else
    actor() = com.sun.star.sheet.FilterOperator.EQUAL
    if Content = "" then  actor() = com.sun.star.sheet.FilterOperator.EMPTY
    Dim oFields(0) As New com.sun.star.sheet.TableFilterField
    oFilterDesc = oSheet.createFilterDescriptor(True)
    With oFields(0)
     .Field = Column
     .IsNumeric = False
     .StringValue = Content '.NumericValue = any value
     .Operator = actor
    End With
    oFilterDesc.setFilterFields(oFields())
    oFilterDesc.ContainsHeader = True
    oRange.filter(oFilterDesc)
end if

oDoc.DatabaseRanges.getByName("FullDataSet").AutoFilter = True
oView = oDoc.CurrentController
oHeadCell = oSheet.getCellByPosition(Column, oRange.RangeAddress.StartRow)
oView.Select(oHeadCell)

End Sub

Benutzeravatar
karolus
Beiträge: 2170
Registriert: Fr 10. Dez 2010, 10:01

Re: Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortc

Beitrag von karolus » Mi 24. Jun 2015, 21:22

Hallo
Etwas aufgeräumt, und mit queryIntersection(..) anstelle einer handgedrechselten `bin ich im Bereich x Prüfung`

Code: Alles auswählen

sub FilterShortcut


oDoc   = ThisComponent
oControl = oDoc.CurrentController
oSheet  = oControl.getActiveSheet
oCell  = oDoc.getCurrentSelection
oRange = oSheet.getCellRangeByName("FullDataSet")
if oRange.queryIntersection(oCell.RangeAddress).Count = 0 then  exit Sub
Row     = oCell.CellAddress.Row
Column  = oCell.CellAddress.Column
Content = oCell.string

oFilterDesc = oSheet.createFilterDescriptor(True)

if Row = oRange.RangeAddress.StartRow then    
    oSheet.filter(oFilterDesc)
else
    actor() = com.sun.star.sheet.FilterOperator.EQUAL
    if Content = "" then  actor() = com.sun.star.sheet.FilterOperator.EMPTY
    Dim oFields(0) As New com.sun.star.sheet.TableFilterField
    With oFields(0)
     .Field = Column
     .IsNumeric = False
     .StringValue = Content '.NumericValue = any value
     .Operator = actor
    End With
    oFilterDesc.setFilterFields(oFields())
    oFilterDesc.ContainsHeader = True
    oRange.filter(oFilterDesc)
end if

oDoc.DatabaseRanges.getByName("FullDataSet").AutoFilter = True
oHeadCell = oSheet.getCellByPosition(Column, oRange.RangeAddress.StartRow)
oControl.Select(oHeadCell)

End Sub
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.3.2 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)

Frank_M
Beiträge: 12
Registriert: Di 23. Jun 2015, 13:56

Re: Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortc

Beitrag von Frank_M » Mi 24. Jun 2015, 22:13

Super, vielen Dank!

Noch eine Frage die mir ganz wichtig wäre: Kann man die Abfrage zu queryIntersection(..) nicht so stellen, dass der Name des Bereiches zurück gegeben wird, in dem der Cursor aktuell steht? Weil am Ende ja in den Header der Tabelle gesprungen wird, und sich die Tabellen nicht immer an der gleichen Stelle befinden könnte ich das Skript dann sehr flexibel für alle Tabellen einsetzen (dass sich Bereiche dann nicht überlappen dürfen ist schon klar ;) )

Viele Grüße,
Frank
karolus hat geschrieben:Hallo
Etwas aufgeräumt, und mit queryIntersection(..) anstelle einer handgedrechselten `bin ich im Bereich x Prüfung`

Benutzeravatar
karolus
Beiträge: 2170
Registriert: Fr 10. Dez 2010, 10:01

Re: Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortc

Beitrag von karolus » Do 25. Jun 2015, 09:31

Du hast die aktuelle Selektion doch schon in der Variablen `oCell` den kompletten Bereichsnamen bekommst du dann mit

Code: Alles auswählen

selName = oCell.AbsoluteName
aber wozu?
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.3.2 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)

Frank_M
Beiträge: 12
Registriert: Di 23. Jun 2015, 13:56

Re: Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortc

Beitrag von Frank_M » Do 25. Jun 2015, 17:43

karolus hat geschrieben:Du hast die aktuelle Selektion doch schon in der Variablen `oCell` den kompletten Bereichsnamen bekommst du dann mit

Code: Alles auswählen

selName = oCell.AbsoluteName
das gibt doch nur die aktuell markierte(n) Zelle(n) zurück. In ''oRange.AbsoluteName'' steht natürlich der korrekte Bereich - aber da wurde er schon über ''getCellRangeByName("FullDataSet")'' bestimmt ;-)
aber wozu?
Das ist notwendig, weil die Datenbereiche nicht immer in Zeile 1 anfangen und nicht immer gleich heißen. Das Makro soll deshalb den Bereichsnamen selber heraus finden, in dem der Cursor gerade steht. Denn von ''oRange.RangeAddress.StartRow'' hängt ab, ob der Filter gesetzt oder gelöscht wird und am Ende des Makros wird der Cursor immer in die Header-Zeile gesetzt.

Damit kann man z.B. so filtern (Ctrl-A als Shortcut zum Makro-Aufruf definiert):
  • Ctrl-A: Schnell-Selektion, Filter wird angewendet (Cursor springt in Kopfzeile)
  • nochmal Ctrl-A: Filter wird aufgehoben (weil Cursor in der Kopfzeile steht)
Wie iteriere ich denn über alle benannten Datenbereiche? Dann könnte ich in jeder Iteration mit ''queryIntersection'' prüfen, ob der Cursor enthalten ist und bei einem Treffer aus dem Namen den Bereich ableiten. Ohne Treffer wird das Makro beendet, weil der Cursor nicht in einer Tabelle steht.

Thanx :-)

Benutzeravatar
karolus
Beiträge: 2170
Registriert: Fr 10. Dez 2010, 10:01

Re: Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortcut?

Beitrag von karolus » Do 25. Jun 2015, 18:33

Hallo
Wie iteriere ich denn über alle benannten Datenbereiche? Dann könnte ich in jeder Iteration mit ''queryIntersection'' prüfen, ob der Cursor enthalten ist und bei einem Treffer aus dem Namen den Bereich ableiten. Ohne Treffer wird das Makro beendet, weil der Cursor nicht in einer Tabelle steht.
Etwa so:

Code: Alles auswählen

doc = ThisComponent
DBRanges = doc.DatabaseRanges
for i = 0 to DBRanges.Count-1
    dbrange = DBRanges.getByIndex(i)
    cellrange = dbrange.ReferredCells
    cellrange.queryIntersection(...)
next
Darf ich dich auf MRI hinweisen?
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.3.2 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)

Frank_M
Beiträge: 12
Registriert: Di 23. Jun 2015, 13:56

Re: Autofilter: "Aktuelle Zelle als Filter" RMB-Menü, Shortcut?

Beitrag von Frank_M » Fr 26. Jun 2015, 13:04

karolus hat geschrieben:Hallo

Darf ich dich auf MRI hinweisen?
Hallo,

Ja, MRI hatte ich gesehen, aber es macht etwas Schwierigkeiten: Beim Aufruf kann ich das oberste Frame nicht verkleinern, so dass ich keinen Code eingeben kann (wie in dem Office-Dokument beschrieben). Egal wie langsam ich mit der Maus über die Ränder gehe: Ich bekomme keine Möglichkeit, die Frame-Größe zu verändern. Vermutlich ein Problem unter kubuntu ..

Ich habe noch einen kleinen Fehler gefunden und bin jetzt insgesamt sehr zufrieden. Das makro macht jetzt genau, was ich wollte :-) Vielen Dank nochmal für Deine bzw. Eure Hilfe!! Vielleicht hackere ich ja ein bisschen öfter hier rum :-)

Schönes Wochenende,
Frank

Anhang: Finale Version des Makros

Code: Alles auswählen

sub FilterShortcut

' Das Makro verwendet die aktuelle Zelle als Filterkriterium
' für einen Autofilter, so dass in der Tabelle nur Zeilen mit
' dem gleichem Inhalt wie in der aktuellen Zelle angezeigt
' werden
'
' Befindet sich der Cursor in der Kopfzeile des Bereichs wird
' der Filter beim Aufruf des Makros aufgehoben.
'
' Nach dem Filtern wird der Cursor in die Kopfzeile des Berei-
' ches verschoben, so dass ein erneuter Aufruf wieder alle
' Zeilen sichtbar macht.
' 
' Voraussetzung ist, dass der zu filternde Bereich als Bereich
' unter "Daten -> Bereich festlegen" eingetragen ist.

oDoc     = ThisComponent
oControl = oDoc.CurrentController
oSheet   = oControl.getActiveSheet
oCell    = oDoc.getCurrentSelection

Row     = oCell.CellAddress.Row
Column  = oCell.CellAddress.Column
Content = oCell.string


' Suche nach Bereich in dem die aktive Zelle steht
oDBRanges = oDoc.DatabaseRanges
for i = 0 to oDBRanges.Count-1
    oDbrange   = oDBRanges.getByIndex(i)
    oCellrange = oDbrange.ReferredCells
    if oCellrange.queryIntersection(oCell.RangeAddress).Count > 0 then
        oRange = oCellrange
        RangeName = oDbrange.LinkDisplayName
    End If
next

' Wenn kein Bereich gefunden wurde, ist oRange undefiniert/leer
' Meldung und Abbruch
If IsEmpty(oRange) then
    msgbox "Kein Datenbereich gefunden"
    exit Sub
End if

oDoc.DatabaseRanges.getByName(RangeName).AutoFilter = True
oFilterDesc = oSheet.createFilterDescriptor(True)

if Row = oRange.RangeAddress.StartRow then   
' Prüfen, ob Cursor in der Kopfzeile des Bereiches Steht
' Wenn ja, soll der Filter gelöscht werden, um alle Elemente
' anzuzeigen
    oSheet.filter(oFilterDesc)
else
    ' Aktuelle Zelle als Filterkriterium in der Spalte verwenden
    actor() = com.sun.star.sheet.FilterOperator.EQUAL
    if Content = "" then  actor() = com.sun.star.sheet.FilterOperator.EMPTY
    ' Spezialfall, dass der Zellinhalt Leer ist
    Dim oFields(0) As New com.sun.star.sheet.TableFilterField
    With oFields(0)
     .Field = Column - oRange.RangeAddress.StartColumn  ' Filter-Spalte
     .IsNumeric = False
     .StringValue = Content '.Filterkriterium, NumericValue = any value
     .Operator = actor
    End With
    ' Filtern
    oFilterDesc.setFilterFields(oFields())
    oFilterDesc.ContainsHeader = True
    oRange.filter(oFilterDesc)
end if

oDoc.DatabaseRanges.getByName(RangeName).AutoFilter = True
oHeadCell = oSheet.getCellByPosition(Column, oRange.RangeAddress.StartRow)
oControl.Select(oHeadCell)

End Sub

Sub InsertNewRow

oDoc     = ThisComponent
oControl = oDoc.CurrentController
oSheet   = oControl.getActiveSheet
oCell    = oDoc.getCurrentSelection
oRows    = oSheet.getrows

oRange = oSheet.getCellRangeByName("FullDataSet")
row      = oRange.RangeAddress.StartRow

oRows.insertbyindex(row+1,1,false)

oSource = oSheet.getCellRangeByPosition(0,row+2,21,row+2).getRangeAddress()
oDestination =  oSheet.getCellByPosition(0,row+1).getCellAddress()

oSheet.copyRange( oDestination , oSource )

oClearRange = oSheet.getCellRangeByPosition(0,row+1,21,row+1)
oClearRange.clearContents( 7 )

End Sub

An alle, die das LibreOffice-Forum nutzen:


Bitte beteiligen Sie sich mit 7 Euro pro Monat und helfen uns bei unserem Budget für das Jahr 2024.
Einfach per Kreditkarte oder PayPal.
Als Dankeschön werden Sie im Forum als LO-SUPPORTER gekennzeichnet.

❤️ Vielen lieben Dank für Ihre Unterstützung ❤️

Antworten