Simpel, aber - Kapitälchen per Makro ein/ausschalten

Programmierung unter AOO/LO (StarBasic, Python, Java, ...)

Moderator: Moderatoren

suavito
***
Beiträge: 54
Registriert: So, 19.12.2004 13:12

Simpel, aber - Kapitälchen per Makro ein/ausschalten

Beitrag von suavito »

Hallo!

Ich möchte eins vorwegschicken: Ich kenne mich mit StarBasic nicht aus und wurstle daher mit Code-Teilen herum, die der Makro-Recorder erstellt hat. Aber ganz so blöd, daß ich so ein eigentlich einfaches Problem, wie ich es hier beschreiben werde, nicht lösen kann, bin ich normalerweise nicht. (Oder eben doch? :oops: )

Um es anders zu sagen: Ich bin kein Freund von MS Word, aber manches geht da wirklich einfacher.

Das Problemchen: Ich möchte Fett, Kursiv, Unterstrichen und eben auch Kapitälchen per Tastatur ein- und ausschalten können (mit EINER Tastenkombination, nicht jeweils einer für an und aus!). Word: Makro-Recorder an, Attribut per Menü oder Icon klicken, Recorder aus, fertig. Weil: VBA verwendet die toggle-Funktion, d. h. der Wahrheitswert eines Attributs wird einfach umgekehrt. Wenn ein Wort schon kursiv ist und ich klicke auf kursiv, dann wird es "normal" - und umgekehrt.

Selbe Prozedur in OOo 1.1.4: Wenn ich aufzeichne, wie ich ein nicht-kursives Wort kursiv setze, dann wird nur genau das Einschalten aufgezeichnet. Wenn ich also mit demselben Makro auf ein schon kursives Wort zugreife, tut sich nichts, es bleibt kursiv.

Aber gut, ganz so leicht gebe ich nicht auf, und schließlich habe ich das Kursiv-Makro soweit umgebaut, das es klappt. Und so sieht es aus:
sub Kursiv
rem ----------------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Italic"
If args1(0).value = true Then
args1(0).value = false
dispatcher.executeDispatch(document, ".uno:Italic", "", 0, args1())
Else
dim args2(0) as new com.sun.star.beans.PropertyValue
rem args2(0).Name = "Bold"
args2(0).value = true
dispatcher.executeDispatch(document, ".uno:Italic", "", 0, args2())
End if


end sub
Unverständnis Nr. 1: Warum muß ich zwei Variablen (args1 und args2, die Benennungen habe ich vom Recorder übernommen) verwenden?

Unverständnis Nr. 2: Warum die rotmarkierte Zeile da nicht stehen darf (mit "rem" natürlich schon)? Nach meinem Verständnis müßte sie da zwingend hin.

Aber gut. Daß aus Recorder-Aufzeichnungen zusammengestückelter Code nicht das Optimum ist, weiß ich - und es funktioniert ja. Soweit, so gut also.

Aber mit den Kapitälchen geht das nicht so einfach.

Hier ein Testcode, mit dem die Kapitälchen eingeschaltet werden, "Kapitälchen" geschrieben wird und anschließend die Kapitälchen wieder ausgeschaltet werden:
Sub Kapitaelchentest

rem ----------------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "CaseMap"
args1(0).Value = 4

dispatcher.executeDispatch(document, ".uno:CaseMap", "", 0, args1())

rem ----------------------------------------------------------------------
dim args2(0) as new com.sun.star.beans.PropertyValue
args2(0).Name = "Text"
args2(0).Value = "Kapitälchen"

dispatcher.executeDispatch(document, ".uno:InsertText", "", 0, args2())

rem ----------------------------------------------------------------------
dim args3(0) as new com.sun.star.beans.PropertyValue
args3(0).Name = "CaseMap"
args3(0).Value = 0

dispatcher.executeDispatch(document, ".uno:CaseMap", "", 0, args3())


