On April 23, 2021, I helped Wayne Phillips introduce the world to twinBASIC at the Access DevCon Vienna conference. I boldly predicted that twinBASIC (along with the Monaco editor) would replace VBA and its outdated development environment by 2025. With that goal in mind, this weekly update is my attempt to keep the project fresh in the minds of the VBA development community.
Every Sunday, I will be providing updates on the status of the project, linking to new articles discussing twinBASIC, and generally trying to increase engagement with the project. If you come across items that should be included here, tweet me @NoLongerSet or email me at mike at nolongerset dot com.
As of version 0.9.2648, twinBASIC added support for attributes using a square-bracket syntax. The following attributes are currently supported:
Here's a screenshot of the new feature in action:
As of version 0.9.2443, twinBASIC added support for DllRegisterServer and DllUnregisterServer. With this update, you can now build ActiveX DLLs with twinBASIC and distribute them to machines. Previously, ActiveX DLLs had to be registered using the VS Code IDE, which meant they could only run on the development machine.
This is the feature that allows you to use
regsvr32 to register your ActiveX DLL in the Windows registry so that you can call it from VBA. For example:
There are a couple of really nice features to go along with this functionality.
Choice of HKLM vs. HKCU
By default, twinBASIC will register the ActiveX DLL in the user registry hive (HKCU). This is important, because it means that registering the library will NOT require admin privileges.
If you need to install your libary machine-wide, that's still an option. There's an option in the Settings file to do that:
Note that if you want to register to HKLM (VB6's behavior), you'll probably want to run VS Code as an administrator to make debugging simpler.
There is also an option to run custom twinBASIC code during the register and unregister process. This code runs in addition to the standard registration and unregistration code.
The custom DllRegisterServer function runs after the normal registration code. So the custom code is only called if the initial registration succeeds. Unregistration works in reverse. The custom DllUnregisterServer function is called before the normal unregistration code.
Returning False from the DllUnregisterServer function will prevent the normal unregistration code from running.
Your two cents
There is an active discussion around this feature at the Github project page: Generated ActiveX DLLs need to support DllRegisterServer and DllUnregisterServer. If you have thoughts on how you want to see this feature implemented, particularly around the exact behavior of the HKLM vs. HKCU registration/unregistration, pop over to GitHub and join the conversation.
PredeclaredId attribute support
As of version 0.9.2648, twinBASIC added support for predeclared twinBASIC classes. If you set a class attribute of PredeclaredID to a twinBASIC class, then twinBASIC will create a default instance of that class using the class's name.
For example, let's say we have a class named App. Normally, to use that class, we would first need to create an object variable of type and then set that variable to a new instance of the App class. With a PredeclaredID, we can use a default instance of that class without creating a separate object variable.
This functionality is available in VBA and VB6, but twinBASIC adds support for a simpler attribute syntax (the existing syntax is still supported for backward compatibility). The new twinBASIC syntax for this is
[PredeclaredID]. That line goes directly above the line that creates the class module.
Here's an example:
Here are the updates from the past week. You can also find this information by installing the twinBASIC VS Code extension and clicking on the Changelog tab of the extension page:
[v0.9.2699, 9th May 2021]
- fixed: type library loading when an alias/typedef refers to an unsupported datatype [ https://github.com/WaynePhillipsEA/twinbasic/issues/128 ]
- fixed: intellisense involving default values where strings were not being JSON encoded for the LSP [ mentioned in https://github.com/WaynePhillipsEA/twinbasic/issues/128 ]
- fixed: type library generation when parameters or return types are defined as the internal type, VBA.Collection [ https://github.com/WaynePhillipsEA/twinbasic/issues/127 ]
- fixed: rubberduck @PredeclaredId attribute was allowed before the class definition, not inside it [ https://github.com/WaynePhillipsEA/twinbasic/issues/126 ]
- fixed: parser error where Foo.Bar -X, Y was interpretted as (Foo.Bar - X), Y [ https://github.com/WaynePhillipsEA/twinbasic/issues/129 ]
[v0.9.2651, 8th May 2021]
- fixed: loading of type library references that are inside a dll with multiple type libraries [ https://github.com/WaynePhillipsEA/twinbasic/issues/125 ]
[v0.9.2649, 8th May 2021]
- fixed: [WithDispatchForwarding] attribute wasn't actually effective
[v0.9.2648, 8th May 2021]
- added: support for predeclared twinBASIC classes (note: not supported from external type libraries like Excel yet)
- added: [PredeclaredId] attribute
- added: @PredeclaredId rubberduck annotation support [ https://github.com/WaynePhillipsEA/twinbasic/issues/12 ]
- fixed: Threading Modal/Model typo in settings [ https://github.com/WaynePhillipsEA/twinbasic/issues/124 ]
- added: [WithDispatchForwarding] attribute for Implements statements. WARNING: temporary WithDispatchForwarding keyword to be removed soon [ https://github.com/WaynePhillipsEA/twinbasic/issues/110 ]
[v0.9.2617, 7th May 2021]
- added: implicit compiler conditional argument of 'TWINBASIC' for conditional compilation purposes
- added: support for attributes using the square-bracket syntax [ https://github.com/WaynePhillipsEA/twinbasic/issues/25 ]
- added: [Description("")] attribute
- added: [DispId(
- added: [DefaultMember] attribute for class members [same as DispId(0)]
- added: [Enumerator] attribute for class members [same as DispId(-4)]
- added: [UseGetLastError(False)] attribute for Declare statements to avoid the implicit call to GetLastError at API call sites
[v0.9.2451, 6th May 2021]
- fixed: Settings / Build confirugation editor not showing in v1.52 of vscode
[v0.9.2450, 5th May 2021]
- fixed: WithEvents event subscriptions when multiple WithEvents fields of the same type are defined in a single class
[v0.9.2443, 5th May 2021]
- added: implementations of DllRegisterServer and DllUnregisterServer, and tweaked the IDE to use them
- added: optional callbacks into twinBASIC for procedures named DllRegisterServer and DllUnregisterServer (i.e. Public Sub DllRegisterServer() As Boolean)
- added: project option: project.dllRegisterLocalMachine (switch between HKEY_CURRENT_USER / HKEY_LOCAL_MACHINE) for DllRegisterServer
- added: vs code command twinbasic.cleanBuild (F1 > "twinBASIC: clean build (deregister & delete built files)")
- added: project option project.comThreadingModal (STA/MTA)
[v0.9.2355, 4th May 2021]
- fixed: fixed-length strings passed to a ByVal String argument in an ansi Declare statement were passing through a temporary BSTR copy [ https://github.com/WaynePhillipsEA/twinbasic/issues/106 ]
- fixed: type library loading and resolving of imported type libraries that are not referenced directly, or where version differs [ https://github.com/WaynePhillipsEA/twinbasic/issues/107 ]
- fixed: double-line feed (\r\n\r\n) parsing over conditionally excluded code [ https://github.com/WaynePhillipsEA/twinbasic/issues/118 ]
- fixed: initial setup of constants now occurs earlier to allow binding from UDT-arrays [ https://github.com/WaynePhillipsEA/twinbasic/issues/116 ]
- fixed: class dispatch table generation now allows for Empty / Null variant default values [ https://github.com/WaynePhillipsEA/twinbasic/issues/116 ]
[v0.9.2311, 4th May 2021]
- changed: moved the project.description setting directly underneath the project.name setting for better UX [ https://github.com/WaynePhillipsEA/twinbasic/issues/113 ]
- fixed: circular reference in Implements statements no longer causes endless loop in the compiler
- fixed: typelibrary generation error when a tB class contained a WithEvents field [ https://github.com/WaynePhillipsEA/twinbasic/issues/112 ]
[v0.9.2300, 3rd May 2021]
- fixed: improved handling of data type suffixes at procedure call sites to avoid 'invalid use of datatype hint' errors [ https://github.com/WaynePhillipsEA/twinbasic/issues/108 ]
- fixed: altering a project reference caused other fields in the project settings to keep losing focus
- fixed: runtime hard-crash when With block was used with a class WithEvents field [ https://github.com/WaynePhillipsEA/twinbasic/issues/104 ]
- fixed: 'implements' matching to procedures prefixed with the type name not always working, e.g. with TKIND_ALIAS types
- fixed: tB now allows passing variants and strings to byte-array parameters, for supporting DAO.Recordset::Bookmark property-let
- fixed: implementation of IDispatch::GetIDsOfNames is now case-insensitive
- fixed: changed the way constant datatypes are handled, so that they are not implicitly Variant when no explicit data type is provided [ https://github.com/WaynePhillipsEA/twinbasic/issues/105 ]
- added: WithDispatchForwarding optional flag to the Implements statement, allowing outer class members to become accessible to a dispatchable implemented interface. [e.g. Implements IRibbonExtensibility WithDispatchForwarding]