DIR Not Functioning Correctly - vba

I am using VBA to import data from .txt files into a table of my spreadsheet which I am using for further pivot charts. The network directory that I am importing the files from contains ~5500 files and will grow over time at about 2000 files per year currently. The entries in the table are sorted by date (oldest to newest).
I have a macro which checks the date of the most recent entry, then uses DIR to search the network location and iterate through the files in that directory. For each file, if the file is newer than the most recent entry, I want to import the data and add it to the table. If the file is older, I want DIR to move to the next file. Below is the code I am currently using.
Sub NewFilesFromNetwork()
Dim myDatabase As Worksheet
Set myDatabase = Sheets("Database")
Dim TotalRows As Long, LastDate As Date
TotalRows = myDatabase.ListObjects("Table1").Range.Rows.Count
LastDate = Cells(TotalRows + 48, 6).Value 'the "+48" here is important because there are 48 hidden rows at the top of the spreadsheet before the table starts
Dim MyFolder As String, MyFile As String
On Error Resume Next
Application.ScreenUpdating = False
MyFolder = "*path to my network location*"
MyFile = Dir(MyFolder & "*.txt")
Dim t As Integer, k As Integer
t = 0 'counter for calculating total files imported
k = 0 'counter for calculating total files checked
Do While MyFile <> ""
TxtFile = MyFolder & MyFile
If FileDateTime(TxtFile) > LastDate Then
Open TxtFile For Input As #1
Do Until EOF(1)
Line Input #1, textline
text = text & textline
Loop
Close #1
Call CommonImportCode 'separate sub which picks out information from the .txt file string and adds it to the table as a new entry
k = k + 1
t = t + 1
MyFile = Dir()
End If
k = k + 1
MyFile = Dir()
Loop
Application.ScreenUpdating = True
MsgBox "Number of files searched = " & k & vbNewLine & "Number of files imported = " & t
End Sub
The issue I am having is this:
I can check the network location and see that there are 10 new files. However, the macro only imports 5 of them, and seems to be importing only every other file of the new files. Is there a reason the macro is skipping files when they meet the conditions of the IF statement?

k = k + 1
MyFile = Dir()
That code is duplicated. If your "If" just above is true, you are jumping one file. Your loop should be :
Do While MyFile <> ""
TxtFile = MyFolder & MyFile
If FileDateTime(TxtFile) > LastDate Then
Open TxtFile For Input As #1
Do Until EOF(1)
Line Input #1, textline
text = text & textline
Loop
Close #1
Call CommonImportCode 'separate sub which picks out information from the .txt file string and adds it to the table as a new entry
t = t + 1
End If
k = k + 1
MyFile = Dir()
Loop
or something approaching.

Related

Starting import from CSV from row 2 using VBA

I'm new to VBA and therefore need some help. I'm trying to import data from a CSV file using a method where I can chose the csv of a list using the following piece of code:
Private Sub commandbuttonimport_click()
Dim fd As Office.FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.Filters.Clear
.Title = "Select a CSV File"
.Filters.Add "CSV", "*.csv", 1
.AllowMultiSelect = False
Dim sfile As String
If .Show = True Then
sfile = .SelectedItems(1)
End If
End With
'import csv from filedialog
If sfile <> "" Then
Open sfile For Input As #1
row_number = 1
Do Until EOF(1)
Line Input #1, LineFromFile
LineItems = Split(LineFromFile, ";")
Application.Range("FC_Range_Final").Cells(row_number, 1).Value = LineItems(0)
Application.Range("FC_Range_Final").Cells(row_number, 2).Value = LineItems(1)
Application.Range("FC_Range_Final").Cells(row_number, 3).Value = LineItems(2)
row_number = row_number + 1
Loop
Close #1
End If
End Sub
But the thing is, I would only like to import the data from the chosen csv file starting from row 2 and skip the first one. If I manually delete the first row from the CSV file (which contains the headers) and then use the code above everything works, but if the headers remain no luck.
Help would be appreciated as I'm kinda stuck right now.
Try the following...
'import csv from filedialog
Dim LineItems() As String
Dim LineFromFile As String
Dim line_number As Long
Dim row_number As Long
line_number = 1
row_number = 1
Open sfile For Input As #1
Do Until EOF(1)
Line Input #1, LineFromFile
If line_number > 1 Then
LineItems = Split(LineFromFile, ";")
Application.Range("FC_Range_Final").Cells(row_number, 1).Value = LineItems(0)
Application.Range("FC_Range_Final").Cells(row_number, 2).Value = LineItems(1)
Application.Range("FC_Range_Final").Cells(row_number, 3).Value = LineItems(2)
row_number = row_number + 1
End If
line_number = line_number + 1
Loop
Close #1
EDIT
Based on your comments, it looks like a line feed (vbLf) is used as the end of line marker. Assuming that this is the case, you'll need to change your code to the following...
'import csv from filedialog
Dim DataFromFile As String
Dim LinesFromData() As String
Dim LineItems() As String
Dim row_number As Long
Open sfile For Input As #1
DataFromFile = Input(LOF(1), 1) ' get contents from entire file
LinesFromData = Split(DataFromFile, vbLf) ' split data into separate lines assuming line feed as end of file marker
For row_number = LBound(LinesFromData) + 1 To UBound(LinesFromData) ' +1 to start with second line of data
LineItems = Split(LinesFromData(row_number), ";") ' split the line into separate items
If UBound(LineItems) <> -1 Then
Application.Range("FC_Range_Final").Cells(row_number, 1).Resize(, 3).Value = LineItems
End If
Next row_number
Close #1

