SSIS: Программное создание нового файла Excel на основе результатов веб-запроса — как сохранить имена таблиц веб-запросов?

Что я пытаюсь сделать?

У меня есть список URL-адресов, которые я хочу очистить с помощью функции веб-запросов Excel. Я пытаюсь полностью автоматизировать процесс, поэтому я разрабатываю пакет SSIS, который вызывает задачу сценария для каждого URL-адреса. Задача сценария создает новую рабочую книгу Excel с рабочим листом, активирует рабочий лист, добавляет соединение QueryTable, обновляет QueryTable для получения данных с помощью XlWebSelectionType.xlAllTables. Затем он сохраняет книгу и закрывает книгу и приложение Excel.

Какие технологии я использую?

  • VS 2015 (предприятие)
  • SQL Server 2016
  • Библиотека объектов Microsoft Excel 16.0
  • Локальная установка Excel из Office 365 профессиональный плюс

В чем проблема?

Хотя задача сценария сохраняет все данные из таблиц на веб-странице, она помещает их все на один рабочий лист и не сохраняет имена таблиц. Поэтому, хотя мои данные правильно сгруппированы на листе, я не могу узнать, какая «группа» данных соответствует какой таблице.

Что мне с этим делать?

В идеале я хотел бы, чтобы каждая таблица QueryTable сохранялась на своем собственном рабочем листе с именем таблицы, установленным в качестве имени рабочего листа. За исключением этого, мне нужен способ сохранить имя таблицы с соответствующими данными. В этом сценарии лучше всего добавить его в качестве нового столбца в 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, я получаю следующее для выбора: введите здесь описание изображения Отображаются все имена таблиц

Однако, когда я извлекаю все таблицы с помощью задачи сценария, я получаю рабочий лист, который выглядит примерно так: введите здесь описание изображения

Другая информация

Я также должен отметить, что хотя большинство веб-страниц имеют схожую структуру, не все они одинаковы. Поэтому я не могу предположить, что каждая страница будет иметь одинаковые имена таблиц или структурировать таблицы одинаково. Мое решение должно быть динамичным и гибким.


person digital.aaron    schedule 08.01.2019    source источник


Ответы (2)


Изменив .WebSelectionType = XlWebSelectionType.xlAllTables на .WebSelectionType = XlWebSelectionType.xlEntirePage, я могу зафиксировать «имена» таблиц. На самом деле это значения aria-title внутри родительского тега <section> каждой таблицы. Это уродливо, но возвращает строки, которые я ищу.

В итоге я сохранил xlAllTables и xlEntirePage QueryTable в виде текстовых файлов. Затем я разбиваю файл xlAllTables на отдельные фрагменты для каждой таблицы, а затем ищу в текстовом файле xlEntirePage «строку», представляющую таблицу, и копирую предыдущую строку с заголовком. Затем я сохраняю текст таблицы как новый файл с скопированным заголовком в качестве имени файла. Это очень хаки, но он сделал то, что мне было нужно.

person digital.aaron    schedule 09.01.2019

Я не думаю, что вы можете получить имена таблиц с помощью веб-запросов, если вы проверите источник веб-страницы, вы заметите, что таблицы не имеют атрибута имени. Имена, которые Excel показывает в интерфейсе, не связаны с таблицами, они являются заголовком раздела (который является родительским тегом таблицы), поэтому они не считаются именем таблицы.

Кроме того, после проверки документации QueryTable нет параметр для получения имен таблиц или заголовка контейнера таблицы, поэтому Excel не должен использовать веб-запросы для отображения таблиц и заголовков в интерфейсе (как показано на снимках экрана)

Я думаю, что есть один способ разделить данные на рабочие листы (без имен таблиц):

  1. Вы должны использовать регулярные выражения для получения количества таблиц с веб-страницы <table></table>.
  2. Вы должны создать рабочий лист для каждой таблицы
  3. Вы должны создать QueryTable для каждой таблицы
  4. В каждой таблице QueryTable вы должны установить диапазон рабочих листов назначения и следующие свойства:

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

Возможно, вам следует использовать анализатор HTML и регулярное выражение для сбора метаданных таблицы

person Hadi    schedule 08.01.2019
comment
Копнув немного глубже, я могу подтвердить, что то, что я вижу в Excel, на самом деле управляется Power Query, а не просто веб-запросом. Сейчас я смотрю, могу ли я использовать Power Query в своей задаче сценария. - person digital.aaron; 09.01.2019
comment
@digital.aaron Сегодня вечером я тоже буду работать таким образом. Надеюсь, что вопрос решится - person Hadi; 09.01.2019
comment
Я нашел супер-хакерское решение, которое пока работает, но я им не доволен. Я думаю, что нужно выяснить, как использовать Power Query в сценарии. - person digital.aaron; 09.01.2019
comment
@digital.aaron digital.aaron Я безуспешно пытался найти решение, если вам нужно получить их с помощью регулярного выражения, возможно, я смогу помочь. И, пожалуйста, сообщите мне, если вы найдете возможное решение. Удачи - person Hadi; 10.01.2019
comment
Я даже хуже в RegEx, чем в VB, поэтому любая помощь, которую вы могли бы оказать, была бы очень полезной. - person digital.aaron; 10.01.2019
comment
Класс, который я ищу, - это класс WorkbookQueries. Из всего, что я читал, это класс только для VBA. Предположительно, он стал родным для Excel с 2016 года, но его нет в библиотеке Excel 16, на которую я ссылаюсь в своей задаче сценария. Теперь я углубляюсь в кроличью нору, исследуя, могу ли я создать модуль в VBA и добавить его в свой объект Excel. support.microsoft.com/en-us/help/219905/ - person digital.aaron; 10.01.2019