Delete Empty Merge Fields

2 posts, 0 answers
  1. Steve
    Steve avatar
    3 posts
    Member since:
    May 2014

    Posted 12 Mar 2015 Link to this post

    Hi,

    I would like to be able to either not insert a custom merge field document fragment if the result is empty or iterate over the document merge fields and delete empty ones.

    I have a custom merge field as follows:
    public class CustomMergeField : MergeField
        {
            public const string CustomFieldName = "MATCustomField";
     
            static CustomMergeField()
            {
                CodeBasedFieldFactory.RegisterFieldType(CustomMergeField.CustomFieldName, () =>
                {
                    return new CustomMergeField();
                });
            }
     
            public override string FieldTypeName
            {
                get
                {
                    return CustomMergeField.CustomFieldName;
                }
            }
     
            public override Field CreateInstance()
            {
                return new CustomMergeField();
            }
     
            public bool ResultFragmentEmpty
            {
                get { return base.IsResultFragmentEmpty(); }
            }
            protected override DocumentFragment GetResultFragment()
            {
                var d = this.Document.MailMergeDataSource.CurrentItem as Dictionary<string, Object>;
                if (d == null)
                {
                    return this.CreateFragmentFromText(this.FieldCode);
                }
                else
                {
                    if (d.ContainsKey(this.PropertyPath))
                    {
                        var f = d[this.PropertyPath] as DGField;
                        if (f != null && f.Data != null)
                        {
                            switch (f.DataType)
                            {
                                case DGField.DataTypeOptions.String:
                                    {
                                        var DataString = f.Data.ToString();
                                        //DataString = DataString.Replace(Environment.NewLine, FormattingSymbolLayoutBox.LINE_BREAK); //"¬""¶"
                                        if (DataString.Contains(Environment.NewLine))
                                        {
                                            var lines = DataString.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
                                             
                                            RadDocumentEditor editor = new RadDocumentEditor(new RadDocument());
                                            editor.ChangeParagraphLineSpacing(1.15);
                                            for (int i = 0; i < lines.Length; i++)
                                            {
                                                editor.Insert(lines[i]);
                                                if (i < lines.Length - 1)
                                                {
                                                    editor.Insert(Environment.NewLine);
                                                }
                                            }
     
                                            return new DocumentFragment(editor.Document);
                                        }
     
                                        return this.CreateFragmentFromText(DataString);
                                    }
                                case DGField.DataTypeOptions.Date:
                                    {
                                        if (f.SchemaName == "General.DateNow")
                                        {
                                            return this.CreateFragmentFromText(DateTime.Now.ToShortDateString());
                                        }
                                        else if (f.SchemaName == "General.DateNowLongFormat")
                                        {
                                            return this.CreateFragmentFromText(DateTime.Now.ToLongDateString());
                                        }
                                        if (f.SchemaName.Contains("LongFormat"))
                                        {
                                            return this.CreateFragmentFromText(((DateTime)f.Data).ToLongDateString());
                                        }
                                        return this.CreateFragmentFromText(((DateTime)f.Data).ToShortDateString());
                                    }
                                case DGField.DataTypeOptions.Currency:
                                    {
                                        string CurrencySymbol;
                                        int CurrencyPrecision;
                                        if (d.ContainsKey("currency.currencysymbol"))
                                        {
                                            CurrencySymbol = ((DGField)d["currency.currencysymbol"]).Data.ToString();
                                        }
                                        else
                                        {
                                            CurrencySymbol = "£";
                                        }
     
                                        if (d.ContainsKey("currency.currencyprecision"))
                                        {
                                            CurrencyPrecision = (int)((DGField)d["currency.currencyprecision"]).Data;
                                        }
                                        else
                                        {
                                            CurrencyPrecision = 2;
                                        }
                                        return this.CreateFragmentFromText(Formatting.Currency.DecimalToCurrency(Convert.ToDecimal(((Money)f.Data).Value), CurrencyPrecision, CurrencySymbol));
                                    }
                                case DGField.DataTypeOptions.Lookup:
                                    return this.CreateFragmentFromText(((EntityReference)f.Data).Name);
                                default:
                                    return this.CreateFragmentFromText(f.Data.ToString());
                            }
                        }
                        else
                        {
                            return this.CreateFragmentFromText(string.Empty);
                        }
                    }
                    else
                    {
                        //return null;
                        return this.CreateFragmentFromText(string.Empty);
                    }
                }
            }
        }

    If the data passed in is empty then ideally I want nothing to be inserted in the document because it leaves white space and in some places a blank line.

    Also your examples if using the TextAfterIfNotEmpty doesn't work as the ¬ symbol just appears as that in my documents. You can see above I have had to comment this symbol out as it just appears inline with the fields all on one line.

    I have tried the following method to delete merge fields which are empty but nothing happens.

    private void ClearBlankFields(object parameter)
            {
                var fields = this.View.radRichTextBox.Document.EnumerateChildrenOfType<FieldRangeStart>().Where(x => x.EnumerateChildrenOfType<FieldRangeStart>().Any(f => f.Field is CustomMergeField));
                foreach (var f in fields)
                {
                    if (((CustomMergeField)f.Field).ResultFragmentEmpty)
                    {
                        f.Parent.Children.Remove(f);
                    }
                }
            }

    It does not throw an exception but the field is still present.

    Thanks for your help
  2. Tanya
    Admin
    Tanya avatar
    402 posts

    Posted 16 Mar 2015 Link to this post

    Hello Steve,

    In order to achieve this behavior you could iterate through all merge fields in result mode, select them and check if the selection contains text. If the field is empty, the selection can be used to delete the whole field. In the snippet below is demonstrated how exactly this could be implemented:
    this.editor.Document.FieldsDisplayMode = FieldDisplayMode.Result;
    var fields = this.editor.Document.GetAnnotationMarkersOfType<FieldRangeStart>().ToList();
     
    for (int i = 0; i < fields.Count(); i++)
    {
        if (fields[i].Field is MergeField && (fields[i].Field as MergeField).DisplayMode == FieldDisplayMode.Result)
        {
            this.editor.Document.CaretPosition.MoveToStartOfDocumentElement(fields[i]);
            DocumentPosition start = new DocumentPosition(this.editor.Document.CaretPosition);
            this.editor.Document.CaretPosition.MoveToStartOfDocumentElement(fields[i].End);
            DocumentPosition end = new DocumentPosition(this.editor.Document.CaretPosition);
     
            this.editor.Document.Selection.SetSelectionStart(start);
            this.editor.Document.Selection.AddSelectionEnd(end);
     
            string value = this.editor.Document.Selection.GetSelectedText();
     
            if (string.IsNullOrEmpty(value))
            {
                this.editor.Delete(false);
            }
        }
    }

    Please, let me know if you have any other questions.

    Regards,
    Tanya
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. DevCraft banner
Back to Top