// xZUGFeRDm.prg Bleines/Mller-Version
#include "Gra.ch"
#include "Common.ch"
#include "Xbp.ch"
#include "Appevent.ch"
#include "Appedit.ch"
#include "Appbrow.ch"
#include "Font.ch"
#include "fileio.ch"
#include "DelDbe.ch"
//13.01.2026 15:52 erstellt wahlweise die xRechnung (UBL in XML) oder die ZUGFeRD-Rechnung (CII in PDF)
FUNCTION xZUGFeRD( zdate, anz, cFormular )
LOCAL nOldArea := Select(), nRec := RecNo() //+11.10.2018 14:24
LOCAL cAuf := StrZero(1->auftrnr,6,0) //13.01.2026 16:03
LOCAL cRechNr := RechnungsNr("") //04.02.2026 14:05
LOCAL aLeist1 := {}, aLeist2 := {}, aLeist3 := {}, aLeistB := {} //03.02.2026 10:08 aLeistB ...aLeist3 brauchen fr was??? FehlerFalle?
LOCAL nL1Sum := 0, nL2Sum := 0, nL3Sum := 0, nLBSum := 0
LOCAL n4 := 4 , n5 := 5, nL12 := 0
LOCAL sbetr, grsu, smwsta, smwstb, zae
LOCAL CR := Chr(13), LF := Chr(10), w_g := "EUR"
PRIVATE aBlatt := {}, aBlattZ := {}, cAnz, cdate, ctextjn
PRIVATE cSeite, cNa, cPrompt, cText, nTFont, cBereich, cFeld, nFFont, nZei, nSpa
PRIVATE aSeite := {}, aNa := {}, aPrompt := {}, aText := {}, aTFont := {}
PRIVATE aBereich := {}, aFeld := {}, aFFont := {}, aZei := {}, aSpa := {}
PRIVATE cUsername := "XR"
PRIVATE cPCName := "TEST"
PRIVATE nArea := 13
PRIVATE cRechDir
DEFAULT cFormular TO cDatver + "BleinesBB2x.png"
EUROV()
IF xdmeu="D" /* DM darf nicht mehr gebraucht werden fr neue F„lle!! */
RETURN .F.
ENDIF
/**/
// RechnungZeilenKorrektur(cAuf) //+21.10.2018 19:21
//06.01.2026 15:24 speziell zum Testen:
DEFAULT zdate TO DtoC(DATE())
DEFAULT anz TO "Z"
SELECT &nArea // die Temp-Rechnungsdatei
DbSuspendNotifications()
DbGotop()
//================================================================================================
//04.01.2026 19:10 die Dateien der Rechnung (.html + .odt + .pdf + .zug.xml + zug.pdf) ...
// ... werden in diesem Verzeichnis archiviert:
cRechDir := cDatver + "Scans\Dokumente\" + cAuf + "\_Rechnung\"
// Verzeichnis erzeugen (wenn noch nicht geschehen):
IF !FExists( Left(cRechDir,Len(cRechDir)-1),"D" ) // ! ohne letzten Backslash !
RunShell( "/C MD "+cRechDir,, .T. )
sleep(200)
ELSEIF FExists(cRechDir+"R"+cAuf+".odt")
nHandle := FOpen( cRechDir+"R"+cAuf+".odt", FO_EXCLUSIVE )
IF nHandle = -1
//+ Die Datei ist bereits auf diesem PC ge”ffnet
FClose(nHandle)
msgbox("Es ist bereits eine Datei R"+cAuf+".odt offen!"+CR+LF+"Bitte im OfficeWriter schlieáen, dann nochmal versuchen!")
RETURN .F.
ELSE
FClose(nHandle)
ENDIF
ELSEIF FExists(cRechDir+"R"+cAuf+".html")
nHandle := FOpen( cRechDir+"R"+cAuf+".html", FO_EXCLUSIVE )
IF nHandle = -1
//+ Die Datei ist bereits auf diesem PC ge”ffnet
FClose(nHandle)
msgbox("Es ist bereits eine Datei R"+cAuf+".html offen!"+CR+LF+"Bitte im OfficeWriter schlieáen, dann nochmal versuchen!")
RETURN .F.
ELSE
FClose(nHandle)
ENDIF
ENDIF
//================================================================================================
// fr alle F„lle:
ASize( aLeist1, 0 ); ASize( aLeist2, 0 ); ASize( aLeist3, 0 ); ASize( aLeistB, 0 )
nAnz := IIf(ValType(anz)=="C",Val(anz),anz) //+22.10.2018 12:26
nArea := 13 // weil oDlg1 fr den Ausdruck ohnehin von Typ 'L' ist, damit es in 'auf3AUFTRNR.dbf' sucht
SELECT &nArea
GO TOP
DbSuspendNotifications() //05.03.2008 13:06
IF Upper(anz)$"ZCXUWP"
// Variablen mit Daten dieses Auftrags fllen:
IF anz $ "ZCW" // CII
cDash := ""
ELSEIF anz == "XUP" // UBL
cDash := "-"
ENDIF
zdate := DtoC(DATE()) // muss ggf noch geREMt werden !?!
// ab hier werden das lauter neue PRIVATE:
cRechnr := "R"+cAuf // provisorisch erstmal fr "WP"
cJJJJMMTT := SubStr(zdate,7,4)+cDash+SubStr(zdate,4,2)+cDash+SubStr(zdate,1,2)
cJJJJMMTT_Lief := SubStr(zdate,7,4)+cDash+SubStr(zdate,4,2)+cDash+SubStr(zdate,1,2)
ydate := DtoC(CtoD(zdate)+10)
cJJJJMMTT_Zahl := SubStr(ydate,7,4)+cDash+SubStr(ydate,4,2)+cDash+SubStr(ydate,1,2)
cRevCharge := Wandeln_in_UTF8("RC-Text")
cVatProz := "19.00"
nTotalNetto := 0.00
nSum_MwSt := 0.00
nTotalNetto4 := 0.0000
nSum_MwSt4 := 0.0000
cAuftrag := StrZero(1->auftrnr,6,0)
cKdnr := "A" + cAuftrag
cLief := cBU2
cLieferant := cBU1 + " " + cBU2
cHRBnr := SubStr(cSTN,At("DE",cSTN))
cMA_Lief := 1->berater
cTel_Lief := cBU6
cMail_Lief := "bestattungshaus-bleines@t-online.de"
cPLZ_Lief := SubStr(cBU5,1,5)
cStr_Lief := Wandeln_in_UTF8(cBU4)
cOrt_Lief := Wandeln_in_UTF8(SubStr(cBU5,6))
cLand_Lief := "DE"
cVAT_Lief := SubStr(cSTN,At("DE",cSTN))
cKunde := Wandeln_in_UTF8(Trim(1->ansp_name))
cMA_Kunde := cKunde // vorl„ufig
cMail_Kunde := IIf("@"$1->ansp_email,Trim(1->ansp_email),"eine.leere@mail.ee")
cMail_MA_Kunde := Wandeln_in_UTF8(cMail_Kunde) // vorl„ufig
cPLZ_Kunde := SubStr (1->ansp_ort,1,5)
cStr_Kunde := Wandeln_in_UTF8(Trim(1->ansp_str))
cOrt_Kunde := Wandeln_in_UTF8(ORTohnePLZ(1->ansp_ort))
cLand_Kunde := "DE" // vorl„ufig
cVAT_Kunde := "DE123456789" // vorl„ufig
cKontoNameLief := cBU1 + " " + cBU2
cIBAN_Lief := "DE88360501050001816768"
cBIC_Lief := "SPESDE3EXXX"
cZahlungsbedingungen := "zahlbar innerhalb 8 Tagen"
// schon mal fr die Rechnungszeilen:
cMenge := "1.0000"
cXml3 := ''
aVatProz := {0,7,19}
aVatCat := {"Z","S","S"}
aTotalNetto := {0,0,0}
aTotalMwst := {0,0,0}
cVatProz := "19.00"
cVatCat := "S"
nVatFakt := 1.19
ENDIF
//07.12.2025 10:21 XML-Erzeugung: KOPF vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
IF anz $ "ZCW" // = CII fr ZUGFeRD
cXML1 := '' + CRLF + ;
'
' //+CR+LF+; // '' + CRLF + ; // '' cHtmlRech := Stuff(cHtmlRech,At("windows",cHtmlRech),12,"UTF-8") // fr .HTML/.ODT und .PDF im Archiv cBrBog := 'BODY LANG="de-DE" BACKGROUND="BleinesBB2.png" DIR="LTR" STYLE="background: url(C:\Bestatt\Bleines\BleinesBB2.png) no-repeat middle center scroll"' cHtmlRech := Stuff(cHtmlRech,At("BODY LANG",cHtmlRech),18,cBrBog) // fr .HTML/.ODT und .PDF im Archiv cFilehtml := cRechDir + "R"+cAuf+".html" // cRechDir ist im Archiv nHandleR2 := FCreate(cFilehtml) FWrite(nHandleR2,Wandeln_in_UTF8(cHtmlRech)) // .... und schreiben als UTF8 in die Archiv-Datei FClose(nHandleR2) */ cAuftrag := StrZero(1->auftrnr,6,0) cFileodt := cRechDir + "R"+StrZero(1->auftrnr,6,0)+".odt" COPY FILE ("c:\hdbe\BleinXbb.odt") TO (cFileodt) // leere Rechnungsdatei mit Briefkopf sleep(200) cCommand := ' &cFilehtml macro:///Standard.Module1.xRechPDF ' // RunShell (' &cFilehtml macro:///Standard.Module1.xRechPDF ', 'C:\Program Files\LibreOffice\program\swriter.exe',.T.) RunShell (' &cFileodt macro:///Standard.Module1.xRechodtPDF ', 'C:\Program Files\LibreOffice\program\swriter.exe',.T.) ENDIF SELECT &nOldArea DbGoto(nRec) //+11.10.2018 14:25 RETURN .T. /* FUNCTION Leistdruck( aLeist, n, zae, nS ) //04.01.2026 14:57 nS SpaltenOffset LOCAL w_g := "" //"EUR" FOR i := n to ( nLL + 1 ) STEP n // nLL = Anzahl der Zeilen dieser Leistung @ ++zae,10-nS say aLeist[i-3] @ zae,57-nS say w_g @ zae,60-nS say Str( aLeist[i-2],8,2 ) // Druck des Betrags aLeist[nLL+1]=aLeist[nLL+1] + aLeist[i-2] // Addition des Betrags (i-2) zur Summe (nLL+1) aLeist[nLL+2]=aLeist[nLL+2] + aLeist[i-2] // Addition des Betrags (i-2) zur Summe (nLL+2) ... wieso doppelt??? IF aLeist[i-1]="3" //mwst_schl = 19% // aLeist[nLL+3]=aLeist[nLL+3] + (aLeist[i-2] / (100+zschl_voll) * zschl_voll) // Addition MwSt zur Summe (nLL+3) aLeist[nLL+3]=aLeist[nLL+3] + (aLeist[i-2] * zschl_voll / 100) // Addition MwSt zur Summe (nLL+3) ENDIF IF aLeist[i-1]="2" //mwst_schl = 7% // aLeist[nLL+4]=aLeist[nLL+4] + (aLeist[i-2] / (100+zschl_halb) * zschl_halb) // Addition MwSt zur Summe (nLL+4) aLeist[nLL+4]=aLeist[nLL+4] + (aLeist[i-2] * zschl_halb / 100) // Addition MwSt zur Summe (nLL+4) ENDIF NEXT @ zae,69-nS say w_g @ zae,72-nS say Str( aLeist[nLL+1],8,2 ) // Druck der Nettosumme IF aLeist[nLL+3]>0 //mwst_schl = 19% @ ++zae,40-nS SAY "+ 19% MwSt" @ zae,69-nS say w_g @ zae,72-nS say Str( aLeist[nLL+3],8,2 ) // Druck der 19%-Summe ENDIF IF aLeist[nLL+4]>0 //mwst_schl = 7% @ ++zae,40-nS SAY "+ 7% MwSt" @ zae,69-nS say w_g @ zae,72-nS say Str( aLeist[nLL+4],8,2 ) // Druck der 7%-Summe ENDIF RETURN aLeist // in aLeist wird auch die Summe zurckgegeben */ /* IF zae > 0 //04.05.2008 17:11 s.u. IF n == 4 // FOR i := 5 to ( nLL + 1 ) STEP 5 // die zweite Zeile der Bezeichnung FOR i := n to ( nLL + 1 ) STEP n // @ ++zae,10 say aLeist[i-4] // IF Len(Trim(aLeist[i-3])) > 0 @ ++zae,10-nS say aLeist[i-3] // ENDIF @ zae,57-nS say w_g @ zae,60-nS say str( aLeist[i-2],8,2 ) aLeist[nLL+1]=aLeist[nLL+1] + aLeist[i-2] aLeist[nLL+2]=aLeist[nLL+2] + aLeist[i-2] if aLeist[i-1]="3" //mwst_schl = 19% aLeist[nLL+3]=aLeist[nLL+3] + (aLeist[i-2] / (100+zschl_voll) * zschl_voll) endif if aLeist[i-1]="2" //mwst_schl = 7% aLeist[nLL+4]=aLeist[nLL+4] + (aLeist[i-2] / (100+zschl_halb) * zschl_halb) endif NEXT ELSE AAdd( aLeist, 0, nLL+5 ) FOR i := n to ( nLL + 1 ) STEP n @ ++zae,5 say "Rechnung-"+Substr(aLeist[i-4],1,34)+"-"+aLeist[i-3] @ zae,64 say w_g @ zae,67 say str( aLeist[i-2],8,2 ) aLeist[nLL+1]=aLeist[nLL+1] + aLeist[i-2] aLeist[nLL+2]=aLeist[nLL+2] + aLeist[i-2] if aLeist[i-1]="3" aLeist[nLL+3]=aLeist[nLL+3] + (aLeist[i-2] / (100+zschl_voll) * zschl_voll) endif if aLeist[i-1]="2" aLeist[nLL+4]=aLeist[nLL+4] + (aLeist[i-2] / (100+zschl_halb) * zschl_halb) endif NEXT ENDIF ELSEIF zae == 0 //04.05.2008 17:10 rechnet in Aufstellung die Vorfinanzierungskosten aus: FOR i := n to ( nLL + 1 ) STEP n aLeist[nLL+1]=aLeist[nLL+1] + aLeist[i-2] aLeist[nLL+2]=aLeist[nLL+2] + aLeist[i-2] NEXT ENDIF RETURN aLeist */ /* FUNCTION BSEingabeX_X( aBlatt, oDlg1 ) LOCAL oDlg, nEvent, mp1, mp2 LOCAL aSizeDesktop := AppDesktop():currentSize() LOCAL nBSb := aSizeDesktop[1] LOCAL nBSh := aSizeDesktop[2] // folgende Zahlen-Werte basieren auf 800x600: LOCAL nV := nBSb/800 // Korrekturfaktor fr tats„chliche Aufl”sung LOCAL nOldArea := Select() LOCAL aEditcontrols := {} // LOCAL oFocus := SetAppFocus() LOCAL aSeite := {}, aNa := {}, aPrompt := {}, aText := {}, aTFont := {} LOCAL aBereich := {}, aFeld := {}, aFFont := {}, aZei := {}, aSpa := {} PRIVATE oWin := oDlg1 cFont := IIf( nBSb < 700, "7.Arial", "8.Arial" ) oDlg := XbpDialog():new( AppDeskTop(), oDlg1 ) oDlg:tasklist := .T. oDlg:title := "Felder korrigieren/eingeben" oDlg:maxButton := .F. oDlg:clipSiblings := .T. oDlg:border := XBPDLG_RAISEDBORDERTHIN_FIXED oDlg:create(,, {10,10}, {int(740*nV),int(460*nV)} ) oDlg:drawingArea:setFontCompoundName( "8.Arial" ) oDlg:drawingArea:setColorBG( GRA_CLR_DARKGREEN ) oCB := oDlg:drawingArea oCB:clipSiblings := .T. nBo := int(430*nV) nBr := 0 j := 0 FOR i := 1 to Len( aBlatt ) aBlattZ := aBlatt[i] AAdd( aSeite, aBlattZ[1] ) AAdd( aNa, aBlattZ[2] ) AAdd( aPrompt, aBlattZ[3] ) AAdd( aText, aBlattZ[4] ) AAdd( aTFont, aBlattZ[5] ) AAdd( aBereich, aBlattZ[6] ) AAdd( aFeld, aBlattZ[7] ) // Feldbezeichnung AAdd( aFFont, aBlattZ[8] ) AAdd( aZei, aBlattZ[9] ) AAdd( aSpa, aBlattZ[10] ) // fr die Positionierung im Editierfenster: nBr := IIf( i<>1 .AND. (aSeite[i]="n" .OR. nBo-Int(j*25*nV) < Int(30*nV)), ; (nBr+Int(370*nV)), nBr ) j := IIf( nBo-Int(j*25*nV) < Int(30*nV) .OR. aSeite[i]="n", 0, j ) IF Upper( aSeite[i] ) = "R" .OR. Upper( aSeite[i] ) = "V" // keine Žnderungen, wenn es sich um "Rechnungszeilen" handelt AAdd( aEditcontrols, aFeld[i] ) ELSE IF aNa[i] = "t" // Text ist zu ver„ndern // aText[i] := aText[i]+Space(70-len(aText[i])) oXbp := XbpStatic():new( oDlg:drawingArea, , {nBr+int(30*nV),nBo-int(++j*25*nV)}, {int(100*nV),int(25*nV)}) oXbp:caption := aPrompt[i] oXbp:clipSiblings := .T. oXbp:options := XBPSTATIC_TEXT_VCENTER+XBPSTATIC_TEXT_RIGHT oXbp:create() oSle := XbpSLE():new( oDlg:drawingArea, , {nBr+int(140*nV),nBo-int(j*25*nV)}, {int(200*nV),int(25*nV)}, { { XBP_PP_BGCLR, XBPSYSCLR_ENTRYFIELD } } ) oSle:bufferLength := 70 oSle:setInputFocus := {|mp1,mp2,obj| HiliteSle( obj ) } oSle:killInputFocus := {|mp1,mp2,obj| DeHiliteSle( obj ) } oSle:group := XBP_WITHIN_GROUP oSle:dataLink := {|x| IIf( PCOUNT()==0, Trim( aText[i] ), aText[i] := x ) } oSle:create():setData() AAdd( aEditcontrols, oSle ) // IF ASC( aFeld[i] ) > 32 cB := aBereich[i] ; cF := aFeld[i] IF !Empty( cF ) .AND. Val( cB ) > 0 aFeld[i] := ((&cB)->(&cF)) //Feldinhalt ENDIF ELSEIF aNa[i] = "f" // Feldinhalt soll editiert werden cB := aBereich[i] ; cF := aFeld[i] xF := ( (&cB)->(&cF) ) //Feldinhalt DO CASE CASE Valtype( xF ) == "C" aFeld[i] := xF CASE ValType( xF ) == "N" aFeld[i] := Str( xF ) CASE ValType( xF ) == "D" aFeld[i] := DtoC( xF ) ENDCASE oXbp := XbpStatic():new( oDlg:drawingArea, , {nBr+int(30*nV),nBo-int(++j*25*nV)}, {int(100*nV),int(25*nV)}) oXbp:caption := aPrompt[i] oXbp:clipSiblings := .T. oXbp:options := XBPSTATIC_TEXT_VCENTER+XBPSTATIC_TEXT_RIGHT oXbp:create() oSle := XbpSLE():new( oDlg:drawingArea, , {nBr+int(140*nV),nBo-int(j*25*nV)}, {int(200*nV),int(25*nV)}, { { XBP_PP_BGCLR, XBPSYSCLR_ENTRYFIELD } } ) oSle:bufferLength := 50 oSle:setInputFocus := {|mp1,mp2,obj| HiliteSle( obj ) } oSle:killInputFocus := {|mp1,mp2,obj| DeHiliteSle( obj ) } oSle:group := XBP_WITHIN_GROUP oSle:dataLink := {|x| IIf( PCOUNT()==0, Trim( aFeld[i] ), aFeld[i] := x ) } oSle:create():setData() AAdd( aEditcontrols, oSle ) aText[i] := "" ELSEIF aNa[i] = "v" .AND. aBereich[i] = "v" // Variable soll editiert werden cF := aFeld[i] xF := &(cF) //Variableninhalt DO CASE CASE Valtype( xF ) == "C" aFeld[i] := xF CASE ValType( xF ) == "N" aFeld[i] := Str( xF ) CASE ValType( xF ) == "D" aFeld[i] := DtoC( xF ) ENDCASE oXbp := XbpStatic():new( oDlg:drawingArea, , {nBr+int(30*nV),nBo-int(++j*25*nV)}, {int(100*nV),int(25*nV)}) oXbp:caption := aPrompt[i] oXbp:clipSiblings := .T. oXbp:options := XBPSTATIC_TEXT_VCENTER+XBPSTATIC_TEXT_RIGHT oXbp:create() oSle := XbpSLE():new( oDlg:drawingArea, , {nBr+int(140*nV),nBo-int(j*25*nV)}, {int(200*nV),int(25*nV)}, { { XBP_PP_BGCLR, XBPSYSCLR_ENTRYFIELD } } ) oSle:bufferLength := 50 oSle:setInputFocus := {|mp1,mp2,obj| HiliteSle( obj ) } oSle:killInputFocus := {|mp1,mp2,obj| DeHiliteSle( obj ) } oSle:group := XBP_WITHIN_GROUP oSle:dataLink := {|x| IIf( PCOUNT()==0, Trim( aFeld[i] ), aFeld[i] := x ) } oSle:create():setData() AAdd( aEditcontrols, oSle ) ELSEIF aNa[i] <> "v" .AND. aBereich[i] = "v" // im aFeld steht Mem-Variable cF := aFeld[i] aFeld[i] := "&(" + cF + ")" AAdd( aEditcontrols, aFeld[i] ) ELSE IF ASC( aFeld[i] ) > 32 cB := aBereich[i] ; cF := aFeld[i] aFeld[i] := ((&cB)->(&cF)) //Feldinhalt ENDIF AAdd( aEditcontrols, aFeld[i] ) ENDIF IF ValType(cF)="C" IF Upper(cF) = "FAM" .OR. Upper(cF) = "KONF" aFeld[i] := Kurzlang( aFeld[i] ) ENDIF ENDIF ENDIF NEXT i=1 oDlg:setModalState( XBP_DISP_APPMODAL ) oDlg:show() IF Len( aEditcontrols ) > 0 .AND. ValType( aEditControls[1] ) = "O" oFocus := SetAppFocus( aEditcontrols[1] ) ELSE oFocus := SetAppFocus( oDlg ) ENDIF DO WHILE nEvent <> xbeP_Close nEvent := AppEvent( @mp1, @mp2, @oXbp ) IF nEvent == xbeM_LbDblClick PostAppEvent( xbeP_Close) ENDIF IF nEvent == xbeP_Keyboard DO CASE CASE mp1 == xbeK_ESC lFluchtB := .T. //+21.10.2018 18:41 ESC bricht jetzt das Drucken ab PostAppEvent( xbeP_Close) CASE mp1 == xbeK_F10 PostAppEvent( xbeP_Close) ENDCASE ENDIF oXbp:handleEvent( nEvent, mp1, mp2 ) ENDDO IF lFluchtB == .F. //+21.10.2018 18:42 zum Abbrechen des Drucks // wie Gather( aEditcontrols ) : FOR i := 1 TO len( aEditcontrols ) IF ValType( aEditcontrols[i] ) == "O" IF aNa[i] == "t" aText[i] := aEditcontrols[i]:getdata() ELSE aFeld[i] := aEditcontrols[i]:getdata() ENDIF ENDIF NEXT FOR i=1 to len(aBlatt) aBlattZ := { aSeite[i], aNa[i], aPrompt[i], Trim(aText[i]), aTFont[i], aBereich[i], ; IIf( ValType(aFeld[i])="C", Trim(aFeld[i]), aFeld[i]), ; aFFont[i], aZei[i], aSpa[i] } aBlatt[i] := aBlattZ NEXT ELSE aBlatt := .F. ENDIF oDlg:setModalState( XBP_DISP_MODELESS ) oDlg:destroy() SetAppFocus( oFocus ) SELECT &nOldArea RETURN aBlatt */ /* FUNCTION Z1214(a) DO CASE CASE cLPT = "LPTA" .and. a = chr(27)+z12p aFonts := {"12.COURIER NEW Fett"} a := "" CASE cLPT = "LPTA" .and. a = chr(27)+z14p aFonts := {"14.COURIER NEW Fett"} a := "" CASE cLPT = "LPTA" .and. a = chr(27)+znorm aFonts := {"12.COURIER NEW"} a := "" CASE cLPT != "LPTA" aFonts := {} ENDCASE //+25.06.2018 19:21 bei HTML-Druck auf Fettdruck schalten: vvvvvvvvvvvvvvv IF isMemVar("cDruckabr") .AND. "HTML"$cDruckabr IF "Fett"$aFonts[1] a := "" ELSEIF Len(aFonts) = 1 a := "" ENDIF ENDIF //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RETURN a */ /* //+21.10.2018 19:22 macht das vor dem Drucken, was sonst erst vor dem Speichern in auftr.dbf gemacht wird: FUNCTION RechnungZeilenKorrektur(cAuf) LOCAL nOldArea := SELECT() LOCAL nZeile := 0, nRec := RecNo() DbSuspendNotifications() IF ConfirmBox( oCB, "Soll die Rechnung geprft und korrigiert werden?" + CRLF +; "(Zeilen ohne Artikelnr oder Artikelbezeichnung l”schen.)", ; "Abrechnungs-Zeilen Checken", ; XBPMB_YESNO, ; XBPMB_QUESTION ) == XBPMB_RET_NO DbResumeNotifications() RETURN .F. ENDIF SELECT 13 // DELETE ALL FOR 13->auftrnr <> Val( cAuf ) .OR. ( Empty(13->zugr_z_st) .AND. Empty(13->bezeichf1)) //+14.10.2018 13:43 statt der Vorzeile folgende Schleife: // hier wird die Temp-Datei von leeren und falschen Zeilen befreit (siehe auch BregieR5L.prg) *** DbGotop() DO WHILE !Eof() IF 13->auftrnr <> Val( cAuf ) .AND. ( !Empty(13->zugr_z_st) .AND. !Empty(13->bezeich)) IF ConfirmBox( oCB, "Zeile erg„nzen+behalten=ja - Zeile l”schen=nein", ; "Zeile "+13->zeile+" hat noch keine Auftragsnummer!", ; XBPMB_YESNO, ; XBPMB_QUESTION ) == XBPMB_RET_YES 13->auftrnr := Val(cAuf) ELSE DbDelete() ENDIF ELSEIF 13->auftrnr == Val( cAuf ) .AND. (Empty(13->zugr_z_st) .OR. Empty(13->bezeich)) IF ConfirmBox( oCB, "Zeile behalten=ja - Zeile l”schen=nein", ; "Zeile "+13->zeile+": Artikelnr oder -bezeichnung ist leer!", ; XBPMB_YESNO, ; XBPMB_QUESTION ) == XBPMB_RET_YES 13->auftrnr := Val(cAuf) // vorsichtshalber ... ELSE DbDelete() ENDIF ELSEIF 13->auftrnr <> Val( cAuf ) DbDelete() // der Rest: keine/falsche Auftragsnummer und leere Zeilen ENDIF DbSkip() ENDDO // bis hier geht die neue DELETE-Routine vom 14.10.2018 PACK IF .NOT. Bof() GO TOP ENDIF DO WHILE .NOT. Eof() ++nZeile REPLACE 13->zeile WITH Str( nZeile,2,0 ) DbSkip() ENDDO DO WHILE Recno() < 20 APPEND BLANK ENDDO SELECT &nOldArea DbCommit() DbResumeNotifications() DbGotop() DbGoto(nRec) RETURN .T. */ FUNCTION Wandeln_in_UTF8(cString) LOCAL aUml := {"„","”","","á","Ž","™","š"} LOCAL aUTF8 := {Chr(0xC3)+Chr(0xA4),Chr(0xC3)+Chr(0xB6),Chr(0xC3)+Chr(0xBC),Chr(0xC3)+Chr(0x9F),Chr(0xC3)+Chr(0x84),Chr(0xC3)+Chr(0x96),Chr(0xC3)+Chr(0x9C)} FOR i:=1 TO Len(cString) IF (n := AScan(aUml, cString[i])) > 0 cString := Stuff( cString, i, 1, aUTF8[n]) ++i ENDIF NEXT RETURN cString /* >>>>>>>>>>>>>>> Aus dem Makro ExportPDF der LibreOffice ZUGFeRD-L”sung: <<<<<<<<<<<<<<<<<<<<<<<<<< REM +++ Erstellung des Pfades zum Archivieren der Dateien. Achiv Jahr Monat Dateiname REM +++ Abspeichern der *.odt-Datei und Erstellen einer *.pdf-Datei, die mit dem entsprechenden Namen versehen ebenfalls abgespeichert wird. REM +++ Wird aus FillTableCarryOver aufgerufen //SUB ExportPDF(oNewDoc AS OBJECT, stPrintDir AS STRING, oForm AS OBJECT, stTarget AS STRING, arSources(), boOhnePreis AS BOOLEAN) // DIM oFrames AS OBJECT, oFrame AS OBJECT, oOldDoc AS OBJECT // DIM stFile AS STRING, stDate AS STRING, stFilename AS STRING, stYear AS STRING, stMonth AS STRING // DIM stWriterFile AS STRING, stXRechnungFile AS STRING, stZUGFeRDFile AS STRING, stZUGFeRDPrintDir AS STRING, stPDFSource AS STRING // DIM stWinEnd AS STRING, stXMLSource AS STRING, stPDFTarget AS STRING, stProgUrl AS STRING // DIM inMonth as INTEGER, inOpen AS INTEGER, i AS INTEGER // DIM arg1(), arMonth(), ar() FUNCTION ExportPDF(oNewDoc AS OBJECT, stPrintDir AS STRING, oForm AS OBJECT, stTarget AS STRING, arSources(), boOhnePreis AS BOOLEAN) LOCAL oFrames AS OBJECT, oFrame AS OBJECT, oOldDoc AS OBJECT LOCAL stFile AS STRING, stDate AS STRING, stFilename AS STRING, stYear AS STRING, stMonth AS STRING LOCAL stWriterFile AS STRING, stXRechnungFile AS STRING, stZUGFeRDFile AS STRING, stZUGFeRDPrintDir AS STRING, stPDFSource AS STRING LOCAL stWinEnd AS STRING, stXMLSource AS STRING, stPDFTarget AS STRING, stProgUrl AS STRING LOCAL inMonth as INTEGER, inOpen AS INTEGER, i AS INTEGER LOCAL arg1(), arMonth(), ar() stFile = oForm.getString(oForm.findColumn("RechnungsnummerMitZusatz")) stFile = Join(Split(stFile, "/"),"_") stDate = oForm.getString(oForm.findColumn("Rechnungsdatum")) stKunde = Trim(oForm.getString(oForm.findColumn("KuerzelDatei"))) stRechnungsname = Trim(oForm.getString(oForm.findColumn("Rechnungsname"))) stDateiname = Trim(oForm.getString(oForm.findColumn("Dateiname"))) IF stKunde <> "" THEN stKunde = stKunde & "_" IF stDateiname <> "" THEN stFilename = Join(Split(stDateiname, "/"),"_") ELSEIF stRechnungsname <> "" THEN stFilename = stFile ELSE stFilename = stKunde & stFile & "_" & stDate END IF REM Bei eingegangenen Rechungen, die weitergeleitet werden, erscheint [WL-] IF arSources(0) = "viw_Lieferung_Spalten_Aenderung" THEN stFilename = "WL-" & stFilename IF arSources(0) = "-M" THEN stFilename = stFilename & arSources(1) stPfad = ArchivPfad(stDate,"",True) stFile = stPfad & stFilename stZUGFeRDDefault = ConvertFromUrl(stPfad & "xrechnung.xml") stWriterFile = stFile & ".odt" oNewDoc.DocumentProperties.Title = stFilename stXRechnungFile = stFile & ".xml" stZUGFeRDFile = stFile & "_zug" & ".xml" stPrintDir = stFile & ".pdf" stZUGFeRDPrintDir = stFile & "_zug" & ".pdf" stPDFSource = ConvertFromUrl(stPrintDir) stXMLSource = ConvertFromUrl(stZUGFeRDFile) stPDFTarget = ConvertFromUrl(stZUGFeRDPrintDir) DIM filterArgs(1) as New com.sun.star.beans.PropertyValue filterArgs(1).Name = "SelectPdfVersion" filterArgs(1).Value = 3 DIM arg(1) AS NEW com.sun.star.beans.PropertyValue arg(0).name = "FilterName" arg(0).value = "writer_pdf_Export" arg(1).Name = "FilterData" arg(1).Value = filterArgs oNewDoc.storeToURL(stPrintDir, arg()) REM Writer-Datei bleibt offen - erst kontrollieren, ob eine entsprechende Datei bereits offen ist oFrames = StarDesktop.getFrames() FOR i = 1 TO oFrames.getCount() oFrame = oFrames.getByIndex(i-1) IF InStr(oFrame.Title, stFilename & ".odt") > 0 THEN inOpen = 1 oOldDoc = oFrame.Controller.Model END IF NEXT IF inOpen = 1 THEN oOldDoc.close(True) END IF oNewDoc.storeAsURL(stWriterFile, arg1()) REM Nur als XRechnung erstellen und per Mail weiterleiten, wenn das Dokument Preise enth„lt. REM Ansonsten wird das Dokument nur gespeichert. IF boOhnePreis = False AND boXRErstellen = True THEN oDatasource = thisDatabaseDocument.CurrentController oConnection = oDatasource.ActiveConnection() oSQL_Statement = oConnection.createStatement() stSql = "SELECT ""Java_Pfad"" FROM ""tbl_Firma""" oResult = oSQL_Statement.executeQuery(stSql) WHILE oResult.Next stProgUrl = oResult.getString(1) WEND IF stProgUrl = "" THEN stProgUrl = "java" IF GetGuiType = 1 THEN stProgUrl = stProgUrl & ".exe"' Windows END IF stApp = ConvertFromUrl(StartPfad & "MustangZug.jar") 'Datei Mustang-CLI-2.20.0.jar einfach umbenannt, damit bei einem Tausch der Code nicht ge„ndert werden muss. Geht auch mit Link. IF stTarget = "ZUGFeRD" THEN SaveZUGFeRD(oForm,stZUGFeRDFile,arSources()) IF FileExists(stPDFTarget) THEN kill(stPDFTarget) 'šberschreiben geht sonst nicht mit Mustang stCommand = stProgUrl & " -jar """ & stApp & """ --action combine --source """ & stPDFSource & """ --source-xml """ & stXMLSource &_ """ --format zf --version 2 --profile X --out """ & stPDFTarget & """ --no-additional-attachments" Shell( stCommand, 1, "", true ) ELSE SaveXRechnung(oForm,stXRechnungFile,arSources()) END IF IF FileExists(StartPfad & "MustangZug.jar") THEN stMsg = "?? Soll die angezeigte Rechnung zus„tzlich validiert werden? ??" & CHR(13) & "Die Validierung kann ca. eine Minute in Anspruch nehmen." inMsg = MsgBox (stMsg, 292, "Validieren") '"Nein" (2. Button) ist der Defaulteintrag IF inMsg = 6 THEN IF stTarget = "ZUGFeRD" THEN stValTest = stPDFTarget REM Im Pfad der Datenbankdatei befindet sich ein Link zu dem Verzeichnis, in dem die Ergebnisdatei gesucht wird. Der Link ist mit "Validation" gekennzeichnet. stValidate = StartPfad & "Validation/" & stFilename & "_zug_result.pdf" ELSE stValTest = ConvertFromUrl(stXRechnungFile) REM Im Pfad der Datenbankdatei befindet sich ein Link zu dem Verzeichnis, in dem die Ergebnisdatei gesucht wird. Der Link ist mit "Validation" gekennzeichnet. stValidate = StartPfad & "Validation/" & stFilename & "_result.pdf" END IF REM Validierung der erzeugten Datei - bisher nur ber Umwege lauff„hig, da die erzeugte PDF-Datei an der Stelle abgeladen wird, von der aus die Base-Datei ge”ffnet wird. REM Wird die Base-Datei durch einen direkten Klick auf die Datei selbst ge”ffnet, so erscheint die Validierungsdatei an diesem Ort. REM Nur in diesem Fall sollte aus Link fr stValidate ® "Validation/" & ¯ entfernt werden. REM Wird die Base-Datei durch einen Link vom Desktop aus ge”ffnet, so erscheint die Validierungsdatei auf dem Desktop. REM Wird die Base-Datei ber das Start-Men des Betriebssystems ge”ffnet, so erscheint die Validierungsdatei direkt im eigenen Home-Verzeichnis. stCommand = stProgUrl & " -jar """ & stApp & """ --action validate --no-notices --source """ & stValTest & """ --log-as-pdf" Shell( stCommand, 1, "", true ) IF FileExists(stValidate) THEN REM Nur wenn die Datei existiert soll der Aufruf versucht werden. Ansonsten soll der (falsche) Pfad in einer Fehlermeldung ausgegeben werden. oShell = createUnoService("com.sun.star.system.SystemShellExecute") oShell.execute(stValidate,"",0) ELSE stValidate = ConvertFromUrl(stValidate) msgbox "Die PDF-Datei mit dem Ergebnis der Validierung konnte nicht gefunden werden." & CHR(13) & "Der angebliche Pfad sollte sein:" & CHR(13) & stValidate END IF END IF END IF stMsg = "?? Soll die Rechnung an das Mailprogamm weitergeleitet werden? ??" & CHR(13) & "Die Rechnung wird bei der ersten Weiterleitung" & CHR(13) & "mit einem entsprechenden Versanddatum gekennzeichnet." inMsg = MsgBox (stMsg, 36, "Mail erstellen") IF inMsg = 6 THEN StartMail(oForm,stFile,stTarget) END IF END IF END SUB */ //ENDE' */ /* nRTxtLen = Len(MemoRead(cRechDir + "R"+StrZero(1->auftrnr,6,0)+".rdr")) //geht das anders? nur die Filel„nge? nHandle := FOpen( cRechDir + "R"+cAuf+".rdr", FO_READ ) cBuffer := Space(nRTxtLen) nBytes := FRead( nHandle, @cBuffer, nRTxtLen ) cHtmlRech += AllTrim(cBuffer) FClose( nHandle ) cHtmlRech += CRLF + '' */ /* nRTxtLen = Len(MemoRead("R"+StrZero(1->auftrnr,6,0)+".html")) //geht das anders? nur die Filel„nge? nHandleR1 := FOpen( "R"+cAuf+".html", FO_READ ) cBuffer := Space(nRTxtLen) nBytes := FRead( nHandleR1, @cBuffer, nRTxtLen ) // cHtmlRech += AllTrim(cBuffer) cHtmlRech := AllTrim(cBuffer) // lesen der mit t_Html gefllten Temp-Datei FClose( nHandleR1 ) // cHtmlRech += CRLF + '