Как скопировать диапазон на несколько листов, используя список листов для копирования

Новичок в VBA здесь. У меня сложная таблица, но я упрощу ее для своего вопроса. Допустим, у меня есть рабочая тетрадь с 20 листами. Каждый рабочий лист имеет трехбуквенное имя, например ABC. На первом листе находится диапазон, называемый CITIES в ячейках A1:A10. В каждой ячейке CITIES указано название города. Также на первом листе в ячейках B1:B10 находится список из 10 названий листов. Я периодически меняю этот список. Мне нужен макрос, чтобы скопировать диапазон CITIES в ячейку C1 каждого листа, указанного в B1:B10.

С моим макросом (показанным ниже) мне приходится менять имена листов в макросе каждый раз, когда я вношу изменения в список B1:B10. Я хочу, чтобы макрос использовал список B1:B10, чтобы определить, на какие листы копировать.

Заранее благодарим за любую помощь, которую вы можете оказать.

Sub CITIES_COPY ()
    Range("CITIES").Select
    Selection.Copy
    Sheets(Array("ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VWX", "YZA", "BCD")). _
        Select
    Sheets("ABC").Activate
    Range("C1").Select
    ActiveSheet.Paste
    Application.CutCopyMode = False
    Range("A1").Select
End Sub
Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
0
0
81
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Поместите этот код в первый модуль кода листа (где находятся данные). Диапазоны жестко запрограммированы, поэтому об этом следует помнить. Например. если листов меньше 10, будет ошибка в отсутствующих именах, а если больше 10, листы больше 10 будут исключены. «A1:A10» может измениться на указанный диапазон.

Sub mulcopy()

Range("A1:A10").Copy
For i = 1 To 10
  shnames = Cells(i, "B")
  Application.Worksheets(shnames).Range("C1").PasteSpecial xlPasteAll
Next i


End Sub

Большое спасибо. Однако я получаю сообщение об ошибке «Ошибка компиляции: переменная не определена», и буква I выделена. Пожалуйста, порекомендуйте.

user25903802 01.07.2024 20:54
Dim i As Long, Dim shnames As String
BigBen 01.07.2024 20:57

Спасибо, БигБен. Теперь он работает идеально!

user25903802 01.07.2024 21:54

Спасибо, Черный кот. С настройкой BigBen все работает отлично!

user25903802 01.07.2024 21:55

Если вы используете Option Explicit в модуле, необходимо объявить каждую переменную. Как прокомментировал @BigBen.

Black cat 02.07.2024 05:30
Ответ принят как подходящий

Мой пример ниже показывает несколько вещей, которые могут помочь, особенно когда вы только начинаете работать с VBA.

  1. Используйте описательные имена для своих переменных и будьте максимально ясными.
  2. Вам не обязательно использовать Select для копирования/вставки. Просто скопируйте диапазон в диапазон.
  3. Я добавил функцию для проверки правописания на листе, потому что это наверняка может сбить вас с толку при попытке отладки.
Option Explicit

Sub CopyCitiesToSheets()
    Dim srcWS As Worksheet
    Set srcWS = ThisWorkbook.Sheets("Source Sheet")
    
    Dim cities As Range
    Set cities = srcWS.Range("CITIES")
    
    '--- does not assume that you have the same number of rows
    Dim destSheetNames As Range
    With srcWS
        Dim lastRow As Long
        lastRow = .Range("CITIES").Offset(0, 1).Cells(.Rows.Count, 1).End(xlUp).Row
        Set destSheetNames = srcWS.Range("CITIES").Offset(0, 1).Resize(lastRow, 1)
    End With
    
    Dim destSheetName As Variant
    For Each destSheetName In destSheetNames
        '--- establish where the cities are going, but sure to match the same
        '    size and shape of the source range
        Dim destination As Range
        Set destination = GetDestinationRange(destSheetName, cities.Rows.Count, cities.Columns.Count)
        destination.Value = cities.Value
    Next destSheetName
    
End Sub

