Avatar of Rob Henson
Rob Henson
Flag for United Kingdom of Great Britain and Northern Ireland asked on

Placement of a Function

Hi All,

i am using the following basic Function to collate a table of comments into a single cell for onward copying into a consolidation file:

Public Function AllComments(Rng As Range)

R = 0
LR = Rng.Cells.Count
For Each Cell In Rng
    Newline = ""
    R = R + 1
    If R < LR Then Newline = Chr(10)
    Collated = Collated & Cell.Text & Newline
Next Cell
    AllComments = Collated
End Function

Open in new window

I am distributing this Function to numerous project files and I was looking to Automate the process.

The function is currently held in a Standard module and I am having to copy the code in the VBE and copy the sheet on which it is used.

Can the function be in the sheet code rather than a module? How do I get the Function to work when it is in the sheet code; I couldn't get it to work like that which is why it is in a standard module.

Also, on a separate but related issue: the file from which I am copying the sheet has lots of Named Ranges. When I copy the sheet I end up with copies of the Named Ranges in the destination file. The destination file already has all of these Named Ranges so I get two copies of each Named Range, one with Workbook scope and one with scope of the copied sheet.

On this occasion the sheet is very simple so it would be just as simple to insert a sheet and copy paste the contents onto the new sheet but I have seen this occur before and on those occasions it wasn't as simple so have had to go in and delete the surplus Named Ranges. I have tried recording this process with the VB Recorder but the script that I end up does not show any indication that it is the Sheet scope Range that it is deleting. Is there a way of defining this when deleting the range name?

Thanks
Rob H
Microsoft ExcelVBA

Avatar of undefined
Last Comment
Rob Henson

8/22/2022 - Mon
Norie

Rob

If you put it in a sheet module you would need to include the sheet's  codename when calling the function from anywhere other than the module it's in.

For example if it was in the module of a worksheet with the codename Sheet1 you would use Sheet1.AllComments.

As for the named range thing, which named ranges would you want to delete?
Rob Henson

ASKER
How do I then use the Function as a formula on the Worksheet?

I have just tried moving the function to the relevant sheet (codename - Sheet5; tab name - VAR)

I tried =Sheet5.AllComments and it didn't accept it.

Thanks
Rob
SOLUTION
Martin Liss

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
Martin Liss

I'm not sure what "I am distributing this Function to numerous project files" means but you could put the standard module and the function in a template file and deliver the template instead.
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Rob Henson

ASKER
But I only want to eliminate those that are Sheet scope. Those that are Workbook scope need to stay but they have the same name as those with sheet scope.
Rob Henson

ASKER
I have already implemented it in a template for future project files. I now need to implement it in the existing files.
Martin Liss

But I only want to eliminate those that are Sheet scope. Those that are Workbook scope need to stay but they have the same name as those with sheet scope.
I didn't test it but I believe that it will only eliminate the ones on the active sheet.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Rob Henson

ASKER
@Martin - with the amendment as below, it worked. Thanks.
Dim NR As Name

With ActiveSheet
    For Each NR In .Names
        NR.Delete
    Next
End With

Open in new window

@Norie - if it has to be on a Standard Module, I could put it on its own module in the template. Can I then have a routine that copies that module to the file, Alternatively, I could export the module first and then import it into the other file. How do I do that?

Thanks
Rob H
Rob Henson

ASKER
@Martin - the question regarding the removal of Range Names maybe should have been a question in its own right. In your position as administrator are you able to move the Range Name related comments to their own question. I will then accept your solution on that as it deserves full quotient of points rather than just an Assisted marking on this question.
Martin Liss

I'm happy with assisted but you could contact a moderator via Request Attention.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Rob Henson

ASKER
@ Norie - Phrasing the question differently, how do I import the exported module .bas file into a file using VBA?

Likewise, how do I get rid of existing modules?

The various project files that I am working with have come from various iterations of the Template file that I am working on so have inherited some of the modules that are now in the template file. The only module that should be in the Project files is the one with the Function as above.

As I open each of the project files I am going through a cleansing exercise deleting other modules as well as implementing the new feature for the collated comments (the function above).
aikimark

You could put the code in a module in an add-in.  That way, it will be available to all workbooks after the add-in has been added.
Martin Liss

how do I import the exported module .bas file into a file using VBA?
Ron de Bruin has this code you can use. But note that he says "Run the ImportModules macro (It delete all existing modules/userforms from [the target] Workbook first)".

