2008-11-18 12 views
10

Tôi cần truy cập bảng tính excel và chèn dữ liệu từ bảng tính vào Cơ sở dữ liệu SQL. Tuy nhiên, các khóa chính được trộn lẫn, hầu hết là số và một số là số alpha.Truy cập Bảng tính Excel với C# thỉnh thoảng trả về giá trị trống cho một số ô

Vấn đề tôi có là khi các phím số và số alpha nằm trong cùng một bảng tính, các ô số alpha trả về giá trị trống, trong khi tất cả các ô khác trả về dữ liệu của chúng mà không gặp sự cố.

Tôi đang sử dụng phương pháp OleDb để truy cập tệp Excel. Sau khi lấy dữ liệu bằng một chuỗi lệnh, tôi đặt dữ liệu vào một DataAdapter và sau đó tôi điền vào một DataSet. Tôi lặp qua tất cả các hàng (dr) trong DataTable đầu tiên trong DataSet.

tôi tham khảo các cột bằng cách sử dụng, dr [ "..."]. ToString()

Nếu tôi gỡ lỗi các dự án trong Visual Studio 2008 và tôi xem các 'thuộc tính mở rộng', bằng cách giữ chuột của tôi trên "dr" Tôi có thể xem các giá trị của DataRow, nhưng Khóa chính phải là số alpha là {}. Các giá trị khác được đặt trong dấu ngoặc kép, nhưng giá trị trống có niềng răng.

Đây có phải là sự cố C# hoặc sự cố Excel không?

Có ai từng gặp vấn đề này trước đây hoặc có thể tìm thấy giải pháp khắc phục sự cố/sửa lỗi không?

Xin cảm ơn trước.

+0

có thể trùng lặp: http://stackoverflow.com/q/3232281/2291 –

Trả lời

1

{} có nghĩa là đây là một loại đối tượng trống và không phải là một chuỗi. Khi bạn di chuột qua đối tượng, bạn sẽ có thể thấy loại của nó. Tương tự như vậy, khi bạn sử dụng đồng hồ bấm giờ để xem dr ["..."] bạn sẽ thấy loại đối tượng. Loại đối tượng bạn nhận được là gì?

1

ItemArray là một mảng đối tượng. Vì vậy, tôi giả định rằng "cột" trong DataRow, mà tôi đang cố gắng tham chiếu, là đối tượng kiểu.

+0

Tôi đã kiểm tra kiểu dữ liệu của cột khi nó được một khóa chính và cột trong DataRow là gấp đôi, khóa chính có một chữ cái trong đó. Tôi hiểu tại sao nó không nhận được giá trị, nhưng làm cách nào để buộc kiểu dữ liệu của cột DataRow thành chuỗi. –

1

Để tương thích với VISTA, bạn có thể sử dụng trình điều khiển EXCEL 12.0 trong chuỗi kết nối. Điều này sẽ giải quyết vấn đề của bạn. Nó đã làm của tôi.

3

Nguồn dữ liệu Excel chọn loại cột cho toàn bộ cột. Nếu một trong các ô không khớp chính xác với loại đó, nó sẽ để trống khoảng trống như thế. Chúng tôi đã có vấn đề mà typist của chúng tôi nhập vào một "8" (một không gian trước khi số lượng, do đó, Excel chuyển nó thành một chuỗi cho ô đó) trong một cột số. Nó sẽ có ý nghĩa với tôi rằng nó sẽ thử các phương pháp. Net Parse vì chúng mạnh mẽ hơn, nhưng tôi đoán đó không phải là cách trình điều khiển Excel hoạt động.

Khắc phục của chúng tôi, vì chúng tôi đã sử dụng dịch vụ nhập cơ sở dữ liệu, là ghi lại tất cả các hàng 'không thành công' theo cách này. Sau đó, chúng tôi quay lại tài liệu XLS và nhập lại các ô đó để đảm bảo loại cơ bản là chính xác. (Chúng tôi tìm thấy chỉ xóa không gian đã không sửa chữa nó - chúng tôi đã phải xóa toàn bộ ô trước tiên, thay vì gõ lại '8'.) Cảm thấy bị hack và không phải là một người không ưa, nhưng đó là phương pháp tốt nhất mà chúng tôi tìm thấy. Nếu trình điều khiển Excel không thể đọc chính xác nó, không có gì bạn có thể làm để lấy dữ liệu đó ra khỏi đó khi bạn đang ở .Net.

