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?
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.