private Columns CreateColumns(IReadOnlyList <ColumnContext> columns)
        {
            Columns columnsElement = new Columns();

            for (int index = 0; index < columns.Count; index++)
            {
                var  columnContext = columns[index];
                uint colNumber     = (uint)(index + 1);

                int columnWidth = ExcelMetadata.GetFirstDefinedValue(
                    ExcelMetadata.ColumnWidth,
                    columnContext.ColumnMetadata,
                    columnContext.SheetMetadata,
                    columnContext.DocumentMetadata);

                columnContext.Column = new Column {
                    Min = colNumber, Max = colNumber, Width = columnWidth, CustomWidth = true
                };

                // External customization
                var customizeFunc = columnContext.ColumnMetadata?.GetValue(ExcelColumnMetadata.ConfigureColumn);
                customizeFunc?.Invoke(columnContext);

                if (columnContext.Column != null)
                {
                    columnsElement.Append(columnContext.Column);
                }
            }

            return(columnsElement);
        }
        private Cell ConstructCell(ColumnContext columnContext, IPropertyContainer source)
        {
            var    propertyRenderer = columnContext.PropertyRenderer;
            string textValue        = propertyRenderer.Render(source);

            var cellMetadata = propertyRenderer.GetMetadata <ExcelCellMetadata>();

            CellValues dataType = ExcelMetadata.GetFirstDefinedValue(
                ExcelMetadata.DataType,
                cellMetadata,
                columnContext.ColumnMetadata,
                columnContext.SheetMetadata,
                columnContext.DocumentMetadata);

            Cell cell = ConstructCell(textValue, dataType);

            if (dataType == CellValues.Date)
            {
                cell.StyleIndex = _documentContext.GetCellFormatIndex("Date");

                var isLocalTime = propertyRenderer.PropertyType == typeof(LocalTime) || propertyRenderer.PropertyType == typeof(LocalTime?);
                if (isLocalTime)
                {
                    cell.StyleIndex = _documentContext.GetCellFormatIndex("Time");
                }
            }

            // External customization
            var customizeFunc = cellMetadata?.GetValue(ExcelCellMetadata.ConfigureCell);

            if (customizeFunc != null)
            {
                customizeFunc.Invoke(new CellContext(columnContext, cellMetadata, cell));
            }

            return(cell);
        }
        private void AddSheet(SheetContext sheetContext)
        {
            WorkbookPart  workbookPart  = sheetContext.DocumentContext.WorkbookPart;
            WorksheetPart worksheetPart = sheetContext.WorksheetPart;
            uint          sheetCount    = workbookPart.GetSheetCount();

            Worksheet worksheet = new Worksheet()
            {
                MCAttributes = new MarkupCompatibilityAttributes()
                {
                    Ignorable = "x14ac xr xr2 xr3"
                }
            };

            worksheet.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
            worksheet.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
            worksheet.AddNamespaceDeclaration("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
            worksheet.AddNamespaceDeclaration("xr", "http://schemas.microsoft.com/office/spreadsheetml/2014/revision");
            worksheet.AddNamespaceDeclaration("xr2", "http://schemas.microsoft.com/office/spreadsheetml/2015/revision2");
            worksheet.AddNamespaceDeclaration("xr3", "http://schemas.microsoft.com/office/spreadsheetml/2016/revision3");

            worksheetPart.Worksheet = worksheet;

            SheetViews sheetViews = worksheet.GetOrCreateSheetViews();
            SheetView  sheetView  = new SheetView {
                WorkbookViewId = (UInt32Value)0U
            };

            if (sheetCount == 0)
            {
                sheetView.TabSelected = true;
            }

            sheetViews.AppendChild(sheetView);

            SheetFormatProperties sheetFormatProperties = new SheetFormatProperties
            {
                DefaultRowHeight = 15D,
                DyDescent        = 0.25D,
            };

            ColumnContext CreateColumnContext(IPropertyRenderer renderer) =>
            new ColumnContext(
                sheetContext,
                renderer.GetMetadata <ExcelColumnMetadata>() ?? _defaultColumnMetadata,
                renderer);

            sheetContext.Columns = sheetContext
                                   .ReportProvider
                                   .Renderers
                                   .Select(CreateColumnContext)
                                   .ToList();

            Columns columns = sheetContext.IsNotTransposed ? CreateColumns(sheetContext.Columns) : CreateColumnsTransposed();

            SheetData sheetData = new SheetData();

            //workSheet.Append(sheetDimension);
            worksheet.Append(sheetViews);
            worksheet.Append(sheetFormatProperties);
            if (columns != null)
            {
                worksheet.Append(columns);
            }
            worksheet.Append(sheetData);
            //workSheet.Append(pageMargins);

            // Append a new worksheet and associate it with the workbook.
            Sheets sheets = workbookPart.Workbook.Sheets;
            Sheet  sheet  = new Sheet
            {
                Id      = workbookPart.GetIdOfPart(worksheetPart),
                SheetId = sheetCount + 1,
                Name    = sheetContext.ReportProvider.ReportName,
            };

            sheets.Append(sheet);

            bool freezeTopRow = ExcelMetadata.GetFirstDefinedValue(
                ExcelMetadata.FreezeTopRow,
                sheetContext.SheetMetadata,
                sheetContext.DocumentMetadata);

            if (freezeTopRow)
            {
                worksheet.FreezeTopRow(rowNum: 1);
            }

            sheetContext.SheetData = sheetData;
            sheetContext.Sheet     = sheet;
        }