Chỉ một trường hợp khác mà Văn phòng ẩn các chi tiết quan trọng của người dùng theo tên đơn giản và do đó làm cho khó khăn hơn khi bạn phải chính xác để sử dụng điện.

+1

Ditto về điều này, và nếu Excel là vô cùng cầu kỳ, bạn có thể thử truy cập vào một ô đơn lẻ: CHỌN F1 TỪ [MyWorksheet $ B12: B12] – Mxyzptlk

+0

Tùy chọn IMEX = 1 trong câu trả lời của @ABHI có hiệu quả đối với chúng tôi trong vài trường hợp. –

25

Giải pháp:

Connection String:

Provider = Microsoft.Jet.OLEDB.4.0; Nguồn dữ liệu = FilePath; Mở rộng Thuộc tính = "Excel 8.0; HDR = Có; IMEX = 1";

  1. HDR=Yes; chỉ ra rằng hàng đầu tiên chứa COLUMNNAMES, không phải dữ liệu. HDR=No; cho biết điều ngược lại.

  2. IMEX=1; yêu cầu người lái luôn đọc cột dữ liệu "intermixed" (số, ngày, chuỗi v.v.) dưới dạng văn bản. Lưu ý rằng tùy chọn này có thể ảnh hưởng đến truy cập ghi excel.

Cú pháp SQL SELECT * FROM [sheet1$]. I E. tên bảng tính excel theo sau là $ và được bọc trong [] dấu ngoặc vuông.

Chú ý:

  • Kiểm tra ra [HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Jet \ 4.0 \ Engines \ Excel] nằm registry REG_DWORD "TypeGuessRows". Đó là chìa khóa để không cho phép Excel chỉ sử dụng 8 hàng đầu tiên để đoán loại dữ liệu cột. Đặt giá trị này thành 0 để quét tất cả các hàng. Điều này có thể làm tổn thương hiệu suất.

  • Nếu sổ làm việc Excel được bảo vệ bằng mật khẩu, bạn không thể mở nó để truy cập dữ liệu, thậm chí bằng cách cung cấp mật khẩu chính xác với chuỗi kết nối của bạn. Nếu bạn cố gắng, bạn nhận được thông báo lỗi sau: "Không thể giải mã tệp."

+2

Hoàn hảo! Giúp tôi với cùng một vấn đề. Thoát dấu ngoặc kép xung quanh: Thuộc tính mở rộng = "Excel 8.0; HDR = Có; IMEX = 1" trở thành Thuộc tính mở rộng = \ "Excel 8.0; HDR = Có; IMEX = 1 \" Và tất cả các vấn đề của bạn sẽ là khỏe! –

+0

