Block Attribute with Field Not Displaying in Defined Position After Update

Block Attribute with Field Not Displaying in Defined Position After Update

melomayo6BC8R
Contributor Contributor
552 Views
6 Replies
Message 1 of 7

Block Attribute with Field Not Displaying in Defined Position After Update

melomayo6BC8R
Contributor
Contributor

Hello everyone,

I would like to ask a question in the .NET forum of Autodesk, as I am facing difficulties with API programming. Specifically, I need help with a block named "DYN-LEVEL", which contains several attributes. One of the attributes, defined as "LEVEL", is linked to a field (FIELD).

 

Purpose of the Block:

This block is intended to display elevation values in construction drawings. The elevation value depends on the insertion point of the block and is read from the Y-value of the 3D point using a field formula.

The elevation is prefixed depending on its value:
- If the elevation is exactly **0**, the prefix `%%p` is used to show the symbol `+/-`.
- For **positive** values, a `+` sign is added.
- For **negative** values, no prefix is necessary, as the minus sign automatically appears.

The defined method is automatically triggered by the AutoCAD event ObjectModified.


Question:
My issue is that the field does not appear in the originally defined position within the block after the update. What errors could be causing this, or what additional steps are necessary to ensure the field displays in the correct position?

 

Thank you in advance for your support!

Block Definition:

01_Defintion_DYN-LEVEL_Block.PNG

Block with correct Attribut Position after inserting:

02_Insert_Position - OK.PNG

Block with wrong Attribut location after update:

 

03_Insert_Position - Wrong.PNG

   

 

 

 

 

/// <summary>
/// Updates the attribute field of a block reference based on its name and tag.
/// </summary>
/// <param name="blockId">The ObjectId of the block reference.</param>
/// <param name="blockName">The name of the block to match.</param>
/// <param name="tag">The tag of the attribute to update.</param>
public static void UpdateAttributeField(ObjectId blockId, string blockName, string tag)
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Database db = doc.Database;
    Editor ed = doc.Editor;

    try
    {
        using (Transaction tr = db.TransactionManager.StartTransaction())
        {
            if (tr.GetObject(blockId, OpenMode.ForRead) is not BlockReference blockRef)
                return;

            BlockTableRecord blockDef = (BlockTableRecord)tr.GetObject(blockRef.DynamicBlockTableRecord, OpenMode.ForRead);
            string blockDefName = blockDef?.IsDynamicBlock == true ? blockDef.Name : blockRef.Name;

            if (!blockDefName.Contains(blockName, StringComparison.OrdinalIgnoreCase))
            {
                ed.WriteMessage($"Block name not found: {blockName}");
                return;
            }

            foreach (ObjectId attId in blockRef.AttributeCollection)
            {
                if (tr.GetObject(attId, OpenMode.ForWrite) is not AttributeReference attRef || attRef.Tag != tag)
                    continue;

                if (attRef.HasFields)
                {
                    Field field = tr.GetObject(attRef.GetField(), OpenMode.ForWrite) as Field;
                    if (field == null)
                    {
                        ed.WriteMessage($"Field could not be updated for tag: {tag}");
                        continue;
                    }

                    string currentFieldCode = field.GetFieldCode(FieldCodeFlags.AddMarkers | FieldCodeFlags.FieldCode);
                    string prefix = GetPrefixForYPosition(blockRef.Position.Y);
                    string newFieldCode = prefix + ExtractFieldFormula(currentFieldCode);

                    Field replaceField = new Field(newFieldCode);
                    replaceField.Evaluate();

                    if (replaceField.EvaluationStatus.Status == FieldEvaluationStatus.Success)
                    {
                        attRef.SetField(replaceField);
                        tr.AddNewlyCreatedDBObject(replaceField, true);
                    }
                    else
                    {
                        ed.WriteMessage($"Field evaluation failed. Status: {replaceField.EvaluationStatus.Status}, Message: {replaceField.EvaluationStatus.ErrorMessage}");
                    }
                }

                // SOLUTION:
                attRef.AdjustAlignment(db);
            }

            tr.Commit();
        }
    }
    catch (Exception ex)
    {
        ed.WriteMessage("An error occurred: " + ex.Message);
    }
}

/// <summary>
/// Determines the prefix for the field code based on the Y-coordinate of the insertion point.
/// </summary>
/// <param name="yPosition">The Y-coordinate of the insertion point.</param>
/// <returns>The prefix for the field code.</returns>
public static string GetPrefixForYPosition(double yPosition)
{
    return yPosition > 0 ? "+" : yPosition < 0 ? "" : "%%p";
}

/// <summary>
/// Extracts the field formula from the input string by removing specific prefixes.
/// </summary>
/// <param name="input">The input string containing the field code.</param>
/// <returns>The cleaned field formula.</returns>
public static string ExtractFieldFormula(string input)
{
    if (string.IsNullOrEmpty(input))
        return input;

    var prefixRegex = new Regex(@"^[+\-]|^%%p", RegexOptions.Compiled);
    input = prefixRegex.Replace(input, string.Empty, 1);

    int startIdx = input.IndexOf("%<\\AcExpr");
    return startIdx != -1 ? input.Substring(startIdx) : input;
}

 

 

 

 

Accepted solutions (2)
553 Views
6 Replies
Replies (6)
Message 2 of 7

ntclmain
Advocate
Advocate
Accepted solution

If your attribute is NOT left-justified then you may need to call the AlignAdjustment method after changing the attributeRef.Textstring

*

These old topic of Keanw may help you:

https://www.keanw.com/2008/05/an-automatic--2.html

https://www.keanw.com/2007/07/updating-a-sp-1.html

Message 3 of 7

melomayo6BC8R
Contributor
Contributor

I tried it and got the same result. Could you please provide a few comments on the changes?

thank yout

Message 4 of 7

ActivistInvestor
Mentor
Mentor
Accepted solution

If the code you show is called from an event handler like ObjectModified, it can't use a regular Transaction. It must use an OpenCloseTransaction.

 

While that may not be the cause of your problem it will cause other problems relating to undo and redo.

 

As to your problem, you can try calling Evaluate() after the call to SetField(), and call AdjustAlignment() after that.

Message 5 of 7

melomayo6BC8R
Contributor
Contributor

Hallo @ntclmain @ActivistInvestor :

Hello, both of you! First of all, I’d like to thank you for the helpful tips. They were really useful to me. I was able to solve my problem as follows, by adding the following steps after line 61. And there it is – it works, and I’m very pleased.

 

 

attRef.AdjustAlignment ( db );

 

 

 

 

 

 

 



Message 6 of 7

melomayo6BC8R
Contributor
Contributor
Thank you
Message 7 of 7

melomayo6BC8R
Contributor
Contributor
than you