Initial commit – AufmaßCreater v2.35

This commit is contained in:
2026-06-10 11:03:43 +02:00
commit 84c933ea9c
2823 changed files with 490495 additions and 0 deletions
@@ -0,0 +1,383 @@
; =============================================================================
; Dataflor X31 -> California X31 Konverter (Version 4.0)
; =============================================================================
; ALLE BUGS BEHOBEN:
;
; Bug 1 (NEU GEFUNDEN): Backreference-Kollision in StringRegExpReplace
; "$1" & "2026-03-20" & "$2" → AutoIt konkateniert zu "$12026-03-20$2"
; AutoIt liest "$12" als Capture-Gruppe 12 (nicht Gruppe 1 + "2026")!
; Gleich bei Zeit: "$10" = Gruppe 10, bei GUID wenn sie mit Ziffer beginnt.
; FIX: "${1}" statt "$1" → AutoIt erkennt Gruppe 1 eindeutig.
;
; Bug 2: <QtyDetermInfo> Tag zerstört durch Anführungszeichen im Regex
; FIX: Chr(34) statt " im Regex-Muster.
;
; Bug 3: Kommentar-Regex "<!--[^>]*-->" bricht am > in URLs ab
; FIX: "<!--[\s\S]*?-->" matcht alles bis zum echten Kommentarende.
; ZUSATZ: In AutoIt muss das als separate Variable gebaut werden.
;
; Bug 4: <Street> mit rohem Zeilenumbruch → ungültiges XML
; FIX: StringRegExp Modus 1 + StringReplace (ohne Callback-Funktion).
;
; Bug 5: Doppelte #include und Global-Deklarationen
; FIX: Bereinigt.
; =============================================================================
#include <Array.au3>
Global $g_iIdCounter = 1000001
; =============================================================================
; EINSTIEGSPUNKT
; =============================================================================
If $CmdLine[0] >= 1 Then
Local $sEin = $CmdLine[1]
Local $sAus
If $CmdLine[0] >= 2 Then
$sAus = $CmdLine[2]
Else
$sAus = StringRegExpReplace($sEin, "(?i)\.x31$", "_California.x31")
If $sAus = $sEin Then $sAus &= "_California.x31"
EndIf
Local $sPrjName = ""
Local $sPrjID = ""
Local $sOwner = ""
If $CmdLine[0] >= 3 Then $sPrjName = $CmdLine[3]
If $CmdLine[0] >= 4 Then $sPrjID = $CmdLine[4]
If $CmdLine[0] >= 5 Then $sOwner = $CmdLine[5]
Dataflor_Zu_California($sEin, $sAus, $sPrjName, $sPrjID, $sOwner)
Else
Konvertieren_Dialog()
EndIf
; =============================================================================
; HAUPTFUNKTION
; =============================================================================
Func Dataflor_Zu_California($sEingabeDatei, $sAusgabeDatei, $sRefPrjName = "", $sRefPrjID = "", $sOwnerName = "")
If Not FileExists($sEingabeDatei) Then
MsgBox(16, "Fehler", "Eingabedatei nicht gefunden:" & @CRLF & $sEingabeDatei)
Return False
EndIf
Local $hLesen = FileOpen($sEingabeDatei, 0)
If $hLesen = -1 Then
MsgBox(16, "Fehler", "Konnte Datei nicht oeffnen:" & @CRLF & $sEingabeDatei)
Return False
EndIf
Local $sInhalt = FileRead($hLesen)
FileClose($hLesen)
; BOM entfernen falls vorhanden
If StringLeft($sInhalt, 3) = Chr(0xEF) & Chr(0xBB) & Chr(0xBF) Then
$sInhalt = StringMid($sInhalt, 4)
EndIf
$g_iIdCounter = 1000001
; =========================================================================
; SCHRITT 1: Zeilenenden normalisieren → einheitlich CRLF
; Muss als ERSTES passieren - Dataflor hat gemischte CR/CRLF!
; =========================================================================
$sInhalt = StringReplace($sInhalt, @CRLF, @LF)
$sInhalt = StringReplace($sInhalt, @CR, @LF)
$sInhalt = StringReplace($sInhalt, @LF, @CRLF)
; =========================================================================
; SCHRITT 2: <Street>-Zeilenumbrüche zu &#10; konvertieren
; Dataflor schreibt mehrzeilige Adressen direkt in den Tag → kaputtes XML
; StringRegExpReplace kann keine Callback-Funktion → manuell extrahieren
; =========================================================================
Local $aStreet = StringRegExp($sInhalt, "(<Street>)([\s\S]*?)(</Street>)", 1)
If Not @error Then
Local $sStreetAlt = $aStreet[0] & $aStreet[1] & $aStreet[2]
Local $sStreetNeu = $aStreet[0] & StringReplace($aStreet[1], @CRLF, "&#10;") & $aStreet[2]
$sInhalt = StringReplace($sInhalt, $sStreetAlt, $sStreetNeu)
EndIf
; =========================================================================
; SCHRITT 3: XML-Kommentar ersetzen
; BUG-FIX: "<!--[^>]*-->" bricht am > in der URL "gaeb-toolbox.de/" ab!
; Korrekt: Muster als Variable bauen → [\s\S]*? matcht alles inkl. >
; =========================================================================
Local $sKommentarMuster = "<!--[\s\S]*?-->"
$sInhalt = StringRegExpReplace($sInhalt, $sKommentarMuster, "<!-- REB 23.003 (2009) - X31 Export AutoIt v5 -->")
; =========================================================================
; SCHRITT 4: GAEBInfo - Datum, Zeit, Programm
;
; BUG-FIX: Backreference-Kollision!
; "$1" & "2026-03-20" & "$2" ergibt nach Konkatenation "$12026-03-20$2"
; AutoIt liest "$12" als Capture-Gruppe 12 → nicht vorhanden → leer!
; Gleiches bei Zeit: "$108:00:00" → Gruppe 10!
; FIX: "${1}" begrenzt die Gruppe eindeutig → kein Kollisionsproblem.
; =========================================================================
Local $sHeute = @YEAR & "-" & StringFormat("%02d", @MON) & "-" & StringFormat("%02d", @MDAY)
Local $sZeit = StringFormat("%02d", @HOUR) & ":" & StringFormat("%02d", @MIN) & ":" & StringFormat("%02d", @SEC)
$sInhalt = StringRegExpReplace($sInhalt, "(<Date>)[^<]*(</Date>)", "${1}" & $sHeute & "${2}")
$sInhalt = StringRegExpReplace($sInhalt, "(<Time>)[^<]*(</Time>)", "${1}" & $sZeit & "${2}")
$sInhalt = StringRegExpReplace($sInhalt, "(<ProgSystem>)[^<]*(</ProgSystem>)", "${1}AutoIt REB Engine V1.2${2}")
$sInhalt = StringRegExpReplace($sInhalt, "(<ProgName>)[^<]*(</ProgName>)", "${1}AutoIt REB X31 Export${2}")
; =========================================================================
; SCHRITT 5: PrjInfo anpassen (nur wenn Parameter übergeben)
; =========================================================================
If $sRefPrjName <> "" Then
$sInhalt = StringRegExpReplace($sInhalt, "(<RefPrjName>)[^<]*(</RefPrjName>)", "${1}" & $sRefPrjName & "${2}")
EndIf
If $sRefPrjID <> "" Then
$sInhalt = StringRegExpReplace($sInhalt, "(<RefPrjID>)[^<]*(</RefPrjID>)", "${1}" & $sRefPrjID & "${2}")
EndIf
; =========================================================================
; SCHRITT 6: QtyDetermInfo GUID ersetzen
;
; BUG-FIX 1: Chr(34) statt " im Regex → kein String-Terminierungs-Problem
; BUG-FIX 2: ${1} und ${2} statt $1/$2 → GUID kann mit Ziffer beginnen!
; Beispiel: GUID "3a4b..." → "$13a4b..." → AutoIt liest "$13" = Gruppe 13!
; =========================================================================
Local $sNeueGUID = _GenerateGUID()
Local $sChr34 = Chr(34)
Local $sGUIDMuster = "(QtyDetermInfo\s+ID=" & $sChr34 & ")[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(" & $sChr34 & ")"
$sInhalt = StringRegExpReplace($sInhalt, $sGUIDMuster, "${1}" & $sNeueGUID & "${2}")
; =========================================================================
; SCHRITT 7: OWN-Name anpassen (optional)
; =========================================================================
If $sOwnerName <> "" Then
Local $aOWN = StringRegExp($sInhalt, "(<OWN>[\s\S]*?</OWN>)", 1)
If Not @error Then
Local $sOWNAlt = $aOWN[0]
Local $sOWNNeu = StringRegExpReplace($sOWNAlt, "(<Name1>)[^<]*(</Name1>)", "${1}" & $sOwnerName & "${2}")
$sInhalt = StringReplace($sInhalt, $sOWNAlt, $sOWNNeu)
EndIf
EndIf
; =========================================================================
; SCHRITT 8: CtlgAssignType entfernen
; =========================================================================
$sInhalt = StringRegExpReplace($sInhalt, "\s*<CtlgAssignType\s*/>", "")
$sInhalt = StringRegExpReplace($sInhalt, "\s*<CtlgAssignType>[^<]*</CtlgAssignType>", "")
; =========================================================================
; SCHRITT 9: BVBS:Explanation entfernen
; =========================================================================
$sInhalt = StringRegExpReplace($sInhalt, "<BVBS:Explanation>[^<]*</BVBS:Explanation>", "")
; =========================================================================
; SCHRITT 10: Leere Items entfernen (Qty=0.000 ohne Mengennachweis)
; =========================================================================
Local $iMax = 30
While $iMax > 0
Local $sVorher = $sInhalt
$sInhalt = StringRegExpReplace($sInhalt, _
"<Item\s[^>]+>\s*<QtyDeterm>\s*<Qty>0[,.]000</Qty>\s*</QtyDeterm>\s*</Item>", "")
If $sInhalt = $sVorher Then ExitLoop
$iMax -= 1
WEnd
; =========================================================================
; SCHRITT 11: Leere Container bereinigen
; =========================================================================
$iMax = 10
While $iMax > 0
Local $sVorher = $sInhalt
$sInhalt = StringRegExpReplace($sInhalt, "<Itemlist>\s*</Itemlist>", "")
$sInhalt = StringRegExpReplace($sInhalt, "<BoQBody>\s*</BoQBody>", "")
$sInhalt = StringRegExpReplace($sInhalt, "<BoQCtgy[^>]*>\s*</BoQCtgy>", "")
If $sInhalt = $sVorher Then ExitLoop
$iMax -= 1
WEnd
; =========================================================================
; SCHRITT 12: IDs neu nummerieren (sequenziell ab DF_1000001)
; =========================================================================
$sInhalt = _NummeriereIDs($sInhalt)
; =========================================================================
; SCHRITT 13: Zeilen-IDs neu vergeben
; PROBLEM: Dataflor vergibt Zeilen-IDs in der ERFASSUNGSREIHENFOLGE,
; nicht in der POSITIONS-Reihenfolge. California sortiert die Anzeige
; nach Zeilen-ID → Positionen erscheinen durcheinander.
; FIX: Alle Zeilen-IDs sequenziell neu vergeben in der Reihenfolge
; wie sie im XML stehen (= Reihenfolge der Positionen).
; =========================================================================
$sInhalt = _RenummeriereZeilenIDs($sInhalt)
; =========================================================================
; SCHRITT 14: XML formatieren
; =========================================================================
$sInhalt = _FormatXML($sInhalt)
; =========================================================================
; SCHRITT 15: Ausgabedatei mit UTF-8 BOM schreiben
; =========================================================================
Local $hDatei = FileOpen($sAusgabeDatei, 2 + 128) ; 2=ueberschreiben, 128=UTF-8 BOM
If $hDatei = -1 Then
MsgBox(16, "Fehler", "Konnte Ausgabedatei nicht erstellen:" & @CRLF & $sAusgabeDatei)
Return False
EndIf
FileWrite($hDatei, $sInhalt)
FileClose($hDatei)
MsgBox(64, "Fertig", "Konvertierung abgeschlossen!" & @CRLF & @CRLF & "Ausgabe:" & @CRLF & $sAusgabeDatei)
Return True
EndFunc
; =============================================================================
; Zeilen-IDs in QTakeoff-Rows neu vergeben (sequenziell in XML-Reihenfolge)
; Verhindert falsche Reihenfolge der Positionen in California
; =============================================================================
Func _RenummeriereZeilenIDs($sXML)
; Zähler
Local $iCounter = 0
Local $iSeite = 1000
; Alle QTakeoff Rows der Reihe nach verarbeiten
; Zeilen-ID-Format: 4 Ziffern + Buchstabe (A-Z) + Ziffer (0-9)
; z.B. 1000A0, 1000A1, ..., 1000A9, 1000B0, ..., 1000Z9, 1001A0, ...
Local $iPos = 1
While True
; Nächste QTakeoff Row finden
Local $iStart = StringInStr($sXML, 'QTakeoff Row="', 0, 1, $iPos)
If $iStart = 0 Then ExitLoop
; Ende der Row suchen (schließendes ")
Local $iEnd = StringInStr($sXML, '"', 0, 1, $iStart + 14)
If $iEnd = 0 Then ExitLoop
; Row-Inhalt extrahieren
Local $sRow = StringMid($sXML, $iStart + 14, $iEnd - $iStart - 14)
; Alte Zeilen-ID am Ende der Row finden und ersetzen
; Format: ...Leerzeichen + XXXXYZ + Leerzeichen am Ende
Local $aMatch = StringRegExp($sRow, "(\s+)(\d{4}[A-Z]\d)(\s*)$", 1)
If Not @error Then
; Neue ID generieren
Local $sLetter = Chr(Asc("A") + Mod(Int($iCounter / 10), 26))
Local $sDigit = Mod($iCounter, 10)
Local $sNeueID = StringFormat("%04d", $iSeite) & $sLetter & $sDigit
$iCounter += 1
If $iCounter >= 260 Then ; A0-Z9 = 260 Kombinationen pro Seite
$iSeite += 1
$iCounter = 0
EndIf
; Alte ID durch neue ersetzen (nur in dieser Row)
Local $sAlteID = $aMatch[1]
Local $sRowNeu = StringRegExpReplace($sRow, "(\s+)\d{4}[A-Z]\d(\s*)$", "${1}" & $sNeueID & "${2}")
Local $sAltFull = 'QTakeoff Row="' & $sRow & '"'
Local $sNeuFull = 'QTakeoff Row="' & $sRowNeu & '"'
$sXML = StringReplace($sXML, $sAltFull, $sNeuFull, 1) ; Nur ERSTES Vorkommen
EndIf
$iPos = $iStart + 14
WEnd
Return $sXML
EndFunc
; =============================================================================
; IDs sequenziell neu nummerieren
; =============================================================================
Func _NummeriereIDs($sXML)
Local $aAlleIDs = StringRegExp($sXML, 'ID="(DF_[0-9]+)"', 3)
If @error Then Return $sXML
Local $aEindeutig[0]
For $i = 0 To UBound($aAlleIDs) - 1
Local $bGefunden = False
For $j = 0 To UBound($aEindeutig) - 1
If $aEindeutig[$j] = $aAlleIDs[$i] Then
$bGefunden = True
ExitLoop
EndIf
Next
If Not $bGefunden Then
ReDim $aEindeutig[UBound($aEindeutig) + 1]
$aEindeutig[UBound($aEindeutig) - 1] = $aAlleIDs[$i]
EndIf
Next
For $i = 0 To UBound($aEindeutig) - 1
Local $sNeu = "DF_" & $g_iIdCounter
$g_iIdCounter += 1
$sXML = StringReplace($sXML, 'ID="' & $aEindeutig[$i] & '"', 'ID="' & $sNeu & '"')
Next
Return $sXML
EndFunc
; =============================================================================
; XML formatieren
; =============================================================================
Func _FormatXML($sXML)
$sXML = StringRegExpReplace($sXML, ">\s+<", ">" & @CRLF & "<")
$sXML = StringReplace($sXML, "<BoQBody>", "<BoQBody>" & @CRLF)
$sXML = StringReplace($sXML, "<Itemlist>", "<Itemlist>" & @CRLF)
$sXML = StringRegExpReplace($sXML, "(<BoQCtgy[^>]*>)", "${1}" & @CRLF)
$sXML = StringRegExpReplace($sXML, "(<Item [^>]*>)", "${1}" & @CRLF)
Local $aClose[5] = ["</BoQBody>", "</Itemlist>", "</BoQCtgy>", "</Item>", "</QtyDeterm>"]
For $i = 0 To 4
$sXML = StringReplace($sXML, $aClose[$i], @CRLF & $aClose[$i] & @CRLF)
Next
$sXML = StringReplace($sXML, "<QtyDeterm>", @CRLF & "<QtyDeterm>" & @CRLF)
While StringInStr($sXML, @CRLF & @CRLF & @CRLF)
$sXML = StringReplace($sXML, @CRLF & @CRLF & @CRLF, @CRLF & @CRLF)
WEnd
While StringLeft($sXML, 2) = @CRLF
$sXML = StringMid($sXML, 3)
WEnd
Return $sXML
EndFunc
; =============================================================================
; GUID generieren
; =============================================================================
Func _GenerateGUID()
Local $aTeile[5] = [8, 4, 4, 4, 12]
Local $sGUID = ""
For $i = 0 To 4
If $i > 0 Then $sGUID &= "-"
For $j = 1 To $aTeile[$i]
$sGUID &= StringLower(Hex(Random(0, 15, 1), 1))
Next
Next
Return $sGUID
EndFunc
; =============================================================================
; Interaktiver Dialog
; =============================================================================
Func Konvertieren_Dialog()
Local $sEingabe = FileOpenDialog( _
"Dataflor X31 Datei waehlen", _
@DesktopDir, _
"X31 Dateien (*.x31)|Alle Dateien (*.*)", 1)
If @error Then Return
Local $sOrdner = StringLeft($sEingabe, StringInStr($sEingabe, "\", 0, -1) - 1)
Local $sName = StringMid($sEingabe, StringInStr($sEingabe, "\", 0, -1) + 1)
$sName = StringRegExpReplace($sName, "(?i)\.x31$", "_California.x31")
Local $sAusgabe = FileSaveDialog( _
"Ausgabedatei speichern", $sOrdner, _
"X31 Dateien (*.x31)", 2 + 16, $sName)
If @error Then Return
Local $sRefPrjName = InputBox("Projektname", _
"RefPrjName fuer California" & @CRLF & "(leer lassen = aus Dataflor uebernehmen):", "")
Local $sRefPrjID = InputBox("Projekt-ID", _
"RefPrjID fuer California" & @CRLF & "(leer lassen = aus Dataflor uebernehmen):", "")
Local $sOwner = InputBox("Aufsteller", _
"Name des Aufstellers (OWN/Name1)" & @CRLF & "(leer lassen = unveraendert):", "")
Dataflor_Zu_California($sEingabe, $sAusgabe, $sRefPrjName, $sRefPrjID, $sOwner)
EndFunc
+680
View File
@@ -0,0 +1,680 @@
#include <Array.au3>
#include <File.au3>
#include <Date.au3>
#include <Debug.au3>
#include <GUIConstantsEx.au3>
; =========================================================
; INDUSTRIAL AUTOIT REB 23.003 → GAEB X31 ENGINE
; kompatibel mit DATAflor / California / GAEB DA XML
; =========================================================
Global $INPUT_FILE = @ScriptDir & "\..\Liebenau_BA_5_Mengennachweiß_AZ002_.txt"
Global $OUTPUT_FILE = @ScriptDir & "\..\export2.x31"
Global $g_iIDCnt = 1000000
; ── Einstiegspunkt ──────────────────────────────────────────
Local $importPfadTxt = @ScriptDir & "\..\Meckenbeueren_AZ10_.txt"
Local $ausgabePfadX31 = @ScriptDir & "\..\Meckenbeueren_AZ10_x31neu.x31"
Local $templateX31 = @ScriptDir & "\..\exporthallo.x31"
_X31_Export($importPfadTxt, $ausgabePfadX31)
Func _X31_Export($sImportTxt, $sAusgabeX31)
; ── 1. Datei einlesen ────────────────────────────────────
Local $hLese = FileOpen($sImportTxt, 0)
If $hLese = -1 Then
MsgBox(16, "Fehler", "Importdatei nicht gefunden:" & @CRLF & $sImportTxt)
Return SetError(1, 0, False)
EndIf
Local $aRawLines[10001]
$aRawLines[0] = 0
While True
Local $sZ = FileReadLine($hLese)
If @error = -1 Then ExitLoop
$sZ = StringReplace($sZ, Chr(13), "")
If $aRawLines[0] < 10000 Then
$aRawLines[0] += 1
$aRawLines[$aRawLines[0]] = $sZ
EndIf
WEnd
FileClose($hLese)
If $aRawLines[0] = 0 Then
MsgBox(16, "Fehler", "Importdatei ist leer.")
Return SetError(2, 0, False)
EndIf
; ── 2. Kopfdaten lesen ───────────────────────────────────
Local $aKopf[30][2]
Local $iKopfN = 0
Local $bInKopf = False
For $i = 1 To $aRawLines[0]
Local $sL = StringStripWS($aRawLines[$i], 3)
If StringInStr($sL, "[Kopfdaten]") Then
$bInKopf = True
ContinueLoop
EndIf
If StringLeft($sL, 1) = "[" And $bInKopf Then
$bInKopf = False
ContinueLoop
EndIf
If $bInKopf Then
Local $iG = StringInStr($sL, "=")
If $iG > 0 And $iKopfN < 28 Then
$aKopf[$iKopfN][0] = StringStripWS(StringLeft($sL, $iG - 1), 3)
$aKopf[$iKopfN][1] = StringStripWS(StringMid($sL, $iG + 1), 3)
$iKopfN += 1
EndIf
EndIf
Next
; Fallback: erste 15 Zeilen
If $iKopfN = 0 Then
For $i = 1 To ($aRawLines[0] < 15 ? $aRawLines[0] : 15)
Local $sF = StringStripWS($aRawLines[$i], 3)
Local $pF = StringInStr($sF, "=")
If $pF > 0 And $iKopfN < 28 Then
$aKopf[$iKopfN][0] = StringStripWS(StringLeft($sF, $pF - 1), 3)
$aKopf[$iKopfN][1] = StringStripWS(StringMid($sF, $pF + 1), 3)
$iKopfN += 1
EndIf
Next
EndIf
Local $sDatum = _KopfGet($aKopf, "Datum")
Local $sBaustelle = _KopfGet($aKopf, "Baustelle")
Local $sBauabs = _KopfGet($aKopf, "Bauabschnitt")
Local $sVertrag = _KopfGet($aKopf, "Vertrag")
Local $sAspaN = _KopfGet($aKopf, "AspaN")
Local $sAspaTel = _KopfGet($aKopf, "AspaTel")
Local $sAbrufNr = _KopfGet($aKopf, "AbrufNr")
Local $sSMNr = _KopfGet($aKopf, "SMNr")
Local $sStartZ = _KopfGet($aKopf, "StartZ")
Local $sEndZ = _KopfGet($aKopf, "EndZ")
Local $sISODatum = _DatumISO($sDatum)
Local $sStartISO = _DatumISO($sStartZ)
Local $sEndISO = _DatumISO($sEndZ)
Local $sUID = _UUID()
Local $sBoQUID = _UUID()
Local $sLVName = ($sVertrag <> "") ? $sVertrag : ($sBaustelle & " " & $sBauabs)
; ── 3. Aufmassdaten parsen ───────────────────────────────
; Spalten: 1=Ort|2=OZ|3=Faktor|4=Einzelmenge|5|6|7=GesamtMenge|
; 8=Einheit|9=Beschreibung|10=Bemerkung|11=Menge2|12=EP|13=GP
Local $aPosData[10001][9]
; [n][0]=OZ [n][1]=Qty(float) [n][2]=Ort [n][3]=Beschreibung
; [n][4]=Bemerkung [n][5]=Einheit [n][6]=EP [n][7]=Faktor [n][8]=EinzelMenge
Local $iPosN = 0
Local $bInData = False
For $i = 1 To $aRawLines[0]
Local $sLine = StringStripWS($aRawLines[$i], 3)
If StringInStr($sLine, "[Aufma") Then
$bInData = True
ContinueLoop
EndIf
If StringLeft($sLine, 1) = "[" And $bInData Then
$bInData = False
ContinueLoop
EndIf
If Not $bInData Then ContinueLoop
If $sLine = "" Then ContinueLoop
If StringStripWS(StringReplace($sLine, "|", ""), 3) = "" Then ContinueLoop
If Not StringInStr($sLine, "|") Then ContinueLoop
Local $aS = StringSplit($sLine, "|", $STR_NOCOUNT)
Local $nS = UBound($aS)
If $nS < 2 Then ContinueLoop
Local $sOZ = ($nS > 1) ? StringStripWS($aS[1], 3) : ""
If Not _IsValidOZ($sOZ) Then ContinueLoop
Local $sOrt = ($nS > 0) ? StringStripWS($aS[0], 3) : ""
Local $sFaktor = ($nS > 2) ? StringStripWS($aS[2], 3) : "1"
Local $sEinzel = ($nS > 3) ? StringStripWS($aS[3], 3) : ""
Local $sGesamt = ($nS > 6) ? StringStripWS($aS[6], 3) : ""
Local $sEinh = ($nS > 7) ? StringStripWS($aS[7], 3) : ""
Local $sBeschr = ($nS > 8) ? StringStripWS($aS[8], 3) : ""
Local $sBemerk = ($nS > 9) ? StringStripWS($aS[9], 3) : ""
Local $sEP = ($nS > 11) ? StringStripWS($aS[11], 3) : ""
; Qty berechnen: Faktor * Einzelmenge, oder direkt Gesamtmenge
Local $fFaktor = _ToFloat($sFaktor)
Local $fEinzel = _ToFloat($sEinzel)
Local $fGesamt = _ToFloat($sGesamt)
Local $fQty = 0
If $fFaktor <> 1 And $fEinzel <> 0 Then
$fQty = $fFaktor * $fEinzel
ElseIf $fGesamt <> 0 Then
$fQty = $fGesamt
ElseIf $fEinzel <> 0 Then
$fQty = $fEinzel
Else
$fQty = $fFaktor
EndIf
$aPosData[$iPosN][0] = $sOZ
$aPosData[$iPosN][1] = $fQty
$aPosData[$iPosN][2] = $sOrt
$aPosData[$iPosN][3] = $sBeschr
$aPosData[$iPosN][4] = $sBemerk
$aPosData[$iPosN][5] = $sEinh
$aPosData[$iPosN][6] = $sEP
$aPosData[$iPosN][7] = $sFaktor
$aPosData[$iPosN][8] = $sEinzel
$iPosN += 1
If $iPosN >= 10000 Then ExitLoop
Next
If $iPosN = 0 Then
MsgBox(16, "Fehler", "Keine gueltigen Positionen gefunden.")
Return SetError(3, 0, False)
EndIf
; ── 4. OZ-Schema ermitteln ───────────────────────────────
; Bestimme Typ und maximale Segmentlängen
Local $sOZTyp = "A"
Local $iMaxL1 = 2
Local $iMaxL2 = 2
Local $iMaxL3 = 2
Local $iMaxPos = 4
For $i = 0 To $iPosN - 1
Local $aOZ = _OZInfo($aPosData[$i][0])
If $aOZ[0] = "B" Then $sOZTyp = "B"
If $aOZ[0] = "C" And $sOZTyp = "A" Then $sOZTyp = "C"
If $aOZ[6] > $iMaxL1 Then $iMaxL1 = $aOZ[6]
If $aOZ[7] > $iMaxL2 Then $iMaxL2 = $aOZ[7]
If $aOZ[8] > $iMaxL3 Then $iMaxL3 = $aOZ[8]
If $aOZ[9] > $iMaxPos Then $iMaxPos = $aOZ[9]
Next
; ── 5. OZ-Hierarchie aufbauen ────────────────────────────
Local $aTitel[100]
Local $iTitelN = 0
Local $aUTitel[1000][3] ; [n][0]=E1 [n][1]=E2 [n][2]=E3(nur Typ B)
Local $iUTitelN = 0
For $i = 0 To $iPosN - 1
Local $aOZI = _OZInfo($aPosData[$i][0])
Local $sE1 = $aOZI[1]
Local $sE2 = $aOZI[2]
Local $sE3 = $aOZI[3]
; Titel (Ebene 1)
If $sE1 <> "" Then
Local $bGefT = False
For $j = 0 To $iTitelN - 1
If $aTitel[$j] = $sE1 Then
$bGefT = True
ExitLoop
EndIf
Next
If Not $bGefT Then
$aTitel[$iTitelN] = $sE1
$iTitelN += 1
EndIf
EndIf
; Untertitel (Ebene 2 + ggf. Ebene 3)
If $sE1 <> "" Then
Local $bGefU = False
For $j = 0 To $iUTitelN - 1
If $aUTitel[$j][0] = $sE1 And $aUTitel[$j][1] = $sE2 And $aUTitel[$j][2] = $sE3 Then
$bGefU = True
ExitLoop
EndIf
Next
If Not $bGefU Then
$aUTitel[$iUTitelN][0] = $sE1
$aUTitel[$iUTitelN][1] = $sE2
$aUTitel[$iUTitelN][2] = $sE3
$iUTitelN += 1
EndIf
EndIf
Next
; ── 6. Zeit ──────────────────────────────────────────────
Local $sTime = StringRight("0" & @HOUR, 2) & ":" & StringRight("0" & @MIN, 2) & ":" & StringRight("0" & @SEC, 2)
; ── 7. XML aufbauen ──────────────────────────────────────
Local $sX = ""
$sX &= '<?xml version="1.0" encoding="UTF-8"?>' & @CRLF
$sX &= '<!-- REB 23.003 (2009) - X31 Export AutoIt v5 -->' & @CRLF
$sX &= '<GAEB xmlns="http://www.gaeb.de/GAEB_DA_XML/DA31/3.3" xmlns:BVBS="BVBS">' & @CRLF
; GAEBInfo
$sX &= '<GAEBInfo>'
$sX &= '<Version>3.3</Version>'
$sX &= '<VersDate>2023-01</VersDate>'
$sX &= '<Date>' & $sISODatum & '</Date>'
$sX &= '<Time>' & $sTime & '</Time>'
$sX &= '<ProgSystem>AutoIt REB Engine V1.2</ProgSystem>'
$sX &= '<ProgName>AutoIt REB X31 Export</ProgName>'
$sX &= '</GAEBInfo>' & @CRLF
; QtyDeterm
$sX &= '<QtyDeterm>' & @CRLF
; PrjInfo
$sX &= '<PrjInfo>'
$sX &= '<RefPrjName>' & _XE($sBaustelle) & '</RefPrjName>'
$sX &= '<RefPrjID>' & _XE($sLVName) & '</RefPrjID>'
$sX &= '</PrjInfo>' & @CRLF
; QtyDetermInfo
$sX &= '<QtyDetermInfo ID="' & $sUID & '">'
$sX &= '<MethodDescription>REB23003-2009</MethodDescription>'
If $sStartISO <> "" Then $sX &= '<PeriodFrom>' & $sStartISO & '</PeriodFrom>'
If $sEndISO <> "" Then $sX &= '<PeriodTo>' & $sEndISO & '</PeriodTo>'
$sX &= '</QtyDetermInfo>' & @CRLF
; DP
$sX &= '<DP>31</DP>' & @CRLF
; OWN (leer, aber Pflichtfeld)
$sX &= '<OWN><Address><Name1>' & _XE($sAspaN) & '</Name1><Name2></Name2>'
$sX &= '<Name3/><Name4/><Street></Street><PCode></PCode><City></City>'
$sX &= '<Contact/><Phone>' & _XE($sAspaTel) & '</Phone><Fax/><Email/>'
$sX &= '</Address></OWN>' & @CRLF
; CTR (leer, aber Pflichtfeld)
$sX &= '<CTR><Address><Name1/><Name2></Name2><Name3/><Name4/>'
$sX &= '<Street></Street><PCode></PCode><City></City>'
$sX &= '<Contact/><Phone/><Fax/><Email/></Address></CTR>' & @CRLF
; BoQ
$sX &= '<BoQ ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<RefBoQName>' & _XE($sLVName) & '</RefBoQName>'
$sX &= '<RefBoQID>' & $sBoQUID & '</RefBoQID>' & @CRLF
; BoQBkdn exakt wie funktionierende alte Version
; WICHTIG: <Num>No</Num> und <LblBoQBkdn> sind Pflicht für MWM/Dataflor!
Select
Case $sOZTyp = "A"
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Titel</LblBoQBkdn><Length>' & $iMaxL1 & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Bauteil</LblBoQBkdn><Length>' & $iMaxL2 & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Item</Type><LblBoQBkdn>Position</LblBoQBkdn><Length>' & $iMaxPos & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Index</Type><LblBoQBkdn>Index</LblBoQBkdn><Length>1</Length><Num>No</Num></BoQBkdn>'
Case $sOZTyp = "B"
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Titel</LblBoQBkdn><Length>' & $iMaxL1 & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Bauteil</LblBoQBkdn><Length>' & $iMaxL2 & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Gewerk</LblBoQBkdn><Length>' & $iMaxL3 & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Item</Type><LblBoQBkdn>Position</LblBoQBkdn><Length>' & $iMaxPos & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Index</Type><LblBoQBkdn>Index</LblBoQBkdn><Length>1</Length><Num>No</Num></BoQBkdn>'
Case $sOZTyp = "C"
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Titel</LblBoQBkdn><Length>2</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Item</Type><LblBoQBkdn>Position</LblBoQBkdn><Length>' & $iMaxPos & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Index</Type><LblBoQBkdn>Index</LblBoQBkdn><Length>1</Length><Num>No</Num></BoQBkdn>'
EndSelect
$sX &= @CRLF
; Ctlg (Pflichtfeld in alter Version)
$sX &= '<Ctlg><CtlgID>idDIN276_1993</CtlgID>'
$sX &= '<CtlgType>cost group DIN 276-93</CtlgType>'
$sX &= '<CtlgName>DIN 276-93</CtlgName></Ctlg>' & @CRLF
; BoQBody
$sX &= '<BoQBody>' & @CRLF
; OZ-Zähler für QTakeoff-Blattadressen
Local $iOZCnt = 0
; Typ C: Flachliste unter einer Sammelgruppe
If $sOZTyp = "C" Then
$sX &= '<BoQCtgy RNoPart="' & _XE($sBauabs) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody><Itemlist>' & @CRLF
For $i = 0 To $iPosN - 1
Local $aOZC = _OZInfo($aPosData[$i][0])
$sX &= _BuildItem($aPosData[$i], $aOZC[4], $iOZCnt)
Next
$sX &= '</Itemlist></BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
; Typ A: 2 Ebenen
ElseIf $sOZTyp = "A" Then
For $t = 0 To $iTitelN - 1
Local $sT = $aTitel[$t]
$sX &= '<BoQCtgy RNoPart="' & _XE($sT) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody>' & @CRLF
For $u = 0 To $iUTitelN - 1
If $aUTitel[$u][0] <> $sT Then ContinueLoop
Local $sU = $aUTitel[$u][1]
$sX &= '<BoQCtgy RNoPart="' & _XE($sU) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody><Itemlist>' & @CRLF
For $p = 0 To $iPosN - 1
Local $aOZA = _OZInfo($aPosData[$p][0])
If $aOZA[1] <> $sT Or $aOZA[2] <> $sU Then ContinueLoop
$sX &= _BuildItem($aPosData[$p], $aOZA[4], $iOZCnt)
Next
$sX &= '</Itemlist></BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
Next
$sX &= '</BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
Next
; Typ B: 3 Ebenen
ElseIf $sOZTyp = "B" Then
For $t = 0 To $iTitelN - 1
Local $sTB = $aTitel[$t]
$sX &= '<BoQCtgy RNoPart="' & _XE($sTB) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody>' & @CRLF
; Ebene 2
Local $aE2Seen[100]
Local $iE2N = 0
For $u = 0 To $iUTitelN - 1
If $aUTitel[$u][0] <> $sTB Then ContinueLoop
Local $sE2 = $aUTitel[$u][1]
; Ebene 2 nur einmal öffnen
Local $bE2New = True
For $x = 0 To $iE2N - 1
If $aE2Seen[$x] = $sE2 Then
$bE2New = False
ExitLoop
EndIf
Next
If $bE2New Then
If $iE2N > 0 Then
; Vorherige Ebene 2 schliessen
$sX &= '</BoQBody></BoQCtgy>' & @CRLF
EndIf
$aE2Seen[$iE2N] = $sE2
$iE2N += 1
$sX &= '<BoQCtgy RNoPart="' & _XE($sE2) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody>' & @CRLF
EndIf
; Ebene 3
Local $sE3 = $aUTitel[$u][2]
$sX &= '<BoQCtgy RNoPart="' & _XE($sE3) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody><Itemlist>' & @CRLF
For $p = 0 To $iPosN - 1
Local $aOZB = _OZInfo($aPosData[$p][0])
If $aOZB[1] <> $sTB Or $aOZB[2] <> $sE2 Or $aOZB[3] <> $sE3 Then ContinueLoop
$sX &= _BuildItem($aPosData[$p], $aOZB[4], $iOZCnt)
Next
$sX &= '</Itemlist></BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
Next
If $iE2N > 0 Then
$sX &= '</BoQBody></BoQCtgy>' & @CRLF
EndIf
$sX &= '</BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
Next
EndIf
$sX &= '</BoQBody>' & @CRLF
$sX &= '</BoQ>' & @CRLF
$sX &= '</QtyDeterm>' & @CRLF
$sX &= '</GAEB>'
; ── 8. Als echtes UTF-8 mit BOM speichern ────────────────
; BOM = EF BB BF, dann UTF-8 Bytes
; StringToBinary($s, 4) = UTF-8 Kodierung
If FileExists($sAusgabeX31) Then FileDelete($sAusgabeX31)
Local $binBOM = Binary("0xEFBBBF")
Local $binBody = StringToBinary($sX, 4)
Local $binFull = $binBOM & $binBody
Local $bOK = FileWrite($sAusgabeX31, $binFull)
If Not $bOK Or Not FileExists($sAusgabeX31) Then
MsgBox(16, "Fehler", "Ausgabedatei konnte nicht geschrieben werden:" & @CRLF & $sAusgabeX31)
Return SetError(4, 0, False)
EndIf
MsgBox(64, "X31 Export", "X31-Datei erfolgreich erstellt!" & @CRLF & @CRLF & _
"Datei: " & $sAusgabeX31 & @CRLF & _
"Positionen: " & $iPosN & @CRLF & _
"OZ-Typ: " & $sOZTyp & @CRLF & _
"Format: GAEB DA XML 3.3 / DA31 / REB 23.003")
Return True
EndFunc
; ==============================================================================
; _BuildItem Einzelnes <Item>-Element erzeugen
; Exakt nach funktionierender alter Struktur:
; <Item>
; <QtyDeterm>
; <Qty>N.NNN</Qty>
; <QDetermItem>
; <QTakeoff Row="K-Zeile"/>
; <BVBS:Explanation>...</BVBS:Explanation>
; </QDetermItem>
; <QDetermItem>
; <QTakeoff Row="L-Zeile"/>
; </QDetermItem>
; </QtyDeterm>
; </Item>
; ==============================================================================
Func _BuildItem(ByRef $aPos, $sPosNr, ByRef $iOZCnt)
Local $fQty = $aPos[1]
Local $sOrt = $aPos[2]
Local $sBeschr = $aPos[3]
Local $sBemerk = $aPos[4]
Local $sFaktor = $aPos[7]
Local $sEinzel = $aPos[8]
; Qty formatieren (3 Dezimalstellen)
Local $sQty = _FmtQty($fQty)
; OZ-Codes für K- und L-Zeile
Local $sOZ1 = _REBOZCode($iOZCnt)
$iOZCnt += 1
Local $sOZ2 = _REBOZCode($iOZCnt)
$iOZCnt += 1
; Formel für L-Zeile: "100091" + Qty
; z.B. "1000912.771=" entspricht Formel 91 mit Wert 2.771
Local $sFormel = "100091" & $sQty
; K-Zeilen-Text: bevorzuge Bemerkung, dann Ort
Local $sKText = $sBemerk
If $sKText = "" Then $sKText = $sOrt
If $sKText = "" Then $sKText = $sBeschr
Local $sItem = ""
$sItem &= '<Item ID="DF_' & _NextID() & '" RNoPart="' & _XE($sPosNr) & '">'
$sItem &= '<QtyDeterm>'
$sItem &= '<Qty>' & $sQty & '</Qty>'
; K-Zeile (Kommentarzeile mit Bezeichnung)
$sItem &= '<QDetermItem>'
$sItem &= '<QTakeoff Row="' & _XE(_KZeile($sKText, $sOZ1)) & '"/>'
$sItem &= '<BVBS:Explanation>' & _XE(StringStripWS($sBeschr, 3)) & '</BVBS:Explanation>'
$sItem &= '</QDetermItem>'
; L-Zeile (Mengenzeile mit Formel 91)
$sItem &= '<QDetermItem>'
$sItem &= '<QTakeoff Row="' & _XE(_LZeile($sFormel, $sOZ2)) & '"/>'
$sItem &= '</QDetermItem>'
$sItem &= '</QtyDeterm>'
$sItem &= '</Item>' & @CRLF
Return $sItem
EndFunc
; ==============================================================================
; Hilfsfunktionen
; ==============================================================================
; K-Zeile: 12sp + * + Bezeichnung(56) + OZCode(6) + 5sp = 80 Zeichen
Func _KZeile($sBez, $sOZCode)
Local $sBezPad = StringLeft($sBez & " ", 56)
Return " *" & $sBezPad & $sOZCode & " "
EndFunc
; L-Zeile: 25sp + Formel"="(44) + OZCode(6) + 5sp = 80 Zeichen
Func _LZeile($sFormel, $sOZCode)
Local $sF = StringLeft($sFormel & "=" & " ", 44)
Return " " & $sF & $sOZCode & " "
EndFunc
; REB OZ-Code aus Zähler: 0-99 → "1000B0"-Format, dann Buchstaben
Func _REBOZCode($iIdx)
If $iIdx < 100 Then
Local $s = String($iIdx)
While StringLen($s) < 3
$s = "0" & $s
WEnd
Return "100" & $s
EndIf
Local $iLIdx = $iIdx - 100
Local $sABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Local $sLet = ""
Local $iWork = $iLIdx
Do
$sLet = StringMid($sABC, Mod($iWork, 26) + 1, 1) & $sLet
$iWork = Int($iWork / 26) - 1
Until $iWork < 0
If StringLen($sLet) > 2 Then $sLet = StringRight($sLet, 2)
Return "100" & $sLet & "0"
EndFunc
; Qty auf 3 Dezimalstellen formatieren
Func _FmtQty($fVal)
; Manuell formatieren ohne StringFormat
Local $iGanz = Int($fVal)
Local $fDez = $fVal - $iGanz
If $fDez < 0 Then $fDez = -$fDez
Local $iD3 = Int($fDez * 1000 + 0.5)
Local $sDez = String($iD3)
While StringLen($sDez) < 3
$sDez = "0" & $sDez
WEnd
Return String($iGanz) & "." & $sDez
EndFunc
; OZ analysieren
Func _OZInfo($sOZ)
Local $aI[10]
$aI[0] = "?"
$aI[1] = ""
$aI[2] = ""
$aI[3] = ""
$aI[4] = $sOZ
$aI[5] = $sOZ
$aI[6] = 0
$aI[7] = 0
$aI[8] = 0
$aI[9] = 0
If $sOZ = "" Then Return $aI
If StringRegExp($sOZ, "^\d{6,10}$") Then
$aI[0] = "C"
$aI[4] = $sOZ
$aI[9] = StringLen($sOZ)
Return $aI
EndIf
Local $aS = StringSplit($sOZ, ".", $STR_NOCOUNT)
Local $n = UBound($aS)
If $n = 3 Then
$aI[0] = "A"
$aI[1] = $aS[0]
$aI[6] = StringLen($aS[0])
$aI[2] = $aS[1]
$aI[7] = StringLen($aS[1])
$aI[4] = $aS[2]
$aI[9] = StringLen($aS[2])
ElseIf $n = 4 Then
$aI[0] = "B"
$aI[1] = $aS[0]
$aI[6] = StringLen($aS[0])
$aI[2] = $aS[1]
$aI[7] = StringLen($aS[1])
$aI[3] = $aS[2]
$aI[8] = StringLen($aS[2])
$aI[4] = $aS[3]
$aI[9] = StringLen($aS[3])
EndIf
$aI[5] = $sOZ
Return $aI
EndFunc
; OZ-Typ prüfen
Func _IsValidOZ($sOZ)
If $sOZ = "" Then Return False
If StringRegExp($sOZ, "^\d{1,4}\.\d{1,4}\.\d{1,6}$") Then Return True
If StringRegExp($sOZ, "^\d{1,4}\.\d{1,4}\.\d{1,4}\.\d{1,6}$") Then Return True
If StringRegExp($sOZ, "^\d{6,10}$") Then Return True
Return False
EndFunc
; Kopfdaten-Wert lesen
Func _KopfGet(ByRef $aKopf, $sKey)
For $i = 0 To UBound($aKopf) - 1
If $aKopf[$i][0] = $sKey Then Return $aKopf[$i][1]
Next
Return ""
EndFunc
; XML-Sonderzeichen kodieren
Func _XE($s)
$s = StringReplace($s, "&", "&amp;")
$s = StringReplace($s, "<", "&lt;")
$s = StringReplace($s, ">", "&gt;")
$s = StringReplace($s, '"', "&quot;")
$s = StringReplace($s, "'", "&apos;")
Return $s
EndFunc
; String zu Float (Komma→Punkt)
Func _ToFloat($s)
If $s = "" Then Return 0
Return Number(StringReplace(StringStripWS($s, 3), ",", "."))
EndFunc
; Datum DD.MM.YYYY → YYYY-MM-DD
Func _DatumISO($s)
$s = StringStripWS($s, 3)
If StringRegExp($s, "^\d{2}\.\d{2}\.\d{4}$") Then
Local $aD = StringSplit($s, ".", $STR_NOCOUNT)
Return $aD[2] & "-" & $aD[1] & "-" & $aD[0]
EndIf
Return $s
EndFunc
; Fortlaufende DF_-ID
Func _NextID()
$g_iIDCnt += 1
Return $g_iIDCnt
EndFunc
; Pseudo-UUID
Func _UUID()
Local $sHex = "0123456789abcdef"
Local $sUID = ""
Local $aLen[5]
$aLen[0] = 8
$aLen[1] = 4
$aLen[2] = 4
$aLen[3] = 4
$aLen[4] = 12
For $i = 0 To 4
If $i > 0 Then $sUID &= "-"
For $j = 1 To $aLen[$i]
$sUID &= StringMid($sHex, Random(1, 16, 1), 1)
Next
Next
Return $sUID
EndFunc
+865
View File
@@ -0,0 +1,865 @@
#include <Array.au3>
#include <File.au3>
#include <String.au3>
#include <Date.au3>
#include <Debug.au3>
#include <Excel.au3>
#include <GUIConstantsEx.au3>
; =========================================================
; INDUSTRIAL AUTOIT REB 23.003 → GAEB X31 ENGINE
; kompatibel mit DATAflor / California / GAEB DA XML
; =========================================================
Global $INPUT_FILE = @ScriptDir & "\..\Liebenau_BA_5_Mengennachweiß_AZ002_.txt"
Global $OUTPUT_FILE = @ScriptDir & "\..\export2.x31"
; Globaler ID-Zähler für XML-IDs (muss vor Func-Aufrufen deklariert sein)
; Globaler ID-Zaehler (vor allen Local-Deklarationen)
Global $g_iIDCnt = 1000000
; ── Einstiegspunkt ──────────────────────────────────────────
Local $importPfadTxt = @ScriptDir & "\..\Meckenbeueren_AZ10_.txt"
Local $ausgabePfadX31 = @ScriptDir & "\..\Meckenbeueren_AZ10_x31neu.x31"
Local $exportExcelCalifornia = @ScriptDir & "\..\Meckenbeueren_AZ10_.xlsx"
;~ Local $importPfadTxt = @ScriptDir & "\..\FTTx_Achberg_AZ001_.txt"
;~ Local $ausgabePfadX31 = @ScriptDir & "\..\FTTx_Achberg_AZ001_x31neu.x31"
; Beispiel Aufruf
_REB_TXT_to_Excel($importPfadTxt,$exportExcelCalifornia)
;~ _X31_Export($importPfadTxt, $ausgabePfadX31)
Func _replaceKom2Punkt($sString)
Return StringReplace($sString, ",", ".")
EndFunc ;==>_replaceKom2Punkt
Func _replacePunkt2Koma($sString)
Return StringReplace($sString, ".", ",")
EndFunc ;==>_replacePunkt2Koma
Func _REB_TXT_to_Excel($sTXT, $sExcel)
Local $aLines
_FileReadToArray($sTXT, $aLines)
Local $Baustelle = ""
Local $Datum = ""
Local $Abschnitt = ""
Local $inHeader = False
Local $inData = False
; Kopf auslesen
For $i = 1 To $aLines[0]
Local $line = $aLines[$i]
If StringInStr($line, "[Kopfdaten]") Then
$inHeader = True
ContinueLoop
EndIf
If StringInStr($line, "[Aufmaßdaten]") Then
$inHeader = False
$inData = True
ExitLoop
EndIf
If $inHeader Then
If StringLeft($line, 9) = "Baustelle" Then
$Baustelle = StringTrimLeft($line, 10)
EndIf
If StringLeft($line, 5) = "Datum" Then
$Datum = StringTrimLeft($line, 6)
EndIf
If StringLeft($line, 13) = "Bauabschnitt=" Then
$Abschnitt = StringTrimLeft($line, 13)
EndIf
EndIf
Next
; Excel starten
Local $oExcel = _Excel_Open()
Local $oBook = _Excel_BookNew($oExcel)
; Kopf schreiben
_Excel_RangeWrite($oBook, Default, "Bauvorhaben", "A2")
_Excel_RangeWrite($oBook, Default, $Baustelle, "C2")
_Excel_RangeWrite($oBook, Default, "Leistungsverzeichnis", "A3")
_Excel_RangeWrite($oBook, Default, $Abschnitt, "C3")
_Excel_RangeWrite($oBook, Default, "Aufmaß", "A4")
_Excel_RangeWrite($oBook, Default, $Datum, "D4")
; Spaltenüberschrift
;~ _Excel_RangeWrite($oBook, Default, "OZ", "A7")
;~ _Excel_RangeWrite($oBook, Default, "Position", "B7")
;~ _Excel_RangeWrite($oBook, Default, "Abschnitt", "C7")
;~ _Excel_RangeWrite($oBook, Default, "Faktor", "D7")
;~ _Excel_RangeWrite($oBook, Default, "REB Formel", "E7")
;~ _Excel_RangeWrite($oBook, Default, "Ergebnis", "F7")
Local $row = 7
$inData = False
For $i = 1 To $aLines[0]
Local $line = $aLines[$i]
If StringInStr($line, "[Aufmaßdaten]") Then
$inData = True
ContinueLoop
EndIf
If $inData = False Then ContinueLoop
If StringStripWS($line, 8) = "" Then ContinueLoop
Local $f = StringSplit($line, "|")
If $f[0] < 10 Then ContinueLoop
Local $Ort = $f[1]
Local $OZ = $f[2]
Local $Formel = $f[3]
Local $Ergebnis = $f[7]
Local $Text = $f[9]
; Zeile 1 (Bemerkung)
_Excel_RangeWrite($oBook, Default, $OZ, "A" & $row)
_Excel_RangeWrite($oBook, Default, $Text, "B" & $row)
_Excel_RangeWrite($oBook, Default, $Ort, "C" & $row)
$row += 1
; Zeile 2 (Formel)
_Excel_RangeWrite($oBook, Default, $OZ, "A" & $row)
_Excel_RangeWrite($oBook, Default, "", "B" & $row)
_Excel_RangeWrite($oBook, Default, "", "C" & $row)
_Excel_RangeWrite($oBook, Default, $Formel, "D" & $row)
_Excel_RangeWrite($oBook, Default, $Formel, "E" & $row)
_Excel_RangeWrite($oBook, Default, $Ergebnis, "F" & $row)
$row += 1
Next
_Excel_BookSaveAs($oBook, $sExcel)
_Excel_Close($oExcel)
EndFunc
Func _X31_Export($sImportTxt, $sAusgabeX31)
; ── 1. Datei einlesen ────────────────────────────────────
Local $hLese = FileOpen($sImportTxt, 0)
If $hLese = -1 Then
MsgBox(16, "Fehler", "Importdatei nicht gefunden:" & @CRLF & $sImportTxt)
Return SetError(1, 0, False)
EndIf
Local $aRawLines[10001]
$aRawLines[0] = 0
While True
Local $sZ = FileReadLine($hLese)
If @error = -1 Then ExitLoop
$sZ = StringReplace($sZ, Chr(13), "")
If $aRawLines[0] < 10000 Then
$aRawLines[0] += 1
$aRawLines[$aRawLines[0]] = $sZ
EndIf
WEnd
FileClose($hLese)
If $aRawLines[0] = 0 Then
MsgBox(16, "Fehler", "Importdatei ist leer.")
Return SetError(2, 0, False)
EndIf
; ── 2. Kopfdaten lesen ───────────────────────────────────
Local $aKopf[30][2]
Local $iKopfN = 0
Local $bInKopf = False
For $i = 1 To $aRawLines[0]
Local $sL = StringStripWS($aRawLines[$i], 3)
If StringInStr($sL, "[Kopfdaten]") Then
$bInKopf = True
ContinueLoop
EndIf
If StringLeft($sL, 1) = "[" And $bInKopf Then
$bInKopf = False
ContinueLoop
EndIf
If $bInKopf Then
Local $iG = StringInStr($sL, "=")
If $iG > 0 And $iKopfN < 28 Then
$aKopf[$iKopfN][0] = StringStripWS(StringLeft($sL, $iG - 1), 3)
$aKopf[$iKopfN][1] = StringStripWS(StringMid($sL, $iG + 1), 3)
$iKopfN += 1
EndIf
EndIf
Next
; Fallback: erste 15 Zeilen
If $iKopfN = 0 Then
For $i = 1 To ($aRawLines[0] < 15 ? $aRawLines[0] : 15)
Local $sF = StringStripWS($aRawLines[$i], 3)
Local $pF = StringInStr($sF, "=")
If $pF > 0 And $iKopfN < 28 Then
$aKopf[$iKopfN][0] = StringStripWS(StringLeft($sF, $pF - 1), 3)
$aKopf[$iKopfN][1] = StringStripWS(StringMid($sF, $pF + 1), 3)
$iKopfN += 1
EndIf
Next
EndIf
Local $sDatum = _KopfGet($aKopf, "Datum")
Local $sBaustelle = _KopfGet($aKopf, "Baustelle")
Local $sBauabs = _KopfGet($aKopf, "Bauabschnitt")
Local $sVertrag = _KopfGet($aKopf, "Vertrag")
Local $sAspaN = _KopfGet($aKopf, "AspaN")
Local $sAspaTel = _KopfGet($aKopf, "AspaTel")
Local $sAbrufNr = _KopfGet($aKopf, "AbrufNr")
Local $sSMNr = _KopfGet($aKopf, "SMNr")
Local $sStartZ = _KopfGet($aKopf, "StartZ")
Local $sEndZ = _KopfGet($aKopf, "EndZ")
Local $sISODatum = _DatumISO($sDatum)
Local $sStartISO = _DatumISO($sStartZ)
Local $sEndISO = _DatumISO($sEndZ)
Local $sUID = _UUID()
Local $sBoQUID = _UUID()
Local $sLVName = ($sVertrag <> "") ? $sVertrag : ($sBaustelle & " " & $sBauabs)
; Feldlängen auf Dataflor-Limits kürzen
; RefBoQName / RefPrjID: max. 20 Zeichen
; RefPrjName / Name1: max. 50 Zeichen
Local $sLVName20 = StringLeft($sLVName, 20)
Local $sBaust50 = StringLeft($sBaustelle, 50)
; ── 3. Aufmassdaten parsen ───────────────────────────────
; Spalten: 1=Ort|2=OZ|3=Faktor|4=Einzelmenge|5|6|7=GesamtMenge|
; 8=Einheit|9=Beschreibung|10=Bemerkung|11=Menge2|12=EP|13=GP
Local $aPosData[10001][9]
; [n][0]=OZ [n][1]=Qty(float) [n][2]=Ort [n][3]=Beschreibung
; [n][4]=Bemerkung [n][5]=Einheit [n][6]=EP [n][7]=Faktor [n][8]=EinzelMenge
Local $iPosN = 0
Local $bInData = False
For $i = 1 To $aRawLines[0]
Local $sLine = StringStripWS($aRawLines[$i], 3)
If StringInStr($sLine, "[Aufma") Then
$bInData = True
ContinueLoop
EndIf
If StringLeft($sLine, 1) = "[" And $bInData Then
$bInData = False
ContinueLoop
EndIf
If Not $bInData Then ContinueLoop
If $sLine = "" Then ContinueLoop
If StringStripWS(StringReplace($sLine, "|", ""), 3) = "" Then ContinueLoop
If Not StringInStr($sLine, "|") Then ContinueLoop
Local $aS = StringSplit($sLine, "|", $STR_NOCOUNT)
Local $nS = UBound($aS)
If $nS < 2 Then ContinueLoop
Local $sOZ = ($nS > 1) ? StringStripWS($aS[1], 3) : ""
If Not _IsValidOZ($sOZ) Then ContinueLoop
Local $sOrt = ($nS > 0) ? StringStripWS($aS[0], 3) : ""
Local $sFaktor = ($nS > 2) ? StringStripWS($aS[2], 3) : "1"
Local $sEinzel = ($nS > 3) ? StringStripWS($aS[3], 3) : ""
Local $sGesamt = ($nS > 6) ? StringStripWS($aS[6], 3) : ""
Local $sEinh = ($nS > 7) ? StringStripWS($aS[7], 3) : ""
Local $sBeschr = ($nS > 8) ? StringStripWS($aS[8], 3) : ""
Local $sBemerk = ($nS > 9) ? StringStripWS($aS[9], 3) : ""
Local $sEP = ($nS > 11) ? StringStripWS($aS[11], 3) : ""
; Qty berechnen: Faktor * Einzelmenge, oder direkt Gesamtmenge
Local $fFaktor = _ToFloat($sFaktor)
Local $fEinzel = _ToFloat($sEinzel)
Local $fGesamt = _ToFloat($sGesamt)
Local $fQty = 0
If $fFaktor <> 1 And $fEinzel <> 0 Then
$fQty = $fFaktor * $fEinzel
ElseIf $fGesamt <> 0 Then
$fQty = $fGesamt
ElseIf $fEinzel <> 0 Then
$fQty = $fEinzel
Else
$fQty = $fFaktor
EndIf
$aPosData[$iPosN][0] = $sOZ
$aPosData[$iPosN][1] = $fQty
$aPosData[$iPosN][2] = $sOrt
$aPosData[$iPosN][3] = $sBeschr
$aPosData[$iPosN][4] = $sBemerk
$aPosData[$iPosN][5] = $sEinh
$aPosData[$iPosN][6] = $sEP
$aPosData[$iPosN][7] = $sFaktor
$aPosData[$iPosN][8] = $sEinzel
$iPosN += 1
If $iPosN >= 10000 Then ExitLoop
Next
If $iPosN = 0 Then
MsgBox(16, "Fehler", "Keine gueltigen Positionen gefunden.")
Return SetError(3, 0, False)
EndIf
; ── 4. OZ-Schema ermitteln ───────────────────────────────
; Typ bestimmen und OZ-Typ-spezifische Standard-Lengths setzen
; WICHTIG: Length = Feldbreite laut OZ-Maske, NICHT max. Zeichenlänge des Werts!
; Dataflor liest die Length aus BoQBkdn und ordnet OZ-Segmente zu.
; Falsche Lengths = kein Import (Segmente passen nicht ins Feld).
;
; Standard-Lengths (aus D11-OZ-Masken abgeleitet):
; Typ A (XX.XX.XXXX): L1=2, L2=2, L3=4 (Maske: 22PPPPi)
; Typ B (X.X.XX.XXXX): L1=1, L2=2, L3=3, L4=4 (Maske: 123PPPi)
; Typ C (XXXXXXXX): L1=8 (Maske: PPPPPPPPi)
Local $sOZTyp = "A"
Local $iMaxPos = 4
For $i = 0 To $iPosN - 1
Local $aOZ = _OZInfo($aPosData[$i][0])
If $aOZ[0] = "B" Then $sOZTyp = "B"
If $aOZ[0] = "C" And $sOZTyp = "A" Then $sOZTyp = "C"
If $aOZ[9] > $iMaxPos Then $iMaxPos = $aOZ[9]
Next
; Feste Standard-Lengths je Typ (aus D11-OZ-Maske)
Local $iL1 = 2 ; Typ A/C Standard
Local $iL2 = 2
Local $iL3 = 2
Select
Case $sOZTyp = "A"
$iL1 = 2 ; z.B. '01'
$iL2 = 2 ; z.B. '03'
; $iMaxPos bereits 4 für '0008'
Case $sOZTyp = "B"
$iL1 = 1 ; z.B. '1' (1 Stelle)
$iL2 = 2 ; z.B. '3' (Feld 2-stellig laut Maske)
$iL3 = 3 ; z.B. '01' (Feld 3-stellig laut Maske '123PPPi')
; $iMaxPos bereits 4 für '0470'
Case $sOZTyp = "C"
; keine Ebenen, nur Item
EndSelect
; ── 5. OZ-Hierarchie aufbauen ────────────────────────────
Local $aTitel[100]
Local $iTitelN = 0
Local $aUTitel[1000][3] ; [n][0]=E1 [n][1]=E2 [n][2]=E3(nur Typ B)
Local $iUTitelN = 0
For $i = 0 To $iPosN - 1
Local $aOZI = _OZInfo($aPosData[$i][0])
Local $sE1 = $aOZI[1]
Local $sE2 = $aOZI[2]
Local $sE3 = $aOZI[3]
; Titel (Ebene 1)
If $sE1 <> "" Then
Local $bGefT = False
For $j = 0 To $iTitelN - 1
If $aTitel[$j] = $sE1 Then
$bGefT = True
ExitLoop
EndIf
Next
If Not $bGefT Then
$aTitel[$iTitelN] = $sE1
$iTitelN += 1
EndIf
EndIf
; Untertitel (Ebene 2 + ggf. Ebene 3)
If $sE1 <> "" Then
Local $bGefU = False
For $j = 0 To $iUTitelN - 1
If $aUTitel[$j][0] = $sE1 And $aUTitel[$j][1] = $sE2 And $aUTitel[$j][2] = $sE3 Then
$bGefU = True
ExitLoop
EndIf
Next
If Not $bGefU Then
$aUTitel[$iUTitelN][0] = $sE1
$aUTitel[$iUTitelN][1] = $sE2
$aUTitel[$iUTitelN][2] = $sE3
$iUTitelN += 1
EndIf
EndIf
Next
; ── 6. Zeit ──────────────────────────────────────────────
Local $sTime = StringRight("0" & @HOUR, 2) & ":" & StringRight("0" & @MIN, 2) & ":" & StringRight("0" & @SEC, 2)
; ── 7. XML aufbauen ──────────────────────────────────────
Local $sX = ""
$sX &= '<?xml version="1.0" encoding="UTF-8"?>' & @CRLF
$sX &= '<!-- REB 23.003 (2009) - X31 Export AutoIt v5 -->' & @CRLF
$sX &= '<GAEB xmlns="http://www.gaeb.de/GAEB_DA_XML/DA31/3.3" xmlns:BVBS="BVBS">' & @CRLF
; GAEBInfo
$sX &= '<GAEBInfo>'
$sX &= '<Version>3.3</Version>'
$sX &= '<VersDate>2023-01</VersDate>'
$sX &= '<Date>' & $sISODatum & '</Date>'
$sX &= '<Time>' & $sTime & '</Time>'
$sX &= '<ProgSystem>AutoIt REB Engine V1.2</ProgSystem>'
$sX &= '<ProgName>AutoIt REB X31 Export</ProgName>'
$sX &= '</GAEBInfo>' & @CRLF
; QtyDeterm
$sX &= '<QtyDeterm>' & @CRLF
; PrjInfo
$sX &= '<PrjInfo>'
$sX &= '<RefPrjName>' & _XE($sBaust50) & '</RefPrjName>'
$sX &= '<RefPrjID>' & _XE($sLVName20) & '</RefPrjID>'
$sX &= '</PrjInfo>' & @CRLF
; QtyDetermInfo NUR MethodDescription laut GAEB DA XML 3.3 Schema!
; PeriodFrom/PeriodTo sind in QtyDetermInfo NICHT erlaubt → Dataflor-Warnung
$sX &= '<QtyDetermInfo ID="' & $sUID & '">'
$sX &= '<MethodDescription>REB23003-2009</MethodDescription>'
$sX &= '</QtyDetermInfo>' & @CRLF
; DP
$sX &= '<DP>31</DP>' & @CRLF
; OWN (leer, aber Pflichtfeld)
$sX &= '<OWN><Address><Name1>' & _XE($sAspaN) & '</Name1><Name2></Name2>'
$sX &= '<Name3/><Name4/><Street></Street><PCode></PCode><City></City>'
$sX &= '<Contact/><Phone>' & _XE($sAspaTel) & '</Phone><Fax/><Email/>'
$sX &= '</Address></OWN>' & @CRLF
; CTR (leer, aber Pflichtfeld)
$sX &= '<CTR><Address><Name1/><Name2></Name2><Name3/><Name4/>'
$sX &= '<Street></Street><PCode></PCode><City></City>'
$sX &= '<Contact/><Phone/><Fax/><Email/></Address></CTR>' & @CRLF
; BoQ
$sX &= '<BoQ ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<RefBoQName>' & _XE($sLVName20) & '</RefBoQName>'
$sX &= '<RefBoQID>' & $sBoQUID & '</RefBoQID>' & @CRLF
; BoQBkdn exakt wie funktionierende alte Version
; WICHTIG: <Num>No</Num> und <LblBoQBkdn> sind Pflicht für MWM/Dataflor!
Select
Case $sOZTyp = "A"
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Titel</LblBoQBkdn><Length>' & $iL1 & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Bauteil</LblBoQBkdn><Length>' & $iL2 & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Item</Type><LblBoQBkdn>Position</LblBoQBkdn><Length>' & $iMaxPos & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Index</Type><LblBoQBkdn>Index</LblBoQBkdn><Length>1</Length><Num>No</Num></BoQBkdn>'
Case $sOZTyp = "B"
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Titel</LblBoQBkdn><Length>' & $iL1 & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Bauteil</LblBoQBkdn><Length>' & $iL2 & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Gewerk</LblBoQBkdn><Length>' & $iL3 & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Item</Type><LblBoQBkdn>Position</LblBoQBkdn><Length>' & $iMaxPos & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Index</Type><LblBoQBkdn>Index</LblBoQBkdn><Length>1</Length><Num>No</Num></BoQBkdn>'
Case $sOZTyp = "C"
$sX &= '<BoQBkdn><Type>BoQLevel</Type><LblBoQBkdn>Titel</LblBoQBkdn><Length>2</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Item</Type><LblBoQBkdn>Position</LblBoQBkdn><Length>' & $iMaxPos & '</Length><Num>No</Num></BoQBkdn>'
$sX &= '<BoQBkdn><Type>Index</Type><LblBoQBkdn>Index</LblBoQBkdn><Length>1</Length><Num>No</Num></BoQBkdn>'
EndSelect
$sX &= @CRLF
; Ctlg (Pflichtfeld in alter Version)
$sX &= '<Ctlg><CtlgID>idDIN276_1993</CtlgID>'
$sX &= '<CtlgType>cost group DIN 276-93</CtlgType>'
$sX &= '<CtlgName>DIN 276-93</CtlgName></Ctlg>' & @CRLF
; BoQBody
$sX &= '<BoQBody>' & @CRLF
; OZ-Zähler für QTakeoff-Blattadressen
Local $iOZCnt = 0
; Typ C: Flachliste unter einer Sammelgruppe
If $sOZTyp = "C" Then
$sX &= '<BoQCtgy RNoPart="' & _XE($sBauabs) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody><Itemlist>' & @CRLF
For $i = 0 To $iPosN - 1
Local $aOZC = _OZInfo($aPosData[$i][0])
$sX &= _BuildItem($aOZC[4], $aPosData[$i][1], $aPosData[$i][2], $aPosData[$i][3], $aPosData[$i][4], $iOZCnt, $aPosData[$i][7], $aPosData[$i][8])
Next
$sX &= '</Itemlist></BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
; Typ A: 2 Ebenen
ElseIf $sOZTyp = "A" Then
For $t = 0 To $iTitelN - 1
Local $sT = $aTitel[$t]
$sX &= '<BoQCtgy RNoPart="' & _XE($sT) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody>' & @CRLF
For $u = 0 To $iUTitelN - 1
If $aUTitel[$u][0] <> $sT Then ContinueLoop
Local $sU = $aUTitel[$u][1]
$sX &= '<BoQCtgy RNoPart="' & _XE($sU) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody><Itemlist>' & @CRLF
For $p = 0 To $iPosN - 1
Local $aOZA = _OZInfo($aPosData[$p][0])
If $aOZA[1] <> $sT Or $aOZA[2] <> $sU Then ContinueLoop
$sX &= _BuildItem($aOZA[4], $aPosData[$p][1], $aPosData[$p][2], $aPosData[$p][3], $aPosData[$p][4], $iOZCnt, $aPosData[$p][7], $aPosData[$p][8])
Next
$sX &= '</Itemlist></BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
Next
$sX &= '</BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
Next
; Typ B: 3 Ebenen (E1.E2.E3.Pos)
ElseIf $sOZTyp = "B" Then
; Eindeutige E1-Werte (bereits in $aTitel)
For $t = 0 To $iTitelN - 1
Local $sTB = $aTitel[$t]
$sX &= '<BoQCtgy RNoPart="' & _XE($sTB) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody>' & @CRLF
; Eindeutige E2-Werte unter diesem E1
Local $aE2List[100]
Local $iE2Cnt = 0
For $u = 0 To $iUTitelN - 1
If $aUTitel[$u][0] <> $sTB Then ContinueLoop
Local $sE2Chk = $aUTitel[$u][1]
Local $bDup = False
For $x = 0 To $iE2Cnt - 1
If $aE2List[$x] = $sE2Chk Then
$bDup = True
ExitLoop
EndIf
Next
If Not $bDup Then
$aE2List[$iE2Cnt] = $sE2Chk
$iE2Cnt += 1
EndIf
Next
; Für jedes E2 unter diesem E1
For $e2i = 0 To $iE2Cnt - 1
Local $sCurE2 = $aE2List[$e2i]
$sX &= '<BoQCtgy RNoPart="' & _XE($sCurE2) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody>' & @CRLF
; Alle E3-Werte unter diesem E1.E2
For $u = 0 To $iUTitelN - 1
If $aUTitel[$u][0] <> $sTB Then ContinueLoop
If $aUTitel[$u][1] <> $sCurE2 Then ContinueLoop
Local $sCurE3 = $aUTitel[$u][2]
$sX &= '<BoQCtgy RNoPart="' & _XE($sCurE3) & '" ID="DF_' & _NextID() & '">' & @CRLF
$sX &= '<BoQBody><Itemlist>' & @CRLF
; Positionen unter diesem E1.E2.E3
For $p = 0 To $iPosN - 1
Local $aOZB = _OZInfo($aPosData[$p][0])
If $aOZB[1] <> $sTB Or $aOZB[2] <> $sCurE2 Or $aOZB[3] <> $sCurE3 Then ContinueLoop
$sX &= _BuildItem($aOZB[4], $aPosData[$p][1], $aPosData[$p][2], $aPosData[$p][3], $aPosData[$p][4], $iOZCnt, $aPosData[$p][7], $aPosData[$p][8])
Next
$sX &= '</Itemlist></BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
Next
$sX &= '</BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
Next
$sX &= '</BoQBody>' & @CRLF
$sX &= '</BoQCtgy>' & @CRLF
Next
EndIf
$sX &= '</BoQBody>' & @CRLF
$sX &= '</BoQ>' & @CRLF
$sX &= '</QtyDeterm>' & @CRLF
$sX &= '</GAEB>'
; ── 8. Als echtes UTF-8 mit BOM speichern ────────────────
; BOM = EF BB BF, dann UTF-8 Bytes
; StringToBinary($s, 4) = UTF-8 Kodierung
If FileExists($sAusgabeX31) Then FileDelete($sAusgabeX31)
Local $binBOM = Binary("0xEFBBBF")
Local $binBody = StringToBinary($sX, 4)
Local $binFull = $binBOM & $binBody
Local $bOK = FileWrite($sAusgabeX31, $binFull)
If Not $bOK Or Not FileExists($sAusgabeX31) Then
MsgBox(16, "Fehler", "Ausgabedatei konnte nicht geschrieben werden:" & @CRLF & $sAusgabeX31)
Return SetError(4, 0, False)
EndIf
MsgBox(64, "X31 Export", "X31-Datei erfolgreich erstellt!" & @CRLF & @CRLF & _
"Datei: " & $sAusgabeX31 & @CRLF & _
"Positionen: " & $iPosN & @CRLF & _
"OZ-Typ: " & $sOZTyp & @CRLF & _
"Format: GAEB DA XML 3.3 / DA31 / REB 23.003")
Return True
EndFunc
; ==============================================================================
; _BuildItem Einzelnes <Item>-Element erzeugen
; Struktur in Dataflor/MWM:
; K-Zeile (*) = RSA-Abschnitt/Ort
; L-Zeile = Formel 91 mit Faktor und Einzelmenge getrennt
; Parameter werden als Einzelwerte übergeben (kein 2D-Array-Slice in AutoIt!)
; ==============================================================================
Func _BuildItem($sPosNr, $fQty, $sOrt, $sBeschr, $sBemerk, ByRef $iOZCnt, $sFaktor = "1", $sEinzel = "")
; Qty für XML (<Qty> Tag): Punkt als Dezimaltrenner
Local $sQtyXML = StringReplace(_FmtQty($fQty), ",", ".")
; Qty für DA11 L-Zeile: Komma, direkt die berechnete Gesamtmenge
Local $sQty = _FmtQty($fQty)
; L-Zeilen-Menge = berechnetes Qty (Faktor bereits eingerechnet)
; Exakt wie Dataflor: "100091" + Gesamtmenge + "="
Local $sMenge = $sQty
; Faktor bereinigen
Local $sFakClean = StringStripWS($sFaktor, 3)
If $sFakClean = "" Or $sFakClean = "0" Then $sFakClean = "1"
$sFakClean = StringReplace($sFakClean, ".", ",")
; OZ-Codes für K- und L-Zeile
Local $sOZ1 = _REBOZCode($iOZCnt)
$iOZCnt += 1
Local $sOZ2 = _REBOZCode($iOZCnt)
$iOZCnt += 1
; K-Zeilen-Text = RSA-Abschnitt (Ort), Fallback auf Bemerkung
Local $sKText = $sOrt
If $sKText = "" Then $sKText = $sBemerk
If $sKText = "" Then $sKText = $sBeschr
Local $sItem = ""
$sItem &= '<Item ID="DF_' & _NextID() & '" RNoPart="' & _XE($sPosNr) & '">'
$sItem &= '<QtyDeterm>'
$sItem &= '<Qty>' & $sQtyXML & '</Qty>'
; K-Zeile: RSA-Abschnitt als Kommentarzeile
$sItem &= '<QDetermItem>'
$sItem &= '<QTakeoff Row="' & _XE(_KZeile($sKText, $sOZ1)) & '"/>'
$sItem &= '<BVBS:Explanation>' & _XE(StringStripWS($sBeschr, 3)) & '</BVBS:Explanation>'
$sItem &= '</QDetermItem>'
; L-Zeile: Formel 91 mit Faktor und Menge getrennt
$sItem &= '<QDetermItem>'
$sItem &= '<QTakeoff Row="' & _XE(_LZeile($sFakClean, $sMenge, $sOZ2)) & '"/>'
$sItem &= '</QDetermItem>'
$sItem &= '</QtyDeterm>'
$sItem &= '</Item>' & @CRLF
Return $sItem
EndFunc
; ==============================================================================
; Hilfsfunktionen
; ==============================================================================
; K-Zeile: 13sp(*) + Ort(56 Zeichen) + OZCode(6) + 5sp = 80 Zeichen
Func _KZeile($sOrt, $sOZCode)
Local $sOrtPad = StringLeft($sOrt & " ", 56)
Return " *" & $sOrtPad & $sOZCode & " "
EndFunc
; L-Zeile: 25sp + "100091" + Menge + "=" + padding auf 44 + BlatAdr(6) + 5sp = 80 Zeichen
; Exakt wie Dataflor-Export: " 100091Menge= BlatAdr "
; Faktor wird als Multiplikator in die Menge eingerechnet (qty = faktor * einzelmenge)
; Der Faktor ist NICHT separat in der Zeile Dataflor rechnet über die Qty
Func _LZeile($sFaktor, $sMenge, $sOZCode)
; Menge mit Komma (DA11-Standard), Punkt entfernen
Local $sMengeK = StringReplace(StringStripWS($sMenge, 3), ".", ",")
; Formel: direkt "100091" + Menge + "="
Local $sFormel = "100091" & $sMengeK & "="
; Auf 44 Zeichen auffüllen
While StringLen($sFormel) < 44
$sFormel &= " "
WEnd
$sFormel = StringLeft($sFormel, 44)
Return " " & $sFormel & $sOZCode & " "
EndFunc
; REB Blattadresse aus Zähler
; Format: Blattnummer(4) + Zeilenkennung(A-Z) + Index(0)
; idx=0 → "1000A0"
; idx=25 → "1000Z0"
; idx=26 → "1001A0" (nächste Blattnummer)
Func _REBOZCode($iIdx)
Local $iBlatt = 1000 + Int($iIdx / 26)
Local $iZeile = Mod($iIdx, 26)
Local $sZeile = Chr(65 + $iZeile) ; 65 = Asc("A")
Local $sBlatt = String($iBlatt)
Return $sBlatt & $sZeile & "0"
EndFunc
; Qty formatieren: ganzzahlig ohne Dezimalstellen, sonst 3 Stellen
; Komma als Dezimaltrenner (DA11-Standard)
Func _FmtQty($fVal)
Local $fAbs = $fVal
If $fAbs < 0 Then $fAbs = -$fAbs
Local $iGanz = Int($fAbs + 0.0005) ; gerundet
Local $fDez = $fAbs - Int($fAbs)
Local $iD3 = Int($fDez * 1000 + 0.5)
If $iD3 >= 1000 Then
$iGanz += 1
$iD3 = 0
EndIf
; Vorzeichenbehandlung
Local $sVorz = ""
If $fVal < 0 Then $sVorz = "-"
; Ganzzahlig? → kein Dezimalteil
If $iD3 = 0 Then
Return $sVorz & String($iGanz)
EndIf
; Mit Dezimalstellen: 3 Stellen, Komma
Local $sDez = String($iD3)
While StringLen($sDez) < 3
$sDez = "0" & $sDez
WEnd
; Trailing Zeros entfernen (z.B. 2,500 → 2,5 für saubere Darstellung)
While StringRight($sDez, 1) = "0" And StringLen($sDez) > 1
$sDez = StringLeft($sDez, StringLen($sDez) - 1)
WEnd
Return $sVorz & String(Int($fAbs)) & "," & $sDez
EndFunc
; OZ analysieren
Func _OZInfo($sOZ)
Local $aI[10]
$aI[0] = "?"
$aI[1] = ""
$aI[2] = ""
$aI[3] = ""
$aI[4] = $sOZ
$aI[5] = $sOZ
$aI[6] = 0
$aI[7] = 0
$aI[8] = 0
$aI[9] = 0
If $sOZ = "" Then Return $aI
If StringRegExp($sOZ, "^\d{6,10}$") Then
$aI[0] = "C"
$aI[4] = $sOZ
$aI[9] = StringLen($sOZ)
Return $aI
EndIf
Local $aS = StringSplit($sOZ, ".", $STR_NOCOUNT)
Local $n = UBound($aS)
If $n = 3 Then
$aI[0] = "A"
$aI[1] = $aS[0]
$aI[6] = StringLen($aS[0])
$aI[2] = $aS[1]
$aI[7] = StringLen($aS[1])
$aI[4] = $aS[2]
$aI[9] = StringLen($aS[2])
ElseIf $n = 4 Then
$aI[0] = "B"
$aI[1] = $aS[0]
$aI[6] = StringLen($aS[0])
$aI[2] = $aS[1]
$aI[7] = StringLen($aS[1])
$aI[3] = $aS[2]
$aI[8] = StringLen($aS[2])
$aI[4] = $aS[3]
$aI[9] = StringLen($aS[3])
EndIf
$aI[5] = $sOZ
Return $aI
EndFunc
; OZ-Typ prüfen
Func _IsValidOZ($sOZ)
If $sOZ = "" Then Return False
If StringRegExp($sOZ, "^\d{1,4}\.\d{1,4}\.\d{1,6}$") Then Return True
If StringRegExp($sOZ, "^\d{1,4}\.\d{1,4}\.\d{1,4}\.\d{1,6}$") Then Return True
If StringRegExp($sOZ, "^\d{6,10}$") Then Return True
Return False
EndFunc
; Kopfdaten-Wert lesen
Func _KopfGet(ByRef $aKopf, $sKey)
For $i = 0 To UBound($aKopf) - 1
If $aKopf[$i][0] = $sKey Then Return $aKopf[$i][1]
Next
Return ""
EndFunc
; XML-Sonderzeichen kodieren
Func _XE($s)
$s = StringReplace($s, "&", "&amp;")
$s = StringReplace($s, "<", "&lt;")
$s = StringReplace($s, ">", "&gt;")
$s = StringReplace($s, '"', "&quot;")
$s = StringReplace($s, "'", "&apos;")
Return $s
EndFunc
; String zu Float (Komma→Punkt)
Func _ToFloat($s)
If $s = "" Then Return 0
Return Number(StringReplace(StringStripWS($s, 3), ",", "."))
EndFunc
; Datum DD.MM.YYYY → YYYY-MM-DD
Func _DatumISO($s)
$s = StringStripWS($s, 3)
If StringRegExp($s, "^\d{2}\.\d{2}\.\d{4}$") Then
Local $aD = StringSplit($s, ".", $STR_NOCOUNT)
Return $aD[2] & "-" & $aD[1] & "-" & $aD[0]
EndIf
Return $s
EndFunc
; Fortlaufende DF_-ID
Func _NextID()
$g_iIDCnt += 1
Return $g_iIDCnt
EndFunc
; Pseudo-UUID
Func _UUID()
Local $sHex = "0123456789abcdef"
Local $sUID = ""
Local $aLen[5]
$aLen[0] = 8
$aLen[1] = 4
$aLen[2] = 4
$aLen[3] = 4
$aLen[4] = 12
For $i = 0 To 4
If $i > 0 Then $sUID &= "-"
For $j = 1 To $aLen[$i]
$sUID &= StringMid($sHex, Random(1, 16, 1), 1)
Next
Next
Return $sUID
EndFunc
+45
View File
@@ -0,0 +1,45 @@
;ZwischenablageTest.au3
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <TabConstants.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=
$hGui = GUICreate("Erweiterte GUI", 701, 501, 192, 125)
$hTab = GUICtrlCreateTab(10, 10, 680, 480)
GUICtrlCreateTabItem("Doku")
$hGroup = GUICtrlCreateGroup("Dokumentation", 16, 67, 420, 176)
GUICtrlSetFont(-1, 8, 400, 0, "Arial")
GUICtrlCreateLabel("MP- Einarbeitung von Gelände/Gebäude:", 26, 87, 200, 20)
$tab_doku_txt_lang = GUICtrlCreateInput("", 236, 87, 44, 22)
$tab_doku_txt_breit = GUICtrlCreateInput("", 290, 87, 44, 22)
GUICtrlCreateLabel("Dokumentation von Cu/Gf HK-Trassen:", 26, 119, 200, 20)
$tab_doku_txt_m_hktr = GUICtrlCreateInput("", 236, 119, 44, 22)
GUICtrlCreateLabel("Dokumentation von Cu/Gf VzK-Trassen:", 26, 151, 200, 20)
$tab_doku_txt_m_vzktr = GUICtrlCreateInput("", 236, 151, 44, 22)
$tab_doku_chb_dokGeh = GUICtrlCreateCheckbox("Dokumentation von Gehäusen", 26, 215, 200, 20)
GUICtrlCreateLabel("Dokumentation Gf-Hausanschluss:", 26, 183, 200, 20)
$tab_doku_txt_anzGFHaus = GUICtrlCreateInput("", 236, 183, 44, 22)
$Label1 = GUICtrlCreateLabel("Länge x Breite", 344, 88, 74, 18)
$Label2 = GUICtrlCreateLabel("Meter", 288, 120, 31, 18)
$Label3 = GUICtrlCreateLabel("Meter", 289, 151, 31, 18)
$Label4 = GUICtrlCreateLabel("Stück", 290, 183, 31, 18)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$tab_doku_bt_add = GUICtrlCreateButton("Hinzufügen", 14, 279, 100, 30)
GUICtrlSetFont(-1, 8, 400, 0, "Arial")
$tab_doku_bt_zuruck = GUICtrlCreateButton("Zurücksetzen", 120, 279, 100, 30)
GUICtrlSetFont(-1, 8, 400, 0, "Arial")
GUICtrlCreateTabItem("")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
EndSwitch
WEnd
File diff suppressed because it is too large Load Diff
+241
View File
@@ -0,0 +1,241 @@
;createCSV.au3
#include <File.au3>
#include <Array.au3>
#include <Debug.au3>
#include <ButtonConstants.au3>
#include <DateTimeConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=
$_1 = GUICreate("Daten Eingabe", 401, 301, 192, 125)
$po_number_input = GUICtrlCreateInput("4212007585", 10, 10, 180, 21)
$po_item_input = GUICtrlCreateInput("00010", 10, 40, 180, 21)
$finalMark_input = GUICtrlCreateInput("No", 10, 70, 180, 21)
$lzvon_input = GUICtrlCreateInput("YYYY-MM-DD", 10, 100, 180, 21)
$lzbis_input = GUICtrlCreateInput("YYYY-MM-DD", 10, 130, 180, 21)
$txz01_input = GUICtrlCreateInput("Hier steht Kurztext mit max 40 Zeichen", 10, 160, 380, 21)
$sbnaman_input = GUICtrlCreateInput("Rutta / Frau Erdmann", 10, 190, 380, 21)
$dlort_input = GUICtrlCreateInput("77749 HohbergSM Auft...", 10, 220, 380, 21)
$generate_button = GUICtrlCreateButton("Generieren", 10, 250, 80, 30)
$date_start = GUICtrlCreateDate(@YEAR & "-" & @MON& "-" & @MDAY, 200, 100, 129, 21)
$date_end = GUICtrlCreateDate(@YEAR & "-" & @MON& "-" & @MDAY, 200, 130, 130, 21)
; Button zum Generieren der Ausgabe
$generate_button = GUICtrlCreateButton("Generieren", 10, 250, 80, 30)
#EndRegion ### END Koda GUI section ###
Local $sStyle = "yyyy/MM/dd"
GUICtrlSendMsg($date_start, $DTM_SETFORMATW, 0, $sStyle)
GUICtrlSendMsg($date_end, $DTM_SETFORMATW, 0, $sStyle)
GUISetState(@SW_SHOW)
; GUI Nachrichtenschleife
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
Exit
Case $generate_button
MsgBox(64, "", "")
$po_number = GUICtrlRead($po_number_input)
$po_item = GUICtrlRead($po_item_input)
$finalMark = GUICtrlRead($finalMark_input)
$lzvon = GUICtrlRead($lzvon_input)
$lzbis = GUICtrlRead($lzbis_input)
$txz01 = GUICtrlRead($txz01_input)
$sbnaman = GUICtrlRead($sbnaman_input)
$dlort = GUICtrlRead($dlort_input)
Local $sFilePath, $aArray
;~ _GUICtrlListView_DeleteAllItems($LV_Aufm)
$aListeImport = ""
Local $message = "Bitte wählen Sie die Import Datei aus!"
Local $sFilePath = FileOpenDialog($message, @ScriptDir & "\..\_Aufmaße\", "Text (*.txt)", 1 + 4)
If @error Then
MsgBox(4096, "", "Keine Datei(en) ausgewählt")
Return "No Datei"
Else
$sFilePath = StringReplace($sFilePath, "|", @CRLF)
;~ MsgBox(4096, "", "Es wurde(n) " & $var & " ausgewählt")
_FileReadToArray($sFilePath, $aArray)
If IsArray($aArray) Then
Dim $aListeImport[$aArray[0] - 15][13]
$iZ = 0
For $i = 16 To UBound($aArray) - 1
$aTemp = StringSplit($aArray[$i], "|")
For $ii = 1 To UBound($aTemp) - 1
$aListeImport[$iZ][$ii - 1] = $aTemp[$ii]
Next
$iZ = $iZ + 1
Next
EndIf
_DebugArrayDisplay($aArray)
_DebugArrayDisplay($aListeImport)
;~ $S_srvpos = _ArrayToString($aListeImport, ";", Default , Default , )
;~ $S_menge =
;~ $S_longText =
;~ $S_sectionText =
$aData = $aListeImport
$S_srvpos = ""
$S_sectionText = ""
$S_longText = ""
$S_menge = ""
;~ Bachstr. 11||||||||||||
;~ |10034578|1,0||||1|ST|FTTH- GrundstüeksersehIieI?ung HP PIus||1|67,80|67,8
;~ |10037463|1,0|2||||M|Einbringen v. KabeI/Rohren unbeIegt|||1,81|
;~ |10037473|1,0|22|||22|M|Ein-/Ausbr. v. KabeI/Rohren beIegt||22|2,37|52,14
;~ |10034682|1,0|3,8|||3,8|M|ZuIage HausansehIuss >10m||3,8|42,77|162,526
;~ |10034642|1,0||||1|ST|Gf-HausansehIuss hersteIIen||1|680,00|680
For $i = 0 To UBound($aData) - 1
If $aData[$i][2] <> "" Then
$S_srvpos &= $aData[$i][1] & ";"
$S_sectionText &= $aData[$i][0] & ";"
$S_longText &= $aData[$i][9] & ";"
$aData[$i][$j] = StringReplace($aData[$i][$j], "ä", "ae")
$aData[$i][$j] = StringReplace($aData[$i][$j], "ö", "oe")
$aData[$i][$j] = StringReplace($aData[$i][$j], "ü", "ue")
$aData[$i][$j] = StringReplace($aData[$i][$j], "ß", "ss")
; Überprüfen, ob der Inhalt eine Zahl ist, und dann Punkt durch Komma ersetzen
If StringRegExp($aData[$i][$j], "^[\d+\.?\d*]$") Then
$aData[$i][$j] = StringReplace($aData[$i][$j], ".", ",")
EndIf
; Anpassung der Zeichenkette für $S_menge ohne Berechnung, nur Ausdruck
Local $expr = ""
Switch $aData[$i][7]
Case "ST"
$expr = $aData[$i][2] & "*" & $aData[$i][6]
Case "M"
$expr = $aData[$i][2] & "*" & $aData[$i][3]
Case "M2"
$expr = $aData[$i][2] & "*" & $aData[$i][3] & "*" & $aData[$i][4]
Case "M3"
$expr = $aData[$i][2] & "*" & $aData[$i][3] & "*" & $aData[$i][4] & "*" & $aData[$i][5]
EndSwitch
$S_menge &= $expr & ";"
EndIf
Next
; Entfernen des letzten Semikolons von jeder Variable, um Übereinstimmung zu gewährleisten
$S_srvpos = StringTrimRight($S_srvpos, 1)
$S_sectionText = StringTrimRight($S_sectionText, 1)
$S_longText = StringTrimRight($S_longText, 1)
$S_menge = StringTrimRight($S_menge, 1)
; Ausgabe generieren
$sFirst = "po_number;po_item;finalMark;lzvon;lzbis;txz01;sbnaman;dlort;srvpos;menge;longText;sectionText"
$dataLine = $po_number & ";" & $po_item & ";" & $finalMark & ";" & $lzvon & ";" & $lzbis & ";" & _
$txz01 & ";" & $sbnaman & ";" & $dlort & ';"' & $S_srvpos & '";"' & $S_menge & '";"' & _
$S_longText & '";"' & $S_sectionText
; Ausgabe in Konsole
ConsoleWrite($sFirst & @CRLF & $dataLine & @CRLF)
; Ausgabedateipfad definieren
$sOutputFilePath = @ScriptDir & "\..\ausgabe.csv"
; Datei im Schreibmodus öffnen, UTF-8 ohne BOM
$hFile = FileOpen($sOutputFilePath, $FO_OVERWRITE + $FO_UTF8_NOBOM)
If $hFile = -1 Then
MsgBox($MB_SYSTEMMODAL, "Fehler", "Konnte die Ausgabedatei nicht öffnen.")
Exit
EndIf
; Kopfzeile und Datenzeile schreiben
FileWrite($hFile, $sFirst & @CRLF & $dataLine & @CRLF)
; Datei schließen
FileClose($hFile)
; FileWrite(@ScriptDir & "\..\ausgabe.csv", $sFirst & @CRLF & $dataLine)
EndIf
case $date_start
GUICtrlSetData($lzvon_input, GUICtrlRead($date_start))
case $date_end
GUICtrlSetData($lzbis_input, GUICtrlRead($date_end))
EndSwitch
WEnd
;~ ; Ausgabe der Variablen zur Überprüfung
;~ ConsoleWrite("S_srvpos: " & $S_srvpos & @CRLF)
;~ ConsoleWrite("S_sectionText: " & $S_sectionText & @CRLF)
;~ ConsoleWrite("S_longText: " & $S_longText & @CRLF)
;~ ConsoleWrite("S_menge: " & $S_menge & @CRLF)
;~ $sTeilaufma = StringReplace($aArray[2], "Teilaufma=", "")
;~ If $sTeilaufma = "X" Then
;~ Else
;~ EndIf
;~ $sSchlussaufma = StringReplace($aArray[3], "Schlussaufma=", "")
;~ If $sSchlussaufma = "X" Then
;~ Else
;~ EndIf
;~ $kopf_tab_txt_datum = StringReplace($aArray[4], "Datum=", "")
;~ $kopf_tab_txt_baustelle = StringReplace($aArray[5], "Baustelle=", "")
;~ $kopf_tab_txt_abrufnr = StringReplace($aArray[6], "AbrufNr=", "")
;~ $kopf_tab_txt_smnr = StringReplace($aArray[7], "SMNr=", "")
;~ $kopf_tab_chb_vertrag = StringReplace($aArray[8], "Vertrag=", "")
;~ $kopf_tab_datum_start = StringReplace($aArray[9], "StartZ=", "")
;~ $kopf_tab_txt_datum_ende = StringReplace($aArray[10], "EndZ=", "")
;~ $kopf_tab_txt_aspa = StringReplace($aArray[11], "AspaN=", "")
;~ $kopf_tab_txt_telnr = StringReplace($aArray[12], "AspaTel=", "")
;~ $kopf_tab_txt_bauabschnitt = StringReplace($aArray[13], "Bauabschnitt=", "")
;~ $kopf_tab_txt_kolone = StringReplace($aArray[14], "Kolone=", "")
;~ $lve_tab_chb_vertrag = StringReplace($aArray[8], "Vertrag=", "")
;~ $kopf_tab_chb_vertrag = StringReplace($aArray[8], "Vertrag=", "")
;~ $aStartDatum = StringSplit($kopf_tab_datum_start, ".")
;~ If IsArray($aStartDatum) Then
;~ If UBound($aStartDatum) = 3 Then
;~ $iYear = $aStartDatum[3]
;~ $iMonth = $aStartDatum[2]
;~ $iDay = $aStartDatum[1]
;~ $kopf_tab_datumfeld_start = $iYear & "-" & $iMonth & "-" & $iDay
;~ EndIf
;~ EndIf
;~ $aStartDatum = StringSplit($kopf_tab_txt_datum_ende, ".")
;~ If IsArray($aStartDatum) Then
;~ If UBound($aStartDatum) = 3 Then
;~ $iYear = $aStartDatum[3]
;~ $iMonth = $aStartDatum[2]
;~ $iDay = $aStartDatum[1]
;~ $kopf_tab_datumfeld_ende = $iYear & "-" & $iMonth & "-" & $iDay
;~ EndIf
;~ EndIf
;~ EndIf
;~
+55
View File
@@ -0,0 +1,55 @@
;export_X31.au3
#include <File.au3>
Global $sIn = "FTTX_KIS_GWG_Zaisenhofen_AR_01.b_.txt"
Global $sOut = "Abrechnung.X31"
; 1) GAEB-X31-Header (XML-Start)
Local $sXML = '<?xml version="1.0" encoding="UTF-8"?>' & @CRLF
$sXML &= '<GAEB xmlns="http://www.gaeb.de/GAEB_DA_XML/3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' & @CRLF
$sXML &= ' <Header>' & @CRLF
$sXML &= ' <Version>3.1</Version>' & @CRLF
$sXML &= ' <Date>' & @YEAR & "-" & StringFormat("%02d", @MON) & "-" & StringFormat("%02d", @MDAY) & '</Date>' & @CRLF
$sXML &= ' <FileType>X31</FileType>' & @CRLF
$sXML &= ' </Header>' & @CRLF
$sXML &= ' <Project>' & @CRLF
$sXML &= ' <ProjectName>Bauprojekt</ProjectName>' & @CRLF
$sXML &= ' <Site>Baustelle Muster</Site>' & @CRLF
; 2) Quelldatei einlesen
Local $aLines = FileReadToArray($sIn)
If @error Then Exit MsgBox(16, "Fehler", "Quelldatei nicht gefunden")
; 3) Aufmaßdaten einlesen
Local $iSection = 0
$sXML &= ' <Positions>' & @CRLF
For $i = 1 To $aLines[0]
Local $s = StringStripWS($aLines[$i], 3)
If $s = "[Aufmaßdaten]" Then
$iSection = 1
ElseIf $iSection = 1 And StringLeft($s, 1) = "|" Then
; CSV-Linie in Felder aufsplitten
Local $a = StringSplit($s, "|", 12)
; GAEB-Positionen erzeugen
$sXML &= ' <Position>' & @CRLF
$sXML &= ' <PositionNumber>' & StringStripWS($a[2], 3) & '</PositionNumber>' & @CRLF
$sXML &= ' <ShortText>' & StringStripWS($a[9], 3) & '</ShortText>' & @CRLF
$sXML &= ' <Quantity>' & StringReplace($a[10], ",", ".") & '</Quantity>' & @CRLF
$sXML &= ' <Unit>' & $a[8] & '</Unit>' & @CRLF
$sXML &= ' <UnitPrice>' & StringReplace($a[11], ",", ".") & '</UnitPrice>' & @CRLF
$sXML &= ' </Position>' & @CRLF
EndIf
Next
$sXML &= ' </Positions>' & @CRLF
$sXML &= ' </Project>' & @CRLF
; 4) GAEB-X31-Footer
$sXML &= '</GAEB>'
; 5) XML-Datei speichern
If _FileWriteFromArray($sOut, StringSplit($sXML, @CRLF, 1)) Then
MsgBox(64, "Erfolgreich", "GAEB-X31-Datei '" & $sOut & "' wurde erstellt.")
Else
MsgBox(16, "Fehler", "GAEB-X31-Datei konnte nicht erstellt werden.")
EndIf