Can you use multiple wildcards in the VBA Dir function?

I am working on a macro to output filenames. I have a directory containing log files for an industrial batch process. Each batch is assigned a 5-digit batch number, and for each batch there is a .csv and .txt file. The filename for both files is the same and contains the batch number, for example:
XYZ 53482 20180827.csv
XYZ 53482 20180827.txt
XYZ 53483 20180828.csv
XYZ 53483 20180828.txt
XYZ 53484 20180829.csv
XYZ 53484 20180829.txt
My macro so far is:
Sub FindBatchFile()
Dim Batch As Double
Dim DirPath As String, r As Integer
Batch = InputBox("Enter Batch Number")
DirPath = Dir("C:\Data\* " & Batch & "*", vbDirectory)
r = 1
Workbooks.Add
MsgBox (DirPath)
Do Until DirPath = ""
Cells(r, 1).Value = DirPath
MsgBox (DirPath)
r = r + 1
DirPath = Dir
Loop
End Sub
This works adequately but the output contains both .csv and .txt files. Is there a way of using multiple wildcards in the Dir function (ie. include a "*.csv" criterion as well as the "*Batch*")?
Many thanks in advance!
I believe the following will work as you expect it to, just added the .csv in your DirPath:
Sub FindBatchFile()
Dim Batch As Double
Dim DirPath As String, r As Integer
Batch = InputBox("Enter Batch Number")
DirPath = Dir("C:\Data\* " & Batch & "*.csv", vbDirectory)
r = 1
Workbooks.Add
MsgBox (DirPath)
Do Until DirPath = ""
Cells(r, 1).Value = DirPath
MsgBox (DirPath)
r = r + 1
DirPath = Dir
Loop
End Sub

Combining CSV files from one folder into one file through MS Acces s vba

