Am Monatsende schickt der Shop dem Steuerberater einen Stapel Rechnungs-PDFs, dazu den PayPal-Auszug und den Kontoauszug. In der Kanzlei tippt jemand die Umsätze ab, Rechnung für Rechnung, und sortiert sie nach Steuersatz. In Österreich arbeiten viele Kanzleien mit BMD NTCS oder RZL. Beide Programme können Buchungen aus einer Datei einlesen, WooCommerce liefert so eine Datei aber nicht.
Dieser Artikel zeigt, was die Kanzlei aus dem Shop braucht, wie BMD und RZL Buchungen einlesen, wie ein Export mit ein paar Zeilen Code aussieht und welche fertigen Wege es gibt.
Was die Kanzlei aus dem Shop braucht
Klären Sie das vor jeder Technik mit Ihrer Kanzlei. Sie legt Konten, Steuercodes und das Format fest, und sie entscheidet, ob sie jede Rechnung einzeln oder Summen pro Tag haben will. Meist geht es um diese Punkte:
- Erlöse nach Steuersatz. 20, 13 und 10 Prozent, seit 1. Juli 2026 dazu 4,9 Prozent für bestimmte Grundnahrungsmittel (Unternehmensserviceportal). Eine Bestellung mit Versandkosten und Produkten zu verschiedenen Sätzen wird zu mehreren Buchungen.
- Lieferungen ins Ausland. Verkaufen Sie an Privatkunden in anderen EU-Ländern über der Schwelle von 10.000 Euro, gilt die Umsatzsteuer des Ziellandes, gemeldet über den One-Stop-Shop (WKO). Diese Umsätze bucht die Kanzlei getrennt.
- Gutschriften und Stornos als eigene Belege mit negativem Betrag, nicht als geänderte Rechnung.
- Belegnummer gleich Rechnungsnummer. Über sie findet die Kanzlei den Zahlungseingang zur Rechnung.
- Zahlungsanbieter. PayPal, Stripe und Klarna zahlen gesammelt aus und ziehen ihre Gebühren vorher ab. Gebührenabrechnungen, Sammelauszahlungen und Erstattungen braucht die Kanzlei als eigene Unterlagen (FreeFinance).
Wie BMD Buchungen einliest
BMD NTCS liest Buchungen über die Schnittstelle „BuErf“ ein: eine Textdatei mit Semikolon
als Trennzeichen und einer Kopfzeile mit den Feldnamen. Die Reihenfolge der Spalten ist frei,
das Feld satzart mit dem Wert 0 kennzeichnet eine Buchungszeile. Zu den Feldern gehören
konto, gkonto, belegnr, belegdatum, buchsymbol,
buchcode, prozent, steuercode, betrag, steuer und
text (bis 40 Zeichen); extbelegnr wird zur OP-Nummer. Ist das Konto ein
Personenkonto, steht in betrag der Bruttobetrag
(Handbuch BuErf-Import, dvo).
Für Ausgangsrechnungen beschreibt eine Partnerdokumentation das Schema so: Konto ist der Debitor, Gegenkonto das Erlöskonto, Buchungssymbol AR für Rechnungen und AG für Gutschriften, Buchungscode 1, der Betrag positiv bei Rechnungen und negativ bei Gutschriften, die Steuer mit umgekehrtem Vorzeichen (COSMO CONSULT). Eine Zeile sieht dann etwa so aus:
satzart;konto;gkonto;belegnr;belegdatum;buchsymbol;buchcode;prozent;steuercode;betrag;steuer;text
0;200000;4000;1234;05.11.2026;AR;1;20;1;120,00;-20,00;Bestellung 1234
Eine öffentliche Beschreibung des Formats von BMD selbst haben wir nicht gefunden. Die Kanzleien bekommen sie in einem BMD-Seminar zum Buchungsimport, zusammen mit Vorlagen (BMD Akademie). Die Steuercodes unterscheiden sich in den Unterlagen, die wir gefunden haben. Nehmen Sie deshalb Konten, Steuercodes, Zahlenformat und Zeichensatz aus der Tabelle Ihrer Kanzlei. Beim Einlesen kann die Kanzlei den Stapel zuerst anzeigen und korrigieren, bevor sie ihn bucht (EDV Hausleitner).
Wie RZL Buchungen einliest
RZL beschreibt sein Importformat öffentlich im Handbuch Datenimport. Die Datei ist ANSI-kodiert (Codepage 1252), getrennt durch Semikolons, jede Zeile endet mit CR/LF. Anders als bei BMD haben die Felder keine Namen, sondern feste Positionen: Kontonummer, Gegenkonto, OP-Nummer, Belegdatum (TTMMJJJJ), Beträge, Belegkreis, Belegnummer, Steuerland, Steuerschlüssel, Buchungstext und weitere. Brutto muss gleich Netto plus Steuer sein, Gutschriften und Stornos sind negativ, und Sammelbuchungen erzeugt RZL selbst; sie gehören nicht in die Datei.
Zweiter Weg bei RZL: Das Programm liest auch das DATEV-Format ein, unter „Bearbeiten / Datenimport / Datev-Format“. Dafür müssen die Konten nach dem Kontenrahmen SKR 07 angelegt sein, die Belegnummern dürfen nur aus Ziffern bestehen, und RZL möchte vorher Testdaten (RZL, DATEV-Schnittstelle). DATEV-Exporte aus deutschen WooCommerce-Plugins nutzen meist die deutschen Kontenrahmen SKR 03 oder 04; das passt nicht ohne Weiteres.
Weg 1: Code, ohne Plugin
Das folgende Snippet erzeugt für einen Monat eine BMD-Datei im oben beschriebenen Schema: pro bezahlter Bestellung eine Zeile je Steuersatz, pro Erstattung eine Gutschrift. Sie rufen es als Administrator über eine Adresse auf und schicken die Datei der Kanzlei.
Bitte prüfen Sie das Snippet vor dem Einsatz in einer Testumgebung und lesen Sie die erste Datei gemeinsam mit der Kanzlei probeweise ein. Es ist ein Beispiel: Für den Einsatz in Ihrem Shop übernehmen wir keine Haftung.
Fügen Sie den Code in die functions.php Ihres Child-Themes ein oder in ein Plugin für
Code-Schnipsel:
/**
* WooCommerce-Bestellungen eines Monats als BMD-Buchungsdatei (BuErf, Ausgangsrechnungen).
* Beispiel ohne Gewähr: vor dem Einsatz in einer Testumgebung prüfen und mit der Kanzlei abstimmen.
* Aufruf als Administrator: /wp-admin/admin-post.php?action=meinshop_bmd&monat=2026-10
*/
const MEINSHOP_BMD_DEBITOR = '200000'; // Sammeldebitor für Shopkunden, laut Kanzlei
const MEINSHOP_BMD_STEUERCODE = '1'; // Steuercode für Inlandsumsatz, laut Kanzlei
const MEINSHOP_BMD_ERLOES = array( // Steuersatz => Erlöskonto, laut Kanzlei
'20' => '4000',
'13' => '4013',
'10' => '4010',
'4.9' => '4005',
);
add_action( 'admin_post_meinshop_bmd', function () {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( 'Keine Berechtigung.' );
}
$monat = isset( $_GET['monat'] ) ? sanitize_text_field( wp_unslash( $_GET['monat'] ) ) : '';
if ( ! preg_match( '/^\d{4}-\d{2}$/', $monat ) ) {
wp_die( 'Monat als JJJJ-MM angeben, z. B. 2026-10.' );
}
// Zeitstempel statt Datumstexte: ältere WooCommerce-Versionen rechnen Datumstexte falsch um.
$start = new DateTimeImmutable( $monat . '-01 00:00:00', wp_timezone() );
$bereich = $start->getTimestamp() . '...' . ( $start->modify( 'first day of next month' )->getTimestamp() - 1 );
$bestellungen = wc_get_orders( array(
'type' => 'shop_order',
'status' => array_merge( wc_get_is_paid_statuses(), array( 'refunded' ) ),
'date_paid' => $bereich,
'limit' => -1,
) );
$erstattungen = wc_get_orders( array(
'type' => 'shop_order_refund',
'date_created' => $bereich,
'limit' => -1,
) );
$zeilen = array( 'satzart;konto;gkonto;belegnr;belegdatum;buchsymbol;buchcode;prozent;steuercode;betrag;steuer;text' );
foreach ( array_merge( $bestellungen, $erstattungen ) as $beleg ) {
$gutschrift = $beleg instanceof WC_Order_Refund;
$order = $gutschrift ? wc_get_order( $beleg->get_parent_id() ) : $beleg;
$datum = $gutschrift ? $beleg->get_date_created() : $beleg->get_date_paid();
$text = ( $gutschrift ? 'Gutschrift ' : 'Bestellung ' ) . $order->get_order_number();
// Lieferungen ins Ausland (OSS, Ausfuhr) bucht die Kanzlei anders: markieren statt raten.
$land = $order->get_shipping_country() ?: $order->get_billing_country();
if ( $land && 'AT' !== $land ) {
$text = 'PRUEFEN ' . $land . ' ' . $text;
}
$saetze = meinshop_bmd_saetze( $beleg, $order );
if ( ! $saetze ) {
// Erstattung ohne Positionen: Betrag bekannt, Steuersatz nicht.
$saetze = array( '?' => array( 'netto' => -(float) $beleg->get_amount(), 'steuer' => 0 ) );
$text = 'PRUEFEN Satz ' . $text;
}
foreach ( $saetze as $satz => $summe ) {
$zeilen[] = implode( ';', array(
'0',
MEINSHOP_BMD_DEBITOR,
MEINSHOP_BMD_ERLOES[ $satz ] ?? 'KONTO?',
$order->get_order_number(),
$datum ? $datum->date( 'd.m.Y' ) : '',
$gutschrift ? 'AG' : 'AR',
'1',
str_replace( '.', ',', (string) $satz ),
MEINSHOP_BMD_STEUERCODE,
meinshop_bmd_zahl( $summe['netto'] + $summe['steuer'] ), // brutto auf dem Personenkonto
meinshop_bmd_zahl( -$summe['steuer'] ), // Steuer mit umgekehrtem Vorzeichen
mb_substr( str_replace( ';', ',', $text ), 0, 40 ),
) );
}
}
nocache_headers();
header( 'Content-Type: text/csv; charset=windows-1252' );
header( 'Content-Disposition: attachment; filename="bmd-' . $monat . '.csv"' );
echo mb_convert_encoding( implode( "\r\n", $zeilen ) . "\r\n", 'Windows-1252', 'UTF-8' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
exit;
} );
// Netto und Steuer je Steuersatz, über Artikel, Versand und Gebühren. Erstattungen sind negativ.
function meinshop_bmd_saetze( WC_Abstract_Order $beleg, WC_Order $order ) {
$prozent = array();
foreach ( $order->get_taxes() as $tax ) {
$prozent[ $tax->get_rate_id() ] = (string) (float) $tax->get_rate_percent();
}
$saetze = array();
foreach ( $beleg->get_items( array( 'line_item', 'shipping', 'fee' ) ) as $item ) {
$netto = (float) $item->get_total();
$steuern = array_filter( $item->get_taxes()['total'] ?? array(), 'floatval' );
if ( ! $netto && ! $steuern ) {
continue; // Gratisversand oder 100 % Rabatt
}
$steuern = $steuern ?: array( 0 => 0 );
$letzte = array_key_last( $steuern );
foreach ( $steuern as $rate_id => $steuer ) {
$satz = $prozent[ $rate_id ] ?? '0';
// Mehrere Sätze auf einer Position: Netto aus der Steuer zurückrechnen, der Rest geht auf den letzten Satz.
$anteil = ( $rate_id === $letzte || ! (float) $satz ) ? $netto : (float) $steuer * 100 / (float) $satz;
$netto -= $anteil;
$saetze[ $satz ]['netto'] = ( $saetze[ $satz ]['netto'] ?? 0 ) + $anteil;
$saetze[ $satz ]['steuer'] = ( $saetze[ $satz ]['steuer'] ?? 0 ) + (float) $steuer;
}
}
return $saetze;
}
function meinshop_bmd_zahl( $wert ) {
return number_format( round( $wert, 2 ), 2, ',', '' );
}
Was Sie anpassen müssen:
- Debitor, Erlöskonten und Steuercode nach der Vorgabe Ihrer Kanzlei. Fehlt ein Steuersatz in
der Liste, steht in der Datei
KONTO?. - Belegnummer und Datum, wenn Sie ein Rechnungs-Plugin nutzen. Das Snippet nimmt die Bestellnummer und das Zahlungsdatum; die Kanzlei braucht meist die Rechnungsnummer.
- Eigene Bestellstatus wie „Versendet“: Ergänzen Sie sie in der Abfrage, sonst fehlen diese Bestellungen in der Datei.
- Zahlenformat und Zeichensatz, falls die Kanzlei es anders braucht.
Was das Snippet bewusst nicht macht: Lieferungen ins Ausland richtig buchen (es markiert
sie mit PRUEFEN), Zahlungseingänge und Gebühren der Zahlungsanbieter, das RZL-Format
und einen automatischen Versand an die Kanzlei. Für einen kleinen Shop mit Kunden in
Österreich kann das reichen.
Weg 2: fertige Lösungen
Stand 7.11.2026, jeweils von der Seite des Anbieters.
WooCommerce-Plugins. Ein Plugin, das WooCommerce-Bestellungen direkt im Format von BMD oder RZL exportiert, haben wir auf WordPress.org nicht gefunden. Die verbreiteten Pakete für den deutschsprachigen Markt helfen hier wenig: Germanized nennt unter Buchhaltung PDF-Rechnungen und Lieferscheine, German Market verbindet sich mit Lexware Office und sevdesk. Buchungsstapel Order Export erzeugt eine Monatsdatei, die ein kostenpflichtiger Dienst in einen DATEV-Stapel umwandelt. Es ist auf Deutschland ausgelegt (19 und 7 Prozent, SKR 03/04).
Buchhaltungsprogramm dazwischen. FreeFinance übernimmt WooCommerce-Bestellungen über make.com (mit German Market oder Germanized) und exportiert an die Kanzlei nach BMD oder RZL. Das lohnt sich, wenn Sie ohnehin ein Programm für die eigene Buchhaltung suchen; es ist ein weiteres Werkzeug mit eigenen Kosten.
Weg 3: wir richten den Export ein
Wenn das Snippet nicht reicht, weil Sie ins Ausland verkaufen, mehrere Zahlungsanbieter haben oder die Kanzlei RZL nutzt, richten wir den Export für Ihren Shop ein. Abgestimmt mit Ihrer Kanzlei, im Format, das sie einliest, mit einer Liste der Fälle, die ein Mensch prüfen muss. Die Datei bereitet vor, gebucht wird in der Kanzlei. Mehr zu WooCommerce bei opuswerk.
Und steuerlich?
Dieser Artikel ist keine Steuerberatung. Was gebucht wird und wie, entscheidet Ihre Kanzlei. Zwei Punkte gelten unabhängig vom Export: Bücher und Belege sind sieben Jahre aufzubewahren, elektronische Unterlagen elektronisch (Unternehmensserviceportal). Und der Export ersetzt die Rechnungen nicht, er fasst sie für die Buchhaltung zusammen.
opuswerk baut WooCommerce-Shops und verbindet sie mit Buchhaltung, ERP und Versand.