private ExcelTemplateDefinitionPart Execute(ExcelTemplateDefinition excelTemplateDefinition, TemplateDefinitionPartType partType, ExcelInterop.Range firstRange, ExcelInterop.Range lastRange)
        {
            ExcelTemplateDefinitionPart part = new ExcelTemplateDefinitionPart(excelTemplateDefinition, partType, firstRange, lastRange);

            for (int rowId = 0; rowId < part.DefinitionCells.Rows.Count; rowId++)
            {
                List <int>         posLinks = null;
                ExcelInterop.Range row      = part.DefinitionCells.Rows[rowId + 1];

                for (int cellId = 0; cellId < row.Cells.Count; cellId++)
                {
                    ExcelInterop.Range cell           = row.Cells[cellId + 1];
                    IDefinitionPart    definitionPart = AnalyzeCell(part, cell);
                    part.DefinitionParts[rowId, cellId] = definitionPart;

                    if (definitionPart is LinkedTemplateDefinition)
                    {
                        if (posLinks == null)
                        {
                            posLinks = new List <int>();
                        }
                        posLinks.Add(cellId);
                    }

                    if (definitionPart is IBindingDefinition)
                    {
                        if (((IBindingDefinition)definitionPart).IsMultiLine)
                        {
                            part.ContainMultiLinesCells = true;
                        }

                        if (((IBindingDefinition)definitionPart).OnAfterRendering != null)
                        {
                            if (part.OnAfterRendering == null)
                            {
                                part.OnAfterRendering = new List <EventCallback>();
                            }
                            part.OnAfterRendering.Add(((IBindingDefinition)definitionPart).OnAfterRendering);
                        }
                    }
                }
                part.PositionLinkedTemplates.Add(posLinks);
            }

            return(part);
        }
        //@@/// <summary> If a expandable header is defined, contains the binding excelTemplateDefinition used to manage the 'Expand' property of the template (needs a header defined on the template.</summary>
        //public IBindingDefinition ExpanderBindingDefinition
        //{ get; set; }
        #endregion

        #region .ctors
        public ExcelTemplateDefinitionPart(ExcelTemplateDefinition parent, TemplateDefinitionPartType partType, ExcelInterop.Range firstRange, ExcelInterop.Range lastRange) : base(partType)
        {
            Parent = parent;
            DefinitionFirstCell = firstRange;
            DefinitionLastCell  = lastRange;

            Width  = DefinitionLastCell.Column - DefinitionFirstCell.Column + 1;
            Height = DefinitionLastCell.Row - DefinitionFirstCell.Row + 1;
            if (Width == 0 || Height == 0)
            {
                throw new System.Exception("A template part ('Header','Body' or 'Footer' must have a 'Height' and a 'Width' >= 1");
            }

            ExcelInterop.Range templateRange = DefinitionFirstCell;
            DefinitionCells = DefinitionFirstCell = templateRange.Cells[1, 1];

            DefinitionCells = templateRange.Resize[Height, Width];
            DefinitionParts = new IDefinitionPart[Height, Width];

            PositionLinkedTemplates = new List <List <int> >();
        }
        /// <summary>Analyze a cell of the template part</summary>
        private IDefinitionPart AnalyzeCell(ExcelTemplateDefinitionPart templateDefinitionPart, ExcelInterop.Range cell)
        {
            IDefinitionPart part = null;

            if (cell.Value2 != null)
            {
                string value = cell.Value2.ToString();
                if (!string.IsNullOrEmpty(value))
                {
                    string trimmedValue = value.Trim();
                    if (trimmedValue.StartsWith(LINKED_TEMPLATE_PREFIX))
                    {
                        try
                        {
                            XmlTemplateLink xmlTemplateLink = trimmedValue.Deserialize <XmlTemplateLink>();
                            TemplateLink    templateLink    = TemplateLink.CreateInstance(xmlTemplateLink);

                            ExcelTemplateDefinition  templateDefinition       = (ETKExcel.TemplateManager as ExcelTemplateManager).GetTemplateDefinitionFromLink(templateDefinitionPart, templateLink);
                            LinkedTemplateDefinition linkedTemplateDefinition = new LinkedTemplateDefinition(templateDefinitionPart.Parent, templateDefinition, templateLink);
                            templateDefinitionPart.AddLinkedTemplate(linkedTemplateDefinition);
                            part = linkedTemplateDefinition;
                        }
                        catch (Exception ex)
                        {
                            string message = $"Cannot create the linked template dataAccessor '{trimmedValue}'. {ex.Message}";
                            throw new EtkException(message, false);
                        }
                    }
                    else
                    {
                        if (trimmedValue.StartsWith(ExcelBindingFilterDefinition.Filter_PREFIX))
                        {
                            ExcelBindingFilterDefinition filterdefinition = ExcelBindingFilterDefinition.CreateInstance(templateDefinitionPart, trimmedValue);
                            templateDefinitionPart.AddFilterDefinition(filterdefinition);
                            part = filterdefinition;
                        }
                        else if (trimmedValue.StartsWith(ExcelBindingSearchDefinition.Search_PREFIX))
                        {
                            ExcelBindingSearchDefinition searchdefinition = ExcelBindingSearchDefinition.CreateInstance(trimmedValue);
                            templateDefinitionPart.AddSearchDefinition(searchdefinition);
                            part = searchdefinition;
                        }
                        else
                        {
                            try
                            {
                                IBindingDefinition bindingDefinition = CreateBindingDefinition(templateDefinitionPart, value, trimmedValue);
                                templateDefinitionPart.AddBindingDefinition(bindingDefinition);
                                part = bindingDefinition;
                            }
                            catch (Exception ex)
                            {
                                string message = $"Cannot create the binding definition for '{trimmedValue}'. {ex.Message}";
                                throw new EtkException(message, false);
                            }
                        }
                    }
                }
            }
            return(part);
        }