How can I change my variant referencing to an input box? - excel

I'm trying to simplify a file_split script to a point of self-service in my dept. No one really has any understanding of the language, so I was checking to see if any of this could be further simplified so coworkers don't have to update the code from the editor pane.
for instance, I have things like Basepath to designate where the files will be saved off. How can I change
Dim Basepath As String
Basepath = "C:\Users\File Cuts\"
directory as string
to something like this where a user can select a folder pathway?
Dim Basepath as filedialog
with basepath
.title = "Select save location"
.directory = .selecteditems(1)
end with
and then instances where I have specific columns to reference (target value columns for each new file, naming convention columns, etc...)
as in:
Dim Manager_Name, Login_ID, Leader
Manager_Name = SourceData(i,4)
Login_ID = SourceData(i,5)
Leader = SourceData(i,9)
to be inputted by an input box for column letter like:
Dim column_selection as variant
column_selection = InputBox("Enter Column Letter")
Manager_Name = SourceData(i,column_selection)
There are quite a few references that I'd like to see if I could change so that edits could be made without actually touching the code (the column ranges where variants like name, and login ID will be changing a lot)
rest of code:
Option Explicit
Sub File_Splits()
Dim Wb As Workbook
Dim SourceData, Mgr_Name, Login_Id
Dim i As Long, j As Long, k As Long, a As Long
Dim Destination_Cell As Range
Dim Basepath As String, strNewpath As String, strLeader As String
Basepath = "C:\File Cuts\" '1. paste in file save pathway, keep last \
Set Wb = Workbooks.Open("C:\File_Split_Mgr_Template.xlsx") '2. paste template ws address here
Set Destination_Cell = Wb.Worksheets("Manager Data").Range("A2") '3. Update worksheet name and target cell
With ThisWorkbook.Worksheets("Roster")
SourceData = .Range("I10", .Range("A" & Rows.Count).End(xlUp)) '4. change I10 to your last column letter, dont change the number(keep the 10)
End With
Wb.Activate
Call Speed_Up_Code(True)
For i = 1 To UBound(SourceData)
If SourceData(i, 5) <> Login_Id Then '5. change the 1 to login column #
If i > 9 Then
Destination_Cell.Select
strNewpath = Basepath & strLeader & "\" 'comment this out if folders aren't needed
If Len(Dir(strNewpathD, vbDirectory)) = 0 Then 'comment this out if folders aren't needed
MkDir strNewpath 'comment this out if folders aren't needed
End If 'comment this out if folders aren't needed
Wb.SaveCopyAs strNewpath & _
ValidFileName(Login_Id & "_" & Mgr_Name & "_File Name.xlsx") '6. update file name
End If
With Wb.Worksheets("Manager Data") '7. change to template sheet
.Rows(2 & ":" & .Rows.Count).ClearContents '8. change 2 to row after header(s)--if header isn't in row 1
End With
Mgr_Name = SourceData(i, 4) '9. change 1 to mgr name column
Login_Id = SourceData(i, 5) '10. change 2 to login ID column
strLeader = SourceData(i, 9) '11. change 5 to lvl 3 mgr column
j = 0
End If
a = 0
For k = 1 To UBound(SourceData, 2)
Destination_Cell.Offset(j, a) = SourceData(i, k)
a = a + 1
Next
j = j + 1
Next
If Len(Dir(strNewpath, vbDirectory)) = 0 Then
MkDir strNewpath
End If
SaveCopy Wb, strNewpath, Login_Id, Mgr_Name
Call Speed_Up_Code(False)
End Sub
Public Sub SaveCopy(Wb As Workbook, strNewpath As String, Login_Id, Mgr_Name)
Wb.SaveCopyAs strNewpath & _
ValidFileName(Login_Id & "_" & Mgr_Name & "_File Name.xlsx") '12. update file name
End Sub

Have you considered having a sheet called something like "Configuration" where users write to and your script can read from. Hidden or protected if necessary
For example, list all your configuration description in col A, and the user fills in the value next to in col B, So if A1 contains the text "Manager Name Column [A-Z] =" the user enters the value "D" or 4 in cell B1. The script become Mgr_Name = SourceData(i, wsConfig.range("B1")). I guess you could add validation to their entries.
Layout the sheet like a form in logical groups and highlight where the entry cells are. In a case like entering column names I would put them horizontal with the descripting above and entry cell below, that seems more natural. Protect all the cells except the highlighted ones.

Related

How to use VBA Excel Code to display a pop-up message to users that have out of date information

I want to have a pop-up appear when the spreadsheet is opened.
Each tech is required to log their issues in the spreadsheet. When the sheet is opened, I would like it to check for the user's username against the issue list and alert them of any that have exceed their time estimate. If any issue is beyond the estimated time frame, I want the sheet to pop-up a dialog box or windows saying you have Issues A,B,C,, and that those issues need to be closed or extended.
Col A is issue Number.
Col B is the date an issue was started.
Col C is the number of Days expected for issue to be resolved (30, 60, 90, X - using a dropdown menu for these options. X Meaning it is going to be an extended time frame; unknown at entry.)
Col D is the status either Closed or Open also controlled by dropdown.
Col E is the closure date which I'm already handling using a VBA code to auto-populate when closed is chosen from dropdown.
Col F is the name of the tech handling issue.
SS of Spreadsheet
Here is where I am with the code
'DECLARE VARIABLE
Dim x_matrix As Range
Dim x_copyrange, sheet_name, issueString, currentTechName As String
Dim x_step, x_fnl_row As Long
Dim issIDCol, issStatCol, issTechCol, IssLogDateCol As Variant
Dim IssExpClosCol As Variant
'DEFINE VARIABLE
sheet_name = "Log" 'PUT YOUR SHEET NAME
issueString = "Alerts have been found to be late, Please extend or Close"
issIDCol = Columns(1) 'Put Your Report ID Column
currentTechName = Application.UserName 'returns username currently using sheet
issTechCol = Columns(6) 'The Tech name column
issStatCol = Columns(4) ' The Issue Status Column
IssLogDateCol = Columns(2) 'Column where you are logging the date issue reported
IssExpClosCol = Columns(3) '30, 60, 90, X Column
'CREATE MATRIX
x_fnl_row = Worksheets(sheet_name).Cells(Rows.Count, 1).End(xlUp).Row
'Find last row of Log # Col & used to make the loop larger each time an entry is added
Let x_copyrange = "a" & 1 & ":" & "F" & x_fnl_row
'sets a1 to bottom of last entry in F as a range
Set x_matrix = Worksheets(sheet_name).Range(x_copyrange)
'Sets the parameters for X_Matrix as a range on the worksheet
'LOOP TO
x_step = Rows(2) 'Skips the header row at the top of sheet so loop will not loop through row 1
Do While x_step <= x_fnl_row 'Sets the loop to run through the range as long as the final row is farther down then the first row
'This is your Loop
'Make your Conditions Here
'Issue is open and issue date starting is greater than expected closure date.
'Tech Names Match
If x_matrix(x_step, IssExpClosCol) <> "PPSC Closure" Then ' Xmatrix is the whole range (Xstep is the rows of range, tells it what col to search)
If x_matrix(x_step, issTechCol) = currentTechName And _
x_matrix(x_step, issStatCol) = "OPEN" And _
Now() > x_matrix(x_step, IssLogDateCol) + x_matrix(x_step, IssExpClosCol) _
Then
issueString = issueString + x_matrix(x_step, issIDCol) + ", "
End If
End If
x_step = x_step + 1
Loop
MsgBox (issueString)
End Sub
I posted some code below that works based on the how i set up my spreadsheet columns (see attached picture). I think this might be what you are asking for. Take a look see if it will work for you.
Sub standard()
'DECLARE VARIABLE
Dim x_matrix, y_matrix, z_matrix As Range
Dim x_copyrange, y_copyrange, z_copyrange, sheet_name, issueString, currentTechName As String
Dim x_step, y_step, z_step, x_fnl_row, y_fnl_row, z_fnl_row As Integer
Dim issIDCol, issStatCol, issTechCol, IssLogDateCol, IssExpClosCol As Integer
'DEFINE VARIABLE
sheet_name = "Log" 'PUT YOUR SHEET NAME
issueString = "Alerts have been found to be late, Please extend or Close"
issIDCol = 1 'Put Your Report ID Column
currentTechName = Application.UserName 'Sound like you need to add your VBA here to know the tech using the sheet
issTechCol = 6 'The Tech name column
issStatCol = 4 ' The Issue Status Column
IssLogDateCol = 2 'Column where you are logging the date issue reported
IssExpClosCol = 3 '30, 60, 90, X Column
'CREATE MATIX
x_fnl_row = Worksheets(sheet_name).Cells(Rows.Count, issIDCol).End(xlUp).Row
Let x_copyrange = "a" & 1 & ":" & "e" & x_fnl_row
Set x_matrix = Worksheets(sheet_name).Range(x_copyrange)
'LOOP TO
x_step = 2 'I am guessing you have a Header Row so start at 2
Do While x_step <= x_fnl_row
'This is your Loop
'Make your Conditions Here
'Issue is open and issue date starting is greater than expected closure date.
'Tech Names Match
If x_matrix(x_step, IssExpClosCol) <> "X" Then
If x_matrix(x_step, issTechCol) = currentTechName And _
x_matrix(x_step, issStatCol) <> "Closed" And _
Now() > x_matrix(x_step, IssLogDateCol) + x_matrix(x_step, IssExpClosCol) _
Then
issueString = issueString + x_matrix(x_step, issIDCol) + ", "
End If
End If
x_step = x_step + 1
Loop
MsgBox (issueString)
End Sub