Function GetDestinationRange(ByVal destSheetName As String, _
                             ByVal numRows As Long, _
                             ByVal numCols As Long) As Range
    Dim dstWS As Worksheet
    On Error Resume Next
    Set dstWS = ThisWorkbook.Sheets(destSheetName)
    If Err <> 0 Then
        MsgBox "ERROR: not a value worksheet name!  Did you misspell it?", _
               Buttons:=vbCritical + vbOKOnly, _
               Title: = "ERROR in Worksheet Name"
    End If
    Set GetDestinationRange = dstWS.Range("C1").Resize(numRows, numCols)
End Function

Спасибо, ПитерТ. Я не пробовал ваше решение, потому что мою проблему уже решили Black Cat и BigBen. Тем не менее, я очень ценю ваш ответ и советы по программированию.

user25903802 01.07.2024 21:56

Отлично сделано +:); К вашему сведению, вы опубликовали альтернативное решение с помощью метода Excel FillAcrossSheets, которое может вас заинтересовать.

T.M. 03.07.2024 20:43

Поздний пост с демонстрацией малоизвестного метода FillAcrossSheets.

Он копирует

  • заданный диапазон на листе Sheet1 (например, ячейки A1:A10)
  • в заданный целевой диапазон (например, ячейки C1:C10)
  • во все листы, предварительно определенные в соседних ячейках (здесь: B1:B10):

Пример звонка

Option Explicit               ' (code module head)

Sub ExampleCall()
'0) base definitions
    With Sheet1.Range("CITIES")       ' << Change sheet reference as needed
        Dim cities:   cities = .Value2
        Dim mySheets: mySheets = getSheets(.Offset(0, 1))
        If UBound(mySheets) = -1 Then Exit Sub
    End With
'1) set target range in first sheet of chosen worksheets
    Dim tgtRng As Range
    Set tgtRng = ThisWorkbook.Worksheets(mySheets(1)).Range("C1").Resize(UBound(cities), 1)
'2) write cities to target range in chosen worksheets
    FillSheets tgtRng, cities, mySheets    ' << main procedure FillSheets
End Sub

Основная процедура FillSheets

Sub FillSheets(rng As Range, data, Optional SheetsArr)
'Purp: write data to all sheets included in argument SheetsArr
'Note: c.f. https://stackoverflow.com/questions/58879621/how-to-write-identical-information-in-a-specific-cell-for-all-sheets/58884112#58884112
'      c.f. https://learn.microsoft.com/en-us/office/vba/api/excel.sheets.fillacrosssheets
'a) fill the range in the first target sheet
    rng = data
'b) write data via Excel method FillAcrossSheets
    If IsMissing(SheetsArr) Then    ' fill all sheets
        Sheets().FillAcrossSheets rng
    Else                            ' fill only target sheets
        If UBound(SheetsArr) - LBound(SheetsArr) Then
            Sheets(SheetsArr).FillAcrossSheets rng
        End If
    End If
End Sub

Вспомогательная функция getSheets (по сравнению с MS365)

Function getSheets(rng As Range)
'Purp:  assign sheet names to 1D array ignoring empty cells
'Note:  needs vers. MS365 !
    Dim addr As String: addr = rng.Address(external:=True)
    getSheets = Evaluate("Transpose(Filter(" & addr & "," & addr & "<>0))")
End Function

GetSheets() для более ранних версий

Если вы не избавитесь от vers. MS 365, чтобы получить имена листов, вы можете попробовать следующий код:

Function getSheets(rng As Range)
'Purp:  assign sheet names to 1D array and omit empty names
'a) assign values to 1D array
    Dim tmp: tmp = Application.Transpose(rng.Value2)
'b) omit empty sheet names
    Dim i As Long, ii As Long
    For i = 1 To UBound(tmp)
        If Len(Trim(tmp(i))) Then
            ii = ii + 1: tmp(ii) = tmp(i)
        End If
    Next i
    If ii Then
        ReDim Preserve tmp(1 To ii)
    Else
        tmp = Array()
    End If
'c) return function result
    getSheets = tmp
End Function

Другие вопросы по теме