How to Automatically Open Text File: Find, Copy Data, and Paste - excel

So I'm trying to automate a task that involves opening a whole folder of .ist documents that are similar and paste the data. I already have code that allows me to click each item but I'm trying to make this task completely automatic. I'm pretty new at this. I have experience coding in C but I've been coding vba for only a week.
So here's what I have:
This is the code that works
Sub Figureitout()
Dim fileName As Variant, text(1 To 890) As String, textline As String
Dim num As Integer
Dim strDir As String, fso As Object, objFiles As Object, obj As Object, fileCount As Integer
Dim myFile As Variant
Dim posTorque As Integer, posOffset As Integer
'specify folder path
strDir = "C:\Users\Desktop\Folder\"
'create filesystemobj
Set fso = CreateObject("Scripting.FileSystemObject")
'get the folder
Set objFiles = fso.GetFolder(strDir).Files
'count all the files
fileCount = objFiles.Count
'Total number of files in folder
MsgBox fileCount
'read file name
'fileName = Dir(strDir)
'MsgBox fileName
'counter intitialize
num = 1
Do Until num = fileCount
'choose file
myFile = Application.GetOpenFilename("Text Files(*.IST),*.ist", , , , False)
'open file
Open myFile For Input As #num
'copy file contents
Do Until EOF(num)
Line Input #(num), textline
text(num) = text(num) & textline
Loop
'find data
posTorque = InStr(text(num), "Torque:")
posOffset = InStr(text(num), "Offset:")
'close file
Close #num
'make sure offset value exists in document
If InStr(text(num), "Offset:") <> 0 Then
'paste data
Range("A" & num).Value = Mid(text(num), posTorque + 12, 4)
Range("B" & num).Value = Mid(text(num), posOffset + 13, 4)
End If
'delete chosen file
Kill (myFile)
'increment prior to loop
num = num + 1
'Reset data
posTorque = 0
posOffset = 0
Loop
End Sub
So I'm thinking about having something that is like:
For Each fileName in fileCount
FileName = "Dir(strDir)"
Open fileName for Input As #num
but I keep getting type mismatch errors. I'm assuming that's because fileName is a string in this scenario?
Tips? Tricks? Advice?

No need to store the complete text from all the files in an array, just check each lines as you read it.
Sub ProcessFiles()
Const FOLDER = "C:\Users\Desktop\Folder\"
Dim ws As Worksheet
Dim sFilename As String, textline As String
Dim i As Integer, ff As Integer, p As Integer, count As Long
sFilename = Dir(FOLDER & "*.ist") ' first file
Set ws = ActiveSheet
i = 0
Do While Len(sFilename) > 0
ff = FreeFile
i = i + 1
Open FOLDER & sFilename For Input As #ff
Do Until EOF(ff)
Line Input #ff, textline
p = InStr(textline, "Torque:")
If p > 0 Then
ws.Range("A" & i).Value = Mid(textline, p + 12, 4)
End If
p = InStr(textline, "Offset:")
If p > 0 Then
Range("B" & i).Value = Mid(textline, p + 13, 4)
End If
Loop
Close ff
sFilename = Dir ' get next
count = count + 1
Loop
MsgBox count & " files proccessed in " & FOLDER, vbInformation
End Sub

Related

Save an embedded file to a location (export file from excel) with VBA

