How to get all contents from .TXT file maintaining leading "0"? - excel

I have this code
Dim FileToOpen As Variant
Dim OpenBook As Workbook
FileToOpen = Application.GetOpenFilename("Text Files (*.txt), *.txt")
If FileToOpen <> False Then
Set OpenBook = Application.Workbooks.Open(FileToOpen)
OpenBook.Sheets(1).UsedRange.Select
Selection.NumberFormat = "#"
OpenBook.Sheets(1).UsedRange.Copy
ThisWorkbook.Worksheets("BOM").Range("C1").PasteSpecial xlPasteValues
OpenBook.Close False
End If
Which is how I tried to automate manual actions of:
Opening a .txt file
Ctrl + a
Ctrl + c
Pasting it in my workbook via VBA code which is irrelevant in this case.
In the end I end up with this kind of table (main workbook in the image below has .NumberFormat = "#"):
https://i.stack.imgur.com/98tiC.png
But when I run it with the code above - I end up with:
https://i.stack.imgur.com/bJahk.png
Ignore the column titles in the row 1.
The problem I faced is that this code I have above, opens .txt file contents with already lost leading "0" in a temporary excel workbook from where it then copies them to my active workbook.
I'm wondering if there's any ways around it to get what I am looking to get done i.e. properly automating the sequence of manual actions listed above via VBA code displaying a search message box as it does now and then me choosing a .txt file I need and getting all the contents from it to my active workbook while maintaining all leading zeros (the number of zeroes and length of strings may vary so no solutions of adding them back in again won't be what I'm looking for)

The issue that you have is that as soon as excel gets hold of the data it creates problems.
So read it as a text file and split each line and output that directly to your target range - it will therefor stop excel parsing any strings as values - after that you can do whatever you want
option explicit
Sub read_text()
Dim FileToOpen As Variant
FileToOpen = Application.GetOpenFilename("Text Files (*.txt), *.txt")
Dim max_cols As Long
max_cols = 0
Dim r_out As Range
Set r_out = ThisWorkbook.Worksheets("BOM").Range("C1")
Dim row_offset As Long
offset = 0
If FileToOpen <> False Then
Dim fso As Object
Dim file As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set file = fso.OpenTextFile(FileToOpen, 1)
While Not file.AtEndOfStream
Dim line As String
line = file.ReadLine
Dim line_arr As Variant
line_arr = Split(line, vbTab)
ThisWorkbook.Worksheets("BOM").Range("C1").offset(row_offset, 0) _
.Resize(1, UBound(line_arr) - LBound(line_arr) + 1).Value = line_arr
row_offset = row_offset + 1
Wend
file.Close
End If
End Sub
output

Related

Modifying CSV files from a local folder-VBA

I am trying to rearrange the order of the columns in csv files in a folder on my local drive.
At the moment, from a tutorial, I have found a way to loop through the files. I wanted to cut a column and re insert in a different column. When running this code, Excel is crashing. It seems to be going through duplicate files.
I expected the columns to have moved in all the files in the folder. But they didn't move. And excel is crashing, looks like it's duplicating the files when hitting CTRL + G and running the code.
Here's the code.
Option Explicit
Sub FleetMoveColumns()
Dim fileDirectory As String
Dim fileCriteria As String
Dim fileName As String
Dim fileToOpen As Workbook
Application.ScreenUpdating = False
fileDirectory = "C:\...\*csv"
fileName = Dir(fileDirectory)
Do While Len(fileName) > 0
Set fileToOpen = Workbooks.Open(fileDirectory & fileName)
Columns("R").Cut
Columns("AB").Insert
Debug.Print fileName
Loop
Application.ScreenUpdating = True
End Sub
Please help.
You need to fully qualify your Columns object with a Worksheet object.
You need to place FileName = Dir within your Do While loop.
Modified code
Do While Len(FileName) > 0
Set fileToOpen = Workbooks.Open(fileDirectory & FileName)
' set the worksheet object
Set Sht = fileToOpen.Worksheets(1) ' <-- Rename "Sheet1" to your desired worksheet
With Sht
.Columns("R").Cut
.Columns("AB").Insert
End With
' clear objects
Set Sht = Nothing
Set fileToOpen = Nothing
Debug.Print FileName
FileName = Dir
Loop

Copy and Paste multiple txt in single Excel worksheet in pre-determined cells

