SHEET ORDER में शीट नाम पाने के लिए Excel OleDb का उपयोग करना


103

मैं कई शीट के साथ एक्सेल वर्कबुक से पढ़ने के लिए ओलेडब का उपयोग कर रहा हूं।

मुझे शीट नामों को पढ़ने की आवश्यकता है, लेकिन मुझे उन्हें उसी क्रम में चाहिए, जिस क्रम में उन्हें स्प्रेडशीट में परिभाषित किया गया है; इसलिए यदि मेरे पास एक फाइल है जो इस तरह दिखती है;

|_____|_____|____|____|____|____|____|____|____|
|_____|_____|____|____|____|____|____|____|____|
|_____|_____|____|____|____|____|____|____|____|
\__GERMANY__/\__UK__/\__IRELAND__/

फिर मुझे शब्दकोश प्राप्त करने की आवश्यकता है

1="GERMANY", 
2="UK", 
3="IRELAND"

मैंने उपयोग करने की कोशिश की है OleDbConnection.GetOleDbSchemaTable(), और यह मुझे नामों की सूची देता है, लेकिन यह वर्णानुक्रम में उन्हें क्रमबद्ध करता है। अल्फा-सॉर्ट का मतलब है कि मुझे नहीं पता कि कौन सी शीट नंबर किसी विशेष नाम से मेल खाती है। तो मुझे मिलता है;

GERMANY, IRELAND, UK

जिसने UKऔर के क्रम को बदल दिया है IRELAND

मुझे इसे सॉर्ट करने के लिए कारण की आवश्यकता है कि मुझे उपयोगकर्ता को नाम या इंडेक्स द्वारा डेटा की एक श्रेणी चुनने देना है; वे 'GERMANY से IRELAND का सारा डेटा' या 'शीट 1 से शीट 3 का डेटा' के लिए पूछ सकते हैं।

किसी भी विचार की बहुत प्रशंसा की जाएगी।

अगर मैं कार्यालय इंटरोप कक्षाओं का उपयोग कर सकता हूं, तो यह सीधा होगा। दुर्भाग्य से, मैं नहीं कर सकता क्योंकि इंटरोप कक्षाएं गैर-संवादात्मक वातावरण जैसे कि विंडोज़ सेवाओं और ASP.NET साइटों में मज़बूती से काम नहीं करती हैं, इसलिए मुझे OLEDB का उपयोग करने की आवश्यकता थी।


आप एक्सेल फ़ाइल के किस संस्करण को पढ़ रहे हैं?
यमन

30
वाह, आपने कैसे आकर्षित किया और आपके पास कैसे आकर्षित करने का धैर्य था
l'''''''--------- '' '' '' '' '' ''

4
@ Арт rowsмЦарионов - वे तालिका के लिए ऊर्ध्वाधर सलाखों (!) और अंडरस्कोर (_) की पंक्तियाँ हैं, और टैब के लिए आगे और पीछे-स्लैश (\ /) हैं। इसे टेक्स्ट एडिटर में कॉपी करें और आप देखेंगे।
सिड हॉलैंड

जवाबों:


17

यह वास्तविक MSDN प्रलेखन में नहीं मिल सकता है, लेकिन मंचों में एक मध्यस्थ ने कहा

मुझे डर है कि OLEDB शीट ऑर्डर को संरक्षित नहीं करता है क्योंकि वे एक्सेल में थे

शीट ऑर्डर में एक्सेल शीट नाम

ऐसा लगता है कि एक सामान्य पर्याप्त आवश्यकता होगी कि एक सभ्य समाधान होगा।


हालाँकि इसने सीधे जवाब दिया, यह अनावश्यक कोशिशों पर बहुत समय बचाता है।
शिह जांग

75

क्या आप 0 से लेकर नामों की गिनती तक शीट के माध्यम से लूप नहीं कर सकते हैं? इस तरह आपको उन्हें सही क्रम में प्राप्त करना चाहिए।

संपादित करें