Hi there so I finished the section of a program which calculates and exports a csv with results. (ends up about 1600 csv files) each having only 1 column and between 20 and 0 rows. I would like my MS Access VBA program to join them together into one larger CSV. So Same header only once at the top of the new file.
The program i have so far seems to fall over at the part where it tries to import the Reg. Number of the File.
Dim db As DAO.Database
Set db = CurrentDb
MTH = Format(Date, "mmm")
UserInput = InputBox("Enter Country Code")
Dim strSourcePath As String
Dim strDestPath As String
Dim strFile As String
Dim strData As String
Dim x As Variant
Dim Cnt As Long
Dim r As Long
Dim c As Long
Dim wks As Excel.Worksheet
Application.Echo False
'Change the path to the source folder accordingly
strSourcePath = "Q:\CCNMACS\AWD" & CTRY
If Right(strSourcePath, 1) <> "\" Then strSourcePath = strSourcePath & "\"
'Change the path to the destination folder accordingly
strDestPath = "Q:\CCNMACS\AWDFIN"
If Right(strDestPath, 1) <> "\" Then strDestPath = strDestPath & "\"
strFile = Dir(strSourcePath & "*.csv")
Do While Len(strFile) > 0
Cnt = Cnt + 1
If Cnt = 1 Then
r = 1
Else
r = Cells(Rows.Count, "A").End(xlUp).Row + 1
End If
Open strSourcePath & strFile For Input As #1
If Cnt > 1 Then
Line Input #1, strData
End If
Do Until EOF(1)
Line Input #1, strData
x = Split(strData, ",")
For c = 0 To UBound(x)
wks.Cells(r, c + 1).Value = Trim(x(c)) 'Error is here: Run time error '91': Object variable or With Block variable not set
Next c
r = r + 1
Loop
Close #1
Name strSourcePath & strFile As strDestPath & strFile
strFile = Dir
Loop
Application.Echo True
If Cnt = 0 Then _
MsgBox "No CSV files were found...", vbExclamation
Your question isn't absolutely definitive as to what you're trying to do, but if I understand correctly, you just need to append several files to the end of each other, to make "one big CSV".
If that's true then there are several ways to do this a lot simpler than using VBA. .CSV files are just plain text files with comma's separating each field, and a .CSV filename extension.
Personally I would use Notepad++ (I assume it's capable of this; it does everything else), or perhaps even easier, I would use the Windows Command Prompt.
Let's say you have a folder with files:
File1.csv
File2.csv
File3.csv
...etc
Open the Windows Command Prompt. (One way is with the Windows key + R, then type cmd and hit Enter.)
Change directory with to the file location using cd (same as ChDir).
(For example, you might use cd c:\users\myFolder,
and then hit Enter)
To combine all CSV's in the folder into one, you could use a command like:
copy *.csv combinedfile.csv
That's it!
A file is created named combinedfile.csv. You can open in Excel or a text editor (like Notepad) to double-check it and adjust manually if necessary.
Obviously there are many ways you could vary the command, like if you only wanted the files that start with the word File you could use:
copy file*.csv combinedFile.csv
This should do what you want.
Sub Import()
Dim strPathFile As String, strFile As String, strPath As String
Dim strTable As String
Dim blnHasFieldNames As Boolean
' Change this next line to True if the first row in EXCEL worksheet
' has field names
blnHasFieldNames = True
' Replace C:\Documents\ with the real path to the folder that
' contains the EXCEL files
strPath = "C:\your_path_here\"
' Replace tablename with the real name of the table into which
' the data are to be imported
strTable = "Table1"
strFile = Dir(strPath & "*.csv")
Do While Len(strFile) > 0
strPathFile = strPath & strFile
DoCmd.TransferText acImportDelim, "", strTable, strPathFile, blnHasFieldNames
' Uncomment out the next code step if you want to delete the
' EXCEL file after it's been imported
' Kill strPathFile
strFile = Dir()
Loop
End Sub
See the links below for additional details pertaining to this topic.
https://anthonysmoak.com/2018/04/10/how-to-fix-an-import-specification-error-in-microsoft-access/
https://www.oakdome.com/programming/MSAccess_ExportSpecifications_TransferText_To_CSV.php

Create text files from data rows in Excel

I have a source spreadsheet in Excel with 450-or-so rows. Each row has 6 columns of data, and I need to create a separate file from each row with the filename = Column A and the contents = Columns B-G with a line break between them.
For example, I'm trying this but getting an error "File not found":
Sub DataDump()
Dim X
Dim lngRow As Long
Dim StrFolder As String
StrFolder = "/Users/danielfowler/Documents/_users_text_6.16"
X = Range([a1], Cells(Rows.Count, 2).End(xlUp))
For lngRow = 1 To UBound(X)
Open StrFolder & "\" & X(lngRow, 1) & ".txt" For Output As #1
Write #1, X(lngRow, 2)
Close #1
Next
End Sub
I see a half dozen questions like this already here on StackOverflow...
Create text Files from every row in an Excel spreadsheet
Write each Excel row to new .txt file with ColumnA as file name
Outputting Excel rows to a series of text files with spaces in filenames using VBA
Outputting Excel rows to a series of text files
But every one of these solutions returns a different error for me. I'm using Excel for Mac 2011, v14.4.2.
Sub VBA_Print_to_a_text_file()
Dim strFile_Path As String
strFile_Path = "C:\temp\test.txt" ‘Change as per your test folder path
Open strFile_Path For Output As #1
Print #1, "This is my sample text"
Close #1
End Sub
This outputs a text file for each row with column A as the title and columns B to the last column as the content for each file. You can change the directory to whatever you want but currently it saves the text file(s) to the same directory as the Excel file. You can also change the file extension to whatever you want.
Sub toFile()
Dim FilePath As String, CellData As String, LastCol As Long, LastRow As Long
Dim Filenum As Integer
LastCol = ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Column
LastRow = ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row
For i = 1 To LastRow
FilePath = Application.DefaultFilePath & "\" & Trim(ActiveSheet.Cells(i, 1).Value) & ".xpd"
Filenum = FreeFile
Open FilePath For Output As Filenum
CellData = ""
For j = 2 To LastCol
CellData = Trim(ActiveSheet.Cells(i, j).Value)
Write #Filenum, CellData
Next j
Close #Filenum
Next i
MsgBox ("Done")
End Sub
As for the breaks in between each line, unfortunately I'm not experienced enough to know how to do that.

Reading all files in Folder and showing content in Excel

I want to show 7000 files content that are in a folder and in excel?
I have a found a piece of code that helped me but its only reading one by one. However, I want to read 7000 all in one go. Please help.
Option Explicit
Sub Import_TXT_File()
Dim strg As Variant
Dim EntireLine As String
Dim FName As String
Dim i As String
Application.ScreenUpdating = False
FName = Application.GetOpenFilename("Text Files (*.txt), *.txt", , "Choose File to Import")
Open FName For Input Access Read As #1
i = 1
While Not EOF(1)
Line Input #1, EntireLine
strg = EntireLine
'Change "Sheet1" to relevant Sheet Name
'Change "A" to the relevant Column Name
Sheets("Sheet1").Range("A" & i).Value = strg
i = i + 1
Wend
EndMacro:
On Error GoTo 0
Application.ScreenUpdating = True
Close #1
End Sub
user1185158
The code which you are using will be very slow when you are reading 7000 files. Also there is no code which can read 7000 files in 1 go. You will have to loop through the 7000 files. However there is one good news :) Instead of looping through every line in the text file, you can read the entire file into an array and then write it to excel. For example see this code which is very fast as compared to the code that you have above.
TRIED AND TESTED
Sub Sample()
Dim MyData As String, strData() As String
Open "C:\MyFile.Txt" For Binary As #1
MyData = Space$(LOF(1))
Get #1, , MyData
Close #1
strData() = Split(MyData, vbCrLf)
End Sub
Now using the same code in a loop we can write it into an Excel File
'~~> Change this to the relevant path
Const strPath As String = "C:\Temp\"
Sub Sample()
Dim ws As Worksheet
Dim MyData As String, strData() As String
Dim WriteToRow As Long, i As Long
Dim strCurrentTxtFile As String
Set ws = Sheets("Sheet1")
'~~> Start from Row 1
WriteToRow = 1
strCurrentTxtFile = Dir(strPath & "*.Txt")
'~~> Looping through all text files in a folder
Do While strCurrentTxtFile <> ""
'~~> Open the file in 1 go to read it into an array
Open strPath & strCurrentTxtFile For Binary As #1
MyData = Space$(LOF(1))
Get #1, , MyData
Close #1
strData() = Split(MyData, vbCrLf)
'~~> Read from the array and write to Excel
For i = LBound(strData) To UBound(strData)
ws.Range("A" & WriteToRow).Value = strData(i)
WriteToRow = WriteToRow + 1
Next i
strCurrentTxtFile = Dir
Loop
MsgBox "Done"
End Sub
What the above code does is that it reads the contents of the 7000 text files in sheet 1 (one below the other). Also I have not included error handling. Please do that.
CAUTION: If you are reading heavy text files, say, each file has 10000 lines then you will have to tweak the code in the above scenario as you will get errors. for example
7000 Files * 10000 lines = 70000000 lines
Excel 2003 has 65536 rows and Excel 2007/2010 has 1048576 rows.
So once the WriteRow reaches the maximum row, you might want to read the text file contents into Sheet 2 and so on...
HTH
Sid
Taking Siddharth's solution a little further. You probably don't want to write each row one at a time, calls to the worksheet are extremely slow in Excel, it is better to do any looping in memory and write back in one fell swoop :)
Sub Sample()
Dim ws As Worksheet
Dim MyData As String, strData() As String, strData2() As String
Dim WriteToRow As Long, i As Long
Dim strCurrentTxtFile As String
Set ws = Sheets("Sheet1")
'~~> Start from Row 1
WriteToRow = 1
strCurrentTxtFile = Dir(strPath & "*.Txt")
'~~> Looping through all text files in a folder
Do While strCurrentTxtFile <> ""
'~~> Open the file in 1 go to read it into an array
Open strPath & strCurrentTxtFile For Binary As #1
MyData = Space$(LOF(1))
Get #1, , MyData
Close #1
strData = Split(MyData, vbCrLf)
'Resize and transpose 1d array to 2d
ReDim strData2(1 To UBound(strData) + 1, 1 To 1)
For i = 1 To UBound(strData)
strData2(i, 1) = strData(i - 1)
Next i
Sheet1.Range("A1").Offset(Sheet1.Rows.Count - 1, 0).End(xlUp).Offset(1).Resize(UBound(strData), 1).Value = strData2
strCurrentTxtFile = Dir
Loop
MsgBox "Done"
End Sub