Search code examples
vbarubberduck

How can I edit files with VBA code using Rubberduck, leaving no traces of Rubberduck in the VBA project


A very limiting factor I'm having with Rubberduck is that merely opening a VBA project on a development PC that has it installed modifies it. Even if I don't change anything on purpose and just look at it, something does change because the VB editor asks if I want to save changes to every single project that it opened.

Compare this to a "normal" programming language that uses plain text files for source code. For example, if I received a .py python script from someone, edited it to add a function and sent it back, they could never know nor would it even matter to them if I used notepad, vscode, vim or whatever to edit it

If I did the same with a VBA project and I have rubberduck installed it would change the files somehow, even parts of the code I wasn't supposed to touch, which is precisely what I want to avoid. I want to make it so that it couldn't possibly matter that I use Rubberduck myself if possible.

What I want to achieve is:

  • I receive a binary file that contains a VBA project and I'm tasked with adding a single function
  • I edit it to add my function, but I leave a lot of existing modules and other code untouched
  • Maybe I use rubberduck features for myself only to make it easier to code, maybe have some tests on my side
  • I somehow "clean up" the VBA project completely from any other modifications Rubberduck may have made or needed to make
  • I send them the file back and they can't ever possibly know I used Rubberduck in my computer, and except for the new function I wrote, nothing else whatsoever on the VBA project has been touched

The key requirements are:

  • They send the binary (e.g. an .xlsxm) and need to receive the very same thing back (the .xlsxm but I added a function in some module). I can't send them back just the VB source code in a text file, for example
  • I can't touch anything I wasn't meant to touch
  • The receiver is another developer so the VBA project source code does matter to them, it's not an end user who wouldn't see it
  • Not looking for anything application-specific, excel file is just an example

Only thing I've thought is various forms of copying text over to another project (directly, or exporting to text files then importing or similar) but it sounds problematic:

  • Involves manual steps and is error prone. Would probably introduce more problems than I aimed to solve in the first place
  • I'm not aware of ALL of the ramifications and changes Rubberduck does on the entire project. Maybe there are even some that don't just involve the "text" source code itself? How can I be sure the file is 100% clean?

And I did see this question but it involves excluding the code of test modules specifically. In my case I want to know if there's a proper, clean way to avoid ALL side-effects of Rubberduck completely, not just not including a certain module or piece of code.


Solution

  • It has to be the ProjectId.

    Back in 2015, we made a source control panel that integrated git and would allow you to fetch, pull, commit, and push directly from the VBE. While great in theory, in practice it turned out a nightmare and it was eventually removed so we could focus on the actual functionality we wanted to build for Rubberduck... but by then the ProjectId was everywhere and removing it would have required massive changes we weren't prepared for... so it stayed, as it was deemed pretty innocuous (it really is).

    Because of the embedded nature of VBA projects, keeping the in-editor code as the "single source of truth" meant we needed a way to uniquely identify any given project, in order to know that Project1 with a Module1 standard module was the code you intended to be under source control: if you had 2+ workbooks opened and they each had a Module1 standard module, without [writing some host-specific code or] some kind of ID coming from the host document there'd be no way to know for sure which of the Module1 modules is supposed to be synchronized with the repository.

    So whenever Rubberduck first sees a project (that would be during the initial parse), it generates an ID and then writes it to the VBProject.HelpFile property, which hopefully nobody is using (it's referring to Windows Help tech that's long been deprecated).

    If there's already a value in that field, then Rubberduck takes it as a unique project ID and runs with it, without modifying the host project.

    You could generate a GUID (to ensure uniqueness) and put it in VBProject.HelpFile, save the document, and then Rubberduck would leave it alone.

    Alternatively, you could clear the value before saving and closing, but then know that Rubberduck will generate and write a new ID the next time it comes across that project.

    Rubberduck 3.0 (currently under development) being essentially a complete rewrite, will not be doing this.