मैंने टिप्पणियों के माध्यम से देखा कि शीट नामों को पुनः प्राप्त करने के लिए इंटरोप कक्षाओं का उपयोग करने के बारे में बहुत सारी चिंताएं हैं। इसलिए यहाँ उन्हें पुनः प्राप्त करने के लिए OLEDB का उपयोग करके एक उदाहरण दिया गया है:

/// <summary>
/// This method retrieves the excel sheet names from 
/// an excel workbook.
/// </summary>
/// <param name="excelFile">The excel file.</param>
/// <returns>String[]</returns>
private String[] GetExcelSheetNames(string excelFile)
{
    OleDbConnection objConn = null;
    System.Data.DataTable dt = null;

    try
    {
        // Connection String. Change the excel file to the file you
        // will search.
        String connString = "Provider=Microsoft.Jet.OLEDB.4.0;" + 
          "Data Source=" + excelFile + ";Extended Properties=Excel 8.0;";
        // Create connection object by using the preceding connection string.
        objConn = new OleDbConnection(connString);
        // Open connection with the database.
        objConn.Open();
        // Get the data table containg the schema guid.
        dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

        if(dt == null)
        {
           return null;
        }

        String[] excelSheets = new String[dt.Rows.Count];
        int i = 0;

        // Add the sheet name to the string array.
        foreach(DataRow row in dt.Rows)
        {
           excelSheets[i] = row["TABLE_NAME"].ToString();
           i++;
        }

        // Loop through all of the sheets if you want too...
        for(int j=0; j < excelSheets.Length; j++)
        {
            // Query each excel sheet.
        }

        return excelSheets;
   }
   catch(Exception ex)
   {
       return null;
   }
   finally
   {
      // Clean up.
      if(objConn != null)
      {
          objConn.Close();
          objConn.Dispose();
      }
      if(dt != null)
      {
          dt.Dispose();
      }
   }
}

CodeProject पर अनुच्छेद से निकाला गया ।


वह कोड मैं देखना चाहूंगा! आप 'एनटी शीट' और शीट की संख्या के लिए कैसे क्वेरी कर सकते हैं?
स्टीव कूपर

13
नमस्ते जेम्स। यह मेरी मूल समस्या से बहुत अधिक है - जबकि GetOleDbSchemaTable () विधि के नाम मिलते हैं, पंक्ति संख्या कार्यपुस्तिका शीट नंबर के अनुरूप नहीं होती है। तो शीट 4 पंक्ति 0 होगी, अगर यह वर्णमाला में पहली बार आती है।
स्टीव कूपर

23
पोस्टर प्रश्न का उत्तर नहीं देता (वह एक्सेल में उपस्थिति के क्रम में चाहता है)
एंड्रयू व्हाइट

7
@Samuel मुझे नहीं लगता कि इसने सीधे ओपी की समस्या को हल कर दिया है, हालांकि, ऐसा लगता है कि यह एक समान मुद्दे के साथ दूसरों की बहुत मदद करता है।
जेम्स

1
ओपी के सवाल को हल नहीं करता है, जो कि मैं देख रहा हूं। (मैं हमेशा एक पतन का कारण पोस्ट करता हूं।)
फिल निकोलस

23

चूंकि उपरोक्त कोड एक्सेल 2007 के लिए शीट नाम की सूची निकालने की प्रक्रियाओं को कवर नहीं करता है, एक्सेल (97-2003) और एक्सेल 2007 दोनों के लिए भी निम्नलिखित कोड लागू होगा:

public List<string> ListSheetInExcel(string filePath)
{
   OleDbConnectionStringBuilder sbConnection = new OleDbConnectionStringBuilder();
   String strExtendedProperties = String.Empty;
   sbConnection.DataSource = filePath;
   if (Path.GetExtension(filePath).Equals(".xls"))//for 97-03 Excel file
   {
      sbConnection.Provider = "Microsoft.Jet.OLEDB.4.0";
      strExtendedProperties = "Excel 8.0;HDR=Yes;IMEX=1";//HDR=ColumnHeader,IMEX=InterMixed
   }
   else if (Path.GetExtension(filePath).Equals(".xlsx"))  //for 2007 Excel file
   {
      sbConnection.Provider = "Microsoft.ACE.OLEDB.12.0";
      strExtendedProperties = "Excel 12.0;HDR=Yes;IMEX=1";
   }
   sbConnection.Add("Extended Properties",strExtendedProperties);
   List<string> listSheet = new List<string>();
   using (OleDbConnection conn = new OleDbConnection(sbConnection.ToString()))
   {
     conn.Open();
     DataTable dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);         
     foreach (DataRow drSheet in dtSheet.Rows)
     {
        if (drSheet["TABLE_NAME"].ToString().Contains("$"))//checks whether row contains '_xlnm#_FilterDatabase' or sheet name(i.e. sheet name always ends with $ sign)
        {
             listSheet.Add(drSheet["TABLE_NAME"].ToString());
        } 
     }
  }
 return listSheet;
}

उपरोक्त फ़ंक्शन दोनों एक्सेल प्रकार (97,2003,2007) के लिए विशेष रूप से एक्सेल फ़ाइल में शीट की सूची देता है।


11
यह कोड शीट को उस क्रम में नहीं लौटाता है जिस क्रम में वे एक्सेल में दिखाई देते हैं
एंड्रयू व्हाइट

10

यह छोटा, तेज, सुरक्षित और प्रयोग करने योग्य है ...

