Blog · Inventor · 1 Oct 2026 · 3 min read
How to fill the Inventor title block from a spreadsheet automatically
AddTitleBlock with prompt strings returns success and leaves every field empty. Most title block fields are property fields that read the model's iProperties. Set the iProperties on the part, update the drawing, and read the register with the invariant culture. The working iLogic code and the traps.
Short answer: most title block fields are property fields, not prompted entries. They show the iProperties of the model in the view. So don't pass values to AddTitleBlock: write them into the part's iProperties (by property ID), then call Update() on the drawing. Read numbers from the register with the invariant culture, or 10.0 with a comma becomes 1000.
Three attempts that failed
| Attempt | Result |
|---|---|
AddTitleBlock(def, prompts.ToArray()) |
Type mismatch (0x80020005): the array went into the position argument. The old title block was already deleted, so the sheet had none |
The same inside a silent Catch |
Title block present, fields empty, no error shown |
AddTitleBlock(def, Nothing, prompts) |
Returns OK and fills nothing |
The reason: the fields were property fields. Their FormattedText is a <Property Document='model' ...> tag. SetPromptResultText on them gives E_INVALIDARG.
Lesson: a silent Catch hid the real error for a whole round. Log every exception.
Where each field reads from
Find out by reading the FormattedText of each field in the title block definition. In ours:
| Field | Property set | Property |
|---|---|---|
| Designer | Design Tracking | ID 41 |
| Creation date | Design Tracking | ID 4 |
| Description | Design Tracking | ID 29 |
| Part number | Design Tracking | ID 5 |
| Revision | Summary Information | ID 9 |
| Job number | User Defined | JOB |
| Quantity | User Defined | QTY |
Use property IDs, not names: names change with the Inventor language.
The code
Dim oDT As PropertySet = Nothing
Try : oDT = oPS.Item("Design Tracking Properties") : Catch : End Try
If Not (oDT Is Nothing) Then
SetPid(oDT, 41, sDesigner)
SetPid(oDT, 5, sCode)
SetPid(oDT, 29, sDescription.ToUpper())
End If
Dim oUD As PropertySet = Nothing
Try : oUD = oPS.Item("Inventor User Defined Properties") : Catch : End Try
If Not (oUD Is Nothing) Then
SetCustom(oUD, "JOB", sJob) ' Add if missing, else set .Value
SetCustom(oUD, "QTY", CStr(qty))
End If
' then create the view, and finally: oDrawing.Update()
Set the iProperties before creating the view. The fields resolve when the drawing updates.
Reading the register
The register (a CSV with one row per part) is the single source. Three rules:
- Invariant culture for numbers. On an Italian Windows,
10.0read with the local culture failed and10,0became 1000:sp.1000on 101 drawings out of 130.
Double.TryParse(fields(3).Trim(), Globalization.NumberStyles.Any, _
Globalization.CultureInfo.InvariantCulture, dThickness)
- Columns by header name, not index. And check the name exactly:
codeis notdelivery_code. - No separator inside a field. A
;inside a note split the row.
Notes on the sheet
Values that appear in a note (code, thickness, quantity, material) are written into the note's FormattedText, token by token, never into Text. Line breaks are <Br/>, never \P.
Don't edit the title block definition by script
A script that modified the title block definition in the template corrupted the template. Change the definition by hand, once. Scripts only set values.
Do and don't
Do
- Read each field's
FormattedTextto see where it reads from. - Set iProperties on the part, by ID, before the view.
- Call
Update()at the end. - Parse numbers with the invariant culture.
Don't
- Don't pass prompt strings to property fields.
- Don't wrap title block code in a silent
Catch. - Don't edit title block definitions from code.
- Don't read CSV columns by position.
Questions people ask
Can an AI agent fill title blocks on hundreds of drawings? Yes, from the register, in the same rule that creates the drawings. Then it opens a sample and checks every field, because empty fields produce no error.
What if the client wants their own title block? Map their fields once (which property each one reads), then the same code fills them.