Не удается VBA записать данные в ячейки в Excel 2007/2010 внутри функции - PullRequest
6 голосов
/ 28 февраля 2012

Я хочу установить значение для ячеек по VBA.Я гуглил и вижу какое-то разрешение:

Sheets("SheetName").Range("A1").value = someValue
Sheets("SheetName").Cells(1,1).value = someValue

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

Обновление

Код для установки значения ячейки A1 помещается в Function, как показано ниже.

Function abb()
    Sheets("SheetName").Range("A1").value = 122333
    abb = 'any thing'
End Function

В ячейке B2, Iустановите =abb() и нажмите ввод.Я получаю # ЗНАЧЕНИЕ, но в A1 ничего не происходит.

Помещая этот код в макрос, он работает.

У меня вопрос, как сделать так, чтобы A1 имел значения внутри функции?

Ответы [ 4 ]

13 голосов
/ 29 февраля 2012

Из вашего комментария выше вы хотели попробовать этот подход

Если вы введете
=abb()
в любую ячейку

Тогда ячейка A1 этого листа будет установлена ​​в12333

Это строка для обновления, чтобы выбрать ячейку для обновления и поместить в нее значение
Range("A1").Value = 122333

С Мне не нужен мой ExcelНадстройка для возврата массива (вместо этого мне нужен UDF для изменения других ячеек)

Я перенесу этот кусок магии из Кевин Джонс, он же Зорвек сидит за EE Paywall (ссылка прикреплена, если у кого-то есть доступ)

В то время как Excel строго запрещает UDF изменять любые свойства ячейки, листа или книги, существует способ осуществить такие изменениякогда UDF вызывается с использованием таймера Windows и таймера Application.OnTime по очереди.Таймер Windows должен использоваться в UDF, потому что Excel игнорирует любые вызовы Application.OnTime внутри UDF.Но, поскольку у таймера Windows есть ограничения (Excel будет мгновенно завершать работу, если таймер Windows пытается запустить код VBA, если ячейка редактируется или открывается диалоговое окно), он используется только для планирования таймера Application.OnTime, безопасного таймера.какой Excel разрешает запуск только в том случае, если ячейка не редактируется и диалоговые окна не открыты.

В приведенном ниже примере кода показано, как запустить таймер Windows из UDF, как использовать эту процедуру таймера для запускатаймер Application.OnTime и способ передачи информации, известной только UDF, в последующие подпрограммы, выполняемые таймером.Код ниже должен быть помещен в обычный модуль.

Declare Function SetTimer Lib "user32" ( _
      ByVal HWnd As Long, _
      ByVal nIDEvent As Long, _
      ByVal uElapse As Long, _
      ByVal lpTimerFunc As Long _
   ) As Long

Private Declare Function KillTimer Lib "user32" ( _
      ByVal HWnd As Long, _
      ByVal nIDEvent As Long _
   ) As Long

Private mCalculatedCells As Collection
Private mWindowsTimerID As Long
Private mApplicationTimerTime As Date

Public Function abb()

' This is a UDF that returns the sum of two numbers and starts a windows timer
' that starts a second Appliction.OnTime timer that performs activities not
' allowed in a UDF. Do not make this UDF volatile, pass any volatile functions
' to it, or pass any cells containing volatile formulas/functions or
' uncontrolled looping will start.

   abb = "Whatever you want"

   ' Cache the caller's reference so it can be dealt with in a non-UDF routine
   If mCalculatedCells Is Nothing Then Set mCalculatedCells = New Collection
   On Error Resume Next
   mCalculatedCells.Add Application.Caller, Application.Caller.Address
   On Error GoTo 0

   ' Setting/resetting the timer should be the last action taken in the UDF
   If mWindowsTimerID <> 0 Then KillTimer 0&, mWindowsTimerID
   mWindowsTimerID = SetTimer(0&, 0&, 1, AddressOf AfterUDFRoutine1)

End Function

Public Sub AfterUDFRoutine1()

' This is the first of two timer routines. This one is called by the Windows
' timer. Since a Windows timer cannot run code if a cell is being edited or a
' dialog is open this routine schedules a second safe timer using
' Application.OnTime which is ignored in a UDF.

   ' Stop the Windows timer
   On Error Resume Next
   KillTimer 0&, mWindowsTimerID
   On Error GoTo 0
   mWindowsTimerID = 0

   ' Cancel any previous OnTime timers
   If mApplicationTimerTime <> 0 Then
      On Error Resume Next
      Application.OnTime mApplicationTimerTime, "AfterUDFRoutine2", , False
      On Error GoTo 0
   End If

   ' Schedule timer
   mApplicationTimerTime = Now
   Application.OnTime mApplicationTimerTime, "AfterUDFRoutine2"

End Sub

Public Sub AfterUDFRoutine2()

' This is the second of two timer routines. Because this timer routine is
' triggered by Application.OnTime it is safe, i.e., Excel will not allow the
' timer to fire unless the environment is safe (no open model dialogs or cell
' being edited).

   Dim Cell As Range

   ' Do tasks not allowed in a UDF...
   Application.ScreenUpdating = False
   Application.Calculation = xlCalculationManual
   Do While mCalculatedCells.Count > 0
      Set Cell = mCalculatedCells(1)
      mCalculatedCells.Remove 1
      Range("A1").Value = 122333
   Loop
   Application.Calculation = xlCalculationAutomatic
   Application.ScreenUpdating = True
   End Sub
6 голосов
/ 28 февраля 2012

Вы не можете изменить ячейку A1 с функцией в B2.

Визит: Описание ограничений пользовательских функций в Excel . Текст включает в себя:

"Пользовательская функция, вызываемая формулой в ячейке рабочего листа, не может изменить среду Microsoft Excel. Это означает, что такая функция не может выполнять одно из следующих действий:

  • Вставка, удаление или форматирование ячеек в электронной таблице.
  • Изменить значение другой ячейки. [Мое выделение]
  • Перемещение, переименование, удаление или добавление листов в рабочую книгу.
  • Изменение любых параметров среды, таких как режим расчета или виды экрана.
  • Добавление имен в рабочую книгу.
  • Установить свойства или выполнить большинство методов. "

Почему вы хотите изменить ячейку A1 таким образом? Объясните свою цель, и, возможно, кто-то может помочь.

2 голосов
/ 28 февраля 2012

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

Function abb()
    Dim arr As Variant
    ReDim arr(1 To 2)
    arr(1) = "aardvark"
    arr(2) = "bee"
    abb = arr
End Function

Выберите ячейки от А2 до В2. Введите =abb() и нажмите Shift Ctrl Введите , чтобы указать, что это формула массива. Затем эта формула изменяет обе ячейки (A2 и B2) одновременно.

Возможно, вы можете настроить это, чтобы делать то, что вы хотите.

0 голосов
/ 28 февраля 2012

это должно работать - попробуйте это

  1. Открыть новый лист Excel
  2. Создать новый макрос
  3. Добавить это Sheets("Sheet1").Range("A1").Value2 = "value"

Вы можете использовать как .Value, так и .Value2, убедитесь, что имя листа указано правильно.

...