Rubberduck: Parser removes a userform and re-imports it as a code module

Created on 16 May 2017  路  8Comments  路  Source: rubberduck-vba/Rubberduck

I have installed the latest version (RD 2.0.13 hotfix).

I have a code base that I was using under RD 1.4. This project has 1 user-form in it.

I have followed the installation wiki and installed executable as administrator, and have also run the command-line registrations (again as administrator).

When the IDE opens, the RD button says Pending. I click the button and it seems to successfully parse the first time, such that the button says "Ready".

If I do nothing at all, but hit the button again, it successfully parses again.

Instead of doing nothing, I open one of the code modules, add one blank space on an empty line, and hit the RD button again, the following happens:
The UserForm is removed from the Forms section of the Project Explorer, ad is re-inserted under modules. There is metadata in the form file which gives an error on compile (although compiling it is no particularly sensible anyway as the project is now corrupted).

This is the metadata
VERSION 5#
Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} DeltaAlgoForm
Caption = "DeltaAlgo"
ClientHeight = 4290
ClientLeft = 45
ClientTop = 330
ClientWidth = 7200
OleObjectBlob = "DeltaAlgoForm.frx":0000
StartUpPosition = 1 'CenterOwner
End

If I open the UnitTest explorer, it correctly shows me all of the tests. If I try to re-parse from the UnitTest explorer, the same issue happens.

Any help would be greatly appreciated.

bug critical feature-source-control

Most helpful comment

We had noticed the extra line in the form module, so every git commit ended up including the form as well. Did not realize it was a microsoft bug, and certainly I was not clever enough to create a fix for it!

Let me see if I can re-create the issue and get you some actual data

All 8 comments

Never seen this happen. Can you clarify the repro steps? Is it the UserForm that's modified with a single blank space?

The only Rubberduck code that re-imports modules (for now) is the Source Control feature; beyond that every module is exported to a temporary file that gets processed (we pick up module & member attributes from the exported text files), and then promptly deleted.

If you have logging enabled, there's probably valuable information in the logs. You can enable logging in the RD settings dialog - "TRACE" level logs everything.

Hi Mathieu,
Thanks for picking this up so quickly.

There are a number of things that I should have mentioned in the first comment, that may or may not be germane.

I am currently in the middle of reviving some code that was last used a year ago, and was working well with RD 1.4.

First, OS is Windows 7 BUT it is running under Parallels on a Mac.
Excel is 2016 for Windows
Next, the project is under Git source control. The way I have it set up now is that the repository is on the Mac drive which is "network mounted" on Windows. Provided I am careful about where I access the file from, this actually works OK. I usually use GitHub desktop. Under the Windows/Parallels situation I need to do this under Windows because of the different handling of CR/LF. If I use GitHub desktop on the Mac side, and I sync with the GitHub based repository, the line endings get messed up.

Next, I had implemented a similar source-code export feature 18 months +/- ago, when I was using RD 1.4 - before RD 2.0 came out and provided similar features. I have been fighting with the RD/Mac/Windows/Parallels/Line Ending/Poorly written export code for about 2 weeks now, so have been through MANY permutations. Nonetheless, I got most of the issues sorted, except this last one which I am writing to you about. My code export puts files in a folder called VBAProjectFiles. I only mention this because I don't know if that is what your code is looking for. I tried (in one attempt) of using your source code control, but was unsuccessful. I believe I was primarily unsuccessful because of this issue, although, these items may be related. My point here is that during this trial I was NOT trying to use your source code support, although may have been unwittingly.

Before I wrote the previous comment, I had uninstalled, reinstalled, and thought I was starting clean, although that may not be the case.

In terms of reproducing the steps, the steps were as follows:

  1. Open my .xlsm file with my code in it.
  2. Choose Developer on the Toolbar
  3. Choose VBA from the Developer Toolbar. At this point the RD splashscreen appears.
  4. Find the RD button which says "Pending", and hit the button.
  5. Wait for RD to parse(?) all of the modules in the project. Eventually the button's label changes to "Ready".
  6. Next I randomly selected a CODE Module - Not the User Form - just any other module and added a blank space. I believe the only purpose of this was to flag something as having been changed.
  7. Press the RD button that says "Ready" - Even though it did not say "pending" or seem to require a re-parse, I knew I had changed something.
  8. When it is complete, the UserForm is gone - as in the folder section in the Project Explorer is now gone (I only had one form) - and the which was part of the UserForm is now in a code module under the Modules folder.

I don't believe it would have matter what I changed, as long as I changed something.

I have had the logging on trace and it is verbose. Many of the messages are of the form of "Inserting Module 1". Renaming Module 1 to "One of my module names".

I tried to boil this down to an even simpler example by adding a very simple user form and seeing if I could re-create the problem. When I did that, however, my very simple userform was completely removed and not reinstated anywhere. I decided that instead of trying to chase that issue, I should just stick with the primary issue at the start. One of the primary reasons for trying to set up a small example of the issue is because I can not post detailed log listings to the website, at least not without a bit of sanitizing. If that is what is required, I will do so, but perhaps with this broader context you may be able to steer me in the right direction. I love the tool, and want to get the most out of it.

Thanks,
Rob

@rssmith1 thanks for the update, and the feedback! I wonder if the source control configuration file (%appdata%\Rubberduck\SourceControl.Rubberduck) wouldn't happen to be corrupt, somehow getting source control to respond to a parse request by refreshing the files in the local repository - forms disappearing sound a lot like #2939; if SC isn't involved with your issue one way or another then I'm very much puzzled, because nothing in Rubberduck is importing code files, except the source control panel.