What i am trying to do is select multiple txt files, then copy-paste each one into its predetermined cell of the current working sheet, and organize it in columns. Every file has the same structure (10 by 10 for example), and needs to be allocated in a certain cell (for example file_1 into F14, file_2 into X14, etc.), with the same horizontal distance between each other.
What I am missing is a way to copy-paste every one of the selected files into the desired positions.
I tried to do something by doing research on the internet but i couldn't figure it out.
Thank you in advance for any help.
Here is the code I was working on:
Sub ImportTXTFiles()
Dim fso As Object
Dim xlsheet As Worksheet
Dim qt As QueryTable
Dim txtfilesToOpen As Variant, txtfile As Variant
Application.ScreenUpdating = False
Set fso = CreateObject("Scripting.FileSystemObject")
txtfilesToOpen = Application.GetOpenFilename _
(FileFilter:="Text Files (*.txt), *.txt", _
MultiSelect:=True, Title:="Text Files to Open")
i = 14
j = 6
With ActiveSheet
For Each txtfile In txtfilesToOpen
' WHAT DO I PUT HERE????
j = j + 20
Next txtfile
End With
End Sub

Excel crashing randomly when running macro

I'm having an issue with the following code, that is supposed to sequentially open 〜100 csv files, check for a value in a cell (validation, if it is file with correct structure), copy single line of data and paste it into ThisWorkbook.Worksheets("2 CSV").Range("B" & row_number).
This solution worked for two years until this month. Now the whole Excel crashes randomly on any file without any error message. Sometimes it manages to loop through 20 files, sometimes 5.
The weirdest thing is, that I can loop manually using F8 through the whole thing without any problem.
The macro:
Sub b_load_csv()
Dim appStatus As Variant
Dim folder_path As String 'folder path to where CSVs are stored
Dim file_name As String 'file name of current CSV file
Dim row_number As Integer 'row number in target sheet
Dim source_sheet_name As String 'name of the source sheet of the CSV = CSV file name
Dim wb_src As Workbook 'variable for opened CSV source workbook
Dim sht_src As Worksheet 'variable for opened CSV source sheet
Dim sht_csv As Worksheet 'variable for target sheet in ThisWorkbook
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
.DisplayAlerts = False
If .StatusBar = False Then appStatus = False Else appStatus = .StatusBar 'show currently processing file in status bar
End With
folder_path = "C:\Folder\SubFolder\" 'here are the files stored
file_name = Dir(folder_path & "*.csv") 'using dir to get file names
row_number = 3 'row number for pasting values
Set sht_csv = ThisWorkbook.Worksheets("2 CSV") 'target sheet for data aggregation
Do While file_name <> ""
Workbooks.Open (folder_path & file_name), UpdateLinks:=False, Local:=True 'open csv file
Set wb_src = Workbooks(file_name) 'assign opened csv file to variable
source_sheet_name = Left(file_name, InStr(file_name, ".") - 1) 'sheet name in csv is the same as the file name
Set sht_src = wb_src.Worksheets(source_sheet_name) 'assign source sheet to variable
If sht_src.Range("C1").Value2 = "OJ_POPIS" Then 'checks if the csv has the correct structure
sht_src.Range("A2:FZ2").Copy 'if so copies desired range
sht_csv.Range("B" & row_number).PasteSpecial 'and pastes it into target worksheet column B
End If
sht_csv.Range("A" & row_number).Value2 = file_name 'writes file name into column A
Application.CutCopyMode = False
wb_src.Close SaveChanges:=False
file_name = Dir() 'fetch next file name
row_number = row_number + 1
'the following lines is what I tried to fix the problem of random excel crashing
Set wb_src = Nothing
Set sht_src = Nothing
Application.StatusBar = "Processing file " & file_name
DoEvents
Application.Wait (Now + TimeValue("0:00:02"))
ThisWorkbook.Save 'save after every loaded file to see which files are causing the problem
Loop
MsgBox "Data from CSV files copied", vbOKOnly
Set sht_csv = Nothing
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Source CSV files are encoded both in UTF-8 and ANSI (my ACP is ANSI, 1250) and ; delimited.
Group policy restricting macros doesn't apply to me. I can sign my own macros.
What I tried:
Lines of code at the end of the loop
Identifying and deleting files triggering the crash (they have nothing in common, seemingly random, by the time a remove half of them... what is the point)
Simplifying the macro
New workbook
Different machine
VPN On/Off
Thank you for your help!
First thing I'd try is include a proper error handler (not resume next), particularly with x64, and ensure 'Break on all unhandled errors' is selected in Tools / Options / General.
Second thing I'd try is avoid using the clipboard -
With sht_src.Range("A2:FZ2")
sht_cvs.Range("B" & row_number).Resize(.Rows.Count, .Columns.Count).Value = .Value
End With
(no need then to clear CutCopyMode)
Third thing I'd try is don't filter with Dir but something like this -
sFilter = "*.cvs"
file_name = Dir$(, 15) ' without vbDirectory if not getting subfolders
Do While Len(file_name)
If file_name Like sFilter Then
' process file
End If
file_name = Dir$(, 15)
Loop
Fourth thing I'd try is a good cup of coffee!

