Forum Discussion

Baccma's avatar
Baccma
Copper Contributor
Jul 23, 2022

Advanced formula environment: suggested improvement to UI

Would be great if there was the facility within the AFE to select an existing workbook and import all or selected lambda functions from it, rather than having to go through cut and paste.

  • blairj's avatar
    blairj
    Copper Contributor

    Baccma, I agree. I posted a similar message in the feedback portal and copied below. Import or copy/paste is better than having to retype by hand for sure, but not really maintainable.

     

    The Awesome
    The Advanced Forumula Environment is awesome. It, along with changes to formulas such as LET, LAMBDA, and dynamic arrays have completely transformed Excel into something much more powerful and usable. So please take this out of the garage and put it out on the street as soon as possible.
     
    The addition of modules is also a welcome addition. I can create many tailored functions that help enormously in building more helpful views of data more quickly.
     
    The Problem
    The problem now is maintainability. I have a number of different spreadsheets each with different queries for related but different purposes. Each of these have to do many of the same things with the data and so can use the same functions. To do this, a way is required to provide common functions in a module or set of modules that can be shared among different spreadsheets. Cut and paste is available, but that's pretty clunky and I have to know which spreadsheets to go to and then manually go to each one and update each module by pasting over the new version. I don't have access to GitHub and I shouldn't have to have yet another account to pay for just to store a few modules that apply only to these related spreadsheets. And even that seems like it's an import, not a reference to central definition.
     
    The Ask
    Excel already has the ability to reference data from other workbooks, and simply being able to do the same with modules would solve this problem in a stroke. Even just being able to have the modules saved as plain text files externally to reuse would be awesome. Then those files could then, if desired, be managed by a source control system. I have access to a subversion repository and possibly a GIT repository as well so being able to version them would be awesome, and then make them easily shareable within the company.
     
    Conclusion
    Seems like a number of things are happening with the Advanced Formula Environment, and hopefully many great things are coming, and I'm loving it. For me the greatest bottleneck at this stage to leveraging all of that awesomeness to it's fullest is the maintainability of modules. After that, the sky's the limit.
    • jack-williams's avatar
      jack-williams
      Icon for Microsoft rankMicrosoft
      Thanks for the feedback blairj.

      We need to update the feedback page in the add-in. We do check the feedback portal and these forums, but the frequency is limited because we're a research team and garage project, as Sergei mentions.
      • ecovonrein's avatar
        ecovonrein
        Iron Contributor

        We all come up against the same production problems.  I had a look at AFE/Modules and cannot quite understand where this is going.  What would be required IMHO is a link in Excel to a file containing Lambdas that gets automatically pulled in whenever the spreadsheet is opened.  We do something similar in our environment already with .bas files.  So I sat down last night and cooked up a solution that extends our staging to Lambdas. I am happy to donate the code as a belated Xmas present to the community.  Insert this code into a VBA module (adjust "Root" to your environment):

         

        Option Explicit
        
        Const Root As String = "C:\Users\some_file_path\"
        Const charsToTrim As String = " " & vbTab & vbCr & vbLf
        
        Private Function trimLeft(aString As String) As Variant
            Dim i As Long, n As Long
            
            n = Len(aString)
            For i = 1 To n Step 1
                If InStr(charsToTrim, Mid(aString, i, 1)) = 0 Then
                    trimLeft = Mid(aString, i, n)
                    Exit Function
                End If
            Next
        
            trimLeft = ""
        End Function
        
        Private Function trimRight(aString As String) As Variant
            Dim i As Long, n As Long
            
            n = Len(aString)
            For i = n To 1 Step -1
                If InStr(charsToTrim, Mid(aString, i, 1)) = 0 Then
                    trimRight = Mid(aString, 1, i)
                    Exit Function
                End If
            Next
        
            trimRight = ""
        End Function
        
        Private Sub addGlobal(aName As String, RefersTo As String)
            On Error Resume Next
            Names(aName).Delete
            Names.Add aName, RefersTo
        End Sub
        
        Private Function getLineFromFile(fileNo As Long, ByRef aLine As String) As Boolean
            Do Until EOF(fileNo)
                Line Input #fileNo, aLine
                aLine = trimLeft(aLine)
                If Len(aLine) > 0 Then
                    If Left(aLine, 1) <> "'" Then
                        getLineFromFile = True
                        Exit Function
                    End If
                End If
            Loop
            
            getLineFromFile = False
        End Function
        
        Public Sub installLambdas(modName As String)
            Dim lbdFile As String, aLine As String
            Dim aName As String, aLambda As String
            Dim iToken As Long
        
            lbdFile = Root & modName & ".lbd"
            Open lbdFile For Input As #1
        
            aLambda = "="
            Do While getLineFromFile(1, aLine)
                If aLambda = "=" Then
                    iToken = InStr(1, aLine, "=")
                    If iToken = 0 Then GoTo Cleanup
                    aName = trimRight(Left(aLine, iToken - 1))
                    If Left(aName, 1) = "." Then aName = modName & aName
                Else
                    iToken = 0
                End If
                
                aLambda = aLambda & trimLeft(trimRight(Mid(aLine, iToken + 1, 9999)))
                
                If Right(aLambda, 1) = "_" Then
                    aLambda = Mid(aLambda, 1, Len(aLambda) - 1)
                Else
                    addGlobal aName, aLambda
                    aLambda = "="
                End If
            Loop
        
        Cleanup:
           Close #1
        End Sub
        
        Public Sub Auto_Open()
            installLambdas "myLambdas"
        End Sub

         

        To make this stuff work, you must change your XLSX into an XLSM (which means that it won't work in Excel Online.  But you are unlikely to be much concerned about that).

         

        The code above reads a text file named "myLambdas.lbd" (inside the "Root" folder on your corporate OneDrive).  This file contains the lambdas that you want to maintain centrally in a format akin to that proposed by AFE.  An example:

         

        ' .perSum simply sums up any numbers in given row iRow of the loan data (LD) that fall within the date bracket [EOFY_1;EOFY].
        ' 30/12/2022 V1.0, OVR
        
        .perSum = LAMBDA(LD,iRow,EOFY_1,EOFY,LET( _
        	Dates, INDEX(LD,1,0), _
        	Items, INDEX(LD,iRow,0), _
        	SUMIFS(Items,Dates,">"&EOFY_1,Dates,"<="&EOFY) _
        ))

         

        The VBA code lacks the IntelliSense of AFE so cannot count brackets etc.  To ease my life, I fall back on the VBA idea of suffixing a "_" where I want to break a Lambda over another line.  I also use the VBA syntax for comments ("'").

         

        A couple of things to know:

        1  VBA does not understand localization when assigning Range Names.  Therefore, you MUST use "," in your composition of Lambdas (not eg ";" as Europeans would).  (I also suspect that you must write decimals as "2.0", not "2,0" - have not tried.)

        2  You can insert empty lines as you please.  Even inside Lambdas (ie between "_").  Ditto lines with comments.  What you CANNOT do is append a trailing comment (on the same line as other code).

        3  You can space out with tabs or spaces, as you like.

        4  Like in AFE/Modules, every Lambda is introduced with "Name = Lambda(...)".  In my world, this creates a global "Name".  In the world of AFE, you would create "Module.Name".  I very much like the idea of namespaces for Lambdas, so I taught the script a little trick.  Write ".Name = Lambda(...)" in your myLambdas.lbd file and you will get "myLambdas.Name".  So you can have the best of both worlds.

         

        This solution does not nearly have the power of AFE and you must be super careful with your "_"s but assuming that the .lbd files are created by a central development team, they are not likely to fall victim of total numbnutz, so Notepad might be an acceptable editor.

         

        Happy New Year !

    • blairj 

      I'm not sure that feedback portal is right place to comment MS Garage projects. Portal is more for the production Excel, research team from Cambridge not necessary monitor this resource. What they recommend is to publish here with proper tag

      Low chances the will see the post without such tag.

       

      Again, I prefer to communicate on GitHub here Issues · microsoft/advanced-formula-environment (github.com) , free account is more than enough for that.

    • Baccma's avatar
      Baccma
      Copper Contributor

      SergeiBaklan I'm pretty sure I replied using the feedback function on the AFE itself.

       

Resources