Sequencing a part number using User Form

I am completely new in VBA or programming. Right now I am developing a macro for a manufacturing site that inputs process data using Excel's User Forms. One of the things I want this macro to do is to automatically create run numbers for each process. The run number syntax we use is as follows:
V1.yy.mm.dd-1
V1.yy.mm.dd-2
V1.yy.mm.dd-3
Ex V1.20.04.29-1
The way I am trying to set up the run number creation is that when I select an item from a ComboBox the part number gets created into a TextBox to later be submitted into the corresponding database. I am not sure how to create a sequence after the Prefix = V1.yy.mm.dd-, I tried to use a CountIf application that would count the number of Prefixes with the same date in the spreadsheet for sequencing, but it seems the function does not work for partial matches. I tried to use the following but I can't get it to work. I am sure there are simpler ways to do this, can you give me a few suggestions? Thanks
This is the code I wrote so far:
Private Sub ComboBox1_Change()
If Me.ComboBox1.Value <> "" Then
Dim Prefix As String
Dim mm, dd, yy As String
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("2- V1 Loading (2)")
Dim s As Long
s = 1 + sh.Application.Count(Application.Match(Prefix, Range("B:B"), 0))
mm = Format(Date, "mm")
dd = Format(Date, "dd")
yy = Format(Date, "yy")
Prefix = "V1." & yy & "." & mm & "." & dd & "-"
v1 = "V1." & yy & "." & mm & "." & dd & "-" & "" & s
Me.TextBox6.Value = v1
End If
Maybe something like this ?
Private Sub ComboBox1_Change()
If Me.ComboBox1.Value <> "" Then
Set sh = ThisWorkbook.Sheets("2- V1 Loading (2)")
oDate = Format(Date, "yy.mm.dd")
oConst = "V1." & oDate & "-"
Range("B1:B10000").Copy Destination:=Range("zz1") 'copy all the item to helper column
Range("zz:zz").Replace What:=oConst, Replacement:="" 'get only the number from all the items with the current date
nextNum = Application.Max(Range("zz:zz")) + 1 'get the next number
MsgBox oConst & CStr(nextNum) 'this line only for checking
Range("zz:zz").ClearContents 'clear the helper column
Me.TextBox6.Value = oConst & CStr(nextNum)
End If
But this assuming that the item number in columns B is only at the same day.
If for example there is a forgotten data from any day before the current day, and this want to be inputted with that day and the next number, it need an input box or maybe a cell in sheet where the value is that day, then it will give the last number of that day.
Suppose the data in column B is something like below:
If the code is run today, it will show V1.20.04.30-4 as the next number. With the same data like above, if the code is run tomorrow, it will give V1.20.05.01-1.
To get the next number from yesterday (29 Apr 2020), the code need more line - which is to know on what day the code must get the next number.
Or this kind of line maybe is shorter:
oConst = "V1." & Format(Date, "yy.mm.dd") & "-"
nextNum = oConst & Application.WorksheetFunction.CountIf(Range("B:B"), "*" & oConst & "*") + 1
MsgBox nextNum
There are a few ways you could go about this but I'd say the easiest would be to put the incrementing run number in a separate cell somewhere on your worksheet (or another one if you want) to reference each time.
For example:
When the data is entered onto your 'database' sheet, write the run value to ThisWorkbook.Sheets("2- V1 Loading (2)").Range("AZ1").
Then in your code check that value like so:
Private Sub ComboBox1_Change()
If Me.ComboBox1.Value <> "" Then
Dim Prefix As String
Dim mm, dd, yy As String
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("2- V1 Loading (2)")
Dim s As Long
s = 1 + sh.Range("AZ1").Value
mm = Format(Date, "mm")
dd = Format(Date, "dd")
yy = Format(Date, "yy")
Prefix = "V1." & yy & "." & mm & "." & dd & "-"
v1 = "V1." & yy & "." & mm & "." & dd & "-" & s
Me.TextBox6.Value = v1
Presuming that the reference numbers are written to column B of the 2- V1 Loading (2) tab then the next number must always be the one found at the bottom of the column + 1. If there is no number for that date than the new sequential number should be 1. The code below implements that method
Function NextRef() As String
' 016
Dim Fun As String
Dim Counter As Integer
Dim Rng As Range
Dim Fnd As Range
Dim Sp() As String
Fun = Format(Date, """V1.""yy.mm.dd")
With ThisWorkbook.Worksheets("2- V1 Loading (2)")
' start in row 2 (row 1 holding column captions)
Set Rng = .Range(.Cells(2, "B"), .Cells(.Rows.Count, "B").End(xlUp))
End With
If Rng.Row > 1 Then ' skip, if the column is empty
' finds the first occurrence of Ref from the bottom
Set Fnd = Rng.Find(What:=Fun, _
After:=Rng.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchDirection:=xlPrevious)
If Not Fnd Is Nothing Then
Sp = Split(Fnd.Value, "-")
If UBound(Sp) Then Counter = Val(Sp(1))
End If
End If
NextRef = Fun & -(Counter + 1)
End Function
You can use the function simply like ComboBox1.Value = NextRef. However when and how to call that line of code is a bit unclear in your design as published. Especially, it's not clear why you would want it in a ComboBox at all, given that the box might also contain other information. Your idea to use the Change event may not work as intended because that event occurs with every letter the user types. I have tested this:-
Private Sub ComboBox1_GotFocus()
' 016
With ComboBox1
If .Value = "" Then .Value = NextRef
End With
End Sub
The next reference number is inserted as soon as you click on the ComboBox. It works but it doesn't make sense. I think now that you have the function that does the work you will find a way to deploy it. Good luck.

Concatenate path and filename recursively

I have an output exported to Excel which lists paths and filenames.
The paths and filenames are on separate rows however. If the path is consistent the filename is simply listed on the next row. Then the next path is on the next line followed by filenames ect.
C:\
file1.doc
C:\Windows\
file2.doc
file3.doc
file4.doc
C:\Windows\Folder\
file5.doc
I need to concatenate all the paths with the filenames. All paths begin with c:\ (or other drive letters which can be defined). For the example above the following output is required:
C:\file1.doc
C:\Windows\file2.doc
C:\Windows\file3.doc
C:\Windows\file4.doc
C:\Windows\Folder\file2.doc
Happy to have white spaces as these can be filtered out in Excel.
Thanks,
Jono
VBA approach:
Sub test()
Dim ws As Worksheet
Dim iRow As Long
Dim i As Integer
Dim strFirstValue, strScndValue, strNewValue, strValue As String
Dim startFlag, endFlag As Boolean
Set ws = Sheets(1)
iRow = ws.Range("A1048576").End(xlUp).Row
strFirstValue = ws.Range("A2:A2")
strFirstValue = "": strScndValue = ""
startFlag = False
strFirstValue = ws.Range("A2:A2")
For i = 2 To iRow 'Assuming you have header, otherwise change 2 to 1
If endFlag Then
strFirstValue = ws.Range("A" & i & ":A" & i)
End If
strValue = strFirstValue
strScndValue = ws.Range("A" & i + 1 & ":A" & i + 1)
If InStr(strValue, ":") > 0 Then
startFlag = True
If Not strScndValue = "" Then
If Not InStr(strScndValue, ":") > 0 Then
strNewValue = strFirstValue & strScndValue
ws.Range("B" & i + 1 & ":B" & i + 1) = strNewValue
endFlag = False
Else
endFlag = True
End If
End If
End If
Next i
'To remove the row with drive info
For i = 2 To iRow
strValue = ws.Range("B" & i & ":B" & i)
If strValue = "" Then
ws.Range("B" & i & ":B" & i).EntireRow.Delete
End If
Next i
Set ws = Nothing
End Sub
Before:
After:
With data in column A, this macro will put the results in column B:
Sub dural()
Dim s As String, J As Long, r As Range
J = 1
For Each r In Intersect(ActiveSheet.UsedRange, Range("A:A"))
s = r.Text
If s = "" Then Exit Sub
If Right(s, 1) = "\" Then
pref = s
Else
Cells(J, 2).Value = pref & s
J = J + 1
End If
Next r
End Sub
Non-VBA solution, which will require some helper columns:
Assuming your data is in column A, and you don't care about sorting the results / having blanks within the results:
Put this in cell B2 and copy down [I recommend you have a header row for row 1]
=if(mid(A2,2,2)=":/",A2,B1)
This puts the new file path in column B, and if it's not a new file path (doesn't start with "x:/"), it takes the file path from column the previous cell.
In cell C2, copied down:
=if(mid(A2,2,2)=":/","",B2&A2)
This checks if the line you're on is a file path or a file name. If it's a file name, it adds the file name to the file path and displays as a single string. If it's a filepath, it returns a blank.
Alternatively you could save a tiny bit of processing time by using columns B-D instead of B-C. Some calculation is wasted here because we are doing the same check ("does cell A2 include ':/'?") twice, so excel needs to calculate it twice. Like so:
Put this in Cell B2:
=mid(a2,2,2)=":/"
Returns TRUE if the cell in column A is a filepath; returns FALSE if the cell in column A is a filename. Then put this in cell C2 and copy down:
=if(B2,A2,B1)
Works same as above, but uses the test already defined in cell B2. Put this in cell D2 and copy down:
=if(B2,"",B2&A2)
If you do want to sort your results column, there's just 2 extra steps (this is kind of unnecessary, but if you want to present / print your data in some format, you will need to either do this or manually copy + paste values):
Add an extra column to the right of the final column from my above response. Here, you want to check to see whether your current row is a new filepath + filename, or if it is blank (meaning column A was a filepath). I will assume you used my second option above, using columns B-D.
In column E, starting at E2 and copied down:
=if(B2,B1,B1+1)
If B2 is TRUE, the row is a filepath, and doesn't create a new filename + filepath. Therefore, we can keep the last counter. Otherwise, add a new counter.
In column F, starting at F2 and copied down:
=if(row()-1>max(E:E),"",index(D:D,match(row()-1,E:E,0)))
This looks at your results column, column D, which is unsorted and contains blanks. If the current row number in column F (minus 1 for the header row) is no bigger than the biggest counter in column D, it returns the matching item for that row number from column D.
Hope this helps you in similar situations in the future.

Excel - Match item http string and display result

I have column H that contains long GET requests on sheet 1 such as:
H
GET /profiles/text/23493495_3492/g93id93kd
GET /edit/result/393493/te3903k4d
I would like to have a second sheet with the following type of list in columns A and B:
A B
23493495 identifier1
3903k4 realid2
g93id realid3
Ultimately, I would like a function that will search sheet 1 column H for any of the values in sheet 2 column A. Most of the time there is no separator so I need it to search for strings within the GET string. Once a value in sheet 2 column A is matched with a value in sheet 1 column H, I would like the function to take the corresponding text in sheet 2 column B and print it in sheet 1 column I. There may be multiple matches in a cell, so that would need to be taken into account. So if using the example above:
In H1, there would be a match of 23493495 and g93id within the string. I would like sheet 1 column I to display:
I
identifier1, realid3
I initially started with the below code where I had to specify the list but it doesn't use a second sheet or print the corresponding text of the match. So I would rather have something that meets my needs above, but below is an example of what I have tried so far:
=ListSearchB(J2, "23493495 g93id")
With this module I found that I modified a little:
Function ListSearchB(text As String, wordlist As String, Optional caseSensitive As Boolean = False)
Dim strMatches As String
Dim res As Variant
Dim arrWords() As String
arrWords = Split(wordlist)
On Error Resume Next
Err.Clear
For Each word In arrWords
If caseSensitive = False Then
res = InStr(LCase(text), LCase(word))
Else
res = InStr(text, word)
End If
If res > 0 Then
strMatches = strMatches & word
End If
Next word
If Len(strMatches) <> 0 Then
strMatches = Right(strMatches, Len(strMatches))
End If
ListSearchB = strMatches
End Function
That gives me:
23493495g93id in column I, and I wasn't sure how to separate the two with a comma.
In general though, I would prefer, to use some way to pull the list from sheet 2 and display the value in column I as specified initially.
Give this a try - just adjust the sheet names where commented before running
Sub your_sub()
Dim sGet As Worksheet
Dim sIDs As Worksheet
Dim rget As Range
Dim rIds As Range
'ADJUST SHEET NAME
With Worksheets("GET")
Set rget = Range(.Range("H1"), .Range("h" & .Rows.count).End(xlUp))
End With
'ADJUST SHEET NAME
With Worksheets("IDs")
Set rIds = Range(.Range("A1"), .Range("A" & .Rows.count).End(xlUp))
End With
mys = vbNullString
i = 1
For Each cget In rget
For Each cIds In rIds
If InStr(cget.Value, cIds) <> 0 Then
mys = mys & ", " & cIds.Offset(0, 1).Value
End If
Next cIds
If mys <> vbNullString Then
mys = Right(mys, Len(mys) - 2)
'ADJUST SHEET NAME
Worksheets("GET").Range("I" & i).Value = mys
End If
i = i + 1
mys = vbNullString
Next cget
End Sub

VBA Insert function VLOOKUP into range,lookup range in other workbook

VBA Insert function VLOOKUP into range,lookup range in other workbook. The file containing the lookup table is achieved using filename_AcctMgr = Application.GetOpenFilename(, , "Select Acct Mgr File", "Select"), then opening the file. Let's call this workbook2.
In workbook1 I am adding the VLOOKUP formula into "F2" and looking up Column "A" values in workbook2, columns A:C. I Then copy the formula to all rows of column "F".
I cannot find the syntax required to properly reference the workbook2 range in columns A:C.
ActiveCell.Formula = _
"=VLOOKUP(activecell.offset(0,-5).address,'ws.name'!A:C,3,FALSE)"
Can anyone suggest the proper syntax?
Try this:
Range("F2").Resize(10).Formula = "=VLOOKUP(A2,[Book2]Sheet1!$A:$C,3,FALSE)"
Or
Range("F2:F10").Formula = "=VLOOKUP(A2,[Book2]Sheet1!$A:$C,3,FALSE)"
EDIT: Sorry I forgot the piece about the filename as a variable:
Dim MyFile As String
Dim vSplit As Variant
Dim iCnt As Integer
MyFile = Application.GetOpenFilename(, , "Select Acct Mgr File", "Select")
vSplit = Split(MyFile, "\")
iCnt = UBound(vSplit)
vSplit(iCnt) = "[" & vSplit(iCnt) & "]"
MyFile = Join(vSplit, "\")
Range("F2:F10").Formula = "=VLOOKUP(A2,'" & MyFile & "Sheet1'!$A:$C,3,FALSE)"
You will need to add error handling in case someone clicks cancel. Also I doubt you want to add the formula to all rows in column f so just define the range you want. My examples is rows 2 to 10.
I am assuming you want the name of the sheet / range to be in a variable, rather than hard-coded. As it it, you have the name of the variable in the middle of your string, but it will be treated as a string, not a variable containing a string.
I suggest that you do something like the following:
Dim sheetName, lookupFrom, myRange ' always declare your variables
sheetName = "This is the sheet name" ' note I added some spaces to make it challenging
lookupFrom = ActiveCell.Offset(0, -5).address
myRange = "'" & sheetName & "'!A:C" ' putting quotes around the string so it's always valid
ActiveCell.Formula = "=VLOOKUP(" & lookupFrom & "," & myRange & ", 3, FALSE)"
You can of course do this all at once - it just gets messy to look at:
ActiveCell.Formula = "=VLOOKUP(" & ActiveCell.Offset(0, -5).Address & ", '" & sheetName & "'!A:C, 3, TRUE)"
Further note - the sheetName can of course contain the name of the other workbook - but you need name of workbook AND sheet... so
sheetName = "[Book2]Sheet1"
would be fine.
In your example you used ws.name (without proper quoting) - but that would not have given you the full path since you need both the workbook and the worksheet name to make sure you reference the right data. Better be explicit - if Excel can make the wrong assumptions about what you want, it will - and you will be left scratching your head...
Since you actually showed you had opened the book, you have the name of the file (the workbook) in your variable filename_AcctMgr. Then you should be able to use:
sheetName = "[" & filename_acctMgr & "]Sheet1"
and take it from there.

Resources