Für Entwickler, Stand 31.10.2022
Einführung
MoneyMoney kann mit Extensions erweitert werden, zur Weiterverarbeitung in anderen Anwendungen zu exportieren. Diese Extensions sind kurze Lua-Skripte, die einfach zu erstellen, zu modifizieren und auszuwechseln sind.
Das Skript des CSV-Exports steht für eigene Anpassungen als Open-Source zur Verfügung. So lässt sich der CSV-Export durch Modifikation dieses Skripts bis ins Detail konfigurieren. (Download)
Die Lua-Skripte werden in einer virtuellen Maschine ausgeführt und kommunizieren über eine dokumentierte API mit MoneyMoney. Das vorliegende Dokument spezifiziert diese API. Die Wahl der Skriptsprache fiel auf Lua, da sie relativ leicht zu erlernen ist und sich gut mit C/C++/Objective-C kombinieren lässt. Für unsere Extensions reicht es vollkommen aus, die ersten fünf Kapitel von »Programming in Lua« gelesen zu haben. Die meisten innerhalb einer Extension aufgerufenen Funktionen sind nämlich gar nicht Bestandteil von Lua, sondern existieren ausschließlich in MoneyMoney.
Vom Skript zur Extension
Installation
Das Verzeichnis, in dem eigene Extensions abgelegt werden, kann über Menü Hilfe → Zeige Datenbank im Finder im Finder geöffnet werden:
~/Library/Containers/com.moneymoney-app.retail/Data/Library/Application Support/MoneyMoney/Extensions
Jede Änderung an Dateien in diesem Verzeichnis wirkt sich unmittelbar auf MoneyMoney aus, d.h. es ist nicht nötig, MoneyMoney neu zu starten.
Fehlermeldungen werden im Protokoll-Fenster von MoneyMoney angezeigt. Das Protokoll-Fenster lässt sich mit der Menüfunktion »Fenster« → »Protokollfenster« erreichen.
Die eigene Extension wird beim Aufruf der Menüfunktion »Konto« → »Umsätze exportieren« in der Formatauswahl mit der im Parameter format festgelegten Bezeichnung (siehe nächster Abschnitt) angezeigt und kann dort ausgewählt werden.
Registrierung einer Extension
Ein Skript weist sich als Export-Extension aus, indem es am Beginn des Skripts einen Aufruf der Art
Exporter{version = 1.00,
format = "Custom CSV file",
fileExtension = "csv",
description = "Export transactions as custom CSV file"}
enthält. Bei den benannten Parameter der Funktion Exporter handelt es sich um:
- Number
version: Versionsnummer der Extension - String
format(optional): Bezeichnung des Dateiformats, wie sie in der Formatauswahl des Datei-Speichern-Dialogs angezeigt wird - String
fileExtension(optional): Dateinamenserweiterung - String
bundleIdentifier(optional): Wenn dieser Parameter mit dem Bundle-Identifier einer installierten App belegt ist, wird die App im Menü »Sende Umsätze an« gelistet. - Boolean
hidden(optional): Wenn dieser Parameter mittruebelegt ist, wird diese Extension nicht im Auswahldialog für den manuellen Umsatzexport angezeigt. Standardmäßig wird die Extension angezeigt. - Boolean
reverseOrder(optional): Wenn dieser Parameter mittruebelegt ist, werden die Umsätze in umgekehrter Reihenfolge an das Skript übergeben. Standardmäßig werden die Umsätze in der gleichen Reihenfolge übergeben, wie sie in MoneyMoney angezeigt werden, d.h. neueste Umsätze zuerst. - String
description(optional): Beschreibung der Extension
Lua-Laufzeitumgebung
Die Parameter der Funktion Exporter sind später im Skript als globale Variablen version, format, fileExtension, bundleIdentifier, reverseOrder und description zugänglich. Zusätzlich ist auch noch die globale Variable extensionName mit dem Namen der Extension definiert.
Die Variablen MM.productName und MM.productVersion enthalten Informationen zur Anwendung, also MoneyMoney.
Die Ausgabe der Standard-Funktion print wird im Protokoll-Fenster von MoneyMoney angezeigt.
Die Standard-Funktion error bricht die Ausführung des Skripts ab.
Das Skript selbst muss UTF-8-kodiert sein und es werden auch alle Strings als UTF-8-Strings zwischen dem Skript und MoneyMoney übergeben, außer es steht in der API-Beschreibung, dass es sich um Binärdaten handelt.
Aufbau einer Export-Extension
Einsprungspunkte
MoneyMoney treibt die Ausführung des Skripts, was bedeutet, dass jedes Skript bestimmte Funktionen als Einsprungspunkte zur Verfügung stellen muss. MoneyMoney ruft zum Umsatzexport folgende Funktionen des Skripts auf:
WriteHeader(Dateianfang)- für jeden Buchungstag:
WriteTransactions(Umsätze schreiben) WriteTail(Dateiende)
Es wird das einfache I/O-Modell von Lua verwendet: Das Skript braucht die Daten bloß mit assert(io.write(...)) zur Standardausgabe (stdout) schreiben. Das Öffnen und Schließen der Ausgabedatei übernimmt MoneyMoney.
Dateianfang
Diese Funktion schreibt den Dateianfang:
function WriteHeader (account, startDate, endDate, transactionCount)
Parameter:
- Table
account: Das Konto, von dem die Umsätze exportiert werden; Die Strukur ist im Abschnitt »Datenstruktur eines Kontos« beschrieben. - Number
startDate: Das Buchungsdatum des ältesten Umsatzes; Die Angabe erfolgt in Form eines POSIX-Zeitstempels. - Number
endDate: Das Buchungsdatum des neuesten Umsatzes; Die Angabe erfolgt in Form eines POSIX-Zeitstempels. - Number
transactionCount: Anzahl der zu exportierenden Umsätze
Mögliche Rückgabewerte:
- Nichts oder
nil, wenn die Funktion erfolgreich war. - Ein String mit einer Fehlermeldung.
Umsätze schreiben
Diese Funktion schreibt die Umsätze eines Buchungstags in die Datei:
function WriteTransactions (account, transactions)
Parameter:
- Table
account: Das Konto, von dem die Umsätze exportiert werden; Die Strukur ist im Abschnitt »Datenstruktur eines Kontos« beschrieben. - Array
transactions: Ein Array mit den Umsätzen eines Buchungstags; Die Struktur der Array-Elemente ist im Abschnitt »Datenstruktur eines Umsatzes« beschrieben.
Mögliche Rückgabewerte:
- Nichts oder
nil, wenn die Funktion erfolgreich war. - Ein String mit einer Fehlermeldung.
Dateiende
Diese Funktion schreibt das Dateiende:
function WriteTail (account)
Parameter:
Table account: Das Konto, von dem die Umsätze exportiert werden; Die Strukur ist im Abschnitt »Datenstruktur eines Kontos« beschrieben.
Mögliche Rückgabewerte:
- Nichts oder
nil, wenn die Funktion erfolgreich war. - Ein String mit einer Fehlermeldung.
Vorlage
Folgende Vorlage kann als Ausgangspunkt für eigene Export-Extensions dienen.
Exporter{version = 1.00,
format = "Custom CSV file",
fileExtension = "csv",
description = "Export transactions as custom CSV file"}
local function csvField (str)
-- Helper function for quoting separator character and escaping double quotes.
if str == nil then
return ""
elseif string.find(str, ";") then
return '"' .. string.gsub(str, '"', '""') .. '"'
else
return str
end
end
function WriteHeader (account, startDate, endDate, transactionCount)
-- Write CSV header.
assert(io.write("Date;Value date;Category;Name;Purpose;Account;Bank;Amount;Currency\n"))
end
function WriteTransactions (account, transactions)
-- Write one line per transaction.
for _,transaction in ipairs(transactions) do
assert(io.write(csvField(MM.localizeDate(transaction.bookingDate)) .. ";" ..
csvField(MM.localizeDate(transaction.valueDate)) .. ";" ..
csvField(string.gsub(transaction.category, [[\]], " - ")) .. ";" ..
csvField(transaction.name) .. ";" ..
csvField(transaction.purpose) .. ";" ..
csvField(transaction.accountNumber) .. ";" ..
csvField(transaction.bankCode) .. ";" ..
csvField(MM.localizeNumber("0.00;-0.00", transaction.amount)) .. ";" ..
csvField(transaction.currency) .. "\n"))
end
end
function WriteTail (account)
-- Nothing to do.
end
Die API von MoneyMoney
Datenstruktur eines Kontos
Die Informationen eines Konto werden in einer Lua-Tabelle gespeichert. Folgende Felder sind definiert:
- String
name: Bezeichnung des Kontos - String
owner: Name des Kontoinhabers - String
accountNumber: Kontonummer - String
subAccount: Unterkontomerkmal - String
bankCode: Bankleitzahl - String
currency: Kontowährung - String
iban: IBAN - String
bic: BIC - Konstante
type: Kontoart; Mögliche Werte sindAccountTypeGiro(Girokonto),AccountTypeSavings(Sparkonto),AccountTypeFixedTermDeposit(Festgeldanlage),AccountTypeLoan(Darlehenskonto),AccountTypeCreditCard(Kreditkarte),AccountTypeCash(Bargeld),AccountTypeOther(Sonstige). Die Konstanten sind mit dem englischen Beschreibungstext belegt. Der in Klammern angegebene deutsche Beschreibungstext kann mit der FunktionMM.localizeTexterzeugt werden. - Table
attributes: Benutzerdefinierte Felder - String
comment: Notiz - Number
balance: Kontostand - Number
balanceDate: Datum des Kontostands; Die Angabe erfolgt in Form eines POSIX-Zeitstempels.
Datenstruktur eines Umsatzes
Die Daten eines Umsatzes werden in einer Lua-Tabelle gespeichert:
- String
name: Name des Auftraggebers/Zahlungsempfängers - String
accountNumber: Kontonummer oder IBAN des Auftraggebers/Zahlungsempfängers - String
bankCode: Bankzeitzahl oder BIC des Auftraggebers/Zahlungsempfängers - Number
amount: Betrag - String
currency: Währung - Number
bookingDate: Buchungstag; Die Angabe erfolgt in Form eines POSIX-Zeitstempels. - Number
valueDate: Wertstellungsdatum; Die Angabe erfolgt in Form eines POSIX-Zeitstempels. - String
purpose: Verwendungszweck; Mehrere Zeilen können durch Zeilenumbrüche ("\n") getrennt werden. - Number
transactionCode: Geschäftsvorfallcode - Number
textKeyExtension: Textschlüsselergänzung - String
purposeCode: SEPA-Verwendungsschlüssel - String
bookingKey: SWIFT-Buchungsschlüssel - String
bookingText: Umsatzart - String
primanotaNumber: Primanota-Nummer - String
batchReference: Sammlerreferenz - String
endToEndReference: SEPA-Ende-zu-Ende-Referenz - String
mandateReference: SEPA-Mandatsreferenz - String
creditorId: SEPA-Gläubiger-ID - String
returnReason: Rückgabegrund - Boolean
booked: Gebuchter oder vorgemerkter Umsatz - Boolean
checkmark: Als erledigt oder unerledigt markierter Umsatz - String
category: Kategorienname - String
comment: Notiz - Number
id: Interner Primärschlüssel dieses Umsatzes in der MoneyMoney-Datenbank
Sonstige Funktionen
str = MM.localizeText(str)
Mit dieser Funktion kann ein Text übersetzt werden. Diese Funktion ist primär für die mit MoneyMoney ausgelieferten Extensions gedacht. Sie ist ein Wrapper für die Cocoa-Funktion NSLocalizedString und liefert natürlich nur dann eine Übersetzung, wenn der Text in MoneyMoney hinterlegt worden ist.
Parameter:
String str: Englischer Text
Rückgabewert:
String str: Übersetzter Text
str = MM.localizeDate([format, ]date)
Lokalisiert eine Zeitangabe. Da die von Lua unterstützten POSIX Locales innerhalb von macOS-Apps nicht zur Verfügung stehen, baut diese Funktion auf der Cocoa-Klasse NSDateFormatter auf.
Parameter:
- String
format(optional): Ausgabeformat; Die Angabe erfolgt wie bei der Cocoa-KlasseNSDateFormatternach dem Unicode Technical Standard #35. - Number
date: Datum; Die Angabe erfolgt in Form eines POSIX-Zeitstempels.
Rückgabewert:
String str: Datum im lokalisierten Format
str = MM.localizeNumber([format, ]num)
Lokalisiert eine Zahl. Da die von Lua unterstützten POSIX Locales innerhalb von macOS-Apps nicht zur Verfügung stehen, baut diese Funktion auf der Cocoa-Klasse NSNumberFormatter auf.
Parameter:
- String
format(optional): Ausgabeformat; Die Angabe erfolgt wie bei der Cocoa-KlasseNSNumberFormatternach dem Unicode Technical Standard #35. - Number
num: Zahl
Rückgabewert:
String str: Zahl im lokalisierten Format
str = MM.localizeAmount([format, ]amount[, currency])
Lokalisiert einen Währungsbetrag.
Parameter:
- String
format(optional): Ausgabeformat; Die Angabe erfolgt wie bei der Cocoa-KlasseNSNumberFormatternach dem Unicode Technical Standard #35. - Number
amount: Betrag - String
currency(optional): Währung; Ohne diesen Parameter wird nur der Betrag ohne Währungsangabe zurückgegeben.
Rückgabewert:
String str: Währungsbetrag im lokalisierten Format
data = MM.toEncoding(charset, str[, bom])
Konvertiert einen Text von UTF-8 zu einem anderen Zeichensatz.
Parameter:
- String
charset: Zeichensatz; Die Angabe erfolgt wie bei HTTP nach IANA. - String
str: Text in UTF-8 - Boolean
bom(optional): Wenn dieser Parameter mittruebelegt ist, wird der Rückgabewert um eine Byte Order Mark (BOM) ergänzt, sofern sie für den angegeben Zeichensatz existiert.
Rückgabewert:
Binary data: Text im angegebenen Zeichensatz
str = MM.fromEncoding(charset, data)
Konvertiert einen Text von einem anderen Zeichensatz zu UTF-8.
Parameter:
- String
charset: Zeichensatz; Die Angabe erfolgt wie bei HTTP nach IANA. - Binary
data: Text im angegebenen Zeichensatz
Rückgabewert:
String str: Text in UTF-8