I'm have about 100 .xls files under one folder and I have a Macro script to loop through each one to do some data processing. The objective is to split each workbook into three with name N1, N2, N3 respectively. So far my SplitData Macro worked fine but I have issue with extracted workbooks.
I want to merge newly extracted three workbooks to already existed ones instead of getting alerts like "File N1 already exists." every time. I changed Application.DisplayAlerts = false because of my previous question's suggested answer but now I got a new error:
After the alert is disabled, my first two extracted workbook keeps updating same result from the first workbook that I started extraction while the third one trapped in a loop, adding same result from the starting workbook. I assume there's something wrong with my loop but cannot find it, can anyone help me check please?
Thanks a lot!
This is my code to loop through folder:
Sub OpenFiles()
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
On Error Resume Next
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
xFile = Dir(xStrPath & "\*.xls")
Do While xFile <> ""
Call SplitData
Loop
End Sub
This is SplitData Macro:
Sub SplitData()
' 1. Fill every cells in merged columns for future steps
Dim cell As Range, joinedCells As Range
For Each cell In Range("E4:I60")
If cell.MergeCells Then
Set joinedCells = cell.MergeArea
cell.MergeCells = False
joinedCells.Value = cell.Value
End If
Next
' 2. Split original sheet into three based on one col value
' loop through selected column to check if has different values
Const NameCol = "B"
Const HeaderRow = 3
Const FirstRow = 4
Dim SrcSheet As Worksheet
Dim TrgSheet As Worksheet
Dim SrcRow As Long
Dim LastRow As Long
Dim TrgRow As Long
Dim Student As String
Application.ScreenUpdating = False
Set SrcSheet = ActiveSheet
LastRow = SrcSheet.Cells(SrcSheet.Rows.Count, NameCol).End(xlUp).Row
For SrcRow = FirstRow To LastRow
Student = SrcSheet.Cells(SrcRow, NameCol).Value
Set TrgSheet = Nothing
On Error Resume Next
Set TrgSheet = Worksheets(Student)
On Error GoTo 0
If TrgSheet Is Nothing Then
Set TrgSheet = Worksheets.Add(After:=Worksheets(Worksheets.Count))
TrgSheet.Name = Student
SrcSheet.Rows(HeaderRow).Copy Destination:=TrgSheet.Rows(HeaderRow)
End If
TrgRow = TrgSheet.Cells(TrgSheet.Rows.Count, NameCol).End(xlUp).Row + 1
SrcSheet.Rows(SrcRow).Copy Destination:=TrgSheet.Rows(TrgRow)
Next SrcRow
Application.ScreenUpdating = True
' 3. Extract three new worksheets into three workbooks
Dim Pointer As Long
Set MainWorkBook = ActiveWorkbook
Range("E4").Value = MainWorkBook.Sheets.Count
Application.ScreenUpdating = False 'enhance the performance
For Pointer = 2 To MainWorkBook.Sheets.Count
Set NewWorkbook = Workbooks.Add
MainWorkBook.Sheets(Pointer).Copy After:=NewWorkbook.Sheets(1)
Application.DisplayAlerts = False
NewWorkbook.Sheets(1).Delete
Application.DisplayAlerts = False
With NewWorkbook
.SaveAs Filename:="D:\***\Inventory\" & MainWorkBook.Sheets(Pointer).Name & ".xls"
End With
NewWorkbook.Close SaveChanges:=True
Next Pointer
Application.ScreenUpdating = True
End Sub
It seems to have to open and close the file.
Sub OpenFiles()
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
On Error Resume Next
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
xFile = Dir(xStrPath & "\*.xls")
Dim Wb As Workbook
Do While xFile <> ""
Set Wb = Workbooks.Open(Filename:=xStrPath & "\" & xFile) '<~~ open file
Call SplitData
Wb.Close (0) '<~~ close file
xFile = Dir '<~~ re dir
Loop
End Sub
You need to add xFile = Dir in your loop to cycle through the files.
...
xFile = Dir(xStrPath & "\*.xls")
Do While xFile <> ""
Call SplitData
xFile = Dir
Loop
...
It's unclear on how xFile gets passed to SplitData. Shouldn't SplitData have an argument that receives xFile?
Related
I want my code to pick up a file (file 2) and then list out all the tabs in that file in my current spreadsheet ("Input_tab" from file1). The code is not making creating the list. What is the error in my code?
Sub ListSheets()
Dim FilePicker As FileDialog
Dim mypath As String
Dim sheet_count As Integer
Dim i As Integer
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(Sheet1)
Set FilePicker = Application.FileDialog(msoFileDialogFilePicker)
With FilePicker
.Title = "Please Select a File"
.ButtonName = "Confirm"
.AllowMultiSelect = False
If .Show = -1 Then
mypath = .SelectedItems(1)
Else
End
End If
End With
Workbooks.Open Filename:=mypath
sheet_count = Sheets.Count
For i = 1 To sheet_count
ws.Cells(i, 1) = Sheets(i).Name
Next i
ActiveWorkbook.Close savechanges:=False
End Sub
When working with multiple workbooks (or really all the time) you should always be explicit about what (eg) Sheets collection you want to refer to (ie. in which workbook?)
This works for me
Sub ListSheets()
Dim mypath As String
Dim i As Long 'prefer Long over Integer
Dim ws As Worksheet, wb As Workbook
Set ws = ThisWorkbook.Sheets("Sheet1")
mypath = GetFilePath("Please Select a File", "Confirm")
If Len(mypath) = 0 Then Exit Sub
Application.ScreenUpdating = False 'hide opening workbook
Set wb = Workbooks.Open(Filename:=mypath, ReadOnly:=True) 'get a reference to the opened workbook
ws.Cells(1, 1).value = mypath '<<<
For i = 1 To wb.Sheets.Count
ws.Cells(i + 1, 1) = wb.Sheets(i).Name
Next i
wb.Close savechanges:=False
End Sub
'return user-selected file path
Function GetFilePath(TitleText As String, ButtonText As String) As String
With Application.FileDialog(msoFileDialogFilePicker)
.Title = TitleText
.ButtonName = ButtonText
.AllowMultiSelect = False
If .Show = -1 Then GetFilePath = .SelectedItems(1)
End With
End Function
I run a machine which puts out multiple text files which I plot, I have a VBA script which can import all of the files I want to plot from a folder and puts them on their own sheet. I was wondering if there was a way in which I could automatically have them plotted when they are imported as well? I need a separate graph for each pair of tests. That is I have "Test A-1" and "Test A-2" which are plotted against each other, "Test B-1" and "Test B-2" on a new graph etc. Sorry if this is confusing, I am still pretty new to VBA and would love a tool like this to make my life a bit easier. I have included my code which does all the importing below. Each text file (which is just data for a x-y scatter plot) is then given its own sheet, with the data in columns A and B. Apologies in advance for the terrible formatting, I didn't write it!
Sub ImportTextToExcel()
'UpdatebyExtendoffice20180911
Dim xWb As Workbook
Dim xToBook As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
Dim xFiles As New Collection
Dim I As Long
Dim xIntRow As Long
Dim xFNum, xFArr As Long
Dim xStrValue As String
Dim xRg As Range
Dim xArr
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
If Right(xStrPath, 1) <> "\" Then xStrPath = xStrPath & "\"
xFile = Dir(xStrPath & "*.txt")
If xFile = "" Then
MsgBox "No files found", vbInformation
Exit Sub
End If
Do While xFile <> ""
xFiles.Add xFile, xFile
xFile = Dir()
Loop
Set xToBook = ThisWorkbook
On Error Resume Next
Application.ScreenUpdating = False
If xFiles.Count > 0 Then
For I = 1 To xFiles.Count
Set xWb = Workbooks.Open(xStrPath & xFiles.Item(I))
xWb.Worksheets(1).Copy after:=xToBook.Sheets(xToBook.Sheets.Count)
ActiveSheet.Name = xWb.Name
xWb.Close False
xIntRow = ActiveCell.CurrentRegion.Rows.Count
For xFNum = 1 To xIntRow
Set xRg = ActiveSheet.Range("A" & xFNum)
xArr = Split(xRg.Text, " ")
If UBound(xArr) > 0 Then
For xFArr = 0 To UBound(xArr)
If xArr(xFArr) <> "" Then
xRg.Value = xArr(xFArr)
Set xRg = xRg.Offset(ColumnOffset:=1)
End If
Next
End If
Next
Next
End If
Application.ScreenUpdating = True
End Sub
Option Explicit
Sub ImportTextToExcel()
'UpdatebyExtendoffice20180911
Dim xWb As Workbook, xToBook As Workbook, ws As Worksheet
Dim xFile As String, xStrPath As String, xStrValue As String
Dim xRg As Range, cht As Chart
Dim xFiles As New Collection
Dim i As Long
' choose folder
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Title = "Select a folder"
If .Show = -1 Then
xStrPath = .SelectedItems(1)
End If
End With
If xStrPath = "" Then
Exit Sub
ElseIf Right(xStrPath, 1) <> "\" Then
xStrPath = xStrPath & "\"
End If
' build collection of text files
xFile = Dir(xStrPath & "*.txt")
Do While xFile <> ""
xFiles.Add xFile, xFile
xFile = Dir()
Loop
If xFiles.Count = 0 Then
MsgBox "No files found", vbCritical
Exit Sub
End If
' import data
Set xToBook = ThisWorkbook
Application.ScreenUpdating = False
For i = 1 To xFiles.Count
' import data into new sheet
Set xWb = Workbooks.Open(xStrPath & xFiles.Item(i))
xWb.Worksheets(1).Copy after:=xToBook.Sheets(xToBook.Sheets.Count)
Set ws = ActiveSheet
ws.Name = xWb.Name
xWb.Close False
' split on space
Set xRg = ws.Range("A1")
xRg.CurrentRegion.TextToColumns Destination:=xRg.Cells(1, 1), _
DataType:=xlDelimited, _
ConsecutiveDelimiter:=True, _
Space:=True, FieldInfo:=Array(Array(1, 1), Array(2, 1))
' create chart
Set cht = ws.Shapes.AddChart.Chart
With cht
.ChartType = xlXYScatter
.SetSourceData Source:=xRg.CurrentRegion
End With
Next
Application.ScreenUpdating = True
MsgBox xFiles.Count & " files imported", vbInformation
End Sub
I was using below code to get the multiple CSV files into single sheet.
code is working fine but the issue is that, it should not copy the headers of each file, because each file header is same.
Code should copy the first file header not all files.
One more thing that i do not want first column to copy all sheets name i have tried to remove that filed but code does not work.
Can i get any help.
thanks
Sub CSV()
Dim xSht As Worksheet
Dim xWb As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
On Error GoTo ErrHandler
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder [Kutools for Excel]"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
Set xSht = ThisWorkbook.ActiveSheet
Application.ScreenUpdating = False
xFile = Dir(xStrPath & "\" & "*.csv")
Do While xFile <> ""
Set xWb = Workbooks.Open(xStrPath & "\" & xFile)
Columns(1).Insert xlShiftToRight
Columns(1).SpecialCells(xlBlanks).Value = ActiveSheet.Name
ActiveSheet.UsedRange.Copy xSht.Range("A" & Rows.Count).End(xlUp).Offset(1)
xWb.Close False
xFile = Dir
Loop
Application.ScreenUpdating = True
Exit Sub
ErrHandler:
MsgBox "no files csv", , "Kutools for Excel"
End Sub
EDIT: I did two attempts, first one untested, and did it on my phone:
Sub CSV()
Dim xSht As Worksheet
Dim xWb As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
On Error GoTo ErrHandler
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder [Kutools for Excel]"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
Set xSht = ThisWorkbook.ActiveSheet
Application.ScreenUpdating = False
xFile = Dir(xStrPath & "\" & "*.csv")
Dim counter as Long
Do While xFile <> ""
Set xWb = Workbooks.Open(xStrPath & "\" & xFile)
Dim sourceRange as Range
Set sourceRange = xWb.Worksheets(1).UsedRange
If counter = 0 then
sourceRange.Copy xSht.Range("A" & Rows.Count).End(xlUp).Offset(1)
else
sourceRange.Offset(1, 0).Resize(sourceRange.Rows.Count - 1, sourceRange.Columns.Count).Copy xSht.Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
xWb.Close False
xFile = Dir
counter = counter + 1
Loop
Application.ScreenUpdating = True
Exit Sub
ErrHandler:
MsgBox "no files csv", , "Kutools for Excel"
End Sub
Second attempt from my computer, I refactored the code handled first file case, skipped the clipboard and use proper procedure and variable names.
Public Sub ImportAndAppendCSVFromFolder()
' Set basic error handling
On Error GoTo CleanFail
' Turn off stuff
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim xSht As Worksheet
Dim xWb As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
' Prepare and display file dialog to user
Dim customFileDialog As FileDialog
Set customFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
customFileDialog.AllowMultiSelect = False
customFileDialog.Title = "Select a folder"
' Get folder path from file dialog
If customFileDialog.Show = -1 Then
Dim folderPath As String
folderPath = customFileDialog.SelectedItems(1)
End If
' Exit if nothing was selected
If folderPath = vbNullString Then Exit Sub
' Set reference to active sheet (could be replaced to a specific sheet name with this: ThisWorkbook.Worksheets("SheetName") )
Dim targetSheet As Worksheet
Set targetSheet = ThisWorkbook.ActiveSheet
' Get files in directory ending with specific extension
Dim sourceFile As String
sourceFile = Dir(folderPath & "\" & "*.csv")
' Loop through files
Do While sourceFile <> ""
' Open file
Dim sourceWorkbook As Workbook
Set sourceWorkbook = Workbooks.Open(folderPath & "\" & sourceFile)
' Set reference to sheet in file (as it's a csv file, it only has one worksheet)
Dim sourceSheet As Worksheet
Set sourceSheet = sourceWorkbook.Worksheets(1)
' Depending if it's the first file, include headers or not
Dim counter As Long
If counter = 0 Then
' Set reference to used range in source file
Dim sourceRange As Range
Set sourceRange = sourceSheet.UsedRange
' Calc offset if it's first file
Dim rowOffset As Long
rowOffset = 0
Else
' Don't include headers in range
Set sourceRange = sourceSheet.UsedRange.Offset(1, 0).Resize(sourceSheet.UsedRange.Rows.Count - 1, sourceSheet.UsedRange.Columns.Count)
' Calc offset if it's not first file
rowOffset = 1
End If
' Perform copy (as this comes from a csv file, we can skip the clipboard
targetSheet.Range("A" & targetSheet.Rows.Count).End(xlUp).Resize(sourceRange.Rows.Count, sourceRange.Columns.Count).Offset(rowOffset).Value2 = sourceRange.Value2
' Close csv file
sourceWorkbook.Close False
' Get reference to next file
sourceFile = Dir
counter = counter + 1
Loop
CleanExit:
' Turn on stuff again
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
CleanFail:
MsgBox "An error occurred:" & Err.Description
GoTo CleanExit
End Sub
I have managed to make a macro which imports multiple xml-files to excel, in individual tables. The problem is that some of the tables includes one extra column. I want the column names to be in the same column for all tables.
I am using VBA and I do not have that much experience with this.
Sub CommandButton1_Click()
Dim xWb As Workbook
Dim xSWb As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
Dim xCount As Long
On Error GoTo ErrHandler
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder [Kutools for Excel]"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
Application.ScreenUpdating = False
Set xSWb = ThisWorkbook
xCount = 1
xFile = Dir(xStrPath & "\*.xml")
Do While xFile <> ""
Set xWb = Workbooks.OpenXML(xStrPath & "\" & xFile)
xWb.Sheets(1).UsedRange.Copy xSWb.Sheets(1).Cells(xCount, 1)
xWb.Close False
xCount = xSWb.Sheets(1).UsedRange.Rows.Count + 2
xFile = Dir()
Loop
Application.ScreenUpdating = True
xSWb.Save
On Error Resume Next
Columns("D").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Exit Sub
ErrHandler:
MsgBox "no files xml", , "Kutools for Excel"
End Sub
I would suggest you delete the extra column in the source sheet before you copy the data. As you close the file after the copy without saving, it shouldn't be a problem.
Note that when you delete something, you should always do it from the end to the start.
Dim startRow As Long
startRow = 1
xFile = Dir(xStrPath & "\*.xml")
Do While xFile <> ""
Set xWb = Workbooks.OpenXML(xStrPath & "\" & xFile)
With xWb.Sheets(1)
Dim lastCol As Long, col As Long
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
' Loop over all columns from right to left
For col = lastCol To 1 Step -1
' Throw the extra column away
If .Cells(1, col) = "YourUnwantedCol" Then
.Cells(1, col).EntireColumn.Delete
End If
Next col
' Now copy the data
.UsedRange.Copy xSWb.Sheets(1).Cells(startRow, 1)
startRow = startRow + .UsedRange.Rows.Count
' Close without saving, don't show a warning.
Application.DisplayAlerts = False
xWb.Close False
Application.DisplayAlerts = True
xFile = Dir()
End With
Loop
Sub CommandButton2_Click()
Dim xWb As Workbook
Dim xSWb As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
Dim xCount As Long
On Error GoTo ErrHandler
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder [Kutools for Excel]"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
Application.ScreenUpdating = False
Set xSWb = ThisWorkbook
xCount = 1
xFile = Dir(xStrPath & "\*.xml")
Dim startRow As Long
startRow = 1
xFile = Dir(xStrPath & "\*.xml")
Do While xFile <> ""
Set xWb = Workbooks.OpenXML(xStrPath & "\" & xFile)
With xWb.Sheets(1)
Dim lastCol As Long, col As Long
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
' Loop over all columns from right to left
For col = lastCol To 1 Step -1
' Throw the extra column away
If .Cells(1, col) = "Content" Then
.Cells(1, col).EntireColumn.Delete
End If
Next col
' Now copy the data
.UsedRange.Copy xSWb.Sheets(1).Cells(startRow, 1)
startRow = startRow + .UsedRange.Rows.Count
' Close without saving, don't show a warning.
Application.DisplayAlerts = False
xWb.Close False
Application.DisplayAlerts = True
xFile = Dir()
End With
Loop
Application.ScreenUpdating = True
xSWb.Save
'Removes rows with no "event id"
On Error Resume Next
Columns("D").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Exit Sub
ErrHandler:
MsgBox "no files xml", , "Kutools for Excel"
End Sub
I have multiple CSV in one directory, I need to select specific files instead of the entire directory and I want to be able to select the column that I want (X) and import this to a single worksheet!
I have already made the code above but I'm fighting to add a input box that give the capability do select the column that I want to extract from each CSV.
Moreover, whenever I import the CSV there are not sorted correctly. I found out that I need to apply this formula ""=LEFT(F1;1)&TEXT(SUBSTITUTE(F1;LEFT(F1;1);"";"00") " ", but any idea how to apply in code in order to rename the .csv files.
Sub ImportCSVsWithReferenceI()
Dim xSht As Worksheet
Dim xWb As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
Dim xCount As Long
Dim Newname As String
On Error GoTo ErrHandler
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
Set xSht = ThisWorkbook.ActiveSheet.Add
Newname = InputBox("Name for new worksheet?")
If Newname <> "" Then
Sheets.Add Type:=xlWorksheet
ActiveSheet.Name = Newname
End If
Set xSht = ThisWorkbook.ActiveSheet
If MsgBox("Clear the existing sheet before importing?", vbYesNo, "Kutools for Excel") = vbYes Then
xSht.UsedRange.Clear
xCount = 1
Else
xCount = xSht.Cells(3, Columns.Count).End(xlToLeft).Column + 1
End If
Application.ScreenUpdating = False
xFile = Dir(xStrPath & "\" & "*.csv")
Do While xFile <> ""
Set xWb = Workbooks.Open(xStrPath & "\" & xFile)
Rows(1).Insert xlShiftDown
Range("A1") = ActiveSheet.Name
ActiveSheet.UsedRange.Copy xSht.Cells(1, xCount)
xWb.Close False
xFile = Dir
xCount = xSht.Cells(3, Columns.Count).End(xlToLeft).Column + 1
Loop
Application.ScreenUpdating = True
Exit Sub
ErrHandler:
MsgBox "error"
End Sub
Data example (some times I want to extract the columns A or B or C or .... :
Example of a result: