#excel #vba
#excel #vba
Вопрос:
У меня есть два листа
- Источник (ThisWorkbook) — содержит несколько листов
- Назначение (WBD) — содержит 1 лист
Это процесс:
- Сравните каждую ячейку из диапазона в WBD (B2: B6) со всеми именами листов в этой рабочей книге
- Если найдено совпадение, выберите диапазон в WBD (C2: C7) и найдите его на соответствующем листе
- (вот тут у меня проблемы) Как мне получить значение ячейки средней цены? Нужен ли мне еще один цикл?
* расстояние между типом и ценой соответствует.
Вот что я получил до сих пор:
For Each cel In WBD.Worksheets(1).Range("B2:B6")
For Each ws In ThisWorkbook.Worksheets
ws.Activate
If ws.Name = cel.Value Then
'find C2:C7 , offset, copy avg price, paste
Next ws
Next cel
Источник — ThisWorkbook
Назначение — WBD
Ответ №1:
Поиск по листам
Подход Application.Match
Option Explicit
Sub lookupValues()
Const dFirst As Long = 2
Const sFirst As Long = 2
Dim swb As Workbook: Set swb = ThisWorkbook
'Dim WBD As Workbook: Set WBD = ThisWorkbook
Dim drg As Range
Dim dLast As Long
With WBD.Worksheets(1)
dLast = .Cells(.Rows.Count, "C").End(xlUp).Row ' because merged in 'B'
Set drg = .Cells(dFirst, "B").Resize(dLast - dFirst 1)
End With
Dim src As Worksheet
Dim srg As Range
Dim cel As Range
Dim dMatch As Variant
Dim sMatch As Variant
Dim sLast As Long
For Each src In swb.Worksheets
sLast = src.Cells(src.Rows.Count, "C").End(xlUp).Row
Set srg = Nothing
On Error Resume Next
Set srg = src.Cells(sFirst, "B").Resize(sLast - sFirst 1)
On Error GoTo 0
If Not srg Is Nothing Then
dMatch = Application.Match(src.Name, drg, 0)
If IsNumeric(dMatch) Then
Set cel = drg.Cells(dMatch)
Do
sMatch = Application.Match(cel.Offset(, 1).Value, srg, 0)
If IsNumeric(sMatch) Then
cel.Offset(, 2).Value _
= srg.Cells(sMatch).Offset(3, 2).Value
End If
Set cel = cel.Offset(, 1).Offset(1, -1) ' because merged
Loop Until Len(cel.Value) > 0 Or cel.Row > dLast
End If
End If
Next src
'WBD.Save
'swb.Close SaveChanges:=False
End Sub
Комментарии:
1. Я пытаюсь понять, что делает каждая строка. Можете ли вы просветить меня по
With WBD.Worksheets(1) dLast = .Cells(.Rows.Count, "C").End(xlUp).Row ' because merged in 'B' Set drg = .Cells(dFirst, "B").Resize(dLast - dFirst 1) End With
2. Сначала вычисляется последняя строка в столбце
C
, потому что в столбцеB
результат может быть неправильным из-за объединенных ячеек. Затем он определяет столбецDestination (Read) Column Range
inB
, используя в качестве первой строки константуdFirst
, а для последней строки только что вычисленнуюdLast
(на вашем изображенииB2:B7
; вычисленная последняя строка в столбцеB
приведет кB2:B6
(неправильному)).3.
Resize
Часть немного сложнее. У вас есть.Cells(dFirst, "B")
то же.Range("B" amp; dFirst)
самое, что и или в данном конкретном случаеB2
. Представьте, что вычисленная последняя строка была row7
. Если вы это сделаетеRange("B2").Resize(7 - 2 1)
, вы можете упроститьRange("B2").Resize(6)
, что в итогеRange("B2:B7")
(нетRange("B2:B8")
). Обратите внимание, чтоRange("A1").Resize(1)
это все ещеRange("A1")
иRange("A1").Resize(2)
естьRange("A1:A2")
, покаRange("A1").Offset(1)
естьRange("A2")
.4. Не могли бы вы помочь мне изменить код, если строка / столбцы настроены таким образом? imgur.com/a/khG6oNA
Ответ №2:
Sub m1()
For Each cel In ThisWorkbook.Worksheets(1).Range("B2:B6")
If cel.MergeCells Then
shname = cel.MergeArea.Cells(1, 1).Value ' if cells merged, only first cell contains value
Else
shname = cel.Value
End If
For Each ws In ThisWorkbook.Worksheets
If ws.Name = shname Then
Set f = ws.Columns("B").Find(cel.Offset(0, 1).Value, lookat:=xlWhole)
If Not f Is Nothing Then ' its found
Set f = ws.Cells.Find("avg price", after:=f.Offset(0, 1))
If Not f Is Nothing Then ' its found
cel.Offset(0, 2).Value = f.Offset(0, 1).Value
End If
End If
End If
Next ws
Next cel
End Sub
Комментарии:
1. Я забыл упомянуть, что средняя цена указана в одном типе данных. Я пытаюсь выяснить, почему код не работает с моей стороны.
2. Тип данных в этом случае не имеет значения, поскольку команда cel. Смещение (0, 2) .Значение = f.Смещение (0, 1) .Значение присваивает ячейке слева значение любого типа из ячейки справа. Что касается причин неработоспособности этого кода, это обычно решается путем пошаговой отладки кода
3. Нужно ли объявлять f?
4. Переменные в VBA не обязательно объявлять, без объявления они имеют тип Variant . Необходимость объявления переменных зависит от того, есть ли в модуле явный оператор Option.
5. Я думаю, что я получил свою ошибку, значение, которое я нахожу в B, является объединенной ячейкой. Кроме того, ячейка средней цены и ячейка справа от нее также являются объединенной ячейкой. Как мне это решить?