I have a little macro, that opens a Form where you can input details,
when you click on a button, you create a list with all the entries and save a selected pdf file thats embedded on another worksheet.
The Code works when you dont embed it as symbol. It basically creates a "screenshot" with the pdf. But i simply want to save the embedded object in a fixed path
`
Sub Schaltfläche6_Klicken()
Dim saveLocation As String
Dim sFolderPath As String
UserForm1.Show
sFolderPath = "C:\test\Excel"
saveLocation = "C:\test\Excel\Dummy.pdf"
If Dir(sFolderPath) <> "" Then
MkDir "C:\test\Excel"
End If
Worksheets("Dummy").ExportAsFixedFormat Type:=xlTypePDF, _
Filename:=saveLocation
End Sub
`
Hope you have a solution for the problem
i tried to find some solutions on the internet, but it didnt really helped. It looked a bit too complicated for what i really want
Please, use the next scenario. It cannot be a simple one, as I tried suggesting in my above comment:
Embed the pdf files but use 'Alt Text' to place there the pdf file name. It can be manually add by right clicking on the OLE object - Format Object... - Alt Text or in code, if you embed the files in this way. I can supply a code modification for such a case, if needed.
The workbook where from to be embedded pdf files extracted (WBPdf), must be closed.
Since, as stated above, WBPdf should be closed, the next code must be copied in a xlsm file and run it from there. Basically, it saves a copy of WBPdf with zip extension (in fact workbook type xlsx, xlsm, xlsa etc. are such archives containing many xml files and objects. The code firstly extracts the files from archive \xl\worksheets, processes them to extract a logical association between the bin files in \xl\embeddings and the pdf name extracted from worksheets xml files. Then, it binary open the found bin files, and process them to become correct pdf files. I placed a link to an answer where this process has very well explained some years before:
a. Create a Public variable on top of a standard module (in the declarations area):
Public ExpArr()
It will keep the correspondence between the bin file to pdf name to be saved as.
b. Copy the next code in a standard module:
Sub ExtractEmbeddedPDFs() 'it does NOT work if the workbook to be processed is Open!
Dim pdfFolder As String, embWB As String, zipName As String, oShell As Object, arrO, i As Long
pdfFolder = ThisWorkbook.Path & "\Extracted PDF"
embWB = ThisWorkbook.Path & "\Embedded pdf.xlsx"
zipName = left(embWB, InStrRev(embWB, ".")) & "zip"
If Dir(pdfFolder, vbDirectory) = "" Then 'if the folder where to save pdf files does not exist
MkDir pdfFolder 'it is created
End If
'Deleting any previously created files, if any:
On Error Resume Next
Kill zipName
Kill pdfFolder & "\*.*"
Kill pdfFolder & "\_rels\*.*"
RmDir pdfFolder & "\_rels\"
On Error GoTo 0
'Copy/rename the Excel file changing extension to zip:
On Error Resume Next
FileCopy embWB, zipName
If err.Number = 70 Then 'error in case of workbook being open:
err.Clear: On Error GoTo 0
MsgBox "Please, close the workbook where from the embedded pdf files should be extracted." & vbCrLf & _
"A zipped copy cannot be created...", vbInformation, "Need to close the workbook": Exit Sub
End If
On Error GoTo 0
Dim flsWsh As Object, fileNameInZip As Variant
Set oShell = CreateObject("Shell.Application")
Set flsWsh = oShell.NameSpace(oShell.NameSpace((zipName)).Items.Item(("xl\worksheets")))
For Each fileNameInZip In oShell.NameSpace(flsWsh).Items
oShell.NameSpace((pdfFolder)).CopyHere _
oShell.NameSpace(flsWsh).Items.Item(CStr(fileNameInZip))
Next
getOLEObjSheetsREL pdfFolder 'build the array which matches any .bin oleObject with the extracted pdf name
For i = 0 To UBound(ExpArr)
arrO = Split(ExpArr(i), "|") 'split the matching array elements by "|" to extract bin name in relation with pdf name
oShell.NameSpace((pdfFolder)).CopyHere oShell.NameSpace((zipName)).Items.Item("xl\embeddings\" & arrO(0))
ReadAndWriteExtractedBinFile pdfFolder & "\" & arrO(0), pdfFolder, CStr(arrO(1))
Next i
On Error Resume Next
Kill zipName
Kill pdfFolder & "\*.bin"
Kill pdfFolder & "\*.xml"
Kill pdfFolder & "\_rels\*.*"
RmDir pdfFolder & "\_rels\"
On Error GoTo 0
MsgBox "Ready..."
Shell "explorer.exe" & " " & pdfFolder, vbNormalFocus 'open the folder keeping extracted files
End Sub
'Eliminate specific characters from binary file to make it pdf compatible:
'see here a good process explanation:
'https://stackoverflow.com/questions/52778729/download-embedded-pdf-file
Sub ReadAndWriteExtractedBinFile(s As String, TmpPath, Optional pdfName As String = "")
Dim byteFile As Long, byt As Byte, fileName As String
Dim MyAr() As Byte, NewAr() As Byte, i As Long, j As Long, k As Long
byteFile = FreeFile: j = 1
Open s For Binary Access Read As byteFile 'Open the bin file
Do While Not EOF(byteFile) 'loop untill the last line (count the file bytes)
Get byteFile, , byt: j = j + 1
Loop
'create the (correct) pdf byte file, removing some bytes (characters) from the bin byte one:___
ReDim MyAr(1 To j - 1) 'initially reDim it to have the same dimension as byteFile
j = 1
If EOF(byteFile) Then Seek byteFile, 1 'set first byte position for the next iteration
Do While Not EOF(byteFile) 'place the content of bin byteFile in MyAr:
Get byteFile, , byt
MyAr(j) = byt: j = j + 1
Loop
Close byteFile
'build the correct byte array without bytes existing up to %PDF:
For i = LBound(MyAr) To UBound(MyAr)
If i = UBound(MyAr) - 4 Then Exit For 'eliminate the not necessary last 4 bytes
If val(MyAr(i)) = 37 And val(MyAr(i + 1)) = 80 And _
val(MyAr(i + 2)) = 68 And val(MyAr(i + 3)) = 70 Then 'when find %PDF
ReDim NewAr(1 To j - i + 1) 'reDim the array to eliminate everything before it
k = 1
For j = i To UBound(MyAr)
NewAr(k) = MyAr(j): k = k + 1
Next j
Exit For 'exits the loop (after finding %PDF bytes)
End If
Next i
byteFile = FreeFile
'Set the pdf to be saved name:
If pdfName = "" Then 'if no pdfName parameter, it builds a unique name:
fileName = TmpPath & "\" & Format(Now, "ddmmyyhhmmss") & ".pdf"
Else
fileName = TmpPath & "\" & pdfName 'this solution uses only the extracted (from OLEObject) name
End If
'Write the new (pdf) binary file:
If isArrLoaded(NewAr()) Then 'only for PDF (bin) embedded files:
Open fileName For Binary Lock Read Write As #byteFile
For i = LBound(NewAr) To UBound(NewAr)
Put #byteFile, , CByte(NewAr(i))
Next i
Close #byteFile
Else
'If by mistake a not appropriate bin file has been choosen:
Debug.Print "The object is not of pdf type..." 'theoretically, this line should never be reached
End If
End Sub
Private Sub getOLEObjSheetsREL(strPath As String)
Dim patt As String: patt = "oleObject\d{1,3}.bin"
Dim strFold As String, strFile As String, strText As String
Dim fso As Object, ts As Object, arrOLE, arrOLEC(1), arrTot, i As Long
strFold = strPath & "\_rels\" 'copied folder (from archive) keeping sheets keeping OLEObjects
ReDim arrTot(0)
strFile = Dir(strFold & "*.rels")
Do While strFile <> "" 'iterate between all existing files
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.getFile(strFold & strFile).OpenAsTextStream(1, -2)
strText = ts.ReadAll 'read their content
ts.Close
arrOLE = getOLEObj(strText, patt) 'extract an array linking OLEObject to pdf file name
If arrOLE(0) <> "" Then
arrOLEC(0) = left(strFile, Len(strFile) - 5): arrOLEC(1) = arrOLE
BubbleSort arrOLEC(1) 'sort the array
arrTot(i) = arrOLEC: i = i + 1: ReDim Preserve arrTot(i)
End If
strFile = Dir()
Loop
ReDim Preserve arrTot(i - 1)
getOLEObjects arrTot, strPath 'returning an array linking the bin object to pdf to be saved file name
End Sub
Private Sub BubbleSort(arr)
Dim i As Long, j As Long, temp
For i = LBound(arr) To UBound(arr) - 1
For j = i + 1 To UBound(arr)
If arr(i) > arr(j) Then
temp = arr(i): arr(i) = arr(j)
arr(j) = temp
End If
Next j
Next i
End Sub
Private Sub getOLEObjects(arrOLE As Variant, strPath As String)
Dim strFile As String, strText As String
Dim fso As Object, ts As Object, j As Long
Dim arr, frstTxt As String, El, i As Long, strName As String, PrID As String
Dim k As Long: ReDim ExpArr(100)
Const strObj As String = "oleObject"
For j = 0 To UBound(arrOLE)
strFile = strPath & "\" & arrOLE(j)(0)
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.getFile(strFile).OpenAsTextStream(1, -2)
strText = ts.ReadAll
ts.Close
arr = extractBetweenChars(strText, "<oleObject progId=", "<\/mc:Fallback>")
For Each El In arr
strName = "": PrID = ""
strName = extractBetweenChars(CStr(El), "altText=""", """ r:id")(0)
PrID = extractBetweenChars(CStr(El), """", """")(0)
If PrID = "Acrobat Document" Or PrID = "Packager Shell Object" Then i = i + 1
If strName <> "" Then
If InStr(strName, ".pdf") > 0 Then
ExpArr(k) = strObj & i & ".bin" & "|" & strName: k = k + 1
End If
End If
Next
Next j
'keep only the elements keeping values:
If k > 0 Then
ReDim Preserve ExpArr(k - 1)
Else
Erase ExpArr
End If
End Sub
The workbook keeping embedded pdf files, can also contain embedded csv, xls, txt, jpg files. The code is able to distinguish between them and use for extraction only the appropriate bin files.
Please, send some feedback after testing it.

Move file to (error) different directory in case of duplicate file name

I have a code which renames text files based on content of the first row of text.
The name of the saved text file could be doubled a duplicate.
I want to save double duplicate text files in a different directory "C:\Research syntheses - Meta analysis\Txt files ECS\out\double\".
Sub RenameTextFile()
Const SpecialCharacters As String = "\,/,:,*,?,<,>,|,""," ' Modify this as neccesary
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fso, MyFile, FileName, TextLine
Dim char As Variant
Set fso = CreateObject("Scripting.FileSystemObject")
Set fol = fso.GetFolder("C:\Research syntheses - Meta analysis\Txt files ECS\out\")
For Each fil In fol.Files
FileName = fil
Set MyFile = fso.OpenTextFile(FileName, ForReading)
Do While MyFile.AtEndOfStream <> True
Do
Dim tmpLine As String
TextLine = MyFile.ReadLine
tmpLine = RemoveWhiteSpace(TextLine)
If Len(tmpLine) = 0 Then
TextLine = tmpLine
End If
Loop Until Len(TextLine) > 0
MyFile.Close
For Each char In Split(SpecialCharacters, ",")
TextLine = Replace(TextLine, char, "")
Next
fil.Name = TextLine & ".txt"
Exit Do
Loop
MyFile.Close
Next fil
End Sub
Option Explicit
Sub RenameTextFile()
Const SpecialCharacters As String = "\,/,:,*,?,<,>,|,""," ' Modify this as neccesary
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Const foldPath As String = "C:\Research syntheses - Meta analysis\Txt files ECS\out\"
Dim fso, MyFile, FileName, TextLine, fol As Object, fil As Object
Dim char As Variant, arrSavedFiles(), k As Long, El As Variant, boolFound As Boolean
Set fso = CreateObject("Scripting.FileSystemObject")
Set fol = fso.GetFolder(foldPath)
ReDim arrSavedFiles(k)
For Each fil In fol.Files
FileName = fil
Set MyFile = fso.OpenTextFile(FileName, ForReading)
Do While MyFile.AtEndOfStream <> True
Do
Dim tmpLine As String
TextLine = MyFile.ReadLine
tmpLine = Trim(TextLine)
If Len(tmpLine) <> 0 Then
TextLine = tmpLine: Exit Do
End If
Loop Until Len(TextLine) > 0
MyFile.Close
For Each char In Split(SpecialCharacters, ",")
TextLine = Replace(TextLine, char, "")
Next
For Each El In arrSavedFiles
If El = TextLine & ".txt" Then boolFound = True: Exit For
Next
If Not boolFound Then
fil.Name = TextLine & ".txt"
arrSavedFiles(k) = TextLine & ".txt"
k = k + 1: ReDim Preserve arrSavedFiles(k)
Else
boolFound = False
If Not fso.FolderExists(foldPath & "error\") Then MkDir foldPath & "error\"
FileCopy foldPath & fil.Name, foldPath & "error\" & fil.Name
Kill foldPath & fil.Name
End If
Exit Do
Loop
MyFile.Close
Next fil
End Sub
This will do what (I understood) you need. But, if there will be more then two files containing the same first line text, you must adapt the code in a similar way. I mean, before copying the file in the 'error' folder you must fill another array and check the file existence there. And do something (create another folder, warn using a message etc.)...
The moved files name will not be changed! It can be if necessary, in the same piece of code, or run the code again for the 'error' folder.

How to copy 100 files to a folder based on first and last file name and display in listbox vba

Im trying to come up with a piece of script that will allow me to copy 100 files from one folder and create a new folder based on the first file and last file name and then move those 100 files to that folder.
After moving those files, i want it to display the folders in a userform listbox as clickable items.
For example, each item in the listbox will be a folder, if i double click on a folders name it will display all the contents of the file (of each of 100 files) in a sheet i've set up.
I haven't been able to test this code yet, all i've done for the past week was research and rewrite the code over and over until i could understand it properly before adding it to the program. So there's bound to be some or more errors along the way.
What i did notice was the "objFile.CopyFile Folderpath & FCount & "_" & LCount" piece of code that doesnt specify which files could be copied specifically. For example, i want it to start at the first file and start coping the first 100 files, when the code is executed again, it will start at file 101 and copy the next 100 files. If there's way to ensure that it wouldnt keep copying the first 100 files, that would be awesome!
Sub Main()
'====CHECK IF THERE'S 100 FILES====
Dim filename, folderpath, path As String
Dim count As Integer
Dim FCount, LCount, FlagCount, IntCount As Integer
Dim objFSO As Object
Dim obj As Object
FCount = 0 ' First File name
LCount = 0 'Last file name
count = 0 'file count
FlagCount = Sheets("Flag Sheet").Range("A2").Value
folderpath = "Work\Big Book\" '==================Location Of The Book
path = folderpath & "*.xls"
filename = Dir(path)
Do While filename <> ""
count = count + 1
filename = Dir(path)
Loop
If count < 100 Then
'====CREATE A FOLDER FOR THE FILES====
If FlagCount <> "" Then '====If there is a flag count, it will create a folder based on the last number it was used
FCount = FlagCount + 1
LCount = FlagCount + 101
MkDir folderpath & FCount & "_" & LCount
Else '=======================else if there isnt one, it will use the first file name to create the folder
FCount = IntCount + 1
LCount = IntCount + 100
MkDir folderpath & FCount & "_" & LCount
End If
'====MOVE 100 FILES TO FOLDER====
For Each objFile In objFSO.GetFolder(path)
If FlagCount <> "" Then '====================if theres a flag count it will move the files starting after the flag count + 101
objFile.CopyFile folderpath & FCount & "_" & LCount
IntCount = FlagCount + 1
If IntCount = FlagCount + 100 Then Exit For
Else '======================================else it will just move the first 100 files
objFile.CopyFile folderpath & FCount & "_" & LCount
IntCount = IntCount + 1
If IntCount = IntCount + 100 Then Exit For
End If
Next
End If
Else
'===Do Nothing===
End If
End Sub
'=====Display Folders In Listbox=====
'====Display Folder Items In Book====
'Call the function
DisplayFoldersInListBox folderpath & FCount & "_" & LCount, Me.Listbox1
Sub Button_Click()
For Each File in Folderpath & FCount & "_" & LCount & "\" & Listbox.value
'[INSERT BIG BOOK CODE]
Next
End Sub
Private Sub DisplayFoldersInListBox(ByVal strRootFolder As String, ByRef lbxDisplay As MSForms.ListBox)
Dim fso As Object
Dim fsoRoot As Object
Dim fsoFolder As Object
'Make sure that root folder contains trailing backslash
If Right$(strRootFolder, 1) <> "\" Then strRootFolder = strRootFolder & "\"
'Get reference to the FileSystemObject
Set fso = CreateObject("Scripting.FileSystemObject")
'Get the root folder
Set fsoRoot = fso.GetFolder(strRootFolder)
'Clear the listbox
lbxDisplay.Clear
'Populate the listbox with subfolders of Root
For Each fsoFolder In fsoRoot.SubFolders
lbxDisplay.AddItem fsoFolder.Name
Next fsoFolder
'Clean up
Set fsoRoot = Nothing
Set fso = Nothing
End Sub
This link: Copy only the first file of a folder VBA
Seems to be the answer for the coping of the files, but im not entirely sure how to add it to my script. Can anyone help me out?
Back to the basics:
CopyXNumberOfFiles:Sub
Sub CopyXNumberOfFiles(SourceFolder As String, TargetFolder As String, Optional MaxNumFiles As Long = 100)
Dim fso As Object, objFile As Object
Dim count As Long
Dim Path As String
Set fso = CreateObject("Scripting.FileSystemObject")
If Not Right(SourceFolder, 1) = "\" Then SourceFolder = SourceFolder & "\"
If Not Right(TargetFolder, 1) = "\" Then TargetFolder = TargetFolder & "\"
For Each objFile In fso.GetFolder(SourceFolder).Files
If objFile.Path Like "*.xls?" Then
Path = TargetFolder & objFile.Name
If Len(Dir(Path)) = 0 Then
FileCopy objFile.Path, Path
count = count + 1
If count >= MaxNumFiles Then Exit For
End If
End If
Next
End Sub
Usage
CopyXNumberOfFiles "C:\","C:\Data"
Addendum
This function will copy the files over and return an array of the new file paths.
Function getCopyXNumberOfFiles(SourceFolder As String, TargetFolder As String, Optional MaxNumFiles As Long = 100) As String()
Dim fso As Object, objFile As Object
Dim count As Long, n As Long
Dim Path As String
Dim data() As String, results() As String
ReDim data(1 To 2, 1 To MaxNumFiles)
Set fso = CreateObject("Scripting.FileSystemObject")
If Not Right(SourceFolder, 1) = "\" Then SourceFolder = SourceFolder & "\"
If Not Right(TargetFolder, 1) = "\" Then TargetFolder = TargetFolder & "\"
For Each objFile In fso.GetFolder(SourceFolder).Files
If objFile.Path Like "*.xls?" Then
Path = TargetFolder & objFile.Name
If Len(Dir(Path)) = 0 Then
FileCopy objFile.Path, Path
count = count + 1
data(1, count) = objFile.Path
data(2, count) = Path
If count >= MaxNumFiles Then Exit For
End If
End If
Next
ReDim Preserve results(1 To count, 1 To 2)
For n = 1 To count
results(n, 1) = data(1, n)
results(n, 2) = data(2, n)
Next
getCopyXNumberOfFiles = results
End Function
Usage
Column 1 has the original paths and column 2 has the new paths.
Dim Files() as String, firstFilePath as String, lastFilePath as String
Files = getCopyXNumberOfFiles("C:\", "C:\New Folder\", 100)
Original Paths
firstFilePath = Files(1, 1)
lastFilePath = Files(Ubound(Files), 1)
New Paths
firstFilePath = Files(1, 2)
lastFilePath = Files(Ubound(Files), 2)

Opening a CSV file and saving the same CSV with a different name and filepath

OK so I am having trouble trying to open a file with the name "testymctesttest_0001a.csv" then rename then save the same file with just the name "001a" to a different folder. I'm trying to do this on roughly 700 files in a given folder. Some have a letter at the end of the number (ex. 0001a) and some do not have the letter (ex 0218). Is there a way to do this without copying all the csv data into a workbook just to save that workbook as another CSV? I tried the code below and everything worked except all the newly saved CSV data was corrupted in the new folder.
Sub openSavefile()
Dim filePaths() As String
Dim lineFromFile As String
Dim lineItems() As String
Dim rowNum As Long
Dim actWkb As Workbook
Dim ary() As String
Dim ary2() As String
Dim fPath As String
Dim i As Long
Dim j As Long
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Line1:
filePaths = selectFilesFunc
If filePaths(1) = "0" Then
Exit Sub
End If
If filePaths(1) = "-1" Then
GoTo Line1
End If
For j = 1 To UBound(filePaths)
Workbooks.Add
Set actWkb = ActiveWorkbook
Cells(1, 1).Activate
rowNum = 0
ary = Split(filePaths(j), "\")
ary2 = Split(ary(UBound(ary)), "_")
ary = Split(ary2(UBound(ary2)), ".")
Cells(1, 10).Value = ary(0)
fPath = "H:\TEST\FR2\"
Open filePaths(j) For Input As #1
Do Until EOF(1)
Line Input #1, lineFromFile
lineItems = Split(lineFromFile, ",")
If UBound(lineItems) < 4 Then
For i = 0 To UBound(lineItems)
ActiveCell.Offset(rowNum, i).Value = lineItems(i)
Next i
Else
If lineItems(7) = "HEX" Then
Range("D" & rowNum + 1 & ":G" & rowNum + 1).NumberFormat = "#"
'Range("D" & rowNum + 1 & ":G" & rowNum + 1).HorizontalAlignment = xlRight
End If
For i = 0 To UBound(lineItems)
ActiveCell.Offset(rowNum, i).Value = lineItems(i)
Next i
End If
rowNum = rowNum + 1
Loop
actWkb.SaveAs fPath & ary(0) & ".csv"
actWkb.Close
Close #1
Next j
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
The Function selectFilesFunc just gets an array of file paths to open. and the array index ary(0) just holds the new file name to be saved as (ex 0001a or 0218).
I have searched many places to find an answer and I feel like it is a simple command I am missing. But my final goal is just to open the CSV using Open filePaths(j) For Input As #1 or something similar and just save that same file with the new name and file path. But if I have to import it to a workbook to then save as a CSV, then I would like to know how to do this without corrupting the data.
Thanks for any help!
This will do it without opening the file.
It just renames the file to the text after the last underscore and moves the file from sSourceFolder to sDestinationFolder:
Public Sub RenameAndMove()
Dim colFiles As Collection
Dim vFile As Variant
Dim sFileName As String
Dim oFSO As Object
Dim sSourceFolder As String
Dim sDestinationFolder As String
Set colFiles = New Collection
sSourceFolder = "S:\DB_Development_DBC\Test\"
sDestinationFolder = "S:\DB_Development_DBC\Test1\"
EnumerateFiles sSourceFolder, "*.csv", colFiles
Set oFSO = CreateObject("Scripting.FileSystemObject")
For Each vFile In colFiles
'Get the new filename.
sFileName = Mid(vFile, InStrRev(vFile, "_") + 1, Len(vFile))
On Error Resume Next
'Move the file.
oFSO.movefile vFile, sDestinationFolder & sFileName
'You can delete this row if you want.
'It states whether the move was successful in the Immediate window.
Debug.Print vFile & " = " & (Err.Number = 0)
Err.Clear
Next vFile
End Sub
Sub EnumerateFiles(ByVal sDirectory As String, _
ByVal sFileSpec As String, _
ByRef cCollection As Collection)
Dim sTemp As String
sTemp = Dir$(sDirectory & sFileSpec)
Do While Len(sTemp) > 0
cCollection.Add sDirectory & sTemp
sTemp = Dir$
Loop
End Sub

Excel vba: Import multiple text files, and move files after import?

I really hope someone can help with this. At the moment I am using vba to import each line of text from a text file into a new column on one row. And each time I run the function a new row of data is created below the previous.
Results:
Row 1 (Showing Data from TextFile 1)
Column A Column B Column C
Data Data Data
Row 2 (Showing Data from TextFile 2)
Column A Column B Column C
Data Data Data
So this all works fine and after I have imported the text from the file, the file is moved from my directory 'unactioned' to a directory called 'actioned'.
So at the moment my code is not quite there yet, I am currently having to define the text file name so that I can import the data from the text file into my spreadsheet and again i am defining the text file name i want to move, this code will only currently work for 1 text file. However what i want to be able to do is if there are several text files in my folder 'unactioned', then i want to import each of these text files into a new row, and move all the text files we have just imported the data from to my folder 'actioned' at the same time
Here is my code:
Sub ImportFile()
Dim rowCount As Long
rowCount = ActiveSheet.UsedRange.Rows.Count + 1
If Cells(1, 1).Value = "" Then rowCount = 1
Close #1
Open "Y:\Incident Logs\Unactioned\INSC89JH.txt" For Input As #1
A = 1
Do While Not EOF(1)
Line Input #1, TextLine
Cells(rowCount, A) = TextLine
A = A + 1
Loop
Close #1
Dim d As String, ext, x
Dim srcPath As String, destPath As String, srcFile As String
srcPath = "Y:\Incident Logs\Unactioned\"
destPath = "Y:\Incident Logs\Actioned\"
ext = Array("*.txt", "*.xls")
For Each x In ext
d = Dir(srcPath & x)
Do While d <> ""
srcFile = srcPath & d
FileCopy srcFile, destPath & d
Kill srcFile
d = Dir
Loop
Next
End Sub
please can someone show me how i would amend this code to do what i need it to do? Thanks in advance
I would suggest breaking your code into multiple functions.
You can change the ImportFile method to not kill ALL files, but just the file it operates on, and then have it take a specific file to operate on one at a time. E.g.:
Sub ImportFile(directory As String, filename As String)
Dim rowCount As Long
rowCount = ActiveSheet.UsedRange.Rows.Count + 1
If Cells(1, 1).Value = "" Then rowCount = 1
Close #1
Open directory & filename For Input As #1
A = 1
Do While Not EOF(1)
Line Input #1, TextLine
Cells(rowCount, A) = TextLine
A = A + 1
Loop
Close #1
'Move the file and delete it
Dim srcPath As String, destPath As String
srcPath = directory & filename
destPath = "C:\Incident Logs\Actioned\" & filename
FileCopy srcPath, destPath
Kill srcPath
End Sub
Then, here is another stackoverflow post on how to iterate files in a folder
So with a little adaptation you could have something like:
Sub ImportAllFiles()
ImportFilesWithExtension "*.txt"
ImportFilesWithExtension "*.xls*"
End Sub
Sub ImportFilesWithExtension(extension As String)
Dim StrFile As String, myDir As String
myDir = "C:\Incident Logs\Unactioned\"
StrFile = Dir(myDir & extension)
Do While Len(StrFile) > 0
ImportFile myDir, StrFile
StrFile = Dir
Loop
End Sub
I'd also break it down into functions:
Sub ImportFile()
Dim rLastCell As Range
Dim vFolder As Variant
Dim vFile As Variant
Dim colFiles As Collection
With ThisWorkbook.Worksheets("Sheet1") 'Note - update sheet name.
'First find the last cell on the named sheet.
Set rLastCell = .Cells.Find( _
What:="*", _
LookIn:=xlValues, _
SearchDirection:=xlPrevious)
If rLastCell Is Nothing Then
'Set LastCell to A2.
Set rLastCell = .Cells(2, 1)
Else
'Set LastCell to column A, last row + 1
Set rLastCell = .Range(rLastCell.Row + 1, 1)
End If
vFolder = GetFolder()
Set colFiles = New Collection
EnumerateFiles vFolder, "\*.txt", colFiles
For Each vFile In colFiles
'Do stuff with the file.
'Close the file and move it.
MoveFile CStr(vFile), "S:\Bartrup-CookD\Text 1\" & Mid(vFile, InStrRev(vFile, "\") + 1, Len(vFile)) 'Note - update folder name.
Next vFile
End With
End Sub
This will place all files into a collection:
Sub EnumerateFiles(ByVal sDirectory As String, _
ByVal sFileSpec As String, _
ByRef cCollection As Collection)
Dim sTemp As String
sTemp = Dir$(sDirectory & sFileSpec)
Do While Len(sTemp) > 0
cCollection.Add sDirectory & "\" & sTemp
sTemp = Dir$
Loop
End Sub
This will ask you to select a folder:
' To Use : vFolder = GetFolder()
' : vFolder = GetFolder("S:\Bartrup-CookD\Customer Services Phone Reports")
Function GetFolder(Optional startFolder As Variant = -1) As Variant
Dim fldr As FileDialog
Dim vItem As Variant
Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
With fldr
.Title = "Select a Folder"
.AllowMultiSelect = False
If startFolder = -1 Then
.InitialFileName = Application.DefaultFilePath
Else
If Right(startFolder, 1) <> "\" Then
.InitialFileName = startFolder & "\"
Else
.InitialFileName = startFolder
End If
End If
If .Show <> -1 Then GoTo NextCode
vItem = .SelectedItems(1)
End With
NextCode:
GetFolder = vItem
Set fldr = Nothing
End Function
This will move a file from folder A to folder B:
'----------------------------------------------------------------------
' MoveFile
'
' Moves the file from FromFile to ToFile.
' Returns True if it was successful.
'----------------------------------------------------------------------
Public Function MoveFile(FromFile As String, ToFile As String) As Boolean
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
objFSO.MoveFile FromFile, ToFile
MoveFile = (Err.Number = 0)
Err.Clear
End Function

Resources