Seite 1 von 1

Textfield-Makro: Fehler bei leerem Unterformular vermeiden

Verfasst: Mo 7. Okt 2024, 15:08
von Freischreiber
Hallo,

ich möchte Adressen und Auftragsnummer in einen Brief bringen, die Aufträge stehen in einem Unterformular.

Das Makro fängt so an:

Code: Alles auswählen

Sub Textfield_Adressen (oButtonevent as object)
 DialogLibraries.LoadLibrary( "Standard" )

       oDoc = thisComponent
       oDrawpage = oDoc.drawpage
		oForm = oDrawpage.forms.getbyName("MainForm")
		oFormAuftraege = oForm.getByName("UnterformularAuftraege")
		oFormKontakt = oForm.getbyname("FormKontakt")
        oColumns = oForm.Columns
        nKontakt = oFormKontakt.getint(oFormKontakt.findcolumn("KontaktartID"))
        scurrentKontakt = oFormKontakt.getString(oFormKontakt.findcolumn("Nummer"))
        
        oController = oDoc.getCurrentController()
        
  	    oListenfeldAnrede = oForm.getByName("fmtAnredenID")
  	    oView = oController.getControl(oListenfeldAnrede)
        stAnrede = oView.SelectedItem
        
        oListenfeldTitel = oForm.getByName("fmtTitelID")
  	    oView = oController.getControl(oListenfeldTitel)
  	  	stTitel = oView.SelectedItem
  	  	
  	    'Cursor-Fehlermeldung vermeiden, wenn kein Auftrag vorhanden:
        if IsNull( oFormAuftraege.getstring(oFormAuftraege.findcolumn("AuftragID"))) then
        stAuftrag = ""
        else stAuftrag = oFormAuftraege.getstring(oFormAuftraege.findcolumn("AuftragID")) 
        endif
 		     ...
Und der letzte Absatz ist das Problem: Wenn es einen Auftrag im Unterformular gibt, wird die Auftragsnummer im Writer-Dokument eingetragen (Platzhalterfeld). Wenn es keinen gibt, bleibt das Makro stehen mit der Fehlermeldung "Der Cursor zeigt vor die erste beziehungsweise hinter die letzte Zeile..".

Ohne den ganzen Absatz gibt es zwar keine Fehlermeldung, aber die Auftragsnummer wird auch nicht eingetragen.

Wie kann man diesen Fall "kein Auftrag vorhanden" richtig abfangen?

Witzig finde ich: ein leeres Unterformular "Kontakte" schadet gar nichts. Dort werden verschiedene Fälle behandelt mit

Code: Alles auswählen

 select case nKontakt
        case 3
          scurrentKontakt = "vorab per Fax: " & scurrentKontakt                  
        case 6
           scurrentKontakt = "vorab per Mail: " & scurrentKontakt
       Case else
          scurrentKontakt = ""
       end select

Gruß
Freischreiber

Re: Textfield-Makro: Fehler bei leerem Unterformular vermeiden

Verfasst: Mo 7. Okt 2024, 15:57
von Freischreiber
Hurra, ich konnte aus Roberts Handbuch etwas verwenden, was dort fürs Hauptformular genommen wurde:

Code: Alles auswählen

IF oFormAuftraege.RowCount = 0 THEN
			stAuftrag = ""
        	else stAuftrag = oFormAuftraege.getstring(oFormAuftraege.findcolumn("AuftragID"))
        endif

Inzwischen habe ich sogar MRI installiert, also die Extension, aber es zum Laufen zu bringen, ist nochmal ein Projekt für sich. :oops:

Re: Textfield-Makro: Fehler bei leerem Unterformular vermeiden

Verfasst: Di 8. Okt 2024, 10:44
von RobertG
Nimm statt mri xray. Schau einmal hier: https://ask.libreoffice.org/t/objektvar ... ods/111033

Re: Textfield-Makro: Fehler bei leerem Unterformular vermeiden

