【发布时间】:2012-05-18 14:24:25
【问题描述】:
我在使用 OLEDB 从 Excel 电子表格中获取工作表名称时遇到问题。问题是当我使用 GetOleDbSchemaTable 时,生成的 DataTable 不仅仅是实际的工作表名称;它有额外的“表格”行,我只能假设 Excel 在内部使用这些行。
例如,如果我有一个名为 myWorksheet 的工作表,下面的代码可能会以包含 myWorksheet$、myWorksheet$PrintTable 和 myWorksheet$_ 的列表结束。只有第一个 myWorksheet$ 记录用于实际工作表。其他的只是我不需要的垃圾。当您在元数据中查看它们时,它们看起来就像常规表,即使是 TABLE 类型。
目前我只是手动过滤掉名称中带有“$_”或“$Print”的任何内容,但谁知道其他 Excel 功能可能会使这些额外记录以不同的格式出现。
有谁知道仅获取实际工作表名称而不是这些不是工作表的内部表的最佳方法?元数据中有什么东西可以区分它们吗?
private ArrayList getXlsWorksheetNames(OleDb.OleDbConnection conn)
{
ArrayList wsList = new ArrayList();
DataTable schemaTable;
try
{
conn.Open();
schemaTable = conn.GetOleDbSchemaTable(OleDb.OleDbSchemaGuid.Tables, null);
foreach (DataRow row in schemaTable.Rows)
{
//form.appendToResultsTxt("Adding worksheet to list: " + Environment.NewLine +
// "Name = " + row.Field<string>("TABLE_NAME") + "," + Environment.NewLine +
// "Type = " + row.Field<string>("TABLE_TYPE") + "," + Environment.NewLine + Environment.NewLine);
wsList.Add(row.Field<string>("TABLE_NAME"));
}
conn.Close();
}
catch (Exception ex)
{
if (this.mode == Cps2TxtUtilModes.GUI_MODE)
{
this.form.appendToResultsTxt(ex.ToString());
}
throw;
}
return wsList;
}
我通读了此链接上的文章,但他们似乎没有做任何与我不同的事情,而且我没有看到任何过滤掉额外的非工作表表格,所以微软似乎没有提供了正确的答案。
http://support.microsoft.com/kb/318452
我还查看了很多 StackOverflow,比如下面链接中的线程,它很有帮助,但并没有解决这个问题。
Using Excel OleDb to get sheet names IN SHEET ORDER
在有人问之前,我还想说,我无法真正控制电子表格中使用的功能,所以我不能只告诉他们“不要打开过滤”或“不要'不使用打印表"。
非常感谢任何想法。谢谢!
【问题讨论】:
-
只过滤掉任何不带“$”的东西。我已经使用了一段时间,它从未失败过,即使有数据透视表、过滤列表等。
-
谢谢;我会去做。就像我在下面的评论中所说的那样,这不太理想,因为它依赖于实现细节,但如果这是我必须要做的,那就这样吧。
-
我对您在上面链接的问题的回答显示了如何使用 DAO 来做到这一点,但如果您不想使用 COM,那么这不是一个选择。但是,Esen 对答案的附录显示了另一种方法,即将 .xlsx 重命名为 .zip、打开 zip 文件内容并读取其中的一个 xml 文件以获取工作表名称。我还没有测试过隐藏的工作表是否出现在那里,它只适用于 2007 (.xlsx) 文件,但它可能值得一试。
-
好消息 Sid,但不幸的是我必须支持 Excel 2003,而且我绝对不想使用 COM / interop。很高兴知道 XLSX 文件可以重命名为 zip 并打开以获取一些元数据宝石。希望小费对其他人有所帮助;它可能会在未来的某个时候对我有所帮助,但对这个项目没有帮助。
-
仅供参考,供所有可能查看此内容以供将来参考的人使用。如果工作表的名称中有空格,则元数据中的表名将用单引号括起来,这意味着 $ 不会是表名中的最后一个字符,即使它是有效的工作表。因此,仅查找以 $ 作为最后一个字符的所有内容是不够的。您必须首先删除任何周围的单个 qoutes,然后评估 $ 是否是最后一个字符。这至少可以说是蹩脚的。为什么 Microsoft 不在元数据中包含表示用户工作表的内容?