быстрый способ скопировать форматирование в Excel - PullRequest
12 голосов
/ 23 декабря 2011

У меня есть два бита кода.Сначала стандартную копию вставьте из ячейки 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 и новый метод сравниваются, вот результаты или до и после

Новый код= 65 мсек

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

Старый код = 1296 мсек

'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 ]

15 голосов
/ 19 декабря 2014

Вы могли бы просто использовать Range("x1").value(11) что-то вроде ниже:

Sheets("Output").Range("$A$1:$A$500").value(11) =  Sheets(sheet_).Range("$A$1:$A$500").value(11)

диапазон имеет свойство по умолчанию "Значение" плюс значение может иметь 3 необязательных параметра 10,11,12.11 - это то, что вам нужно, чтобы оценить как значение, так и форматы.Он не использует буфер обмена, поэтому он быстрее.- Дургеш

6 голосов
/ 23 декабря 2011

Для меня ты не можешь. Но если это соответствует вашим потребностям, вы можете использовать форматирование со скоростью и , копируя весь диапазон сразу, а не зацикливаясь:

range("B2:B5002").Copy Destination:=Sheets("Output").Cells(startrow, 2)

И, кстати, вы можете создать произвольную строку диапазона, как Range("B2:B4, B6, B11:B18")


edit : если ваш источник "разреженный", вы не можете просто отформатировать место назначения сразу после завершения копирования?

3 голосов
/ 25 декабря 2011

Помните, что когда вы пишете:

MyArray = Range("A1:A5000")

вы действительно пишете

MyArray = Range("A1:A5000").Value

Вы также можете использовать имена:

MyArray = Names("MyWSTable").RefersToRange.Value

Но значение неединственное свойство Range.Я использовал:

MyArray = Range("A1:A5000").NumberFormat

Я сомневаюсь, что

MyArray = Range("A1:A5000").Font

будет работать, но я бы ожидал, что

MyArray = Range("A1:A5000").Font.Bold

будет работать.

Я делаюне знаю, в какие форматы вы хотите скопировать, поэтому вам придется попробовать.

Однако я должен добавить, что когда вы копируете и вставляете большой диапазон, это не намного медленнее, чем делать это через массив, как мывсе думал.

Опубликовать Редактировать информацию

Разместив вышесказанное, я попробовал по собственному совету.Мои эксперименты с копированием Font.Color и Font.Bold в массив не увенчались успехом.

Из следующих утверждений второе завершится неудачно с несовпадением типов:

  ValueArray = .Range("A1:T5000").Value
  ColourArray = .Range("A1:T5000").Font.Color

ValueArray должен иметь значениеТиповой вариант.Я попробовал оба варианта и long для ColourArray без успеха.

Я заполнил ColourArray значениями и попробовал следующее утверждение:

  .Range("A1:T5000").Font.Color = ColourArray

Весь диапазон будет окрашен в соответствии с первым элементом ColourArrayа затем Excel зациклился, занимая около 45% процессорного времени, пока я не завершил его с помощью диспетчера задач.

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

Я построил эксперимент, который широко отражает ваши требования.Я заполнил рабочий лист Time1 5000 строками по 20 ячеек, которые были выборочно отформатированы следующим образом: жирный, курсив, подчеркивание, нижний индекс, границы, красный, зеленый, синий, коричневый, желтый и серый - 80%.

В версии 1Я скопировал каждую седьмую ячейку из рабочей таблицы «Time1» в рабочую таблицу «Time2», используя копию.

В версии 2 я скопировал каждую седьмую ячейку из рабочей таблицы «Time1» в рабочую таблицу «Time2», скопировав значение ицвет через массив.

В версии 3 я копировал каждую седьмую ячейку с рабочего листа «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
0 голосов
/ 02 июля 2015

Просто используйте свойство NumberFormat после свойства Value: в этом примере диапазоны определяются с помощью переменных с именами ColLetter и SheetRow, и это происходит из цикла for-next с использованием целого числа i, но, конечно, они могут быть обычными определенными диапазонами.

TransferSheet.Range (ColLetter & SheetRow). Значение = Range (ColLetter & i). Значение TransferSheet.Range (ColLetter & SheetRow) .NumberFormat = Range (ColLetter & i) .NumberFormat

0 голосов
/ 23 декабря 2011

Работает ли:

Set Sheets("Output").Range("$A$1:$A$500") =  Sheets(sheet_).Range("$A$1:$A$500")

...?(Передо мной нет Excel, поэтому я не могу проверить.)

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