VBA - import n lines from multiple text files

I have a piece of code that imports multiple text files with some data I need. I'd like to change it a bit - I want it to stop reading the file after reaching line number 50 in the text file and import only those first 50 lines. Is there a way I could do this? I was thinking about a loop that goes line by line and executes the code until the line number is larger than 50. I figured out a way to write such a loop, however it doesn't split the line into columns and I need that. Also in the way I wrote it it imports only 1 file. I had a code that worked in terms of reading multiple files and dividing them into columns, but I couldn't make it to end after 50 lines. I used QueryTables for this. Maybe instead of doing that loop I could draw on that?
Here's what I have - it obviously doesn't work:
Sub RT()
Dim fso As Object
Dim xlsheet As Worksheet
Dim qt As QueryTable
Dim txtfilesToOpen As Variant, txtfile As Variant
Dim rec As String
Dim i As Long
Dim txtfilnumber As Integer
Dim FileNumber
Dim txtline As String
i = 0
Application.ScreenUpdating = False
txtfilesToOpen = Application.GetOpenFilename _
(FileFilter:="Text Files (*.txt), *.txt", _
MultiSelect:=True, Title:="Text Files to Open")
With ActiveSheet
.Cells.ClearContents
For Each txtfile In txtfilesToOpen
importrow = 2 + .Cells(.Rows.Count, 1).End(xlUp).Row
With CreateObject("Scripting.FileSystemObject").OpenTextFile(txtfile)
Do While Not .AtEndOfStream
If .line < 50 Then
Cells(.line, 1).Value = .ReadLine
Else: Exit Do
End If
Loop
End With
Next txtfile
For Each qt In .QueryTables
qt.Delete
Next qt
End With
Application.ScreenUpdating = True
MsgBox "Successfully imported text files!", vbInformation, "SUCCESSFUL IMPORT"
Set fso = Nothing
End Sub
Does anyone know how I can approach this? I'm really new at this and still very lost. I'm pretty much stabbing in the dark here. If you could give me a tip on what I can do or what function to use I'll be really thankful!
Your code imports more that one file, however, it always overwrite the content of a previous imported file. You need to add importrow to the cell address.
When you want to split the text into several columns, you need to know how to split it. Do you have a field separator (Tab, Semicolon, comma)? Fixed length?
The following code will split the text into several cells assuming the semicolon as separator. It may be a little bit slow, but you will get the idea.
Do While Not .AtEndOfStream
If .line > 50 Then Exit Do
Dim txtLine as String, tokens() as String, i as long
txtLine = .ReadLine
tokens = Split(txtLine, ";")
For i = 0 to UBound(tokens)
.Cells(importrow + .line, i+1).Value = tokens(i)
Next i
Loop

VBS Save File From Link

