Домашняя страница Undo Do New Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/Копирование ячеек по условию - Мир MS Excel

Старая форма входа
  • Страница 1 из 1
  • 1
Модератор форума: китин, _Boroda_  
Копирование ячеек по условию
Jenialij Дата: Среда, 15.01.2025, 18:24 | Сообщение № 1
Группа: Пользователи
Ранг: Прохожий
Сообщений: 3
Репутация: 0 ±
Замечаний: 0% ±

2021
Здравствуйте.
С VBA только начал знакомиться, поэтому решил обратиться за помощью.

В книге два листа "Price" и "Price2". Данные в "умных" таблицах.
С помощью макроса нужно копировать данные из столбца "Примечание" ("Price2") в столбец "Примечание" ("Price") используя столбец "Артикул" как критерий.
Количество строк в обеих таблицах разное. Перед вставкой содержимое в столбце "Примечание" ("Price") очищать.
Задачу можно решить формулами, но нужно сохранить форматирование ячеек из столбца "Примечание" ("Price2").
К сообщению приложен файл: price_primer.xls (33.5 Kb)


Сообщение отредактировал Jenialij - Среда, 15.01.2025, 18:41
 
Ответить
СообщениеЗдравствуйте.
С VBA только начал знакомиться, поэтому решил обратиться за помощью.

В книге два листа "Price" и "Price2". Данные в "умных" таблицах.
С помощью макроса нужно копировать данные из столбца "Примечание" ("Price2") в столбец "Примечание" ("Price") используя столбец "Артикул" как критерий.
Количество строк в обеих таблицах разное. Перед вставкой содержимое в столбце "Примечание" ("Price") очищать.
Задачу можно решить формулами, но нужно сохранить форматирование ячеек из столбца "Примечание" ("Price2").

Автор - Jenialij
Дата добавления - 15.01.2025 в 18:24
Gustav Дата: Среда, 15.01.2025, 21:12 | Сообщение № 2
Группа: Админы
Ранг: Участник клуба
Сообщений: 2820
Репутация: 1188 ±
Замечаний: ±

начинал с Excel 4.0, видел 2.1
В качестве первого приближения решения можно поступить примерно так:
[vba]
Код
Sub transferRemarks()
    Dim colD As Range, rng1 As Range, cell As Range
    Dim wks1 As Worksheet, wks2 As Worksheet
    Dim i As Long, vals As Variant
    Dim matchKey As String, matchPos As Double
    
    Set wks1 = Worksheets("Price")
    Set wks2 = Worksheets("Price2")
    Set colD = Intersect(wks2.UsedRange, wks2.Columns("D").Resize(wks2.Rows.Count - 1).Offset(1))
    Set rng1 = Intersect(wks1.UsedRange, wks1.Columns("A:D")).Resize(, 5)
    
'формирование в массиве "колонки" с ключами поиска для листа Price
    vals = rng1.Value
    For i = 1 To rng1.Rows.Count
        vals(i, 5) = vals(i, 1) & "_" & vals(i, 2) & "_" & vals(i, 3)
    Next i
    
'перебор непустых ячеек колонки D листа Price2
    On Error Resume Next
    For Each cell In colD.SpecialCells(xlCellTypeConstants, 23).Cells
        matchKey = cell.Offset(, -3) & "_" & cell.Offset(, -2) & "_" & cell.Offset(, -1)
        matchPos = WorksheetFunction.Match(matchKey, WorksheetFunction.Index(vals, 0, 5), 0)
        If Err Then
            'ОШИБКА: значение ключа поиска matchKey не найдено в Price
            Err.Clear
            Debug.Print "Для строки " & cell.Row & " листа Price2 не найдена строка на листе Price"
        Else
            'УСПЕХ: matchKey найдено - копируем
            cell.Copy wks1.Cells(matchPos, 4)
        End If
    Next cell
    On Error GoTo 0
