2009-01-09 35 views
6

Tôi có một công việc C# /. Net nhập dữ liệu từ Excel và sau đó xử lý nó. Khách hàng của chúng tôi xóa các tệp và chúng tôi xử lý chúng (quan trọng vì tôi không có bất kỳ quyền kiểm soát nào đối với tệp gốc).Ký pháp khoa học khi nhập từ Excel vào .Net

Tôi sử dụng thư viện OleDb để điền vào tập dữ liệu (Tôi ghét viết mã đó. Nghiêm túc, có bất kỳ mã nào mà một nhà phát triển .Net viết nhiều hơn thế không?). Tệp này chứa một số số như 30829300, 30071500, v.v ... Loại dữ liệu cho các cột đó là "Văn bản".

Những số đó được chuyển đổi thành ký hiệu khoa học khi tôi nhập dữ liệu. Có cách nào để ngăn điều này xảy ra không?

-Chris

+0

dữ liệu gì được bạn nhập khẩu chuỗi số thành? – scottm

Trả lời

3

Thư viện OleDb sẽ, thường xuyên hơn, không làm hỏng dữ liệu của bạn trong bảng tính Excel. Điều này chủ yếu là do nó buộc mọi thứ vào bố cục cột cố định, đoán ở loại mỗi cột từ các giá trị trong 8 ô đầu tiên trong mỗi cột. Nếu nó đoán sai, bạn kết thúc bằng các chuỗi chữ số được chuyển đổi thành ký hiệu khoa học. Blech!

Để tránh điều này, bạn nên bỏ qua OleDb và đọc bản thân trực tiếp. Bạn có thể làm điều này bằng cách sử dụng giao diện COM của Excel (cũng blech!), Hoặc trình đọc tương thích với .NET của bên thứ ba. SpreadsheetGear là một trong những thư viện đó hoạt động khá tốt, và có một giao diện rất giống với giao diện COM của Excel.

0

Tôi nhận thấy rằng cách dễ nhất là chọn định dạng Zip, thay vì định dạng văn bản cho các cột có số 'lớn'.

+0

Như tôi đã nói ở trên, tôi không có quyền kiểm soát tệp. Khách hàng tạo ra điều đó. – ChrisDiRulli

0

Bạn đã thử truyền giá trị của trường đến (int) hoặc có lẽ (Int64) khi bạn đang đọc nó?

+0

Tôi không "đọc" tệp, API OleDb thực hiện điều đó. Tôi chỉ đơn giản gọi phương thức "fill" trên OleDbDataAdapter và chuyển vào DataSet. Dataset sau đó được lấp đầy với dữ liệu ngon ngọt ngon. – ChrisDiRulli

+0

Tập dữ liệu có được nhập mạnh để trường đó dự kiến ​​một số không? – palehorse

+0

Không, nó không được gõ mạnh. – ChrisDiRulli

0

Tra cứu tùy chọn chuỗi kết nối IMEX = 1 và cài đặt đăng ký TypeGuessRows trên google. Trong sự thật, không có cách nào dễ dàng vòng này bởi vì người đọc gây ra các kiểu dữ liệu cột bằng cách xem xét một vài hàng đầu tiên (theo mặc định). Nếu các hàng chứa tất cả các số thì bạn sẽ không may mắn.

Cách giải quyết không may mà tôi đã sử dụng trong quá khứ là sử dụng tùy chọn chuỗi kết nối HDR = NO và đặt giá trị cài đặt đăng ký TypeGuessRows thành 1, buộc nó đọc hàng đầu tiên dưới dạng dữ liệu hợp lệ để tạo kiểu dữ liệu của nó xác định, thay vì tiêu đề. Đó là một hack, nhưng nó hoạt động. Mã đọc hàng đầu tiên (chứa tiêu đề) dưới dạng văn bản, và sau đó đặt kiểu dữ liệu cho phù hợp.

Thay đổi sổ đăng ký là một nỗi đau (và không phải lúc nào cũng có thể) nhưng tôi khuyên bạn nên khôi phục giá trị ban đầu sau đó.

Nếu dữ liệu nhập của bạn không có hàng tiêu đề, thì tùy chọn thay thế là xử lý trước tệp và chèn 'ký tự trước mỗi số trong cột vi phạm. Điều này làm cho dữ liệu cột được coi là văn bản.

Vì vậy, tất cả trong tất cả, có một loạt các hacks để làm việc xung quanh này, nhưng không có gì thực sự dễ dàng.

+0

