10

I use:

retVal = Shell("program.EXE " & filename, vbNormalFocus)

To execute a program need for my excel spreadsheet.

Is it possible to embed the EXE file in the excel file itself?

And how would I execute it then?

Ideias:

1 - Some kind of a bin2str function to turn binary to string (so I can store it in the program as a variable and a str2bin (the oposite)

2 - I read something about OLE Control (that you can embed it there), but I really don't know where to start on this one

Community
  • 1
  • 1
  • No downvote. Can't you give the external program with the Excel sheet without embedding it in. – Mudassir Nov 28 '11 at 13:05
  • Bad behaved user I have to deal with. And I know they wont delete the xls files. Not so sure about any other files I put there. Also easier to distribute –  Nov 28 '11 at 13:11
  • 3
    You can check for files your program is depending on, and if you don't find any of the files, then inform the user. They have to keep all the components if they wanna use your program. – Mudassir Nov 28 '11 at 13:13

3 Answers3

13

Here's an outline solution that avoids OLE:

  1. Create a hidden worksheet.
  2. Use a base 64 encoded to convert the exe to text.
  3. Store that text in worksheet cells on the hidden worksheet. Since there is a limit on the number of characters in a cell (32,767) you will need to break the string into chunks.

Obviously you'll need to reverse this procedure when you want to save and execute the exe file.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
4

You can do this by using: Insert > Object and then selecting 'Create from File'.

To add it to your sheet using VBA:

Dim o As OLEObject
Set o = ActiveSheet.OLEObjects.Add(Filename:="C:\program.exe")

Then this is the command to execute program.exe:

o.Verb Verb:=xlPrimary

Not sure how to pass arguments to it, however (e.g. your filename).

Note: Untrusted applications prompt a warning when you run them.

Jean-François Corbett
  • 37,420
  • 30
  • 139
  • 188
0

Adding code to @DavidHeffernan's reply (base64 method):

  1. Insert base64.
#Linux
cat input.exe | base64 > output.txt

# Windows
certutil -encodehex -f "input.exe" "output.txt" 0x40000001 1>null
# Python
import base64
with open("input.exe", "rb") as file_in:
    with open("output.txt", "wb") as file_out:
        file_out.write(base64.b64encode(file_in.read()))

The current version of Microsoft Excel automatically splits long text into parts, so open it in Notepad and insert into cell A1. Example:

Excel with embedded base64

In my example, the text is split into 5 parts.

  1. Add the Developer tab.

https://support.microsoft.com/en-us/office/show-the-developer-tab-e1192344-5e56-4d45-931b-e5fd9bea2d45

  1. Create a script.

Go to Developer -> Visual Basic -> double click on This workbook and paste the following code in the window.

Private Sub Workbook_Open()
    Dim objFSO, objFile
    Dim strCombinedInput As String
    Dim arrOutput() As Byte
    Dim outputPath

    ' Initialize FileSystemObject
    Set objFSO = CreateObject("Scripting.FileSystemObject")

    ' Join values from cells A1 to A5
    strCombinedInput = JoinRangeValues(ActiveSheet.Range("A1:A5")) ' EDIT TO YOUR RANGE
    
    ' Decode Base64
    arrOutput = DecodeBase64(strCombinedInput)

    ' Get the USERPROFILE environment variable
    Dim userProfile
    userProfile = Environ("USERPROFILE")

    ' Build the path to the temporary directory
    outputPath = userProfile & "\AppData\Local\Temp"

    ' Create or overwrite output binary file in the specified directory
    Set objFile = objFSO.CreateTextFile(outputPath & "\output.exe", True)
    objFile.Write BinaryToString(arrOutput)
    objFile.Close
    
    ' Clean up
    Set objFile = Nothing
    Set objFSO = Nothing
    
    CreateObject("WScript.Shell").Exec (outputPath & "./output.exe")
End Sub

Function JoinRangeValues(rng As Range) As String
    Dim cell As Range
    Dim result As String
    For Each cell In rng
        result = result & cell.Value & vbCrLf
    Next cell
    JoinRangeValues = result
End Function

Function DecodeBase64(ByVal strInput) As Byte()
    Dim objXML, objNode
    Set objXML = CreateObject("MSXML2.DOMDocument.6.0")
    Set objNode = objXML.createElement("b64")
    
    ' Decode Base64
    objNode.DataType = "bin.base64"
    objNode.Text = strInput
    DecodeBase64 = objNode.NodeTypedValue
    
    ' Clean up
    Set objNode = Nothing
    Set objXML = Nothing
End Function

Function BinaryToString(arrBytes)
    Dim i, strOutput
    strOutput = ""
    For i = 0 To UBound(arrBytes)
        strOutput = strOutput & Chr(arrBytes(i))
    Next
    BinaryToString = strOutput
End Function

Make sure you have edited the cell range.

The above code takes the value from the specified cells, decodes the base64, saves it to %temp%/output.exe and executes it. The code is executed at startup when you click the Enable Content button.

Jurakin
  • 832
  • 1
  • 5
  • 19