End Sub
[/vba]
Я, правда, искал не по одному "Артикулу", а по сцепке из трех полей "Наименование"+"Бренд"+"Артикул" (потому что невнимательно прочитал задание). Зато сразу пример на более общий случай поиска не по одному полю получился. А если искать по одному "Артикулу", то процедуру можно заметно упростить, заодно переходя от рабочих листов к объектам "умных таблиц" - раз уж они теперь есть в словаре разработчика, то почему бы их не использовать:
[vba]
Код
Sub transferRemarks_v2()
    Dim colD As Range, rng1 As Range, cell As Range
    Dim vals As Variant, matchKey As String, matchPos As Double
    Dim tbl1 As ListObject, tbl2 As ListObject
    
    Set tbl1 = Worksheets("Price2").ListObjects("Таблица1")
    Set tbl2 = Worksheets("Price").ListObjects("Таблица2")
    Set colD = tbl1.ListColumns("Примечание").DataBodyRange
    Set rng1 = tbl2.ListColumns("Артикул").Range 'колонка Артикул (с заголовком)
    
'формирование в массиве "колонки" с ключами поиска для листа Price
    vals = rng1.Value
    
'перебор непустых ячеек колонки D листа Price2
    On Error Resume Next
    For Each cell In colD.SpecialCells(xlCellTypeConstants, 23).Cells
        matchKey = cell.Offset(, -1) 'колонка Артикул
        matchPos = WorksheetFunction.Match(matchKey, vals, 0)
        If Err Then
            'ОШИБКА: значение ключа поиска matchKey не найдено в Price
            Err.Clear
            Debug.Print "Для строки " & cell.Row & " листа Price2 не найдена строка на листе Price"
        Else
            'УСПЕХ: matchKey найдено - копируем
            cell.Copy tbl2.Range.Cells(matchPos, 4)
        End If
    Next cell
    On Error GoTo 0
End Sub
[/vba]


МОИ: Ник, Tip box: 41001663842605
 
Ответить
СообщениеВ качестве первого приближения решения можно поступить примерно так:
[vba]
Код
Sub transferRemarks()
    Dim colD As Range, rng1 As Range, cell As Range
    Dim wks1 As Worksheet, wks2 As Worksheet
    Dim i As Long, vals As Variant
    Dim matchKey As String, matchPos As Double
    
    Set wks1 = Worksheets("Price")
    Set wks2 = Worksheets("Price2")
    Set colD = Intersect(wks2.UsedRange, wks2.Columns("D").Resize(wks2.Rows.Count - 1).Offset(1))
    Set rng1 = Intersect(wks1.UsedRange, wks1.Columns("A:D")).Resize(, 5)
    
'формирование в массиве "колонки" с ключами поиска для листа Price
    vals = rng1.Value
    For i = 1 To rng1.Rows.Count
        vals(i, 5) = vals(i, 1) & "_" & vals(i, 2) & "_" & vals(i, 3)
    Next i
    
'перебор непустых ячеек колонки D листа Price2
    On Error Resume Next
    For Each cell In colD.SpecialCells(xlCellTypeConstants, 23).Cells
        matchKey = cell.Offset(, -3) & "_" & cell.Offset(, -2) & "_" & cell.Offset(, -1)
        matchPos = WorksheetFunction.Match(matchKey, WorksheetFunction.Index(vals, 0, 5), 0)
        If Err Then
            'ОШИБКА: значение ключа поиска matchKey не найдено в Price
            Err.Clear
            Debug.Print "Для строки " & cell.Row & " листа Price2 не найдена строка на листе Price"
        Else
            'УСПЕХ: matchKey найдено - копируем
            cell.Copy wks1.Cells(matchPos, 4)
        End If
    Next cell
    On Error GoTo 0
