Importing multiple text files to Excel - excel

I have about 600 text files. Each file contains 2 columns and is space delimited. Is there any way I can import all of them to the same excel spreadsheet?
I saw a post about this and used the following script but that didn't work for me. It gived me User-defined type not defined
Sub ReadFilesIntoActiveSheet()
Dim fso As FileSystemObject
Dim folder As folder
Dim file As file
Dim FileText As TextStream
Dim TextLine As String
Dim Items() As String
Dim i As Long
Dim cl As Range
' Get a FileSystem object
Set fso = New FileSystemObject
' get the directory you want
Set folder = fso.GetFolder("D:\mypath\")
' set the starting point to write the data to
Set cl = ActiveSheet.Cells(1, 1)
' Loop thru all files in the folder
For Each file In folder.Files
' Open the file
Set FileText = file.OpenAsTextStream(ForReading)
' Read the file one line at a time
Do While Not FileText.AtEndOfStream
TextLine = FileText.ReadLine
' Parse the line into | delimited pieces
Items = Split(TextLine, "|")
' Put data on one row in active sheet
For i = 0 To UBound(Items)
cl.Offset(0, i).Value = Items(i)
Next
' Move to next row
Set cl = cl.Offset(1, 0)
Loop
' Clean up
FileText.Close
Next file
Set FileText = Nothing
Set file = Nothing
Set folder = Nothing
Set fso = Nothing
End Sub
`
Thanks for the help!

Most likely you need to set a reference to the Windows Scripting Host Object Model.
To do this, from the Visual Basic Editor choose Tools/References, then scroll down to find "Windows Script Host Object Model". Tick this box then press OK. Now try to run your code again.
Additionally, I notice you mention that your data is split into two columns and space-delimited. You'll need to replace the delimiter on the following line:
Items = Split(TextLine, "|")
With this:
Items = Split(TextLine, " ")
Finally, you'd be slightly better off replacing this:
For i = 0 To UBound(Items)
cl.Offset(0, i).Value = Items(i)
Next
With this:
cl.Resize(1,UBound(Items)-LBound(Items)+1).value = Items

Related

Run time error 5792- File name changes if word docx open

The macro is supposed to extract data from Docx files in a particular folder. If any of these folders are open when the macro is run, the program throws up an error 5792 and when I check the file name, the file name is changed partially. Why does it do that and how can I program around it.
File name is this: C:\Users\Ashley\Desktop\Victim Complaints\Victim Complaint Form.docx
When the docx is open and the macro is run, the file name changes to this and I get the error:
C:\Users\Ashley.Martin\Desktop\Victim Complaints\~$ctim Complaint Form.docx
The program appears to run through the actual files that are there, but then it will run an extra file with the corrupted file name.
Option Explicit
Dim FSO As Object
Dim myFile As Object
Dim myFolder As Object
Dim file As Object
Dim intRow As Integer
Dim docVic As Worksheet
Dim i As Integer
Dim strSumDoc As String
Dim LastSave As Date
Dim SumLastSave As Date
Dim docWord As Object
Dim appWord As Object
Dim FilePath As Variant
Dim HeadRange As Range
Sub VictimComplaints()
Set FSO = CreateObject("Scripting.FileSystemObject")
Set myFolder = FSO.getfolder(ThisWorkbook.Path)
Set docVic = ThisWorkbook.Worksheets("Sheet1")
Set appWord = CreateObject("Word.Application.16")
Set HeadRange = ThisWorkbook.Worksheets("Sheet1").Range("A2:AT2")
appWord.Visible = False
iCol = 1
'loops through filepaths in folder
For Each myFile In myFolder.Files
LastSave = FileDateTime(myFile)
If Right(myFile, 5) = ".docx" Then
intRow = docVic.Cells(docVic.Rows.Count, "B").End(xlUp).Row + 1
i = 3
Do While i <= intRow
strSumDoc = Cells(i, "B")
SumLastSave = Cells(i, "C")
'info on summary doc is already the latest bit of information
If strSumDoc = myFile And LastSave <= SumLastSave Then
Exit Do
'matching file already on document and saved later than last save date so info gets updated
ElseIf strSumDoc = myFile And LastSave > SumLastSave Then
'**Extracts data--works fine
Exit Do
'No match was found and at first empty row, make new entry on the summary doc
ElseIf strSumDoc = "" Then
'copy info to last row
'MsgBox "Copy to last row " & myFile.Name
strSumDoc = myFile
Set docWord = appWord.documents.Open(strSumDoc) '**Throws error because file name changed but there should be no file left.
tblCount = docWord.tables.Count
With docWord
With .tables(1)
'Extracts data from table, works fine
Exit Do
Else: 'iteration doesn't match myfile, loop to next row
End If
i = i + 1
Loop
End If
Next
appWord.Quit
Set appWord = Nothing
End Sub
To program around it, I skipped filenames that started with the "~$". No clue why or how it finds that filename when looping through the files in the folder. There are no files named that in there. So this question is like half answered. I likely just bandaided over a bigger problem.
Just had the same problem with a slipstick.com macro to save an outlook item as docx. I had commented out "wrdDoc.Close" with an apostrophe as I was trying to get the docx to open and be tha active document, as I am trying to call 4 macros after each other. If I remove the apostrophe then the temp file with "tideS" disappears, and the macro works fine, the folder is not shared with anyone. Maybe if the file is not just created by a macro, you have to close down all the App versions for the doc type you want to open. Annoying, happened again not really sure with docx files. using www.mrexcel.com/board/threads/can-vb-open-the-most-recently-created-file-in-a-folder.223730. I changed line near end to: Documents.Open myDir & strFilename. Just worked but not again. For myDir I added a backspace after the folder.

Open ZipFile, Look for Specific File Type And Save File Name

So I posted a question here:
VBA - Find Specific Sub Folders by Name Identifiers
This question was very broad, but I was facing specific issues I needed help identifying and resolving. Now, I managed to resolve those issues in the original post, however, there is still a good portion of the question unanswered and I would like to close the question only when I am able to post the full result.
Currently, what I still need to do, it the last 4 steps:
Open ZipFile
Look for .png extenstion
Grab the name of the .png file
Put the name in a cell in excel
The issue I am facing, is that of properly opening the zip file. I been through so many posts on this but NOTHING seems to work for me.
The closest I have come to accomplishing the task is what I found here:
https://www.ozgrid.com/forum/forum/help-forums/excel-general/109333-how-to-count-number-of-items-in-zip-file-with-vba-2007
I figure, if at the very least, I am able to enter the zip file, I can then work from there. But alas, I am still stuck at simply trying to open the file.
Here is the code I have (Using from the link above):
Sub CountZipContents()
Dim zCount As Double, CountContents As Double
Dim sh As Object, fld As Object, n As Object
Dim FSO As Object
CountContents = 0
zCount = 0
x = "C:\Users\UserName\Desktop\Today\MyFolder\"
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FolderExists(x) Then
For Each FileInFolder In FSO.GetFolder(x).Files
If Right(FileInFolder.Name, 4) = ".png" Then
CountContents = CountContents + 1
ElseIf Right(FileInFolder.Name, 4) = ".Zip" Then
Set sh = CreateObject("Shell.Application")
Set ZipFile = sh.Namespace(CVar(x & "\" & FileInFolder.Name))
Debug.Print FileInFolder.Name
For Each fileInZip In ZipFile.Items
If LCase(fileInZip) Like LCase("*.png") Then
CountContents = CountContents + 1
End If
Next
End If
Next FileInFolder
End If
Set sh = Nothing
End Sub
The issue I get is on this line:
For Each fileInZip In ZipFile.Items
Error Message:
Object variable or With block not set
Whenever I tried to use Shell, like below:
Dim oShell As New Shell
I get this error:
User-defined type not defined
With the below:
Link https://msdn.microsoft.com/en-us/library/windows/desktop/bb776890(v=vs.85).aspx
Dim oApp As Object
Set oApp = CreateObject("WScript.Shell")
'get a shell object
Set oApp = CreateObject("Shell.Application")
If oApp.Namespace(ZipFile).Items.count > 0 Then
I get this error:
Object doesn't support this property or method
On this line:
If oApp.Namespace(ZipFile).Items.count > 0 Then
References to links I have tried:
https://wellsr.com/vba/2015/tutorials/open-and-close-file-with-VBA-Shell/
http://www.vbaexpress.com/forum/showthread.php?38616-quot-shell-quot-not-work-in-Excel
Excel VBA - read .txt from .zip files
I just don't understand why this step is taking so much time to complete.
Your main problem is a really simple one: Your path "C:\Users\UserName\Desktop\Today\MyFolder\" contains already a trailing backslash, and when you set your ZipFile-variable, you are adding another one between path and filename. This will cause the shell-command to fail and ZipFile is nothing.
There are some minor problems with the code. I would recommend to use the GetExtensionName of your FileSystemObject to get the extension and convert this to lowercase so that you catch all files, no matter if they are .PNG, .png or .Png
For Each FileInFolder In FSO.GetFolder(x).Files
Dim fileExt As String
fileExt = LCase(FSO.GetExtensionName(FileInFolder.Name))
If fileExt = "png" Then
CountContents = CountContents + 1
Debug.Print "unzipped " & FileInFolder.Name
ElseIf fileExt = "zip" Then
Dim ZipFileName As String, ZipFile, fileInZip
Set sh = CreateObject("Shell.Application")
ZipFileName = x & FileInFolder.Name
Set ZipFile = sh.Namespace(CVar(ZipFileName))
For Each fileInZip In ZipFile.Items
If LCase(FSO.GetExtensionName(fileInZip)) = "png" Then
CountContents = CountContents + 1
Debug.Print "zipped in " & FileInFolder.Name & ": " & fileInZip
End If
Next
End If
Next FileInFolder
Additionally the strong advice to use Option Explicit and define all your variables. And split commands into smaller pieces. This costs you only a few seconds of typing the extra lines but helps you when debugging your code:
' Instead of
' Set ZipFile = sh.Namespace(CVar(x & "\" & FileInFolder.Name))
' write
Dim fName as string
fName = x & "\" & FileInFolder.Name; ' Now you can check fName and see the problem.
Set ZipFile = sh.Namespace(CVar(fName))
Try this:
Option Explicit
' Just to test CheckZipFolder
Sub TestZip()
Dim sZipFold As String: sZipFold = "C:\Temp\MyZip.zip" ' Change this to the path to your zip file
CheckZipFolder sZipFold
End Sub
Sub CheckZipFolder(ByVal sZipFold As String)
Dim oSh As New Shell ' For this, you need to add reference to 'Microsoft Shell Controls and Automation'
Dim oFi As Object
' Loop through all files in the folder
For Each oFi In oSh.Namespace(sZipFold).Items
' Checking for file type (excel file in this case)
If oFi.Type = "Microsoft Excel Worksheet" Then
MsgBox oFi.Name
'..... Add your actions here
End If
' This will make the UDF recursive. Remove this code if not needed
If oFi.IsFolder Then
CheckZipFolder oFi.Path
End If
Next
' Clear object
Set oSh = Nothing
End Sub

How to read text files in a folder and and save in an excel file

I have numerous text files in one folder. Each text file has two values that are written in separate lines (using \n\ in .write function). It looks like the following.
0.907831
0.992549
I want to create one master excel file that has all of the values in my text files combined (rather than manually entering them).
The desired output would look like the following.
'Filename' 0.907831 0.992549
So far, I have the following code.
import xlwt
import os
import fnmatch
path='Z:\Data\13-output'
wbk = xlwt.Workbook()
sheet = wbk.add_sheet('data')
row = 0
for files in os.walk(path):
for file in files:
if fnmatch.fnmatch(file, '*.txt'):
L = open(os.path.join( file), "r").read()
sheet.write(row,5,L)
row += 1
wbk.save('all_values_in_txt.xls')
It does generate the excel file named, 'all_values_in_txt.xls'. However, the excel sheet is blank. Any idea on how I can improve/fix the code?
Edit 1 (fixed by changing fnmatch to fnmatch.fnmatch): I realized I had some issues with following error, if fnmatch(file, '*.txt'): TypeError: 'module' object is not callable
Edit 2: I am now running into new errors
File "<ipython-input-81-ddeb0284f378>", line 17, in <module>
if fnmatch.fnmatch(file, '*.txt'):
File "C:\Users\JohnDoe\Anaconda3\lib\fnmatch.py", line 34, in fnmatch
name = os.path.normcase(name)
File "C:\Users\JohnDoe\Anaconda3\lib\ntpath.py", line 48, in normcase
s = os.fspath(s)
TypeError: expected str, bytes or os.PathLike object, not list
Just based on some very light testing, this seems like it should work for you.
Sub ReadFilesIntoActiveSheet()
Dim fso As FileSystemObject
Dim folder As folder
Dim file As file
Dim FileText As TextStream
Dim TextLine As String
Dim Items() As String
Dim i As Long
Dim cl As Range
' Get a FileSystem object
Set fso = New FileSystemObject
' get the directory you want
Set folder = fso.GetFolder("C:\your_path_here\")
' set the starting point to write the data to
'Set cl = ActiveSheet.Cells(1, 1)
Dim sht As Worksheet
Dim LastRow As Long
Set sh = ActiveSheet
' Loop thru all files in the folder
For Each file In folder.Files
' Write file-name
LastRow = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row + 1
Range("A" & LastRow).Select
ActiveCell = file.Name
' open the file
Set txtFile = fso.OpenTextFile(file)
col = 2
Do While Not txtFile.AtEndOfStream
dat = Application.Transpose(Application.Index(Split(txtFile.ReadLine, ","), 1, 0))
sh.Cells(LastRow, col).Resize(UBound(dat), 1) = dat
col = col + 1
Loop
' Clean up
txtFile.Close
'Range(cl.Address).Offset(1, 0).Select
Next file
Set FileText = Nothing
Set file = Nothing
Set folder = Nothing
Set fso = Nothing
End Sub
Notice, you need to run this from a Module in Excel.

How to export CSV file encoded with "Unicode"

Currently i using VBA code to export range data to a CSV file:
Sub Fct_Export_CSV_Migration() Dim Value As String Dim size As Integer
Value = ThisWorkbook.Path & "\Export_Migration" & Sheets(1).range("B20").Value & ".csv" chemincsv = Value
Worksheets("Correspondance Nv Arborescence").Select Dim Plage As Object, oL As Object, oC As Object, Tmp As String, Sep$ Sep = ";" size = Worksheets("Correspondance Nv Arborescence").range("B" & Rows.Count).End(xlUp).Row Set Plage = ActiveSheet.range("A1:B" & size)
Open chemincsv For Output As #1 For Each oL In Plage.Rows
Tmp = ""
For Each oC In oL.Cells
Tmp = Tmp & CStr(oC.Text) & Sep
Next
'take one less than length of the string number of characters from left, that would eliminate the trailing semicolon
Tmp = Left(Tmp, Len(Tmp) - 1)
Print #1, Tmp Next Close
MsgBox "OK! Export to " & Value End Sub
Now, i would like to export CSV encoded with "Unicode". I think i need to use VBA function like SaveAs( xlUnicodeText ) but how to use that ?
Thx
Unicode CSVs are not one of the file formats supported by Excel, out of the box. This means we cannot use the SaveAs method. The good news we can work around this restriction, using VBA.
My approach uses the file system object. This incredibly handy object is great for interacting with the file system. Before you can use it you will need to add a reference:
From the VBA IDE click Tools.
Click References...
Select Windows Script Host Object Model from the list.
Press OK.
The code:
' Saves the active sheet as a Unicode CSV.
Sub SaveAsUnicodeCSV()
Dim fso As FileSystemObject ' Provides access to the file system.
Dim ts As TextStream ' Writes to your text file.
Dim r As Range ' Used to loop over all used rows.
Dim c As Range ' Used to loop over all used columns.
' Use the file system object to write to the file system.
' WARNING: This code will overwrite any existing file with the same name.
Set fso = New FileSystemObject
Set ts = fso.CreateTextFile("!!YOUR FILE PATH HERE.CSV!!", True, True)
' Read each used row.
For Each r In ActiveSheet.UsedRange.Rows
' Read each used column.
For Each c In r.Cells
' Write content to file.
ts.Write c.Value
If c.Column < r.Columns.Count Then ts.Write ","
Next
' Add a line break, between rows.
If r.Row < ActiveSheet.UsedRange.Count Then ts.Write vbCrLf
Next
' Close the file.
ts.Close
' Release object variables before they leave scope, to reclaim memory and avoid leaks.
Set ts = Nothing
Set fso = Nothing
End Sub
This code loops over each used row in the active worksheet. Within each row, it loops over every column in use. The contents of each cell is appended to your text file. At the end of each row, a line break is added.
To use; simply replace !!YOUR FILE PATH HERE.CSV!! with your file name.

Importing multiple text files to Excel based on specific characters in the data, and adding additional data when importing

I've found an answer to import lines of data from numerous text files into an Excel sheet (https://stackoverflow.com/a/4941605/1892030 answered by Chris Neilsen). However I would like to also do the following:
There is garbage data before and after the useful data I want to import. The lines of data I want to import all start with an asterix (*).
The data is comma delimited and must be parsed that way when imported into Excel. This I could change by editing the parse code in the above answer.
At the end of each line that is imported, I want to add an additional item of data which is the name of the text file where the data was imported from (name of file only, without file extension).
The answer from Chris refered to above works real well so I would like to edit the code to allow for my additional requirements under points 1 and 3 above - but don't know how. For completeness I copy the code from the earlier answer below. Many thanks.
Sub ReadFilesIntoActiveSheet()
Dim fso As FileSystemObject
Dim folder As folder
Dim file As file
Dim FileText As TextStream
Dim TextLine As String
Dim Items() As String
Dim i As Long
Dim cl As Range
' Get a FileSystem object
Set fso = New FileSystemObject
' get the directory you want
Set folder = fso.GetFolder("C:\#test")
' set the starting point to write the data to
Set cl = ActiveSheet.Cells(1, 1)
' Loop thru all files in the folder
For Each file In folder.Files
' Open the file
Set FileText = file.OpenAsTextStream(ForReading)
' Read the file one line at a time
Do While Not FileText.AtEndOfStream
TextLine = FileText.ReadLine
' Parse the line into comma delimited pieces
Items = Split(TextLine, ",")
' Put data on one row in active sheet
For i = 0 To UBound(Items)
cl.Offset(0, i).Value = Items(i)
Next
' Move to next row
Set cl = cl.Offset(1, 0)
Loop
' Clean up
FileText.Close
Next file
Set FileText = Nothing
Set file = Nothing
Set folder = Nothing
Set fso = Nothing
End Sub
I haven't done it all for you (I expect the file name will need tidying up to fit the format you want) but drop this code in and it will get you started...
' Read the file one line at a time
Do While Not FileText.AtEndOfStream
TextLine = FileText.ReadLine
' Process lines which don't begin with Asterisk (*)
If Left(TextLine,1)<>"*" Then
' This crudely appends the filename as if it were a column in the source file
TextLine = TextLine + "," + file.Name
' Parse the line into comma delimited pieces
Items = Split(TextLine, ",")
' Put data on one row in active sheet
For i = 0 To UBound(Items)
cl.Offset(0, i).Value = Items(i)
Next
' Move to next row
Set cl = cl.Offset(1, 0)
End If
Loop

Resources