使用Excel OleDb获取工作表名称IN SHEET ORDER

Ste*_*per 101 c# oledb excel server-side

我正在使用OleDb从包含许多工作表的excel工作簿中读取.

我需要阅读工作表名称,但我需要按照电子表格中定义的顺序进行操作; 所以如果我有一个看起来像这样的文件;

|_____|_____|____|____|____|____|____|____|____|
|_____|_____|____|____|____|____|____|____|____|
|_____|_____|____|____|____|____|____|____|____|
\__GERMANY__/\__UK__/\__IRELAND__/
Run Code Online (Sandbox Code Playgroud)

然后我需要得到字典

1="GERMANY", 
2="UK", 
3="IRELAND"
Run Code Online (Sandbox Code Playgroud)

我尝试过使用OleDbConnection.GetOleDbSchemaTable(),这给了我名单,但按字母顺序对它们进行排序.字母排序意味着我不知道特定名称对应于哪个表格编号.所以我得到了;

GERMANY, IRELAND, UK
Run Code Online (Sandbox Code Playgroud)

这改变了UK和的顺序IRELAND.

我需要对它进行排序的原因是我必须让用户按名称或索引选择一系列数据; 他们可以要求"从德国到爱尔兰的所有数据"或"从表1到表3的数据".

任何想法将不胜感激.

如果我可以使用办公室互操作课程,这将是直截了当的.不幸的是,我不能,因为互操作类在非交互式环境(如Windows服务和ASP.NET站点)中不能可靠地工作,所以我需要使用OLEDB.

Jam*_*mes 75

你能不能只是将表格从0循环到名字-1的计数?那样你应该按照正确的顺序得到它们.

编辑

我通过评论注意到,使用Interop类检索工作表名称存在很多问题.因此,这是一个使用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();
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

从CodeProject上的文章中提取.

  • 不回答海报问题(他希望它在Excel中出现的顺序) (23认同)
  • 嗨,詹姆斯.这几乎是我原来的问题 - 当GetOleDbSchemaTable()方法获取名称时,行号与工作簿表号不对应.因此,如果它在字母表中排在第一位,那么第4页将是第0行. (13认同)
  • @Samuel我不认为它直接解决了OP的问题,但它似乎帮助了很多其他类似问题的人. (6认同)

小智 23

由于上述代码不包括提取Excel 2007工作表名称列表的过程,因此以下代码也适用于Excel(97-2003)和Excel 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;
}
Run Code Online (Sandbox Code Playgroud)

上面的函数返回两个excel类型(97,2003,2007)的特定excel文件的工作表列表.

  • 此代码不会按照它们在Excel中显示的顺序返回工作表 (11认同)

小智 17

在实际的MSDN文档中找不到这个,但论坛中的主持人说

我担心OLEDB不像Excel中那样保留工作表顺序

工作表顺序中的Excel工作表名称

似乎这是一个普遍的要求,将有一个体面的解决方法.


小智 8

其他方式:

xls(x)文件只是存储在*.zip容器中的*.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>
Run Code Online (Sandbox Code Playgroud)

该文件是德语文件(Arbeitsblätter= worksheets).表名(Tabelle3等)的顺序正确.你只需要阅读这些标签;)

问候


rda*_*ans 6

我使用@kraeppy(/sf/answers/1395127051/)答案中提供的信息创建了以下函数.这需要使用.net framework 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);
        }
    }
Run Code Online (Sandbox Code Playgroud)


Moh*_*MFa 5

这是简短,快速,安全和可用的......

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;
}
Run Code Online (Sandbox Code Playgroud)