Как ссылаться на таблицы в Excel с помощью VBA?

Возможно ли в Excel VBA ссылаться на именованную таблицу?

Гипотетически это может быть...

Sheets("Sheet1").Table("A_Table").Select

Я видел некоторые упоминания о том, что таблицы являются объектом списка, но я не уверен, что это одно и то же.


person 1212__Hello    schedule 03.08.2013    source источник


Ответы (6)


Преобразование диапазона в таблицу, как описано в этом ответе:

Sub CreateTable()
    ActiveSheet.ListObjects.Add(xlSrcRange, Range("$B$1:$D$16"), , xlYes).Name = _
        "Table1"
        'No go in 2003
    ActiveSheet.ListObjects("Table1").TableStyle = "TableStyleLight2"
End Sub
person Bgvv1983    schedule 03.08.2013

ОП спросил, можно ли сослаться на таблицу, а не как добавить таблицу. Таким образом, рабочий эквивалент

Sheets("Sheet1").Table("A_Table").Select

будет это утверждение:

Sheets("Sheet1").ListObjects("A_Table").Range.Select

или для выбора частей (вроде только данные в таблице):

Dim LO As ListObject
Set LO = Sheets("Sheet1").ListObjects("A_Table")
LO.HeaderRowRange.Select        ' Select just header row
LO.DataBodyRange.Select         ' Select just data cells
LO.TotalsRowRange.Select        ' Select just totals row

Для частей вы можете проверить наличие строк заголовков и итогов перед их выбором.

А если серьезно, то это единственный вопрос по ссылкам на таблицы в VBA в SO? Таблицы в Excel имеют такой смысл, но с ними так сложно работать в VBA!

person GlennFromIowa    schedule 20.06.2014
comment
как мы можем использовать таблицы в запросе VBA, как мы это делали для листов, например, выберите * из [лист1 $], где col1 = 'x' - person Vikky; 17.06.2016
comment
@Vikky Я не знаком с запросом VBA, на который вы ссылаетесь, но он меня заинтриговал. У вас есть ссылка на документацию (MSDN или иную) для этого типа запроса? Используется ли это при ссылке на Excel из другого приложения или инструмента через OLE или ODBC? Если да, то какое приложение? - person GlennFromIowa; 24.06.2016
comment
Во-первых, я хотел бы поблагодарить вас за ответ. У меня есть решение для моего вопроса, таблицы в листе Excel можно использовать с помощью oledb. это ссылка на статью, которая помогает мне chandoo. org/wp/2012/04/02/использование-excel-как-вашей-базы-данных - person Vikky; 29.06.2016
comment
Таблицы в Excel имеют такой смысл, но с ними так сложно работать в VBA! Расскажите мне об этом! Почему их нельзя просто запрашивать, как таблицу базы данных? - person Charles Wood; 11.11.2016
comment
@Vikky, эта ссылка о том, как использовать Excel для OLE DB, действительно была интересной, но обратите внимание, что она не связана с концепцией таблицы, обсуждаемой здесь, поэтому неправильно говорить, что таблицы в листе Excel можно использовать с помощью oledb. (Из вашей ссылки: Прежде чем мы начнем: ... 2. Это не имеет ничего общего со встроенной функцией таблицы (2007 г. и выше)/списка (2003 г. и ранее) в Excel.) - person Egalth; 05.09.2017

«Таблица» в Excel действительно известна как ListObject.

«Правильный» способ сослаться на таблицу - получить ее ListObject из ее рабочего листа, то есть SheetObject.ListObjects(ListObjectName).

Если вы хотите сослаться на таблицу, не используя лист, вы можете использовать хак Application.Range(ListObjectName).ListObject.

ПРИМЕЧАНИЕ. Этот прием основан на том факте, что Excel всегда создает именованный диапазон для DataBodyRange таблицы с тем же именем, что и таблица. Однако это имя диапазона можно изменить... хотя это не то, что вы хотели бы делать, поскольку имя будет сброшено, если вы отредактируете имя таблицы! Также вы можете получить именованный диапазон без связанного ListObject.

Учитывая не очень полезное сообщение об ошибке 1004 Excel, когда вы неправильно называете имя, вы можете создать оболочку...

Public Function GetListObject(ByVal ListObjectName As String, Optional ParentWorksheet As Worksheet = Nothing) As Excel.ListObject
On Error Resume Next

    If (Not ParentWorksheet Is Nothing) Then
        Set GetListObject = ParentWorksheet.ListObjects(ListObjectName)
    Else
        Set GetListObject = Application.Range(ListObjectName).ListObject
    End If

On Error GoTo 0 'Or your error handler

    If (Not GetListObject Is Nothing) Then
        'Success
    ElseIf (Not ParentWorksheet Is Nothing) Then
        Call Err.Raise(1004, ThisWorkBook.Name, "ListObject '" & ListObjectName & "' not found on sheet '" & ParentWorksheet.Name & "'!")
    Else
        Call Err.Raise(1004, ThisWorkBook.Name, "ListObject '" & ListObjectName & "' not found!")
    End If

End Function

Также некоторая полезная информация о ListObject здесь< /а>.

