Seite 1 von 1

Berechnung von Werten mit Kreisbezug und ModifyListener

Verfasst: So 12. Mai 2013, 00:25
von hank2000
Hallo,

ich habe eine Frage zur Makroprogrammierung unter Verwendung des ModifyListener.

Mein Wunsch ist in einer Tabelle, die Gewinn und Verlust-Rechnung beinhaltet, für die Ausgaben in den Spalten Netto/Brutto, MwSt und MwSt-Satz automatisch bei festem MwSt-Satz je nach Eingabe jeweils Brutto oder Netto entsprechend zu bestimmen und in dem aktuellen Feld darzustellen. Also der MwSt-Satz ist fest, bei Eingabe von Netto wird Brutto bestimmt und umgekehrt.

In Tabellenkalkulationen anderer Hersteller habe ich gelesen geht das offenbar mit:

Code: Alles auswählen

Private Sub Worksheet_Change(ByVal Target As Range)
Außerdem habe ich gelesen daß das mit LibreOffice wohl nicht so geht. Stimmt das?

Also baue ich einen ModifyListener und registriere ihn auf die beiden Spalten Netto und Brutto. So weit so gut.

Aber nun ändere ich einen Wert, der neue Wert wird korrekt bestimmt und in die andere Spalte eingetragen, hier feuert aber das ModifyEvent und startet wiederum den Listener, der wiederum den anderen Wert berechnet, ihn wieder in die Spalte der ersten Änderung einträgt und damit wieder den ModifyEvent der ersten Spalte feuert usw. Nicht so toll :-(

Soll ich also nun vor Eintragen des neu bestimmten Wertes den Listener der Zielzelle deaktivieren? Geht das mit removeModifyListener?
Soll ich zwei unterschiedliche Listener registrieren? Hilft das?
Kann ich den Wert einer Zelle ändern ohne den ModifyListener zu aktivieren?

Gibt es eine andere Coole Lösung die ich bisher nur nicht gefunden habe?

Mein Code wird langsam etwas unübesichtlich, wenn man die propagierte Lösung von Tabellenkalkulationen anderer Hersteller so anschaut.....

Ist die Anforderung Käse?

Auf Drittspalten (Trennung von Eingabe und Anzeige) usw. habe ich eigentlich keine Lust, das wirkt dann unelegant IMHO.

Vielen Dank für Gedanken Antworten und Anregungen.

Grüße

Re: Berechnung von Werten mit Kreisbezug und ModifyListener

Verfasst: So 12. Mai 2013, 00:54
von F3K Total
Hi Hank,
warum so kompliziert?
Es gibt Tabellenereignisse, siehe Tabellenreiter, rechte Maustaste.
Dieses Makro an "Inhalt geändert" funzt in Spalte A und B:

Code: Alles auswählen

REM  *****  BASIC  *****

const Mwst = 0.19
Sub S_calculate_Netto_Brutto(event)
    if event.supportsservice("com.sun.star.sheet.SheetCell") then
        ocell = event
        ocelladdress = ocell.celladdress
        osheet = thiscomponent.sheets(ocelladdress.sheet)
        if ocelladdress.Column = 0 then'Spalte A
            dValue = ocell.value
            nrow = ocelladdress.row
            otargetcell = osheet.getcellbyposition(1,nrow)'Nachbarzelle in Spalte B
            otargetcell.value = dValue *(1 + Mwst)
        elseif ocelladdress.Column = 1 then'Spalte B
            dValue = ocell.value
            nrow = ocelladdress.row
            otargetcell = osheet.getcellbyposition(0,nrow)'Nachbarzelle in Spalte A
            otargetcell.value = dValue /(1 + Mwst)
        endif
    endif
End Sub
Siehe auch Beispieldatei.

Gruß R

Re: Berechnung von Werten mit Kreisbezug und ModifyListener

Verfasst: So 12. Mai 2013, 03:00
von hank2000
Moin R,

ja, warum so kompliziert?
Weil mir die elegante Lösung leider nicht eingefallen ist :-)
Eigentlich richtig cool, so was hatte ich mir vorgestellt, schlank und elegant.