Khoá đăng ký khác với trình điều khiển ACE Excel: Excel 2007: HKEY_LOCAL_MACHINE \ Software \ Microsoft \ Office \ 12.0 \ Truy cập kết nối Engine \ Engines \ Excel \ TypeGuessRows Excel 2010: HKEY_LOCAL_MACHINE \ Software \ Microsoft \ Office \ 14.0 \ Access Connectivity Engine \ Engines \ Excel \ TypeGuessRows Excel 2013: HKEY_LOCAL_MACHINE \ Software \ Microsoft \ Office \ 15.0 \ Truy cập kết nối Engine \ Engines \ Excel \ TypeGuessRows [nguồn] (https://social.msdn.microsoft.com/ Diễn đàn/sqlserver/en-US/41222f92-b079-4e6c-ae17-3aa3534a45a7/thiết lập-typeguessrows-cho-excel-ace-driver? Forum = sqlintegrationservices) –

1

Giải pháp:

  1. Bạn đặt HDR = Không để hàng đầu tiên không được xem là tiêu đề cột. Chuỗi kết nối: Nhà cung cấp = Microsoft.Jet.OLEDB.4.0; Nguồn dữ liệu = FilePath; Thuộc tính mở rộng = "Excel 8.0; HDR = Không; IMEX = 1";
  2. Bạn bỏ qua hàng đầu tiên và bạn truy cập dữ liệu theo bất kỳ cách nào bạn muốn (DataTable, DataReader ect). Bạn gắn các cột theo chỉ mục số, thay vì tên cột.

Nó làm việc cho tôi. Bằng cách này bạn không phải sửa đổi sổ đăng ký!

1

Tôi đã trả lời câu hỏi tương tự here. Ở đây tôi đã sao chép và dán cùng một câu trả lời để thuận tiện cho bạn:

Tôi đã gặp vấn đề tương tự, nhưng có thể làm việc xung quanh nó mà không cần đến giao diện Excel COM hoặc phần mềm của bên thứ ba. Nó liên quan đến một ít chi phí xử lý, nhưng dường như được làm việc cho tôi.

  1. Đầu đọc trong các dữ liệu để có được các tên cột
  2. Sau đó tạo một DataSet mới với mỗi người trong số các cột này, thiết lập mỗi kiểu dữ liệu của họ để chuỗi.
  3. Đọc lại dữ liệu trong bộ dữ liệu mới này. Voila - ký hiệu khoa học hiện đã biến mất và mọi thứ được đọc dưới dạng chuỗi.

Dưới đây là một số mã minh họa điều này và như một phần thưởng bổ sung, nó thậm chí còn là StyleCopped!

public void ImportSpreadsheet(string path) 
{ 
    string extendedProperties = "Excel 12.0;HDR=YES;IMEX=1"; 
    string connectionString = string.Format(
     CultureInfo.CurrentCulture, 
     "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"{1}\"", 
     path, 
     extendedProperties); 

    using (OleDbConnection connection = new OleDbConnection(connectionString)) 
    { 
     using (OleDbCommand command = connection.CreateCommand()) 
     { 
      command.CommandText = "SELECT * FROM [Worksheet1$]"; 
      connection.Open(); 

      using (OleDbDataAdapter adapter = new OleDbDataAdapter(command)) 
      using (DataSet columnDataSet = new DataSet()) 
      using (DataSet dataSet = new DataSet()) 
      { 
       columnDataSet.Locale = CultureInfo.CurrentCulture; 
       adapter.Fill(columnDataSet); 

       if (columnDataSet.Tables.Count == 1) 
       { 
        var worksheet = columnDataSet.Tables[0]; 

        // Now that we have a valid worksheet read in, with column names, we can create a 
        // new DataSet with a table that has preset columns that are all of type string. 
        // This fixes a problem where the OLEDB provider is trying to guess the data types 
        // of the cells and strange data appears, such as scientific notation on some cells. 
        dataSet.Tables.Add("WorksheetData"); 
        DataTable tempTable = dataSet.Tables[0]; 

        foreach (DataColumn column in worksheet.Columns) 
        { 
         tempTable.Columns.Add(column.ColumnName, typeof(string)); 
        } 

        adapter.Fill(dataSet, "WorksheetData"); 

        if (dataSet.Tables.Count == 1) 
        { 
         worksheet = dataSet.Tables[0]; 

         foreach (var row in worksheet.Rows) 
         { 
          // TODO: Consume some data. 
         } 
        } 
       } 
      } 
     } 
    } 
} 
0

hi tất cả các mã này là được giá trị chữ và số cũng

using System.Data.OleDb; 

string ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + filepath + ";" + "Extended Properties="+(char)34+"Excel 8.0;IMEX=1;"+(char)34; 

string CommandText = "select * from [Sheet1$]"; 

OleDbConnection myConnection = new OleDbConnection(ConnectionString); 
myConnection.Open(); 

OleDbDataAdapter myAdapter = new OleDbDataAdapter(CommandText, myConnection); 

ds = null; 
ds = new DataSet(); 
myAdapter.Fill(ds); 
1

thứ tự các hồ sơ trong file xls theo mã ascii trong thứ tự giảm dần do đó lĩnh vực chữ và số sẽ xuất hiện ở phía trên cùng bên dưới tiêu đề hàng. Điều này đảm bảo rằng hàng đầu tiên của dữ liệu đọc sẽ xác định loại dữ liệu là "varchar" hoặc "nvarchar"

0

Điều này không hoàn toàn đúng! Rõ ràng, Jet/ACE ALWAYS giả định một kiểu chuỗi nếu 8 hàng đầu tiên trống, bất kể IMEX = 1. Ngay cả khi tôi đã thực hiện các hàng đọc đến 0 trong sổ đăng ký, tôi vẫn có cùng một vấn đề. Đây là chỉ chắc chắn lửa cách để có được nó để làm việc:

try 
{ 
    Console.Write(wsReader.GetDouble(j).ToString()); 
} 
catch //Lame unfixable bug 
{ 
    Console.Write(wsReader.GetString(j)); 
}