быстрый способ копирования форматирования в excel
у меня есть два бита кода. Сначала стандартная вставка копии из ячейки A в ячейку B
Sheets(sheet_).Cells(x, 1).Copy Destination:=Sheets("Output").Cells(startrow, 2)
Я могу сделать почти то же самое с помощью
Sheets("Output").Cells(startrow, 2) = Sheets(sheet_).Cells(x, 1)
теперь этот второй метод намного быстрее, избегая копирования в буфер обмена и вставки снова. Однако он не копирует через форматирование, как и первый метод. Вторая версия почти мгновенно копирует 500 строк, в то время как первый метод добавляет около 5 секунд к времени. И окончательная версия может быть выше 5000 ячейки.
поэтому мой вопрос может быть изменен на вторую строку, чтобы включить форматирование ячейки (в основном цвет шрифта), оставаясь быстрым.
В идеале я хотел бы иметь возможность копировать значения ячеек в массив / список вместе с форматированием шрифта, чтобы я мог выполнять дальнейшую сортировку и операции над ними, прежде чем я "вставлю" их обратно на рабочий лист..
поэтому моим идеальным решением было бы что-то вроде
for x = 0 to 5000
array(x) = Sheets(sheet_).Cells(x, 1) 'including formatting
next
for x = 0 to 5000
Sheets("Output").Cells(x, 1)
next
можно ли использовать строки RTF в VBA или это возможно только в vb.net и т. д.
ответ*
просто чтобы увидеть, как мой метод origianl и новый метод compar, вот результаты или до и после
новый код = 65msec
Sheets("Output").Cells(startrow, 2) = Sheets(sheet_).Cells(x, 1)
Sheets("Output").Range("B" & startrow).Font.ColorIndex = Sheets(sheet_).Range("A" & x).Font.ColorIndex 'copy font colour as well
старый код = 1296msec
'Sheets("Output").Cells(startrow, 2).Value = Sheets(sheet_).Cells(x, 1)
'Sheets(sheet_).Cells(x, 1).Copy
'Sheets("Output").Cells(startrow, 2).PasteSpecial (xlPasteFormats)
'Application.CutCopyMode = False
5 ответов
для меня, вы не можете. Но если это соответствует вашим потребностям, вы могли бы скорость и форматирование путем копирования всего диапазона сразу, вместо цикла:
range("B2:B5002").Copy Destination:=Sheets("Output").Cells(startrow, 2)
и, кстати, вы можете создать пользовательскую строку диапазона, например Range("B2:B4, B6, B11:B18")
редактировать: если ваш источник "разрежен", вы не можете просто отформатировать пункт назначения сразу после завершения копирования ?
вы могли бы просто использовать Range("x1").value(11)
что-то вроде ниже:
Sheets("Output").Range("$A:$A0").value(11) = Sheets(sheet_).Range("$A:$A0").value(11)
диапазон имеет свойство по умолчанию "значение" плюс значение может иметь 3 необязательных orguments 10,11,12. 11-это то, что вам нужно для преобразования значений и форматов. Он не использует буфер обмена, поэтому он быстрее.- Дургеш!--3-->
помните, что когда вы пишете:
MyArray = Range("A1:A5000")
ты действительно пишешь
MyArray = Range("A1:A5000").Value
вы также можете использовать имена:
MyArray = Names("MyWSTable").RefersToRange.Value
но значение не является единственным свойством диапазона. Я использовал:
MyArray = Range("A1:A5000").NumberFormat
сомневаюсь
MyArray = Range("A1:A5000").Font
будет работать, но я бы ожидал
MyArray = Range("A1:A5000").Font.Bold
на работу.
Я не знаю, какие форматы вы хотите скопировать, так что вам придется попробовать.
однако, я должен добавить когда вы копируете и вставляете большой диапазон, это не намного медленнее, чем делать это через массив, как мы все думали.
сообщение редактировать информацию
разместив выше, я попробовал по собственному совету. Мои эксперименты с копированием шрифта.Цвет и шрифт.Полужирный для массива не удалось.
из следующих утверждений второй потерпел бы неудачу с несоответствием типа:
ValueArray = .Range("A1:T5000").Value
ColourArray = .Range("A1:T5000").Font.Color
ValueArray должен иметь тип variant. Я пробовал оба вариант и длинный для ColourArray без успеха.
я заполнил ColourArray значениями и попробовал следующее утверждение:
.Range("A1:T5000").Font.Color = ColourArray
весь диапазон будет окрашен в соответствии с первым элементом ColourArray, а затем Excel зациклен, потребляя около 45% времени процессора, пока я не завершу его с помощью Диспетчера задач.
существует штраф времени, связанный с переключением между листами, но последние вопросы о продолжительности макроса вызвали все, чтобы пересмотреть наше убеждение, что работа с помощью массивов была значительно быстрее.
я построил эксперимент, который в целом отражает ваше требование. Я заполнил time1 листа 5000 строк из 20 ячеек, которые были выборочно отформатированы как: полужирный, курсив, подчеркивание, подстрочный, граничный, красный, зеленый, синий, коричневый, желтый и серый-80%.
С версией 1 я скопировал каждую 7-ю ячейку с листа " Time1 "на лист" Time2", используя copy.
С версии 2, я скопировал каждую 7-ю ячейку с листа " Time1 "на лист" Time2", скопировав значение и цвет через массив.
С версией 3 я скопировал каждую 7-ю ячейку с листа " Time1 "на лист" Time2", скопировав формулу и цвет через массив.
Версия 1 заняла в среднем 12,43 секунды, версия 2 заняла в среднем 1,47 секунды, а версия 3 заняла в среднем 1,83 секунды. Версия 1 скопировать формулу и форматирование, версия 2 копировать значения и цвет в то время как версия 3 скопировала формулы и цвет. С версиями 1 и 2 Вы можете добавить жирный и курсив, скажем, и все еще иметь некоторое время в руке. Однако я не уверен, что стоит беспокоиться, учитывая, что копирование 21,300 значений занимает всего 12 секунд.
** код для версии 1**
Я не думаю, что этот код включает в себя все, что нуждается в объяснении. Ответьте комментарием, Если я ошибаюсь, и я исправлю.
Sub SelectionCopyAndPaste()
Dim ColDestCrnt As Integer
Dim ColSrcCrnt As Integer
Dim NumSelect As Long
Dim RowDestCrnt As Integer
Dim RowSrcCrnt As Integer
Dim StartTime As Single
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
NumSelect = 1
ColDestCrnt = 1
RowDestCrnt = 1
With Sheets("Time2")
.Range("A1:T715").EntireRow.Delete
End With
StartTime = Timer
Do While True
ColSrcCrnt = (NumSelect Mod 20) + 1
RowSrcCrnt = (NumSelect - ColSrcCrnt) / 20 + 1
If RowSrcCrnt > 5000 Then
Exit Do
End If
Sheets("Time1").Cells(RowSrcCrnt, ColSrcCrnt).Copy _
Destination:=Sheets("Time2").Cells(RowDestCrnt, ColDestCrnt)
If ColDestCrnt = 20 Then
ColDestCrnt = 1
RowDestCrnt = RowDestCrnt + 1
Else
ColDestCrnt = ColDestCrnt + 1
End If
NumSelect = NumSelect + 7
Loop
Debug.Print Timer - StartTime
' Average 12.43 secs
Application.Calculation = xlCalculationAutomatic
End Sub
** код для Версии 2 и 3**
определение типа пользователя должно быть помещено перед любой подпрограммой в модуле. Код работает через исходный лист, копируя значения или формулы и цвета в следующий элемент массива. После завершения выбора он копирует собранную информацию на целевой лист. Это позволяет избежать переключения между листами больше, чем необходимо.
Type ValueDtl
Value As String
Colour As Long
End Type
Sub SelectionViaArray()
Dim ColDestCrnt As Integer
Dim ColSrcCrnt As Integer
Dim InxVLCrnt As Integer
Dim InxVLCrntMax As Integer
Dim NumSelect As Long
Dim RowDestCrnt As Integer
Dim RowSrcCrnt As Integer
Dim StartTime As Single
Dim ValueList() As ValueDtl
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' I have sized the array to more than I expect to require because ReDim
' Preserve is expensive. However, I will resize if I fill the array.
' For my experiment I know exactly how many elements I need but that
' might not be true for you.
ReDim ValueList(1 To 25000)
NumSelect = 1
ColDestCrnt = 1
RowDestCrnt = 1
InxVLCrntMax = 0 ' Last used element in ValueList.
With Sheets("Time2")
.Range("A1:T715").EntireRow.Delete
End With
StartTime = Timer
With Sheets("Time1")
Do While True
ColSrcCrnt = (NumSelect Mod 20) + 1
RowSrcCrnt = (NumSelect - ColSrcCrnt) / 20 + 1
If RowSrcCrnt > 5000 Then
Exit Do
End If
InxVLCrntMax = InxVLCrntMax + 1
If InxVLCrntMax > UBound(ValueList) Then
' Resize array if it has been filled
ReDim Preserve ValueList(1 To UBound(ValueList) + 1000)
End If
With .Cells(RowSrcCrnt, ColSrcCrnt)
ValueList(InxVLCrntMax).Value = .Value ' Version 2
ValueList(InxVLCrntMax).Value = .Formula ' Version 3
ValueList(InxVLCrntMax).Colour = .Font.Color
End With
NumSelect = NumSelect + 7
Loop
End With
With Sheets("Time2")
For InxVLCrnt = 1 To InxVLCrntMax
With .Cells(RowDestCrnt, ColDestCrnt)
.Value = ValueList(InxVLCrnt).Value ' Version 2
.Formula = ValueList(InxVLCrnt).Value ' Version 3
.Font.Color = ValueList(InxVLCrnt).Colour
End With
If ColDestCrnt = 20 Then
ColDestCrnt = 1
RowDestCrnt = RowDestCrnt + 1
Else
ColDestCrnt = ColDestCrnt + 1
End If
Next
End With
Debug.Print Timer - StartTime
' Version 2 average 1.47 secs
' Version 3 average 1.83 secs
Application.Calculation = xlCalculationAutomatic
End Sub
просто используйте свойство NumberFormat после свойства Value: В этом примере диапазоны определяются с помощью переменных, называемых ColLetter и SheetRow, и это происходит из цикла for-next с использованием целого числа i, но они могут быть обычными определенными диапазонами, конечно.
лист передачи.Ряд (ColLetter & SheetRow).Value = диапазон (ColLetter & i).Значение TransferSheet.Ряд (ColLetter & SheetRow).NumberFormat = диапазон (ColLetter & i).NumberFormat
тут:
Set Sheets("Output").Range("$A:$A0") = Sheets(sheet_).Range("$A:$A0")
...работа? (У меня нет Excel передо мной, поэтому я не могу проверить.)