Public Sub ImportModules()
    Dim wkbTarget As Excel.Workbook
    Dim objFSO As Scripting.FileSystemObject
    Dim objFile As Scripting.File
    Dim szTargetWorkbook As String
    Dim szImportPath As String
    Dim szFileName As String
    Dim cmpComponents As VBIDE.VBComponents

    If ActiveWorkbook.Name = ThisWorkbook.Name Then
        MsgBox "Select another destination workbook" & _
        "Not possible to import in this workbook "
        Exit Sub
    End If

    'Get the path to the folder with modules
    If FolderWithVBAProjectFiles = "Error" Then
        MsgBox "Import Folder not exist"
        Exit Sub
    End If

    ''' NOTE: This workbook must be open in Excel.
    szTargetWorkbook = ActiveWorkbook.Name
    Set wkbTarget = Application.Workbooks(szTargetWorkbook)
    
    If wkbTarget.VBProject.Protection = 1 Then
    MsgBox "The VBA in this workbook is protected," & _
        "not possible to Import the code"
    Exit Sub
    End If

    ''' NOTE: Path where the code modules are located.
    szImportPath = FolderWithVBAProjectFiles & "\"
        
    Set objFSO = New Scripting.FileSystemObject
    If objFSO.GetFolder(szImportPath).Files.Count = 0 Then
       MsgBox "There are no files to import"
       Exit Sub
    End If

    'Delete all modules/Userforms from the ActiveWorkbook
    Call DeleteVBAModulesAndUserForms

    Set cmpComponents = wkbTarget.VBProject.VBComponents
    
    ''' Import all the code modules in the specified path
    ''' to the ActiveWorkbook.
    For Each objFile In objFSO.GetFolder(szImportPath).Files
    
        If (objFSO.GetExtensionName(objFile.Name) = "cls") Or _
            (objFSO.GetExtensionName(objFile.Name) = "frm") Or _
            (objFSO.GetExtensionName(objFile.Name) = "bas") Then
            cmpComponents.Import objFile.Path
        End If
        
    Next objFile
    
    MsgBox "Import is ready"
End Sub

Function FolderWithVBAProjectFiles() As String
    Dim WshShell As Object
    Dim FSO As Object
    Dim SpecialPath As String

    Set WshShell = CreateObject("WScript.Shell")
    Set FSO = CreateObject("scripting.filesystemobject")

    SpecialPath = WshShell.SpecialFolders("MyDocuments")

    If Right(SpecialPath, 1) <> "\" Then
        SpecialPath = SpecialPath & "\"
    End If
    
    If FSO.FolderExists(SpecialPath & "VBAProjectFiles") = False Then
        On Error Resume Next
        MkDir SpecialPath & "VBAProjectFiles"
        On Error GoTo 0
    End If
    
    If FSO.FolderExists(SpecialPath & "VBAProjectFiles") = True Then
        FolderWithVBAProjectFiles = SpecialPath & "VBAProjectFiles"
    Else
        FolderWithVBAProjectFiles = "Error"
    End If
    
End Function

Function DeleteVBAModulesAndUserForms()
        Dim VBProj As VBIDE.VBProject
        Dim VBComp As VBIDE.VBComponent
        
        Set VBProj = ActiveWorkbook.VBProject
        
        For Each VBComp In VBProj.VBComponents
            If VBComp.Type = vbext_ct_Document Then
                'Thisworkbook or worksheet module
                'We do nothing
            Else
                VBProj.VBComponents.Remove VBComp
            End If
        Next VBComp
End Function

Open in new window

Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Rob Henson

ASKER
@aikimark - I don't believe an Add-In will be suitable as that would be specific to a machine.  Although I am administering these Project files and implementing this feature they are looked after on a daily basis by a group of Project Managers in various offices.  Also we have hot-desk policy in our workplace so can't guarantee which desk we will be using.

@Martin - I will try Ron De Bruin's code. The note that you highlight is what I want to do anyway, remove all and leave only the one that I import which has the function in it.

Thanks
Rob
Rob Henson

ASKER
I get a Compile error on this line:

Dim objFSO As Scripting.FileSystemObject

and on:

Dim VBProj As VBIDE.VBProject

I am using Excel 2010, does that make a difference?
SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Rob Henson

ASKER
Norie, how do I check to see if I have or get the references and libraries?

If they aren't standard with Excel 2010 then I doubt I will be able to download. We have very strict download protocols because of the nature of our work.

Thanks
Rob
Your help has saved me hundreds of hours of internet surfing.
fblack61
Rob Henson

ASKER
Found them in the References list and ticked to "activate" them.

Should the script from Ron now just work???

It would appear not.

My References dialogue looks like:References
Should there be anything else included?
Martin Liss

Try it and see.
Rob Henson

ASKER
Still get the same error. Object not defined.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER CERTIFIED SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Rob Henson

