Inserting fields inside a document from a macro

Hello,

I’m writing a macro which is supposed to insert some fields in the document.
The fields names are retrieved from a database, so there’s a dialog containing a list that is displayed, and then the user selects one field, and this field has to be inserted in the document.

I already searched on Google and inside this forum but I still can’t understand how it works…
Actually, I’m converting a macro from Word, so I perfectly understand how it works in Word, but not fully understand how in works inside Writer, even when I try to do it manually.

For example I saw this kind of code :

  textFields = thisComponent.getTextFields()
  textFieldMasters = thisComponent.getTextFieldMasters()

but I don’t know what is a field master, compared to a simple field.

Can anyone tell me how I can simply add a custom field inside a document from a macro ?

If not a professional you may consider to start based on some examples. Models for text processing are very complicated for many reasons, and if you once insert a “Caption” for an image or a PageNumber field in a header or an Annotation (“comment”) to a position in the text the purposes are already very different. Some kinds of textfields will need a masterTextField of wich they then will be “dependent textfields” others may not. (I think you will not need to create the master explicitly.)
Study the famous texts by Andrew Pitonyak, or start here with a much more specialized question. An answer to this very general question might require to write a book - and to know much more than most contributors do.

Thanks for your answer.

Let me explain what I want to achieve with the macro. To explain better, I will tell you how I do it manually :

I put the cursor where I want in the document.
Then I go to the menu “Insert / Field / Other fields”
Here I choose “Display the variable”, I select the variable that I want and click on the “inter” button.

About these variables, I’m not sure how they work : if I create a variable, will it be available when I open another document ? Or will I have to create it first ?

In my case, the variables that I want to insert in the document (they are all straing variables) are not yet inside the document. Their names are inside a database, so the macro will browse the records and display a list of all the available variables.

So when I click on a variable name and then click on “insert button” of my dialog, the macro will have to check if this variable exist, if not, it will have to create it, and then insert the variable inside the document, where the cursor is.

Is it clearer for you now ?

I will try to make some tests in the meantime. But it’s not something easy…

Thanks for your great help !

may give you some (re)directions :wink:

Hello again,

I made some tests and finally undertstood how things work but I still have a question.

Here’s my coide :

Sub InsertFieldIntoDocument(sFieldName As String, Optional oSection As Boolean, Optional oSectionOpened As Boolean)

	Dim oDoc As Object
    Dim oText As Object
    Dim oViewCursor As Object
    Dim oUserFieldMaster, oUserFieldMasters, oUserField As Object
    Dim bMasterExists As Boolean
    Dim sPrefix As String

    oDoc = ThisComponent
    oText = oDoc.getText()
    oViewCursor = oDoc.getCurrentController().getViewCursor()

    ' Getting the collection of masters of user fields 
    oUserFieldMasters = oDoc.getTextFieldMasters()
    bMasterExists = False

    ' Checks is master field already exists
    sCalculatedFieldName = sFieldName
    ' If it's a section, we have to search for a specific field name
    If oSection Then
    	If oSectionOpened Then
	    	sCalculatedFieldName = "SECT_" & sFieldName
    	Else
    		sCalculatedFieldName = "SECT_END_" & sFieldName
    	End If
    End If
    If oUserFieldMasters.hasByName("com.sun.star.text.fieldmaster.User." & sCalculatedFieldName) Then
        bMasterExists = True
        oUserFieldMaster = oUserFieldMasters.getByName("com.sun.star.text.fieldmaster.User." & sCalculatedFieldName)
    End If

    ' Creates master field if it doesn't exist
    If Not bMasterExists Then
        oUserFieldMaster = oDoc.createInstance("com.sun.star.text.fieldmaster.User")
        oUserFieldMaster.Name = sCalculatedFieldName
        oUserFieldMaster.Value = "abc"
        Msgbox oUserFieldMaster.Value
    End If

    ' Creates the textfield that uses master
    oUserFieldMaster.Value = "abc"
    oUserField = oDoc.createInstance("com.sun.star.text.textfield.User")
    oUserField.attachTextFieldMaster(oUserFieldMaster)

    ' Insert the field in the document
    oText.insertTextContent(oViewCursor, oUserField, False)

End Sub

As you can see, first I check if the master field already exists. If yes, I insert it, and if not, I firest create the master field before inserting it.

My problem is that the field value is always 0 and when I use the inspector, I can see that its type is double. I don’t understand why.

Could you please help me ? When I do it manually, I’m able to insert fields that are “texts”, but when I run the macro they’re always numeric…

Thanks for your help.

oUserFieldMaster.Content = "abc"

Small note: for boolean variables is better the prefix b- instead of o- Optional bSection As Boolean. And then set the default value for Optional variable:

if IsMissing(bSection) then bSection=false

@KamilLanda you rock !!!
Thanks a lot for the “Content” property that I had been looking for for ages !

About the note, I rewrote the code and you’re right, it’s a lot better now.
Here it is :

Sub InsertFieldIntoDocument(sFieldName As String, Optional bSection As Boolean, Optional bSectionOpened As Boolean)

	Dim oDoc As Object
    Dim oText As Object
    Dim oViewCursor As Object
    Dim oUserFieldMaster, oUserFieldMasters, oUserField As Object
    Dim bMasterExists As Boolean
    Dim sPrefix As String

    oDoc = ThisComponent
    oText = oDoc.getText()
    oViewCursor = oDoc.getCurrentController().getViewCursor()
    
    ' Handling optional values
    If IsMissing(bSection) Then bSection = False
    If IsMissing(bSectionOpened) Then bSectionOpened = False

    ' Getting the collection of masters of user fields 
    oUserFieldMasters = oDoc.getTextFieldMasters()
    bMasterExists = False

    ' Checks is master field already exists
    sCalculatedFieldName = sFieldName
    ' If it's a section, we have to search for a specific field name
    If bSection Then
    	If bSectionOpened Then
	    	sCalculatedFieldName = "SECT_" & sFieldName
    	Else
    		sCalculatedFieldName = "SECT_END_" & sFieldName
    	End If
    End If
    If oUserFieldMasters.hasByName("com.sun.star.text.fieldmaster.User." & sCalculatedFieldName) Then
        bMasterExists = True
        oUserFieldMaster = oUserFieldMasters.getByName("com.sun.star.text.fieldmaster.User." & sCalculatedFieldName)
    End If

    ' Creates master field if it doesn't exist
    If Not bMasterExists Then
        oUserFieldMaster = oDoc.createInstance("com.sun.star.text.fieldmaster.User")
        oUserFieldMaster.Name = sCalculatedFieldName
        oUserFieldMaster.Content = ""
        Msgbox oUserFieldMaster.Value
    End If

    ' Creates the textfield that uses master
    oUserField = oDoc.createInstance("com.sun.star.text.textfield.User")
    oUserField.attachTextFieldMaster(oUserFieldMaster)

    ' Insert the field in the document
    oText.insertTextContent(oViewCursor, oUserField, False)

End Sub

Everything is working as expected and I think the code is clean now.

Thanks again, you saved my day (even my week)