I wonder whether someone can help me please.
I wanting to use this solution in a script I'm trying to put together, but I'm a little unsure about how to make a change which needs to be made.
You'll see in the solution that the file type which is opened is a Excel and indeed it's saved as such. But I the files I'd like to open and save are a mixture of .docx and .dat (Used by Dragon software) files.
Could someone possible tell me please is there a way by which I can amend the code so it opens and saves the files in file types other than Excel workbooks.
The reason behind this question because I'm currently using a script which creates a list of files in a Excel spreadsheet from a given folder. For each file that is retrieved there is a hyperlink, which I'd like to add fucntionality to which enables the user to copy the file and save it to a location of their choice.
To help this is the code which I use to create the list of files.
Public Sub ListFilesInFolder(SourceFolder As Scripting.folder, IncludeSubfolders As Boolean)
Dim LastRow As Long
Dim fName As String
On Error Resume Next
For Each FileItem In SourceFolder.Files
' display file properties
Cells(iRow, 3).Formula = iRow - 12
Cells(iRow, 4).Formula = FileItem.Name
Cells(iRow, 5).Formula = FileItem.Path
Cells(iRow, 6).Select
Selection.Hyperlinks.Add Anchor:=Selection, Address:= _
FileItem.Path, TextToDisplay:="Click Here to Open"
iRow = iRow + 1 ' next row number
With ActiveSheet
LastRow = .Cells(.Rows.Count, "C").End(xlUp).Row
LastRow = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
End With
For Each Cell In Range("C13:F" & LastRow) ''change range accordingly
If Cell.Row Mod 2 = 1 Then ''highlights row 2,4,6 etc|= 0 highlights 1,3,5
Cell.Interior.Color = RGB(232, 232, 232) ''color to preference
Else
Cell.Interior.Color = RGB(141, 180, 226) 'color to preference or remove
End If
Next Cell
Next FileItem
If IncludeSubfolders Then
For Each SubFolder In SourceFolder.SubFolders
ListFilesInFolder SubFolder, True
Next SubFolder
End If
Set FileItem = Nothing
Set SourceFolder = Nothing
Set FSO = Nothing
End Sub
Many thanks and kind regards
Chris
Miguel provided a fantastic solution which on initial testing appeared to work 100%. But as you will see from the comments at the end of the post there were some issues when the user cancelled the operation, so I made another post at this link where the problems were ironed out. Many thanks and kind regards. Chris
The code below shows how to retrieve the extension of a file, define an array with “allowed” extensions, and match the extension of the file to the array.
This is the outline for file manipulation, you'll just need to tailor it to you needs
Dim MinExtensionX
Dim Arr() As Variant
Dim lngLoc As Variant
'Retrieve extension of file
MinExtensionX = Mid(MyFile.Name, InStrRev(MyFile.Name, ".") + 1)
Arr = Array("xls", "xlsx", "docx", "dat") 'define which extensions you want to allow
On Error Resume Next
lngLoc = Application.WorksheetFunction.Match(MinExtensionX, Arr(), 0)
If Not IsEmpty(lngLoc) Then '
'check which kind of extension you are working with and create proper obj manipulation
If MinExtensionX = "docx" then
Set wApp = CreateObject("Word.Application")
wApp.DisplayAlerts = False
Set wDoc = wApp.Documents.Open (Filename:="C:\Documents\SomeWordTemplate.docx", ReadOnly:=True)
'DO STUFF if it's an authorized file. Then Save file.
With wDoc
.ActiveDocument.SaveAs Filename:="C:\Documents\NewWordDocumentFromTemplate.docx"
End With
wApp.DisplayAlerts = True
End if
End If
For files .Dat its a bit more complex, specially if you need to open/process data from the file, but this might help you out.
Edit:
2: Comments added
Hi IRHM,
I think you want something like this:
'Worksheet_FollowHyperlink' is an on click event that occurs every time you click on an Hyperlink within a Worksheet, You can find more here
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
'disable events so the user doesn't see the codes selection
Application.EnableEvents = False
Dim FSO
Dim sFile As String
Dim sDFolder As String
Dim thiswb As Workbook ', wb As Workbook
'Define workbooks so we don't lose scope while selecting sFile(thisworkbook = workbook were the code is located).
Set thiswb = thisworkbook
'Set wb = ActiveWorkbook ' This line was commented out because we no longer need to cope with 2 excel workbooks open at the same time.
'Target.Range.Value is the selection of the Hyperlink Path. Due to the address of the Hyperlink being "" we just assign the value to a
'temporary variable which is not used so the Click on event is still triggers
temp = Target.Range.Value
'Activate the wb, and attribute the File.Path located 1 column left of the Hyperlink/ActiveCell
thiswb.Activate
sFile = Cells(ActiveCell.Row, ActiveCell.Column - 1).Value
'Declare a variable as a FileDialog Object
Dim fldr As FileDialog
'Create a FileDialog object as a File Picker dialog box.
Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
'Allow only single selection on Folders
fldr.AllowMultiSelect = False
'Show Folder picker dialog box to user and wait for user action
fldr.Show
'add the end slash of the path selected in the dialog box for the copy operation
sDFolder = fldr.SelectedItems(1) & "\"
'FSO System object to copy the file
Set FSO = CreateObject("Scripting.FileSystemObject")
' Copy File from (source = sFile), destination , (Overwrite True = replace file with the same name)
FSO.CopyFile (sFile), sDFolder, True
' check if there's multiple excel workbooks open and close workbook that is not needed
' section commented out because the Hyperlinks no longer Open the selected file
' If Not thiswb.Name = wb.Name Then
' wb.Close
' End If
Application.EnableEvents = True
End Sub
The above code Triggers when you click the Hyperlink and it promps a folder selection window.
You just need to paste the code into the Worksheet code. And you should be good to go.

Resources