Есть книга, в которой 10 листов. Нужно скопировать содержимое 8-го листа в 3-й лист.
Я пытался сделать это следующим способом:
Set CurrentWorkbook = ThisWorkbook
Set sheetTemp = CurrentWorkbook.Worksheets(8)
With Application: .ScreenUpdating = False: .DisplayAlerts = False: End With
With CurrentWorkbook
sheetTemp.Copy CurrentWorkbook.Worksheets(3)
End With
With Application: .ScreenUpdating = True: .DisplayAlerts = True: End With
Все работает, но вместо записи в 3-й лист оно создает перед третьим листом новый лист. Как сделать так, чтобы при копировании не создавался новый лист и записывалось в существующий лист?
задан 21 сен 2018 в 10:35
2
Полное копирование столбцов (ширина, форматирование, значения, примечания…):
Sub CopyRange()
Worksheets("Лист1").Columns("C:E").Copy
Worksheets("Лист2").Columns("C:E").PasteSpecial
End Sub
или
Sub CopyRange()
Worksheets("Лист1").Columns("C:E").Copy Worksheets("Лист2").Columns("C:E")
End Sub
Для копирования только нужного:
Worksheets("Лист1").Range("C3:E50").Copy
With Worksheets("Лист2").Range("C3")
.PasteSpecial xlPasteColumnWidths ' ширина столбца'
.PasteSpecial xlPasteValues' значения'
.PasteSpecial xlPasteFormats' форматы'
.PasteSpecial xlPasteFormulasAndNumberFormats ' формулы'
' .....'
End With
После копирования очистить буфер:
Application.CutCopyMode = False
ответ дан 21 сен 2018 в 11:38
Решение задачи по копированию данных с одного листа на другой без использования и с использованием массивов. Вызов из кода VBA Excel других процедур.
Условие задачи по копированию данных
На одном листе расположен список повторяющихся городов с информацией о предприятиях общепита:
Исходная таблица задания №1
Необходимо данные по каждому городу перенести в одну строку на другом листе (таблица обрезана справа):
Часть результирующего списка задания №1
Решение копированием с листа на лист
Это решение значительно проще, чем с использованием массивов, но более медленное. При больших объемах информации обработка может длиться достаточно долго. Решение достигается путем присваивания значений ячеек из таблицы первого листа ячейкам второго листа.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Sub Resheniye1() Dim n1 As Long, n2 As Long, n3 As Long, n4 As Long, _ i1 As Long, gorod As Variant n1 = Sheets(«Лист1»).Cells(1, 1).CurrentRegion.Rows.Count For i1 = 1 To n1 With Sheets(«Лист1») If gorod <> .Cells(i1, 1) Then gorod = .Cells(i1, 1) n2 = 1 n3 = n3 + 1 n4 = 1 Else n2 = 2 End If Do While .Cells(i1, n2) <> «» Sheets(«Лист2»).Cells(n3, n4) = .Cells(i1, n2) n4 = n4 + 1 n2 = n2 + 1 Loop End With Next End Sub |
Переменные:
- n1 – количество строк в исходной таблице;
- n2 – номер столбца текущей ячейки исходной таблицы, к которой обращается цикл;
- n3 – номер строки текущей ячейки на втором листе;
- n4 – номер столбца текущей ячейки на втором листе;
- i1 – счетчик цикла For… Next;
- gorod – переменная с наименованием города, предназначенная для контроля за сменой текущего города, который обрабатывается циклом.
Решение с использованием массивов
Циклы в массивах работают очень быстро, но решение с ними может быть сложнее, чем при простом присваивании значений одних ячеек другим. В этом примере для упрощения кода две процедуры записаны отдельно и в нужные моменты вызываются для исполнения.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
‘Объявление глобальных переменных ‘в разделе Declarations Dim massiv1 As Variant, n2 As Long, _ n3 As Long, i1 As Long, txt1 As Variant ‘Исполняемая процедура для решения ‘задания вторым способом Sub Resheniye2() Dim n1 As Long, gorod As Variant With Sheets(«Лист1»).Cells(1, 1) massiv1 = .CurrentRegion n1 = .CurrentRegion.Rows.Count n2 = .CurrentRegion.Columns.Count End With n3 = 0 txt1 = «» For i1 = 1 To n1 If gorod <> massiv1(i1, 1) Then If txt1 <> «» Then Call Vstavka End If gorod = massiv1(i1, 1) txt1 = massiv1(i1, 1) Call Kopirovanie Else Call Kopirovanie End If If i1 = n1 Then Call Vstavka End If Next End Sub ‘Копирование данных из массива в ‘строковую переменную через разделитель Sub Kopirovanie() Dim i2 As Long For i2 = 2 To n2 If massiv1(i1, i2) <> Empty Then txt1 = txt1 & «|» & massiv1(i1, i2) End If Next End Sub ‘Обработка данных из строковой ‘переменной в дополнительных массивах и ‘вставка очередной строки на второй лист Sub Vstavka() Dim n4 As Long, massiv2 As Variant, _ massiv3 As Variant, i3 As Long n3 = n3 + 1 massiv2 = Split(txt1, «|») n4 = UBound(massiv2) ReDim massiv3(0 To 0, 0 To n4) For i3 = 0 To n4 massiv3(0, i3) = massiv2(i3) Next Sheets(«Лист2»).Range(Cells(n3, 1), _ Cells(n3, n4 + 1)).Value = massiv3 End Sub |
Подпрограммы Kopirovanie
и Vstavka
используются в цикле For... Next
процедуры Resheniye2
по два раза, поэтому их коды вынесены за пределы процедуры Resheniye2
и вызываются по мере необходимости.
Переменные:
- massiv1 – его элементам присваиваются значения ячеек исходной таблицы;
- massiv2 – одномерный массив, заполняемый данными из переменной txt1;
- massiv3 – двумерный массив, заполняемый данными из одномерного массива massiv2 и используемый для вставки очередной строки на второй лист;
- txt1 – сюда копируются через разделитель значения элементов массива massiv1, предназначенные для заполнения очередной строки на втором листе;
- n1 – количество строк в исходной таблице;
- n2 – количество столбцов в исходной таблице;
- n3 – номер текущей строки на втором листе;
- n4 – количество столбцов текущей строки на втором листе (соответствует количеству элементов массива massiv2);
- i1, i2, i3 – счетчики цикла For… Next;
- gorod – переменная с наименованием города, предназначенная для контроля за сменой текущего города, который обрабатывается циклом.
Переменные, использующиеся более чем в одной процедуре, объявлены как глобальные в разделе Declarations
программного модуля.
VistaSV30 Пользователь Сообщений: 70 |
#1 08.10.2015 09:08:51 Добрый день!
Спасибо! Изменено: VistaSV30 — 08.10.2015 09:10:21 <#0> |
||
yoozhik Пользователь Сообщений: 239 |
#2 08.10.2015 09:28:52
|
||
VistaSV30 Пользователь Сообщений: 70 |
Спасибо, скопировать получилось! |
Sanja Пользователь Сообщений: 14838 |
#4 08.10.2015 09:43:01 Ну из двух сделайте один макрос. И зачем эти навороты с Set Ar…?
Изменено: Sanja — 08.10.2015 09:47:00 Согласие есть продукт при полном непротивлении сторон. |
||
VistaSV30 Пользователь Сообщений: 70 |
Спасибо, Sanja. Сделал как Вы посоветовали |
Hugo Пользователь Сообщений: 23253 |
#6 08.10.2015 10:12:52 Ещё вариант в одну строку (можно написать ещё чуть короче)
|
||
Introduction
This tip shows 2 ways to copy data between Excel sheets in the same workbook using VBA.
Background
Most beginners in VBA programming make several mistakes, which are commonly named: bad practice. What is bad practice in Excel-VBA from my point of view?
- Using code without context, for example:
Range("A1") = "Some Text" Cells(5,5) = 125
Imagine, you wanted to insert those values into
Sheet2
, but when a code has been executed,Sheet1
was active. Where the data has been written? Of course, intoSheet1
. - Using
Select
andActivate
methodThis might be the reason for several issues, such as unnecessary calculations.
- Using undefined variables (not explicitly declared as some other type)
In that case, every variable consumes more memory than is necessary, because of type of variant.
See Data types - Using code without error handling
For further details, please see: Excel VBA Performance Coding Best Practices
Let’s say you want to copy some portion of data from Sheet1
into Sheet2
. A condition is defined as: Level
has to be greater than 1 (see image below).
Using the code
Solution #1 — Using ADODB.Recordset and Range.CopyFromRecordset Method
This method is really quick!
Note: Before you run below code, you have to add a reference to Microsoft ActiveX Data Object Library x.x. How? Check or Add an Object Library Reference
Please, check out below code (Excel 2007 ad higher). Do not forget to read my comments.
Sub CopyData1() Dim oConn As ADODB.Connection, oRst As ADODB.Recordset Dim sConn As String, sSql As String On Error GoTo Err_CopyData1 sConn = "Provider=Microsoft.ACE.OLEDB.12.0;_ Data Source=" & ThisWorkbook.FullName & ";_ Extended Properties='Excel 12.0 Macro;HDR=YES';" Set oConn = New ADODB.Connection With oConn .ConnectionString = sConn .Open End With sSql = "SELECT [Part_Number], [Name], [Version], [Level]" & vbCr & _ "FROM [Sheet1$A1:D100]" & vbCr & _ "WHERE [Level]>1;" Set oRst = New ADODB.Recordset oRst.Open sSql, oConn, adOpenStatic, adLockReadOnly With ThisWorkbook.Worksheets("Sheet2") .Range("A2:D10000").Delete xlShiftUp .Range("A2").CopyFromRecordset oRst End With Exit_CopyData1: On Error Resume Next If Not oConn Is Nothing Then oConn.Close Set oConn = Nothing If Not oRst Is Nothing Then oRst.Close Set oRst = Nothing Exit Sub Err_CopyData1: MsgBox Err.Description, vbExclamation, Err.Number Resume Exit_CopyData1 End Sub
For further details, please see:
- ADODB.Recordset
- Range.CopyFromRecordset
In case you want to fetch data from another type of workbook or you want to refer to earlier version of MS Excel files, you have to change connection string. See: Excel — OleDb 12.0 connection strings
If you would like to know, how to copy data into new or existing Sheet in different workbook, please find related content below.
Solution #2 — Using Do/While..Loop or For…Next Loop
Sub CopyData2() Dim srcWsh As Worksheet, dstWsh As Worksheet Dim i As Integer, j As Integer On Error GoTo Err_CopyData2 Set srcWsh = ThisWorkbook.Worksheets("Sheet1") Set dstWsh = ThisWorkbook.Worksheets("Sheet2") dstWsh.Range("A2:D10000").Clear i = 2 j = 2 Do While srcWsh.Range("A" & i) <> "" If srcWsh.Range("D" & i) = 1 Then GoTo SkipThisRow With dstWsh .Range("A" & j) = srcWsh.Range("A" & i) .Range("B" & j) = srcWsh.Range("B" & i) .Range("C" & j) = srcWsh.Range("C" & i) .Range("D" & j) = srcWsh.Range("D" & i) End With j = j + 1 SkipThisRow: i = i + 1 Loop Exit_CopyData2: On Error Resume Next Set srcWsh = Nothing Set dstWsh = Nothing Exit Sub Err_CopyData2: MsgBox Err.Description, vbExclamation, Err.Number Resume Exit_CopyData2 End Sub
You may want to ask me: Why a set of columns has been hard-coded in above example?
The answer is pretty easy. You may want to copy data in defferent order or into different range.
Other solutions
Using Filter-And-Copy
Sub FilterAndCopy() Dim srcWsh As Worksheet Dim dstWsh As Worksheet Set wsSource = ThisWorkbook.Worksheets("Sheet1") Set wsTarget = ThisWorkbook.Worksheets("Sheet2") On Error GoTo Err_FilterAndCopy dstWsh.Range("A2:A10000").Clear With srcWsh .Range("A1").AutoFilter .UsedRange.AutoFilter Field:=4, Criteria1:=">1" .UsedRange.Copy Destination:=dstWsh.Range("A2") End With Application.CutCopyMode = False srcWsh.Range("A1").AutoFilter Exit_FilterAndCopy: On Error Resume Next Set srcWsh = Nothing Set dstWsh = Nothing Exit Sub Err_FilterAndCopy: MsgBox Err.Description, vbCritical, Err.Number Resume Exit_FilterAndCopy End Sub
Above method is pretty good, but has several limitations. The main issue is copying a large portion of data. When you copy simple data (no formulas), it can take a while for the operation to complete. But when you’re copying the data containing set of formulas, then the time needed to complete operation may increase several times due an Excel have to perform thousands of calculations…
Copy data into new worksheet/workbook or into existing sheet in different workbook
This is quite easy. Depending on situation (workbook is already open or not), you have to change only one line or few lines.
Set dstWsh = Workbooks("ShortNameOfWorkbook.xlsx").WorkSheets("DestinationSheet") Workbooks.Open "FullPathAndNameOfWorkbook.xlsx" Set dstWsh = ActiveWorkbook.Worksheets("DestinationSheet")
Final Note
I hope you’ve learned how to copy data between sheets and workbooks.
History
- 2017-05-23 — Added: other solutions and information about copying data into new or existing workbook/worksheet
- 2017-05-17 — Initial version
wishcom 1 / 1 / 0 Регистрация: 17.02.2010 Сообщений: 131 |
||||||||
1 |
||||||||
18.12.2010, 21:39. Показов 19007. Ответов 20 Метки нет (Все метки)
Не понимаю почему работат.
,а
нет.
0 |
pashulka 4131 / 2235 / 940 Регистрация: 01.12.2010 Сообщений: 4,624 |
||||
19.12.2010, 03:06 |
2 |
|||
Вы забыли инструкцию Select или Activate
0 |
wishcom 1 / 1 / 0 Регистрация: 17.02.2010 Сообщений: 131 |
||||
19.12.2010, 18:09 [ТС] |
3 |
|||
Activate Точно отпадает.
0 |
4131 / 2235 / 940 Регистрация: 01.12.2010 Сообщений: 4,624 |
|
19.12.2010, 18:36 |
4 |
Вы спросили, почему не работает Ваш код, и я ответил, что
0 |
1 / 1 / 0 Регистрация: 17.02.2010 Сообщений: 131 |
|
19.12.2010, 20:48 [ТС] |
5 |
Неужели никак иначе.
0 |
4131 / 2235 / 940 Регистрация: 01.12.2010 Сообщений: 4,624 |
|
19.12.2010, 21:39 |
6 |
Можно и иначе, советую более внимательно ознакомиться с help.
0 |
22 / 5 / 1 Регистрация: 05.09.2010 Сообщений: 370 |
|
20.12.2010, 09:55 |
7 |
Так чтобы не маячило, может надо
0 |
1 / 1 / 0 Регистрация: 17.02.2010 Сообщений: 131 |
|
20.12.2010, 20:04 [ТС] |
8 |
Да отлично я это знаю.
0 |
22 / 5 / 1 Регистрация: 05.09.2010 Сообщений: 370 |
|
21.12.2010, 05:25 |
9 |
А так?
0 |
1 / 1 / 0 Регистрация: 17.02.2010 Сообщений: 131 |
|
21.12.2010, 22:56 [ТС] |
10 |
НЕ…
0 |
4131 / 2235 / 940 Регистрация: 01.12.2010 Сообщений: 4,624 |
|
22.12.2010, 07:06 |
11 |
А вот так …
0 |
wishcom 1 / 1 / 0 Регистрация: 17.02.2010 Сообщений: 131 |
||||
22.12.2010, 20:06 [ТС] |
12 |
|||
0 |
pashulka 4131 / 2235 / 940 Регистрация: 01.12.2010 Сообщений: 4,624 |
||||
22.12.2010, 22:58 |
13 |
|||
А вот так :
‘хотя в Excel наверняка существует функция возвращающая имя столбца,
0 |
1 / 1 / 0 Регистрация: 17.02.2010 Сообщений: 131 |
|
23.12.2010, 18:14 [ТС] |
14 |
У тебя код побыстрее, но у меня для Rows и Cols, в функции содержатся все операторы. Кстати. Ссылка на адрес… это черевато крахом Exel.
0 |
4131 / 2235 / 940 Регистрация: 01.12.2010 Сообщений: 4,624 |
|
24.12.2010, 01:41 |
15 |
Этот код я написал специально для Вас, и в свете вышеописанных задач он свою функцию выполняет на 100%.
0 |
1 / 1 / 0 Регистрация: 17.02.2010 Сообщений: 131 |
|
24.12.2010, 11:29 [ТС] |
16 |
У меня сверху стоит Option Explicit Ну мне покрайней мере надо было Не. Дописал бы.. Самому пригодилось бы…
0 |
wishcom 1 / 1 / 0 Регистрация: 17.02.2010 Сообщений: 131 |
||||
24.12.2010, 14:01 [ТС] |
17 |
|||
Я тут к твоему коду присмотрелся и написал…
0 |
Dimakart 0 / 0 / 1 Регистрация: 11.10.2010 Сообщений: 48 |
||||
24.12.2010, 19:51 |
18 |
|||
А вот так не проще ли будет ?
0 |
1 / 1 / 0 Регистрация: 17.02.2010 Сообщений: 131 |
|
24.12.2010, 22:08 [ТС] |
19 |
По моему мой код побыстрее…
0 |
4131 / 2235 / 940 Регистрация: 01.12.2010 Сообщений: 4,624 |
|
25.12.2010, 01:21 |
20 |
Снимаю шляпу перед Dimakart. Я этот код хотел оставить напоследок, как мега извращение. Теперь снова придётся придумывать что-то более извращённое.
0 |