End Sub
[/vba]
Я, правда, искал не по одному "Артикулу", а по сцепке из трех полей "Наименование"+"Бренд"+"Артикул" (потому что невнимательно прочитал задание). Зато сразу пример на более общий случай поиска не по одному полю получился. А если искать по одному "Артикулу", то процедуру можно заметно упростить, заодно переходя от рабочих листов к объектам "умных таблиц" - раз уж они теперь есть в словаре разработчика, то почему бы их не использовать:
[vba]
Код
Sub transferRemarks_v2()
    Dim colD As Range, rng1 As Range, cell As Range
    Dim vals As Variant, matchKey As String, matchPos As Double
    Dim tbl1 As ListObject, tbl2 As ListObject
    
    Set tbl1 = Worksheets("Price2").ListObjects("Таблица1")
    Set tbl2 = Worksheets("Price").ListObjects("Таблица2")
    Set colD = tbl1.ListColumns("Примечание").DataBodyRange
    Set rng1 = tbl2.ListColumns("Артикул").Range 'колонка Артикул (с заголовком)
    
'формирование в массиве "колонки" с ключами поиска для листа Price
    vals = rng1.Value
    
'перебор непустых ячеек колонки D листа Price2
    On Error Resume Next
    For Each cell In colD.SpecialCells(xlCellTypeConstants, 23).Cells
        matchKey = cell.Offset(, -1) 'колонка Артикул
        matchPos = WorksheetFunction.Match(matchKey, vals, 0)
        If Err Then
            'ОШИБКА: значение ключа поиска matchKey не найдено в Price
            Err.Clear
            Debug.Print "Для строки " & cell.Row & " листа Price2 не найдена строка на листе Price"
        Else
            'УСПЕХ: matchKey найдено - копируем
            cell.Copy tbl2.Range.Cells(matchPos, 4)
        End If
    Next cell
    On Error GoTo 0
End Sub
[/vba]

Автор - Gustav
Дата добавления - 15.01.2025 в 21:12
i691198 Дата: Среда, 15.01.2025, 21:52 | Сообщение № 3
Группа: Проверенные
Ранг: Обитатель
Сообщений: 359
Репутация: 113 ±
Замечаний: 0% ±

Более простой вариант макроса. [vba]
Код
Sub CopyForm()
  Dim Lr1%, Lr2%, Cl As Range, Dl As Range
  Lr1 = Sheets("Price2").Cells(Rows.Count, 3).End(xlUp).Row
  Lr2 = Sheets("Price").Cells(Rows.Count, 3).End(xlUp).Row
  Sheets("Price").Range("D2:D" & Lr2).Clear
  For Each Cl In Sheets("Price2").Range("C2:C" & Lr1)
    Cl.Offset(, 1).Copy
    Set Dl = Sheets("Price").Range("C2:C" & Lr2).Find(Cl.Value)
    If Not Dl Is Nothing Then Sheets("Price").Paste Dl.Offset(, 1)
  Next
  Application.CutCopyMode = False
End Sub
[/vba]
 
Ответить
СообщениеБолее простой вариант макроса. [vba]
Код
Sub CopyForm()
  Dim Lr1%, Lr2%, Cl As Range, Dl As Range
  Lr1 = Sheets("Price2").Cells(Rows.Count, 3).End(xlUp).Row
  Lr2 = Sheets("Price").Cells(Rows.Count, 3).End(xlUp).Row
  Sheets("Price").Range("D2:D" & Lr2).Clear
  For Each Cl In Sheets("Price2").Range("C2:C" & Lr1)
    Cl.Offset(, 1).Copy
    Set Dl = Sheets("Price").Range("C2:C" & Lr2).Find(Cl.Value)
    If Not Dl Is Nothing Then Sheets("Price").Paste Dl.Offset(, 1)
  Next
  Application.CutCopyMode = False
End Sub
[/vba]

Автор - i691198
Дата добавления - 15.01.2025 в 21:52
Jenialij Дата: Четверг, 16.01.2025, 14:29 | Сообщение № 4
Группа: Пользователи
Ранг: Прохожий
Сообщений: 3
Репутация: 0 ±
Замечаний: 0% ±

2021
Gustav,
i691198,
искренне благодарю за отзыв и помощь!
Все работает.