tôi đã thử IMEX = 1 thuộc tính .. chuỗi con là "Nhà cung cấp = Microsoft.ACE.OLEDB.12.0; Nguồn dữ liệu = # FILEPATH #; Thuộc tính mở rộng = 'Excel 12.0 Xml; HDR = NO; IMEX = 1" nhưng giá trị đến như 2.13123219999999E + 18 ........... – dankyy1

+0

Bạn cũng phải đặt mục đăng ký TypeGuessRows. Như tôi đã nói, đó là một hack không may. –

0

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

Tôi mệt mỏi khối mã này nhưng vẫn còn giá trị trong sc.notation ... – dankyy1

+0

darn! không phải loại vấn đề này khiến bạn muốn cắt tóc ra sao? –

0

Tôi googled xung quanh tình trạng này .. Dưới đây là solulition tôi bước

  • Đối với mẫu file excel

1-định dạng Excel coloumn như chữ 2- ghi vĩ mô để vô hiệu hóa cảnh báo lỗi cho Số -> văn bản hội tụ

Private Sub Workbook_BeforeClose(Cancel As Boolean) 
Application.ErrorCheckingOptions.BackgroundChecking = Ture 
End Sub 
Private Sub Workbook_Open() 
Application.ErrorCheckingOptions.BackgroundChecking = False 
End Sub 
  • On codebehind

3- khi đọc dữ liệu để nhập thử để phân tích dữ liệu đến để Int64 hoặc Int32 ....

0

Tôi quan tâm để biết nếu có ai có câu trả lời cho điều này . Tôi đã được tất cả lên và xuống interwebs và thử tất cả các kết hợp của IMEX và HDR. IMEX = 1 là người duy nhất tôi quản lý để trích xuất ngày, tiền tệ, và các giá trị số chung với. Nhưng số lượng lớn vẫn cho thấy là khoa học. Tôi chỉ cần đọc các tập tin và thay đổi bảng tính, đăng ký, bên thứ 3 không phải là một lựa chọn.

5

Một workaround cho vấn đề này là để thay đổi lựa chọn công bố của bạn, thay vì SELECT * làm điều này:

"SELECT Format([F1], 'General Number') From [Sheet1$]" 
-or- 
"SELECT Format([F1], \"#####\") From [Sheet1$]" 

Tuy nhiên, làm như vậy sẽ nổ tung nếu các tế bào của bạn chứa nhiều hơn 255 ký tự với các lỗi sau: "Nhiều lỗi OLE DB hoạt động được tạo ra. Kiểm tra từng giá trị trạng thái OLE DB, nếu có. Không có công việc nào được thực hiện".

May mắn thay khách hàng của tôi không quan tâm đến lỗi trong trường hợp này.

Trang này có một loạt các điều tốt đẹp để thử cũng như: http://www.dicks-blog.com/archives/2004/06/03/external-data-mixed-data-types/

+0

Xin chào. Tôi đã sử dụng bản sửa lỗi này và dường như đã khắc phục mọi thứ cho tôi. Vấn đề là dường như làm tròn mọi số để hai chữ số cuối cùng là số 0. Ví dụ 12345678 trở thành 12345600. Có ai biết cách tôi sửa lỗi này không? – Loogawa

1

Nếu bạn nhìn vào các tập tin .XSLX thực tế sử dụng SDK Open XML 2.0 Năng suất Tool (hoặc đơn giản là giải nén tập tin và xem các XML trong notepad) bạn sẽ thấy rằng Excel 2007 thực sự lưu trữ dữ liệu thô ở định dạng khoa học.

Ví dụ 0,00001 được lưu giữ như 1.0000000000000001E-5

<x:c r="C18" s="11" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> 
    <x:v>1.0000000000000001E-5</x:v> 
</x:c> 

Nhìn vào các tế bào trong Excel của mình hiển thị như 0,00001 ở cả tế bào và thanh công thức. Vì vậy, nó không phải luôn luôn đúng là OleDB đang gây ra vấn đề.

2

Sử dụng chuỗi kết nối này:

Provider=Microsoft.ACE.OLEDB.12.0; data source={0}; Extended Properties=\"Excel 12.0;HDR=NO;IMEX=1\" 

với Excel 2010 tôi đã nhận thấy những điều sau đây. Nếu tệp Excel được mở khi bạn chạy OLEDB SELECT thì bạn sẽ nhận được phiên bản hiện tại của các ô, chứ không phải các giá trị tệp đã lưu. Hơn nữa các giá trị chuỗi trả lại cho một số dài, giá trị thập phân và ngày nhìn như thế này:

5.0130370071e+012 
4.08 
36808 

Nếu file không mở cửa thì giá trị trả lại là:

loại
5013037007084 
£4.08 
Monday, October 09, 2000 
Các vấn đề liên quan