【问题标题】:How to programmatically wrap a QueryTable in a ListObject?如何以编程方式将 QueryTable 包装在 ListObject 中?
【发布时间】:2017-09-21 15:16:36
【问题描述】:

过去,Excel 中的外部数据查询用QueryTables 表示。
ListObjects 在某些时候出现,但它们尚未与QueryTables 兼容,无法包含它们。

在 Office 2007 中,它们不仅兼容,而且成为默认设置。从那时起,创建外部查询就意味着创建一个ListObject,而QueryTable 被简化为它的内部组件。

“独立”QueryTables,未包装在 ListObject 中,无法再使用接口创建,但可以使用代码创建,并且在新旧文件格式中都得到完美支持。

然后 Excel 2016 出现并引入了一个错误,在“独立”QueryTable 的情况下,在某些情况下会永久损坏工作簿。将 QueryTables 从错误中保存的唯一方法是将它们包装在 ListObject 中。


所以我有 10k+ 个旧版 Excel 文档,其中现有的 QueryTables 需要用 ListObjects 包装。重要的是,大多数查询表的右侧都有filled down automatically 的公式。

使用 Excel 界面,将查询包装在列表中很简单(在查询结果中激活一个单元格,Insert - Table - Ok) 并按预期工作,留下一个功能齐全的列表,从查询中获取其数据。

将此操作记录为宏产生:

ActiveSheet.ListObjects.Add(xlSrcRange, Range("$B$5:$D$9"), , xlYes).Name = _
    "Table_Query_from_MS_Access"

但是,不加任何修改地执行这段代码会产生一个科学怪人查询表:它在外部看起来像一个列表对象,但它不起作用,无法刷新,无法编辑,显示旧式属性对话框,并且列表对象报告它是一个xlSrcRange,而不是接口创建的列表报告的xlSrcQuery

像电子一样,它会干扰自身(列表对象部分与查询表部分重叠并因此拒绝刷新,即使它们应该是相同的 - 回想一下右边有公式查询表,它们现在也必须是列表的一部分):

很明显,在转换表格时,界面所做的比宏记录器捕获的要多得多。

我尝试使用各种参数调用ListObjects.Add,提供Range 作为源,WorkbookConnection 作为源,QueryTable's Connection 作为源 - 只要它与现有的重叠,所有这些都不起作用查询表。

我已经研究过取消链接现有的 QueryTable 并从头开始重新创建 ListObject,但这会导致表格周围的公式出现各种问题。

以编程方式用ListObject 包装现有QueryTable 的完整、正确代码是什么,与接口的功能完全匹配?

目前在我看来,我必须通过直接操作我讨厌的 xslx 格式中的 XML 来做到这一点。

【问题讨论】:

    标签: excel office-2016 listobject vba


    【解决方案1】:

    我无法以编程方式将 QueryTable 包装在 ListObject 中,但我可以为 Microsoft 的 Excel 2016/2019 QueryTable 错误提供缓解措施,因为避免其影响似乎是您的真正目标。

    1. Closed-source 3rd-party Excel add-in by Event 1 Software - 根据我的经验,这通常可以解决问题,但我只有几份报告仍然受到影响。您需要 2.11 或更高版本。您可以使用公式检查加载的加载项的版本:=XLQT3Version()

    2. 更改报告设计以降低 Microsoft 错误的风险(来源:报告设计方面的大量工作,包括在未安装任何事件 1 产品的系统上):

    2.1 确保您的 QueryTable 的标题不是 QueryTable 的一部分。您仍然可以在表格上方放置一个手动标题。

    2.2 在 QueryTable 的第一行上方插入一个空白行(在 QueryTable 和手动表头之间。

    2.3 在新的空白行中,粘贴 QueryTable 所需的所有格式和公式。

    2.4 将新行的高度设置为“3”。这将防止标头被完全或部分复制到 QueryTable 的正文中。相反,该错误将导致将所需的格式和公式复制到 QueryTable 中,而不是破坏 oueryTable 的那些部分。重要提示:您不得隐藏行或将行高设置得太低。这样做会消除它的保护作用。

    2.5 刷新前禁用所有数据过滤器。您可以在刷新完成后重新应用它们。如果您需要自动执行此操作,请挂钩 QueryTable 的刷新之前/之后事件,或者使用删除它们的宏,开始刷新,然后恢复它们。

    2.6 分组行和小计也应在刷新和恢复之前删除。刷新后。分组列没问题。

    1. 手动文件(来源:Event 1 Software 的技术支持):

    3.1 打开一个受影响的文档,该文档在错误损坏后尚未保存。也就是说,一个没有损坏但会被 MS bug 损坏的文档。

    3.2 不允许文档连接到数据源或刷新。取消任何登录请求。

    3.3 至少等待 4 秒。

    3.4 刷新 QueryTable(根据需要登录)。

    3.5 再次刷新 QueryTable(有时是第三次。

    【讨论】:

      【解决方案2】:

      我在尝试将我的查询表 CSV 转换为表格时遇到了同样的问题。我没有找到将查询表转换为列表对象的直接方法,但由于我的信息是静态的,因此我使用了一个简单的解决方法。

      1. 创建一个临时工作表以使用查询表方法导入数据
      2. 将临时工作表中的数据复制到计划工作表中
      3. 将复制的数据隐藏到表格中,然后插入公式

      如果您的 XML 数据不是动态的并且不需要保持到外部数据的链接,那么这可能对您有用。否则这将不是一个有效的解决方法。

      【讨论】:

      • 所有查询表都是动态的(不包含 XML 数据)。如果您正在谈论手动执行此操作,那么 Insert - Table - Ok 会为您执行此操作就好了。
      • 我也很沮丧,因为无法以编程方式重现 queryTable 对象到 listObject 的转换,如原始帖子中所述。在我使用 excel 时,我导入的数据是静态报告,因此一旦我在工作表中获得数据,我就不需要维护数据链接。我不知道复制 GUI 中所做工作的直接答案。也许您可以在使用listObject 处理数据时使用两个工作表queryTable 是隐藏表。当调用触发queryTable 对象更新子的事件时,请实施上面发布的解决方法。
      猜你喜欢
      • 2022-10-15
      • 1970-01-01
      • 2017-08-01
      • 1970-01-01
      • 2018-09-13
      • 2010-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多