как вставить часть массива VBA в диапазон Excel

#excel #vba

#excel #vba

Вопрос:

Возможно ли каким-либо образом перенести часть массива vba в диапазон Excel?

Мне нужно сделать что-то вроде этого:

 dim testday() as Variant
testday = Sheets("raw").Range("E745:BN745").Value
Sheets("raw").Range("E745:BN745").Value = ""
Sheets("Interface").Range("B4:E4") = testday(3, 4, 5, 6).Value
  

но это не работает … есть ли способ это исправить? Спасибо!

Комментарии:

1. Я предпочитаю Sheets("raw").Range("E745:BN745").ClearContents

2. Да, я обычно это делаю, но у меня они отформатированы условно, и я хочу сохранить это, но спасибо!

3. ClearContents не удаляет условное форматирование.

4. хм, хорошо, так что это отличается от .clear? спасибо за это!

Ответ №1:

Вы можете нарезать функцию Array using Index

 Sub Slicer()
 Dim testday() As Variant
 testday = Sheets("raw").Range("E745:BN745").Value
 Sheets("raw").Range("E745:BN745").Value = ""
 Sheets("Interface").Range("B4:E4")= Application.Index(testday, 1, Array(3, 4, 5, 6))
End Sub
  

Комментарии:

1. Это классный подход, и он превосходит мой по простоте ( 1). Вместо Array(3,4,5) я бы использовал Evaluate("TRANSPOSE(ROW(" amp; lStartIndex amp; ":" amp; lFinishIndex amp; "))") , который создает одномерный массив чисел, начинающийся со lStartIndex всего пути lFinishIndex , и может использоваться для динамического выделения произвольного длинного (непрерывного) массива.

2. Я не понимаю, как вы используете Index. Последним значением должен быть номер столбца, но вместо этого у вас есть массив? Как это работает?

Ответ №2:

Если массив, который вы хотите скопировать, является одномерным, и вам нужно скопировать смежные ячейки, вы можете использовать функцию CopyMemory:

 Option Explicit
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" _
    Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)


Sub test()
  Dim vArr(), vArr2()
  Dim lCnt As Long
  Dim lStartIndex As Long, lFinishIndex As Long, lLength As Long


  With Application
    vArr = .Transpose(.Transpose(Range("A1:R1").Value2))
  End With

  lStartIndex = 3
  lFinishIndex = 6
  lLength = lFinishIndex - lStartIndex   1

  ReDim vArr2(1 To lLength)

  CopyMemory vArr2(1), vArr(lStartIndex), lLength * 16

  For lCnt = LBound(vArr2) To UBound(vArr2)
    Debug.Print vArr2(lCnt)
  Next lCnt

  Range("A2").Resize(1, UBound(vArr2)).Value2 = vArr2

End Sub
  

Протестировано с первой строкой

 67.2    9   57.2    boo 52  64  76  39  48  50  28  54  96  29  98  25  68  19
  

ВОЗВРАТ

 57.2    boo 52  64
  

во второй строке.
Таким образом, ваш фрагмент изменится следующим образом

 dim testday(), testday2()
With Application  ' Value2 is faster than Value
  testday = .Transpose(.Transpose(Sheets("raw").Range("E745:BN745").Value2))
End With
Sheets("raw").Range("E745:BN745").ClearContents   ' Good suggestion by JFC
CopyMemory testday2(1), testday(3), 4 * 16        ' Variant = 16 Bytes
Sheets("Interface").Range("B4:E4").Value2 = testday2  ' I would do Resize instead
  

Надеюсь, это поможет!

Ответ №3:

Вы можете либо:

  • Используйте цикл, чтобы скопировать нужные вам значения в новый массив и записать их в свой диапазон. Если вы собираетесь делать это часто, вы можете написать повторно используемую функцию, которая делает это. Или,

  • Прочитайте только то, что вам нужно из вашего "raw" листа, и запишите это в свой диапазон, как показано ниже. Это, вероятно, самое простое решение в вашем конкретном случае.

 Dim testday() As Variant
testday = Sheets("raw").Range("G745:J745").Value ' only read what you need
Sheets("raw").Range("E745:BN745").ClearContents
Sheets("Interface").Range("B4:E4") = testday(3, 4, 5, 6).Value
  

Комментарии:

1. да, спасибо, но мне нужен тестовый день (7,8,9,10) для C4: E4 и т.д. итак, первый метод был бы лучше