person AndrewD    schedule 03.02.2015
comment
Кстати, не ожидайте найти имена диапазонов таблиц DataBodyRange в Application.Names! Но к ним определенно можно получить доступ с помощью Application.Range(...). - person AndrewD; 03.02.2015
comment
Этот способ работает только в том случае, если рабочая книга, содержащая нужную таблицу, в данный момент активна. Если вы каким-то образом запустите код с другим активным файлом, этот метод не сработает. Тот же подход, что и для объекта ActiveSheet. - person tm-; 02.05.2016
comment
Не большой поклонник предложенного вами VBA, но внешняя ссылка, которую вы бросили, была хорошим кратким изложением того, как ссылаться на таблицы и части таблиц, спасибо. - person Pork; 16.08.2016
comment
Нравится хак. Потому что может показаться, что опасность изменения имени листа вполне реальна. Все еще интересно, как это справится с этим, если у пользователя будет открыто старое сохранение файла, а также текущее... если это приведет к ошибке из-за повторяющихся имен. Но комментарий tm заставляет меня думать, что он может работать в любом случае, если вы запускаете его из нужной вам книги? - person JeopardyTempest; 26.08.2018
comment
(Если вы не уверены... попробуйте. Похоже, что это действительно удалось, несмотря на наличие повторяющихся имен в другом открытом файле.) - person JeopardyTempest; 26.08.2018
comment
Ваше недовольное предостережение о том, что диапазон каким-то образом переименовывается из имени таблицы в сторону, это великолепно для использования не только в таблицах, но и во всех именованных диапазонах... кажется, что он может обрабатывать пользователей, непреднамеренно переименовывающих листы... или редизайн, где различные ячейки имен переназначаются на разные листы... когда функция взаимодействует с вещами на нескольких листах [или даже если все они изначально находятся в ActiveSheet, но не позже], без необходимости редактирования VB. Просто кажется, что гибкость, которая (возможно, из-за моего отсутствия опыта работы с VBA, я не понимаю, как иначе обрабатывать такие изменения?), кажется жизненно важной. - person JeopardyTempest; 26.08.2018

Кроме того, удобно определять переменные, ссылающиеся на объекты. Например,

Sub CreateTable()
    Dim lo as ListObject
    Set lo = ActiveSheet.ListObjects.Add(xlSrcRange, Range("$B$1:$D$16"), , xlYes)
    lo.Name = "Table1"
    lo.TableStyle = "TableStyleLight2"
    ...
End Sub

Вы, вероятно, найдете это выгодным сразу.

person sancho.s ReinstateMonicaCellio    schedule 20.11.2013

В дополнение к вышесказанному вы можете сделать это (где «YourListObjectName» — это имя вашей таблицы):

Dim LO As ListObject
Set LO = ActiveSheet.ListObjects("YourListObjectName")

Но я думаю, что это работает, только если вы хотите сослаться на объект списка, который находится на активном листе.

Я нашел ваш вопрос, потому что хотел сослаться на объект списка (таблицу) на одном листе, на который ссылается сводная таблица на другом листе. Поскольку объекты списка являются частью коллекции Worksheets, вам необходимо знать имя рабочего листа, на котором находится объект списка, чтобы ссылаться на него. Таким образом, чтобы получить имя рабочего листа, на котором находится объект списка, я получил имя объекта исходного списка сводной таблицы (опять же, таблицы) и перебрал рабочие листы и их объекты списка, пока не нашел рабочий лист, содержащий список объект, который я искал.

Public Sub GetListObjectWorksheet()
' Get the name of the worksheet that contains the data
' that is the pivot table's source data.

    Dim WB As Workbook
    Set WB = ActiveWorkbook

    ' Create a PivotTable object and set it to be
    ' the pivot table in the active cell:
    Dim PT As PivotTable
    Set PT = ActiveCell.PivotTable

    Dim LO As ListObject
    Dim LOWS As Worksheet

    ' Loop through the worksheets and each worksheet's list objects
    ' to find the name of the worksheet that contains the list object
    ' that the pivot table uses as its source data:
    Dim WS As Worksheet
    For Each WS In WB.Worksheets
        ' Loop through the ListObjects in each workshet:
        For Each LO In WS.ListObjects
            ' If the ListObject's name is the name of the pivot table's soure data,
            ' set the LOWS to be the worksheet that contains the list object:
            If LO.Name = PT.SourceData Then
                Set LOWS = WB.Worksheets(LO.Parent.Name)
            End If
        Next LO
    Next WS

    Debug.Print LOWS.Name

End Sub

Может кто знает более прямой способ.

person Hugh Seagraves    schedule 23.01.2014
comment
Учитывая то, что @AndrewD написал о потенциальных недостатках метода application.range, это кажется единственным надежным методом получения ListObject таблицы, используя только имя таблицы. - person ChrisB; 04.08.2017
comment
Помимо создания сводной таблицы в вашем коде, что, вероятно, не входило в ваши намерения, я думаю, что ваш путь настолько прямолинеен, насколько это возможно. Я попытался добавить общую функцию, чтобы получить ListObject с именем PivotTable к вашему ответу, но, видимо, это не кошерно. Поэтому я решил создать новый вопрос и укажите этот код в качестве ответа. Но я проголосовал за ваш ответ здесь, потому что предсказуемая необходимость иметь возможность получить ListObject из имени PivotTable. - person GlennFromIowa; 08.09.2017

Добавление третьего варианта. «Сокращенная» версия второго варианта @AndrewD.

  1. ЛистОбъект.СписокОбъектов("ИмяТаблицы")
  2. Application.Range("ИмяТаблицы").ListObject
  3. [ИмяТаблицы].ListObject

Да, в скобках нет кавычек.

person GollyJer    schedule 11.01.2020