visual variable ultima seleccionar rango para hoja hasta datos con codigos codigo celda vba dll ms-word word-vba

variable - Establecer de manera programada la ruta de búsqueda de DLL en la macro de VBA



vba excel (4)

Hay otra solución realmente muy fea, pero este blogger lo descubrió, y no puedo entender de otra manera:

http://blogs.msdn.com/pranavwagh/archive/2006/08/30/How-To-Load-Win32-dlls-Dynamically-In-VBA.aspx

Básicamente, usted escribe un procedimiento que crea un módulo de código en VBA durante el tiempo de ejecución. Este módulo debe crear una referencia al dll y debe crear una función ficticia (o procedimiento) como parte de este módulo que llama al dll. Luego, desde su código, usa Application.Run (dummyfunction (), arg1, arg2 ...). Esto es necesario porque, de lo contrario, el proyecto no compilará porque la función ficticia aún no es una función.

Notarás en su código que usa InputBox () para obtener la ubicación del .dll, pero obviamente podrías obtener la ubicación de un rango en la hoja de cálculo. El siguiente fragmento de código puede ser útil.

Dim cm As CodeModule Dim vbc As VBComponent Set cm = Application.VBE.ActiveVBProject.VBComponents.Add(vbext_ct_StdModule).CodeModule cm.AddFromString (decString & funcString) cm.Name = "MyNewModule" Set vbc = cm.Parent Application.VBE.ActiveVBProject.VBComponents.Remove vbc

''decString'' y ''funcString'' eran solo cadenas que construí como su ''ss''. El fragmento muestra cómo puede cambiar el nombre del módulo de código para que pueda eliminarlo más adelante si es necesario. Obviamente, esto simplemente lo elimina justo después de que se creó, y es probable que no quieras hacerlo, pero al menos te muestra cómo se haría.

Habiendo dicho todo eso, en su mayoría solo escribimos .exe ahora y pagamos. Si necesita que VBA espere a que finalice el shell, también hay soluciones para ese problema.

El problema

  • Tengo una plantilla de palabra que usa la declaración Declare de VBA para vincular a un archivo DLL, cuya ruta se puede determinar dentro de la macro de VBA
  • Quiero desplegar esto en el directorio% APPDATA% / Microsoft / Word / STARTUP de los usuarios
  • NO QUIERO cambiar permanentemente la variable de entorno PATH del usuario (temporalmente estaría bien, pero parece que no funciona, ya que no se actualizan hasta que se reinicie la aplicación)

Intento de solución

Intenté agregar dinámicamente el código con las instrucciones Declare utilizando ThisDocument.VBProject.CodeModule.AddFromString(code) que funciona al cargar la plantilla desde un directorio normal, pero cuando la plantilla está dentro de Word / STARTUP, da el siguiente error:

Error en tiempo de ejecución ''50289'':

No se puede realizar operación ya que el proyecto está protegido.

Y establecer la clave de registro "HKEY ___ LOCAL_MACHINE / Software / Microsoft / Office / 11.0 / Word / Security / AccessVBOM" en 1 no soluciona esto cuando la plantilla está en Word / STARTUP

Realmente estoy luchando por encontrar una solución. Si alguien sabe una manera de hacer esto, sería genial.


Puede usar LoadLibrary api.

Por ejemplo, en mis proyectos, el código se ve así:

If LibraryLoaded() Then Call MyFunc ... End If Public Function LibraryLoaded() As Boolean Static IsLoaded As Boolean Static TriedToLoadAlready As Boolean If TriedToLoadAlready Then LibraryLoaded = IsLoaded Exit Function End If Dim path As String path = VBAProject.ThisWorkbook.path path = Left(path, InStrRev(path, "/") - 1) IsLoaded = LoadLibrary(path & "/bin/" & cLibraryName) TriedToLoadAlready = True LibraryLoaded = IsLoaded End Function