ASKER
Travelling at the minute so won't be able to check until back in the office tomorrow.
aikimark

You could reference the function with a fully pathed workbook name.
Example:
='C:\Users\AikiMark\Documents\CodeMaster.xls'!AllComments(A2:D4)
='\\AllUsers\CommonCode\CodeMaster.xls'!AllComments(A2:D4)

Open in new window

Rob Henson

ASKER
Surely, having the function in a separate workbook would have the same issues as an Add In?

Each user would have to have a copy of the Codemaster file in their User directory.

Or.... could the file containing the function be in the same directory as the Project Files??? Currently in the same directory there is a file that gets used by all Project files for reference for exchange rates, period dates etc etc.
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
aikimark

@Rob

It is another way to let the user know that they need to do something.
Rob Henson

ASKER
Sorry Aikimark, don't understand that last comment!!

I am not expecting the users to do anything at all. They are filling in effectively a table with variance analysis explanations consisting of columns for Date, Value and Reason. There will be multiple lines in the table for numerous variances.

The function then collates the comments into one cell so that a consolidator file that pulls info from all the files can just look at the one cell to get the comments.
aikimark

@Rob

If you can't add a module to the workbooks or have the people/group policy/administrative automation do an add-in to the users'  Excel environments, then what kind of 'magic' do you expect?  You could perform the concatenation with an external batch program or as part of the importing/consolidation process as a work-around to 'magic'.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Rob Henson

ASKER
I already have the Function written to do the concatenation 'magic' and I am wanting to distribute that into 70+ project files. The consolidation to the summary file is then just simple formula linking to a specific cell/range.

I can do the distribution manually by opening each file and copy and pasting in the VB Editor; and removing other surplus modules while I am in the file.

I was looking for a VBA script (such as Ron De Bruin's code) that would do the clean-up and import for me at the click of a button (or wave of a wand!!). I already have a short script that is copying a sheet from a template file which has the table and concatenation function on it; it is then the copying of the VBA behind the function that I need to copy in.

Unfortunately, I can't get Ron's code to work.

Are you able to answer the question regarding having the function in a central file that each of the project files already link to?

Thanks
Rob
Martin Liss

Unfortunately, I can't get Ron's code to work.
Did you try the version I modified? If so please explain what doesn't work.
aikimark

You could include a hyperlink cell that the user can click if they don't have the workbook with the code.  That still means that the data sheets, themselves would need to be updated.
Example:
=HYPERLINK("c:\users\Aikimark\documents\codemaster.xls","AddMissingWorkbook")

Open in new window

A simpler solution would be to change the data sheets workbook to add the necessary code or open (read only) workbook with the code.  That still means changing something.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
Rob Henson

ASKER
Hi Martin, sorry hadnt seen the updated code. I am away from work now so will try it tomorrow.
Rob Henson

ASKER
Hi Aikimark, I am getting confused by your suggestion.

I have written a basic Function script that looks at a range and concatenates the text from each cell in that range with a carriage return. This function gets used on a separate worksheet. The function script is on a separate standard module.

I am going through a number of project files copying the worksheet and the module from a template file. The template file will be used for future projects.

I have written a small script that is copying the worksheet and wanted to add to it extra lines for copying the module or just the function script.

If instead I can reference the function in a formula when the function is in a module in another workbook I would happily do that but not via hyperlink or anything, just a straight formula as it would be if the function was in the same workbook.

Thanks
Rob
aikimark

You can reference code in another workbook, but that workbook needs to be open.  Clicking on a hyperlink will do that.

You can push the code in different ways (already mentioned) and can automate the process with VBScript, Powershell, and possibly through an AD group policy.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Martin Liss

Ron's code assumes that the code that I posted will be in workbook that is the driver of, rather than the target of the code, and that a second workbook will be open which will be where the imported module(s) will wind ip.
aikimark

You can also provide a link for the user that will invoke a script that will open both workbooks.
Rob Henson

ASKER
HI Martin,

That now appears to be working with a test file. I will see if I can implement it with the real files.

I already have the Module exported so I only need the Delete existing and Import routines.

I will let you know how I get on.

Thanks
Rob
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
Rob Henson

ASKER
Got there in the end.

Many thanks to all who contributed.

Thanks
Rob
Martin Liss

You're welcome and I'm glad I was able to help.

In my profile you'll find links to some articles I've written that may interest you.

Marty - Microsoft MVP 2009 to 2016
              Experts Exchange MVE 2015
              Experts Exchange Top Expert Visual Basic Classic 2012 to 2015
Rob Henson

ASKER
Hi Martin,

I will be raising a follow on question to this shortly. Your input will be much appreciated.

Thanks
Rob
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.