2009-02-20 10 views
5

मैं एक्सेल फ़ाइलों को सफलतापूर्वक पढ़ने के लिए एक ओलेडीबी कनेक्शन का उपयोग कर रहा हूं, लेकिन अब मुझे एक समस्या है। मुझे कोई ऐसा व्यक्ति मिला है जो पहले कॉलम में कुछ भी नहीं के साथ एक्सेल स्प्रेडशीट अपलोड करने का प्रयास कर रहा है और जब मैं फ़ाइल को पढ़ने की कोशिश करता हूं, तो वह कॉलम को पहचान नहीं पाता है।मैं किसी कॉलम को खोए बिना सी # में एक्सेल फ़ाइल कैसे पढ़ूं?

मैं वर्तमान में निम्नलिखित OleDb कनेक्शन स्ट्रिंग का उपयोग कर रहा:

प्रदाता = Microsoft.Jet.OLEDB.4.0;
डेटा स्रोत = सी: \ test.xls;
विस्तारित गुण = "एक्सेल 8.0; IMEX = 1;"

तो, अगर एक्सेल फ़ाइल में 13 कॉलम हैं, तो OleDbDataReader I वापस प्राप्त करने के लिए केवल 12 कॉलम/फ़ील्ड हैं।

किसी भी अंतर्दृष्टि की सराहना की जाएगी।

+0

यदि पहले कॉलम में कुछ भी नहीं है, तो समस्या क्या है? – StingyJack

उत्तर

3

SpreadsheetGear for .NET आप xls के साथ काम करने और नेट से कार्यपुस्तिका xlsx के लिए एक API देता है। ओलेडीबी या एक्सेल COM ऑब्जेक्ट मॉडल से उपयोग करना और तेज़ करना आसान है। आप live samples देख सकते हैं या free trial के साथ अपने आप को आजमाएं।

अस्वीकरण: मैं खुद SpreadsheetGear LLC

संपादित करें:

StingyJack टिप्पणी की, " OleDb से तेज़ बेहतर वापस कि ऊपर का दावा?"।

यह एक उचित अनुरोध है। मैं हर समय दावा करता हूं कि मैं झूठी होने के लिए एक तथ्य के बारे में जानता हूं, इसलिए मैं संदेह के लिए किसी को दोष नहीं दे सकता।

स्प्रेडशीट गियर के साथ 10 कॉलम कार्यपुस्तिका द्वारा 50,000 पंक्ति बनाने के लिए कोड है, इसे डिस्क पर सहेजें, और फिर ओलेडीबी और स्प्रेडशीट गियर का उपयोग करके संख्याओं को योग करें।स्प्रेडशीट गियर 0.31 सेकंड में 500 के कोशिकाओं को ओलेडीबी के साथ 0.63 सेकेंड की तुलना में पढ़ता है - बस तेज़ी से दोगुना से अधिक। स्प्रेडशीट गियर वास्तव में ओलेडीबी के साथ कार्यपुस्तिका को पढ़ने के लिए कम समय में कार्यपुस्तिका बनाता है और पढ़ता है।

कोड नीचे है। आप इसे स्प्रेडशीटगियर मुफ्त परीक्षण के साथ स्वयं आज़मा सकते हैं।

using System; 
using System.Data; 
using System.Data.OleDb; 
using SpreadsheetGear; 
using SpreadsheetGear.Advanced.Cells; 
using System.Diagnostics; 