Esto es lo que terminé haciendo, usando la metodología de Pranav Wagh vinculada anteriormente y el código del sitio de C Pearson ( http://www.cpearson.com/excel/vbe.aspx ). Este código solicita al usuario que seleccione la ruta al archivo dll utilizando una ventana Abrir archivo, crea un nuevo módulo con una función de declaración con la ruta ingresada y una función para ejecutar un protocolo de enlace con la dll. La función creada a propósito en el dll devuelve un 1 si tiene éxito:

Public rtn As Integer Sub LinkToDll() Dim path As String, default As String MsgBox "Select Geo_DLL.dll file from next window" With Application.FileDialog(msoFileDialogOpen) .AllowMultiSelect = False .Title = "Select Geo_DLL.dll file" If .Show = True Then path = .SelectedItems(1) End If End With ''Add a module Dim VBProj As VBIDE.VBProject Dim VBComp As VBIDE.VBComponent Set VBProj = ActiveWorkbook.VBProject Set VBComp = VBProj.VBComponents.Add(vbext_ct_StdModule) VBComp.Name = "LinkModule" ''Add procedure to module Dim CodeMod As VBIDE.CodeModule Dim LineNum As Long Set VBComp = VBProj.VBComponents("LinkModule") Set CodeMod = VBComp.CodeModule With CodeMod LineNum = .CountOfLines + 1 .InsertLines LineNum, "Declare Function RegDll Lib " & Chr(34) & path & Chr(34) & " (ByRef rtn As Integer)" LineNum = LineNum + 1 .InsertLines LineNum, "Sub runthisfunc(rtn)" LineNum = LineNum + 1 .InsertLines LineNum, "On Error Resume Next" LineNum = LineNum + 1 .InsertLines LineNum, "rtn = 0" LineNum = LineNum + 1 .InsertLines LineNum, "RegDll rtn" LineNum = LineNum + 1 .InsertLines LineNum, "If rtn = 1 Then MsgBox (" & Chr(34) & "DLL linked" & Chr(34) & ")" LineNum = LineNum + 1 .InsertLines LineNum, "If rtn = 0 Then MsgBox (" & Chr(34) & "DLL not found" & Chr(34) & ")" LineNum = LineNum + 1 .InsertLines LineNum, "End Sub" End With ''This is what CodeMod.InsertLines is writing: ''-------------------------------------------- ''Declare Function RegDll Lib "C:/path/Geo_DLL.dll" (ByRef rtn As Integer) ''Sub runthisfunc(rtn) ''On Error Resume Next ''rtn = 0 ''RegDll rtn ''If rtn = 1 Then MsgBox ("DLL Linked") ''If rtn = 0 Then MsgBox (DLL not found") ''End Sub Application.Run "runthisfunc", rtn ''Delete Module VBProj.VBComponents.Remove VBComp End Sub

Sin embargo, una vez que convertí el libro de trabajo (xlsm) en un complemento (xlam) encontré que Excel no permitiría que la macro creara nuevos módulos para que mi LinkToDll no funcionara. La solución era volver a poner la función de declaración en LinkToDll con el nombre del archivo dll ("Geo_DLL.dll") como Lib junto con el sub runthisfunc. Encontré que hacer que el usuario simplemente seleccionara el archivo dll a través de la ventana Abrir archivo fue suficiente para apuntar a Excel al dll incluso con el nombre del archivo en la parte Lib de la declaración Declare Function.

Chris


Francamente, no sé cuál es el problema con el uso de todas esas inyecciones de código VBA, generación de ensamblaje para LoadLibrary () llamadas, etc. técnicas que he visto utilizar para esta simple tarea. En mi proyecto uso un código simple para cargar dll desde la misma ubicación que el libro de trabajo, así:

Declare Function MyFunc Lib "MyDll.dll" (....) As ... Sub Test() .... ChDir ActiveWorkbook.Path ... = MyFunc(....) End Sub

Excel 2003 al menos, no tiene problemas para cargar el dll desde la ruta actual, establezca ChDir en cualquier ruta que tenga su DLL. Es posible que también deba cambiar su unidad actual, que está separada de la ruta actual. Tienes que hacerlo solo una vez, antes de la primera llamada de función, después de que la DLL permanezca conectada sin importar dónde esté tu ruta actual, por lo que puedes hacerlo una vez en workbook_open y no molestarte sobre la ruta más adelante. Proporciono una función ficticia vacía en la DLL solo para este pupose. No creo que MS Word sea diferente en esto.

Private Declare Sub Dummy Lib "MyDLL.dll" () Private Sub Workbook_Open() ChDrive Left$(Me.Path, 1) ChDir Me.Path Dummy End Sub