В первых двух решениях от Gustav еще нужно добавить очистку столбца "Примечание" листа "Price", чтобы соответствовало условиям задачи (может кому сгодится)
Что-то типа:
[vba]
Код
Worksheets("Price").ListObjects("Таблица2").ListColumns("Примечание").DataBodyRange.Clear
[/vba]

i691198
В Вашем решении чисто случайно обнаружился один нюанс: поскольку при большом количестве строк в таблицах (сотни) макрос долго отрабатывает, и в это время что-то скопировать в буфер обмена, то эта информация также вставится в ячейку столбца "Примечание" листа "Price". В какую именно, наверно зависит от того, на каком этапе отработки макроса, произойдет "лишнее" копирование в буфер.

Gustav
Еще такой вопрос:
Возможно ли в Ваших решениях "отвязаться" от использования Offset и взаимного расположения колонок, а оперировать переменными или названиями столбцов "умной" таблицы? Или нужно все переделывать?


Сообщение отредактировал Jenialij - Четверг, 16.01.2025, 14:58
 
Ответить
СообщениеGustav,
i691198,
искренне благодарю за отзыв и помощь!
Все работает.

В первых двух решениях от Gustav еще нужно добавить очистку столбца "Примечание" листа "Price", чтобы соответствовало условиям задачи (может кому сгодится)
Что-то типа:
[vba]
Код
Worksheets("Price").ListObjects("Таблица2").ListColumns("Примечание").DataBodyRange.Clear
[/vba]

i691198
В Вашем решении чисто случайно обнаружился один нюанс: поскольку при большом количестве строк в таблицах (сотни) макрос долго отрабатывает, и в это время что-то скопировать в буфер обмена, то эта информация также вставится в ячейку столбца "Примечание" листа "Price". В какую именно, наверно зависит от того, на каком этапе отработки макроса, произойдет "лишнее" копирование в буфер.

Gustav
Еще такой вопрос:
Возможно ли в Ваших решениях "отвязаться" от использования Offset и взаимного расположения колонок, а оперировать переменными или названиями столбцов "умной" таблицы? Или нужно все переделывать?

Автор - Jenialij
Дата добавления - 16.01.2025 в 14:29
_Boroda_ Дата: Четверг, 16.01.2025, 17:01 | Сообщение № 5
Группа: Админы
Ранг: Местный житель
Сообщений: 16763
Репутация: 6549 ±
Замечаний: ±

2003; 2007; 2010; 2013 RUS
Jenialij, еще вариант попробуйте )))
[vba]
Код
Sub Pry()
    With Application
        .ScreenUpdating = 0
        .DisplayAlerts = 0
        .Calculation = 3
        With Sheets("Price2")
            nr2_ = .Cells(.Rows.Count, 3).End(3).Row - 1
            ar21_ = .Cells(2, 3).Resize(nr2_).Value 'Артикул (столбец 3)
            ar22_ = .Cells(2, 4).Resize(nr2_).Value 'Примечание (столбец 4)
        End With
        With Sheets("Price")
            nr_ = .Cells(.Rows.Count, 3).End(3).Row - 1
            ar_ = .Cells(2, 3).Resize(nr_).Value 'Артикул (столбец 3)
            .Cells(2, 4).Resize(nr_).Clear 'Примечание (столбец 4)
            Set slov = CreateObject("Scripting.Dictionary")
            For i = 1 To nr_
                slov.Item(ar_(i, 1)) = i
            Next i
            For i = 1 To nr2_
                If ar22_(i, 1) <> "" Then
                    If slov.exists(ar21_(i, 1)) Then
                        Sheets("Price2").Cells(i + 1, 4).Copy .Cells(slov(ar21_(i, 1)) + 1, 4)
                    End If
                End If
            Next i
        End With
        .Calculation = 1
        .DisplayAlerts = 1
        .ScreenUpdating = 1
    End With
End Sub
[/vba]


Скажи мне, кудесник, любимец ба’гов...
Платная помощь:
Boroda_Excel@mail.ru
Яндекс-деньги: 41001632713405 | Webmoney: R289877159277; Z102172301748; E177867141995
 
