Defining a table with DocumentFormat.OpenXml.Spreadsheet

losol 0 Reputation points
2024-04-26T16:39:17.9333333+00:00

I have successfully managed to make an excel file which is exporting my registration model

    public async Task ExportParticipantListToExcelAsync(
     Stream stream,
     RegistrationListRequest request)
    {
        try
        {
            using var spreadsheetDocument = SpreadsheetDocument.Create(
                stream,
                SpreadsheetDocumentType.Workbook
            );

            var workbookPart = spreadsheetDocument.AddWorkbookPart();
            workbookPart.Workbook = new Workbook();

            var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
            var sheetData = new SheetData();

            var columnConfig = ColumnConfig.GetDefaultConfig();
            WriteHeaderRow(sheetData, columnConfig);

            // Write data rows
            var reader = RegistrationPageReaderFactory.CreateRegistrationPageReader(
                _registrationRetrievalService,
                request
            );

            int dataRowCount = 0;
            while (await reader.HasMoreAsync())
            {
                var registrations = await reader.ReadNextAsync();
                foreach (var registration in registrations)
                {
                    WriteDataRow(sheetData, registration);
                    dataRowCount++;
                }
            }

            // Set the worksheet for the worksheet part
            worksheetPart.Worksheet = new Worksheet(sheetData);

            // Use the helper to add a unique sheet
            ExcelSheetHelper.AddUniqueSheet(workbookPart, worksheetPart, "Participants");

            // Define the Excel table
            ExcelTableBuilder.DefineExcelTable(worksheetPart, columnConfig, dataRowCount);

            // Save the workbook
            workbookPart.Workbook.Save();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "An error occurred while exporting the participant list to Excel.");
            throw;
        }
    }


    private static void AppendRowToSheet(SheetData sheetData, List<string> cellValues)
    {
        var row = new Row();

        foreach (var value in cellValues)
        {
            row.Append(new Cell
            {
                CellValue = new CellValue(string.IsNullOrWhiteSpace(value) ? "a" : value),
                DataType = CellValues.String
            });
        }

        sheetData.Append(row);
    }

    private static void WriteHeaderRow(SheetData sheetData, List<ColumnConfig> columns)
    {
        var headerValues = columns.Select(column => column.Header).ToList();

        AppendRowToSheet(sheetData, headerValues);
    }

    private static void WriteDataRow(SheetData sheetData, Registration registration)
    {
        var config = ColumnConfig.GetDefaultConfig();

        if (config == null || config.Count == 0)
        {
            throw new InvalidOperationException("Column configuration cannot be null or empty.");
        }

        var dataValues = config.Select(column => column.DataExtractor(registration)).ToList();

        AppendRowToSheet(sheetData, dataValues);
    }

}

This is columnconfig


public enum ExcelColumnType
{
    String,
    Number,
    Date,
    Boolean,
}

public class ColumnConfig
{
    public string Header { get; set; }
    public Func<Registration, string> DataExtractor { get; set; }
    public ExcelColumnType ColumnType { get; set; } = ExcelColumnType.String;

    public static List<ColumnConfig> GetDefaultConfig()
    {
        return new List<ColumnConfig>
        {
            new ColumnConfig
            {
                Header = "RegistrationId",
                DataExtractor = reg => reg.RegistrationId.ToString(),
                ColumnType = ExcelColumnType.Number
            },
            new ColumnConfig
            {
                Header = "UserFirstName",
                DataExtractor = reg => reg.User?.GivenName ?? ""
            },
			// omitted some fields for brevity
        };
    }

}

I was hoping that this would define a table for me:


    public static void DefineExcelTable(
        WorksheetPart worksheetPart,
        List<ColumnConfig> columnConfig,
        int dataRowCount
    )
    {

        uint nextTableId = (uint)worksheetPart.GetPartsOfType<TableDefinitionPart>().Count() + 1;

        var table = new Table
        {
            Id = nextTableId,
            Name = "ParticipantList",
            Reference = $"A1:{ExcelColumnName.GetLetters(columnConfig.Count)}{dataRowCount + 1}",
        };

        var tableStyleInfo = new TableStyleInfo
        {
            Name = "TableStyleMedium9",
            ShowFirstColumn = true,
            ShowLastColumn = true,
            ShowRowStripes = true,
            ShowColumnStripes = true,
        };

        table.AppendChild(tableStyleInfo);

        var tableColumns = new TableColumns { Count = (uint)columnConfig.Count };

        uint columnIndex = 1;
        foreach (var config in columnConfig)
        {
            var tableColumn = new TableColumn
            {
                Id = columnIndex,
                Name = config.Header ?? $"Column{columnIndex}"
            };

            tableColumns.Append(tableColumn);
            columnIndex++;
        }

        table.Append(tableColumns);

        var tableDefinitionPart = worksheetPart.GetPartsOfType<TableDefinitionPart>().FirstOrDefault()
                       ?? worksheetPart.AddNewPart<TableDefinitionPart>();
        tableDefinitionPart.Table = table;

        tableDefinitionPart.Table.Save();
    }
}


I was hoping to see this type of table:
User's image

But are currently seeing only a normal spreadsheet without table

User's image

Any tips on how to achieve this?

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,291 questions
Office Development
Office Development
Office: A suite of Microsoft productivity software that supports common business tasks, including word processing, email, presentations, and data management and analysis.Development: The process of researching, productizing, and refining new or existing technologies.
3,517 questions
{count} votes