I just spent a significant amount of time creating identical graphs in several dozen excel files (all containing identically formatted data,) and believe there has to be a more efficient way of completing what I’ve just done.
To simplify things, consider 50 excel documents with data in the same format. Does there exist a method of automatically:
- Creating a simple line graph
- Adding axis labels, a chart label, removing horizontal grid lines
- Including a trend line/R^2 value
- Saving the new workbook to a certain location with “_graphed” appended to the filename
Would this be something that an Excel VBA could be used for?
For this sort of problem I would start by recording a macro of the steps you take manually into a personal macro workbook. You can then look at the code produced by Excel and you may find that you don’t need to make too many changes for this to be useful as a generic procedure.
After testing, if you wanted to take the automation one step further you could write a little procedure to loop through all of the Excel files in a directory and call your chart procedure for each file when it is open. I can dig out come code I wrote doing something similar if it will help.
Here is a thread where I have provided some code to loop through all of the files containing some given text (in this example “.pdf” but could just as easily be “.xls” to cover xlsx, xlsm etc).
Also this example prints out a list of the files it finds to a worksheet. This is a good start to test the results, but once this is okay you would need to replace the line:
Range(c).Offset(j, 0).Value = vFileList(i)
With some code to open that workbook and call your code to generate the chart. Let me know if you get stuck.
I have reviewed the code referred to above and made a few improvements including an additional parameter for you to specify the name of a macro that you want to run against each of the workbooks opened (that meet the condition specified). The macro that you use in the call must exist in the workbook that you are calling all of the other workbooks from (e.g. if the chart macro is in your personal workbook then the code below should also be placed in your personal macro workbook):
Option Explicit Sub FileLoop(pDirPath As String, _ Optional pPrintToSheet = False, _ Optional pStartCellAddr = "$A$1", _ Optional pCheckCondition = False, _ Optional pFileNameContains = "xxx", _ Optional pProcToRunOnWb) On Error GoTo PrintFileList_err ' Local constants / variables Const cProcName = "FileLoop" Dim vFileList() As String ' array for file names Dim i As Integer ' iterator for file name array Dim j As Integer ' match counter Dim c As String ' variables for optional param pProcToRunOnWb Dim vFullPath As String Dim vTmpPath As String Dim wb As Workbook vFullPath = Application.ThisWorkbook.FullName vFileList = GetFileList(pDirPath) c = pStartCellAddr j = 0 For i = LBound(vFileList) To UBound(vFileList) ' if condition is met (i.e. filename cotains text or condition is not required... If pCheckCondition And InStr(1, vFileList(i), pFileNameContains, vbTextCompare) > 0 _ Or Not pCheckCondition Then ' print name to sheet if required... If pPrintToSheet Then Range(c).Offset(j, 0).Value = vFileList(i) j = j + 1 ' increment row offset End If ' open wb to run macro if required... If pProcToRunOnWb <> "" Then Application.DisplayAlerts = False ' set alerts off so that macro can run in other wb vTmpPath = pDirPath & "\" & vFileList(i) Set wb = Workbooks.Open(Filename:=vTmpPath) Workbooks(wb.Name).Activate Application.Run "'" & vFullPath & "'!" & pProcToRunOnWb wb.Close (True) ' save and close workbook Application.DisplayAlerts = True ' set alerts back on End If End If Debug.Print vFileList(i) Next i ' clean up Set wb = Nothing PrintFileList_exit: Exit Sub PrintFileList_err: Debug.Print "Error in ", cProcName, vbCrLf, "Err no: ", Err.Number, _ vbCrLf, "Err Description: ", Err.Description Resume Next End Sub Function GetFileList(pDirPath As String) As Variant On Error GoTo GetFileList_err ' Local constants / variables Const cProcName = "GetFileList" Dim objFSO As Object Dim objFolder As Object Dim objFile As Object Dim c As Double ' upper bound for file name array Dim i As Double ' iterator for file name array Dim vFileList() As String ' array for file names Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFolder = objFSO.GetFolder(pDirPath) c = objFolder.Files.Count i = 0 ReDim vFileList(1 To c) ' set bounds on file array now we know count 'Loop through the Files collection For Each objFile In objFolder.Files 'Debug.Print objFile.Name i = i + 1 vFileList(i) = objFile.Name Next 'Clean up! Set objFolder = Nothing Set objFile = Nothing Set objFSO = Nothing GetFileList = vFileList GetFileList_exit: Exit Function GetFileList_err: Debug.Print "Error in ", cProcName, vbCrLf, "Err no: ", Err.Number, _ vbCrLf, "Err Description: ", Err.Description Resume Next End Function
You can call this from another macro or from the immediate window (ctrl+G) with the parameters required e.g. to get all files containing ‘.xls’, and run a macro named ‘your_macro_name_here’ the code would be:
call FileLoop("C:\Users\Prosserc\Dropbox\Docs\Stack_Overflow\Test", False, "", True, ".xls", "your_macro_name_here")
Obviously change the path in the first parameter to point to the directory containing the files that you want to run the macro against.