Ответить
СообщениеJenialij, еще вариант попробуйте )))
[vba]
Код
Sub Pry()
    With Application
        .ScreenUpdating = 0
        .DisplayAlerts = 0
        .Calculation = 3
        With Sheets("Price2")
            nr2_ = .Cells(.Rows.Count, 3).End(3).Row - 1
            ar21_ = .Cells(2, 3).Resize(nr2_).Value 'Артикул (столбец 3)
            ar22_ = .Cells(2, 4).Resize(nr2_).Value 'Примечание (столбец 4)
        End With
        With Sheets("Price")
            nr_ = .Cells(.Rows.Count, 3).End(3).Row - 1
            ar_ = .Cells(2, 3).Resize(nr_).Value 'Артикул (столбец 3)
            .Cells(2, 4).Resize(nr_).Clear 'Примечание (столбец 4)
            Set slov = CreateObject("Scripting.Dictionary")
            For i = 1 To nr_
                slov.Item(ar_(i, 1)) = i
            Next i
            For i = 1 To nr2_
                If ar22_(i, 1) <> "" Then
                    If slov.exists(ar21_(i, 1)) Then
                        Sheets("Price2").Cells(i + 1, 4).Copy .Cells(slov(ar21_(i, 1)) + 1, 4)
                    End If
                End If
            Next i
        End With
        .Calculation = 1
        .DisplayAlerts = 1
        .ScreenUpdating = 1
    End With
End Sub
[/vba]

Автор - _Boroda_
Дата добавления - 16.01.2025 в 17:01
Gustav Дата: Четверг, 16.01.2025, 20:00 | Сообщение № 6
Группа: Админы
Ранг: Участник клуба
Сообщений: 2820
Репутация: 1188 ±
Замечаний: ±

начинал с Excel 4.0, видел 2.1
"отвязаться" от использования Offset и взаимного расположения колонок, а оперировать переменными или названиями столбцов "умной" таблицы

Кажется, получилось, примерно так:
[vba]
Код
Sub transferRemarks_v3()
    Dim cols1 As ListColumns, cols2 As ListColumns, headRow1 As Long, vals2 As Variant
    Dim cell As Range, matchKey As String, matchPos As Double
    
    Set cols1 = Worksheets("Price2").ListObjects("Таблица1").ListColumns
    headRow1 = cols1("Примечание").Range.Row
    
    Set cols2 = Worksheets("Price").ListObjects("Таблица2").ListColumns
    vals2 = cols2("Артикул").DataBodyRange.Value

'очистка всей колонки "Примечание" листа Price
    cols2("Примечание").DataBodyRange.Clear
    
'перебор непустых ячеек колонки D листа Price2
    On Error Resume Next
    For Each cell In cols1("Примечание").DataBodyRange.SpecialCells(xlCellTypeConstants, 23).Cells
        matchKey = cols1("Артикул").DataBodyRange(cell.Row - headRow1)
        matchPos = WorksheetFunction.Match(matchKey, vals2, 0)
        If Err Then
            'ОШИБКА: значение ключа поиска matchKey не найдено в Price
            Err.Clear
            Debug.Print "Для строки " & cell.Row & " листа Price2 не найдена строка на листе Price"
        Else
            'УСПЕХ: matchKey найдено - копируем
            cell.Copy cols2("Примечание").DataBodyRange(matchPos)
        End If
    Next cell
    On Error GoTo 0
End Sub
[/vba]
В конструкции типа cols2("Примечание").DataBodyRange меня немного смущает "хвост" .DataBodyRange (хоть бы они его как-нибудь коротенько типа .DBR назвали!). Но тут ничего не поделаешь: если хочется от него избавиться, то надо на каждую используемую колонку создавать отдельную переменную типа
[vba]
Код
Dim colPrim2 As Range

Set colPrim2 = cols2("Примечание").DataBodyRange
[/vba]


МОИ: Ник, Tip box: 41001663842605
 
Ответить
Сообщение
"отвязаться" от использования Offset и взаимного расположения колонок, а оперировать переменными или названиями столбцов "умной" таблицы

