ClosedXML - Data Inserted Doesn't Match Data Extracted

41 views Asked by At

Getting away from OLEDB, I decided to try ClosedXML. Very simple to code, but most of the the data coming from the datatable isn't being written to the sheet correctly, and as when using OleDB, I'm getting a corrupted workbook at line 82, column 19.
This is a simple version of the code:

using (XLWorkbook wkb = new XLWorkbook(exportFile.FullName))
{
    var dataTable = GetSqlDbData("usp_GetMyData");
    IXLWorksheet wks = wkb.Worksheet("ExtractData");       
    wks.Cell(2, 1).InsertData(dataTable.AsEnumerable());                    
    wks.Columns().AdjustToContents();
}

The stored procedure returns 21 columns and 445 rows, which are a mix of numeric and text fields. As an example, this is the content of row 1:

Row 1: Column=OfficeName, Type=String, Value=UK - London    
Row 1: Column=AssociateName, Type=String, Value=Smith, Mr    
Row 1: Column=CompanyID, Type=Int32, Value=682    
Row 1: Column=CompanyName, Type=String, Value=My Pension Plan    
Row 1: Column=SchemeID, Type=Int32, Value=820    
Row 1: Column=SchemeName, Type=String, Value=My UK Pension Plan    
Row 1: Column=AccountingDate, Type=String, Value=    
Row 1: Column=AF_Frequency, Type=String, Value=    
Row 1: Column=ValuationDate, Type=DateTime, Value=31/12/2018 00:00:00    
Row 1: Column=VF_Frequency, Type=String, Value=Triennial    
Row 1: Column=TrusteeClientCode, Type=String, Value=618676    
Row 1: Column=TrusteeEngagementCode, Type=String, Value=3302073    
Row 1: Column=CorporateClientCode, Type=String, Value=    
Row 1: Column=CorporateEngagementCode, Type=String, Value=    
Row 1: Column=AccountingCode, Type=String, Value=None    
Row 1: Column=PPFIssue, Type=Boolean, Value=True    
Row 1: Column=PPFASK, Type=String, Value=Trustee    
Row 1: Column=TeamID, Type=Int32, Value=1176    
Row 1: Column=TrusteeAdviceGiven, Type=String, Value=Lots of advice    
Row 1: Column=CompanyAdviceGiven, Type=String, Value=Do not advise    
Row 1: Column=TranscalcUsage, Type=String, Value=None    

Where Value=, the data is NULL in the database.
This is the Xml for the row (row 2) in the corrupted worksheet:

        <x:row r="2" spans="1:21">
        <x:c r="A2" s="0" t="s">
            <x:v>21</x:v>
        </x:c>
        <x:c r="B2" s="0" t="s">
            <x:v>22</x:v>
        </x:c>
        <x:c r="C2" s="1">
            <x:v>682</x:v>
        </x:c>
        <x:c r="D2" s="0" t="s">
            <x:v>23</x:v>
        </x:c>
        <x:c r="E2" s="1">
            <x:v>820</x:v>
        </x:c>
        <x:c r="F2" s="0" t="s">
            <x:v>24</x:v>
        </x:c>
        <x:c r="I2" s="12">
            <x:v>43465</x:v>
        </x:c>
        <x:c r="J2" s="0" t="s">
            <x:v>25</x:v>
        </x:c>
        <x:c r="K2" s="0" t="s">
            <x:v>26</x:v>
        </x:c>
        <x:c r="L2" s="0" t="s">
            <x:v>27</x:v>
        </x:c>
        <x:c r="O2" s="0" t="s">
            <x:v>28</x:v>
        </x:c>
        <x:c r="P2" s="0" t="b">
            <x:v>1</x:v>
        </x:c>
        <x:c r="Q2" s="0" t="s">
            <x:v>29</x:v>
        </x:c>
        <x:c r="R2" s="0">
            <x:v>1176</x:v>
        </x:c>
        <x:c r="S2" s="0" t="s">
            <x:v>30</x:v>
        </x:c>
        <x:c r="T2" s="0" t="s">
            <x:v>31</x:v>
        </x:c>
        <x:c r="U2" s="0" t="s">
            <x:v>28</x:v>
        </x:c>
    </x:row>

The numeric identifiers are correct, i.e. columns C, E and R, and the date field (column I) returns a date serial but the other fields are a value that bears no resemblance, i.e. at row 82, cell A83 = 42 and cell B83 = 401.
Why does the non numeric data from my stored procedure not match when it's fed into the workbook?

1

There are 1 answers

0
MartinS On

It seems the corruption is happening during the download from the server, as the files are perfectly fine before they are downloaded. After some further investigation, I used ClosedXml to stream the file and all is working as expected now.

using (XLWorkbook wkb = new XLWorkbook(exportFile.FullName))
{
    var dataTable = GetSqlDbData("usp_GetMyData");
    IXLWorksheet wks = wkb.Worksheet("ExtractData");       
    wks.Cell(2, 1).InsertData(dataTable.AsEnumerable());                    
    wks.Columns().AdjustToContents();
    HttpContext.Current.Response.Clear();
    using (MemoryStream memoryStream = new MemoryStream())
    {
        wkb.SaveAs(memoryStream);                 
        memoryStream.WriteTo(HttpContext.Current.Response.OutputStream);
        memoryStream.Close();
    }
}

HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpContext.Current.Response.AddHeader("content-disposition", $"attachment;filename={_exportOutput}");
HttpContext.Current.Response.End();
exportFile.Delete();