Verfasst: Di 8. Okt 2024, 16:16
von Freischreiber
:( Jetzt hab ich die Entscheidung mri oder xray monatelang vor mir hergeschoben, bis hier im Forum jemand mri empfohlen hat. Und wieder falsch?

Re: Textfield-Makro: Fehler bei leerem Unterformular vermeiden

Verfasst: Di 8. Okt 2024, 16:21
von Freischreiber
Ich habe noch eine Frage zu dem Unterformular. Mein ganzes Makro sieht jetzt so aus:

Code: Alles auswählen

Sub Textfield_Adressen (oButtonevent as object)
 DialogLibraries.LoadLibrary( "Standard" )

       oDoc = thisComponent
       oDrawpage = oDoc.drawpage
		oForm = oDrawpage.forms.getbyName("MainForm")
		oFormAuftraege = oForm.getByName("UnterformularAuftraege")
		oFormKontakt = oForm.getbyname("FormKontakt")
        oColumns = oForm.Columns
        nKontakt = oFormKontakt.getint(oFormKontakt.findcolumn("KontaktartID"))
        scurrentKontakt = oFormKontakt.getString(oFormKontakt.findcolumn("Nummer"))
        
        oController = oDoc.getCurrentController()
        
  	    oListenfeldAnrede = oForm.getByName("fmtAnredenID")
  	    oView = oController.getControl(oListenfeldAnrede)
        stAnrede = oView.SelectedItem
        
        oListenfeldTitel = oForm.getByName("fmtTitelID")
  	    oView = oController.getControl(oListenfeldTitel)
  	  	stTitel = oView.SelectedItem
  	  	
  	    'Cursor-Fehlermeldung vermeiden, wenn keine Auftragszeile vorhanden:
		IF oFormAuftraege.RowCount = 0 THEN
			stAuftrag = ""
        	else stAuftrag = oFormAuftraege.getstring(oFormAuftraege.findcolumn("AuftragID")) 'Variablenbelegung, wenn AuftragID vorhanden.
        endif
 
  	    select case nKontakt
        case 3
          scurrentKontakt = "vorab per Fax: " & scurrentKontakt                  
        case 6
           scurrentKontakt = "vorab per Mail: " & scurrentKontakt
       Case else
          scurrentKontakt = ""
       end select
       
       REM Pfad zur Vorlage zusammensetzen (ursprünglich neben der .odb-Datei)
       Globalscope.BasicLibraries.loadLibrary("Tools")
      
       
	' Zusatzinformation aus aufrufendem Button auslesen fürs richtige ott-Formular   
	oButton = oButtonevent.source.model
	sTag = oButton.tag
       
       sURL = convertToUrl("C:\Users\user1\") 
       sURL = sURL & sTag
 
       REM Vorlage öffnen
       Dim args(0) as new com.sun.star.beans.PropertyValue
       args(0).Name = "AsTemplate"
       args(0).Value = True
       newDoc = StarDesktop.loadComponentFromURL(sURL,"_blank",0,args)
     
       REM Textfelder holen
       enumTextfields = newDoc.Textfields.createEnumeration   
       Do While enumTextfields.hasMoreElements
          thisTextfield = enumTextfields.nextElement      
          If thisTextfield.supportsService("com.sun.star.text.TextField.JumpEdit") Then
             sColumnname = thisTextfield.PlaceHolder
             
             if thisTextfield.PlaceHolder = "Kontakt" Then
                 thisTextfield.Anchor.String = scurrentKontakt
             end if
            
             If oColumns.hasByName(sColumnname) Then
                nIndex = oForm.findColumn(sColumnname)
                thisTextfield.Anchor.String = oForm.getString(nIndex)
             End If              
          End If
          If sColumnname = "Anrede" Then
			thisTextfield.Anchor.String = stAnrede
		  End If          
		  If sColumnname = "Titel" Then
			thisTextfield.Anchor.String = stTitel
		  End If
		  If sColumnname = "AuftragID" Then
		  thisTextfield.Anchor.String = stAuftrag
		End If 
       Loop
End Sub
Es funktioniert. Allerdings verstehe ich nicht, warum ich für das Feld AuftragID die Zeilen

Code: Alles auswählen

If sColumnname = "AuftragID" Then
		  thisTextfield.Anchor.String = stAuftrag
End If
brauche, nur weil dieses Feld aus einem Unterformular kommt. Es ist ja nicht so wie bei Anrede und Titel, daß dort nur die IDs im Hauptformular stehen und "Herr" und "Dr." aus der Datenbank geholt werden müssen. Die AuftragID steht im Klartext im Unterformular.

Wenn ich diese Zeilen aber weglasse, wird der Platzhalter <AuftragID> nicht ausgefüllt.
Woran liegt das?

Gruß
Freischreiber

Re: Textfield-Makro: Fehler bei leerem Unterformular vermeiden

Verfasst: Mi 9. Okt 2024, 15:12
von RobertG
Vielleicht hängt das damit zusammen, dass Du Text einfügen willst, "AuftragID" aber eine Zahl ist.

Re: Textfield-Makro: Fehler bei leerem Unterformular vermeiden

Verfasst: Mi 9. Okt 2024, 18:07
von Freischreiber
Hallo Robert,

nein, hab gerade nachgeschaut, AuftragID ist sowohl in der Auftragstabelle als auch in der Zwischentabelle, auf der das Unterformular basiert, als Text(Varchar) angelegt, weil auch Buchstaben drin vorkommen.

Was ich nur gerade seltsam finde: die Formularspalte der Auftrags-ID hat in den Eigenschaften unter Allgemein stehen "Max. Textlänge = 0". Ändert aber auch nichts, wenn ich das auf 12 stelle.

Also du meinst auch, diese drei Zeilen sollten gar nicht nötig sein?

Gruß
Freischreiber

Re: Textfield-Makro: Fehler bei leerem Unterformular vermeiden

Verfasst: Mi 9. Okt 2024, 18:11
von Freischreiber
Hm, gerade stoße ich über Google auf etwas im englischsprachigen Handbuch: (gesucht nach der Zeile "IF oTextfield.supportsService("com.sun.star.text.TextField.JumpEdit")"
"If the name of the text field is the same as the column name in the underlying dataset, the
content of the database is transferred to the field in the text document."
Die Spalte heißt in der Auftragstabelle "ID", in der Zwischentabelle aber "AuftragID". Wenn mit "underlying dataset" die Tabelle gemeint ist, dann liegt es vielleicht daran?

Gruß
Freischreiber

Edit: In deinem Handbuch:
Wenn der Name des Textfeldes gleich dem Spaltennamen der Daten ist, die dem Formular
zugrunde liegen, wird der Inhalt aus der Datenbank auf das Feld in dem Textdokument übertra-
gen.

Re: Textfield-Makro: Fehler bei leerem Unterformular vermeiden

Verfasst: Mi 9. Okt 2024, 21:12
von RobertG
Hallo Freischreiber,

der englischsprachige Base Guide 7.3 ist fast ausschließlich eine Übersetzung des deutschsprachigen Base-Handbuchs Version 5.3 (oder so ähnlich). Ich bewege mich bei Makros auch immer etwas im Bereich von Versuch und Irrtum. Aber wenn das eine klappt und das andere nicht, dann suche ich doch erst einmal nach den Unterschieden. Und die weiß ich bei Deinem Beispiel nicht.

Gruß

Robert

Re: Textfield-Makro: Fehler bei leerem Unterformular vermeiden

Verfasst: Do 10. Okt 2024, 10:34
von Freischreiber
Hallo Robert,

das Makro und die Aufgabe "Suche nach Unterschieden" habe ich jetzt einfach mal in ein KI-Chatprogramm eingegeben. Und die Antwort ist - nach einigem Hin- und Her-Geplänkel - verblüffend. Es wird ein Code vorgeschlagen, der prüft, ob ein Feldname direkt aus dem Haupt- oder dem Unterformular kommt, und danach befüllt er den Anchor-String entweder aus der einen oder aus der anderen Quelle: (so habe ich es jedenfalls verstanden).

Code: Alles auswählen

REM Textfelder holen
enumTextfields = newDoc.Textfields.createEnumeration   
Do While enumTextfields.hasMoreElements
    thisTextfield = enumTextfields.nextElement      

    ' Sicherstellen, dass das TextField das richtige Service unterstützt
    If thisTextfield.supportsService("com.sun.star.text.TextField.JumpEdit") Then
        sColumnname = thisTextfield.PlaceHolder

        ' Überprüfen, ob der Platzhalter aus dem Hauptformular kommt
        If oColumns.hasByName(sColumnname) Then
            nIndex = oForm.findColumn(sColumnname)
            thisTextfield.Anchor.String = oForm.getString(nIndex)
        ' Überprüfen, ob der Platzhalter aus dem Unterformular kommt (z.B. AuftragID)
        ElseIf oFormAuftraege.Columns.hasByName(sColumnname) Then
            nIndex = oFormAuftraege.findColumn(sColumnname)
            thisTextfield.Anchor.String = oFormAuftraege.getString(nIndex)
        End If
        
        ' Sonderfall für Kontakt
        If sColumnname = "Kontakt" Then 
            thisTextfield.Anchor.String = scurrentKontakt
        End If

        ' Sonderfall für Anrede
        If sColumnname = "Anrede" Then
            thisTextfield.Anchor.String = stAnrede
        End If

        ' Sonderfall für Titel
        If sColumnname = "Titel" Then
            thisTextfield.Anchor.String = stTitel
        End If
        
    End If ' End of if thisTextfield.supportsService
Loop
Effekt: Ich muß nicht jeden Feldnamen aus dem Unterformular explizit erwähnen. Und es scheint zu funktionieren. Der Placeholder wird ausgefüllt.

Gruß
Freischreiber