2016-11-01 4 views
0

Я новичок в VBA, но я учусь. У меня есть рабочий лист «Модель», который имеет 18 таблиц. Я определил их диапазоны с «началом» и «концом». Итак, как вы можете видеть в VBA ниже, первая таблица находится в C3: E13 и последней таблице в C224: E234. Я хочу скопировать их и вставить их один за другим в Sheet1.VBA for-loop с тремя переменными

Там они должны быть вставлены в ячейки B5, B21, B38, ..., B166. Итак, первая таблица должна быть вставлена ​​в B5, вторая в B21 и т. Д.

Итак, мой вопрос в том, как я могу создать эту переменную 'output' (которая определяет выходную строку) в моем for-loop?

Dim start As Long 
Dim eind As Long 
Dim output As Long 

For start = 3 To 224 Step 13 
    end = start + 10 

      'output = --->>> this should be 5, 21, 38, ..., 166. 
      'So something like output = 5 To 166 Step 16 

Sheets("Model").Select 
Range("C" & start & ":E" & end).Select 
Selection.Copy 
Sheets("Sheet1").Select 
Range("B" & output).Select 
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ 
     :=False, Transpose:=False 
Next start 

Большое спасибо!

+0

ли это на самом деле * Таблица * (например, от Вставки> Таблицы ленты)? –

+0

(FYI, рекомендуется избегать использования '' .Select'/'.Activate'] (http://stackoverflow.com/questions/10714251/how-to-avoid-using-select-in-excel-vba-macros)) – BruceWayne

ответ

4

Отметьте, что 21 + 16 является 37, а не 38 в соответствии с вашими комментариями. Не уверен, что это опечатка. Пересмотрено до avoid Select, что на 99% не нужно, и чтобы избежать относительно дорогого Copy в пользу непосредственной передачи значений из одного диапазона в другой.

Dim start As Long 
Dim end As Long 
Dim output As Long 
Dim tbl as Range 
Dim dest as Range 

output = 5 
For start = 3 To 224 Step 13 
    end = start + 10 
    Set tbl = Sheets("Model").Range("C" & start & ":E" & end) 
    Set dest = Sheets("Sheet1").Range("B" & output).Resize(tbl.Rows.Count, tbl.Columns.Count) 
    dest.Value = tbl.Value 
    output = output + 16 

Next 

Если таблицы являются соответствующие таблицы, которые были созданы из Insert> таблицы, то вы могли бы сделать что-то вроде:

Dim tbl as ListObject 
Dim t as Long 
Dim dest as Range 
For t = 1 to Sheets("Model").ListObjects.Count 
    Set tbl = Sheets("Model").ListObjects(t) 
    Set dest = Sheets("Sheet1").Range("B" & (5 + ((t - 1) * 16))) 
    dest.Resize(tbl.Rows.Count, tbl.Columns.Count).Value = tbl.Value 
Next 
+0

Хороший ответ. Вы даже можете установить 'output' в 5, прежде чем вы начнете цикл for, а затем избавиться от' IIF() ' –

+0

@JohnBustos да, ты прав. Мне это нравится лучше. Перераб. –

+0

Это намного лучше, спасибо. Ты просто облегчил мне жизнь;) – Z117

0

Хотя я бы предложил делать вещи совсем по-другому, позвольте мне ответить на ваш фактический вопрос, поскольку он все равно будет работать и по-прежнему является полностью актуальным вопросом программирования.

Способ сделать это на самом деле есть отдельный «счетчик» переменный (я обычно называю это i из моих старых курсов с ++ колледжем), а затем увеличить start, end и output соответственно в операторе цикла. Это будет выглядеть следующим образом:

Dim i As Integer 

Dim start As Long 
Dim end_ As Long 
Dim output As Long 

i = 0 
Do 

    start = 3 + i * 13 
    end_ = start + 10 
    output = 5 + i * 16 

    ' ... your code.... 

    i = i + 1 
Loop While start <= 224 

В принципе, вы можете установить все переменные, как вы хотите и установить критерии выхода, как это необходимо.

Я надеюсь, что это имеет смысл и работает для вас!

+0

Спасибо большое! Это имеет смысл :) – Z117

+0

Рад, что это имеет смысл и рад, что вы получили то, что искали. Я действительно верю, что вы приняли правильное решение - решение @DavidZemens, безусловно, лучший способ сделать это. Это просто другой способ получить один и тот же результат и позволяет более явную настройку переменной –

0

Вы могли бы попробовать что-то вроде этого. Играйте с приращениями (например, значение шага цикла, j + 10, i + 10 и j = j + 11), чтобы получить расстояние между диапазонами и высотой/шириной ваших таблиц так, как вы хотите.

Public Sub copyTables() 

Dim i As Integer, j As Integer 
Dim ws1 As Worksheet, ws2 As Worksheet 

Set ws1 = ThisWorkbook.Sheets("Sheet1") 
Set ws2 = ThisWorkbook.Sheets("Sheet2") 

j = 5 

For i = 3 To 224 Step 11 
    ws2.Range("B" & j, "D" & j + 10).Value = ws1.Range("C" & i, "E" & i + 10).Value 
    j = j + 11 
Next i 

Set ws1 = Nothing 
Set ws2 = Nothing 

End Sub 
0

вы могли бы попробовать это:

Sub main() 
    Dim iTab As Long 

    With Worksheets("Model").Range("C3:E13") 
     For iTab = 1 To 18 
      Worksheets("Sheet1").Range("B5:D15").Offset((iTab - 1) * 16).Value = .Offset((iTab - 1) * 13).Value 
     Next iTab 
    End With 
End Sub 
Смежные вопросы