Я хочу взять значения из столбца J, умножить их на -1 и поместить в столбец I. У меня есть эта строка:
Range("I2:I9").Value = "=J2*-1"
который помещает формулу в столбец I и вычисляет значение, но мне просто нужно значение.
В качестве альтернативы, если значения в столбце J можно умножить на -1, это тоже будет работать.
Что я могу сделать?
Попробуйте это - только что проверил, у меня работает:
Sub InvertNum()
Dim ws As Worksheet
Dim rngSource As Range, rngTarget As Range
Set ws = Application.ActiveSheet
Set rngSource = ws.Range("J2:J9")
Set rngTarget = ws.Range("I2:I9")
rngTarget.Value = ws.Evaluate("-1 * " & rngSource.Address)
End Sub
Чтобы объявить rngSource
диапазоном, вы должны использовать Dim rngSource As Range, rngTarget As Range
. Строка arr = rngSource.Value
лишняя. Если rngSource
имеет одну область и более одной ячейки (имеет обе), rngSource.Value
в правой части выражения означает, что это двумерный массив, основанный на единице. В строке ниже все, что содержалось в динамическом массиве arr
, перезаписывается независимо от размера. Опять же, правая часть выражения представляет собой массив. Таким образом, вы можете потерять переменную arr
и упростить ее с помощью rngTarget.Value = Application.Evaluate("-1 * " & rngSource.Address
.
Поскольку у вас есть правильная ссылка IMO на рабочий лист (обычно сокращается с помощью Set ws = ActiveSheet
), вам следует использовать более безопасный метод Worksheet.Evaluate, т. е. ws.Evaluate("-1 * " & rngSource.Address)
, поскольку, когда вы передаете адрес (строку), как Excel узнает, на каком листе его искать? С Application.Evaluate
это будет ActiveSheet
. Теперь представьте следующее: вы решили, что лист Sheet1
находится в книге, содержащей этот код, и вы ссылаетесь на лист с помощью Set ws = ThisWorkbook.Sheets("Sheet1")
. Если лист не является активным, код завершится ошибкой.
Отличные советы - спасибо! Отредактировано, чтобы включить. Я забыл As Range
на rngSource
— глупая ошибка. Первоначально я использовал arr
для хранения исходных значений и выполнения вычислений, думая, что это будет быстрее, чем прямая работа с диапазоном (особенно в случае, когда rngSource
намного больше 7 ячеек), но на самом деле я не уверен, что происходит под обложки с помощью rngTarget.Value = ws.Evaluate(...)
и действительно ли это медленнее.
Игнорируя избыточную строку, в вашей предыдущей версии вы берете массив ws.Evaluate("-1 * " & rngSource.Address)
, занимающий некоторую память, и копируете его в другой массив arr
, который занимает еще немного памяти, прежде чем копировать его в целевой диапазон. В этой версии вы берете массив и копируете его в диапазон. Вывод очевиден. Конечно, вы можете не заметить разницы, даже если строк тысячи или больше.
Простой метод «Оценить» может быть [I2:I9] = [-J2:J9]
Этот код инвертирует сигналы на месте:
Sub invertSignal()
Dim rng As Range ' Declares rng as Range
Set rng = Application.ActiveSheet.Range("J2:J9") ' sets rng to desired range
' Loops for each cell in range, multiplying values by -1
For Each cell In rng
cell.Value = cell.Value * -1
Next
End Sub
Еще один способ сделать это на месте. Вам нужна одна пустая ячейка, пусть это будет M1
:
Sub Inversion()
With Range("M1")
.Value = -1
.Copy
Range("J2:J9").PasteSpecial Paste:=xlPasteValues, Operation:=xlMultiply
.ClearContents
End With
End Sub
Попробуйте «обучающий»
With Range("I2:I9"): .Formula = "=J2*-1": .Value = .Value: End With
или более эффективный (динамичный)With Range("I2:I9"): .Value = .Worksheet.Evaluate(.EntireRow.Columns("J").Address & "*-1"): End With
. Чтобы скопировать на место (переключить +/-), вы можете использоватьWith Range("J2:J9"): .Value = .Worksheet.Evaluate(.Address & "*-1"): End With
.