So sieht es nun bei mir aus:

Code: Alles auswählen

REM  *****  BASIC  *****

const headerRow = 2 ' Zeile 3 enthält die Titel

Global nettoCol
Global ustCol
Global mwstCol
Global bruttoCol

Sub S_calculate_Netto_Brutto(event)

    if event.supportsservice("com.sun.star.sheet.SheetCell") then
		setCols
        ocell = event
        ocelladdress = ocell.celladdress
        osheet = thiscomponent.sheets(ocelladdress.sheet)
        nrow = ocelladdress.row

	n = osheet.getcellbyposition(nettoCol, nrow).value
	s = osheet.getcellbyposition(ustCol, nrow).value
	b = osheet.getcellbyposition(bruttoCol, nrow).value
	dValue = ocell.value

        if ocelladdress.Column = nettoCol then
            n = dValue
			m = n * s / 100
			b = m + n
			btargetcell = osheet.getcellbyposition(bruttoCol,nrow)
            btargetcell.value = b
		elseif ocelladdress.Column = bruttoCol then
			b = dValue
			m = s / (100 + s) * b
			n = b - m
			ntargetcell = osheet.getcellbyposition(nettoCol,nrow)
            ntargetcell.value = n
        endif
		mtargetcell = osheet.getcellbyposition(mwstCol,nrow)
       	mtargetcell.value = m
    endif
End Sub

Sub setCols
	mySheet = ThisComponent.CurrentController.getActiveSheet()
   	for iCol = 0 to 20 'Schleife über den Spaltenindex
		cell = mySheet.GetCellbyPosition(iCol, headerRow)
		if Instr(cell.String,"Netto-Betrag") then
			nettoCol = iCol
		elseif Instr(cell.String,"USt-Satz") then
			ustCol = iCol
		elseif Instr(cell.String,"MwSt.") then
			mwstCol = iCol
		else if Instr(cell.String,"Brutto-Betrag") then
			bruttoCol = iCol
		endif
	next
End Sub
Und damit sieht es hervorragend aus. Vielen Dank.

Jetzt fehlt nur noch die Möglichkeit herrauszubekommen, welcher Wert in desem Bereich in der Zeile als letzter geändert wurde, damit könnte dann auch eine Änderung des MwSt-Satzes den älteren Wert (nicht jüngst geänderten Wert) neu berechen.

Aber für heute reicht es erst mal.

Wie kommt man eigentlich auf solche Sachen?

Grüße

Re: Berechnung von Werten mit Kreisbezug und ModifyListener

Verfasst: So 12. Mai 2013, 07:22
von F3K Total
Moin,
hank2000 hat geschrieben:Und damit sieht es hervorragend aus. Vielen Dank.
Na ist doch Klasse, danke für das Feedback und für deinen Code. So sollte es sein, kommt leider viel zu selten vor, dass zurückgemeldet wird, wie das Endergebnis aussieht.
hank2000 hat geschrieben:Jetzt fehlt nur noch die Möglichkeit herrauszubekommen, welcher Wert in desem Bereich in der Zeile als letzter geändert wurde, damit könnte dann auch eine Änderung des MwSt-Satzes den älteren Wert (nicht jüngst geänderten Wert) neu berechen.
Ich denke, dies wird nur sicher möglich sein, wenn Du einen Timestamp in eine zusätzliche Spalte setzt und damit ein Auswahlkriterium schaffst, ala

Code: Alles auswählen

ocell.value = now()
hank2000 hat geschrieben:Wie kommt man eigentlich auf solche Sachen?
Naja, Lesen, Lernen, Probieren ... und die Verwendung eines Inspection-Tools wie MRI oder Xray
Gruß R