Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I receive a weekly Excel file from my IT department with an updated list of employees, their supervisor, department, etc. Every week, I just drag the file from the email into a designated folder on my computer.
Occasionally, I'll want a VBA script to reference and copy info from the latest version of whatever listing IT has sent to me most recently. The naming convention for the file is always the same: "EmployeeListing_20171211," but obviously with the date in the name being whatever day the file is generated. So next week, I can expect the new file to be named "EmployeeListing_20171218."
Because these files are stored in a shared folder, I have no way of knowing if other people are opening & modifying them, so I don't want the script to go by most recent Date Modified, but instead be able to read the date from the name of the file and select the file that's the newest. And all the questions I've seen related to this seem to point towards opening the file that has the most recent Date Modified, not in whose name includes the most recent date.
To do this, it seems to me like I need to read in the names of all the files in the folder, tell VBA how to convert the string to a date, find the date that's the most recent, and then find the corresponding Excel file that matches this date. But I have no idea where to start. Can anyone help with this?
Here's some code with comments that will get you started.
Sub test()
Dim sFile As String
Dim sPath As String
Dim dtFile As Date
Dim dtMax As Date, sMax As String
Dim sDate As String
'Folder where your files live
sPath = Environ("userprofile") & "\Documents\MyFolder\"
'Get the first file that starts with EmployeeListing_
sFile = Dir(sPath & "EmployeeListing_*")
'If there are no files, the lenght = 0
Do While Len(sFile) > 0
sDate = Split(sFile, "_")(1) 'get the date part of the file name
'turn it into an actual date
dtFile = DateSerial(Left$(sDate, 4), Mid$(sDate, 5, 2), Mid(sDate, 7, 2))
'if it's bigger than any others, store the date and name
If dtFile > dtMax Then
dtMax = dtFile
sMax = sFile
End If
'no arguments means get the next file using the same arguments as
'previosly supplied
sFile = Dir
Loop
'Print the file with the biggest date
Debug.Print sPath & sMax
End Sub
Related
Purpose of my question and of the VBA code:
Get specific data (a couple columns) from each one of the "table.csv" file in a network directory. Each networkdirectory/subfolders01/subfolders02 contains one "table.csv" file but 100 other subfolders are included in each network/subfolders01. The other folders are not needed, the only one we are interested in is subfolder02 for each subfolder01. The number of subfolders01 in the network directory is about 15000. However I only need subfolders01 from Jan2020 to Apr2020,for example (200 subfolders).
Final purpose is to trend data.
Issue:
I am trying to understand how I could improve the VBA code that I am currently using.
This code goes through each subfolder one by one and then check the date and file name.
I am wondering if there is a way to add any search filters criteria for subfolder date and name to have a faster loop.
How can we avoid the code to go through each subfolders?
Please see below the code I am using,
I really appreciate your time and hope my request is clear.
'''
Function GetFiles(startPath As String) As Collection
Dim fso As Object, rv As New Collection, colFolders As New Collection, fpath As String
Dim subFolder As Object, f, dMinfold, dtMod
Set fso = CreateObject("Scripting.FileSystemObject")
dMinfold = ThisWorkbook.Sheets("Enter_Date").Cells(2, 1)
colFolders.Add startPath
Do While colFolders.Count > 0
fpath = colFolders(1)
colFolders.Remove 1
'process subfolders
For Each subFolder In fso.getfolder(fpath).subfolders
If subFolder.DateLastModified >= dMinfold Then
colFolders.Add subFolder.Path
End If
Next subFolder
'process files
f = Dir(fso.buildpath(fpath, "*Table.csv"), vbNormal)
Do While f <> ""
f = fso.buildpath(fpath, f)
dtMod = FileDateTime(f)
If dtMod >= dMinfold And Right(f, 3) = "csv" Then
rv.Add f
End If
f = Dir()
Loop
Loop
Set GetFiles = rv
End Function'''
Then I have my code to get transfer data from each file.
Thank you.
I'll put in screenshots to clear up the Get & Transform method, since it is the GUI approach rather than code.
It is possible to filter before loading contents, which will speed things up significantly.
I tried with a few thousand subfolders filtered down to 20, loads instantly.
Here's the initial screen for get data from folder
You can then filter on path. In your case it will be based on the date from the folder name.
Now that it's filtered you can expand the content using the header button.
Inside content, you'll have to expand again to convert from csv to excel table
Choose/rename columns as needed, then hit "close and load" to drop it into excel.
Default is to a new table, but you can "load to" if something more custom is needed.
Here's your output. You can right-click refresh or refresh from vba as needed.
Edit- Just noticed that I used .txt rather than .csv for the files. Might change how a step or two looks in the middle, but the general idea is the same.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am new to VBA but I got this project to work on. I have this excel macro file that takes in as user input a specific date (month, day, year) and displays the graph of that day using the data read from the file of that selected date. Each file is named like "xxxx_20170706.csv". I need to modify this file to achieve below.
Each file is generated once a day containing the temperatures recorded every minute. The problem is, because each file is generated only once a day, and it contains the temperature data of the previous day (data keep being recorded from 00:00 till 23:59), you cannot check or use data of today. Basically, you have to wait until the next day if you wanna see the graph of a day.
In order to fix this issue, we decided to generate one file every hour for each day (that is, 24 files generated per day), and each file contains data of the previous hour. For example, at 1:00am of a day, a file is generated containing temperature data of time from 0:00am till 0:59am of the day. This way, we will be able to see the data of even today.
This means, at 5:30 in the morning, there should be 5 different files generated.
The problem I am having is, I am not sure how I can generate a graph from multiple files. The user input will stay the same, and only prompt a specific date they want to see the temperature data of. The output needs to be one graph reflecting temperature data of the date that exist at that point.
Each file will become named "xxxx_20170706_YY.csv" where YY is the 2 digit hours (from 00 up to 23).
I tried using loop incrementing i and adding it to the end of the file name so it can keep reading the existing files of the selected date. However, it did not work and only displayed the graph of data from the last file read.
If there are 5 files for a day, then all of these 5 files must be used for the graph.
How could this be achieved? An idea I came up with is, I create a new excel file, and each time a file is read in a for-loop, I keep adding the data at the bottom of the file, and at the end read that new excel file once, and generate the graph.
Is there any other better way? Thanks in advance for your help!
I would do that this way:
loop through the hours to current hour to get the file names
inside a loop create query (string)
create connection
create recordset
dump data into Excel sheet, which is used as a source for chart
Please, read my comments in below code:
Option Explicit
'needs reference to MS ActiveX Data Objects x.x Library
Sub GetCsvData()
Dim sPath As String, sFileName As String
Dim i As Integer, iCurrHour As Integer
Dim sSQL As String, sConn As String
Dim oConn As ADODB.Connection, oRst As Recordset, oWsh As Worksheet
On Error GoTo Err_GetCsvData
iCurrHour = Hour(Now) - 1
For i = 0 To iCurrHour
sFileName = "xxxx_" & Format(Date, "yyyyMMdd") & "_" & Right("00" & CStr(i), 2) & ".csv"
sSQL = sSQL & "SELECT * FROM " & sFileName & vbCr & "UNION ALL" & vbCr
Next
sSQL = "SELECT fnl.*" & vbCr & "FROM (" & vbCr & sSQL & ") AS fnl;"
MsgBox sSQL
'temporary exit sub; remove below line
GoTo Exit_GetCsvData
sPath = "c:\txtFilesFolder\" 'path have to ends with "\"
'change HDR=Yes if the first row of csv file contains the names of columns
sConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sPath & ";Extended Properties='text;HDR=No;FMT=Delimited';"
Set oConn = New ADODB.Connection
With oConn
.ConnectionString = sConn
.Open
End With
Set oRst = New ADODB.Recordset
oRst.Open sSQL, oConn, adOpenStatic, adLockReadOnly
Set oWsh = ThisWorkbook.Worksheets("SourceSheetForChart")
oWsh.Range("A1").CopyFromRecordset oRst
Exit_GetCsvData:
Set oWsh = Nothing
If Not oRst Is Nothing Then oRst.Close
Set oRst = Nothing
If Not oConn Is Nothing Then oConn.Close
Set oConn = Nothing
Exit Sub
Err_GetCsvData:
MsgBox Err.Description, vbExclamation, Err.Number
Resume Exit_GetCsvData
End Sub
Note: if your text files contain very specific delimiter or decimal separator, you have create schema.ini file.
For further details, please see:
Much ADO about text files
Schema.ini File
Good luck!
I am working on automating the saving procedure of our purchase orders that we do through an Excel workbook. Instead of the user having to copy the template into the correct directory and renaming it with the correct order number that’s next in the sequence along with the date (for e.g. the previous order was order number SJ-K1880 placed on the 7th July 2016 with filename KO_SJ-K1880_070716, so the next order number would be SJ-K1881 placed on the 11th of July 2016 with filename KO_SJ-K1881_110716), the user only needs to click a Save button and it will save the workbook in the correct directory under the right filename automatically following the sequence. Here’s an example of the full directory of one such file:
C:\Users\User\Desktop\Kyocera Order Doc\
Kyocera Orders\Orders 2016\07 July 2016\
KO SJ-K1880 070716\KO_SJ-K1880_070716.xlsm
Using the current date I have managed to check the existence of the directory up until 07 July 2016 and create it if it doesn’t exist. My problem comes in finding the last folder from that directory (which is KO SJ-K1880 070716 in this example) and using it to determine what the next order number is going to be.
This seems to give you what you want but it relies on an ascending sort of the folder names.
Option Explicit
Sub main()
Dim fldr As String
fldr = Environ("USERPROFILE") & _
"\Desktop\Kyocera Order Doc\Kyocera Orders\Orders 2016\07 July 2016"
Debug.Print mostRecentFolderNdx(fldr)
End Sub
Function mostRecentFolderNdx(base As String)
Dim f As String, lstndx As String
f = Dir(base & "\*", vbDirectory)
Do While CBool(Len(f))
If Not CBool(InStr(1, f, Chr(46))) Then
lstndx = Split(f, Chr(32))(UBound(Split(f, Chr(32))))
End If
f = Dir
Loop
mostRecentFolderNdx = lstndx
End Function
If you are going to rely on an ascending sort order, it is better to have your folders use a naming convention like \20160707\ rather than \07 July 2016\.
I have a macro that reads out external file properties like date created. The file from where I read is stored on a server. Unfortunately the date returned is not the correct one when running the macro the first time. Only when I open the file or when I run the macro several times, the correct updated date created is returned.
Does anyone have an idea how to solve that issue except from opening the file or looping through until the date is correct?
Here is the code:
strFilename = "<FILENAME>"
Workbooks.Open strFilename
Workbooks("strFilename").Close
Set oFS = CreateObject("Scripting.FileSystemObject")
lastcreatedLTVfile = CDate(Format(oFS.GetFile(strFilename).DateCreated, "dd.mm.yyyy"))
Do you want DateCreated or do you actually want DateLastModified? In your question you say "correct updated date" so I guess you should be using DateLastModified.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am using Excel 2010 and am trying to use a macro for the following:
Open the Save As dialogue box
Take the initial file name and check IF there is an underscore followed by 8 consecutive integers (ie. _12345678) before the file type (ie. .xlsx)
IF that DOES EXIST remove and replace it with an underscore followed by today's date in "yyyymmdd" format (ie. _20130730) before the file type (ie. .xlsx)
IF that DOES NOT EXIST simply add an underscore followed by today's date in "yyyymmdd" format (ie. _20130730) before the file type (ie. .xlsx)
The new file name based on criteria above would be present in the File Name field in the open Save As dialogue box but the file will require user to actually save it (just naming and opening Save As. Not actually saving with VBA)
Maintain whatever the original file type is
Assuming today's date is 7/30/2013, the macro would work as follows for the following beginning files:
1.) Test File A_20130615.xlsx would become Test File A_20130730.xlsx
2.) Test File B.xlsx would become Test File B_20130730.xlsx
Any and all help is appreciated!
Thanks
I modified a routine I have that does the same type of thing that you are trying to do, but uses the current name of the file, instead of having 2 save dialog boxes.
Option Explicit
Function SaveIt()
Dim CurrentFile As String
Dim FileExt As String
Dim GetFileName
CurrentFile = Left(ActiveWorkbook.FullName, InStrRev(ActiveWorkbook.FullName, ".") - 1)
FileExt = Mid(ActiveWorkbook.FullName, InStrRev(ActiveWorkbook.FullName, "."))
If InStr(CurrentFile, "_") Then
'has underscore
If InStrRev(CurrentFile, "_") = Len(CurrentFile) - 8 Then
' underscore 8 from end
If Right(CurrentFile, 8) = CStr(Val(Right(CurrentFile, 8))) Then
' and it's 8 digits at the end
CurrentFile = Left(CurrentFile, Len(CurrentFile) - 9)
'strip the end off
End If ' if it fails any of these tests,
End If 'then it's not got the underscore and date
End If ' and we don't touch the filename
CurrentFile = CurrentFile & "_" & Format(Now, "yyyymmdd")
GetFileName = Application.GetSaveAsFilename(CurrentFile & FileExt)
If GetFileName <> False Then 'Cancel returns false, otherwise it returns the filename
ActiveWorkbook.SaveAs GetFileName
End If
End Function
This also allows for people to have files named test_1.xlsx and What_a_lot_of_underscores.xlsm without having to worry about something destructing the name