public static List<string> ToExcelsSheetList(string excelFilePath)
{
    List<string> sheets = new List<string>();
    using (OleDbConnection connection = 
            new OleDbConnection((excelFilePath.TrimEnd().ToLower().EndsWith("x")) 
            ? "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + excelFilePath + "';" + "Extended Properties='Excel 12.0 Xml;HDR=YES;'"
            : "provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + excelFilePath + "';Extended Properties=Excel 8.0;"))
    {
        connection.Open();
        DataTable dt = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
        foreach (DataRow drSheet in dt.Rows)
            if (drSheet["TABLE_NAME"].ToString().Contains("$"))
            {
                string s = drSheet["TABLE_NAME"].ToString();
                sheets.Add(s.StartsWith("'")?s.Substring(1, s.Length - 3): s.Substring(0, s.Length - 1));
            }
        connection.Close();
    }
    return sheets;
}

"बॉक्स से बाहर" काम नहीं करता है। exceladdress- यह क्या है?
माइकल हटर

8

दूसरा रास्ता:

xls (x) फ़ाइल * .zml कंटेनर में संग्रहीत * .xml फ़ाइलों का एक संग्रह है। फ़ोल्डर docProps में फ़ाइल "app.xml" को अनज़िप करें।

<?xml version="1.0" encoding="UTF-8" standalone="true"?>
-<Properties xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes" xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties">
<TotalTime>0</TotalTime>
<Application>Microsoft Excel</Application>
<DocSecurity>0</DocSecurity>
<ScaleCrop>false</ScaleCrop>
-<HeadingPairs>
  -<vt:vector baseType="variant" size="2">
    -<vt:variant>
      <vt:lpstr>Arbeitsblätter</vt:lpstr>
    </vt:variant>
    -<vt:variant>
      <vt:i4>4</vt:i4>
    </vt:variant>
  </vt:vector>
</HeadingPairs>
-<TitlesOfParts>
  -<vt:vector baseType="lpstr" size="4">
    <vt:lpstr>Tabelle3</vt:lpstr>
    <vt:lpstr>Tabelle4</vt:lpstr>
    <vt:lpstr>Tabelle1</vt:lpstr>
    <vt:lpstr>Tabelle2</vt:lpstr>
  </vt:vector>
</TitlesOfParts>
<Company/>
<LinksUpToDate>false</LinksUpToDate>
<SharedDoc>false</SharedDoc>
<HyperlinksChanged>false</HyperlinksChanged>
<AppVersion>14.0300</AppVersion>
</Properties>

फ़ाइल एक जर्मन फ़ाइल (Arbeitsblätter = कार्यपत्रक) है। तालिका के नाम (Tabelle3 आदि) सही क्रम में हैं। आपको बस ये टैग पढ़ने की ज़रूरत है;)

सादर


1
यह xlsx फ़ाइलों के लिए अच्छा काम करता है, लेकिन xls फ़ाइलों के लिए नहीं। वे एक ही संरचना नहीं है। क्या आप जानते हैं कि xls फ़ाइल से समान डेटा कैसे निकाला जा सकता है?
rdans

6

मैंने @kraeppy ( https://stackoverflow.com/a/19930386/2617732 ) से उत्तर में दी गई जानकारी का उपयोग करके नीचे फ़ंक्शन बनाया है । इसके लिए .net फ्रेमवर्क v4.5 का उपयोग करने की आवश्यकता होती है और इसके लिए System.IO.Compression के संदर्भ की आवश्यकता होती है। यह केवल xlsx फ़ाइलों के लिए काम करता है और पुराने xls फ़ाइलों के लिए नहीं।

    using System.IO.Compression;
    using System.Xml;
    using System.Xml.Linq;

    static IEnumerable<string> GetWorksheetNamesOrdered(string fileName)
    {
        //open the excel file
        using (FileStream data = new FileStream(fileName, FileMode.Open))
        {
            //unzip
            ZipArchive archive = new ZipArchive(data);

            //select the correct file from the archive
            ZipArchiveEntry appxmlFile = archive.Entries.SingleOrDefault(e => e.FullName == "docProps/app.xml");

            //read the xml
            XDocument xdoc = XDocument.Load(appxmlFile.Open());

            //find the titles element
            XElement titlesElement = xdoc.Descendants().Where(e => e.Name.LocalName == "TitlesOfParts").Single();

            //extract the worksheet names
            return titlesElement
                .Elements().Where(e => e.Name.LocalName == "vector").Single()
                .Elements().Where(e => e.Name.LocalName == "lpstr")
                .Select(e => e.Value);
        }
    }

2

मुझे 1_Germany, 2_UK, 3_IRELAND के रूप में शीट्स का नाम @deathApril पसंद है। मुझे सैकड़ों चादरों के लिए यह नाम बदलने के लिए आपका मुद्दा भी मिला। यदि आपको शीट नाम का नाम बदलने में कोई समस्या नहीं है, तो आप इस मैक्रो का उपयोग आपके लिए कर सकते हैं। सभी शीट नामों का नाम बदलने में सेकंड से भी कम समय लगेगा। दुर्भाग्य से ODBC, OLEDB asc द्वारा शीट नाम क्रम को वापस करता है। उसके लिए कोई प्रतिस्थापन नहीं है। आपको या तो COM का उपयोग करना होगा या अपना नाम क्रम में होना चाहिए।

Sub Macro1()
'
' Macro1 Macro
'

'
Dim i As Integer
For i = 1 To Sheets.Count
 Dim prefix As String
 prefix = i
 If Len(prefix) < 4 Then
  prefix = "000"
 ElseIf Len(prefix) < 3 Then
  prefix = "00"
 ElseIf Len(prefix) < 2 Then
  prefix = "0"
 End If
 Dim sheetName As String
 sheetName = Sheets(i).Name
 Dim names
 names = Split(sheetName, "-")
 If (UBound(names) > 0) And IsNumeric(names(0)) Then
  'do nothing
 Else
  Sheets(i).Name = prefix & i & "-" & Sheets(i).Name
 End If
Next

End Sub

अद्यतन: BIFF के बारे में @SidHoland टिप्पणी पढ़ने के बाद एक विचार फ्लैश हुआ। निम्नलिखित चरणों को कोड के माध्यम से किया जा सकता है। पता नहीं अगर तुम सच में करना चाहते हैं कि एक ही क्रम में शीट नाम पाने के लिए। मुझे पता है कि क्या आपको कोड के माध्यम से ऐसा करने के लिए मदद चाहिए।

1. Consider XLSX as a zip file. Rename *.xlsx into *.zip
2. Unzip
3. Go to unzipped folder root and open /docprops/app.xml
4. This xml contains the sheet name in the same order of what you see.
5. Parse the xml and get the sheet names

अद्यतन: एक और समाधान - NPOI यहाँ उपयोगी हो सकता है http://npoi.codeplex.com/

 FileStream file = new FileStream(@"yourexcelfilename", FileMode.Open, FileAccess.Read);

      HSSFWorkbook  hssfworkbook = new HSSFWorkbook(file);
        for (int i = 0; i < hssfworkbook.NumberOfSheets; i++)
        {
            Console.WriteLine(hssfworkbook.GetSheetName(i));
        }
        file.Close();

यह समाधान xls के लिए काम करता है। मैंने xlsx की कोशिश नहीं की।

धन्यवाद,

Esen


1
आपको शीट का नाम बदलने या केवल COM का उपयोग करने की आवश्यकता नहीं है , क्योंकि मेरा उत्तर दर्शाता है कि आप DAO का उपयोग कर सकते हैं। मुझे लगता है कि BIFF पढ़कर उन्हें पुनर्प्राप्त करने का एक तरीका भी हो सकता है , लेकिन मैं अभी भी उसकी जांच कर रहा हूं।
सिड हॉलैंड

1
@SidHolland: DAO एक COM घटक है। सर्वर 2008 में COM घटक का उपयोग करना एक समस्या है इसलिए स्टीव ADO.NET के साथ चला गया
Esen

मेरे दिमाग ने यह नहीं कहा कि DAO एक COM घटक है, इसका उपयोग करने के लिए इसे COM संदर्भ के रूप में जोड़ने के बावजूद। सुधारों के लिए धन्यवाद। आपका जोड़ (ज़िप का नाम बदलना और XML पढ़ना) प्रतिभाशाली है। मुझे पता नहीं था कि काम करेगा। यह है, अब तक, केवल विधि जो COM का उपयोग किए बिना शीट दिखाएगा। +1!
सिड हॉलैंड

1

इसने मेरे लिए काम किया। यहाँ से चोरी: आपको एक्सेल वर्कबुक के पहले पेज का नाम कैसे मिलता है?

object opt = System.Reflection.Missing.Value;
Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
Excel.Workbook workbook = app.Workbooks.Open(WorkBookToOpen,
                                         opt, opt, opt, opt, opt, opt, opt,
                                         opt, opt, opt, opt, opt, opt, opt);
Excel.Worksheet worksheet = workbook.Worksheets[1] as Microsoft.Office.Interop.Excel.Worksheet;
string firstSheetName = worksheet.Name;

2
नमस्ते। खुशी है कि आपको वर्किंग कोड मिल गया है, लेकिन वह इंटरॉप कक्षाओं का उपयोग करता है, और वे सर्वर पर मज़बूती से काम नहीं करते हैं; आप Windows Server 2008 पर इस कोड को नहीं चला सकते हैं। इसलिए आप इसे वेब ऐप या सर्वर-साइड कोड में उपयोग नहीं कर सकते। इसलिए मैं इंटरोप के बजाय ऑलेडब के लिए जा रहा था।
कूपर में स्टीव कूपर

1

इसे इस्तेमाल करे। यहाँ कोड नाम पाने के लिए कोड है।

private Dictionary<int, string> GetExcelSheetNames(string fileName)
{
    Excel.Application _excel = null;
    Excel.Workbook _workBook = null;
    Dictionary<int, string> excelSheets = new Dictionary<int, string>();
    try
    {
        object missing = Type.Missing;
        object readOnly = true;
        Excel.XlFileFormat.xlWorkbookNormal
        _excel = new Excel.ApplicationClass();
        _excel.Visible = false;
        _workBook = _excel.Workbooks.Open(fileName, 0, readOnly, 5, missing,
            missing, true, Excel.XlPlatform.xlWindows, "\\t", false, false, 0, true, true, missing);
        if (_workBook != null)
        {
            int index = 0;
            foreach (Excel.Worksheet sheet in _workBook.Sheets)
            {
                // Can get sheet names in order they are in workbook
                excelSheets.Add(++index, sheet.Name);
            }
        }
    }
    catch (Exception e)
    {
        return null;
    }
    finally
    {
        if (_excel != null)
        {

            if (_workBook != null)
                _workBook.Close(false, Type.Missing, Type.Missing);
            _excel.Application.Quit();
        }
        _excel = null;
        _workBook = null;
    }
    return excelSheets;
}

Ist nicht mal compilierfähig! (ज़ील Excel.XlFileFormat.xlWorkbookNormal)
माइकल हटर

0

MSDN के अनुसार, एक्सेल के अंदर स्प्रेडशीट के एक मामले में यह काम नहीं कर सकता क्योंकि एक्सेल फाइलें असली डेटाबेस नहीं हैं। तो आप कार्यपुस्तिका में उनके विज़ुअलाइज़ेशन के क्रम में शीट नाम प्राप्त करने में सक्षम नहीं होंगे।

इंटरॉप का उपयोग करके उनकी दृश्य उपस्थिति के अनुसार शीट नाम प्राप्त करने के लिए कोड:

Microsoft Excel 12.0 ऑब्जेक्ट लाइब्रेरी का संदर्भ जोड़ें।

निम्नलिखित कोड शीट को कार्यपुस्तिका में संग्रहीत वास्तविक क्रम में नाम देगा, न कि क्रमबद्ध नाम।

नमूना कोड:

using Microsoft.Office.Interop.Excel;

string filename = "C:\\romil.xlsx";

object missing = System.Reflection.Missing.Value;

Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();

Microsoft.Office.Interop.Excel.Workbook wb =excel.Workbooks.Open(filename,  missing,  missing,  missing,  missing,missing,  missing,  missing,  missing,  missing,  missing,  missing,  missing,  missing,  missing);

ArrayList sheetname = new ArrayList();

foreach (Microsoft.Office.Interop.Excel.Worksheet  sheet in wb.Sheets)
{
    sheetname.Add(sheet.Name);
}

0

मुझे कोई भी दस्तावेज नहीं दिखाई देता है जो कहता है कि app.xml में ऑर्डर शीट्स का ऑर्डर है। यह पूरी तरह से है, लेकिन OOXML विनिर्देश के अनुसार नहीं है।

दूसरी ओर वर्कबुक.एक्सएमएल फ़ाइल में शीटआईड विशेषता शामिल है, जो अनुक्रम का निर्धारण करती है - 1 से लेकर शीट की संख्या तक। यह OOXML विनिर्देश के अनुसार है। वर्कबुक.एक्सएमएल को उस स्थान के रूप में वर्णित किया जाता है जहां शीट्स का क्रम रखा जाता है।

तो कार्यपुस्तिका को पढ़ने के बाद। Xml को एक्सएलएसएक्स के रूप में निकाले जाने के बाद मेरी सिफारिश होगी। App.xml नहीं। DocProps / app.xml के बजाय, xl / workbook.xml का उपयोग करें और तत्व को देखें, जैसा कि नीचे दिखाया गया है -

`

<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  <fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="9303" /> 
  <workbookPr defaultThemeVersion="124226" /> 
- <bookViews>
  <workbookView xWindow="120" yWindow="135" windowWidth="19035" windowHeight="8445" /> 
  </bookViews>
- <sheets>
  <sheet name="By song" sheetId="1" r:id="rId1" /> 
  <sheet name="By actors" sheetId="2" r:id="rId2" /> 
  <sheet name="By pit" sheetId="3" r:id="rId3" /> 
  </sheets>
- <definedNames>
  <definedName name="_xlnm._FilterDatabase" localSheetId="0" hidden="1">'By song'!$A$1:$O$59</definedName> 
  </definedNames>
  <calcPr calcId="145621" /> 
  </workbook>

`

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.