Schritt 0
Voraussetzungen und Modulauswahl
- Java 17 oder neuer.
datev-exporter-plainfür feste v13/v12-Schemata und Ausgabe.datev-exporter-field-validator, wenn deterministische semantische Prüfungen vor der Annahme jeder Zeile ausgeführt werden sollen.
Das Root-Artefakt datev-exporter ist eine Bill of Materials (BOM), kein Runtime-JAR. Es richtet die Modulversionen aus; anschließend werden nur die tatsächlich verwendeten Module eingebunden.
Die Beispiele verwenden Platzhalter für Berater-/Mandantennummern und Kontenzuordnungen. Alle fachlichen Werte müssen durch für das Zielsystem freigegebene Daten ersetzt werden; die Bibliothek ordnet weder SKR03/SKR04 zu noch bestimmt sie die Steuerbehandlung.
Schritt 1A
Mit Gradle ausführen
Eine Java-Anwendung anlegen, das Java-Beispiel unten als src/main/java/Example.java speichern und dieses build.gradle verwenden:
plugins {
id 'application'
}
repositories {
mavenCentral()
}
dependencies {
implementation platform('io.github.mrtyldr:datev-exporter:0.2.0')
implementation 'io.github.mrtyldr:datev-exporter-plain'
implementation 'io.github.mrtyldr:datev-exporter-field-validator'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
application {
mainClass = 'Example'
}
Mit dem Gradle Wrapper starten:
./gradlew run
Das Repository enthält außerdem eine deterministische, durch CI ausgeführte Anwendung:
git clone https://github.com/mrtyldr/datev-exporter.git
cd datev-exporter
./gradlew :examples:quickstart-gradle:run
Schritt 1B
Mit Maven bauen
Dieselbe Example.java funktioniert mit diesem minimalen pom.xml. Die BOM verwaltet die Modulversionen:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>datev-quickstart</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.github.mrtyldr</groupId>
<artifactId>datev-exporter</artifactId>
<version>0.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.github.mrtyldr</groupId>
<artifactId>datev-exporter-plain</artifactId>
</dependency>
<dependency>
<groupId>io.github.mrtyldr</groupId>
<artifactId>datev-exporter-field-validator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.15.0</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<mainClass>Example</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
Kompilieren und ausführen:
mvn verify exec:java
Schritt 2
Vollständige v13-Datei erstellen
Diese Anwendung schreibt alle drei notwendigen Satzebenen: EXTF-Verwaltungssatz, die exakte v13-Überschrift mit 125 Spalten und eine Buchungszeile. DatevFile behält angenommene Zeilen, damit sie geprüft oder erneut ausgegeben werden können.
import io.github.mrtyldr.datev.core.DatevColumn;
import io.github.mrtyldr.datev.core.DatevField;
import io.github.mrtyldr.datev.core.DatevMetadata;
import io.github.mrtyldr.datev.core.DatevValidationContext;
import io.github.mrtyldr.datev.plain.DatevFile;
import io.github.mrtyldr.datev.validation.DatevValidator;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.LocalDateTime;
public final class Example {
public static void main(String[] args) throws Exception {
LocalDate fiscalStart = LocalDate.of(2026, 1, 1);
LocalDate periodStart = LocalDate.of(2026, 8, 1);
LocalDate periodEnd = LocalDate.of(2026, 8, 31);
DatevMetadata metadata = DatevMetadata.bookingBatchV13()
.createdAt(LocalDateTime.now())
.origin("RE")
.exportedBy("my_application")
.advisorNumber(1001)
.clientNumber(1)
.fiscalYearStart(fiscalStart)
.accountLength(4)
.period(periodStart, periodEnd)
.description("August 2026")
.applicationInformation("my-application")
.build();
DatevValidationContext context = DatevValidationContext.builder()
.accountLength(metadata.accountLength())
.fiscalYearStart(metadata.fiscalYearStart())
.period(metadata.periodStart(), metadata.periodEnd())
.build();
DatevValidator validator = DatevValidator.builder()
.context(context)
.build();
DatevFile file = DatevFile.builder()
.metadata(metadata)
.validator(validator)
.build();
file.append(
DatevColumn.amount(DatevField.AMOUNT,
new BigDecimal("1250.00")),
DatevColumn.of(DatevField.DEBIT_CREDIT_FLAG, "S"),
DatevColumn.of(DatevField.CURRENCY, "EUR"),
DatevColumn.account(DatevField.ACCOUNT, 1000),
DatevColumn.account(DatevField.CONTRA_ACCOUNT, 8400),
DatevColumn.documentDate(LocalDate.of(2026, 8, 10)),
DatevColumn.of(DatevField.DOCUMENT_FIELD_1, "RE-42"),
DatevColumn.of(DatevField.POSTING_TEXT, "Rechnung 42")
);
try (OutputStream output = Files.newOutputStream(
Path.of("EXTF_Buchungsstapel.csv"))) {
file.writeTo(output);
}
}
}
DatevField?
Lesbare englische Konstanten tragen die exakten deutschen Ausgabeüberschriften. Ein falsch geschriebener Feldname wird zum Kompilierfehler, während die Ausgabe kanonisch bleibt.
Große Exporte
Über ein gepuffertes Ziel streamen
DatevStreamWriter schreibt beim Erstellen Verwaltungssatz und Überschrift. Danach wird je append genau eine Buchungszeile vorbereitet und übergeben, ohne erfolgreiche Zeilen zu behalten. Ein ansonsten ungepuffertes Datei- oder Netzwerkziel in BufferedOutputStream einbetten, um kleine Betriebssystem-Schreibvorgänge zusammenzufassen.
import io.github.mrtyldr.datev.plain.DatevStreamWriter;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
try (OutputStream file = Files.newOutputStream(
Path.of("EXTF_Buchungsstapel.csv"));
OutputStream output = new BufferedOutputStream(file);
DatevStreamWriter writer = DatevStreamWriter.builder()
.metadata(metadata)
.validator(validator)
.build(output)) {
for (Map<String, ?> row : bookingRows) {
writer.append(row);
}
}
- Die JDK-Standardpuffergröße ist ein sinnvoller Ausgangspunkt; Anpassungen nur auf Basis von Messungen.
- Keinen zusätzlichen Puffer um
ByteArrayOutputStream,StringWriteroder ein bereits gepuffertes Ziel legen. - Der Writer leert den Puffer, schließt aber das vom Aufrufer verwaltete Ziel nicht. Durch die letzte Deklaration wird zuerst der Writer und danach Puffer und Datei geschlossen.
- Ein Validierungsfehler verändert die bestehende Ausgabe nicht. Ein E/A-Fehler kann auftreten, nachdem das Ziel einen Teil der Zeile angenommen hat; ein physisches Rollback ist unmöglich und der Writer wird terminal.
Der von der Bibliothek verwaltete Arbeitsspeicher folgt der gerade zusammengesetzten Zeile, nicht der Gesamtzahl. Validator oder Ziel – etwa ByteArrayOutputStream – können Daten trotzdem behalten. Für begrenzten Heap ist daher ein tatsächlich streamendes Ziel nötig.
Älterer Vertrag
v12 bewusst auswählen
Passende v12-Metadaten und das v12-Schema verwenden. Der Builder lehnt einen Verwaltungssatz ab, dessen Version nicht zur Überschrift mit 124 Spalten passt.
import io.github.mrtyldr.datev.core.DatevSchema;
DatevMetadata legacyMetadata = DatevMetadata.bookingBatchV12()
.createdAt(LocalDateTime.now())
.origin("RE")
.exportedBy("my_application")
.advisorNumber(1001)
.clientNumber(1)
.fiscalYearStart(fiscalStart)
.accountLength(4)
.period(periodStart, periodEnd)
.build();
DatevFile legacy = DatevFile.builder(DatevSchema.LEGACY_V12)
.metadata(legacyMetadata)
.build();
v12 wird strukturell aus den ersten 124 v13-Feldern abgeleitet und durch Bibliothekstests abgedeckt. Release 0.2.0 besitzt weder ein unabhängig fixiertes offizielles v12-Testobjekt noch ein dokumentiertes Annahmeergebnis aus einem realen Zielsystem. Siehe Versionsmatrix.
Letzter Schritt
Über die Bibliothek hinaus prüfen
Zuordnung testen
Freigegebene Konten, Steuerentscheidungen, Daten und Quellfeldzuordnungen in der Anwendung absichern.
Dateigrenze kontrollieren
Erzeugte Bytes als Windows-1252 mit CRLF-Sätzen erhalten; kein späterer UTF-8-Textschritt darf sie umschreiben.
DATEV-Werkzeuge und reales Ziel nutzen
Den passenden Prüfablauf und einen kontrollierten Import in der lizenzierten, konfigurierten Zielumgebung durchführen. Produkt/Version und Ergebnis als eigene Kompatibilitätsnachweise dokumentieren.