3
votes

I'm trying to create a Pivot table using ClosedXML V0.91.1, but I keep getting problems with my excel file having unreadable content and then the excel workbook removing my pivot table when clicking Yes below.

Error when opening excel file

Below is that shows when I hit Yes. It's removing my pivot table.

Excel removing unreadable content

My Pivot Table is getting data from a table that is created from a history of TFS Changesets. The changesets are set into a IEnumerable<Changeset> which is then converted into a DataTable object which include the column headings.

A table is then created from the DataTable which is the source of the PivotTable. This is the code that I'm using:

public bool CreateReport(IEnumerable<Changeset> changesets)
{
    workbook = new XLWorkbook();
    var sumSheet= workbook.Worksheets.Add("Summary");
    // Converting IEnumerable<Changeset> into DataTable
    DataTable changesetTable = ConvertToDataTable(changesets);
    // Table
    var sumTable = sumSheet.Cell(1, 1).InsertTable(changesetTable.AsEnumerable(), "SummaryTable", true);
    // Table - Formatting table
    tableWithData.Column("A").Cells(firstRow, lastRow).DataType = XLDataType.Number;
    tableWithData.Column("C").Cells(firstRow, lastRow).DataType = XLDataType.DateTime;
    tableWithData.Column("C").Cells(firstRow, lastRow).Style.DateFormat.Format = "d-MMM-yyy";

    sumSheet.Columns().AdjustToContents();

    // Pivot Table
    var header = sumTable.Range(1, 1, 1, 6); // A1 to F1
    var range = sumTable.DataRange;
    var dataRange = sumSheet.Range(header.FirstCell(), range.LastCell());

    var pivotSheet = workbook.Worksheets.Add("History Report");

    var pivotTable = pivotSheet.PivotTables.AddNew("PivotTable", pivotSheet.Cell(1, 1), dataRange);

    // Pivot Table - Formatting table
    pivotTable.ShowPropertiesInTooltips = false;
    pivotTable.RepeatRowLabels = false;
    pivotTable.ShowGrandTotalsColumns = false;
    pivotTable.ShowGrandTotalsRows = false;
    pivotTable.ShowEmptyItemsOnRows = true;
    pivotTable.ShowEmptyItemsOnColumns = true;
    pivotTable.ShowExpandCollapseButtons = false;
    pivotTable.Layout = XLPivotLayout.Tabular;

    pivotTable.RowLabels.Add("Changeset");
    pivotTable.RowLabels.Add("Committer");
    pivotTable.RowLabels.Add("Date");
    pivotTable.RowLabels.Add("Comment");
    pivotTable.RowLabels.Add("File Changes");
    pivotTable.RowLabels.Add("Source");

    // Go off and save the workbook.
    bool saved = SaveFile();
    return saved;
}

I believe the problem is with how I am selecting the dataRange for the source of the Pivot Table.

    var header = sumTable.Range(1, 1, 1, 6); // A1 to F1
    var range = sumTable.DataRange;
    var dataRange = sumSheet.Range(header.FirstCell(), range.LastCell());

I followed the example found on their wiki, but it gives those errors with my implementation. The only difference between my problem and the example, is that I am getting my source for the Pivot Table from a DataTable, and I am only inserting values into RowLabels in my Pivot Table.

If it helps, this is how I convert the IEnumerable<Changeset> to a DataTable

private DataTable ConvertToDataTable(IEnumerable<Changeset> changesets)
{
    DataTable table = new DataTable();
    table.Columns.Add("Changeset", typeof(int));
    table.Columns.Add("Committer", typeof(string));
    table.Columns.Add("Date", typeof(DateTime));
    table.Columns.Add("Comment", typeof(string));
    table.Columns.Add("File Changes", typeof(string));
    table.Columns.Add("Source", typeof(string));

    foreach(Changeset changeset in changesets) // Loop over all changesets
    {
        int changesetID = changeset.ChangesetId;
        string committer = changeset.CommitterDisplayName;
        DateTime creationDate = changeset.CreationDate;
        string comment = changeset.Comment;
        foreach(Change change in changeset.Changes) // Loop over all Changes in changeset
        {
            string filename = change.Item.ServerItem.Substring(change.Item.ServerItem.LastIndexOf("/") + 1);
            table.Rows.Add(changesetID, committer, creationDate, comment, filename, change.Item.ServerItem);
        }
    }
    return table;
}
2
Some comments that are not related to your problem 1) use a using (var workbook... for the XLWorkbook 2) The DataTable isn't required. You can insert the IEnumerable<> directly. 3) header, range, dataRange isn't required, you can pass sumTable.AsRange() as the pivot table source. (I have to update the wiki)Francois Botha

2 Answers

3
votes

If I recall correctly, a pivot table in ClosedXML should have at least one value field.

pivotTable.Values.Add("somefield");
1
votes

I know I am a bit late on this one, but in case anyone else tries to do this in future, my solution was as follows.

IXLPivotTable xlPvTable = TargetWorksheet.PivotTables.Add(
    "PivotTable123", 
    TargetWorksheet.Cell(1, 1), 
    SourceWorksheet.Range(1, 1, MainData.Rows.Count, MainData.Columns.Count)
);

Then add the ColumnLabel and RowLabels etc..