In my Access database, I have a button on a form to open an external file.
Here is the code that I am using for that.
Private Sub btn_OpenFile_Click()
Dim a As New Shell32.Shell
Dim strPath As String
strPath = Me.Attachment
strPath = Chr(34) & strPath & Chr(34)
Call a.ShellExecute(Me.Attachment)
'Call CreateObject("Shell.Application").ShellExecute(strPath)
'MsgBox strPath
End Sub
The problem that I have is if I actually put in the value of the variable (Me.Attachment) it works fine and opens the program and the file.
For Example, If I put in Call a.ShellExecute("C:\Docs\Some File.pdf") it will open. But if I use the variable in it's place it won't open and tells me it cannot find the file. I have verified with the msgbox that it is receiving the correct information. I have tried to wrap it in quotes and have used the Chr(34) as shown above but nothing works.
How can I get that variable to work in the ShellExcute command?
I have looked through all the forums and it seems like everyone is using a string but not a variable. I don't want to use just the shell command as I don't want to track down all of the different apps people use to open different types of files. There will be different file types that will need to be opened and I thought this would be easier than it actually is.
Thank you for the help.
I'm pretty sure that ShellExecute expects a Variant parameter, not a String.
So try this:
Call a.ShellExecute(CVar(strPath))
or use a Variant variable from the start.
I had the same problem here.
Both of the following work for me:
Dim a As New Shell32.Shell
Dim strPath As String
strPath = Me.Attachment
Call a.ShellExecute(strPath)
Dim a As Shell
Dim strPath As String
strPath = Me.Attachment
Set a = CreateObject("Shell.Application")
a.ShellExecute strPath
Even referencing Attachment directly.
a.ShellExecute(Me.Attachment)
If I run the below code I get a different registry string then when I open RegEdit and view the key directly. I an running the code using MSACCESS 2016 starting it, and also RegEdit, in Admin mode. Is there some kind a cache storing the value.
When I look at the value using RegEdit I get:
"|FromSrtCut|||FALSE|0000000|CFI|Check-4-It.accde||C:\Prog...."
When I use the code below, I get :
"|FromSrtCut|||FALSE|0000000|CFI_INV|Check-4-It.accde||C:\Prog...."
enter code here
Dim WshShell, bKey
Dim strKeyPath As String
strKeyPath = "SOFTWARE\Corporate Data Design\Check-4-It"
Set WshShell = CreateObject("WScript.Shell")
Lg_strTemp = WshShell.RegRead("HKEY_CURRENT_USER\" & strKeyPath & "\LiveUpdate")
Debug.Print Lg_strTemp
I'm a beginner and new to Excel VBA, but I'm trying to automate some file sharing in FTP (WinSCP) by connecting to Excel and maybe creating a macro that will help. In FTP I went to Session > Generate Session URL/code > Script (script file) and the following code is there:
open ftp://myUsername:myPassword#theHostname/
# Your command 1
# Your command 2
exit
I'm assuming the open line would connect Excel to FTP. I'm referencing code from this site to put into the '# command' area: https://www.mrexcel.com/forum/excel-questions/261043-connecting-ftp-excel.html
open ftp://myUsername:myPassword#theHostname/
Option Explicit
Sub FtpTest()
MsgBox fnDownloadFile("ftp://yoursite", "username", "password", _
"The name of your file", _
"C:\The name of your file to save as")
End Sub
Function fnDownloadFile(ByVal strHostName As String, _
ByVal strUserName As String, _
ByVal strPassWord As String, _
ByVal strRemoteFileName As String, _
ByVal strLocalFileName As String) As String
'// Set a reference to: Microsoft Internet Transfer Control
'// This is the Msinet.ocx
Dim FTP As Inet 'As InetCtlsObjects.Inet
Set FTP = New Inet 'InetCtlsObjects.Inet
On Error GoTo Errh
With FTP
.URL = strHostName
.Protocol = 2
.UserName = strUserName
.Password = strPassWord
.Execute , "Get " + strRemoteFileName + " " + strLocalFileName
Do While .StillExecuting
DoEvents
Loop
fnDownloadFile = .ResponseInfo
End With
Xit:
Set FTP = Nothing
Exit Function
Errh:
fnDownloadFile = "Error:-" & Err.Description
Resume Xit
End Function
exit
I did as this site said to go to VBA Editor > Tools > reference and check off Microsoft Internet Control.
1) Am I using the code right? Did I place it in the right area (in the '# command' area)? And right now I put the entire code in a Command Button, but when I click it it just gives me a Syntax Error highlighting the first line:
Private Sub CommandButton1_Click())
2) Do I leave the Msgbox on the 3rd line as is to wait for user input or do I fill out with my username/password/hostname? (I'm not very good with functions in VBA yet) If I do fill it out in the code, what do I put for the "yoursite" value since I'm not accessing a website?
I'm sorry I'm so confused :( Any help would be great and thank you in advance!
I think that You should take a look here - Excel VBA reference for Inet objects
it is shown here how to add refernce for INet objects in vba. Furthermore when You just want to test if the code works, instead of assigning macro to button and so on, if You use "Function" then when You go to worksheet cell and start to type =fnDown ... You should see Your macro - there You can put Your function parameters. However first of all You have to take care of the reference to Inet.
This link might also be helpful: VBA Excel and FTP with MSINET.OCX and Inet type
I have a OSI PI Processbook file that I am using VBA on to open a new instance of PI Processbook. Basically I have a text element (Text35) on which I have a vba click event:
Private Sub Text35_Click(ByVal lvarX As Long, ByVal lvarY As Long)
Dim filePathAndName As String
Dim exeLocation As String
Dim PID As Variant
On Error GoTo errHandle
filePathAndName = "C:\Users\myuser\Desktop\TEST.PDI"
exeLocation = "C:\Program Files (x86)\PIPC\Procbook\Procbook.exe"
PID = Shell("""" & exeLocation & """", vbNormalFocus)
'How can I use the above process id to open a PDI file??
Exit Sub
errHandle:
End Sub
Basically I want to open the TEST.PDI file on my desktop in an entirely new copy of PI Processbook. I've tried pplication.Displays.Open(filePathAndName, True) but this opens my TEST.PDI into the same instance of Processbook, not a new application instance like I want.
Is there some Shell command or command like switch argument I can use to both open a new instance of the .exe and open up a file at the same time? I, at least, have the process id of the new instance stored in the "PID" variable, so I am thinking this might help.
I think I've stumbled upon a bug in Excel - I'd really like to verify it with someone else though.
The bug occurs when reading the Workbook.VBProject.HelpFile property when the workbook has been opened with the opening application's .AutomationSecurity property set to ForceDisable. In that case this string property returns a (probably) malformed Unicode string, which VBA in turn displays with question marks. Running StrConv(..., vbUnicode) on it makes it readable again, but it sometimes looses the last character this way; this might indicate that the unicode string is indeed malformed or such, and that VBA therefore tries to convert it first and fails.
Steps to reproduce this behaviour:
Create a new Excel workbook
Go to it's VBA project (Alt-F11)
Add a new code module and add some code to it (like e.g. Dim a As Long)
Enter the project's properties (menu Tools... properties)
Enter "description" as Project description and "abc.hlp" as Help file name
Save the workbook as a .xlsb or .xlsm
Close the workbook
Create a new Excel workbook
Go to it's VBA project (Alt-F11)
Add a fresh new code module
Paste the code below in it
Adjust the path on the 1st line so it points to the file you created above
Run the Test routine
The code to use:
Const csFilePath As String = "<path to your test workbook>"
Sub TestSecurity(testType As String, secondExcel As Application, security As MsoAutomationSecurity)
Dim theWorkbook As Workbook
secondExcel.AutomationSecurity = security
Set theWorkbook = secondExcel.Workbooks.Open(csFilePath)
Call MsgBox(testType & " - helpfile: " & theWorkbook.VBProject.HelpFile)
Call MsgBox(testType & " - helpfile converted: " & StrConv(theWorkbook.VBProject.HelpFile, vbUnicode))
Call MsgBox(testType & " - description: " & theWorkbook.VBProject.Description)
Call theWorkbook.Close(False)
End Sub
Sub Test()
Dim secondExcel As Excel.Application
Set secondExcel = New Excel.Application
Dim oldSecurity As MsoAutomationSecurity
oldSecurity = secondExcel.AutomationSecurity
Call TestSecurity("enabled macros", secondExcel, msoAutomationSecurityLow)
Call TestSecurity("disabled macros", secondExcel, msoAutomationSecurityForceDisable)
secondExcel.AutomationSecurity = oldSecurity
Call secondExcel.Quit
Set secondExcel = Nothing
End Sub
Conclusion when working from Excel 2010:
.Description is always readable, no matter what (so it's not like all string properties behave this way)
xlsb and xlsm files result in an unreadable .HelpFile only when macros are disabled
xls files result in an unreadable .HelpFile in all cases (!)
It might be even weirder than that, since I swear I once even saw the questionmarks-version pop up in the VBE GUI when looking at such a project's properties, though I'm unable to reproduce that now.
I realize this is an edge case if ever there was one (except for the .xls treatment though), so it might just have been overlooked by Microsoft's QA department, but for my current project I have to get this working properly and consistently across Excel versions and workbook formats...
Could anyone else test this as well to verify my Excel installation isn't hosed? Preferably also with another Excel version, to see if that makes a difference?
Hopefully this won't get to be a tumbleweed like some of my other posts here :) Maybe "Tumbleweed generator" might be a nice badge to add...
UPDATE
I've expanded the list of properties to test just to see what else I could find, and of all the VBProject's properties (BuildFileName, Description, Filename, HelpContextID, HelpFile, Mode, Name, Protection and Type) only .HelpFile has this problem of being mangled when macros are off.
UPDATE 2
Porting the sample code to Word 2010 and running that exhibits exactly the same behaviour - the .HelpFile property is malformed when macros are disabled. Seems like the code responsible for this is Office-wide, probably in a shared VBA library module (as was to be expected TBH).
UPDATE 3
Just tested it on Excel 2007 and 2003, and both contain this bug as well. I haven't got an Excel XP installation to test it out on, but I can safely say that this issue already has a long history :)
I've messed with the underlying binary representation of the strings in question, and found out that the .HelpFile string property indeed returns a malformed string.
The BSTR representation (underwater binary representation for VB(A) strings) returned by the .HelpFile property lists the string size in the 4 bytes in front of the string, but the following content is filled with the ASCII representation and not the Unicode (UTF16) representation as VBA expects.
Parsing the content of the BSTR returned and deciding for ourselves which format is most likely used fixes this issue in some circumstances. Another issue is unfortunately at play here as well: it only works for even-length strings... Odd-length strings get their last character chopped off, their BSTR size is reported one short, and the ASCII representation just doesn't include the last character either... In that case, the string cannot be recovered fully.
The following code is the example code in the question augmented with this fix. The same usage instructions apply to it as for the original sample code. The RecoverString function performs the needed magic to, well, recover the string ;) DumpMem returns a 50-byte memory dump of the string you pass to it; use this one to see how the memory is layed out exactly for the passed-in string.
Const csFilePath As String = "<path to your test workbook>"
Private Declare Sub CopyMemoryByte Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Byte, ByVal Source As Long, ByVal Length As Integer)
Private Declare Sub CopyMemoryWord Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Integer, ByVal Source As Long, ByVal Length As Integer)
Private Declare Sub CopyMemoryDWord Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Long, ByVal Source As Long, ByVal Length As Integer)
Function DumpMem(text As String) As String
Dim textAddress As LongPtr
textAddress = StrPtr(text)
Dim dump As String
Dim offset As Long
For offset = -4 To 50
Dim nextByte As Byte
Call CopyMemoryByte(nextByte, textAddress + offset, 1)
dump = dump & Right("00" & Hex(nextByte), 2) & " "
Next
DumpMem = dump
End Function
Function RecoverString(text As String) As String
Dim textAddress As LongPtr
textAddress = StrPtr(text)
If textAddress <> 0 Then
Dim textSize As Long
Call CopyMemoryDWord(textSize, textAddress - 4, 4)
Dim recovered As String
Dim foundNulls As Boolean
foundNulls = False
Dim offset As Long
For offset = 0 To textSize - 1
Dim nextByte As Byte
Call CopyMemoryByte(nextByte, textAddress + offset, 1)
recovered = recovered & Chr(CLng(nextByte) + IIf(nextByte < 0, &H80, 0))
If nextByte = 0 Then
foundNulls = True
End If
Next
Dim isNotUnicode As Boolean
isNotUnicode = isNotUnicode Mod 2 = 1
If foundNulls And Not isNotUnicode Then
recovered = ""
For offset = 0 To textSize - 1 Step 2
Dim nextWord As Integer
Call CopyMemoryWord(nextWord, textAddress + offset, 2)
recovered = recovered & ChrW(CLng(nextWord) + IIf(nextWord < 0, &H8000, 0))
Next
End If
End If
RecoverString = recovered
End Function
Sub TestSecurity(testType As String, secondExcel As Application, security As MsoAutomationSecurity)
Dim theWorkbook As Workbook
secondExcel.AutomationSecurity = security
Set theWorkbook = secondExcel.Workbooks.Open(csFilePath)
Call MsgBox(testType & " - helpfile: " & theWorkbook.VBProject.HelpFile & " - " & RecoverString(theWorkbook.VBProject.HelpFile))
Call MsgBox(testType & " - description: " & theWorkbook.VBProject.Description & " - " & RecoverString(theWorkbook.VBProject.Description))
Call theWorkbook.Close(False)
End Sub
Sub Test()
Dim secondExcel As Excel.Application
Set secondExcel = New Excel.Application
Dim oldSecurity As MsoAutomationSecurity
oldSecurity = secondExcel.AutomationSecurity
Call TestSecurity("disabled macros", secondExcel, msoAutomationSecurityForceDisable)
Call TestSecurity("enabled macros", secondExcel, msoAutomationSecurityLow)
secondExcel.AutomationSecurity = oldSecurity
Call secondExcel.Quit
Set secondExcel = Nothing
End Sub