代码之家  ›  专栏  ›  技术社区  ›  rlb.usa

混合Excel数据类型:缺少数据(&M)

  •  49
  • rlb.usa  · 技术社区  · 15 年前

    我有一个Excel工作表,我想读入一个数据表-所有都很好,除了在我的Excel工作表中的一个特定列。“ProductID”列是如下值的组合 ########## n######### .

    我试过了 let OleDB handle everything by itself automatically 通过将其读入dataset/datatable,但“ProductID”中的任何值 n###### 已丢失、忽略并留空。我尝试通过使用datareader在每一行中循环来手动创建DataTable,但结果完全相同。

    // add the column names manually to the datatable as column_1, column_2, ...
    for (colnum = 0; colnum < num_columns; colnum ++){
      ds.Tables["products"].Columns.Add("column_" +colnum , System.Type.GetType("System.String")); 
    }
    while(myDataReader.Read()){
      // loop through each excel row adding a new respective datarow to my datatable 
      DataRow a_row = ds.Tables["products"].NewRow();
      for (col = 0; col < num_columns; col ++){
        try {  a_row[col] = rdr.GetString(col);  }
        catch {  a_row[col] = rdr.GetValue(col).ToString(); }
      }
      ds.Tables["products"].Rows.Add(a_row);
    }
    

    我不明白为什么它不让我读像这样的价值观 不###### . 我该怎么做?

    6 回复  |  直到 11 年前
        1
  •  105
  •   Charles Caldwell    11 年前

    在使用.NET4.0和读取Excel文件时,我也遇到了类似的问题 OleDbDataAdapter

    据我所知,ADO.NET根据列中的大多数值选择数据类型(与数值数据类型相关)。i、 e.如果样本集中的PartID大部分是数字,ADO.NET会将该列声明为数字。因此,ADO.Net将尝试将每个单元格强制转换为一个数字,这对于“text”PartID值将失败,并且不会导入那些“text”PartID。

    OleDbConnection 要使用的连接字符串 Extended Properties=IMEX=1;HDR=NO

    string sql = "SELECT F1, F2, F3, F4, F5 FROM [sheet1$] WHERE F1 IS NOT NULL";
    
    OleDbConnection connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + PrmPathExcelFile + @";Extended Properties=""Excel 8.0;IMEX=1;HDR=NO;TypeGuessRows=0;ImportMixedTypes=Text""");
    
    OleDbCommand cmd = new OleDbCommand(sql, connection);
    OleDbDataAdapter da = new OleDbDataAdapter(cmd);
    
    DataSet ds = new DataSet();
    ds.Tables.Add("xlsImport", "Excel");
    da.Fill(ds, "xlsImport");
    
    // Remove the first row (header row)
    DataRow rowDel = ds.Tables["xlsImport"].Rows[0];
    ds.Tables["xlsImport"].Rows.Remove(rowDel);
    
    ds.Tables["xlsImport"].Columns[0].ColumnName = "LocationID";
    ds.Tables["xlsImport"].Columns[1].ColumnName = "PartID";
    ds.Tables["xlsImport"].Columns[2].ColumnName = "Qty";
    ds.Tables["xlsImport"].Columns[3].ColumnName = "UserNotes";
    ds.Tables["xlsImport"].Columns[4].ColumnName = "UserID";
    
    connection.Close(); 
    

        var data = ds.Tables["xlsImport"].AsEnumerable();
        var query = data.Where(x => x.Field<string>("LocationID") == "COOKCOUNTY").Select(x =>
                    new Contact
                    {
                        LocationID= x.Field<string>("LocationID"),
                        PartID = x.Field<string>("PartID"),
                        Quantity = x.Field<string>("Qty"),
                        Notes = x.Field<string>("UserNotes"),
                        UserID = x.Field<string>("UserID")
                    });
    
        2
  •  10
  •   Amos Zoellner    10 年前

    我发现有几个论坛声称 IMEX=1;TypeGuessRows=0;ImportMixedTypes=Text 在连接字符串中添加扩展属性可以解决问题,但事实并非如此。我最终解决了这个问题,在连接字符串的扩展属性中添加了“HDR=NO”(正如上面brianwells所示),这样就可以导入混合类型了。

        public static DataTable ImportMyDataTableFromExcel(string filePath)
        {
            DataTable dt = new DataTable();
    
            string fullPath = Path.GetFullPath(filePath);
    
            string connString =
               "Provider=Microsoft.Jet.OLEDB.4.0;" +
               "Data Source=\"" + fullPath + "\";" +
               "Extended Properties=\"Excel 8.0;HDR=No;IMEX=1;\"";
    
            string sql = @"SELECT * FROM [sheet1$]";
    
            using (OleDbDataAdapter dataAdapter = new OleDbDataAdapter(sql, connString))
            {
                dataAdapter.Fill(dt);
            }
    
            dt = BuildHeadersFromFirstRowThenRemoveFirstRow(dt);
    
            return dt;
        }
    
        private static DataTable BuildHeadersFromFirstRowThenRemoveFirstRow(DataTable dt)
        {
            DataRow firstRow = dt.Rows[0];
    
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                if(!string.IsNullOrWhiteSpace(firstRow[i].ToString())) // handle empty cell
                  dt.Columns[i].ColumnName = firstRow[i].ToString().Trim();
            }
    
            dt.Rows.RemoveAt(0);
    
            return dt;
        }
    
        3
  •  6
  •   rlb.usa    15 年前

    处理混合数据类型有两种方法;擅长。

    方法1

    方法2

        4
  •  6
  •   Brian Wells    14 年前

    DateTime栏是我记得的另一个让我悲伤的动物。。。我们处理一个excel文件,OleDbDataAdapter有时会将日期转换为double数据类型(显然,excel将日期存储为double,它对1900年1月0日以来经过的天数进行编码)。

    OleDbConnection mobjExcelConn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + txtExcelFile.Text + @";Extended Properties=""Excel 8.0;IMEX=1;HDR=Yes;""");
    
    OleDbDataAdapter mobjExcelDataAdapter = new OleDbDataAdapter("Select * from [" + txtSheet.Text + "$] where [Supplier ID] <> '' ", mobjExcelConn);
    
    
    DateTime dtShipStatus = DateTime.MinValue;
    shipStatusOrig = excelRow["Est Ship Date"].ToString(); // excelRow is DataRow in the DataSet via the OleDbDataAdapter             
    
    if (shipStatusOrig != string.Empty)
    {
        // Date may be read in via oledb adapter as a double
        if (IsNumeric(shipStatusOrig))
        {
            double d = Convert.ToDouble(shipStatusOrig);
            dtShipStatus = DateTime.FromOADate(d);
    
            if (DateTime.TryParse(dtShipStatus.ToString(), out dtShipStatus))
            {
                validDate = true;
                Debug.WriteLine("{0} converted: ", dtShipStatus.ToString("s"));
            }
        }
        else
        {
            if (ValidateShipDate(shipStatusOrig))
            {
                dtShipStatus = DateTime.Parse(shipStatusOrig);
                validDate = true;
                Debug.WriteLine("{0} converted: ", dtShipStatus.ToString("s"));
            }
            else
            {
                validDate = false;
                MessageBox.Show("Invalid date format in the Excel spreadsheet.\nLine # " + progressBar1.Value + ", the 'Ship Status' value '" + shipStatusOrig + "' is invalid.\nDate should be in a valid date time format.\ne.g. M/DD/YY, M.D.Y, YYYY-MM-DD, etc.", "Invaid Ship Status Date");
            }
        }
    ...
    }
            public static Boolean IsNumeric (Object Expression)
            {
                if(Expression == null || Expression is DateTime)
                    return false;
    
                if(Expression is Int16 || Expression is Int32 || Expression is Int64 || Expression is Decimal || Expression is Single || Expression is Double || Expression is Boolean)
                    return true;
    
                try
                {
                    if(Expression is string)
                        Double.Parse(Expression as string);
                    else
                       Double.Parse(Expression.ToString());
                    return true;
                } catch {} // just dismiss errors but return false
    
                return false;
            }
    
            public bool ValidateShipDate(string shipStatus)
            {
                DateTime startDate;
                try
                {
                    startDate = DateTime.Parse(shipStatus);
                    return true;
                }
                catch
                {
                    return false;
                }
            }
    
        5
  •  1
  •   sh4    14 年前

    1.-执行System.Io.File.Copy并创建excel文件的副本。

    3.-保存excel,然后用HDR=NO对修改后的文件进行查询。

    狡猾,是的,但工作,合理的速度很快,如果有人有任何选择,这一点,我会很高兴听到。

    问候语。

    对不起,我的英语不是我的母语。

        6
  •  1
  •   Ibo    7 年前

    我几乎浏览了这里的所有答案,其中有些对我有用,有些对我没有,但是没有一个对我来说是可取的,因为不知何故ADO没有选择我在Excel文件中的混合类型列中的数据。我得去准备 HDR=NO 为了让ADO读取我的电子表格列,它是文本和数字的混合体,这样我就失去了在SQL语句中使用列标题的能力,这是不好的。如果Excel文件中列的顺序发生变化,SQL语句将导致错误或输出错误。

    在混合数据类型列中,键是前8行。ADO根据前8行确定列的数据类型 因此,如果您仍要使用扩展参数修改连接字符串,只需在通过ADO读取数据之前将列Z排序到Excel文件中的A,这样顶部的行就是文本行,然后列将被选为文本。