2012-02-28 28 views
5

Quiero establecer el valor para las celdas por VBA. He buscado en Google y ver algunos de resolución:No puedo VBA escribir datos en celdas en Excel 2007/2010 dentro de una función

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

Con este tipo de código, que sólo puede leer datos de la celda A1, pero no puedo establecer un nuevo valor a la misma.

actualización

El código para establecer valor de la celda A1 se pone dentro de un Function de la siguiente manera.

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

En la celda B2, configuré =abb() y presioné enter. Obtengo #VALOR pero no pasa nada en A1.

Poniendo este código en una macro, funciona.

Mi pregunta es, ¿cómo hacer A1 tienen valores dentro de una función?

+2

Tiene dos opciones. Puede ejecutarlo como una subrutina o utilizar la solución temporal del temporizador UDF desde http://stackoverflow.com/q/8520732/641067. El primero es más fácil. – brettdj

+1

Si desea una función, devuelva algo en A1, entonces la llamada a la función debe ingresarse en A1. Esa es la forma en que Excel trabaja. –

+0

¿Por qué no atrapa este cambio en B2 con un evento de cambio de hoja y luego rellena A1? Desde su código, la función no se actualizará ya que no tiene ningún argumento. – brettdj

Respuesta

10

Desde su comentario anterior que quería probar este enfoque

Si introduce
=abb()
en cualquier célula

A continuación, la celda A1 de esa hoja de Wil se establece en 12333

Esto es la línea para actualizar para seleccionar la celda para actualizar y para colocar un valor en ella
Range("A1").Value = 122333

De I don't want my Excel Add-In to return an array (instead I need a UDF to change other cells)

Estoy volver a colocar esta pieza de la magia de Kevin Jones aka Zorvek ya que se encuentra behind the EE Paywall (enlace adjunto si alguien tiene acceso)

Mientras Excel prohíbe estrictamente una UDF de cambiar cualquier célula, hoja de cálculo, o propiedades del libro de trabajo, hay una forma de efectuar tales cambios cuando se llama a una UDF usando un temporizador de Windows y un temporizador Application.OnTime en la secuencia . El temporizador de Windows debe utilizarse dentro de la UDF porque Excel ignora cualquier llamada Application.OnTime dentro de una UDF. Pero, debido a el temporizador de Windows tiene limitaciones (Excel se cerrará instantáneamente si un temporizador de Windows intenta ejecutar código VBA si se está editando una celda o está abierto un cuadro de diálogo ), se usa solo para programar un temporizador Application.OnTime , un temporizador seguro que Excel solo permite que se active si una celda está sin editar y no hay diálogos abiertos.

El código de ejemplo siguiente muestra cómo se inicia un temporizador de Windows desde dentro de una UDF, el uso de esa rutina de temporizador para iniciar un temporizador Application.OnTime, y la forma de transmitir la información sólo se conoce a la UDF a la posterior temporizador -ejecuciones ejecutadas. El código a continuación debe ser colocado en un módulo regular.

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 
+2

+1 ¡Esto es demasiado feo para no votar! –

+0

@ Jean-FrançoisCorbett Estoy de acuerdo. Estaba asombrado de que alguien pudiera concebir y luego ejecutar esto. Aunque muestra el peligro de "no se puede hacer". – brettdj

+2

+1 LOL. ¡De acuerdo con JFC! –

0

que debería funcionar - probar este

  1. Abra una nueva hoja de Excel
  2. Crear una nueva macro
  3. Añadir esta Sheets("Sheet1").Range("A1").Value2 = "value"

se puede utilizar tanto .Value y .Value2, asegúrese que el nombre de la hoja es correcto

+0

cuando depuro, obtuve una parada en la declaración "Hojas (" Hoja1 "). Rango (" A1 "). Valor2 =". No sé por qué? – Davuz

+0

¿Cuál es el nombre de la hoja, si no es 'Sheet1' entonces vendrá el problema ... intente esto en cambio' Sheets (1) .Range ("A1"). Value', el índice ayudará a encontrar la hoja correcta Una vez que esto funcione, puede reemplazar el índice con el nombre de la hoja actual. –

+0

@Davuz: ¿Qué quiere decir con "tengo que parar"? ¿Lanza algún error? ¿El libro de trabajo está abierto solo? – shahkalpesh

5

No puede cambiar la celda A1 con una función en B2.

visita: Description of limitations of custom functions in Excel . El texto incluye:.

"Una función definida por el usuario llamado por una fórmula en una celda de la hoja no puede cambiar el entorno de Microsoft Excel Esto significa que esa función no puede hacer cualquiera de los siguientes:

  • Insertar , eliminar o formato de celdas en la hoja de cálculo.
  • Cambiar el valor de otra celda. [Mi resaltado]
  • mover, renombrar, borrar o añadir hojas a un libro.
  • Cambie cualquiera del medio ambiente o funciones, como el modo de cálculo o las vistas de pantalla.
  • Agregue nombres a un libro de trabajo.
  • Establecer las propiedades o ejecutar la mayoría de los métodos ".

¿Por qué desea cambiar la celda A1 de esta manera? Explique su objetivo y tal vez alguien pueda ayudar.

+0

En realidad se puede hacer, pero es complejo. ver http://stackoverflow.com/q/8520732/641067 – brettdj

+1

@brettdj. Me perdí esta pregunta y tu respuesta que es muy interesante. Sin embargo, esta no es una técnica que quisiera recomendar a un novato. Creo que este es un caso en el que el interrogador nos dice cómo cree que se puede resolver su problema en lugar de cuál es su problema. Quiero saber por qué quiere una función en B2 para cambiar A1? –

+0

@TonyDallimore quiero valor de caché. Supongo que calculo la suma de muchas celdas 'Rango (B1: B1000)', quiero almacenar en caché este valor de suma a A1 (o cualquier celda), así que vuelvo a abrir el archivo de Excel, Excel no necesita recalcular – Davuz

1

Si desea modificar dos células con una fórmula, es posible que desee considerar devuelve una matriz de su función He aquí un ejemplo:.

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

Seleccione las celdas A2 a B2.Escriba =abb() y presione ShiftCtrlIngrese para especificar que se trata de una fórmula de matriz. Esta fórmula luego modifica ambas celdas (A2 y B2) al mismo tiempo.

Quizás puedas personalizar esto para hacer lo que quieras.

Cuestiones relacionadas