Кажется, получилось, примерно так:
[vba]
Код
Sub transferRemarks_v3()
    Dim cols1 As ListColumns, cols2 As ListColumns, headRow1 As Long, vals2 As Variant
    Dim cell As Range, matchKey As String, matchPos As Double
    
    Set cols1 = Worksheets("Price2").ListObjects("Таблица1").ListColumns
    headRow1 = cols1("Примечание").Range.Row
    
    Set cols2 = Worksheets("Price").ListObjects("Таблица2").ListColumns
    vals2 = cols2("Артикул").DataBodyRange.Value

'очистка всей колонки "Примечание" листа Price
    cols2("Примечание").DataBodyRange.Clear
    
'перебор непустых ячеек колонки D листа Price2
    On Error Resume Next
    For Each cell In cols1("Примечание").DataBodyRange.SpecialCells(xlCellTypeConstants, 23).Cells
        matchKey = cols1("Артикул").DataBodyRange(cell.Row - headRow1)
        matchPos = WorksheetFunction.Match(matchKey, vals2, 0)
        If Err Then
            'ОШИБКА: значение ключа поиска matchKey не найдено в Price
            Err.Clear
            Debug.Print "Для строки " & cell.Row & " листа Price2 не найдена строка на листе Price"
        Else
            'УСПЕХ: matchKey найдено - копируем
            cell.Copy cols2("Примечание").DataBodyRange(matchPos)
        End If
    Next cell
    On Error GoTo 0
End Sub
[/vba]
В конструкции типа cols2("Примечание").DataBodyRange меня немного смущает "хвост" .DataBodyRange (хоть бы они его как-нибудь коротенько типа .DBR назвали!). Но тут ничего не поделаешь: если хочется от него избавиться, то надо на каждую используемую колонку создавать отдельную переменную типа
[vba]
Код
Dim colPrim2 As Range

Set colPrim2 = cols2("Примечание").DataBodyRange
[/vba]

Автор - Gustav
Дата добавления - 16.01.2025 в 20:00
Jenialij Дата: Пятница, 17.01.2025, 12:10 | Сообщение № 7
Группа: Пользователи
Ранг: Прохожий
Сообщений: 3
Репутация: 0 ±
Замечаний: 0% ±

2021
Gustav
Спасибо! Самое оно.

И Вам, _Boroda_, спасибо за дополнительный пример.
***
Теперь только осталось до конца разобраться во всей этой магии символов. )


Сообщение отредактировал Jenialij - Пятница, 17.01.2025, 12:14
 
Ответить
СообщениеGustav
Спасибо! Самое оно.

И Вам, _Boroda_, спасибо за дополнительный пример.
***
Теперь только осталось до конца разобраться во всей этой магии символов. )

Автор - Jenialij
Дата добавления - 17.01.2025 в 12:10
Gustav Дата: Пятница, 17.01.2025, 14:29 | Сообщение № 8
Группа: Админы
Ранг: Участник клуба
Сообщений: 2820
Репутация: 1188 ±
Замечаний: ±

начинал с Excel 4.0, видел 2.1
меня немного смущает "хвост" .DataBodyRange (хоть бы они его как-нибудь коротенько типа .DBR назвали!)

Попытался избавиться от хвоста .DataBodyRange с помощью коллекций. В коллекции упрятал массивы колонок обеих умных таблиц, точнее, массивы диапазонов данных этих колонок. С последующим обращением к этим диапазонам по именам колонок. Вот что получилось:
[vba]
Код
Sub transferRemarks_v4()
    Dim headRow1 As Long, vals2 As Variant, matchKey As String, matchPos As Double
    Dim cell As Range, lc As ListColumn, dbr1 As New Collection, dbr2 As New Collection 'dbr = DataBodyRange
    
    With Worksheets("Price2").ListObjects("Таблица1")
        For Each lc In .ListColumns
            dbr1.Add lc.DataBodyRange, lc.Name
        Next lc
        headRow1 = .ListColumns("Примечание").Range.Row
    End With
       
    For Each lc In Worksheets("Price").ListObjects("Таблица2").ListColumns
        dbr2.Add lc.DataBodyRange, lc.Name
    Next lc
    vals2 = dbr2("Артикул") 'вот это особенно красиво выглядит

