VBA: How to get a (more) dynamic file name? - excel

So I have a currently working VBA script. I just want to edit the name by which the loop saves files.
I'll give a quick description of what it is currently doing. Basically it loops a set of actions for a defined range of rows, here A2:A72. The is a 'main' workbook where this loop is done is where all the input data is collected. Each row is a separate subject's input data and is copy/pasted into a template in a different workbook. Solver is then run to adjust the template for the given input data. Then it saves and names file as the text in the first cell of the row that was copy pasted. (ie A2,A3,A4,etc..) It then loops this for every row and every row will have its own template set up and saved separately.
This is ALMOST how I ideally want it to work.
I just want it save the File name not just as A2, but as =C2&" - "&A2
I tried using this that was suggested by someone
fName = Range("C" & c.Row) & Range("A" & c.Row)
But when I tried I would get a Method SaveAs error. On the watch view I could see it was because it wasn't reading the fName so it was just the file path in the script value. I changed it back to c.Value and then it started working by naming the file as the A column cell. Admittedly, I don't really understand how c.Value is returning column A which makes it harder for me to figure out how to modify it to get what I want.
Anyway here is the script as I currently have it:
Sub RunModels()
Dim fPath As String
Dim strTemplate As String
Dim fName As String
Dim wb As Workbook
Dim c As Range
Dim rngLoop As Range
'Where will files get stored?
fPath = "H:\ACQUISITIONS\Personal (D-AP)\Gmo\ALL MF"
'Where is the template file?
strTemplate = "H:\ACQUISITIONS\Personal (D-AP)\Gmo\ALL MF\Garden Grove - 11121 Chapman Ave.xlsm"
'Error check
If Right(fPath, 1) <Application.PathSeparator Then
fPath = fPath & Application.PathSeparator
End If
Application.ScreenUpdating = False
'Set Loop
Set rngLoop = ThisWorkbook.Worksheets("Sheet1").Range("A2:A72")
'Set Looped Actions
For Each c In rngLoop.Cells
'Open the template file
Set wb = Workbooks.Open(strTemplate)
'Add some data to the template file
c.EntireRow.Copy Destination:=wb.Worksheets("Insert
Sheet").Range("A2")
SolverOk SetCell:="$H$20", MaxMinVal:=3, ValueOf:=1.2, ByChange:="$F$35", Engine:=1, EngineDesc:="GRG Nonlinear"
SolverSolve
'Dynamic File Naming
fName = c.Value
'Save the file and close
wb.SaveAs Filename:=wb.Path & Application.PathSeparator & fName
wb.Close
Next c
Application.ScreenUpdating = True
End Sub
Thank you very very much for all and any help!!

You should not use wb.Path wb is assigned to the workbook, where fPath is your folder path, so use:
Filename:=fPath & "\" & fName & ".xlsx"
or ".xlsm" as required.
To assign fName use:
fName = c.Offset(, 2).Value & " - " & c.Value

The code assigns the variable c to each cell in the range A2:A72 in turn - so at the moment it is saving the code 71 times. The code
fName = Range("C" & c.Row) & Range("A" & c.Row)
would produce c2 & A2 on the first time through, and then C3 & A3 on the second (and so on. I suspect you'd like it to always use c2 and then add the value in A - in which case you'd need
Fname = Range("C2") & "- " & c

Related

Pulling file names from SharePoint and saving to SharePoint, using VBA

I'm trying to adapt an Excel form I created that uses drive locations to save copies of the form, to work with SharePoint in a similar manner. Currently, the first macro is set up such that it will search the contents of a particular folder to determine the next available number in the queue (i.e. if 1, 2 and 4 already exist, it will assign 3) and save the sheet as that next available number. When the sheet is complete, the second macro will save the file with a specified name based on data within the sheet, in another specified location (again based on data defined within the sheet). The drive is in the process of being retired in our company and everything moved to Cloud-based storage, so I would like a way to complete the same actions but using SharePoint directories.
The code for the first macro is as follows:
Dim strDir As String
Dim file As Variant
Dim savename As Integer
Dim savename_string As String
strDir = "R:\Queue\"
savename = 1
savename_string = CStr(savename)
file = Dir(strDir)
While (CInt(savename_string) = savename)
If file <> (savename & ".xlsm") Then
If file = "" Then
savename = savename + 1
Else
file = Dir
End If
ElseIf file = (savename & ".xlsm") Then
savename = savename + 1
savename_string = CStr(savename)
file = Dir(strDir)
End If
Wend
ActiveWorkbook.SaveAs ("R:\Queue\" & savename_string & ".xlsm")
And then the code for the second macro is as follows:
Dim answer As Integer
Dim error As Integer
Dim delete As String
answer = MsgBox("Are you sure you want to save sheet & close?", vbYesNo + vbQuestion, "WARNING")
If answer = vbYes Then
'Define PWO, assembly, terminal, strand, and gauge As Strings, and define which cells they are on the sheet
delete = ActiveWorkbook.Name
ActiveWorkbook.SaveAs ("R:\" & terminal & assembly & Space(1) & gauge & strand & Space(1) & PWO & Space(1) & Format(Now(), "MM-DD-YYYY") & ".xlsm")
Kill ("R:\Queue\" & delete)
ActiveWorkbook.Close
Else
Exit Sub
End If
Currently the second macro works correctly when replacing the locations with the SharePoint URL locations, but when doing the same with the first macro, it returns an error message "Bad file name or number" at the line file = Dir(strDir). Can I get this code in working order, or is there a better way I should go about this? Thanks!

Excel vba for exporting cell content to TXT file

I have an Excel file (https://www.dropbox.com/s/hv9u68s136es190/Example2.xlsx?dl=0) with in column A all the persons and in the cell next to there name text (column B).
I want to save for every person a text file containing the text in the cell next to there name.
The filename should be called like the persons name.
So in this case i would have three text files. I do not know how to manage this using VBA in Excel.
Can someone help me with this?
Try this code, please. But, you must initially try something on your own. We usually help people correct their code and learn...
The text files will be named like the people names in column A. The folder where they will be saved will be the one of the workbook which keeps the active sheet. You can define it as you need, of course.
Option Explicit
Sub SaveTxtNamePlusTekst()
Dim sh As Worksheet, lastR As Long, i As Long, strPath As String
Set sh = ActiveSheet ' use here the sheet you need
strPath = sh.Parent.path 'you can define here the path you wish...
If Dir(strpath, vbDirectory) = "" Then MsgBox "The folder path is not valid...": Exit Sub
lastR = sh.Range("A" & Cells.Rows.Count).End(xlUp).row 'Last row in A:A
For i = 2 To lastR
'calling a Sub able to create a text file in a folder and put text in it
WriteText sh.Range("A" & i).value, strPath, sh.Range("B" & i).value
Next i
End Sub
Private Sub WriteText(strName As String, strPath As String, strText As String)
Dim filePath As String
filePath = strPath & "\" & strName & ".txt" 'building the txt file path
FreeFile 1
Open filePath For Output As #1
Print #1, strText 'write the text
Close #1
End Sub

Consolidating data from multiple excel workbook into master workbook and eliminate duplicate append

I'm stuck in a problem in VBA while consolidating data from other workbook to master work book and using file name and path name is variable which is changing dynamically in loop i searched but i only find hard coded path so i'm posting here following is my code.
Sub Append()
'Append data from other files
Path = "E:\NPM PahseIII\"
Dim c As Range
'find the first empty cell in ColA
Set c = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Offset(2, 0)
Filename = Dir(Path & "*.xlsx")
Do While Filename <> ""
If InStr(Filename, ".") > 0 Then
Filenamenoext = Left(Filename, InStr(Filename, ".") - 1)
End If
c.Value = Filenamenoext
Set c = c.Offset(1, 0)
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
Windows("Master sheet").Activate
Selection.Consolidate Sources:=Array("'Path & [Filename]Sheet1'!$B$2:$B$5"),
Function:=xlSummary
Workbooks(Filename).Close
Filename = Dir()
Loop
End Sub
The first problem is that this program gives me the error
Object doesn't support this property or method
at this line
Selection.Consolidate Sources:=Array("'Path & [Filename]Sheet1'!$B$2:$B$5"),
Function:=xlSummary
secondly i want that when first time data is appended by running the code again if there is no change in the other files data then code should not append duplicate again.
Note that in that string "'Path & [Filename]Sheet1'!$B$2:$B$5" the Path and Filename is not considered as a variable but as a hard coded string!
You must use something like
"'" & Path & "[" & Filename & "]Sheet1'!$B$2:$B$5"
if you want to use the variable values.
Also according to the documentation of the Range.Consolidate method the constant of the xlConsolidationFunction is not Function:=xlSummary but Function:=xlSum.
Also note that Selection is very undefined and can be anywhere in that worksheet. I recommend to read How to avoid using Select in Excel VBA and reference your ranges, workbooks etc without using .Activate and .Select or Selection. at all.

Excel VBA function to get value using variables from closed workbook

I have the following function which I use to fetch data from a closed workbook:
Public Function GetValue(path, file, sheet, ref)
' Retrieves a value from a closed workbook
Dim arg As String
' Make sure the file exists
If Right(path, 1) <> "\" Then path = path & "\"
If Dir(path & file) = "" Then
GetValue = "File Not Found"
Exit Function
End If
' Create the argument
arg = "'" & path & "[" & file & "]" & sheet & "'!" & _
Range(ref).Range("A1").Address(, , xlR1C1)
' Execute an XLM macro
GetValue = ExecuteExcel4Macro(arg)
End Function
Then I have the following test routine which works:
Sub TestGetValue()
p = Range("B2").Value
f = Range("B3").Value
s = "TOTAL"
a = "D" & ActiveCell.Row + 3
MsgBox GetValue(p, f, s, a)
End Sub
However, if I use the GetValue function in an Excel cell providing all 4 parameters exactly like in the routine, it always throws a #VALUE! error.
Why does it work in a routine and not while being called as a function?
After several attempts I did find 3 solutions:
Using a function with "ExecuteExcel4Macro"
Opening the other workbook in the background by vba procedure, then copy/pasting data
Creating external references by vba procedure, then leaving only values
First one while being able to use it as an excel custom formula, it is the slowest, especially when you need data from a specific range. So I don't recommend this option as it would slow your workbook down a lot.
Second option while being much faster, still takes around 15 seconds to get data from several ranges across 2 workbooks.
Third option was the fastest. Like an instant really less than 1 second execution time during which data was pulled from 2 closed workbooks and for different ranges.
Here's the 3rd option's procedure:
Sub getDS()
asname = "data"
bsname = "Anual"
csname = "Total"
filename = Sheets("data").Range("B64").Value
path = Sheets("data").Range("B63").Value
Dim ws As Worksheet
Set ws = Sheets("data")
With ws.Range("D4:D34")
.ClearContents
.Formula = "='" & path & "[" & filename & "]" & bsname & "'!R11"
.Value = .Value
End With
With ws.Range("J4:J34")
.ClearContents
.Formula = "='" & path & "[" & filename & "]" & bsname & "'!U11"
.Value = .Value
End With
With ws.Range("J37:J37")
.ClearContents
.Formula = "='" & path & "[" & filename & "]" & csname & "'!DW96"
.Value = .Value
End With
End Sub
I found this by far to be the BEST and FASTEST VBA solution to fetch data in an INSTANT from closed workbooks (with variables) without opening them.

VBA code from Excel 2003 does not work properly in Excel 2010 / 2013

I am really new to VBA but I have managed to write some code basing on examples mainly from this site.The piece of code is supposed to copy data from multiple csv files into one xls file (and then to rename the source csv files). While it works fine in Excel 2003, it does not work so well in Excel 2010 / 2013 (I could not test it in E2007). It appears to stop after copying data from the first csv file into xls file, so after this line:
Range("B4:AZ" & LR).Copy wbDEST.Sheets("Data").Range("B" & NR)
with Error 1004 "Application-defined or Object-defined error". Debugger highlights the next line, i.e.
NR = wbDEST.Sheets("Data").Range("B" & Rows.Count).End(xlUp).Row + 1
I just cannot see what is wrong with it as the same line is used at the beginning of the code and does not stop there.
I would appreciate your advice.
And here is the whole code:
Option Explicit
Sub ImportData()
Dim fPATH As String, fNAMEcsv As String, fNAMEbak As String
Dim LR As Long, NR As Long
Dim wbSOURCE As Workbook, wbDEST As Workbook
Set wbDEST = Workbooks.Open("C:\Utility\Data.xls")
NR = wbDEST.Sheets("Data").Range("B" & Rows.Count).End(xlUp).Row + 1
fPATH = "C:\Utility\DataFiles\" 'remember the final \ in this string
fNAMEcsv = Dir(fPATH & "*.csv") 'get the first filename in fpath
Do While Len(fNAMEcsv) > 0
Set wbSOURCE = Workbooks.Open(fPATH & fNAMEcsv, Local:=True) 'open the file
LR = Range("B" & Rows.Count).End(xlUp).Row 'how many rows of info?
If LR > 1 Then
Range("B4:AZ" & LR).Copy wbDEST.Sheets("Data").Range("B" & NR)
NR = wbDEST.Sheets("Data").Range("B" & Rows.Count).End(xlUp).Row + 1
End If
wbSOURCE.Close False 'close data workbook
fNAMEbak = fNAMEcsv & ".bak" 'rename imported file to .bak
Name (fPATH & fNAMEcsv) As (fPATH & fNAMEbak)
fNAMEcsv = Dir 'get the next filename
Loop
MsgBox ("Completed. Check results on PRINTOUT sheet.")
End Sub
Try qualifying your Rows:
NR = wbDEST.Sheets("Data").Range("B" & wbDEST.Sheets("Data").Rows.Count).End(xlUp).Row + 1
The problem could be this:
Here you open a new "source" workbook wbSOURCE:
Set wbSOURCE = Workbooks.Open(fPATH & fNAMEcsv, Local:=True) 'open the file
Maybe it is a workbook in the "new" format (Excel 2007 and later, *.xlsx & Co.). Since you just opened it, it is the active workbook, and therefore the unqualified Rows.Count will return 1048576.
And maybe your destination workbook wbDEST is in the "old" Excel 2003 format (*.xls & Co.). So when you say this:
NR = wbDEST.Sheets("Data").Range("B" & Rows.Count).End(xlUp).Row + 1
you're trying to access wbDEST.Sheets("Data").Range("B" & 1048576) but cell B1048576 doesn't exist in this 2003-format workbook. This will indeed throw an Error 1004 "Application-defined or Object-defined error".
The solution would then be to fully qualify Rows.Count like this:
NR = wbDEST.Sheets("Data").Range("B" & wbDEST.Sheets("Data").Rows.Count).End(xlUp).Row + 1
It's always a good idea to fully qualify everything and not let it depend on the vagaries of Excel.

Resources