There IS such a thing as a Macro that does a RunCode, something you could select manually if you so desired. The code has to be a FUNCTION, not a subroutine, but you can diddle up something from the function that calls the real subroutine and just use the function as a shell. See, for example, command-line switch /X:macroname, which would allow you to execute a macro when launching Access. You can edit your launcher icon to include this option.
One can get pedantic and argue that the act of selecting and running the macro triggers a "macro run" event, but let's not split hairs. No matter how the macro gets run, it can call a function via RunCode.
The problem that you need to understand here is that you could compare Access VBA to some other VB, such as VisualBasic (from Visual Studio or purchased as a separate product). If you do, you would discover something really different between the two VB environments. VB allows you to create a MAIN segment that is your application's main sequencer. For VBA, MSAccess.EXE is the main sequencer and you can't build another MAIN segment. (Can't have two main segments in one image - has to do with the required uniqueness of the startup entry point.)
If you don't have a MAIN segment that you can modify, then you can't write a subroutine that gets called by that MAIN segment "just because it is there." You will need something to trigger MSAccess.EXE to execute your code, and that USUALLY translates to an event.
The next biggie is that VB actually produces machine code and uses a linker to produce a new .EXE file for you. VBA pseudo-compiles what it gets from you and, when an event enters your environment and you have a declared event procedure, you INTERPRET the code that VBA pseudo-compiled earlier. That code is actually DATA in some obscure part of your .MDB or .ACCDB, whatever you have. (More specifically, in the front end portion of your application if you have a split FE/BE file.) So, when you are executing your VBA code, you are actually executing the MSAccess code emulator/interpreter. (Which is one reason why event code routines usually can't interrupt each other.)
You CAN create your (pseudo-)compiled functions that are then callable using the features of SQL execution. There, the event would be the "SQL execute" event and the code operation, analogous to functions in a Macro stream, would not be launched directly in response to an event. Your functions can in turn call subroutines, but the VBA SQL interface requires a function in queries because the reference can ONLY occur in a field specification for a "SELECT list-of-fields-or-values" or a value specification for an "UPDATE MyTable SET field = value" or an "INSERT INTO MyTable (Fields-list) VALUES(values-list)". I.e. the function has to return a value for use in a field.)
Then, there is this pedantic little quibble - even your VB program responds to an event - the Launch Executable event. But that's outside the scope of this discussion. So technically, everything we write is responsive to some external event. In practice, some functions can be invoked by methods that are not immediately considered as events. NO subroutines can be written that run without some other context (such as event context) around them.