private void ManageTemplatePart(RenderingContext renderingContext, ref int currentBindingContextItemId, ref int vOffset, int startPos, int endPos)
        {
            ExcelInterop.Worksheet worksheetFrom = partToRenderDefinition.DefinitionFirstCell.Worksheet;
            ExcelInterop.Worksheet worksheetTo   = currentRenderingTo.Worksheet;

            int gap = endPos - startPos;

            ExcelInterop.Range source = worksheetFrom.Cells[partToRenderDefinition.DefinitionFirstCell.Row + renderingContext.RowId, partToRenderDefinition.DefinitionFirstCell.Column + startPos];
            source = source.Resize[1, gap];
            ExcelInterop.Range workingRange = currentRenderingTo.Resize[1, gap];
            source.Copy(workingRange);

            int bindingContextItemsCount = renderingContext.ContextElement.BindingContextItems.Count;

            for (int colId = startPos; colId < endPos; colId++)
            {
                IBindingContextItem item = partToRenderDefinition.DefinitionParts[renderingContext.RowId, colId] == null || bindingContextItemsCount <= currentBindingContextItemId
                                           ? null
                                           : renderingContext.ContextElement.BindingContextItems[currentBindingContextItemId++];

                if (item != null)
                {
                    if (item is ExcelBindingSearchContextItem)
                    {
                        ExcelInterop.Range range = worksheetTo.Cells[currentRenderingTo.Row, currentRenderingTo.Column + colId - startPos];
                        ((ExcelBindingSearchContextItem)item).SetRange(ref range);
                        range = null;
                    }
                    else if (item is IExcelControl)
                    {
                        ExcelInterop.Range range = worksheetTo.Cells[currentRenderingTo.Row, currentRenderingTo.Column + colId - startPos];
                        ((IExcelControl)item).CreateControl(range);
                        range = null;
                    }
                    if (item.BindingDefinition != null)
                    {
                        if (item.BindingDefinition.IsEnum && !item.BindingDefinition.IsReadOnly)
                        {
                            ExcelInterop.Range range = worksheetTo.Cells[currentRenderingTo.Row, currentRenderingTo.Column + colId - startPos];
                            enumManager.CreateControl(item, ref range);
                            range = null;
                        }
                        if (item.BindingDefinition.IsMultiLine)
                        {
                            ExcelInterop.Range range       = worksheetTo.Cells[currentRenderingTo.Row, currentRenderingTo.Column + colId - startPos];
                            ExcelInterop.Range localSource = source[1, 1 + colId - startPos];
                            multiLineManager.CreateControl(item, ref range, ref localSource, ref vOffset);
                            range = null;
                        }
                        if (item.BindingDefinition.OnAfterRendering != null)
                        {
                            ExcelInterop.Range range = worksheetTo.Cells[currentRenderingTo.Row, currentRenderingTo.Column + colId - startPos];
                            AddAfterRenderingAction(item.BindingDefinition, range);
                            range = null;
                        }
                    }
                }

                renderingContext.DataRow.Add(item);
            }

            source       = null;
            workingRange = null;

            ExcelApplication.ReleaseComObject(worksheetFrom);
            ExcelApplication.ReleaseComObject(worksheetTo);
            worksheetFrom = null;
            worksheetTo   = null;
        }
        private void RenderLink(RenderingContext renderingContext, IBindingContext linkedBindingContext, ExcelInterop.Worksheet worksheetTo)
        {
            ExcelRenderer linkedRenderer = new ExcelRenderer(Parent, renderingContext.LinkedTemplateDefinition.TemplateDefinition, linkedBindingContext, currentRenderingTo,
                                                             renderingContext.LinkedTemplateDefinition.MinOccurencesMethod);

            Parent.RegisterNestedRenderer(linkedRenderer);

            linkedRenderer.Render();

            if (linkedRenderer.RenderedArea != null)
            {
                renderingContext.LinkedViewRenderedWidth = linkedRenderer.Width;
                if (!renderingContext.RowAdded)
                {
                    AddRow(renderingContext);
                    renderingContext.RowAdded = true;
                }

                renderingContext.DataRow.AddRange(linkedRenderer.DataRows[0]);
                //for (int i = 1; i < linkedRenderer.DataRows.Count; i++)
                for (int i = 1; i < linkedRenderer.Height; i++)
                {
                    List <IBindingContextItem> rowToUse;
                    if (i >= renderingContext.CurrentRowHeight)
                    {
                        rowToUse = renderingContext.CurrentRowWidth > 0 ? new List <IBindingContextItem>(new IBindingContextItem[renderingContext.CurrentRowWidth])
                                                                        : new List <IBindingContextItem>();
                        Parent.DataRows.Add(rowToUse);
                    }
                    else
                    {
                        rowToUse = Parent.DataRows[i + renderingContext.RefRow];
                        if (rowToUse.Count < renderingContext.CurrentRowWidth)
                        {
                            rowToUse.AddRange(new IBindingContextItem[renderingContext.CurrentRowWidth - rowToUse.Count]);
                        }
                    }
                    rowToUse.AddRange(linkedRenderer.DataRows[i]);
                }

                // To take the multilines into account
                if (linkedRenderer.Height > linkedRenderer.DataRows.Count)
                {
                    for (int cpt = linkedRenderer.DataRows.Count + 1; cpt <= linkedRenderer.Height; cpt++)
                    {
                        //Parent.DataRow.Add(new List<IBindingContextItem>(new IBindingContextItem[0]));
                        List <IBindingContextItem> rowToUse;
                        if (cpt >= renderingContext.CurrentRowHeight)
                        {
                            rowToUse = renderingContext.CurrentRowWidth > 0 ? new List <IBindingContextItem>(new IBindingContextItem[renderingContext.CurrentRowWidth])
                                                                            : new List <IBindingContextItem>();
                            Parent.DataRows.Add(rowToUse);
                        }
                        else
                        {
                            rowToUse = Parent.DataRows[cpt + renderingContext.RefRow];
                            if (rowToUse.Count < renderingContext.CurrentRowWidth)
                            {
                                rowToUse.AddRange(new IBindingContextItem[renderingContext.CurrentRowWidth - rowToUse.Count]);
                            }
                        }
                        rowToUse.AddRange(new IBindingContextItem[linkedRenderer.Width]);
                    }
                }

                if (renderingContext.CurrentRowHeight < linkedRenderer.Height)
                {
                    renderingContext.CurrentRowHeight = linkedRenderer.Height;
                }

                currentRenderingTo = worksheetTo.Cells[currentRenderingTo.Row, currentRenderingTo.Column + linkedRenderer.Width];
            }
        }
 private void AddRow(RenderingContext renderingContext)
 {
     Parent.DataRows.Add(renderingContext.DataRow);
     renderingContext.CurrentRowHeight = 1;
 }
        protected override void ManageTemplateWithLinkedTemplates()
        {
            ExcelInterop.Worksheet worksheetTo = currentRenderingTo.Worksheet;
            Width = partToRenderDefinition.Width;
            foreach (IBindingContextElement contextElement in bindingContextPart.ElementsToRender)
            {
                ExcelInterop.Range firstElementCell = currentRenderingTo;
                int bindingContextItemsCpt          = 0;
                int cptLinkedDefinition             = 0;
                int elementHeight = 0;
                int elementWidth  = partToRenderDefinition.Width;
                for (int rowId = 0; rowId < partToRenderDefinition.Height; rowId++)
                {
                    RenderingContext renderingContext = new RenderingContext(contextElement, rowId);

                    List <int> posLinks = partToRenderDefinition.PositionLinkedTemplates[rowId];
                    if (posLinks == null)
                    {
                        Parent.DataRows.Add(renderingContext.DataRow);
                        int vOffset = 1;
                        ManageTemplatePart(renderingContext, ref bindingContextItemsCpt, ref vOffset, 0, partToRenderDefinition.Width);
                        currentRenderingTo = worksheetTo.Cells[currentRenderingTo.Row + vOffset, currentRenderingTo.Column];
                        elementHeight     += vOffset;
                    }
                    else
                    {
                        int currentRowHeight = 0;
                        renderingContext.RefRow          = Parent.DataRows.Count > 0 ? Parent.DataRows.Count : 0;
                        renderingContext.PosPreviousLink = 0;
                        int lastPosLink = posLinks.Count - 1;
                        for (int linkCpt = 0; linkCpt < posLinks.Count; linkCpt++)
                        {
                            renderingContext.LinkedViewRenderedWidth  = 0;
                            renderingContext.PosCurrentLink           = posLinks[linkCpt];
                            renderingContext.LinkedTemplateDefinition = partToRenderDefinition.DefinitionParts[rowId, renderingContext.PosCurrentLink] as LinkedTemplateDefinition;
                            // RenderView before link
                            if (renderingContext.PosCurrentLink > 0)
                            {
                                bindingContextItemsCpt = RenderBeforeLink(renderingContext, linkCpt, worksheetTo, bindingContextItemsCpt);
                            }

                            // RenderView link
                            IBindingContext linkedBindingContext = contextElement.LinkedBindingContexts[cptLinkedDefinition++];
                            if (linkedBindingContext.Body != null && (renderingContext.LinkedTemplateDefinition.MinOccurencesMethod != null || linkedBindingContext.Body.ElementsToRender != null && linkedBindingContext.Body.ElementsToRender.Any()))
                            {
                                RenderLink(renderingContext, linkedBindingContext, worksheetTo);
                                renderingContext.CurrentRowWidth += renderingContext.LinkedViewRenderedWidth;
                            }

                            // RenderView after last link
                            if (linkCpt == lastPosLink && renderingContext.PosCurrentLink + 1 < partToRenderDefinition.Width)
                            {
                                bindingContextItemsCpt = RenderAfterLink(renderingContext, bindingContextItemsCpt);
                            }

                            if (renderingContext.CurrentRowWidth > elementWidth)
                            {
                                elementWidth = renderingContext.CurrentRowWidth;
                            }
                            if (renderingContext.CurrentRowHeight > currentRowHeight)
                            {
                                currentRowHeight = renderingContext.CurrentRowHeight;
                            }
                            renderingContext.PosPreviousLink = renderingContext.PosCurrentLink;
                        }
                        elementHeight += currentRowHeight;
                        if (elementWidth > Width)
                        {
                            Width = elementWidth;
                        }
                        currentRenderingTo = worksheetTo.Cells[firstElementCell.Row + elementHeight, firstRangeTo.Column];
                    }
                }

                if (useDecorator && ((ExcelTemplateDefinition)partToRenderDefinition.Parent).Decorator != null)
                {
                    ExcelInterop.Range elementRange = firstElementCell.Resize[elementHeight, elementWidth];
                    Parent.RootRenderer.RowDecorators.Add(new ExcelElementDecorator(elementRange, ((ExcelTemplateDefinition)partToRenderDefinition.Parent).Decorator, contextElement));
                }
                Height += elementHeight;
            }
            ExcelApplication.ReleaseComObject(worksheetTo);
            worksheetTo = null;
        }