Try deleting %appdata%\Rubberduck\SourceControl.Rubberduck.

FWIW it's very much critical that we fix that form-import problem, given I'm getting close to merge my work on synchronizing module & member attributes with custom annotation comments: it would suck to have to exclude forms as a (lame) work-around...

That was it! As in deleting the SourceControl.Rubberduck file (actually just changing the name) resolved the issue around deleting the form.

If this is helpful at all....

Configuration
  SourceControlSettings
    UserName 
    EmailAddress 
    DefaultRepositoryLocation 
    Repositories
      Repository
        Id 108020607  Id
        LocalLocation>C:\Users\rsmith\VBAProject LocalLocation
        RemoteLocation>C:\Users\rsmith\VBAProject RemoteLocation
      Repository
      Repository
        Id 99029544 Id
        LocalLocation> Y:GitHub\IBTradingAlgorithmRB\IBTRB LocalLocation
        RemoteLocation github.com/rssmith1/IBTRB.git RemoteLocation
      Repository
      Repository
        Id 98034480 Id 
        LocalLocation Y:\GitHub\IBTRD LocalLocation
        RemoteLocation 
      Repository
    Repositories
    CommandPromptLocation 
  SourceControlSettings
Configuration

That is the contents of the sourcecontrol file (sort of - I had to edit a little to have it appear properly). There are a few things to point out. There are 3 repositories listed.
The first - 108020607 should be a proper "virtual" directory on my windows VM. That file does indeed exist and has all of the source files in it. In addition to all of the regular source files, there is the form (the one which gets corrupted) in the form of Form.FRM and Form.BAS. FWIW, in the code export that I have been using within the spreadsheet, when it exports the form, I have a Form.FRM and a Form.FRX file, NOT a .BAS file. Could this be the issue?

The other repositories are the leftovers from my many attempts at working through the issue. They are defunct.

In any case, deleting the source control file has solved the problem of using the unit testing. If I can be of any assistance to re-create the BAS vs FRX problem for you though, please let me know.

A MSForms UserForm is always exported as two files:

  • .frm, which contains the code-behind and the module/member attributes; that's the file we're interested in when we parse.
  • .frx, which contais control layout and binary data (e.g. embedded bitmaps, etc.) - essentially the equivalent of the .designer partial class files, if you're any familiar with WinForms in .NET; the parser ignores these files, but the VBE needs them to re-import a form module without wiping everything done in the designer.

When Rubberduck exports a source file, it does it using the ExportAsSourceFile method we've implemented in our VBComponent wrapper implementation - basically we're switching on the component's Type:

            var fullPath = tempFile
                ? Path.Combine(folder, Path.GetRandomFileName())
                : Path.Combine(folder, SafeName + Type.FileExtension());
            switch (Type)
            {
                case ComponentType.UserForm:
                    ExportUserFormModule(fullPath);
                    break;
                case ComponentType.Document:
                    ExportDocumentModule(fullPath);
                    break;
                default:
                    Export(fullPath);
                    break;
            }

So a UserForm module would get exported through the ExportUserFormModule method, which includes a little bit of logic to work around a bug in the VBE that inserts an extra empty line when it exports a form - ultimately it's the VBIDE API performing the actual export... anyway the file extension is determined by the ComponentType; we have an extension method on the enum value, responsible for this:

        public static string FileExtension(this ComponentType componentType)
        {
            switch (componentType)
            {
                case ComponentType.ClassModule:
                    return ClassExtension;
                case ComponentType.UserForm:
                    return FormExtension;
                case ComponentType.StandardModule:
                    return StandardExtension;
                case ComponentType.Document:
                    // documents should technically be a ".cls", but we need to be able to tell them apart.
                    return DocClassExtension;
                case ComponentType.ActiveXDesigner:
                default:
                    return string.Empty;
            }
        }

I really don't see how a UserForm module could be exported with a .bas extension, I'd love to see a repro.

We had noticed the extra line in the form module, so every git commit ended up including the form as well. Did not realize it was a microsoft bug, and certainly I was not clever enough to create a fix for it!

Let me see if I can re-create the issue and get you some actual data

I was able to consistently reproduce the issue - on two separate machines. The initial conditions were as follows:
I was using a version of my project which compiled.
There was no SourceControl.Rubberduck file in ~/AppData/Roaming/Rubberduck

The steps I took to create the issue were:
First create a temporary directory. I used ~/RDTemp

Open the .xlsm file
Select Developer
Select Visual Basic off of the Developer ribbon. The Rubberduck splash screen appears.
click the RD button which says "Pending". The project parses and the button label turns to "Ready"
Click Rubberduck->Tools->Source Control. the Source Control tab opens.
Click Settings. Fill in the fields for username and e-mail address.
For "Default Repository Location" click the browse button and browse to the new directory set up above
Click Update. In the SourceControl the message appears saying "Your username, email, and default repository have been saved"
Click the refresh icon in the SourceControl panel.

A message appears in the source control panel.
_Unknown Exception
Document-type component myuserformname does not exist can not import code from repository
Document-type component myuserformname does not exist can not import code from repository
_

The message is repeated twice as shown above.

If I look in the repository directory, there is a subdirectory VBAProject. In this directory myuserformname.frm is there, but not myuserformname.frx

At this point, the single userform which was in the project is now gone.

This behavior is identical on my Windows 7 VM running on a MacMini and on a Windows 10 Surface 3 machine. Both machines are running Excel 2016

Was this page helpful?
0 / 5 - 0 ratings