namespace SpreadsheetGearAndOleDBBenchmark 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      // Warm up (get the code JITed). 
      BM(10, 10); 

      // Do it for real. 
      BM(50000, 10); 
     } 

     static void BM(int rows, int cols) 
     { 
      // Compare the performance of OleDB to SpreadsheetGear for reading 
      // workbooks. We sum numbers just to have something to do. 
      // 
      // Run on Windows Vista 32 bit, Visual Studio 2008, Release Build, 
      // Run Without Debugger: 
      // Create time: 0.25 seconds 
      // OleDb Time: 0.63 seconds 
      // SpreadsheetGear Time: 0.31 seconds 
      // 
      // SpreadsheetGear is more than twice as fast at reading. Furthermore, 
      // SpreadsheetGear can create the file and read it faster than OleDB 
      // can just read it. 
      string filename = @"C:\tmp\SpreadsheetGearOleDbBenchmark.xls"; 
      Console.WriteLine("\nCreating {0} rows x {1} columns", rows, cols); 
      Stopwatch timer = Stopwatch.StartNew(); 
      double createSum = CreateWorkbook(filename, rows, cols); 
      double createTime = timer.Elapsed.TotalSeconds; 
      Console.WriteLine("Create sum of {0} took {1} seconds.", createSum, createTime); 
      timer = Stopwatch.StartNew(); 
      double oleDbSum = ReadWithOleDB(filename); 
      double oleDbTime = timer.Elapsed.TotalSeconds; 
      Console.WriteLine("OleDb sum of {0} took {1} seconds.", oleDbSum, oleDbTime); 
      timer = Stopwatch.StartNew(); 
      double spreadsheetGearSum = ReadWithSpreadsheetGear(filename); 
      double spreadsheetGearTime = timer.Elapsed.TotalSeconds; 
      Console.WriteLine("SpreadsheetGear sum of {0} took {1} seconds.", spreadsheetGearSum, spreadsheetGearTime); 
     } 

     static double CreateWorkbook(string filename, int rows, int cols) 
     { 
      IWorkbook workbook = Factory.GetWorkbook(); 
      IWorksheet worksheet = workbook.Worksheets[0]; 
      IValues values = (IValues)worksheet; 
      double sum = 0.0; 
      Random rand = new Random(); 
      // Put labels in the first row. 
      foreach (IRange cell in worksheet.Cells[0, 0, 0, cols - 1]) 
       cell.Value = "Cell-" + cell.Address; 
      // Using IRange and foreach be less code, 
      // but we'll do it the fast way. 
      for (int row = 1; row <= rows; row++) 
      { 
       for (int col = 0; col < cols; col++) 
       { 
        double number = rand.NextDouble(); 
        sum += number; 
        values.SetNumber(row, col, number); 
       } 
      } 
      workbook.SaveAs(filename, FileFormat.Excel8); 
      return sum; 
     } 

     static double ReadWithSpreadsheetGear(string filename) 
     { 
      IWorkbook workbook = Factory.GetWorkbook(filename); 
      IWorksheet worksheet = workbook.Worksheets[0]; 
      IValues values = (IValues)worksheet; 
      IRange usedRahge = worksheet.UsedRange; 
      int rowCount = usedRahge.RowCount; 
      int colCount = usedRahge.ColumnCount; 
      double sum = 0.0; 
      // We could use foreach (IRange cell in usedRange) for cleaner 
      // code, but this is faster. 
      for (int row = 1; row <= rowCount; row++) 
      { 
       for (int col = 0; col < colCount; col++) 
       { 
        IValue value = values[row, col]; 
        if (value != null && value.Type == SpreadsheetGear.Advanced.Cells.ValueType.Number) 
         sum += value.Number; 
       } 
      } 
      return sum; 
     } 

     static double ReadWithOleDB(string filename) 
     { 
      String connectionString = 
       "Provider=Microsoft.Jet.OLEDB.4.0;" + 
       "Data Source=" + filename + ";" + 
       "Extended Properties=Excel 8.0;"; 
      OleDbConnection connection = new OleDbConnection(connectionString); 
      connection.Open(); 
      OleDbCommand selectCommand =new OleDbCommand("SELECT * FROM [Sheet1$]", connection); 
      OleDbDataAdapter dataAdapter = new OleDbDataAdapter(); 
      dataAdapter.SelectCommand = selectCommand; 
      DataSet dataSet = new DataSet(); 
      dataAdapter.Fill(dataSet); 
      connection.Close(); 
      double sum = 0.0; 
      // We'll make some assumptions for brevity of the code. 
      DataTable dataTable = dataSet.Tables[0]; 
      int cols = dataTable.Columns.Count; 
      foreach (DataRow row in dataTable.Rows) 
      { 
       for (int i = 0; i < cols; i++) 
       { 
        object val = row[i]; 
        if (val is double) 
         sum += (double)val; 
       } 
      } 
      return sum; 
     } 
    } 
} 
+0

ओलेडीबी से तेज? दावा है कि बेहतर वापस। – StingyJack

+0

स्टिंगी जैक: मैं आपको संदेह के लिए दोषी नहीं ठहराता हूं। मैंने कोड के साथ अपनी प्रतिक्रिया संपादित की है जो दर्शाता है कि स्प्रेडशीट गियर ओलेडीबी से वास्तव में तेज़ है। –

+0

मेरी संख्याएं थोड़ी अलग थीं, लेकिन उचित रूप से बंद थीं। आपको वास्तव में अपनी साइट पर पोस्ट करना चाहिए। एक एक्सएलएस घटक के लिए खरीदारी करते समय, यह वास्तव में देखने के लिए जानकारी होगी। – StingyJack

1

