When using OLEDB with Excel, the data type of a column is determined by the first few items in each column. In your case, the first few items in the column are numbers, so it assumes the column is of type int
. If you want the column to be considered text, you need to make sure you have some dummy rows at the top with data that ensures the right data types, then filter out those rows once the data is read into the data table. I know it's a cluge, but it should work.
Edit - Alternative: Using Excel Interop/COM to fill a DataTable
using Microsoft.Office.Interop.Excel;
using Sd = System.Data;
private void FillTableData(Sd.DataTable table, Worksheet worksheet, Range cells)
{
using (var com = new ComObjectManager())
{
var firstCell = GetFirstCell(com, cells);
var beginCell = com.Get<Range>(() => (Range)cells.Item[2, 1]);
var endCell = GetLastContiguousCell(com, cells, firstCell);
if (beginCell.Value == null) return;
var range = GetRange(com, cells, beginCell, endCell);
var data = (object[,])range.Value;
var rowCount = data.GetLength(0);
for (var rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
var values = new object[table.Columns.Count];
for (var columnIndex = 0; columnIndex < table.Columns.Count; columnIndex++)
{
var value = data[rowIndex + 1, columnIndex + 1];
values[columnIndex] = value;
}
table.Rows.Add(values);
}
}
}
private Range GetFirstCell(ComObjectManager com, Range cells)
{
return com.Get<Range>(() => (Range)cells.Item[1, 1]);
}
private Range GetLastContiguousCell(ComObjectManager com, Range cells, Range beginCell)
{
var bottomCell = com.Get<Range>(() => beginCell.End[XlDirection.xlDown]);
var rightCell = com.Get<Range>(() => beginCell.End[XlDirection.xlToRight]);
return com.Get<Range>(() => (Range)cells.Item[bottomCell.Row, rightCell.Column]);
}
ComObjectManager - ensures that COM objects are properly disposed after being used
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public class ComObjectManager : IDisposable
{
private Stack<object> _comObjects = new Stack<object>();
public TComObject Get<TComObject>(Func<TComObject> getter)
{
var comObject = getter();
_comObjects.Push(comObject);
return comObject;
}
public void Dispose()
{
while (_comObjects.Count > 0)
Marshal.ReleaseComObject(_comObjects.Pop());
}
}