'очистка всей колонки "Примечание" листа Price
    dbr2("Примечание").Clear
    
'перебор непустых ячеек колонки D листа Price2
    On Error Resume Next
    For Each cell In dbr1("Примечание").SpecialCells(xlCellTypeConstants, 23).Cells
        matchKey = dbr1("Артикул")(cell.Row - headRow1)
        matchPos = WorksheetFunction.Match(matchKey, vals2, 0)
        If Err Then
            'ОШИБКА: значение ключа поиска matchKey не найдено в Price
            Err.Clear
            Debug.Print "Для строки " & cell.Row & " листа Price2 не найдена строка на листе Price"
        Else
            'УСПЕХ: matchKey найдено - копируем
            cell.Copy dbr2("Примечание")(matchPos)
        End If
    Next cell
    On Error GoTo 0
End Sub
[/vba]
Единственное неудобство - не работает технология IntelliSense, т.е. по набору точки после идентификаторов типа dbr2("Примечание") не всплывает список свойств и методов (объекта Range). Но известные свойства/методы можно и вручную набрать, либо скопировать от любого другого явно определенного объекта Range.


МОИ: Ник, Tip box: 41001663842605
 
Ответить
Сообщение
меня немного смущает "хвост" .DataBodyRange (хоть бы они его как-нибудь коротенько типа .DBR назвали!)

Попытался избавиться от хвоста .DataBodyRange с помощью коллекций. В коллекции упрятал массивы колонок обеих умных таблиц, точнее, массивы диапазонов данных этих колонок. С последующим обращением к этим диапазонам по именам колонок. Вот что получилось:
[vba]
Код
Sub transferRemarks_v4()
    Dim headRow1 As Long, vals2 As Variant, matchKey As String, matchPos As Double
    Dim cell As Range, lc As ListColumn, dbr1 As New Collection, dbr2 As New Collection 'dbr = DataBodyRange
    
    With Worksheets("Price2").ListObjects("Таблица1")
        For Each lc In .ListColumns
            dbr1.Add lc.DataBodyRange, lc.Name
        Next lc
        headRow1 = .ListColumns("Примечание").Range.Row
    End With
       
    For Each lc In Worksheets("Price").ListObjects("Таблица2").ListColumns
        dbr2.Add lc.DataBodyRange, lc.Name
    Next lc
    vals2 = dbr2("Артикул") 'вот это особенно красиво выглядит

'очистка всей колонки "Примечание" листа Price
    dbr2("Примечание").Clear
    
'перебор непустых ячеек колонки D листа Price2
    On Error Resume Next
    For Each cell In dbr1("Примечание").SpecialCells(xlCellTypeConstants, 23).Cells
        matchKey = dbr1("Артикул")(cell.Row - headRow1)
        matchPos = WorksheetFunction.Match(matchKey, vals2, 0)
        If Err Then
            'ОШИБКА: значение ключа поиска matchKey не найдено в Price
            Err.Clear
            Debug.Print "Для строки " & cell.Row & " листа Price2 не найдена строка на листе Price"
        Else
            'УСПЕХ: matchKey найдено - копируем
            cell.Copy dbr2("Примечание")(matchPos)
        End If
    Next cell
    On Error GoTo 0
End Sub
[/vba]
Единственное неудобство - не работает технология IntelliSense, т.е. по набору точки после идентификаторов типа dbr2("Примечание") не всплывает список свойств и методов (объекта Range). Но известные свойства/методы можно и вручную набрать, либо скопировать от любого другого явно определенного объекта Range.

Автор - Gustav
Дата добавления - 17.01.2025 в 14:29
  • Страница 1 из 1
  • 1
Поиск:

Яндекс.Метрика Яндекс цитирования
© 2010-2025 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!