हम हमेशा स्प्रेडशीट खोलने और सीधे पार्स खोलने के लिए एक्सेल इंटरऑप का उपयोग करते हैं (उदाहरण के लिए आप वीबीए में कोशिकाओं के माध्यम से स्कैन कैसे करेंगे), या हम लॉक डाउन टेम्पलेट्स बनाते हैं जो उपयोगकर्ता को सहेजने से पहले कुछ स्तंभों को भरने के लिए लागू करते हैं डेटा।

+0

इंटरऑप लाइब्रेरी के साथ जाएं। एलएल सही है। – KevDog

0

यदि कॉलम हेडर रखने के लिए एक्सेल शीट के प्रारूप की आवश्यकता हो सकती है, तो आपके पास हमेशा 13 कॉलम होंगे। प्रसंस्करण करते समय आपको हेडर पंक्ति को छोड़ना होगा।

यह उन स्थितियों को भी ठीक करेगा जहां उपयोगकर्ता कॉलम को उस क्रम में रखता है जिसकी आप अपेक्षा नहीं कर रहे हैं। (हेडर पंक्ति में कॉलम इंडेक्स का पता लगाएं और उचित रूप से पढ़ें)

मुझे लगता है कि अन्य एक्सेल इंटरऑप की सिफारिश कर रहे हैं, लेकिन जीज़ यह ओलेडीबी तरीके की तुलना में धीमा विकल्प है। इसके अलावा इसे सर्वर (लाइसेंसिंग) पर एक्सेल या ओडब्ल्यूसी स्थापित करने की आवश्यकता है।

+0

फ़ाइलों में वर्तमान में हेडर पंक्ति है। यहां तक ​​कि जब मैं हेलेर पंक्ति (एचडीआर = एनओ का उपयोग करके) को शामिल करने के लिए ओलेडीबी को बताता हूं, फिर भी यह केवल 12 कॉलम देता है और पहले कॉलम को छोड़ देता है। – Austin

+0

कि एचडीआर विकल्प पीछे की ओर लगता है ... कॉन स्ट्रिंग के संदर्भ के रूप में (http://www.connectionstrings.com/excel) जांचें। – StingyJack

+0

मुझे पता है कि यह पीछे की ओर लगता है, लेकिन आप इसे हेडर पंक्ति देने के लिए एचडीआर = NO सेट करते हैं (मूल रूप से, आप कह रहे हैं कि हेडर पंक्ति एक डेटा पंक्ति है) – Austin

0

आप Excel और COM का उपयोग करने का प्रयास कर सकते हैं। इस तरह, आपको अपनी जानकारी सीधे घोड़े के मुंह के रूप में मिल जाएगी, जैसा कि यह था।

डी आनंद से MSDN मंचों पर खत्म हो गया:

एक्सेल में अपनी परियोजना में एक संदर्भ बनाएं ऑब्जेक्ट्स लाइब्रेरी। एक्सेल ऑब्जेक्ट लाइब्रेरी को संदर्भ संवाद जोड़ने के COM टैब में जोड़ा जा सकता है।

यहाँ सी # में एक्सेल ऑब्जेक्ट मॉडल पर कुछ जानकारी है http://msdn.microsoft.com/en-us/library/aa168292(office.11).aspx

+0

घोड़ों के मुंह में चबाने में थोड़ी देर लगती है, इसलिए यह बड़ी (> 1000 पंक्ति) फ़ाइलों के लिए बहुत अच्छा नहीं होगा। – StingyJack

+1

इसके अलावा घोड़ों का मुंह सर्वर वातावरण में अच्छी तरह से नहीं चलता है अगर यह एक सर्वर वातावरण वातावरण – JoshBerke

+0

हाँ, मैं गति समस्या के कारण COM या इंटरऑप रूट जाने से बचना चाहता हूं; लेकिन यह हो सकता है कि हमें क्या करना है। इससे पहले कि मैं इस तरह से कोई अन्य विचार? – Austin

0

मैं आपको कार्यालय और एक्सेल इंटरऑप के लिए विजुअल स्टूडियो टूल्स का प्रयास करने की सलाह देता हूं! इसका उपयोग करना बहुत आसान है।

1

आप शायद ExcelMapper को देख सकते हैं। यह एक्सेल फ़ाइलों को दृढ़ता से टाइप की गई वस्तुओं के रूप में पढ़ने का एक साधन है। यह आपके कोड से एक्सेल पढ़ने के सभी विवरण छुपाता है। यदि आपके एक्सेल में कॉलम गुम हो रहा है या डेटा कॉलम से गायब है तो यह ख्याल रखेगा। आप उस डेटा को पढ़ते हैं जिसमें आप रुचि रखते हैं। आप http://code.google.com/p/excelmapper/ से ExcelMapper के लिए कोड/निष्पादन योग्य प्राप्त कर सकते हैं।

संबंधित मुद्दे