SSIS:根据网络查询结果以编程方式创建新的 Excel 文件 - 如何保存网络查询 table 名称?

SSIS: Programmatically create new Excel file based on web query results - how do I save the web query table names?

我想做什么?

我有一个 URL 的列表,我想使用 Excel 的 Web 查询功能来抓取它们。我试图完全自动化这个过程,所以我正在开发一个 SSIS 包,它为每个 URL 调用一个脚本任务。脚本任务使用工作表创建一个新的 Excel 工作簿,激活工作表,添加 QueryTable 连接,刷新 QueryTable 以获取数据,使用 XlWebSelectionType.xlAllTables。然后保存工作簿并关闭工作簿和 Excel 应用程序。

我使用了哪些技术?

有什么问题?

虽然脚本任务确实保存了网页上 table 的所有数据,但它会将它们全部放入单个工作表中,并且不保存 table 名称。因此,虽然我的数据在工作表中正确分组,但我无法知道哪个 "group" 数据对应于哪个 table.

我想怎么办?

理想情况下,我希望将每个 QueryTable table 保存到其自己的工作表中,并将 table 名称设置为工作表名称。除此之外,我需要一种方法来保存 table 名称和相应的数据。在这种情况下,最好将其添加为 QueryTable 中的新列。

到目前为止我有什么?

这是脚本的主要部分:

Public Sub Main()
    Dim URL As String = Dts.Variables("User::URL").Value.ToString()
    Dim FileName As String = Dts.Variables("User::FileName").Value.ToString()
    Dim xlNone As XlWebFormatting = XlWebFormatting.xlWebFormattingNone
    Dim Format As XlFileFormat = XlFileFormat.xlCSVWindows
    Dim ScrapeStatus As Integer = 1

    Dim excel As New Microsoft.Office.Interop.Excel.ApplicationClass

    With excel
        .SheetsInNewWorkbook = 1
        .DisplayAlerts = False
    End With

    Dim wb As Microsoft.Office.Interop.Excel.Workbook = excel.Workbooks.Add()

    With wb
        .Activate()
        .Worksheets.Select(1)
    End With

    Try

        Dim rnStart As Range = wb.ActiveSheet.Range("A1:Z100")
        Dim qtQtrResults As QueryTable = wb.ActiveSheet.QueryTables.Add(Connection:="URL;" + URL, Destination:=rnStart)

        With qtQtrResults
            .BackgroundQuery = False
            .WebFormatting = xlNone
            .WebSelectionType = XlWebSelectionType.xlAllTables
            .Refresh()
        End With

        excel.CalculateUntilAsyncQueriesDone()
        wb.SaveAs(FileName)

        wb.Close()
        excel.Quit()
        System.Runtime.InteropServices.Marshal.ReleaseComObject(excel)
        GC.Collect()
        GC.WaitForPendingFinalizers()
        Dts.TaskResult = ScriptResults.Success

    Catch ex As Exception

        Dts.Variables("User::Error").Value = ex.Message.ToString()
        wb.Saved = True
        wb.Close()
        excel.Quit()
        System.Runtime.InteropServices.Marshal.ReleaseComObject(excel)
        GC.Collect()
        GC.WaitForPendingFinalizers()
        Dts.TaskResult = ScriptResults.Failure

    End Try

End Sub

我得到了什么结果?

对于 URL http://athletics.chabotcollege.edu/information/directory/home#directory,如果我在 Excel 中使用 Web 查询功能,我会从 select 获得以下信息: 所有 table 个名字都显示出来

但是,当我通过脚本任务拉取所有 table 时,我最终得到一个看起来类似于此的工作表:

其他信息

我还应注意,虽然大多数网页的结构相似,但并非所有网页都相同。所以我不能假设每个页面都具有相同的 table 名称,或者以相同的方式构建 table。我的解决方案需要动态且灵活。

我认为您无法通过网络查询获得 table 名称,如果您检查网页源代码,您会注意到 table 没有名称属性。 Excel 在界面中显示的名称与 table 无关,它们是该部分的标题(即 Table 的 parent 标签)所以他们不被视为 Tablename.

此外,检查 QueryTable documentation 后,没有选项可以检索 table 名称或 table 容器的标题,因此 Excel 没有必要使用Web 查询在界面 中显示 Tables 和 headers(如屏幕截图所示)

我认为有一种方法可以将数据拆分到工作表(没有 table 名称)是:

  1. 您必须使用正则表达式从网页 <table></table>
  2. 中检索 Table 计数
  3. 您必须为每个 Table
  4. 创建一个工作表
  5. 您必须为每个 Table
  6. 创建一个查询Table
  7. 在每个查询中Table您必须设置目标工作表范围和以下属性:

    .WebSelectionType = XlWebSelectionType.xlSpecifiedTables
    .WebTables = i 'Where i is the index of Table
    

也许您应该使用 HTML 解析器和正则表达式来收集 Table 元数据

通过将 .WebSelectionType = XlWebSelectionType.xlAllTables 更改为 .WebSelectionType = XlWebSelectionType.xlEntirePage,我能够捕获 table 的 "names"。它们实际上是每个 table 的 parent <section> 标签内的 aria-title 值。它很丑陋,但确实 return 我正在寻找的字符串。

我最终将 xlAllTablesxlEntirePage QueryTables 都保存为文本文件。然后我将 xlAllTables 文件拆分为每个 table 的单独块,然后在 xlEntirePage 文本文件中搜索代表 table 的 "string",然后我复制具有标题的前一行。然后我将 table 文本保存为一个新文件,并将复制的标题作为文件名。它非常 hacky,但它完成了我需要它做的事情。