Hi,
I am trying to import a number of CSV's from a number of folders including subfolders. The snag is that I need to record the folder name with the file contents from each folder.
I can import the file name and contents when it is from one folder, but not multiple.
I am able to import the full directory list including the folder/subfolder names but not the contents of the actual files. I have used a function from http://allenbrowne.com/ser-59alt.html fofull location for this.
If i have the full path of the files I need in a seperate table, can I use this to loop through to import the files?
I have tried everything I have found on the subject and believe I'm very close :)
Thanks all
Gareth
Not sure if you are still interested, but I do believe that I did come up with a purely based Access solution. Won't go into details unless you request them, just look at the Attached Demo.
23 3799
This will get all the file names that meet your criteria in folders and subfolders.
If you have a routine to import the data, put that in where the Debug statement goes - Sub Test()
-
-
Dim colFiles As New Collection
-
-
RecursiveDir colFiles, "E:\Phil Data\Access", "*.Csv", True
-
-
Dim vFile As Variant
-
For Each vFile In colFiles
-
Debug.Print vFile
-
Next vFile
-
-
End Sub
-
-
Public Function RecursiveDir(colFiles As Collection, _
-
strFolder As String, _
-
strFileSpec As String, _
-
bIncludeSubfolders As Boolean)
-
-
Dim strTemp As String
-
Dim colFolders As New Collection
-
Dim vFolderName As Variant
-
-
'Add files in strFolder matching strFileSpec to colFiles
-
strFolder = TrailingSlash(strFolder)
-
strTemp = Dir(strFolder & strFileSpec)
-
Do While strTemp <> vbNullString
-
colFiles.Add strFolder & strTemp
-
strTemp = Dir
-
Loop
-
-
If bIncludeSubfolders Then
-
'Fill colFolders with list of subdirectories of strFolder
-
strTemp = Dir(strFolder, vbDirectory)
-
Do While strTemp <> vbNullString
-
If (strTemp <> ".") And (strTemp <> "..") Then
-
If (GetAttr(strFolder & strTemp) And vbDirectory) <> 0 Then
-
colFolders.Add strTemp
-
End If
-
End If
-
strTemp = Dir
-
Loop
-
-
'Call RecursiveDir for each subfolder in colFolders
-
For Each vFolderName In colFolders
-
Call RecursiveDir(colFiles, strFolder & vFolderName, strFileSpec, True)
-
Next vFolderName
-
End If
-
-
End Function
-
-
Public Function TrailingSlash(strFolder As String) As String
-
' Add a backslah if it's missing
-
If Len(strFolder) > 0 Then
-
If right(strFolder, 1) = "\" Then
-
TrailingSlash = strFolder
-
Else
-
TrailingSlash = strFolder & "\"
-
End If
-
End If
-
-
End Function
Phil
AIRCODE Example: - Let's assume that you have the very simple Table Structure and Data below:
-
ID FilePath
-
1 C:\Test\File1.csv
-
2 C:\Test\File2.csv
-
3 C:\Test\File3.csv
-
- The following Code will loop thru all the *.csv File Paths contained within the [FilePath] Field, then Import the *.csv File into a Table named with the corresponding Primary Key Field ([ID]) Value.
- Dim MyDB As DAO.Database
-
Dim rst As DAO.Recordset
-
Dim intCtr As Integer
-
-
Set MyDB = CurrentDb
-
Set rst = MyDB.OpenRecordset("tblCSVFiles", dbOpenSnapshot)
-
-
With rst
-
Do While Not .EOF
-
DoCmd.TransferText acImportDelim, , ![ID], ![FilePath], True
-
.MoveNext
-
Loop
-
End With
-
-
rst.Close
-
Set rst = Nothing
- After Code Execution you will have three new Tables named 1, 2, and 3.
- The Code assumes that you have Field Names embedded in the *.csv Files.
Thanks both for replying. I tried the code from AIRCODE and I am 90% there now.I have a list of tables with the contents of the CSV's, and each table name corresponds with the ID of the path in the directory table.
I have tried and tried however to find a way of linking the table name with the ID of the directory table. Is there a way of doing this? I presume it will involve some sort of INSERT INTO query where I would insert the tablename into the corresponding table.
I have tried looking for a function to loop through all tables and add the table name to the table.
Is this possible via VBA or a function do you think?
I am even closer now. I have used the below code to append all the tables into one: - Dim db As DAO.Database
-
Dim rs As DAO.Recordset
-
-
Const cstrAppend As String = "INSERT INTO maintable SELECT * FROM "
-
-
Set db = CurrentDb()
-
Set rs = db.OpenRecordset("tableoftables")
-
-
Do Until rs.EOF
-
db.Execute cstrAppend & rs!TableName, dbFailOnError
-
rs.MoveNext
-
Loop
-
-
rs.Close: Set rs = Nothing
-
Set db = Nothing
-
I have then tried this one to do the same as the above, but append the tablename as well - Dim db As DAO.Database
-
Dim rs As DAO.Recordset
-
Dim cstrAppend As String
-
-
Set db = CurrentDb()
-
Set rs = db.OpenRecordset("tableoftables")
-
-
cstrAppend = "INSERT INTO maintable SELECT *, """ & rs!TableName & """, FROM & rs!TableName"
-
-
Do Until rs.EOF
-
-
db.Execute cstrAppend, dbFailOnError
-
rs.MoveNext
-
Loop
-
-
rs.Close: Set rs = Nothing
-
Set db = Nothing
However the second one gives me this error;
No Destination field name in INSERT INTO statement ("993")
993 is my ID above which is correct.
Any ideas?
Thanks
AFIK The Append query takes the form of
INSERT INTO MainTable (Field1, Field2.....)
SELECT FieldA, FieldB... FROM SecondTable;
So I think you need to define the corresponding fields from both tables.
As, in your case, the SecondTable is a calculated value, I think I would try
FROM Chr$(34) & rs!TableName & Chr$(34);
I have a pet hatred of """, and always use Chr$(34) which is a double quote
Phil
I have tried all ways of using Chr$(34) but cannot seem to get the syntax right. I have gone a slightly different way below and am agonisingly close now...
When I hover over the strSQL I can see
"INSERT INTO maintable select *, "993", from "993""
All the rs!tablename variables are correct. - Dim db As DAO.Database
-
Dim rs As DAO.Recordset
-
Dim cstrAppend As String
-
-
Set db = CurrentDb()
-
Set rs = db.OpenRecordset("tableoftables")
-
-
strsql = "INSERT INTO maintable SELECT *, """ & rs!TableName & """, FROM """ & rs!TableName & """"
-
Do Until rs.EOF
-
-
db.Execute strsql, dbFailOnError
-
rs.MoveNext
-
Loop
-
-
rs.Close: Set rs = Nothing
-
Set db = Nothing
I still get the error No Destination field name in INSERT INTO statement ("993")
Do i need to specify an alias in the statement? I have tried a few ways but I just get a syntax error.
Please read my previous post. You have not defined the fields specifically in the Main table that you want to append, nor defined specifically the fields that the data is coming from in your input tables.
I've tried doing this but unfortunately I keep getting syntax errors. All the fields from other tables copy across ok as they are picked up in the SELECT *. The only issue is the table name variable rs!tablename. I have added a field to the new table called "tablename" however I dont believe this makes a difference. I believe I need to specify what field to append the tablename to, but I am sure of the syntax.
Appreciate your help with this :)
Without knowing the field names in the two tables, it is difficult to be of further help. Perhaps you would enlighten us
Phil
No problem, these are all test names for now, but there is a table containing all the table names called "tableoftables" with [ID] and [tablename]
The fields in each table I am appending from has [field1] and [field2]. These copy append fine into a table called "maintable".
I have added a field called [tablename] into this "maintable" as it is the same name as the field in "tableoftables" The only issue appears to be appending the table name :(
I used my previous Code Segment to illustrate how you can utilize a Table Name and Primary Key, inserting a combination of both into a Main Table: -
Dim MyDB As DAO.Database
-
Dim rst As DAO.Recordset
-
Dim strTableName As String
-
Dim strSQL As String
-
-
strTableName = "tblCSVFiles"
-
-
Set MyDB = CurrentDb
-
Set rst = MyDB.OpenRecordset(strTableName, dbOpenSnapshot)
-
-
With rst
-
Do While Not .EOF
-
strSQL = "INSERT INTO [MainTable] ([MyID]) VALUES('" & ![ID] & "_" & strTableName & "')"
-
CurrentDb.Execute strSQL, dbFailOnError
-
.MoveNext
-
Loop
-
End With
-
-
rst.Close
-
Set rst = Nothing
Try strSQL = "INSERT INTO [MainTable] ([MyID]) SELECT ![ID] & "_" & !strTableName AS NewTable"
You certainly need an exclamation mark before strTableName
If ID is numeric, you may need Cstr(!ID)
Phil
You certainly need an exclamation mark before strTableName
Not required, it is a String Variable, not a Field Name.
If ID is numeric, you may need Cstr(!ID)
Not required, it will be coerced to a String.
We are a step closer as this now adds the table ID to the main table, however it doesnt add the contents of the other tables. Is there a way we can incorporate SELECT * from the other tables as well as appending the table name?
What I believe I need is something like - strSQL = "INSERT INTO [MainTable] SELECT *,([MyID]) VALUES('" & ![ID] & "_" & strTableName & "')"
But this doesnt work :(
Really appreciate all your help with this one.
@Gareth:
Sorry, but I am a little confused at this point. Is there any chance of you Uploading a subset of your DB, stripped of any sensitive information, along with an exact explanation of what you are looking for and what the correct results should be?
Thanks for taking the time on this. I have uploaded the DB for you to look at. The DB just contains the functions to make this work as a concept.
First I click button1 which runs the function in module 1. This imports the directory listing of the specifc folder including subfolders, which creats [tbldirectory]
Button2 then creates a new table from [tbldirectory] that combines the path and CSV file name into [tbldirectory2]. It then imports the contents of the CSVs into seperate tables. Each table name is the ID of [tbldirectory2]. (You will see these are 1011, 1012 etc)
Button3 then appends the contents of all the above tables into one [Maintable] Its at this point I need the table name of each table (1011, 1012 etc) to be appended to the maintable. This is so I know the location of each CSV. Otherwise [maintable] is just data with no reference to where it orginated from.
Let me know if you need anymore information, thanks.
I've looked at your Database and this is what I see: - You want to Append the Data in Tables 1011, 1012, 1013, 1014, 1015, and 1016 to the Table maintable.
- Tables 1011 thru 1016 consist of different Fields.
- maintable is a conglomeration of all the Field Names in Tables 1011 thru 1016.
- If the above statements are correct, then you have a difficult task ahead of you. As you Append each Table to maintable you must first synchronize the Fields to Append. A case in point would be:
Table 1011 has the following Fields which must be Appended to maintable along with the Table Name: -
[db_name]
-
[min]
-
[max]
-
[name1]
-
- Tables 1012 thru 1016 may/may not have these Fields as well as additional Fields.
I see what you mean. There may be a way of appending the table name to each table individually before appending them all together.
Something along the lines of for each table ID in tbldirectory2, append the ID to the table with the same ID. I can then combine all these into one table which I have done already. That is all I need to do TBH.
I think that it can actually be done, but I will not be able to attempt it until Friday at the earliest. I'll check back in then, and if you are still interested, I'll see what I can come up with.
I've got it :) I started from scratch and it though it may be easier to append the folder path using Excel. So the method I used to automate the whole process was to first import the folder structure into Access using button1 in the DB. Then I exported this folder structure into Excel. I then used the below code to import the content in: - Sub step1()
-
-
Dim wsMstr As Worksheet: Set wsMstr = ThisWorkbook.Sheets("sheet1")
-
-
wsMstr.UsedRange.Clear
-
-
Call step2
-
-
End Sub
-
- Sub step2()
-
-
Call Combined
-
-
End Sub
-
- Sub Combined()
-
-
If Sheets("sheet2").Range("A2") = "" Then
-
Exit Sub
-
-
Else
-
-
Call ImportCSVsWithReference
-
-
Rows("2:2").Select
-
Selection.Delete Shift:=xlUp
-
-
Call step2
-
-
End If
-
-
End Sub
- Sub ImportCSVsWithReference()
-
-
Dim wbCSV As Workbook
-
Dim wsMstr As Worksheet: Set wsMstr = ThisWorkbook.Sheets("sheet1")
-
Dim fPath As String: fPath = Sheets("sheet2").Range("A2") 'path to CSV files, include the final \
-
Dim fCSV As String
-
-
Application.ScreenUpdating = False 'speed up macro
-
-
fCSV = Dir(fPath & "*.csv") 'start the CSV file listing
-
-
Do While Len(fCSV) > 0
-
'open a CSV file
-
Set wbCSV = Workbooks.Open(fPath & fCSV)
-
'insert col A and add CSV name
-
Columns(1).Insert xlShiftToRight
-
Columns(1).SpecialCells(xlBlanks).Value = ActiveSheet.Name & fPath
-
'copy date into master sheet and close source file
-
ActiveSheet.UsedRange.Copy wsMstr.Range("A" & Rows.Count).End(xlUp).Offset(1)
-
wbCSV.Close False
-
'ready next CSV
-
fCSV = Dir
-
Loop
-
-
Application.ScreenUpdating = True
-
-
End Sub
-
I then imported the resulting 25k rows back into Access :)
Thank you all again for your help in getting this to a resolution. Really appreciate it.
Not sure if you are still interested, but I do believe that I did come up with a purely based Access solution. Won't go into details unless you request them, just look at the Attached Demo.
This is perfect. I will use your one as it does exactly what I need and does not need the steps to Excel.
Appreciate the time you took to create this. Thanks :)
Glad it all worked out for you. Just keep in mind that the Code is based on two MAJOR assumptions: - The Imported *.csv Files will always be imported into Tables whose Names are Numeric, namely: 1011, 1022, 1234, 6724, etc. No other Tables in your Database, aside from the Imported CSVs, have Names that are purely Numeric.
- All Fields in the imported Tables have exact counterparts, both in Name and Data Types, in maintable.
Post your reply Sign in to post your reply or Sign up for a free account.
Similar topics
1 post
views
Thread by Mark Everett |
last post: by
|
reply
views
Thread by Jaco Karsten |
last post: by
|
1 post
views
Thread by Harley |
last post: by
|
7 posts
views
Thread by Pete |
last post: by
|
1 post
views
Thread by D2 |
last post: by
|
2 posts
views
Thread by ink |
last post: by
| |
1 post
views
Thread by moijes12 |
last post: by
| | | | | | | | | | | |