End Sub
Nicht sehr kompliziert, dachte ich. Muß man doch bloß die if-Struktur vom Kursiv-Makro nehmen, die als .Name "CaseMap"-Werte setzen und statt true und false 0 und 4 abfragen.

Funktioniert aber nicht. Ich bekomme nur ein Einschalten ODER ein Ausschalten (je nachdem, wie herum ich abfrage) hin. Warum, weshalb? Ich weiß es nicht.

Wer hat eine Idee? Oder noch besser, einen anderen, besseren Weg, dieses an sich unglaublich winzige Problem zu lösen?

Bin dankbar für jede Hilfe!
Stephan
********
Beiträge: 12368
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Beitrag von Stephan »

Aber ganz so blöd, daß ich so ein eigentlich einfaches Problem, wie ich es hier beschreiben werde, nicht lösen kann, bin ich normalerweise nicht. (Oder eben doch? :oops: )
Sicher nicht, aber: Was hast Du denn unternommen um (auch ohne Kenntnisse der Sprache StarBasic) Dich davon zu überzeugen, das der folgende Code so arbeitet wie Du denkst das er arbeitet? Hast Du z.B. mal mit Message-Boxen geprüft wie die Werte der Variablen sind...
sub Kursiv
rem ----------------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Italic"
If args1(0).value = true Then
args1(0).value = false
dispatcher.executeDispatch(document, ".uno:Italic", "", 0, args1())
Else
dim args2(0) as new com.sun.star.beans.PropertyValue
rem args2(0).Name = "Bold"
args2(0).value = true
dispatcher.executeDispatch(document, ".uno:Italic", "", 0, args2())
End if
end sub
Die If Then Else Prüfung funktioniert doch garnicht. Das ist reine Kosmetik. Warum?
in jeder Programmiersprache deklariert Dim eine Variable, diese ist jedoch "leer" solange keine Wertzuweisung erfolgt:

Code: Alles auswählen

dim args1(0) as new com.sun.star.beans.PropertyValue
hier z.B. erfolgt eine Wertzuweisung:

Code: Alles auswählen

args1(0).Name = "Italic"
Bloß die nächste Zeile fragt den Wert einer Variable ab obwohl diese gerade erst deklariert wurde und noch keinen Wert haben kann:

Code: Alles auswählen

If args1(0).value = true Then


Wodurch die ganze IF-Then-Else Kontruktion heiße Luft ist.

Warum funktioniert es dann?
Weil das hier genausogut funktioniert:

Code: Alles auswählen

sub Kursiv 
rem ---------------------------------------------------------------------- 
rem define variables 
dim document as object 
dim dispatcher as object 
rem ---------------------------------------------------------------------- 
rem get access to the document 
document = ThisComponent.CurrentController.Frame 
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper") 
rem ---------------------------------------------------------------------- 
dim args(0) as new com.sun.star.beans.PropertyValue 
dispatcher.executeDispatch(document, ".uno:Italic", "", 0, args()) 
end sub
Und das funktioniert deshalb weil Du auch per Menü oder Tastenkombination eine Formatierung kursiv anwenden kannst und wenn das was formatiert werden soll bereits kursiv ist dann normal wird.

Somit zunächst:
für Kursiv oder fett an/aus mit derselben Tastenkombination brauchst Du kein Makro sondern nur die Befehle kursiv oder fett wiederholen. Bei OpenOffice 1.1.4 sind das Tasten STRG+K bzw. STRG+F (das ist bei Word auch so allerdings mit STRG+UMSCHALT+F oder K)
Unverständnis Nr. 1: Warum muß ich zwei Variablen (args1 und args2, die Benennungen habe ich vom Recorder übernommen) verwenden?


Mußt Du nicht, bloß so wie Dein Code ist funktionieren die Variablen ohnehin nicht wie gewünscht (siehe oben).
Unverständnis Nr. 2: Warum die rotmarkierte Zeile da nicht stehen darf (mit "rem" natürlich schon)? Nach meinem Verständnis müßte sie da zwingend hin
Weil eine Bold-Eigenschaft nicht mit einem UNO-Aufruf .unoItalic "harmoniert" bzw. wirkungslos oder falsch ist
Wer hat eine Idee? Oder noch besser, einen anderen, besseren Weg, dieses an sich unglaublich winzige Problem zu lösen?
Für fett und kursiv die Tastenkombinationen wie oben beschrieben nutzen, für Kapitälchen diesen Code:

Code: Alles auswählen

Sub kapitaelchen
auswahl = ThisComponent.getCurrentSelection()
If Not IsNull(auswahl) Then
'nur eine zusammenhängende Auswahl
inhalt = auswahl.getByIndex(0)
if inhalt.CharCaseMap <> com.sun.star.style.CaseMap.SMALLCAPS Then
inhalt.CharCaseMap = com.sun.star.style.CaseMap.SMALLCAPS
Else
inhalt.CharCaseMap = com.sun.star.style.CaseMap.NONE
End if
End If
End sub
Hinweis:
der Code enthält keine Fehlerroutine, Du mußt also darauf achten das wirklich text und nicht z.B. eine Grafik markiert ist sonst läuft der Code nicht.
Das Makro gilt für eine zusammenhängende Auswahl, sonst müßtest Du erst prüfen wieviele Teil-Auswahlen vorliegen und über diese interieren.

das Ganze für Fett und Kursiv:

Code: Alles auswählen

Sub fett
auswahl = ThisComponent.getCurrentSelection()
If Not IsNull(auswahl) Then
'nur eine zusammenhängende Auswahl
inhalt = auswahl.getByIndex(0)
if inhalt.CharWeight <> com.sun.star.awt.FontWeight.BOLD Then
inhalt.CharWeight = com.sun.star.awt.FontWeight.BOLD
Else
inhalt.CharWeight = com.sun.star.awt.FontWeight.NORMAL
End if
End If
End sub

Code: Alles auswählen

Sub kursiv
auswahl = ThisComponent.getCurrentSelection()
If Not IsNull(auswahl) Then
'nur eine zusammenhängende Auswahl
inhalt = auswahl.getByIndex(0)
if inhalt.CharPosture <> com.sun.star.awt.FontSlant.ITALIC Then
inhalt.CharPosture = com.sun.star.awt.FontSlant.ITALIC
Else
inhalt.CharPosture = com.sun.star.awt.FontSlant.NONE
End if
End If
End sub

P.S.:
Du kannst nicht Lernen zu programmieren wenn Du den Makro-Rekorder benutzt, weil dieser nur Dispatcher-Code verwendet, was zum Programmieren zumindest unpraktisch ist. Schau Dir doch mal die Links an die ich zusammengestellt habe: viewtopic.php?t=1553

Gruß
Stephan
suavito
***
Beiträge: 54
Registriert: So, 19.12.2004 13:12

Beitrag von suavito »

Danke für die umfangreiche und (wie immer) kompetente Antwort.

Du hast natürlich recht, mit einem Makrorecorder (wie gut er auch immer ist) und damit erstellten Codebrocken kann man nicht richtig Programmieren lernen.

Aber ich sehe mich auch nicht als Developer, bislang sind es ja wirklich nur kleine Aufgaben, die ich ausführen will. Und dafür werde ich mich sicherlich nicht ins StarBasic knien. Das Handbuch-pdf hatte ich mir aber schon mal runtergeladen und durchgeguckt, aber nicht das richtige gefunden. Danke auch noch für die anderen links!

Mein Makro zum Einschalten von Kursiv hatte ich als Test gebastelt, ich wußte schon, daß man das sowieso per Tastatur einschalten kann. Und nachdem es funktionierte, dachte ich halt, würde es genügen, bloß das Attribut kursiv durch Kapitälchen zu ersetzen. Was man halt so denkt, wenn der Tag lang ist... :oops:

Daß eine Variablendeklarierung noch nicht die Zuweisung eines Wertes ist, hätte mir aber tatsächlich selber klar sein müssen, ganz ohne spezielle Kenntnisse von StarBasic.
Antworten