一个读取Excel时遇到的奇怪问题

今天在读取Excel时发现某些列会有数据丢失的情况,起初我的连接字符串如下:

String connectionString = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0;HDR=YES;IMEX=1;'", filePath);

丢失的数据列是混合类型,前二十多行是Number,中间有些空值,后面几行是字符串。根据网上资料介绍MaxScanRowsImportMixedTypes等扩展属性貌似可以解决我的问题,但需要变更Provider引擎为Jet,加上修改注册表,并非上上策。再看看HDR 属性,为YES时会自动帮我忽略表格中的第一行,当作列名保存起来,还会帮我自动判断类型。

image

这个自动判断类型很方便,但也是丢失数据的罪魁祸首,当ADO认为某一列是Number类型的时候,后面遇到了字符串直接当作DBNull处理。

image

HDR=NO时ADO不会处理列名和类型,但读取的数据需要加工一下,将第一行数据手动设置为列名,然后将其删除,这样即保证了数据的完整性,同时也可以按照之前的方式通过列名访问数据,将改动降到最低,下面贴出核心代码,以作笔记之用。

public class ExcelHelper
{
    public static DataTable GetExcelContent(String filePath, string sheetName)
    {
        DataSet dateSet = new DataSet();
        String connectionString = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0;HDR=NO;IMEX=1;'", filePath);
        String commandString = string.Format("SELECT * FROM [{0}$]", sheetName);
        using (OleDbConnection connection = new OleDbConnection(connectionString))
        {
            connection.Open();
            using (OleDbCommand command = new OleDbCommand(commandString, connection))
            {
                OleDbCommand objCmd = new OleDbCommand(commandString, connection);
                OleDbDataAdapter myData = new OleDbDataAdapter(commandString, connection);
                myData.Fill(dateSet, sheetName);
                DataTable table = dateSet.Tables[sheetName];

                for (int i = 0; i < table.Rows[0].ItemArray.Length; i++)
                {
                    var cloumnName = table.Rows[0].ItemArray[i].ToString();
                    if (!string.IsNullOrEmpty(cloumnName))
                        table.Columns[i].ColumnName = cloumnName;
                }
                table.Rows.RemoveAt(0);
                return table;
            }
        }
    }
}
posted @ 2013-12-06 12:36  冯翔  阅读(316)  评论(0)    收藏  举报